2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 #include "mesa_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
44 /* x11drv GDI escapes */
45 #define X11DRV_ESCAPE 6789
46 enum x11drv_escape_codes
48 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
49 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
50 X11DRV_GET_FONT, /* get current X font for a DC */
53 /* They are non-static as they are used by Direct3D in the creation function */
54 const GUID IID_D3DDEVICE_OpenGL = {
58 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
61 const float id_mat[16] = {
68 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
69 D3DPRIMITIVETYPE d3dptPrimitiveType,
70 DWORD d3dvtVertexType,
71 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
77 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
79 /* retrieve the X display to use on a given DC */
80 inline static Display *get_display( HDC hdc )
83 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
85 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
86 sizeof(display), (LPSTR)&display )) display = NULL;
91 #define UNLOCK_TEX_SIZE 256
93 #define DEPTH_RANGE_BIT (0x00000001 << 0)
94 #define VIEWPORT_BIT (0x00000001 << 1)
96 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
97 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
98 DWORD opt_bitmap = 0x00000000;
100 if (gl_d3d_dev->unlock_tex == 0) {
101 glGenTextures(1, &gl_d3d_dev->unlock_tex);
102 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
109 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
111 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
112 glMatrixMode(GL_TEXTURE);
116 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
117 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
118 d3ddevice_set_ortho(d3d_dev);
121 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
122 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
123 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
124 glEnable(GL_TEXTURE_2D);
125 glEnable(GL_SCISSOR_TEST);
126 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
127 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
128 glDepthRange(0.0, 1.0);
129 opt_bitmap |= DEPTH_RANGE_BIT;
131 if ((d3d_dev->active_viewport.dwX != 0) ||
132 (d3d_dev->active_viewport.dwY != 0) ||
133 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
134 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
135 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
136 opt_bitmap |= VIEWPORT_BIT;
138 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
139 pRect->right - pRect->left, pRect->bottom - pRect->top);
140 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
141 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
143 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
144 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
145 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
146 glAlphaFunc(GL_GREATER, 0.0);
149 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
151 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
152 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
153 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
154 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
155 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
160 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
161 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
163 /* And restore all the various states modified by this code */
164 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
165 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
166 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
167 glEnable(GL_ALPHA_TEST);
168 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
169 glDisable(GL_ALPHA_TEST);
171 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
172 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
173 glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
174 (d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
177 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
178 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
179 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
180 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
181 glDisable(GL_SCISSOR_TEST);
182 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
183 if (opt_bitmap & DEPTH_RANGE_BIT) {
184 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
186 if (opt_bitmap & VIEWPORT_BIT) {
187 glViewport(d3d_dev->active_viewport.dwX,
188 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
189 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
191 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
192 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
195 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
196 DrawPrimitive call, this will bind the correct texture to this stage. */
197 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
198 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
201 /* retrieve the X drawable to use on a given DC */
202 inline static Drawable get_drawable( HDC hdc )
205 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
207 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
208 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
215 #define MEASUREMENT_WINDOW 5
216 #define NUMBER_OF_WINDOWS 10
218 static LONGLONG perf_freq;
219 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
220 static LONGLONG prev_time = 0;
221 static unsigned int current_window;
222 static unsigned int measurements_in_window;
223 static unsigned int valid_windows;
227 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
229 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
230 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
232 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
234 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
235 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
237 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
238 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
239 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
244 LONGLONG current_time;
245 LONGLONG frame_duration;
246 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
248 if (prev_time != 0) {
249 LONGLONG total_time = 0;
252 frame_duration = current_time - prev_time;
253 prev_time = current_time;
255 perf_storage[current_window] += frame_duration;
256 measurements_in_window++;
258 if (measurements_in_window >= MEASUREMENT_WINDOW) {
262 if (valid_windows < NUMBER_OF_WINDOWS) {
264 tot_meas = valid_windows * MEASUREMENT_WINDOW;
265 for (i = 0; i < valid_windows; i++) {
266 total_time += perf_storage[i];
270 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
271 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
272 total_time += perf_storage[i];
276 DPRINTF("FPS : %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
278 if (current_window >= NUMBER_OF_WINDOWS) {
281 perf_storage[current_window] = 0;
282 measurements_in_window = 0;
285 prev_time = current_time;
286 memset(perf_storage, 0, sizeof(perf_storage));
289 measurements_in_window = 0;
290 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
299 /*******************************************************************************
300 * OpenGL static functions
302 static void set_context(IDirect3DDeviceImpl* This)
304 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
306 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
308 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
309 ERR("Error in setting current context (context %p drawable %ld)!\n",
310 glThis->gl_context, glThis->drawable);
315 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
317 pc->dwSize = sizeof(*pc);
318 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
319 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
320 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
321 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
322 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
323 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
324 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
325 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
326 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
327 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
328 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
329 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
330 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
331 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
332 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
333 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
334 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
335 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
336 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
337 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
338 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
339 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
340 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
341 pc->dwStippleWidth = 32;
342 pc->dwStippleHeight = 32;
345 static void fill_opengl_caps(D3DDEVICEDESC *d1)
347 /* GLint maxlight; */
349 d1->dwSize = sizeof(*d1);
350 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
351 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
352 d1->dcmColorModel = D3DCOLOR_RGB;
353 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
354 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
355 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
356 /* D3D 7 capabilities */
357 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
358 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
359 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
360 d1->bClipping = TRUE;
361 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
362 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
363 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
364 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
365 fill_opengl_primcaps(&(d1->dpcLineCaps));
366 fill_opengl_primcaps(&(d1->dpcTriCaps));
367 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
368 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
369 d1->dwMaxBufferSize = 0;
370 d1->dwMaxVertexCount = 65536;
371 d1->dwMinTextureWidth = 1;
372 d1->dwMinTextureHeight = 1;
373 d1->dwMaxTextureWidth = 1024;
374 d1->dwMaxTextureHeight = 1024;
375 d1->dwMinStippleWidth = 1;
376 d1->dwMinStippleHeight = 1;
377 d1->dwMaxStippleWidth = 32;
378 d1->dwMaxStippleHeight = 32;
379 d1->dwMaxTextureRepeat = 16;
380 d1->dwMaxTextureAspectRatio = 1024;
381 d1->dwMaxAnisotropy = 0;
382 d1->dvGuardBandLeft = 0.0;
383 d1->dvGuardBandRight = 0.0;
384 d1->dvGuardBandTop = 0.0;
385 d1->dvGuardBandBottom = 0.0;
386 d1->dvExtentsAdjust = 0.0;
387 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
388 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
389 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
390 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
391 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
392 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
395 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
399 /* Copy first D3D1/2/3 capabilities */
400 fill_opengl_caps(&d1);
402 /* And fill the D3D7 one with it */
403 d->dwDevCaps = d1.dwDevCaps;
404 d->dpcLineCaps = d1.dpcLineCaps;
405 d->dpcTriCaps = d1.dpcTriCaps;
406 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
407 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
408 d->dwMinTextureWidth = d1.dwMinTextureWidth;
409 d->dwMinTextureHeight = d1.dwMinTextureHeight;
410 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
411 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
412 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
413 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
414 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
415 d->dvGuardBandLeft = d1.dvGuardBandLeft;
416 d->dvGuardBandTop = d1.dvGuardBandTop;
417 d->dvGuardBandRight = d1.dvGuardBandRight;
418 d->dvGuardBandBottom = d1.dvGuardBandBottom;
419 d->dvExtentsAdjust = d1.dvExtentsAdjust;
420 d->dwStencilCaps = d1.dwStencilCaps;
421 d->dwFVFCaps = d1.dwFVFCaps;
422 d->dwTextureOpCaps = d1.dwTextureOpCaps;
423 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
424 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
425 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
426 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
427 d->deviceGUID = IID_IDirect3DTnLHalDevice;
428 d->wMaxUserClipPlanes = 1;
429 d->wMaxVertexBlendMatrices = 0;
430 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
431 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
438 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
440 D3DDEVICEDESC dref, d1, d2;
443 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
444 Let's put the string in a sufficiently sized array in writable memory. */
445 char device_name[50];
446 strcpy(device_name,"direct3d");
448 fill_opengl_caps(&dref);
451 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
452 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
455 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
456 if (ret_value != D3DENUMRET_OK)
460 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
463 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
464 if (ret_value != D3DENUMRET_OK)
467 return D3DENUMRET_OK;
470 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
472 D3DDEVICEDESC7 ddesc;
474 fill_opengl_caps_7(&ddesc);
476 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
478 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
482 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
484 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
485 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
487 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
488 if (!--(This->ref)) {
490 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
492 /* Release texture associated with the device */
493 for (i = 0; i < MAX_TEXTURES; i++) {
494 if (This->current_texture[i] != NULL)
495 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
496 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
499 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
500 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
501 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
502 surf->aux_ctx = NULL;
503 surf->aux_data = NULL;
504 surf->aux_flip = NULL;
508 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
509 IDirectDrawSurfaceImpl *surf2;
510 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
511 for (; surf2 != NULL; surf2 = surf2->next_attached) {
512 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
513 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
514 /* Override the Lock / Unlock function for all these surfaces */
515 surf2->lock_update = surf2->lock_update_prev;
516 surf2->unlock_update = surf2->unlock_update_prev;
517 /* And install also the blt / bltfast overrides */
518 surf2->aux_blt = NULL;
519 surf2->aux_bltfast = NULL;
521 surf2->d3ddevice = NULL;
525 /* And warn the D3D object that this device is no longer active... */
526 This->d3d->d3d_removed_device(This->d3d, This);
528 HeapFree(GetProcessHeap(), 0, This->world_mat);
529 HeapFree(GetProcessHeap(), 0, This->view_mat);
530 HeapFree(GetProcessHeap(), 0, This->proj_mat);
532 if (glThis->surface_ptr)
533 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
535 DeleteCriticalSection(&(This->crit));
538 if (glThis->unlock_tex)
539 glDeleteTextures(1, &(glThis->unlock_tex));
540 glXDestroyContext(glThis->display, glThis->gl_context);
542 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
544 HeapFree(GetProcessHeap(), 0, This);
551 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
552 LPD3DDEVICEDESC lpD3DHWDevDesc,
553 LPD3DDEVICEDESC lpD3DHELDevDesc)
555 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
559 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
561 fill_opengl_caps(&desc);
562 dwSize = lpD3DHWDevDesc->dwSize;
563 memset(lpD3DHWDevDesc, 0, dwSize);
564 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
566 dwSize = lpD3DHELDevDesc->dwSize;
567 memset(lpD3DHELDevDesc, 0, dwSize);
568 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
570 TRACE(" returning caps : (no dump function yet)\n");
575 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
576 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
580 LPDDPIXELFORMAT pformat;
582 /* Do the texture enumeration */
583 sdesc.dwSize = sizeof(DDSURFACEDESC);
584 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
585 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
586 pformat = &(sdesc.ddpfPixelFormat);
587 pformat->dwSize = sizeof(DDPIXELFORMAT);
588 pformat->dwFourCC = 0;
590 TRACE("Enumerating GL_RGBA unpacked (32)\n");
591 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
592 pformat->u1.dwRGBBitCount = 32;
593 pformat->u2.dwRBitMask = 0x00FF0000;
594 pformat->u3.dwGBitMask = 0x0000FF00;
595 pformat->u4.dwBBitMask = 0x000000FF;
596 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
597 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
598 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
600 TRACE("Enumerating GL_RGB unpacked (32)\n");
601 pformat->dwFlags = DDPF_RGB;
602 pformat->u1.dwRGBBitCount = 32;
603 pformat->u2.dwRBitMask = 0x00FF0000;
604 pformat->u3.dwGBitMask = 0x0000FF00;
605 pformat->u4.dwBBitMask = 0x000000FF;
606 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
607 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
608 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
610 TRACE("Enumerating GL_RGB unpacked (24)\n");
611 pformat->dwFlags = DDPF_RGB;
612 pformat->u1.dwRGBBitCount = 24;
613 pformat->u2.dwRBitMask = 0x00FF0000;
614 pformat->u3.dwGBitMask = 0x0000FF00;
615 pformat->u4.dwBBitMask = 0x000000FF;
616 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
617 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
618 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
620 /* Note : even if this is an 'emulated' texture format, it needs to be first
621 as some dumb applications seem to rely on that. */
622 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
623 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
624 pformat->u1.dwRGBBitCount = 16;
625 pformat->u2.dwRBitMask = 0x00007C00;
626 pformat->u3.dwGBitMask = 0x000003E0;
627 pformat->u4.dwBBitMask = 0x0000001F;
628 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
629 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
630 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
632 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
633 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
634 pformat->u1.dwRGBBitCount = 16;
635 pformat->u2.dwRBitMask = 0x00000F00;
636 pformat->u3.dwGBitMask = 0x000000F0;
637 pformat->u4.dwBBitMask = 0x0000000F;
638 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
639 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
640 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
642 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
643 pformat->dwFlags = DDPF_RGB;
644 pformat->u1.dwRGBBitCount = 16;
645 pformat->u2.dwRBitMask = 0x0000F800;
646 pformat->u3.dwGBitMask = 0x000007E0;
647 pformat->u4.dwBBitMask = 0x0000001F;
648 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
649 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
650 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
652 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
653 pformat->dwFlags = DDPF_RGB;
654 pformat->u1.dwRGBBitCount = 16;
655 pformat->u2.dwRBitMask = 0x00007C00;
656 pformat->u3.dwGBitMask = 0x000003E0;
657 pformat->u4.dwBBitMask = 0x0000001F;
658 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
659 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
660 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
663 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
664 find enumerated, others the last one. And both want to have the ARGB one.
666 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
668 /* See argument about the RGBA format for 'packed' texture formats */
669 TRACE("Enumerating GL_RGBA unpacked (32)\n");
670 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
671 pformat->u1.dwRGBBitCount = 32;
672 pformat->u2.dwRBitMask = 0xFF000000;
673 pformat->u3.dwGBitMask = 0x00FF0000;
674 pformat->u4.dwBBitMask = 0x0000FF00;
675 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
676 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
677 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
679 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
680 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
681 pformat->u1.dwRGBBitCount = 16;
682 pformat->u2.dwRBitMask = 0x0000F000;
683 pformat->u3.dwGBitMask = 0x00000F00;
684 pformat->u4.dwBBitMask = 0x000000F0;
685 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
686 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
687 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
689 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
690 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
691 pformat->u1.dwRGBBitCount = 16;
692 pformat->u2.dwRBitMask = 0x0000F800;
693 pformat->u3.dwGBitMask = 0x000007C0;
694 pformat->u4.dwBBitMask = 0x0000003E;
695 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
696 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
697 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
700 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
701 pformat->dwFlags = DDPF_RGB;
702 pformat->u1.dwRGBBitCount = 8;
703 pformat->u2.dwRBitMask = 0x000000E0;
704 pformat->u3.dwGBitMask = 0x0000001C;
705 pformat->u4.dwBBitMask = 0x00000003;
706 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
707 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
708 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
710 TRACE("Enumerating Paletted (8)\n");
711 pformat->dwFlags = DDPF_PALETTEINDEXED8;
712 pformat->u1.dwRGBBitCount = 8;
713 pformat->u2.dwRBitMask = 0x00000000;
714 pformat->u3.dwGBitMask = 0x00000000;
715 pformat->u4.dwBBitMask = 0x00000000;
716 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
717 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
718 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
720 TRACE("End of enumeration\n");
726 d3ddevice_find(IDirectDrawImpl *d3d,
727 LPD3DFINDDEVICESEARCH lpD3DDFS,
728 LPD3DFINDDEVICERESULT lplpD3DDevice)
732 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
733 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
734 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
735 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
737 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
738 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
739 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
740 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
741 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
742 TRACE(" no match for this GUID.\n");
743 return DDERR_INVALIDPARAMS;
747 /* Now return our own GUID */
748 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
749 fill_opengl_caps(&desc);
750 lplpD3DDevice->ddHwDesc = desc;
751 lplpD3DDevice->ddSwDesc = desc;
753 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
759 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
760 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
763 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
764 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
765 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
769 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
770 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
773 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
774 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
775 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
779 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
780 D3DRENDERSTATETYPE dwRenderStateType,
783 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
784 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
786 /* Call the render state functions */
787 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
788 set_render_state(This, dwRenderStateType, &This->state_block);
794 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
795 D3DRENDERSTATETYPE dwRenderStateType,
796 LPDWORD lpdwRenderState)
798 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
799 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
801 /* Call the render state functions */
802 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
804 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
810 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
811 D3DLIGHTSTATETYPE dwLightStateType,
814 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
816 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
818 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
819 TRACE("Unexpected Light State Type\n");
820 return DDERR_INVALIDPARAMS;
822 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
823 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
828 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
830 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
831 switch (dwLightState) {
833 ERR("DDCOLOR_MONO should not happen!\n");
836 /* We are already in this mode */
839 ERR("Unknown color model!\n");
843 D3DRENDERSTATETYPE rs;
844 switch (dwLightStateType) {
846 case D3DLIGHTSTATE_AMBIENT: /* 2 */
847 rs = D3DRENDERSTATE_AMBIENT;
849 case D3DLIGHTSTATE_FOGMODE: /* 4 */
850 rs = D3DRENDERSTATE_FOGVERTEXMODE;
852 case D3DLIGHTSTATE_FOGSTART: /* 5 */
853 rs = D3DRENDERSTATE_FOGSTART;
855 case D3DLIGHTSTATE_FOGEND: /* 6 */
856 rs = D3DRENDERSTATE_FOGEND;
858 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
859 rs = D3DRENDERSTATE_FOGDENSITY;
861 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
862 rs = D3DRENDERSTATE_COLORVERTEX;
868 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
875 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
878 case D3DPT_POINTLIST:
879 TRACE("Start POINTS\n");
884 TRACE("Start LINES\n");
888 case D3DPT_LINESTRIP:
889 TRACE("Start LINE_STRIP\n");
890 glBegin(GL_LINE_STRIP);
893 case D3DPT_TRIANGLELIST:
894 TRACE("Start TRIANGLES\n");
895 glBegin(GL_TRIANGLES);
898 case D3DPT_TRIANGLESTRIP:
899 TRACE("Start TRIANGLE_STRIP\n");
900 glBegin(GL_TRIANGLE_STRIP);
903 case D3DPT_TRIANGLEFAN:
904 TRACE("Start TRIANGLE_FAN\n");
905 glBegin(GL_TRIANGLE_FAN);
909 FIXME("Unhandled primitive %08x\n", d3dpt);
914 /* This function calculate the Z coordinate from Zproj */
915 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
918 /* Assume that X = Y = 0 and W = 1 */
919 a = This->proj_mat->_33;
920 b = This->proj_mat->_34;
921 c = This->proj_mat->_43;
922 d = This->proj_mat->_44;
923 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
924 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
925 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
927 return (d*Zproj - c) / (a - b*Zproj);
930 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
933 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
935 for (i = 0; i < 3; i++) {
936 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
938 for (elt = 0; elt < 0x10000; elt++) {
939 /* We apply the fog transformation and cache the result */
940 DWORD fog_intensity = elt & 0xFF;
941 DWORD vertex_color = (elt >> 8) & 0xFF;
942 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
947 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
948 BOOLEAN vertex_transformed,
949 BOOLEAN vertex_lit) {
950 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
952 /* Puts GL in the correct lighting / transformation mode */
953 if ((vertex_transformed == FALSE) &&
954 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
955 /* Need to put the correct transformation again if we go from Transformed
956 vertices to non-transformed ones.
958 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
959 This->world_mat, This->view_mat, This->proj_mat);
960 glThis->transform_state = GL_TRANSFORM_NORMAL;
962 } else if ((vertex_transformed == TRUE) &&
963 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
964 /* Set our orthographic projection */
965 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
966 glThis->transform_state = GL_TRANSFORM_ORTHO;
967 d3ddevice_set_ortho(This);
971 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
972 if no fogging state change occured */
973 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
974 if (vertex_transformed == TRUE) {
975 if (glThis->fogging != 0) {
979 /* Now check if our fog_table still corresponds to the current vertex color.
980 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
981 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
982 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
983 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
984 /* We need to rebuild our fog table.... */
985 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
988 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
989 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
990 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
991 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
992 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
994 if (vertex_lit == FALSE) {
995 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
996 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
998 /* Special case of 'pixel fog' */
999 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
1000 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
1002 if (glThis->fogging == 0) {
1004 glThis->fogging = 1;
1007 if (glThis->fogging != 0) {
1009 glThis->fogging = 0;
1014 if (glThis->fogging != 0) {
1016 glThis->fogging = 0;
1020 /* Handle the 'no-normal' case */
1021 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
1022 if (glThis->lighting == 0) {
1023 glEnable(GL_LIGHTING);
1024 glThis->lighting = 1;
1027 if (glThis->lighting != 0) {
1028 glDisable(GL_LIGHTING);
1029 glThis->lighting = 0;
1033 /* Handle the code for pre-vertex material properties */
1034 if (vertex_transformed == FALSE) {
1035 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1036 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1037 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1038 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1039 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1040 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
1041 glEnable(GL_COLOR_MATERIAL);
1048 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1049 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1051 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1054 case D3DVT_VERTEX: {
1055 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1056 strided.position.dwStride = sizeof(D3DVERTEX);
1057 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1058 strided.normal.dwStride = sizeof(D3DVERTEX);
1059 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1060 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1061 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1064 case D3DVT_LVERTEX: {
1065 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1066 strided.position.dwStride = sizeof(D3DLVERTEX);
1067 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1068 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1069 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1070 strided.specular.dwStride = sizeof(D3DLVERTEX);
1071 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1072 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1073 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1076 case D3DVT_TLVERTEX: {
1077 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1078 strided.position.dwStride = sizeof(D3DTLVERTEX);
1079 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1080 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1081 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1082 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1083 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1084 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1085 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1089 FIXME("Unhandled vertex type %08x\n", d3dvt);
1095 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1096 D3DPRIMITIVETYPE d3dptPrimitiveType,
1097 D3DVERTEXTYPE d3dvtVertexType,
1099 DWORD dwVertexCount,
1102 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1104 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1105 if (TRACE_ON(ddraw)) {
1106 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1109 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1115 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1116 D3DPRIMITIVETYPE d3dptPrimitiveType,
1117 D3DVERTEXTYPE d3dvtVertexType,
1119 DWORD dwVertexCount,
1124 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1125 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1126 if (TRACE_ON(ddraw)) {
1127 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1130 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1136 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1137 LPD3DEXECUTEBUFFERDESC lpDesc,
1138 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1139 IUnknown* pUnkOuter)
1141 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1142 IDirect3DExecuteBufferImpl *ret;
1145 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1147 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1148 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1150 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1155 /* These are the various handler used in the generic path */
1156 inline static void handle_xyz(D3DVALUE *coords) {
1157 glVertex3fv(coords);
1159 inline static void handle_xyzrhw(D3DVALUE *coords) {
1160 if (coords[3] < 1e-8)
1161 glVertex3fv(coords);
1163 GLfloat w = 1.0 / coords[3];
1165 glVertex4f(coords[0] * w,
1171 inline static void handle_normal(D3DVALUE *coords) {
1172 glNormal3fv(coords);
1175 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1176 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1177 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1178 glColor4ub((*color >> 16) & 0xFF,
1179 (*color >> 8) & 0xFF,
1180 (*color >> 0) & 0xFF,
1181 (*color >> 24) & 0xFF);
1183 glColor3ub((*color >> 16) & 0xFF,
1184 (*color >> 8) & 0xFF,
1185 (*color >> 0) & 0xFF);
1189 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1190 glColor4ub((*color >> 16) & 0xFF,
1191 (*color >> 8) & 0xFF,
1192 (*color >> 0) & 0xFF,
1193 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1196 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1197 if ((lighted == FALSE) &&
1198 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1199 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1200 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1201 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1202 handle_diffuse_base(sb, color);
1204 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1205 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1206 handle_diffuse_base(sb, color);
1208 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1209 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1210 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1211 handle_diffuse_base(sb, color);
1213 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1214 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1215 handle_diffuse_base(sb, color);
1218 handle_diffuse_base(sb, color);
1222 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1223 if ((lighted == FALSE) &&
1224 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1225 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1226 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1227 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1228 handle_specular_base(sb, color);
1230 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1231 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1232 handle_specular_base(sb, color);
1234 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1235 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1236 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1237 handle_specular_base(sb, color);
1239 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1240 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1241 handle_specular_base(sb, color);
1244 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1247 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1248 if (lighted == TRUE) {
1249 DWORD color = *color_d;
1250 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1251 /* Special case where the specular value is used to do fogging */
1252 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1253 color &= 0xFF000000; /* Only keep the alpha component */
1254 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1255 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1256 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1258 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1259 /* Standard specular value in transformed mode. TODO */
1261 handle_diffuse_base(sb, &color);
1263 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1264 handle_diffuse(sb, color_d, FALSE);
1265 handle_specular(sb, color_s, FALSE);
1267 /* In that case, only put the diffuse color... */
1268 handle_diffuse_base(sb, color_d);
1273 inline static void handle_texture(D3DVALUE *coords) {
1274 glTexCoord2fv(coords);
1276 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1277 /* For the moment, draw only the first texture.. */
1278 if (tex_index == 0) glTexCoord2fv(coords);
1281 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1282 D3DPRIMITIVETYPE d3dptPrimitiveType,
1283 DWORD d3dvtVertexType,
1284 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1285 DWORD dwVertexCount,
1290 BOOLEAN vertex_lighted = FALSE;
1291 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1292 int num_active_stages = 0;
1294 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1295 if (TRACE_ON(ddraw)) {
1296 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1299 /* This is to prevent 'thread contention' between a thread locking the device and another
1300 doing 3D display on it... */
1301 EnterCriticalSection(&(This->crit));
1304 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1305 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1308 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1310 /* Just a hack for now.. Will have to find better algorithm :-/ */
1311 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1312 vertex_lighted = TRUE;
1314 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1317 /* Compute the number of active texture stages and set the various texture parameters */
1318 num_active_stages = draw_primitive_handle_textures(This);
1320 draw_primitive_handle_GL_state(This,
1321 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1323 draw_primitive_start_GL(d3dptPrimitiveType);
1325 /* Some fast paths first before the generic case.... */
1326 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1329 for (index = 0; index < dwIndexCount; index++) {
1330 int i = (dwIndices == NULL) ? index : dwIndices[index];
1332 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1333 D3DVALUE *tex_coord =
1334 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1335 D3DVALUE *position =
1336 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1338 handle_normal(normal);
1339 handle_texture(tex_coord);
1340 handle_xyz(position);
1342 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1343 position[0], position[1], position[2],
1344 normal[0], normal[1], normal[2],
1345 tex_coord[0], tex_coord[1]);
1347 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1350 for (index = 0; index < dwIndexCount; index++) {
1351 int i = (dwIndices == NULL) ? index : dwIndices[index];
1353 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1355 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1356 D3DVALUE *tex_coord =
1357 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1358 D3DVALUE *position =
1359 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1361 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1362 handle_texture(tex_coord);
1363 handle_xyzrhw(position);
1365 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1366 position[0], position[1], position[2], position[3],
1367 (*color_d >> 16) & 0xFF,
1368 (*color_d >> 8) & 0xFF,
1369 (*color_d >> 0) & 0xFF,
1370 (*color_d >> 24) & 0xFF,
1371 (*color_s >> 16) & 0xFF,
1372 (*color_s >> 8) & 0xFF,
1373 (*color_s >> 0) & 0xFF,
1374 (*color_s >> 24) & 0xFF,
1375 tex_coord[0], tex_coord[1]);
1377 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1378 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1379 /* This is the 'slow path' but that should support all possible vertex formats out there...
1380 Note that people should write a fast path for all vertex formats out there...
1383 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1384 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1386 for (index = 0; index < dwIndexCount; index++) {
1387 int i = (dwIndices == NULL) ? index : dwIndices[index];
1390 if (d3dvtVertexType & D3DFVF_NORMAL) {
1392 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1393 handle_normal(normal);
1395 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1397 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1399 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1400 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1402 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1404 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1405 handle_specular(&(This->state_block), color_s, vertex_lighted);
1406 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1408 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1409 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1413 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1414 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF0000;
1415 if (tex_index >= num_tex_index) {
1416 handle_textures((D3DVALUE *) no_index, tex_stage);
1418 D3DVALUE *tex_coord =
1419 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1420 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1421 handle_textures(tex_coord, tex_stage);
1425 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1426 D3DVALUE *position =
1427 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1428 handle_xyz(position);
1429 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1430 D3DVALUE *position =
1431 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1432 handle_xyzrhw(position);
1435 if (TRACE_ON(ddraw_geom)) {
1438 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1439 D3DVALUE *position =
1440 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1441 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1442 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1443 D3DVALUE *position =
1444 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1445 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1447 if (d3dvtVertexType & D3DFVF_NORMAL) {
1449 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1450 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1452 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1454 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1455 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1456 (*color_d >> 16) & 0xFF,
1457 (*color_d >> 8) & 0xFF,
1458 (*color_d >> 0) & 0xFF,
1459 (*color_d >> 24) & 0xFF);
1461 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1463 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1464 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1465 (*color_s >> 16) & 0xFF,
1466 (*color_s >> 8) & 0xFF,
1467 (*color_s >> 0) & 0xFF,
1468 (*color_s >> 24) & 0xFF);
1470 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1471 D3DVALUE *tex_coord =
1472 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1473 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1474 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1476 TRACE_(ddraw_geom)("\n");
1480 ERR(" matrix weighting not handled yet....\n");
1485 /* Whatever the case, disable the color material stuff */
1486 glDisable(GL_COLOR_MATERIAL);
1491 LeaveCriticalSection(&(This->crit));
1495 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1496 D3DPRIMITIVETYPE d3dptPrimitiveType,
1497 DWORD d3dvtVertexType,
1499 DWORD dwVertexCount,
1502 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1503 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1505 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1506 if (TRACE_ON(ddraw)) {
1507 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1510 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1511 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1517 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1518 D3DPRIMITIVETYPE d3dptPrimitiveType,
1519 DWORD d3dvtVertexType,
1521 DWORD dwVertexCount,
1526 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1527 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1529 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1530 if (TRACE_ON(ddraw)) {
1531 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1534 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1535 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1541 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1542 D3DPRIMITIVETYPE d3dptPrimitiveType,
1544 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1545 DWORD dwVertexCount,
1548 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1550 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1551 if (TRACE_ON(ddraw)) {
1552 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1554 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1560 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1561 D3DPRIMITIVETYPE d3dptPrimitiveType,
1563 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1564 DWORD dwVertexCount,
1569 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1571 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1572 if (TRACE_ON(ddraw)) {
1573 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1576 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1582 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1583 D3DPRIMITIVETYPE d3dptPrimitiveType,
1584 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1585 DWORD dwStartVertex,
1586 DWORD dwNumVertices,
1589 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1590 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1591 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1593 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1594 if (TRACE_ON(ddraw)) {
1595 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1598 if (vb_impl->processed == TRUE) {
1599 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1600 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1602 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1603 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1604 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1606 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1607 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1610 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1611 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1618 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1619 D3DPRIMITIVETYPE d3dptPrimitiveType,
1620 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1621 DWORD dwStartVertex,
1622 DWORD dwNumVertices,
1627 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1628 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1629 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1631 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1632 if (TRACE_ON(ddraw)) {
1633 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1636 if (vb_impl->processed == TRUE) {
1637 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1638 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1640 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1641 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1642 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1644 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1645 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1648 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1649 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1655 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1657 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1659 BOOLEAN is_complement = FALSE;
1660 BOOLEAN is_alpha_replicate = FALSE;
1661 BOOLEAN handled = TRUE;
1663 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1667 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1668 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1673 if (tex_op == D3DTOP_SELECTARG2) {
1677 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1678 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1683 if (tex_op == D3DTOP_SELECTARG2) {
1688 if (dwState & D3DTA_COMPLEMENT) {
1689 is_complement = TRUE;
1691 if (dwState & D3DTA_ALPHAREPLICATE) {
1692 is_alpha_replicate = TRUE;
1694 dwState &= D3DTA_SELECTMASK;
1695 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1696 dwState = D3DTA_DIFFUSE;
1700 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1701 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1702 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1703 case D3DTA_TFACTOR: {
1704 /* Get the constant value from the current rendering state */
1706 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1708 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1709 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1710 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1711 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1712 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1714 src = GL_CONSTANT_EXT;
1716 default: src = GL_TEXTURE; handled = FALSE; break;
1720 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1721 if (is_alpha_replicate) {
1722 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1724 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1727 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1728 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1735 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1737 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1740 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1741 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1745 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1747 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1749 switch (d3dTexStageStateType) {
1750 #define GEN_CASE(a) case a: type = #a; break
1751 GEN_CASE(D3DTSS_COLOROP);
1752 GEN_CASE(D3DTSS_COLORARG1);
1753 GEN_CASE(D3DTSS_COLORARG2);
1754 GEN_CASE(D3DTSS_ALPHAOP);
1755 GEN_CASE(D3DTSS_ALPHAARG1);
1756 GEN_CASE(D3DTSS_ALPHAARG2);
1757 GEN_CASE(D3DTSS_BUMPENVMAT00);
1758 GEN_CASE(D3DTSS_BUMPENVMAT01);
1759 GEN_CASE(D3DTSS_BUMPENVMAT10);
1760 GEN_CASE(D3DTSS_BUMPENVMAT11);
1761 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1762 GEN_CASE(D3DTSS_ADDRESS);
1763 GEN_CASE(D3DTSS_ADDRESSU);
1764 GEN_CASE(D3DTSS_ADDRESSV);
1765 GEN_CASE(D3DTSS_BORDERCOLOR);
1766 GEN_CASE(D3DTSS_MAGFILTER);
1767 GEN_CASE(D3DTSS_MINFILTER);
1768 GEN_CASE(D3DTSS_MIPFILTER);
1769 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1770 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1771 GEN_CASE(D3DTSS_MAXANISOTROPY);
1772 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1773 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1774 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1776 default: type = "UNKNOWN";
1779 /* Store the values in the state array */
1780 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1781 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1782 /* Some special cases when one state modifies more than one... */
1783 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1784 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1785 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1790 switch (d3dTexStageStateType) {
1791 case D3DTSS_MINFILTER:
1792 case D3DTSS_MIPFILTER:
1793 if (TRACE_ON(ddraw)) {
1794 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1795 switch ((D3DTEXTUREMINFILTER) dwState) {
1796 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1797 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1798 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1801 switch ((D3DTEXTUREMIPFILTER) dwState) {
1802 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1803 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1804 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1805 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1811 case D3DTSS_MAGFILTER:
1812 if (TRACE_ON(ddraw)) {
1813 switch ((D3DTEXTUREMAGFILTER) dwState) {
1814 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1815 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1816 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1821 case D3DTSS_ADDRESS:
1822 case D3DTSS_ADDRESSU:
1823 case D3DTSS_ADDRESSV: {
1824 switch ((D3DTEXTUREADDRESS) dwState) {
1825 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1826 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1827 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1828 #if defined(GL_VERSION_1_4)
1829 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1830 #elif defined(GL_ARB_texture_mirrored_repeat)
1831 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1833 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1837 case D3DTSS_ALPHAOP:
1838 case D3DTSS_COLOROP: {
1840 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1845 #define GEN_CASE(a) case a: value = #a; break
1846 GEN_CASE(D3DTOP_DISABLE);
1847 GEN_CASE(D3DTOP_SELECTARG1);
1848 GEN_CASE(D3DTOP_SELECTARG2);
1849 GEN_CASE(D3DTOP_MODULATE);
1850 GEN_CASE(D3DTOP_MODULATE2X);
1851 GEN_CASE(D3DTOP_MODULATE4X);
1852 GEN_CASE(D3DTOP_ADD);
1853 GEN_CASE(D3DTOP_ADDSIGNED);
1854 GEN_CASE(D3DTOP_ADDSIGNED2X);
1855 GEN_CASE(D3DTOP_SUBTRACT);
1856 GEN_CASE(D3DTOP_ADDSMOOTH);
1857 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1858 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1859 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1860 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1861 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1862 GEN_CASE(D3DTOP_PREMODULATE);
1863 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1864 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1865 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1866 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1867 GEN_CASE(D3DTOP_BUMPENVMAP);
1868 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1869 GEN_CASE(D3DTOP_DOTPRODUCT3);
1870 GEN_CASE(D3DTOP_FORCE_DWORD);
1872 default: value = "UNKNOWN";
1875 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1876 glDisable(GL_TEXTURE_2D);
1877 TRACE(" disabling 2D texturing.\n");
1879 /* Re-enable texturing */
1880 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1881 glEnable(GL_TEXTURE_2D);
1882 TRACE(" enabling 2D texturing.\n");
1885 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1886 if (dwState != D3DTOP_DISABLE) {
1887 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1888 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1889 glThis->current_tex_env = GL_COMBINE_EXT;
1893 /* Now set up the operand correctly */
1895 case D3DTOP_DISABLE:
1896 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1897 and it works, so ignore this op */
1898 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1901 case D3DTOP_SELECTARG1:
1902 case D3DTOP_SELECTARG2:
1903 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1906 case D3DTOP_MODULATE4X:
1907 scale = scale * 2; /* Drop through */
1908 case D3DTOP_MODULATE2X:
1909 scale = scale * 2; /* Drop through */
1910 case D3DTOP_MODULATE:
1911 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1915 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1918 case D3DTOP_ADDSIGNED2X:
1919 scale = scale * 2; /* Drop through */
1920 case D3DTOP_ADDSIGNED:
1921 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1924 /* For the four blending modes, use the Arg2 parameter */
1925 case D3DTOP_BLENDDIFFUSEALPHA:
1926 case D3DTOP_BLENDTEXTUREALPHA:
1927 case D3DTOP_BLENDFACTORALPHA:
1928 case D3DTOP_BLENDCURRENTALPHA: {
1929 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1932 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1933 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1934 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1935 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1938 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1939 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1940 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1941 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1942 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1951 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1952 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1953 /* Switch the arguments if needed... */
1954 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1955 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1956 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1958 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1959 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1962 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1963 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1965 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1966 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1972 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1973 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1975 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1977 TRACE(" Stage type is : %s => %s\n", type, value);
1979 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1983 case D3DTSS_COLORARG1:
1984 case D3DTSS_COLORARG2:
1985 case D3DTSS_ALPHAARG1:
1986 case D3DTSS_ALPHAARG2: {
1987 const char *value, *value_comp = "", *value_alpha = "";
1989 D3DTEXTUREOP tex_op;
1991 switch (dwState & D3DTA_SELECTMASK) {
1992 #define GEN_CASE(a) case a: value = #a; break
1993 GEN_CASE(D3DTA_DIFFUSE);
1994 GEN_CASE(D3DTA_CURRENT);
1995 GEN_CASE(D3DTA_TEXTURE);
1996 GEN_CASE(D3DTA_TFACTOR);
1997 GEN_CASE(D3DTA_SPECULAR);
1999 default: value = "UNKNOWN";
2001 if (dwState & D3DTA_COMPLEMENT) {
2002 value_comp = " | D3DTA_COMPLEMENT";
2004 if (dwState & D3DTA_ALPHAREPLICATE) {
2005 value_alpha = " | D3DTA_ALPHAREPLICATE";
2008 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2009 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2011 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2014 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2017 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2019 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2023 case D3DTSS_MIPMAPLODBIAS: {
2024 D3DVALUE value = *((D3DVALUE *) &dwState);
2025 BOOLEAN handled = TRUE;
2031 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2033 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2037 case D3DTSS_MAXMIPLEVEL:
2038 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2041 case D3DTSS_BORDERCOLOR:
2042 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2043 ((dwState >> 16) & 0xFF),
2044 ((dwState >> 8) & 0xFF),
2045 ((dwState >> 0) & 0xFF),
2046 ((dwState >> 24) & 0xFF));
2049 case D3DTSS_TEXCOORDINDEX: {
2050 BOOLEAN handled = TRUE;
2053 switch (dwState & 0xFFFF0000) {
2054 #define GEN_CASE(a) case a: value = #a; break
2055 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2056 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2057 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2058 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2060 default: value = "UNKNOWN";
2062 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2066 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2068 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2072 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2073 const char *projected = "", *value;
2074 BOOLEAN handled = TRUE;
2075 switch (dwState & 0xFF) {
2076 #define GEN_CASE(a) case a: value = #a; break
2077 GEN_CASE(D3DTTFF_DISABLE);
2078 GEN_CASE(D3DTTFF_COUNT1);
2079 GEN_CASE(D3DTTFF_COUNT2);
2080 GEN_CASE(D3DTTFF_COUNT3);
2081 GEN_CASE(D3DTTFF_COUNT4);
2083 default: value = "UNKNOWN";
2085 if (dwState & D3DTTFF_PROJECTED) {
2086 projected = " | D3DTTFF_PROJECTED";
2090 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2091 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2094 if (handled == TRUE) {
2095 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2097 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2102 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2112 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2114 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2117 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2118 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2120 /* First check if we need to bind any other texture for this stage */
2121 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2122 if (This->current_texture[stage] == NULL) {
2123 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2124 glBindTexture(GL_TEXTURE_2D, 0);
2125 glDisable(GL_TEXTURE_2D);
2127 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2129 if (glThis->current_bound_texture[stage] == NULL) {
2130 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2131 TRACE(" enabling 2D texturing and");
2132 glEnable(GL_TEXTURE_2D);
2135 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2136 glBindTexture(GL_TEXTURE_2D, tex_name);
2139 glThis->current_bound_texture[stage] = This->current_texture[stage];
2141 if (glThis->current_bound_texture[stage] == NULL) {
2142 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2144 TRACE(" using already bound texture id %d for stage %ld.\n",
2145 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2149 /* If no texure valid for this stage, go out of the loop */
2150 if (This->current_texture[stage] == NULL) break;
2152 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2153 This will also update the various texture parameters if needed.
2155 gltex_upload_texture(surf_ptr, This, stage);
2162 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2164 LPDIRECTDRAWSURFACE7 lpTexture2)
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2168 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2170 if (dwStage > 0) return DD_OK;
2172 if (This->current_texture[dwStage] != NULL) {
2173 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2176 if (lpTexture2 == NULL) {
2177 This->current_texture[dwStage] = NULL;
2179 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2180 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2181 This->current_texture[dwStage] = tex_impl;
2188 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2189 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2191 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2192 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2194 fill_opengl_caps_7(lpD3DHELDevDesc);
2196 TRACE(" returning caps : no dump function yet.\n");
2202 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2203 LPD3DMATERIAL7 lpMat)
2205 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2206 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2208 if (TRACE_ON(ddraw)) {
2209 TRACE(" material is : \n");
2210 dump_D3DMATERIAL7(lpMat);
2213 This->current_material = *lpMat;
2216 glMaterialfv(GL_FRONT_AND_BACK,
2218 (float *) &(This->current_material.u.diffuse));
2219 glMaterialfv(GL_FRONT_AND_BACK,
2221 (float *) &(This->current_material.u1.ambient));
2222 glMaterialfv(GL_FRONT_AND_BACK,
2224 (float *) &(This->current_material.u2.specular));
2225 glMaterialfv(GL_FRONT_AND_BACK,
2227 (float *) &(This->current_material.u3.emissive));
2228 glMaterialf(GL_FRONT_AND_BACK,
2230 This->current_material.u4.power); /* Not sure about this... */
2238 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2240 LPD3DLIGHT7 lpLight)
2242 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2243 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2244 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2246 if (TRACE_ON(ddraw)) {
2247 TRACE(" setting light : \n");
2248 dump_D3DLIGHT7(lpLight);
2251 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2252 This->set_lights |= 0x00000001 << dwLightIndex;
2253 This->light_parameters[dwLightIndex] = *lpLight;
2255 /* Some checks to print out nice warnings :-) */
2256 switch (lpLight->dltType) {
2257 case D3DLIGHT_DIRECTIONAL:
2258 case D3DLIGHT_POINT:
2259 /* These are handled properly... */
2263 if ((lpLight->dvTheta != 0.0) ||
2264 (lpLight->dvTheta != lpLight->dvPhi)) {
2265 ERR("dvTheta not fully supported yet !\n");
2270 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2273 /* This will force the Light setting on next drawing of primitives */
2274 glThis->transform_state = GL_TRANSFORM_NONE;
2280 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2284 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2285 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2287 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2291 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2292 /* Set the default parameters.. */
2293 TRACE(" setting default light parameters...\n");
2294 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2296 glEnable(GL_LIGHT0 + dwLightIndex);
2297 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2298 /* This light gets active... Need to update its parameters to GL before the next drawing */
2299 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2301 This->active_lights |= 0x00000001 << dwLightIndex;
2302 glThis->transform_state = GL_TRANSFORM_NONE;
2305 glDisable(GL_LIGHT0 + dwLightIndex);
2306 This->active_lights &= ~(0x00000001 << dwLightIndex);
2314 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2316 ICOM_THIS(IDirect3DDeviceImpl,iface);
2317 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2319 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2321 if (dwIndex >= This->max_clipping_planes) {
2322 return DDERR_INVALIDPARAMS;
2325 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2327 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2329 /* This is to force the reset of the transformation matrices on the next drawing.
2330 * This is needed to use the correct matrices for the various clipping planes.
2332 glThis->transform_state = GL_TRANSFORM_NONE;
2338 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2339 LPD3DVIEWPORT7 lpData)
2341 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2342 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2344 if (TRACE_ON(ddraw)) {
2345 TRACE(" viewport is : \n");
2346 TRACE(" - dwX = %ld dwY = %ld\n",
2347 lpData->dwX, lpData->dwY);
2348 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2349 lpData->dwWidth, lpData->dwHeight);
2350 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2351 lpData->dvMinZ, lpData->dvMaxZ);
2355 /* Set the viewport */
2356 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2357 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2358 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2360 if ((lpData->dwX != This->active_viewport.dwX) ||
2361 (lpData->dwY != This->active_viewport.dwY) ||
2362 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2363 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2364 glViewport(lpData->dwX,
2365 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2366 lpData->dwWidth, lpData->dwHeight);
2371 This->active_viewport = *lpData;
2376 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2377 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2379 # define XCAST(fun) (void*)
2382 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2384 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2385 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2386 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2387 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2388 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2389 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2390 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2391 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2392 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2393 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2394 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2395 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2396 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2397 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2398 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2399 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2400 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2401 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2402 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2403 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2404 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2405 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2406 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2407 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2408 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2409 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2410 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2411 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2412 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2413 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2414 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2415 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2416 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2417 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2418 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2419 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2420 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2421 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2422 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2423 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2424 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2425 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2426 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2427 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2428 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2429 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2430 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2431 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2432 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2433 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2436 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2441 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2442 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2444 # define XCAST(fun) (void*)
2447 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2449 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2450 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2451 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2452 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2453 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2454 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2455 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2456 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2457 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2458 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2459 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2460 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2461 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2462 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2463 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2464 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2465 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2466 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2467 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2468 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2469 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2470 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2471 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2472 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2473 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2474 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2475 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2476 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2477 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2478 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2479 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2480 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2481 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2482 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2483 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2484 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2485 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2486 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2487 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2488 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2489 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2490 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2491 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2494 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2499 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2500 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2502 # define XCAST(fun) (void*)
2505 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2507 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2508 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2509 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2510 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2511 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2512 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2513 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2514 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2515 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2516 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2517 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2518 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2519 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2520 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2521 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2522 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2523 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2524 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2525 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2526 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2527 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2528 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2529 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2530 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2531 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2532 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2533 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2534 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2535 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2536 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2537 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2538 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2539 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2540 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2543 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2548 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2549 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2551 # define XCAST(fun) (void*)
2554 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2556 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2557 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2558 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2559 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2560 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2561 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2562 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2563 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2564 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2565 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2566 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2567 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2568 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2569 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2570 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2571 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2572 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2573 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2574 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2575 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2576 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2577 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2578 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2581 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2585 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2586 WINE_GL_BUFFER_TYPE buffer_type,
2594 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2595 GLbitfield bitfield = 0;
2599 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2600 if (TRACE_ON(ddraw)) {
2603 TRACE(" rectangles : \n");
2604 for (i = 0; i < dwCount; i++) {
2605 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2614 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2615 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2619 /* Clears the screen */
2622 if (dwFlags & D3DCLEAR_TARGET) {
2623 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2624 /* TODO: optimize here the case where Clear changes all the screen... */
2625 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2627 glThis->state[buffer_type] = SURFACE_GL;
2630 if (dwFlags & D3DCLEAR_ZBUFFER) {
2631 bitfield |= GL_DEPTH_BUFFER_BIT;
2632 if (glThis->depth_mask == FALSE) {
2633 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2635 if (dvZ != glThis->prev_clear_Z) {
2637 glThis->prev_clear_Z = dvZ;
2639 TRACE(" depth value : %f\n", dvZ);
2641 if (dwFlags & D3DCLEAR_STENCIL) {
2642 bitfield |= GL_STENCIL_BUFFER_BIT;
2643 if (dwStencil != glThis->prev_clear_stencil) {
2644 glClearStencil(dwStencil);
2645 glThis->prev_clear_stencil = dwStencil;
2647 TRACE(" stencil value : %ld\n", dwStencil);
2649 if (dwFlags & D3DCLEAR_TARGET) {
2650 bitfield |= GL_COLOR_BUFFER_BIT;
2651 if (dwColor != glThis->prev_clear_color) {
2652 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2653 ((dwColor >> 8) & 0xFF) / 255.0,
2654 ((dwColor >> 0) & 0xFF) / 255.0,
2655 ((dwColor >> 24) & 0xFF) / 255.0);
2656 glThis->prev_clear_color = dwColor;
2658 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2661 glEnable(GL_SCISSOR_TEST);
2662 for (i = 0; i < dwCount; i++) {
2663 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2664 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2667 glDisable(GL_SCISSOR_TEST);
2669 if (dwFlags & D3DCLEAR_ZBUFFER) {
2670 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2678 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2686 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2690 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2691 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2693 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2694 WINE_GL_BUFFER_TYPE buffer_type;
2696 /* First check if we BLT to the backbuffer... */
2697 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2698 buffer_type = WINE_GL_BUFFER_BACK;
2699 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2700 buffer_type = WINE_GL_BUFFER_FRONT;
2702 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2703 return DDERR_INVALIDPARAMS;
2706 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2707 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2708 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2709 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2710 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2711 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2714 return DDERR_INVALIDPARAMS;
2716 *buffer_type_p = buffer_type;
2722 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2723 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2724 DWORD dwFlags, LPDDBLTFX lpbltfx)
2726 WINE_GL_BUFFER_TYPE buffer_type;
2730 rect.u1.x1 = rdst->left;
2731 rect.u2.y1 = rdst->top;
2732 rect.u3.x2 = rdst->right;
2733 rect.u4.y2 = rdst->bottom;
2737 rect.u3.x2 = This->surface_desc.dwWidth;
2738 rect.u4.y2 = This->surface_desc.dwHeight;
2741 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2743 if (dwFlags & DDBLT_COLORFILL) {
2744 /* This is easy to handle for the D3D Device... */
2748 /* The color as given in the Blt function is in the format of the frame-buffer...
2749 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2751 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2752 if (This->palette) {
2753 color = ((0xFF000000) |
2754 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2755 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2756 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2760 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2761 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2762 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2763 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2764 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2765 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2766 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2767 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2770 color = ((0xFF000000) |
2771 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2772 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2773 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2775 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2776 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2777 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2778 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2779 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2780 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2782 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2783 return DDERR_INVALIDPARAMS;
2786 ERR("Wrong surface type for BLT override !\n");
2787 return DDERR_INVALIDPARAMS;
2790 TRACE(" executing D3D Device override.\n");
2794 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2795 if (buffer_type == WINE_GL_BUFFER_FRONT)
2796 glDrawBuffer(GL_FRONT);
2798 glDrawBuffer(GL_BACK);
2800 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2802 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2803 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2804 glDrawBuffer(prev_draw);
2809 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2810 /* Normal blit without any special case... */
2812 /* And which has a SRC surface */
2813 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2815 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2816 (src_impl->d3ddevice == This->d3ddevice) &&
2817 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2818 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2822 WINE_GL_BUFFER_TYPE src_buffer_type;
2823 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2824 BOOLEAN initial = FALSE;
2829 src_rect.u1.x1 = rsrc->left;
2830 src_rect.u2.y1 = rsrc->top;
2831 src_rect.u3.x2 = rsrc->right;
2832 src_rect.u4.y2 = rsrc->bottom;
2836 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2837 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2840 width = src_rect.u3.x2 - src_rect.u1.x1;
2841 height = src_rect.u4.y2 - src_rect.u2.y1;
2843 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2844 (height != (rect.u4.y2 - rect.u2.y1))) {
2845 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2846 return DDERR_INVALIDPARAMS;
2849 /* First check if we BLT from the backbuffer... */
2850 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2851 src_buffer_type = WINE_GL_BUFFER_BACK;
2852 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2853 src_buffer_type = WINE_GL_BUFFER_FRONT;
2855 ERR("Unexpected case in direct buffer to buffer copy !\n");
2856 return DDERR_INVALIDPARAMS;
2859 TRACE(" using direct buffer to buffer copy.\n");
2863 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2865 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2866 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2867 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2869 return DDERR_INVALIDPARAMS;
2872 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2873 if (buffer_type == WINE_GL_BUFFER_FRONT)
2874 glDrawBuffer(GL_FRONT);
2876 glDrawBuffer(GL_BACK);
2878 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2879 glReadBuffer(GL_FRONT);
2881 glReadBuffer(GL_BACK);
2883 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2884 And directly re-draws this on the destination buffer. */
2885 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2888 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2889 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2891 get_height = UNLOCK_TEX_SIZE;
2893 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2896 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2897 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2899 get_width = UNLOCK_TEX_SIZE;
2901 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2902 0, UNLOCK_TEX_SIZE - get_height,
2903 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2904 get_width, get_height);
2907 glTexCoord2f(0.0, 0.0);
2908 glVertex3d(rect.u1.x1 + x,
2909 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2911 glTexCoord2f(1.0, 0.0);
2912 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2913 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2915 glTexCoord2f(1.0, 1.0);
2916 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2919 glTexCoord2f(0.0, 1.0);
2920 glVertex3d(rect.u1.x1 + x,
2927 upload_surface_to_tex_memory_release();
2928 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2930 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2931 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2932 glDrawBuffer(prev_draw);
2938 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
2939 (this prevents calling glReadPixels) */
2943 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2944 BOOLEAN initial = FALSE;
2947 double x_stretch, y_stretch;
2949 if (dwFlags & DDBLT_KEYSRC) {
2950 /* As I have no game using this, did not bother to do it yet as I cannot test it anyway */
2951 FIXME(" Blt overide with color-keying not supported yet.\n");
2952 return DDERR_INVALIDPARAMS;
2956 src_rect.u1.x1 = rsrc->left;
2957 src_rect.u2.y1 = rsrc->top;
2958 src_rect.u3.x2 = rsrc->right;
2959 src_rect.u4.y2 = rsrc->bottom;
2963 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2964 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2967 width = src_rect.u3.x2 - src_rect.u1.x1;
2968 height = src_rect.u4.y2 - src_rect.u2.y1;
2970 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
2971 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
2973 TRACE(" using memory to buffer Blt overide.\n");
2977 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2979 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
2980 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2981 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
2983 return DDERR_INVALIDPARAMS;
2986 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2987 if (buffer_type == WINE_GL_BUFFER_FRONT)
2988 glDrawBuffer(GL_FRONT);
2990 glDrawBuffer(GL_BACK);
2992 /* Now the serious stuff happens. This is basically the same code that for the memory
2993 flush to frame buffer ... with stretching and different rectangles added :-) */
2994 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2997 flush_rect.top = src_rect.u2.y1 + y;
2998 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3000 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3002 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3003 flush_rect.left = src_rect.u1.x1 + x;
3004 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3006 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3008 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3011 glTexCoord2f(0.0, 0.0);
3012 glVertex3d(rect.u1.x1 + (x * x_stretch),
3013 rect.u2.y1 + (y * y_stretch),
3015 glTexCoord2f(1.0, 0.0);
3016 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3017 rect.u2.y1 + (y * y_stretch),
3019 glTexCoord2f(1.0, 1.0);
3020 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3021 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3023 glTexCoord2f(0.0, 1.0);
3024 glVertex3d(rect.u1.x1 + (x * x_stretch),
3025 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3031 upload_surface_to_tex_memory_release();
3032 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
3034 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3035 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3036 glDrawBuffer(prev_draw);
3044 return DDERR_INVALIDPARAMS;
3048 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3049 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3050 LPRECT rsrc, DWORD trans)
3054 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3055 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3056 WINE_GL_BUFFER_TYPE buffer_type;
3060 int width, height, x, y;
3062 /* Cannot support DSTCOLORKEY blitting... */
3063 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3066 WARN("rsrc is NULL - getting the whole surface !!\n");
3068 rsrc->left = rsrc->top = 0;
3069 rsrc->right = src_impl->surface_desc.dwWidth;
3070 rsrc->bottom = src_impl->surface_desc.dwHeight;
3078 rdst.right = dstx + (rsrc->right - rsrc->left);
3079 if (rdst.right > This->surface_desc.dwWidth) {
3080 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3081 rdst.right = This->surface_desc.dwWidth;
3083 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3084 if (rdst.bottom > This->surface_desc.dwHeight) {
3085 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3086 rdst.bottom = This->surface_desc.dwHeight;
3089 width = rsrc->right - rsrc->left;
3090 height = rsrc->bottom - rsrc->top;
3092 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3094 TRACE(" using BltFast memory to frame buffer overide.\n");
3098 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3100 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3101 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3102 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3103 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3105 return DDERR_INVALIDPARAMS;
3108 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3109 if (buffer_type == WINE_GL_BUFFER_FRONT)
3110 glDrawBuffer(GL_FRONT);
3112 glDrawBuffer(GL_BACK);
3114 /* Now the serious stuff happens. This is basically the same code that for the memory
3115 flush to frame buffer but with different rectangles for source and destination :-) */
3116 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3119 flush_rect.top = rsrc->top + y;
3120 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3122 (rsrc->top + y + UNLOCK_TEX_SIZE));
3124 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3125 flush_rect.left = rsrc->left + x;
3126 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3128 (rsrc->left + x + UNLOCK_TEX_SIZE));
3130 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3133 glTexCoord2f(0.0, 0.0);
3134 glVertex3d(rdst.left + x,
3137 glTexCoord2f(1.0, 0.0);
3138 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3141 glTexCoord2f(1.0, 1.0);
3142 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3143 rdst.top + (y + UNLOCK_TEX_SIZE),
3145 glTexCoord2f(0.0, 1.0);
3146 glVertex3d(rdst.left + x,
3147 rdst.top + (y + UNLOCK_TEX_SIZE),
3153 upload_surface_to_tex_memory_release();
3154 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3156 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3157 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3158 glDrawBuffer(prev_draw);
3166 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3168 GLfloat height, width;
3169 GLfloat trans_mat[16];
3171 TRACE("(%p)\n", This);
3173 width = This->surface->surface_desc.dwWidth;
3174 height = This->surface->surface_desc.dwHeight;
3176 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3177 to OpenGL screen coordinates (ie the upper left corner is not the same).
3178 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3179 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3180 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3181 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3182 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
3183 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3186 glMatrixMode(GL_MODELVIEW);
3188 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3189 Correctness Tips section).
3191 Basically, from what I understood, if the game does not filter the font texture,
3192 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3193 one and we will have strange artifacts (as the rounding and stuff may give different results
3194 for different pixels, ie sometimes take the left pixel, sometimes the right).
3196 glTranslatef(0.375, 0.375, 0);
3197 glMatrixMode(GL_PROJECTION);
3198 glLoadMatrixf(trans_mat);
3203 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3204 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3206 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3209 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3210 glMatrixMode(GL_MODELVIEW);
3211 glLoadMatrixf((float *) view_mat);
3213 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3214 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3217 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3218 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3221 plane[0] = This->clipping_planes[i].plane[0];
3222 plane[1] = This->clipping_planes[i].plane[1];
3223 plane[2] = This->clipping_planes[i].plane[2];
3224 plane[3] = This->clipping_planes[i].plane[3];
3226 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3230 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3234 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3235 if (runner & This->active_lights) {
3236 switch (This->light_parameters[i].dltType) {
3237 case D3DLIGHT_DIRECTIONAL: {
3239 float cut_off = 180.0;
3241 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3242 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3243 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3244 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3246 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3247 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3248 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3250 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3253 case D3DLIGHT_POINT: {
3255 float cut_off = 180.0;
3257 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3258 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3259 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3260 position[0] = This->light_parameters[i].dvPosition.u1.x;
3261 position[1] = This->light_parameters[i].dvPosition.u2.y;
3262 position[2] = This->light_parameters[i].dvPosition.u3.z;
3264 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3265 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3266 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3267 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3268 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3271 case D3DLIGHT_SPOT: {
3274 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3276 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3277 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3278 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3280 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3281 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3282 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3284 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3285 position[0] = This->light_parameters[i].dvPosition.u1.x;
3286 position[1] = This->light_parameters[i].dvPosition.u2.y;
3287 position[2] = This->light_parameters[i].dvPosition.u3.z;
3289 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3290 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3291 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3292 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3293 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3294 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3298 /* No warning here as it's already done at light setting */
3305 glMultMatrixf((float *) world_mat);
3307 if ((matrices & PROJMAT_CHANGED) != 0) {
3308 glMatrixMode(GL_PROJECTION);
3309 glLoadMatrixf((float *) proj_mat);
3315 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3317 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3318 DWORD tex_mat, tex_stage;
3320 TRACE("(%p,%08lx)\n", This, matrices);
3322 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3323 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3324 /* This will force an update of the transform state at the next drawing. */
3325 glThis->transform_state = GL_TRANSFORM_NONE;
3328 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3329 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3332 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3333 if (matrices & tex_mat) {
3334 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3335 if (tex_stage == 0) {
3336 /* No multi-texturing support for now ... */
3337 glMatrixMode(GL_TEXTURE);
3338 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3339 if (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE))) {
3340 This->tex_mat_is_identity[tex_stage] = FALSE;
3342 This->tex_mat_is_identity[tex_stage] = TRUE;
3346 if (tex_stage == 0) {
3347 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3348 glMatrixMode(GL_TEXTURE);
3350 This->tex_mat_is_identity[tex_stage] = TRUE;
3360 /* TODO for both these functions :
3361 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3362 by other OpenGL code in D3D
3363 - handle the case where no 'Begin / EndScene' was done between two locks
3364 - handle the rectangles in the unlock too
3365 - handle pitch correctly...
3367 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3369 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3370 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3371 WINE_GL_BUFFER_TYPE buffer_type;
3374 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3375 buffer_type = WINE_GL_BUFFER_FRONT;
3376 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3377 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3378 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3380 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3381 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3382 buffer_type = WINE_GL_BUFFER_BACK;
3383 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3384 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3385 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3387 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3389 ERR("Wrong surface type for locking !\n");
3393 if (pRect == NULL) {
3396 loc_rect.bottom = This->surface_desc.dwHeight;
3397 loc_rect.right = This->surface_desc.dwWidth;
3401 /* Try to acquire the device critical section */
3402 EnterCriticalSection(&(d3d_dev->crit));
3404 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3405 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3406 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3408 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3410 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3411 /* Check if the new rectangle is in the previous one or not.
3412 If it is not, flush first the previous locks on screen.
3414 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3415 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3416 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3417 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3418 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3419 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3420 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3421 pRect->left, pRect->top, pRect->right, pRect->bottom,
3422 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3423 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3424 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3426 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3427 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3429 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3431 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3434 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3435 /* If the surface is already in memory, no need to do anything here... */
3436 GLenum buffer_format;
3437 GLenum buffer_color;
3441 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3442 pRect->left, pRect->top, pRect->right, pRect->bottom);
3444 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3445 may only write to the device... But when we will blit it back to the screen, we need
3446 also to blit correctly the parts the application did not overwrite... */
3448 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3449 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3450 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3451 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3452 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3453 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3454 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3455 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3456 buffer_color = GL_RGB;
3457 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3458 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3459 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3460 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3461 buffer_format = GL_UNSIGNED_BYTE;
3462 buffer_color = GL_RGB;
3463 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3464 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3465 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3466 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3467 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3468 buffer_color = GL_BGRA;
3470 ERR(" unsupported pixel format at device locking.\n");
3474 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3480 if (buffer_type == WINE_GL_BUFFER_FRONT)
3481 /* Application wants to lock the front buffer */
3482 glReadBuffer(GL_FRONT);
3484 /* Application wants to lock the back buffer */
3485 glReadBuffer(GL_BACK);
3487 dst = ((char *)This->surface_desc.lpSurface) +
3488 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3489 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3490 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3492 glReadPixels(pRect->left, y,
3493 pRect->right - pRect->left, 1,
3494 buffer_color, buffer_format, dst);
3495 dst += This->surface_desc.u1.lPitch;
3498 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3501 /* I keep this code here as it's very useful to debug :-) */
3503 static int flush_count = 0;
3507 if ((++flush_count % 50) == 0) {
3508 sprintf(buf, "lock_%06d.pnm", flush_count);
3509 f = fopen(buf, "wb");
3510 DDRAW_dump_surface_to_disk(This, f);
3519 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3521 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3523 BOOLEAN initial = FALSE;
3526 /* Note : no need here to lock the 'device critical section' as we are already protected by
3527 the GL critical section. */
3529 if (pRect == NULL) {
3532 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3533 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3537 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3539 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3541 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3542 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3543 ERR(" unsupported pixel format at frame buffer flush.\n");
3547 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3551 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3553 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3554 /* First, upload the texture... */
3555 flush_rect.left = x;
3556 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3558 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3561 glTexCoord2f(0.0, 0.0);
3562 glVertex3d(x, y, 0.5);
3563 glTexCoord2f(1.0, 0.0);
3564 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3565 glTexCoord2f(1.0, 1.0);
3566 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3567 glTexCoord2f(0.0, 1.0);
3568 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3573 upload_surface_to_tex_memory_release();
3574 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3577 /* I keep this code here as it's very useful to debug :-) */
3579 static int flush_count = 0;
3583 if ((++flush_count % 50) == 0) {
3584 sprintf(buf, "flush_%06d.pnm", flush_count);
3585 f = fopen(buf, "wb");
3586 DDRAW_dump_surface_to_disk(surf, f);
3592 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3594 WINE_GL_BUFFER_TYPE buffer_type;
3595 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3596 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3598 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3599 buffer_type = WINE_GL_BUFFER_FRONT;
3600 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3601 buffer_type = WINE_GL_BUFFER_BACK;
3603 ERR("Wrong surface type for locking !\n");
3607 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3608 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3609 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3611 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3613 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3614 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3615 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3618 TRACE(" flushing front buffer immediatly on screen.\n");
3621 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3622 glDrawBuffer(GL_FRONT);
3623 /* Note: we do not use the application provided lock rectangle but our own stored at
3624 lock time. This is because in old D3D versions, the 'lock' parameter did not
3627 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
3628 glDrawBuffer(prev_draw);
3631 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3635 /* And 'frees' the device critical section */
3636 LeaveCriticalSection(&(d3d_dev->crit));
3640 apply_texture_state(IDirect3DDeviceImpl *This)
3644 /* Initialize texture stages states */
3645 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3646 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3647 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3648 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3649 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3656 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3658 IDirect3DDeviceImpl *object;
3659 IDirect3DDeviceGLImpl *gl_object;
3660 IDirectDrawSurfaceImpl *surf;
3665 XVisualInfo template;
3666 GLenum buffer = GL_FRONT;
3668 GLint max_clipping_planes = 0;
3670 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3671 if (object == NULL) return DDERR_OUTOFMEMORY;
3673 gl_object = (IDirect3DDeviceGLImpl *) object;
3677 object->surface = surface;
3678 object->set_context = set_context;
3679 object->clear = d3ddevice_clear_back;
3680 object->set_matrices = d3ddevice_set_matrices;
3681 object->matrices_updated = d3ddevice_matrices_updated;
3682 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3684 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3686 InitializeCriticalSection(&(object->crit));
3688 TRACE(" device critical section : %p\n", &(object->crit));
3690 device_context = GetDC(surface->ddraw_owner->window);
3691 gl_object->display = get_display(device_context);
3692 gl_object->drawable = get_drawable(device_context);
3693 ReleaseDC(surface->ddraw_owner->window,device_context);
3696 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3697 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3699 HeapFree(GetProcessHeap(), 0, object);
3700 ERR("No visual found !\n");
3702 return DDERR_INVALIDPARAMS;
3704 TRACE(" visual found\n");
3707 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3710 if (gl_object->gl_context == NULL) {
3711 HeapFree(GetProcessHeap(), 0, object);
3712 ERR("Error in context creation !\n");
3714 return DDERR_INVALIDPARAMS;
3716 TRACE(" context created (%p)\n", gl_object->gl_context);
3719 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3720 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3721 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3722 surf->aux_ctx = (LPVOID) object;
3723 surf->aux_data = (LPVOID) gl_object->drawable;
3724 surf->aux_flip = opengl_flip;
3729 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3731 TRACE(" no double buffering : drawing on the front buffer\n");
3735 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3736 IDirectDrawSurfaceImpl *surf2;
3737 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3738 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3739 TRACE(" checking surface %p :", surf2);
3740 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3741 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3742 /* Override the Lock / Unlock function for all these surfaces */
3743 surf2->lock_update_prev = surf2->lock_update;
3744 surf2->lock_update = d3ddevice_lock_update;
3745 surf2->unlock_update_prev = surf2->unlock_update;
3746 surf2->unlock_update = d3ddevice_unlock_update;
3747 /* And install also the blt / bltfast overrides */
3748 surf2->aux_blt = d3ddevice_blt;
3749 surf2->aux_bltfast = d3ddevice_bltfast;
3751 TRACE(" overiding direct surface access.\n");
3753 TRACE(" no overide.\n");
3755 surf2->d3ddevice = object;
3759 /* Set the various light parameters */
3760 for (light = 0; light < MAX_LIGHTS; light++) {
3761 /* Only set the fields that are not zero-created */
3762 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3763 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3764 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3765 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3766 object->light_parameters[light].dvDirection.u3.z = 1.0;
3769 /* Allocate memory for the matrices */
3770 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3771 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3772 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3773 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3774 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3775 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3776 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3777 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3778 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3779 object->tex_mat_is_identity[tex_num] = TRUE;
3782 /* Initialisation */
3783 TRACE(" setting current context\n");
3784 object->set_context(object);
3785 TRACE(" current context set\n");
3787 /* allocate the clipping planes */
3788 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3789 if (max_clipping_planes>32) {
3790 object->max_clipping_planes=32;
3792 object->max_clipping_planes = max_clipping_planes;
3794 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3795 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3797 glHint(GL_FOG_HINT,GL_NICEST);
3799 /* Initialize the various GL contexts to be in sync with what we store locally */
3802 glClearColor(0.0, 0.0, 0.0, 0.0);
3803 glDepthMask(GL_TRUE);
3804 gl_object->depth_mask = TRUE;
3805 glEnable(GL_DEPTH_TEST);
3806 gl_object->depth_test = TRUE;
3807 glDisable(GL_ALPHA_TEST);
3808 glDisable(GL_STENCIL_TEST);
3809 glDisable(GL_CULL_FACE);
3810 glDisable(GL_LIGHTING);
3811 glDisable(GL_BLEND);
3813 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3814 gl_object->current_tex_env = GL_REPLACE;
3816 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3817 glDrawBuffer(buffer);
3818 glReadBuffer(buffer);
3819 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3822 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3823 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3825 /* fill_device_capabilities(d3d->ddraw); */
3827 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3828 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3829 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3830 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3834 TRACE(" creating implementation at %p.\n", *obj);
3836 /* And finally warn D3D that this device is now present */
3837 object->d3d->d3d_added_device(object->d3d, object);
3839 /* FIXME: Should handle other versions than just 7 */
3840 InitDefaultStateBlock(&object->state_block, 7);
3841 /* Apply default render state and texture stage state values */
3842 apply_render_state(object, &object->state_block);
3843 apply_texture_state(object);
3845 /* And fill the fog table with the default fog value */
3846 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);