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);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
56 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
59 const float id_mat[16] = {
66 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
67 D3DPRIMITIVETYPE d3dptPrimitiveType,
68 DWORD d3dvtVertexType,
69 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
75 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
77 /* retrieve the X display to use on a given DC */
78 inline static Display *get_display( HDC hdc )
81 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
83 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
84 sizeof(display), (LPSTR)&display )) display = NULL;
90 /* retrieve the X drawable to use on a given DC */
91 inline static Drawable get_drawable( HDC hdc )
94 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
96 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
97 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
103 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
105 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
106 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
108 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
110 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
111 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]);
113 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
114 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
115 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
122 /*******************************************************************************
123 * OpenGL static functions
125 static void set_context(IDirect3DDeviceImpl* This)
127 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
129 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
131 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
132 ERR("Error in setting current context (context %p drawable %ld)!\n",
133 glThis->gl_context, glThis->drawable);
138 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
140 pc->dwSize = sizeof(*pc);
141 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
142 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
143 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
144 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
145 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
146 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
147 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
148 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
149 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
150 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
151 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
152 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
153 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
154 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
155 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
156 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
157 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
158 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
159 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
160 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
161 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
162 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
163 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
164 pc->dwStippleWidth = 32;
165 pc->dwStippleHeight = 32;
168 static void fill_opengl_caps(D3DDEVICEDESC *d1)
170 /* GLint maxlight; */
172 d1->dwSize = sizeof(*d1);
173 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
174 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
175 d1->dcmColorModel = D3DCOLOR_RGB;
176 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
177 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
178 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
179 /* D3D 7 capabilities */
180 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
181 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
182 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
183 d1->bClipping = TRUE;
184 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
185 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
186 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
187 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
188 fill_opengl_primcaps(&(d1->dpcLineCaps));
189 fill_opengl_primcaps(&(d1->dpcTriCaps));
190 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
191 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
192 d1->dwMaxBufferSize = 0;
193 d1->dwMaxVertexCount = 65536;
194 d1->dwMinTextureWidth = 1;
195 d1->dwMinTextureHeight = 1;
196 d1->dwMaxTextureWidth = 1024;
197 d1->dwMaxTextureHeight = 1024;
198 d1->dwMinStippleWidth = 1;
199 d1->dwMinStippleHeight = 1;
200 d1->dwMaxStippleWidth = 32;
201 d1->dwMaxStippleHeight = 32;
202 d1->dwMaxTextureRepeat = 16;
203 d1->dwMaxTextureAspectRatio = 1024;
204 d1->dwMaxAnisotropy = 0;
205 d1->dvGuardBandLeft = 0.0;
206 d1->dvGuardBandRight = 0.0;
207 d1->dvGuardBandTop = 0.0;
208 d1->dvGuardBandBottom = 0.0;
209 d1->dvExtentsAdjust = 0.0;
210 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
211 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
212 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
213 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
214 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
215 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
218 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
222 /* Copy first D3D1/2/3 capabilities */
223 fill_opengl_caps(&d1);
225 /* And fill the D3D7 one with it */
226 d->dwDevCaps = d1.dwDevCaps;
227 d->dpcLineCaps = d1.dpcLineCaps;
228 d->dpcTriCaps = d1.dpcTriCaps;
229 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
230 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
231 d->dwMinTextureWidth = d1.dwMinTextureWidth;
232 d->dwMinTextureHeight = d1.dwMinTextureHeight;
233 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
234 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
235 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
236 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
237 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
238 d->dvGuardBandLeft = d1.dvGuardBandLeft;
239 d->dvGuardBandTop = d1.dvGuardBandTop;
240 d->dvGuardBandRight = d1.dvGuardBandRight;
241 d->dvGuardBandBottom = d1.dvGuardBandBottom;
242 d->dvExtentsAdjust = d1.dvExtentsAdjust;
243 d->dwStencilCaps = d1.dwStencilCaps;
244 d->dwFVFCaps = d1.dwFVFCaps;
245 d->dwTextureOpCaps = d1.dwTextureOpCaps;
246 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
247 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
248 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
249 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
250 d->deviceGUID = IID_IDirect3DTnLHalDevice;
251 d->wMaxUserClipPlanes = 1;
252 d->wMaxVertexBlendMatrices = 0;
253 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
254 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
261 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
263 D3DDEVICEDESC dref, d1, d2;
266 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
267 Let's put the string in a sufficiently sized array in writable memory. */
268 char device_name[50];
269 strcpy(device_name,"direct3d");
271 fill_opengl_caps(&dref);
274 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
275 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
278 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
279 if (ret_value != D3DENUMRET_OK)
283 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
286 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
287 if (ret_value != D3DENUMRET_OK)
290 return D3DENUMRET_OK;
293 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
295 D3DDEVICEDESC7 ddesc;
297 fill_opengl_caps_7(&ddesc);
299 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
301 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
305 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
307 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
308 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
310 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
311 if (!--(This->ref)) {
313 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
315 /* Release texture associated with the device */
316 for (i = 0; i < MAX_TEXTURES; i++) {
317 if (This->current_texture[i] != NULL)
318 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
319 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
322 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
323 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
324 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
325 surf->aux_ctx = NULL;
326 surf->aux_data = NULL;
327 surf->aux_flip = NULL;
331 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
332 IDirectDrawSurfaceImpl *surf2;
333 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
334 for (; surf2 != NULL; surf2 = surf2->next_attached) {
335 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
336 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
337 /* Override the Lock / Unlock function for all these surfaces */
338 surf2->lock_update = surf2->lock_update_prev;
339 surf2->unlock_update = surf2->unlock_update_prev;
340 /* And install also the blt / bltfast overrides */
341 surf2->aux_blt = NULL;
342 surf2->aux_bltfast = NULL;
344 surf2->d3ddevice = NULL;
348 /* And warn the D3D object that this device is no longer active... */
349 This->d3d->d3d_removed_device(This->d3d, This);
351 HeapFree(GetProcessHeap(), 0, This->world_mat);
352 HeapFree(GetProcessHeap(), 0, This->view_mat);
353 HeapFree(GetProcessHeap(), 0, This->proj_mat);
355 if (glThis->surface_ptr)
356 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
358 DeleteCriticalSection(&(This->crit));
361 if (glThis->unlock_tex)
362 glDeleteTextures(1, &(glThis->unlock_tex));
363 glXDestroyContext(glThis->display, glThis->gl_context);
365 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
367 HeapFree(GetProcessHeap(), 0, This);
374 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
375 LPD3DDEVICEDESC lpD3DHWDevDesc,
376 LPD3DDEVICEDESC lpD3DHELDevDesc)
378 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
382 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
384 fill_opengl_caps(&desc);
385 dwSize = lpD3DHWDevDesc->dwSize;
386 memset(lpD3DHWDevDesc, 0, dwSize);
387 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
389 dwSize = lpD3DHELDevDesc->dwSize;
390 memset(lpD3DHELDevDesc, 0, dwSize);
391 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
393 TRACE(" returning caps : (no dump function yet)\n");
398 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
399 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
403 LPDDPIXELFORMAT pformat;
405 /* Do the texture enumeration */
406 sdesc.dwSize = sizeof(DDSURFACEDESC);
407 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
408 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
409 pformat = &(sdesc.ddpfPixelFormat);
410 pformat->dwSize = sizeof(DDPIXELFORMAT);
411 pformat->dwFourCC = 0;
413 TRACE("Enumerating GL_RGBA unpacked (32)\n");
414 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
415 pformat->u1.dwRGBBitCount = 32;
416 pformat->u2.dwRBitMask = 0x00FF0000;
417 pformat->u3.dwGBitMask = 0x0000FF00;
418 pformat->u4.dwBBitMask = 0x000000FF;
419 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
420 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
421 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
423 TRACE("Enumerating GL_RGB unpacked (32)\n");
424 pformat->dwFlags = DDPF_RGB;
425 pformat->u1.dwRGBBitCount = 32;
426 pformat->u2.dwRBitMask = 0x00FF0000;
427 pformat->u3.dwGBitMask = 0x0000FF00;
428 pformat->u4.dwBBitMask = 0x000000FF;
429 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
430 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
431 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
433 TRACE("Enumerating GL_RGB unpacked (24)\n");
434 pformat->dwFlags = DDPF_RGB;
435 pformat->u1.dwRGBBitCount = 24;
436 pformat->u2.dwRBitMask = 0x00FF0000;
437 pformat->u3.dwGBitMask = 0x0000FF00;
438 pformat->u4.dwBBitMask = 0x000000FF;
439 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
440 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
441 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
443 /* Note : even if this is an 'emulated' texture format, it needs to be first
444 as some dumb applications seem to rely on that. */
445 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
446 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
447 pformat->u1.dwRGBBitCount = 16;
448 pformat->u2.dwRBitMask = 0x00007C00;
449 pformat->u3.dwGBitMask = 0x000003E0;
450 pformat->u4.dwBBitMask = 0x0000001F;
451 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
452 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
453 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
455 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
456 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
457 pformat->u1.dwRGBBitCount = 16;
458 pformat->u2.dwRBitMask = 0x00000F00;
459 pformat->u3.dwGBitMask = 0x000000F0;
460 pformat->u4.dwBBitMask = 0x0000000F;
461 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
462 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
463 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
465 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
466 pformat->dwFlags = DDPF_RGB;
467 pformat->u1.dwRGBBitCount = 16;
468 pformat->u2.dwRBitMask = 0x0000F800;
469 pformat->u3.dwGBitMask = 0x000007E0;
470 pformat->u4.dwBBitMask = 0x0000001F;
471 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
472 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
473 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
475 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
476 pformat->dwFlags = DDPF_RGB;
477 pformat->u1.dwRGBBitCount = 16;
478 pformat->u2.dwRBitMask = 0x00007C00;
479 pformat->u3.dwGBitMask = 0x000003E0;
480 pformat->u4.dwBBitMask = 0x0000001F;
481 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
482 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
483 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
486 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
487 find enumerated, others the last one. And both want to have the ARGB one.
489 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
491 /* See argument about the RGBA format for 'packed' texture formats */
492 TRACE("Enumerating GL_RGBA unpacked (32)\n");
493 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
494 pformat->u1.dwRGBBitCount = 32;
495 pformat->u2.dwRBitMask = 0xFF000000;
496 pformat->u3.dwGBitMask = 0x00FF0000;
497 pformat->u4.dwBBitMask = 0x0000FF00;
498 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
499 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
500 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
502 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
503 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
504 pformat->u1.dwRGBBitCount = 16;
505 pformat->u2.dwRBitMask = 0x0000F000;
506 pformat->u3.dwGBitMask = 0x00000F00;
507 pformat->u4.dwBBitMask = 0x000000F0;
508 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
509 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
510 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
512 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
513 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
514 pformat->u1.dwRGBBitCount = 16;
515 pformat->u2.dwRBitMask = 0x0000F800;
516 pformat->u3.dwGBitMask = 0x000007C0;
517 pformat->u4.dwBBitMask = 0x0000003E;
518 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
519 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
520 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
523 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
524 pformat->dwFlags = DDPF_RGB;
525 pformat->u1.dwRGBBitCount = 8;
526 pformat->u2.dwRBitMask = 0x000000E0;
527 pformat->u3.dwGBitMask = 0x0000001C;
528 pformat->u4.dwBBitMask = 0x00000003;
529 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
530 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
531 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
533 TRACE("Enumerating Paletted (8)\n");
534 pformat->dwFlags = DDPF_PALETTEINDEXED8;
535 pformat->u1.dwRGBBitCount = 8;
536 pformat->u2.dwRBitMask = 0x00000000;
537 pformat->u3.dwGBitMask = 0x00000000;
538 pformat->u4.dwBBitMask = 0x00000000;
539 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
540 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
541 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
543 TRACE("End of enumeration\n");
549 d3ddevice_find(IDirectDrawImpl *d3d,
550 LPD3DFINDDEVICESEARCH lpD3DDFS,
551 LPD3DFINDDEVICERESULT lplpD3DDevice)
555 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
556 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
557 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
558 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
560 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
561 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
562 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
563 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
564 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
565 TRACE(" no match for this GUID.\n");
566 return DDERR_INVALIDPARAMS;
570 /* Now return our own GUID */
571 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
572 fill_opengl_caps(&desc);
573 lplpD3DDevice->ddHwDesc = desc;
574 lplpD3DDevice->ddSwDesc = desc;
576 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
582 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
583 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
586 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
587 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
588 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
592 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
593 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
596 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
597 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
598 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
602 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
603 D3DRENDERSTATETYPE dwRenderStateType,
606 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
607 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
609 /* Call the render state functions */
610 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
611 set_render_state(This, dwRenderStateType, &This->state_block);
617 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
618 D3DRENDERSTATETYPE dwRenderStateType,
619 LPDWORD lpdwRenderState)
621 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
622 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
624 /* Call the render state functions */
625 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
627 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
633 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
634 D3DLIGHTSTATETYPE dwLightStateType,
637 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
639 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
641 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
642 TRACE("Unexpected Light State Type\n");
643 return DDERR_INVALIDPARAMS;
645 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
646 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
651 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
653 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
654 switch (dwLightState) {
656 ERR("DDCOLOR_MONO should not happen!\n");
659 /* We are already in this mode */
662 ERR("Unknown color model!\n");
666 D3DRENDERSTATETYPE rs;
667 switch (dwLightStateType) {
669 case D3DLIGHTSTATE_AMBIENT: /* 2 */
670 rs = D3DRENDERSTATE_AMBIENT;
672 case D3DLIGHTSTATE_FOGMODE: /* 4 */
673 rs = D3DRENDERSTATE_FOGVERTEXMODE;
675 case D3DLIGHTSTATE_FOGSTART: /* 5 */
676 rs = D3DRENDERSTATE_FOGSTART;
678 case D3DLIGHTSTATE_FOGEND: /* 6 */
679 rs = D3DRENDERSTATE_FOGEND;
681 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
682 rs = D3DRENDERSTATE_FOGDENSITY;
684 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
685 rs = D3DRENDERSTATE_COLORVERTEX;
691 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
698 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
701 case D3DPT_POINTLIST:
702 TRACE("Start POINTS\n");
707 TRACE("Start LINES\n");
711 case D3DPT_LINESTRIP:
712 TRACE("Start LINE_STRIP\n");
713 glBegin(GL_LINE_STRIP);
716 case D3DPT_TRIANGLELIST:
717 TRACE("Start TRIANGLES\n");
718 glBegin(GL_TRIANGLES);
721 case D3DPT_TRIANGLESTRIP:
722 TRACE("Start TRIANGLE_STRIP\n");
723 glBegin(GL_TRIANGLE_STRIP);
726 case D3DPT_TRIANGLEFAN:
727 TRACE("Start TRIANGLE_FAN\n");
728 glBegin(GL_TRIANGLE_FAN);
732 FIXME("Unhandled primitive %08x\n", d3dpt);
737 /* This function calculate the Z coordinate from Zproj */
738 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
741 /* Assume that X = Y = 0 and W = 1 */
742 a = This->proj_mat->_33;
743 b = This->proj_mat->_34;
744 c = This->proj_mat->_43;
745 d = This->proj_mat->_44;
746 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
747 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
748 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
750 return (d*Zproj - c) / (a - b*Zproj);
753 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
756 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
758 for (i = 0; i < 3; i++) {
759 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
761 for (elt = 0; elt < 0x10000; elt++) {
762 /* We apply the fog transformation and cache the result */
763 DWORD fog_intensity = elt & 0xFF;
764 DWORD vertex_color = (elt >> 8) & 0xFF;
765 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
770 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
771 BOOLEAN vertex_transformed,
772 BOOLEAN vertex_lit) {
773 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
775 /* Puts GL in the correct lighting / transformation mode */
776 if ((vertex_transformed == FALSE) &&
777 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
778 /* Need to put the correct transformation again if we go from Transformed
779 vertices to non-transformed ones.
781 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
782 This->world_mat, This->view_mat, This->proj_mat);
783 glThis->transform_state = GL_TRANSFORM_NORMAL;
785 } else if ((vertex_transformed == TRUE) &&
786 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
787 /* Set our orthographic projection */
788 glThis->transform_state = GL_TRANSFORM_ORTHO;
789 d3ddevice_set_ortho(This);
792 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
793 if no fogging state change occured */
794 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
795 if (vertex_transformed == TRUE) {
797 /* Now check if our fog_table still corresponds to the current vertex color.
798 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
799 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
800 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
801 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
802 /* We need to rebuild our fog table.... */
803 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
806 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
807 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
808 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
809 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
810 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
812 if (vertex_lit == FALSE) {
813 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
814 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
816 /* Special case of 'pixel fog' */
817 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
818 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
829 /* Handle the 'no-normal' case */
830 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
831 glEnable(GL_LIGHTING);
833 glDisable(GL_LIGHTING);
835 /* Handle the code for pre-vertex material properties */
836 if (vertex_transformed == FALSE) {
837 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
838 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
839 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
840 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
841 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
842 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
843 glEnable(GL_COLOR_MATERIAL);
850 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
851 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
853 D3DDRAWPRIMITIVESTRIDEDDATA strided;
857 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
858 strided.position.dwStride = sizeof(D3DVERTEX);
859 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
860 strided.normal.dwStride = sizeof(D3DVERTEX);
861 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
862 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
863 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
866 case D3DVT_LVERTEX: {
867 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
868 strided.position.dwStride = sizeof(D3DLVERTEX);
869 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
870 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
871 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
872 strided.specular.dwStride = sizeof(D3DLVERTEX);
873 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
874 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
875 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
878 case D3DVT_TLVERTEX: {
879 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
880 strided.position.dwStride = sizeof(D3DTLVERTEX);
881 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
882 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
883 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
884 strided.specular.dwStride = sizeof(D3DTLVERTEX);
885 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
886 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
887 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
891 FIXME("Unhandled vertex type %08x\n", d3dvt);
897 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
898 D3DPRIMITIVETYPE d3dptPrimitiveType,
899 D3DVERTEXTYPE d3dvtVertexType,
904 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
906 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
907 if (TRACE_ON(ddraw)) {
908 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
911 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
917 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
918 D3DPRIMITIVETYPE d3dptPrimitiveType,
919 D3DVERTEXTYPE d3dvtVertexType,
926 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
927 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
928 if (TRACE_ON(ddraw)) {
929 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
932 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
938 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
939 LPD3DEXECUTEBUFFERDESC lpDesc,
940 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
943 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
944 IDirect3DExecuteBufferImpl *ret;
947 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
949 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
950 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
952 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
957 /* These are the various handler used in the generic path */
958 inline static void handle_xyz(D3DVALUE *coords) {
961 inline static void handle_xyzrhw(D3DVALUE *coords) {
962 if (coords[3] < 1e-8)
965 GLfloat w = 1.0 / coords[3];
967 glVertex4f(coords[0] * w,
973 inline static void handle_normal(D3DVALUE *coords) {
977 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
978 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
979 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
980 glColor4ub((*color >> 16) & 0xFF,
981 (*color >> 8) & 0xFF,
982 (*color >> 0) & 0xFF,
983 (*color >> 24) & 0xFF);
985 glColor3ub((*color >> 16) & 0xFF,
986 (*color >> 8) & 0xFF,
987 (*color >> 0) & 0xFF);
991 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
992 glColor4ub((*color >> 16) & 0xFF,
993 (*color >> 8) & 0xFF,
994 (*color >> 0) & 0xFF,
995 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
998 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
999 if ((lighted == FALSE) &&
1000 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1001 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1002 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1003 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1004 handle_diffuse_base(sb, color);
1006 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1007 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1008 handle_diffuse_base(sb, color);
1010 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1011 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1012 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1013 handle_diffuse_base(sb, color);
1015 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1016 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1017 handle_diffuse_base(sb, color);
1020 handle_diffuse_base(sb, color);
1024 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1025 if ((lighted == FALSE) &&
1026 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1027 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1028 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1029 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1030 handle_specular_base(sb, color);
1032 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1033 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1034 handle_specular_base(sb, color);
1036 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1037 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1038 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1039 handle_specular_base(sb, color);
1041 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1042 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1043 handle_specular_base(sb, color);
1046 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1049 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1050 if (lighted == TRUE) {
1051 DWORD color = *color_d;
1052 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1053 /* Special case where the specular value is used to do fogging */
1054 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1055 color &= 0xFF000000; /* Only keep the alpha component */
1056 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1057 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1058 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1060 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1061 /* Standard specular value in transformed mode. TODO */
1063 handle_diffuse_base(sb, &color);
1065 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1066 handle_diffuse(sb, color_d, FALSE);
1067 handle_specular(sb, color_s, FALSE);
1069 /* In that case, only put the diffuse color... */
1070 handle_diffuse_base(sb, color_d);
1075 inline static void handle_texture(D3DVALUE *coords) {
1076 glTexCoord2fv(coords);
1078 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1079 /* For the moment, draw only the first texture.. */
1080 if (tex_index == 0) glTexCoord2fv(coords);
1083 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1084 D3DPRIMITIVETYPE d3dptPrimitiveType,
1085 DWORD d3dvtVertexType,
1086 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1087 DWORD dwVertexCount,
1092 BOOLEAN vertex_lighted = FALSE;
1093 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1094 int num_active_stages = 0;
1096 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1097 if (TRACE_ON(ddraw)) {
1098 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1101 /* This is to prevent 'thread contention' between a thread locking the device and another
1102 doing 3D display on it... */
1103 EnterCriticalSection(&(This->crit));
1106 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1107 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1110 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1112 /* Just a hack for now.. Will have to find better algorithm :-/ */
1113 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1114 vertex_lighted = TRUE;
1116 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1119 /* Compute the number of active texture stages and set the various texture parameters */
1120 num_active_stages = draw_primitive_handle_textures(This);
1122 draw_primitive_handle_GL_state(This,
1123 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1125 draw_primitive_start_GL(d3dptPrimitiveType);
1127 /* Some fast paths first before the generic case.... */
1128 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1131 for (index = 0; index < dwIndexCount; index++) {
1132 int i = (dwIndices == NULL) ? index : dwIndices[index];
1134 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1135 D3DVALUE *tex_coord =
1136 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1137 D3DVALUE *position =
1138 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1140 handle_normal(normal);
1141 handle_texture(tex_coord);
1142 handle_xyz(position);
1144 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1145 position[0], position[1], position[2],
1146 normal[0], normal[1], normal[2],
1147 tex_coord[0], tex_coord[1]);
1149 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1152 for (index = 0; index < dwIndexCount; index++) {
1153 int i = (dwIndices == NULL) ? index : dwIndices[index];
1155 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1157 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1158 D3DVALUE *tex_coord =
1159 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1160 D3DVALUE *position =
1161 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1163 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1164 handle_texture(tex_coord);
1165 handle_xyzrhw(position);
1167 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1168 position[0], position[1], position[2], position[3],
1169 (*color_d >> 16) & 0xFF,
1170 (*color_d >> 8) & 0xFF,
1171 (*color_d >> 0) & 0xFF,
1172 (*color_d >> 24) & 0xFF,
1173 (*color_s >> 16) & 0xFF,
1174 (*color_s >> 8) & 0xFF,
1175 (*color_s >> 0) & 0xFF,
1176 (*color_s >> 24) & 0xFF,
1177 tex_coord[0], tex_coord[1]);
1179 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1180 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1181 /* This is the 'slow path' but that should support all possible vertex formats out there...
1182 Note that people should write a fast path for all vertex formats out there...
1185 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1186 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1188 for (index = 0; index < dwIndexCount; index++) {
1189 int i = (dwIndices == NULL) ? index : dwIndices[index];
1192 if (d3dvtVertexType & D3DFVF_NORMAL) {
1194 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1195 handle_normal(normal);
1197 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1199 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1201 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1202 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1204 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1206 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1207 handle_specular(&(This->state_block), color_s, vertex_lighted);
1208 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1210 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1211 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1215 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1216 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF0000;
1217 if (tex_index >= num_tex_index) {
1218 handle_textures((D3DVALUE *) no_index, tex_stage);
1220 D3DVALUE *tex_coord =
1221 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1222 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1223 handle_textures(tex_coord, tex_stage);
1227 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1228 D3DVALUE *position =
1229 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1230 handle_xyz(position);
1231 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1232 D3DVALUE *position =
1233 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1234 handle_xyzrhw(position);
1237 if (TRACE_ON(ddraw_geom)) {
1240 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1241 D3DVALUE *position =
1242 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1243 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1244 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1245 D3DVALUE *position =
1246 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1247 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1249 if (d3dvtVertexType & D3DFVF_NORMAL) {
1251 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1252 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1254 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1256 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1257 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1258 (*color_d >> 16) & 0xFF,
1259 (*color_d >> 8) & 0xFF,
1260 (*color_d >> 0) & 0xFF,
1261 (*color_d >> 24) & 0xFF);
1263 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1265 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1266 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1267 (*color_s >> 16) & 0xFF,
1268 (*color_s >> 8) & 0xFF,
1269 (*color_s >> 0) & 0xFF,
1270 (*color_s >> 24) & 0xFF);
1272 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1273 D3DVALUE *tex_coord =
1274 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1275 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1276 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1278 TRACE_(ddraw_geom)("\n");
1282 ERR(" matrix weighting not handled yet....\n");
1287 /* Whatever the case, disable the color material stuff */
1288 glDisable(GL_COLOR_MATERIAL);
1293 LeaveCriticalSection(&(This->crit));
1297 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1298 D3DPRIMITIVETYPE d3dptPrimitiveType,
1299 DWORD d3dvtVertexType,
1301 DWORD dwVertexCount,
1304 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1305 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1307 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1308 if (TRACE_ON(ddraw)) {
1309 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1312 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1313 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1319 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1320 D3DPRIMITIVETYPE d3dptPrimitiveType,
1321 DWORD d3dvtVertexType,
1323 DWORD dwVertexCount,
1328 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1329 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1331 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1332 if (TRACE_ON(ddraw)) {
1333 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1336 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1337 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1343 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1344 D3DPRIMITIVETYPE d3dptPrimitiveType,
1346 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1347 DWORD dwVertexCount,
1350 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1352 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1353 if (TRACE_ON(ddraw)) {
1354 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1356 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1362 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1363 D3DPRIMITIVETYPE d3dptPrimitiveType,
1365 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1366 DWORD dwVertexCount,
1371 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1373 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1374 if (TRACE_ON(ddraw)) {
1375 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1378 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1384 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1385 D3DPRIMITIVETYPE d3dptPrimitiveType,
1386 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1387 DWORD dwStartVertex,
1388 DWORD dwNumVertices,
1391 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1392 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1393 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1395 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1396 if (TRACE_ON(ddraw)) {
1397 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1400 if (vb_impl->processed == TRUE) {
1401 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1402 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1404 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1405 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1406 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1408 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1409 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1412 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1413 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1420 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1421 D3DPRIMITIVETYPE d3dptPrimitiveType,
1422 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1423 DWORD dwStartVertex,
1424 DWORD dwNumVertices,
1429 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1430 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1431 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1433 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1434 if (TRACE_ON(ddraw)) {
1435 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1438 if (vb_impl->processed == TRUE) {
1439 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1440 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1442 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1443 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1444 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1446 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1447 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1450 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1451 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1457 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1459 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1461 BOOLEAN is_complement = FALSE;
1462 BOOLEAN is_alpha_replicate = FALSE;
1463 BOOLEAN handled = TRUE;
1465 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1469 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1470 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1475 if (tex_op == D3DTOP_SELECTARG2) {
1479 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1480 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1485 if (tex_op == D3DTOP_SELECTARG2) {
1490 if (dwState & D3DTA_COMPLEMENT) {
1491 is_complement = TRUE;
1493 if (dwState & D3DTA_ALPHAREPLICATE) {
1494 is_alpha_replicate = TRUE;
1496 dwState &= D3DTA_SELECTMASK;
1497 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1498 dwState = D3DTA_DIFFUSE;
1502 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1503 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1504 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1505 case D3DTA_TFACTOR: {
1506 /* Get the constant value from the current rendering state */
1508 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1510 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1511 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1512 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1513 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1514 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1516 src = GL_CONSTANT_EXT;
1518 default: src = GL_TEXTURE; handled = FALSE; break;
1522 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1523 if (is_alpha_replicate) {
1524 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1526 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1529 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1530 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1537 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1539 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1542 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1546 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1548 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1550 switch (d3dTexStageStateType) {
1551 #define GEN_CASE(a) case a: type = #a; break
1552 GEN_CASE(D3DTSS_COLOROP);
1553 GEN_CASE(D3DTSS_COLORARG1);
1554 GEN_CASE(D3DTSS_COLORARG2);
1555 GEN_CASE(D3DTSS_ALPHAOP);
1556 GEN_CASE(D3DTSS_ALPHAARG1);
1557 GEN_CASE(D3DTSS_ALPHAARG2);
1558 GEN_CASE(D3DTSS_BUMPENVMAT00);
1559 GEN_CASE(D3DTSS_BUMPENVMAT01);
1560 GEN_CASE(D3DTSS_BUMPENVMAT10);
1561 GEN_CASE(D3DTSS_BUMPENVMAT11);
1562 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1563 GEN_CASE(D3DTSS_ADDRESS);
1564 GEN_CASE(D3DTSS_ADDRESSU);
1565 GEN_CASE(D3DTSS_ADDRESSV);
1566 GEN_CASE(D3DTSS_BORDERCOLOR);
1567 GEN_CASE(D3DTSS_MAGFILTER);
1568 GEN_CASE(D3DTSS_MINFILTER);
1569 GEN_CASE(D3DTSS_MIPFILTER);
1570 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1571 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1572 GEN_CASE(D3DTSS_MAXANISOTROPY);
1573 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1574 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1575 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1577 default: type = "UNKNOWN";
1580 /* Store the values in the state array */
1581 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1582 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1583 /* Some special cases when one state modifies more than one... */
1584 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1585 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1586 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1591 switch (d3dTexStageStateType) {
1592 case D3DTSS_MINFILTER:
1593 case D3DTSS_MIPFILTER:
1594 if (TRACE_ON(ddraw)) {
1595 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1596 switch ((D3DTEXTUREMINFILTER) dwState) {
1597 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1598 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1599 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1602 switch ((D3DTEXTUREMIPFILTER) dwState) {
1603 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1604 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1605 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1606 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1612 case D3DTSS_MAGFILTER:
1613 if (TRACE_ON(ddraw)) {
1614 switch ((D3DTEXTUREMAGFILTER) dwState) {
1615 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1616 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1617 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1622 case D3DTSS_ADDRESS:
1623 case D3DTSS_ADDRESSU:
1624 case D3DTSS_ADDRESSV: {
1625 switch ((D3DTEXTUREADDRESS) dwState) {
1626 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1627 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1628 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1629 #if defined(GL_VERSION_1_4)
1630 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1631 #elif defined(GL_ARB_texture_mirrored_repeat)
1632 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1634 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1638 case D3DTSS_ALPHAOP:
1639 case D3DTSS_COLOROP: {
1641 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1646 #define GEN_CASE(a) case a: value = #a; break
1647 GEN_CASE(D3DTOP_DISABLE);
1648 GEN_CASE(D3DTOP_SELECTARG1);
1649 GEN_CASE(D3DTOP_SELECTARG2);
1650 GEN_CASE(D3DTOP_MODULATE);
1651 GEN_CASE(D3DTOP_MODULATE2X);
1652 GEN_CASE(D3DTOP_MODULATE4X);
1653 GEN_CASE(D3DTOP_ADD);
1654 GEN_CASE(D3DTOP_ADDSIGNED);
1655 GEN_CASE(D3DTOP_ADDSIGNED2X);
1656 GEN_CASE(D3DTOP_SUBTRACT);
1657 GEN_CASE(D3DTOP_ADDSMOOTH);
1658 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1659 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1660 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1661 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1662 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1663 GEN_CASE(D3DTOP_PREMODULATE);
1664 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1665 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1666 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1667 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1668 GEN_CASE(D3DTOP_BUMPENVMAP);
1669 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1670 GEN_CASE(D3DTOP_DOTPRODUCT3);
1671 GEN_CASE(D3DTOP_FORCE_DWORD);
1673 default: value = "UNKNOWN";
1676 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1677 glDisable(GL_TEXTURE_2D);
1678 TRACE(" disabling 2D texturing.\n");
1680 /* Re-enable texturing */
1681 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1682 glEnable(GL_TEXTURE_2D);
1683 TRACE(" enabling 2D texturing.\n");
1686 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1687 if (dwState != D3DTOP_DISABLE) {
1688 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1691 /* Now set up the operand correctly */
1693 case D3DTOP_DISABLE:
1694 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1695 and it works, so ignore this op */
1696 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1699 case D3DTOP_SELECTARG1:
1700 case D3DTOP_SELECTARG2:
1701 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1704 case D3DTOP_MODULATE4X:
1705 scale = scale * 2; /* Drop through */
1706 case D3DTOP_MODULATE2X:
1707 scale = scale * 2; /* Drop through */
1708 case D3DTOP_MODULATE:
1709 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1713 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1716 case D3DTOP_ADDSIGNED2X:
1717 scale = scale * 2; /* Drop through */
1718 case D3DTOP_ADDSIGNED:
1719 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1722 /* For the four blending modes, use the Arg2 parameter */
1723 case D3DTOP_BLENDDIFFUSEALPHA:
1724 case D3DTOP_BLENDTEXTUREALPHA:
1725 case D3DTOP_BLENDFACTORALPHA:
1726 case D3DTOP_BLENDCURRENTALPHA: {
1727 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1730 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1731 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1732 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1733 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1736 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1737 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1738 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1739 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1740 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1749 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1750 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1751 /* Switch the arguments if needed... */
1752 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1753 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1754 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1756 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1757 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1760 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1761 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1763 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1764 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1770 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1771 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1773 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1775 TRACE(" Stage type is : %s => %s\n", type, value);
1777 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1781 case D3DTSS_COLORARG1:
1782 case D3DTSS_COLORARG2:
1783 case D3DTSS_ALPHAARG1:
1784 case D3DTSS_ALPHAARG2: {
1785 const char *value, *value_comp = "", *value_alpha = "";
1787 D3DTEXTUREOP tex_op;
1789 switch (dwState & D3DTA_SELECTMASK) {
1790 #define GEN_CASE(a) case a: value = #a; break
1791 GEN_CASE(D3DTA_DIFFUSE);
1792 GEN_CASE(D3DTA_CURRENT);
1793 GEN_CASE(D3DTA_TEXTURE);
1794 GEN_CASE(D3DTA_TFACTOR);
1795 GEN_CASE(D3DTA_SPECULAR);
1797 default: value = "UNKNOWN";
1799 if (dwState & D3DTA_COMPLEMENT) {
1800 value_comp = " | D3DTA_COMPLEMENT";
1802 if (dwState & D3DTA_ALPHAREPLICATE) {
1803 value_alpha = " | D3DTA_ALPHAREPLICATE";
1806 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1807 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1809 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1812 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1815 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1817 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1821 case D3DTSS_MIPMAPLODBIAS: {
1822 D3DVALUE value = *((D3DVALUE *) &dwState);
1823 BOOLEAN handled = TRUE;
1829 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1831 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1835 case D3DTSS_MAXMIPLEVEL:
1836 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1839 case D3DTSS_BORDERCOLOR:
1840 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1841 ((dwState >> 16) & 0xFF),
1842 ((dwState >> 8) & 0xFF),
1843 ((dwState >> 0) & 0xFF),
1844 ((dwState >> 24) & 0xFF));
1847 case D3DTSS_TEXCOORDINDEX: {
1848 BOOLEAN handled = TRUE;
1851 switch (dwState & 0xFFFF0000) {
1852 #define GEN_CASE(a) case a: value = #a; break
1853 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1854 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1855 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1856 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1858 default: value = "UNKNOWN";
1860 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1864 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1866 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1870 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1871 const char *projected = "", *value;
1872 BOOLEAN handled = TRUE;
1873 switch (dwState & 0xFF) {
1874 #define GEN_CASE(a) case a: value = #a; break
1875 GEN_CASE(D3DTTFF_DISABLE);
1876 GEN_CASE(D3DTTFF_COUNT1);
1877 GEN_CASE(D3DTTFF_COUNT2);
1878 GEN_CASE(D3DTTFF_COUNT3);
1879 GEN_CASE(D3DTTFF_COUNT4);
1881 default: value = "UNKNOWN";
1883 if (dwState & D3DTTFF_PROJECTED) {
1884 projected = " | D3DTTFF_PROJECTED";
1888 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1889 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1892 if (handled == TRUE) {
1893 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1895 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1900 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1910 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
1912 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1915 for (stage = 0; stage < MAX_TEXTURES; stage++) {
1916 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
1918 /* First check if we need to bind any other texture for this stage */
1919 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
1920 if (This->current_texture[stage] == NULL) {
1921 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
1922 glBindTexture(GL_TEXTURE_2D, 0);
1923 glDisable(GL_TEXTURE_2D);
1925 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
1927 if (glThis->current_bound_texture[stage] == NULL) {
1928 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
1929 TRACE(" enabling 2D texturing and");
1930 glEnable(GL_TEXTURE_2D);
1933 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
1934 glBindTexture(GL_TEXTURE_2D, tex_name);
1937 glThis->current_bound_texture[stage] = This->current_texture[stage];
1939 if (glThis->current_bound_texture[stage] == NULL) {
1940 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
1942 TRACE(" using already bound texture id %d for stage %ld.\n",
1943 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
1947 /* If no texure valid for this stage, go out of the loop */
1948 if (This->current_texture[stage] == NULL) break;
1950 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
1951 This will also update the various texture parameters if needed.
1953 gltex_upload_texture(surf_ptr, This, stage);
1960 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1962 LPDIRECTDRAWSURFACE7 lpTexture2)
1964 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1966 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1968 if (dwStage > 0) return DD_OK;
1970 if (This->current_texture[dwStage] != NULL) {
1971 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1974 if (lpTexture2 == NULL) {
1975 This->current_texture[dwStage] = NULL;
1977 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1978 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
1979 This->current_texture[dwStage] = tex_impl;
1986 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1987 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1989 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1990 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1992 fill_opengl_caps_7(lpD3DHELDevDesc);
1994 TRACE(" returning caps : no dump function yet.\n");
2000 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2001 LPD3DMATERIAL7 lpMat)
2003 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2004 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2006 if (TRACE_ON(ddraw)) {
2007 TRACE(" material is : \n");
2008 dump_D3DMATERIAL7(lpMat);
2011 This->current_material = *lpMat;
2014 glMaterialfv(GL_FRONT_AND_BACK,
2016 (float *) &(This->current_material.u.diffuse));
2017 glMaterialfv(GL_FRONT_AND_BACK,
2019 (float *) &(This->current_material.u1.ambient));
2020 glMaterialfv(GL_FRONT_AND_BACK,
2022 (float *) &(This->current_material.u2.specular));
2023 glMaterialfv(GL_FRONT_AND_BACK,
2025 (float *) &(This->current_material.u3.emissive));
2026 glMaterialf(GL_FRONT_AND_BACK,
2028 This->current_material.u4.power); /* Not sure about this... */
2036 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2038 LPD3DLIGHT7 lpLight)
2040 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2041 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2042 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2044 if (TRACE_ON(ddraw)) {
2045 TRACE(" setting light : \n");
2046 dump_D3DLIGHT7(lpLight);
2049 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2050 This->set_lights |= 0x00000001 << dwLightIndex;
2051 This->light_parameters[dwLightIndex] = *lpLight;
2053 /* Some checks to print out nice warnings :-) */
2054 switch (lpLight->dltType) {
2055 case D3DLIGHT_DIRECTIONAL:
2056 case D3DLIGHT_POINT:
2057 /* These are handled properly... */
2061 if ((lpLight->dvTheta != 0.0) ||
2062 (lpLight->dvTheta != lpLight->dvPhi)) {
2063 ERR("dvTheta not fully supported yet !\n");
2068 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2071 /* This will force the Light setting on next drawing of primitives */
2072 glThis->transform_state = GL_TRANSFORM_NONE;
2078 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2082 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2083 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2085 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2089 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2090 /* Set the default parameters.. */
2091 TRACE(" setting default light parameters...\n");
2092 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2094 glEnable(GL_LIGHT0 + dwLightIndex);
2095 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2096 /* This light gets active... Need to update its parameters to GL before the next drawing */
2097 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2099 This->active_lights |= 0x00000001 << dwLightIndex;
2100 glThis->transform_state = GL_TRANSFORM_NONE;
2103 glDisable(GL_LIGHT0 + dwLightIndex);
2104 This->active_lights &= ~(0x00000001 << dwLightIndex);
2112 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2114 ICOM_THIS(IDirect3DDeviceImpl,iface);
2115 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2117 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2119 if (dwIndex >= This->max_clipping_planes) {
2120 return DDERR_INVALIDPARAMS;
2123 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2125 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2127 /* This is to force the reset of the transformation matrices on the next drawing.
2128 * This is needed to use the correct matrices for the various clipping planes.
2130 glThis->transform_state = GL_TRANSFORM_NONE;
2136 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2137 LPD3DVIEWPORT7 lpData)
2139 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2140 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2142 if (TRACE_ON(ddraw)) {
2143 TRACE(" viewport is : \n");
2144 TRACE(" - dwX = %ld dwY = %ld\n",
2145 lpData->dwX, lpData->dwY);
2146 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2147 lpData->dwWidth, lpData->dwHeight);
2148 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2149 lpData->dvMinZ, lpData->dvMaxZ);
2151 This->active_viewport = *lpData;
2155 /* Set the viewport */
2156 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2157 glViewport(lpData->dwX,
2158 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2159 lpData->dwWidth, lpData->dwHeight);
2166 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2167 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2169 # define XCAST(fun) (void*)
2172 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2174 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2175 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2176 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2177 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2178 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2179 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2180 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2181 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2182 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2183 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2184 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2185 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2186 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2187 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2188 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2189 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2190 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2191 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2192 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2193 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2194 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2195 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2196 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2197 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2198 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2199 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2200 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2201 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2202 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2203 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2204 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2205 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2206 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2207 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2208 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2209 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2210 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2211 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2212 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2213 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2214 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2215 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2216 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2217 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2218 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2219 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2220 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2221 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2222 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2223 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2226 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2231 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2232 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2234 # define XCAST(fun) (void*)
2237 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2239 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2240 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2241 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2242 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2243 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2244 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2245 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2246 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2247 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2248 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2249 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2250 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2251 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2252 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2253 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2254 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2255 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2256 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2257 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2258 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2259 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2260 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2261 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2262 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2263 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2264 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2265 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2266 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2267 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2268 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2269 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2270 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2271 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2272 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2273 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2274 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2275 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2276 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2277 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2278 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2279 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2280 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2281 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2284 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2289 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2290 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2292 # define XCAST(fun) (void*)
2295 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2297 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2298 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2299 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2300 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2301 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2302 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2303 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2304 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2305 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2306 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2307 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2308 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2309 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2310 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2311 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2312 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2313 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2314 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2315 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2316 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2317 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2318 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2319 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2320 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2321 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2322 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2323 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2324 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2325 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2326 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2327 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2328 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2329 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2330 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2333 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2338 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2339 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2341 # define XCAST(fun) (void*)
2344 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2346 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2347 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2348 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2349 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2350 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2351 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2352 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2353 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2354 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2355 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2356 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2357 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2358 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2359 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2360 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2361 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2362 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2363 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2364 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2365 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2366 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2367 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2368 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2371 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2375 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2383 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2385 GLfloat old_z_clear_value;
2386 GLbitfield bitfield = 0;
2387 GLint old_stencil_clear_value;
2388 GLfloat old_color_clear_value[4];
2392 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2393 if (TRACE_ON(ddraw)) {
2396 TRACE(" rectangles : \n");
2397 for (i = 0; i < dwCount; i++) {
2398 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2404 /* Not sure if this is really needed... */
2408 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2409 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2413 /* Clears the screen */
2416 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
2417 /* TODO: optimize here the case where Clear changes all the screen... */
2418 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
2420 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
2422 if (dwFlags & D3DCLEAR_ZBUFFER) {
2423 bitfield |= GL_DEPTH_BUFFER_BIT;
2424 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2425 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2426 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2428 TRACE(" depth value : %f\n", dvZ);
2430 if (dwFlags & D3DCLEAR_STENCIL) {
2431 bitfield |= GL_STENCIL_BUFFER_BIT;
2432 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2433 glClearStencil(dwStencil);
2434 TRACE(" stencil value : %ld\n", dwStencil);
2436 if (dwFlags & D3DCLEAR_TARGET) {
2437 bitfield |= GL_COLOR_BUFFER_BIT;
2438 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2439 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2440 ((dwColor >> 8) & 0xFF) / 255.0,
2441 ((dwColor >> 0) & 0xFF) / 255.0,
2442 ((dwColor >> 24) & 0xFF) / 255.0);
2443 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2446 glEnable(GL_SCISSOR_TEST);
2447 for (i = 0; i < dwCount; i++) {
2448 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2449 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2452 glDisable(GL_SCISSOR_TEST);
2454 if (dwFlags & D3DCLEAR_ZBUFFER) {
2456 glClearDepth(old_z_clear_value);
2458 if (dwFlags & D3DCLEAR_STENCIL) {
2459 bitfield |= GL_STENCIL_BUFFER_BIT;
2460 glClearStencil(old_stencil_clear_value);
2462 if (dwFlags & D3DCLEAR_TARGET) {
2463 bitfield |= GL_COLOR_BUFFER_BIT;
2464 glClearColor(old_color_clear_value[0],
2465 old_color_clear_value[1],
2466 old_color_clear_value[2],
2467 old_color_clear_value[3]);
2476 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2477 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2478 DWORD dwFlags, LPDDBLTFX lpbltfx)
2480 if (dwFlags & DDBLT_COLORFILL) {
2481 /* This is easy to handle for the D3D Device... */
2487 /* First check if we BLT to the backbuffer... */
2488 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2490 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2493 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2494 return DDERR_INVALIDPARAMS;
2497 /* The color as given in the Blt function is in the format of the frame-buffer...
2498 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2500 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2501 if (This->palette) {
2502 color = ((0xFF000000) |
2503 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2504 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2505 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2509 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2510 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2511 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2512 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2513 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2514 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2515 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2516 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2519 color = ((0xFF000000) |
2520 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2521 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2522 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2524 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2525 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2526 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2527 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2528 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2529 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2531 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2532 return DDERR_INVALIDPARAMS;
2535 ERR("Wrong surface type for BLT override !\n");
2536 return DDERR_INVALIDPARAMS;
2539 TRACE(" executing D3D Device override.\n");
2542 rect.u1.x1 = rdst->left;
2543 rect.u2.y1 = rdst->top;
2544 rect.u3.x2 = rdst->right;
2545 rect.u4.y2 = rdst->bottom;
2550 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2552 glDrawBuffer(GL_FRONT);
2554 glDrawBuffer(GL_BACK);
2556 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2558 if ((( is_front) && (prev_draw == GL_BACK)) ||
2559 ((!is_front) && (prev_draw == GL_FRONT)))
2560 glDrawBuffer(prev_draw);
2566 return DDERR_INVALIDPARAMS;
2570 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2571 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2572 LPRECT rsrc, DWORD trans)
2574 return DDERR_INVALIDPARAMS;
2578 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2580 GLfloat height, width;
2581 GLfloat trans_mat[16];
2583 TRACE("(%p)\n", This);
2585 width = This->surface->surface_desc.dwWidth;
2586 height = This->surface->surface_desc.dwHeight;
2588 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2589 to OpenGL screen coordinates (ie the upper left corner is not the same).
2590 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2591 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2592 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2593 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2594 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2595 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2598 glMatrixMode(GL_MODELVIEW);
2600 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2601 Correctness Tips section).
2603 Basically, from what I understood, if the game does not filter the font texture,
2604 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2605 one and we will have strange artifacts (as the rounding and stuff may give different results
2606 for different pixels, ie sometimes take the left pixel, sometimes the right).
2608 glTranslatef(0.375, 0.375, 0);
2609 glMatrixMode(GL_PROJECTION);
2610 glLoadMatrixf(trans_mat);
2615 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2616 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2618 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
2621 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2622 glMatrixMode(GL_MODELVIEW);
2623 glLoadMatrixf((float *) view_mat);
2625 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2626 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2629 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2630 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2633 plane[0] = This->clipping_planes[i].plane[0];
2634 plane[1] = This->clipping_planes[i].plane[1];
2635 plane[2] = This->clipping_planes[i].plane[2];
2636 plane[3] = This->clipping_planes[i].plane[3];
2638 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2642 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2646 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2647 if (runner & This->active_lights) {
2648 switch (This->light_parameters[i].dltType) {
2649 case D3DLIGHT_DIRECTIONAL: {
2651 float cut_off = 180.0;
2653 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2654 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2655 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2656 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2658 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2659 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2660 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2662 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2665 case D3DLIGHT_POINT: {
2667 float cut_off = 180.0;
2669 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2670 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2671 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2672 position[0] = This->light_parameters[i].dvPosition.u1.x;
2673 position[1] = This->light_parameters[i].dvPosition.u2.y;
2674 position[2] = This->light_parameters[i].dvPosition.u3.z;
2676 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2677 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2678 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2679 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2680 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2683 case D3DLIGHT_SPOT: {
2686 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2688 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2689 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2690 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2692 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2693 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2694 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2696 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2697 position[0] = This->light_parameters[i].dvPosition.u1.x;
2698 position[1] = This->light_parameters[i].dvPosition.u2.y;
2699 position[2] = This->light_parameters[i].dvPosition.u3.z;
2701 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2702 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2703 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2704 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2705 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2706 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2710 /* No warning here as it's already done at light setting */
2717 glMultMatrixf((float *) world_mat);
2719 if ((matrices & PROJMAT_CHANGED) != 0) {
2720 glMatrixMode(GL_PROJECTION);
2721 glLoadMatrixf((float *) proj_mat);
2727 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2729 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2730 DWORD tex_mat, tex_stage;
2732 TRACE("(%p,%08lx)\n", This, matrices);
2734 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
2735 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2736 /* This will force an update of the transform state at the next drawing. */
2737 glThis->transform_state = GL_TRANSFORM_NONE;
2740 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2741 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2744 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2745 if (matrices & tex_mat) {
2746 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2747 if (tex_stage == 0) {
2748 /* No multi-texturing support for now ... */
2749 glMatrixMode(GL_TEXTURE);
2750 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2753 glMatrixMode(GL_TEXTURE);
2762 /* TODO for both these functions :
2763 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2764 by other OpenGL code in D3D
2765 - handle the case where no 'Begin / EndScene' was done between two locks
2766 - handle the rectangles in the unlock too
2767 - handle pitch correctly...
2769 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2771 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2772 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2773 WINE_GL_BUFFER_TYPE buffer_type;
2776 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2777 buffer_type = WINE_GL_BUFFER_FRONT;
2778 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
2779 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
2780 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2782 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
2783 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2784 buffer_type = WINE_GL_BUFFER_BACK;
2785 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
2786 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
2787 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2789 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
2791 ERR("Wrong surface type for locking !\n");
2795 if (pRect == NULL) {
2798 loc_rect.bottom = This->surface_desc.dwHeight;
2799 loc_rect.right = This->surface_desc.dwWidth;
2803 /* Try to acquire the device critical section */
2804 EnterCriticalSection(&(d3d_dev->crit));
2806 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
2807 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
2808 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
2810 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
2812 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
2813 /* Check if the new rectangle is in the previous one or not.
2814 If it is not, flush first the previous locks on screen.
2816 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
2817 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
2818 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
2819 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2820 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2821 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
2822 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
2823 pRect->left, pRect->top, pRect->right, pRect->bottom,
2824 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
2825 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
2826 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
2828 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
2829 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
2831 /* In the other case, do not upgrade the locking rectangle as it's no need... */
2833 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
2836 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
2837 /* If the surface is already in memory, no need to do anything here... */
2838 GLenum buffer_format;
2839 GLenum buffer_color;
2843 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
2844 pRect->left, pRect->top, pRect->right, pRect->bottom);
2846 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2847 may only write to the device... But when we will blit it back to the screen, we need
2848 also to blit correctly the parts the application did not overwrite... */
2850 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
2851 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2852 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2853 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2854 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2855 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2856 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2857 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
2858 buffer_color = GL_RGB;
2859 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
2860 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
2861 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
2862 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
2863 buffer_format = GL_UNSIGNED_BYTE;
2864 buffer_color = GL_RGB;
2865 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2866 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2867 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2868 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2869 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
2870 buffer_color = GL_BGRA;
2872 ERR(" unsupported pixel format at device locking.\n");
2876 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
2882 if (buffer_type == WINE_GL_BUFFER_FRONT)
2883 /* Application wants to lock the front buffer */
2884 glReadBuffer(GL_FRONT);
2886 /* Application wants to lock the back buffer */
2887 glReadBuffer(GL_BACK);
2889 dst = ((char *)This->surface_desc.lpSurface) +
2890 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
2891 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
2892 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
2894 glReadPixels(pRect->left, y,
2895 pRect->right - pRect->left, 1,
2896 buffer_color, buffer_format, dst);
2897 dst += This->surface_desc.u1.lPitch;
2900 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
2903 /* I keep this code here as it's very useful to debug :-) */
2905 static int flush_count = 0;
2909 if ((++flush_count % 50) == 0) {
2910 sprintf(buf, "lock_%06d.pnm", flush_count);
2911 f = fopen(buf, "wb");
2912 DDRAW_dump_surface_to_disk(This, f);
2921 #define UNLOCK_TEX_SIZE 256
2923 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2925 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2926 GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog;
2928 BOOLEAN initial = FALSE;
2930 /* Note : no need here to lock the 'device critical section' as we are already protected by
2931 the GL critical section. */
2933 if (pRect == NULL) {
2936 loc_rect.bottom = surf->surface_desc.dwHeight;
2937 loc_rect.right = surf->surface_desc.dwWidth;
2941 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
2943 /* This is a hack to prevent querying the current texture from GL */
2944 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
2946 if (gl_d3d_dev->unlock_tex == 0) {
2947 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2948 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2950 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2951 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2953 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2957 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
2958 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2959 ERR(" unsupported pixel format at frame buffer flush.\n");
2963 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2964 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2965 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2966 glGetIntegerv(GL_CULL_FACE, &cull_face);
2967 glGetIntegerv(GL_LIGHTING, &lighting);
2968 glGetIntegerv(GL_BLEND, &blend);
2969 glGetIntegerv(GL_FOG, &fog);
2970 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2971 glMatrixMode(GL_TEXTURE);
2973 /* TODO: scissor test if ever we use it ! */
2975 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2976 d3ddevice_set_ortho(d3d_dev);
2978 glDisable(GL_DEPTH_TEST);
2979 glEnable(GL_TEXTURE_2D);
2980 glEnable(GL_SCISSOR_TEST);
2981 glDepthRange(0.0, 1.0);
2982 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
2983 glScissor(pRect->left, surf->surface_desc.dwHeight - pRect->bottom,
2984 pRect->right - pRect->left, pRect->bottom - pRect->top);
2985 glDisable(GL_LIGHTING);
2986 glDisable(GL_CULL_FACE);
2987 glDisable(GL_ALPHA_TEST);
2988 glDisable(GL_STENCIL_TEST);
2989 glDisable(GL_BLEND);
2991 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2993 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
2994 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
2995 /* First, upload the texture... */
2998 flush_rect.left = x;
3000 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3001 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3003 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3006 glColor3ub(0xFF, 0xFF, 0xFF);
3007 glTexCoord2f(0.0, 0.0);
3008 glVertex3d(x, y, 0.5);
3009 glTexCoord2f(1.0, 0.0);
3010 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3011 glTexCoord2f(1.0, 1.0);
3012 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3013 glTexCoord2f(0.0, 1.0);
3014 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3019 upload_surface_to_tex_memory_release();
3021 /* And restore all the various states modified by this code */
3022 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
3023 if (lighting != 0) glEnable(GL_LIGHTING);
3024 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
3025 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
3026 if (cull_face != 0) glEnable(GL_CULL_FACE);
3027 if (blend != 0) glEnable(GL_BLEND);
3028 if (fog != 0) glEnable(GL_FOG);
3029 glDisable(GL_SCISSOR_TEST);
3030 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3031 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3032 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3033 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
3034 glViewport(d3d_dev->active_viewport.dwX,
3035 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
3036 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
3037 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3039 /* I keep this code here as it's very useful to debug :-) */
3041 static int flush_count = 0;
3045 if ((++flush_count % 50) == 0) {
3046 sprintf(buf, "flush_%06d.pnm", flush_count);
3047 f = fopen(buf, "wb");
3048 DDRAW_dump_surface_to_disk(surf, f);
3054 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3056 WINE_GL_BUFFER_TYPE buffer_type;
3057 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3058 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3060 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3061 buffer_type = WINE_GL_BUFFER_FRONT;
3062 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3063 buffer_type = WINE_GL_BUFFER_BACK;
3065 ERR("Wrong surface type for locking !\n");
3069 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3070 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3071 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3073 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3075 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3076 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3077 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3080 TRACE(" flushing front buffer immediatly on screen.\n");
3083 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3084 glDrawBuffer(GL_FRONT);
3085 /* Note: we do not use the application provided lock rectangle but our own stored at
3086 lock time. This is because in old D3D versions, the 'lock' parameter did not
3089 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]);
3090 glDrawBuffer(prev_draw);
3093 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3097 /* And 'frees' the device critical section */
3098 LeaveCriticalSection(&(d3d_dev->crit));
3102 apply_texture_state(IDirect3DDeviceImpl *This)
3106 /* Initialize texture stages states */
3107 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3108 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3109 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3110 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3111 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3118 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3120 IDirect3DDeviceImpl *object;
3121 IDirect3DDeviceGLImpl *gl_object;
3122 IDirectDrawSurfaceImpl *surf;
3127 XVisualInfo template;
3128 GLenum buffer = GL_FRONT;
3130 GLint max_clipping_planes = 0;
3132 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3133 if (object == NULL) return DDERR_OUTOFMEMORY;
3135 gl_object = (IDirect3DDeviceGLImpl *) object;
3139 object->surface = surface;
3140 object->set_context = set_context;
3141 object->clear = d3ddevice_clear;
3142 object->set_matrices = d3ddevice_set_matrices;
3143 object->matrices_updated = d3ddevice_matrices_updated;
3144 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3146 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3148 InitializeCriticalSection(&(object->crit));
3150 TRACE(" device critical section : %p\n", &(object->crit));
3152 device_context = GetDC(surface->ddraw_owner->window);
3153 gl_object->display = get_display(device_context);
3154 gl_object->drawable = get_drawable(device_context);
3155 ReleaseDC(surface->ddraw_owner->window,device_context);
3158 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3159 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3161 HeapFree(GetProcessHeap(), 0, object);
3162 ERR("No visual found !\n");
3164 return DDERR_INVALIDPARAMS;
3166 TRACE(" visual found\n");
3169 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3172 if (gl_object->gl_context == NULL) {
3173 HeapFree(GetProcessHeap(), 0, object);
3174 ERR("Error in context creation !\n");
3176 return DDERR_INVALIDPARAMS;
3178 TRACE(" context created (%p)\n", gl_object->gl_context);
3181 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3182 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3183 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3184 surf->aux_ctx = (LPVOID) object;
3185 surf->aux_data = (LPVOID) gl_object->drawable;
3186 surf->aux_flip = opengl_flip;
3191 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3193 TRACE(" no double buffering : drawing on the front buffer\n");
3197 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3198 IDirectDrawSurfaceImpl *surf2;
3199 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3200 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3201 TRACE(" checking surface %p :", surf2);
3202 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3203 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3204 /* Override the Lock / Unlock function for all these surfaces */
3205 surf2->lock_update_prev = surf2->lock_update;
3206 surf2->lock_update = d3ddevice_lock_update;
3207 surf2->unlock_update_prev = surf2->unlock_update;
3208 surf2->unlock_update = d3ddevice_unlock_update;
3209 /* And install also the blt / bltfast overrides */
3210 surf2->aux_blt = d3ddevice_blt;
3211 surf2->aux_bltfast = d3ddevice_bltfast;
3213 TRACE(" overiding direct surface access.\n");
3215 TRACE(" no overide.\n");
3217 surf2->d3ddevice = object;
3221 /* Set the various light parameters */
3222 for (light = 0; light < MAX_LIGHTS; light++) {
3223 /* Only set the fields that are not zero-created */
3224 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3225 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3226 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3227 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3228 object->light_parameters[light].dvDirection.u3.z = 1.0;
3231 /* Allocate memory for the matrices */
3232 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3233 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3234 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3235 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3236 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3237 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3238 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3239 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3240 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3243 /* Initialisation */
3244 TRACE(" setting current context\n");
3245 object->set_context(object);
3246 TRACE(" current context set\n");
3248 /* allocate the clipping planes */
3249 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3250 if (max_clipping_planes>32) {
3251 object->max_clipping_planes=32;
3253 object->max_clipping_planes = max_clipping_planes;
3255 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3256 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3258 glHint(GL_FOG_HINT,GL_NICEST);
3260 glClearColor(0.0, 0.0, 0.0, 0.0);
3261 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3262 glDrawBuffer(buffer);
3263 glReadBuffer(buffer);
3264 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3267 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3268 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3270 /* fill_device_capabilities(d3d->ddraw); */
3272 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3273 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3274 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3275 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3279 TRACE(" creating implementation at %p.\n", *obj);
3281 /* And finally warn D3D that this device is now present */
3282 object->d3d->d3d_added_device(object->d3d, object);
3284 /* FIXME: Should handle other versions than just 7 */
3285 InitDefaultStateBlock(&object->state_block, 7);
3286 /* Apply default render state and texture stage state values */
3287 apply_render_state(object, &object->state_block);
3288 apply_texture_state(object);
3290 /* And fill the fog table with the default fog value */
3291 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);