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 #ifndef HAVE_GLEXT_PROTOTYPES
60 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
61 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
62 GLsizei width, GLenum format, GLenum type,
66 const float id_mat[16] = {
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74 D3DPRIMITIVETYPE d3dptPrimitiveType,
75 DWORD d3dvtVertexType,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
86 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
88 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
89 sizeof(display), (LPSTR)&display )) display = NULL;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
99 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
101 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
102 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
108 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
110 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
111 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
113 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
115 if (gl_d3d_dev->state == SURFACE_MEMORY) {
116 d3d_dev->flush_to_framebuffer(d3d_dev, NULL);
118 gl_d3d_dev->state = SURFACE_GL;
119 gl_d3d_dev->front_state = SURFACE_GL;
120 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
127 /*******************************************************************************
128 * OpenGL static functions
130 static void set_context(IDirect3DDeviceImpl* This)
132 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
135 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
136 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
137 ERR("Error in setting current context (context %p drawable %ld)!\n",
138 glThis->gl_context, glThis->drawable);
143 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
145 pc->dwSize = sizeof(*pc);
146 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
147 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
148 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
149 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
150 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
151 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
152 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
153 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
154 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
155 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
156 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
157 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
158 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
159 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
160 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
161 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
162 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
163 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
164 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
165 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
166 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
167 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
168 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
169 pc->dwStippleWidth = 32;
170 pc->dwStippleHeight = 32;
173 static void fill_opengl_caps(D3DDEVICEDESC *d1)
175 /* GLint maxlight; */
177 d1->dwSize = sizeof(*d1);
178 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
179 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
180 d1->dcmColorModel = D3DCOLOR_RGB;
181 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
182 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
183 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
184 /* D3D 7 capabilities */
185 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
186 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
187 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
188 d1->bClipping = TRUE;
189 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
190 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
191 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
192 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
193 fill_opengl_primcaps(&(d1->dpcLineCaps));
194 fill_opengl_primcaps(&(d1->dpcTriCaps));
195 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
196 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
197 d1->dwMaxBufferSize = 0;
198 d1->dwMaxVertexCount = 65536;
199 d1->dwMinTextureWidth = 1;
200 d1->dwMinTextureHeight = 1;
201 d1->dwMaxTextureWidth = 1024;
202 d1->dwMaxTextureHeight = 1024;
203 d1->dwMinStippleWidth = 1;
204 d1->dwMinStippleHeight = 1;
205 d1->dwMaxStippleWidth = 32;
206 d1->dwMaxStippleHeight = 32;
207 d1->dwMaxTextureRepeat = 16;
208 d1->dwMaxTextureAspectRatio = 1024;
209 d1->dwMaxAnisotropy = 0;
210 d1->dvGuardBandLeft = 0.0;
211 d1->dvGuardBandRight = 0.0;
212 d1->dvGuardBandTop = 0.0;
213 d1->dvGuardBandBottom = 0.0;
214 d1->dvExtentsAdjust = 0.0;
215 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
216 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
217 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
218 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
220 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
223 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
227 /* Copy first D3D1/2/3 capabilities */
228 fill_opengl_caps(&d1);
230 /* And fill the D3D7 one with it */
231 d->dwDevCaps = d1.dwDevCaps;
232 d->dpcLineCaps = d1.dpcLineCaps;
233 d->dpcTriCaps = d1.dpcTriCaps;
234 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
235 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
236 d->dwMinTextureWidth = d1.dwMinTextureWidth;
237 d->dwMinTextureHeight = d1.dwMinTextureHeight;
238 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
239 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
240 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
241 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
242 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
243 d->dvGuardBandLeft = d1.dvGuardBandLeft;
244 d->dvGuardBandTop = d1.dvGuardBandTop;
245 d->dvGuardBandRight = d1.dvGuardBandRight;
246 d->dvGuardBandBottom = d1.dvGuardBandBottom;
247 d->dvExtentsAdjust = d1.dvExtentsAdjust;
248 d->dwStencilCaps = d1.dwStencilCaps;
249 d->dwFVFCaps = d1.dwFVFCaps;
250 d->dwTextureOpCaps = d1.dwTextureOpCaps;
251 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
252 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
253 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
254 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
255 d->deviceGUID = IID_IDirect3DTnLHalDevice;
256 d->wMaxUserClipPlanes = 1;
257 d->wMaxVertexBlendMatrices = 0;
258 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
259 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
266 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
267 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
269 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
270 const char *ext_string;
271 Mesa_DeviceCapabilities *devcap;
273 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
274 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
277 ext_string = glGetString(GL_EXTENSIONS);
278 /* Query for the ColorTable Extension */
279 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
280 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
281 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
283 TRACE("Color table extension not found.\n");
291 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
293 D3DDEVICEDESC dref, d1, d2;
296 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
297 Let's put the string in a sufficiently sized array in writable memory. */
298 char device_name[50];
299 strcpy(device_name,"direct3d");
301 fill_opengl_caps(&dref);
304 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
305 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
308 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
309 if (ret_value != D3DENUMRET_OK)
313 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
316 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
317 if (ret_value != D3DENUMRET_OK)
320 return D3DENUMRET_OK;
323 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
325 D3DDEVICEDESC7 ddesc;
327 fill_opengl_caps_7(&ddesc);
329 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
331 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
335 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
337 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
338 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
340 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
341 if (!--(This->ref)) {
343 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
345 /* Release texture associated with the device */
346 for (i = 0; i < MAX_TEXTURES; i++) {
347 if (This->current_texture[i] != NULL)
348 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
349 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
352 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
353 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
354 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
355 surf->aux_ctx = NULL;
356 surf->aux_data = NULL;
357 surf->aux_flip = NULL;
361 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
362 IDirectDrawSurfaceImpl *surf2;
363 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
364 for (; surf2 != NULL; surf2 = surf2->next_attached) {
365 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
366 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
367 /* Override the Lock / Unlock function for all these surfaces */
368 surf2->lock_update = surf2->lock_update_prev;
369 surf2->unlock_update = surf2->unlock_update_prev;
370 /* And install also the blt / bltfast overrides */
371 surf2->aux_blt = NULL;
372 surf2->aux_bltfast = NULL;
374 surf2->d3ddevice = NULL;
378 /* And warn the D3D object that this device is no longer active... */
379 This->d3d->removed_device(This->d3d, This);
381 HeapFree(GetProcessHeap(), 0, This->world_mat);
382 HeapFree(GetProcessHeap(), 0, This->view_mat);
383 HeapFree(GetProcessHeap(), 0, This->proj_mat);
385 DeleteCriticalSection(&(This->crit));
388 if (glThis->unlock_tex)
389 glDeleteTextures(1, &(glThis->unlock_tex));
390 glXDestroyContext(glThis->display, glThis->gl_context);
392 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
394 HeapFree(GetProcessHeap(), 0, This);
401 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
402 LPD3DDEVICEDESC lpD3DHWDevDesc,
403 LPD3DDEVICEDESC lpD3DHELDevDesc)
405 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
409 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
411 fill_opengl_caps(&desc);
412 dwSize = lpD3DHWDevDesc->dwSize;
413 memset(lpD3DHWDevDesc, 0, dwSize);
414 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
416 dwSize = lpD3DHELDevDesc->dwSize;
417 memset(lpD3DHELDevDesc, 0, dwSize);
418 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
420 TRACE(" returning caps : (no dump function yet)\n");
425 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
426 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
430 LPDDPIXELFORMAT pformat;
432 /* Do the texture enumeration */
433 sdesc.dwSize = sizeof(DDSURFACEDESC);
434 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
435 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
436 pformat = &(sdesc.ddpfPixelFormat);
437 pformat->dwSize = sizeof(DDPIXELFORMAT);
438 pformat->dwFourCC = 0;
441 /* See argument about the RGBA format for 'packed' texture formats */
442 TRACE("Enumerating GL_RGBA unpacked (32)\n");
443 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
444 pformat->u1.dwRGBBitCount = 32;
445 pformat->u2.dwRBitMask = 0xFF000000;
446 pformat->u3.dwGBitMask = 0x00FF0000;
447 pformat->u4.dwBBitMask = 0x0000FF00;
448 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
449 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
450 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
453 TRACE("Enumerating GL_RGBA unpacked (32)\n");
454 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
455 pformat->u1.dwRGBBitCount = 32;
456 pformat->u2.dwRBitMask = 0x00FF0000;
457 pformat->u3.dwGBitMask = 0x0000FF00;
458 pformat->u4.dwBBitMask = 0x000000FF;
459 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
460 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
461 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
463 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
464 TRACE("Enumerating GL_RGB unpacked (32)\n");
465 pformat->dwFlags = DDPF_RGB;
466 pformat->u1.dwRGBBitCount = 32;
467 pformat->u2.dwRBitMask = 0x00FF0000;
468 pformat->u3.dwGBitMask = 0x0000FF00;
469 pformat->u4.dwBBitMask = 0x000000FF;
470 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
471 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
472 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
475 TRACE("Enumerating GL_RGB unpacked (24)\n");
476 pformat->dwFlags = DDPF_RGB;
477 pformat->u1.dwRGBBitCount = 24;
478 pformat->u2.dwRBitMask = 0x00FF0000;
479 pformat->u3.dwGBitMask = 0x0000FF00;
480 pformat->u4.dwBBitMask = 0x000000FF;
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;
485 /* Note : even if this is an 'emulated' texture format, it needs to be first
486 as some dumb applications seem to rely on that. */
487 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
488 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
489 pformat->u1.dwRGBBitCount = 16;
490 pformat->u2.dwRBitMask = 0x00007C00;
491 pformat->u3.dwGBitMask = 0x000003E0;
492 pformat->u4.dwBBitMask = 0x0000001F;
493 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
494 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
495 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
497 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
498 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499 pformat->u1.dwRGBBitCount = 16;
500 pformat->u2.dwRBitMask = 0x00000F00;
501 pformat->u3.dwGBitMask = 0x000000F0;
502 pformat->u4.dwBBitMask = 0x0000000F;
503 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
504 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
505 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
507 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
508 pformat->dwFlags = DDPF_RGB;
509 pformat->u1.dwRGBBitCount = 16;
510 pformat->u2.dwRBitMask = 0x0000F800;
511 pformat->u3.dwGBitMask = 0x000007E0;
512 pformat->u4.dwBBitMask = 0x0000001F;
513 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
514 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
515 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
517 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
518 pformat->dwFlags = DDPF_RGB;
519 pformat->u1.dwRGBBitCount = 16;
520 pformat->u2.dwRBitMask = 0x00007C00;
521 pformat->u3.dwGBitMask = 0x000003E0;
522 pformat->u4.dwBBitMask = 0x0000001F;
523 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
524 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
525 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
528 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
529 find enumerated, others the last one. And both want to have the ARGB one.
531 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
533 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
534 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
535 pformat->u1.dwRGBBitCount = 16;
536 pformat->u2.dwRBitMask = 0x0000F000;
537 pformat->u3.dwGBitMask = 0x00000F00;
538 pformat->u4.dwBBitMask = 0x000000F0;
539 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
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("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
544 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
545 pformat->u1.dwRGBBitCount = 16;
546 pformat->u2.dwRBitMask = 0x0000F800;
547 pformat->u3.dwGBitMask = 0x000007C0;
548 pformat->u4.dwBBitMask = 0x0000003E;
549 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
550 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
551 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
554 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
555 pformat->dwFlags = DDPF_RGB;
556 pformat->u1.dwRGBBitCount = 8;
557 pformat->u2.dwRBitMask = 0x000000E0;
558 pformat->u3.dwGBitMask = 0x0000001C;
559 pformat->u4.dwBBitMask = 0x00000003;
560 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
564 TRACE("Enumerating Paletted (8)\n");
565 pformat->dwFlags = DDPF_PALETTEINDEXED8;
566 pformat->u1.dwRGBBitCount = 8;
567 pformat->u2.dwRBitMask = 0x00000000;
568 pformat->u3.dwGBitMask = 0x00000000;
569 pformat->u4.dwBBitMask = 0x00000000;
570 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
571 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
572 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
574 TRACE("End of enumeration\n");
580 d3ddevice_find(IDirect3DImpl *d3d,
581 LPD3DFINDDEVICESEARCH lpD3DDFS,
582 LPD3DFINDDEVICERESULT lplpD3DDevice)
586 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
587 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
588 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
589 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
591 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
592 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
593 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
594 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
595 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
596 TRACE(" no match for this GUID.\n");
597 return DDERR_INVALIDPARAMS;
601 /* Now return our own GUID */
602 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
603 fill_opengl_caps(&desc);
604 lplpD3DDevice->ddHwDesc = desc;
605 lplpD3DDevice->ddSwDesc = desc;
607 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
613 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
614 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
617 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
618 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
619 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
623 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
624 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
627 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
628 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
629 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
633 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
634 D3DRENDERSTATETYPE dwRenderStateType,
637 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
638 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
640 /* Call the render state functions */
641 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
642 set_render_state(This, dwRenderStateType, &This->state_block);
648 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
649 D3DRENDERSTATETYPE dwRenderStateType,
650 LPDWORD lpdwRenderState)
652 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
653 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
655 /* Call the render state functions */
656 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
658 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
664 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
665 D3DLIGHTSTATETYPE dwLightStateType,
668 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
670 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
672 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
673 TRACE("Unexpected Light State Type\n");
674 return DDERR_INVALIDPARAMS;
676 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
677 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
684 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
686 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
687 switch (dwLightState) {
689 ERR("DDCOLOR_MONO should not happen!\n");
692 /* We are already in this mode */
695 ERR("Unknown color model!\n");
699 D3DRENDERSTATETYPE rs;
700 switch (dwLightStateType) {
702 case D3DLIGHTSTATE_AMBIENT: /* 2 */
703 rs = D3DRENDERSTATE_AMBIENT;
705 case D3DLIGHTSTATE_FOGMODE: /* 4 */
706 rs = D3DRENDERSTATE_FOGVERTEXMODE;
708 case D3DLIGHTSTATE_FOGSTART: /* 5 */
709 rs = D3DRENDERSTATE_FOGSTART;
711 case D3DLIGHTSTATE_FOGEND: /* 6 */
712 rs = D3DRENDERSTATE_FOGEND;
714 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
715 rs = D3DRENDERSTATE_FOGDENSITY;
717 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
718 rs = D3DRENDERSTATE_COLORVERTEX;
724 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
731 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
734 case D3DPT_POINTLIST:
735 TRACE("Start POINTS\n");
740 TRACE("Start LINES\n");
744 case D3DPT_LINESTRIP:
745 TRACE("Start LINE_STRIP\n");
746 glBegin(GL_LINE_STRIP);
749 case D3DPT_TRIANGLELIST:
750 TRACE("Start TRIANGLES\n");
751 glBegin(GL_TRIANGLES);
754 case D3DPT_TRIANGLESTRIP:
755 TRACE("Start TRIANGLE_STRIP\n");
756 glBegin(GL_TRIANGLE_STRIP);
759 case D3DPT_TRIANGLEFAN:
760 TRACE("Start TRIANGLE_FAN\n");
761 glBegin(GL_TRIANGLE_FAN);
765 FIXME("Unhandled primitive %08x\n", d3dpt);
770 /* This function calculate the Z coordinate from Zproj */
771 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
774 /* Assume that X = Y = 0 and W = 1 */
775 a = This->proj_mat->_33;
776 b = This->proj_mat->_34;
777 c = This->proj_mat->_43;
778 d = This->proj_mat->_44;
779 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
780 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
781 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
783 return (d*Zproj - c) / (a - b*Zproj);
786 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
789 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
791 for (i = 0; i < 3; i++) {
792 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
794 for (elt = 0; elt < 0x10000; elt++) {
795 /* We apply the fog transformation and cache the result */
796 DWORD fog_intensity = elt & 0xFF;
797 DWORD vertex_color = (elt >> 8) & 0xFF;
798 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
803 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
804 BOOLEAN vertex_transformed,
805 BOOLEAN vertex_lit) {
806 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
808 /* Puts GL in the correct lighting / transformation mode */
809 if ((vertex_transformed == FALSE) &&
810 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
811 /* Need to put the correct transformation again if we go from Transformed
812 vertices to non-transformed ones.
814 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
815 This->world_mat, This->view_mat, This->proj_mat);
816 glThis->transform_state = GL_TRANSFORM_NORMAL;
818 } else if ((vertex_transformed == TRUE) &&
819 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
820 /* Set our orthographic projection */
821 glThis->transform_state = GL_TRANSFORM_ORTHO;
822 d3ddevice_set_ortho(This);
825 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
826 if no fogging state change occured */
827 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
828 if (vertex_transformed == TRUE) {
830 /* Now check if our fog_table still corresponds to the current vertex color.
831 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
832 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
833 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
834 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
835 /* We need to rebuild our fog table.... */
836 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
839 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
840 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
841 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
842 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
843 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
845 if (vertex_lit == FALSE) {
846 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
847 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
849 /* Special case of 'pixel fog' */
850 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
851 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
862 /* Handle the 'no-normal' case */
863 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
864 glEnable(GL_LIGHTING);
866 glDisable(GL_LIGHTING);
868 /* Handle the code for pre-vertex material properties */
869 if (vertex_transformed == FALSE) {
870 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
871 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
872 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
873 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
874 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
875 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
876 glEnable(GL_COLOR_MATERIAL);
883 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
884 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
886 D3DDRAWPRIMITIVESTRIDEDDATA strided;
890 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
891 strided.position.dwStride = sizeof(D3DVERTEX);
892 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
893 strided.normal.dwStride = sizeof(D3DVERTEX);
894 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
895 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
896 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
899 case D3DVT_LVERTEX: {
900 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
901 strided.position.dwStride = sizeof(D3DLVERTEX);
902 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
903 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
904 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
905 strided.specular.dwStride = sizeof(D3DLVERTEX);
906 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
907 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
908 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
911 case D3DVT_TLVERTEX: {
912 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
913 strided.position.dwStride = sizeof(D3DTLVERTEX);
914 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
915 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
916 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
917 strided.specular.dwStride = sizeof(D3DTLVERTEX);
918 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
919 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
920 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
924 FIXME("Unhandled vertex type %08x\n", d3dvt);
930 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
931 D3DPRIMITIVETYPE d3dptPrimitiveType,
932 D3DVERTEXTYPE d3dvtVertexType,
937 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
939 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
940 if (TRACE_ON(ddraw)) {
941 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
944 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
950 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
951 D3DPRIMITIVETYPE d3dptPrimitiveType,
952 D3DVERTEXTYPE d3dvtVertexType,
959 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
960 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
961 if (TRACE_ON(ddraw)) {
962 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
965 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
971 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
972 LPD3DEXECUTEBUFFERDESC lpDesc,
973 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
976 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
977 IDirect3DExecuteBufferImpl *ret;
980 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
982 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
983 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
985 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
990 /* These are the various handler used in the generic path */
991 inline static void handle_xyz(D3DVALUE *coords) {
994 inline static void handle_xyzrhw(D3DVALUE *coords) {
995 if (coords[3] < 1e-8)
998 GLfloat w = 1.0 / coords[3];
1000 glVertex4f(coords[0] * w,
1006 inline static void handle_normal(D3DVALUE *coords) {
1007 glNormal3fv(coords);
1010 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1011 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1012 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1013 glColor4ub((*color >> 16) & 0xFF,
1014 (*color >> 8) & 0xFF,
1015 (*color >> 0) & 0xFF,
1016 (*color >> 24) & 0xFF);
1018 glColor3ub((*color >> 16) & 0xFF,
1019 (*color >> 8) & 0xFF,
1020 (*color >> 0) & 0xFF);
1024 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1025 glColor4ub((*color >> 16) & 0xFF,
1026 (*color >> 8) & 0xFF,
1027 (*color >> 0) & 0xFF,
1028 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1031 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1032 if ((lighted == FALSE) &&
1033 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1034 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1035 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1036 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1037 handle_diffuse_base(sb, color);
1039 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1040 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1041 handle_diffuse_base(sb, color);
1043 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1044 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1045 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1046 handle_diffuse_base(sb, color);
1048 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1049 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1050 handle_diffuse_base(sb, color);
1053 handle_diffuse_base(sb, color);
1057 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1058 if ((lighted == FALSE) &&
1059 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1060 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1061 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1062 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1063 handle_specular_base(sb, color);
1065 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1066 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1067 handle_specular_base(sb, color);
1069 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1070 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1071 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1072 handle_specular_base(sb, color);
1074 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1075 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1076 handle_specular_base(sb, color);
1079 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1082 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1083 if (lighted == TRUE) {
1084 DWORD color = *color_d;
1085 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1086 /* Special case where the specular value is used to do fogging */
1087 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1088 color &= 0xFF000000; /* Only keep the alpha component */
1089 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1090 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1091 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1093 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1094 /* Standard specular value in transformed mode. TODO */
1096 handle_diffuse_base(sb, &color);
1098 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1099 handle_diffuse(sb, color_d, FALSE);
1100 handle_specular(sb, color_s, FALSE);
1102 /* In that case, only put the diffuse color... */
1103 handle_diffuse_base(sb, color_d);
1108 inline static void handle_texture(D3DVALUE *coords) {
1109 glTexCoord2fv(coords);
1111 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1112 /* For the moment, draw only the first texture.. */
1113 if (tex_index == 0) glTexCoord2fv(coords);
1116 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1117 D3DPRIMITIVETYPE d3dptPrimitiveType,
1118 DWORD d3dvtVertexType,
1119 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1120 DWORD dwVertexCount,
1125 BOOLEAN vertex_lighted = FALSE;
1126 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1127 int num_active_stages = 0;
1130 if (glThis->state == SURFACE_MEMORY) {
1131 This->flush_to_framebuffer(This, NULL);
1135 glThis->state = SURFACE_GL;
1137 /* Compute the number of active texture stages */
1138 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1140 /* This is to prevent 'thread contention' between a thread locking the device and another
1141 doing 3D display on it... */
1142 EnterCriticalSection(&(This->crit));
1144 if (TRACE_ON(ddraw)) {
1145 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1150 /* Just a hack for now.. Will have to find better algorithm :-/ */
1151 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1152 vertex_lighted = TRUE;
1154 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1157 draw_primitive_handle_GL_state(This,
1158 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1160 draw_primitive_start_GL(d3dptPrimitiveType);
1162 /* Some fast paths first before the generic case.... */
1163 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1166 for (index = 0; index < dwIndexCount; index++) {
1167 int i = (dwIndices == NULL) ? index : dwIndices[index];
1169 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1170 D3DVALUE *tex_coord =
1171 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1172 D3DVALUE *position =
1173 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1175 handle_normal(normal);
1176 handle_texture(tex_coord);
1177 handle_xyz(position);
1179 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1180 position[0], position[1], position[2],
1181 normal[0], normal[1], normal[2],
1182 tex_coord[0], tex_coord[1]);
1184 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1187 for (index = 0; index < dwIndexCount; index++) {
1188 int i = (dwIndices == NULL) ? index : dwIndices[index];
1190 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1192 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1193 D3DVALUE *tex_coord =
1194 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1195 D3DVALUE *position =
1196 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1198 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1199 handle_texture(tex_coord);
1200 handle_xyzrhw(position);
1202 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1203 position[0], position[1], position[2], position[3],
1204 (*color_d >> 16) & 0xFF,
1205 (*color_d >> 8) & 0xFF,
1206 (*color_d >> 0) & 0xFF,
1207 (*color_d >> 24) & 0xFF,
1208 (*color_s >> 16) & 0xFF,
1209 (*color_s >> 8) & 0xFF,
1210 (*color_s >> 0) & 0xFF,
1211 (*color_s >> 24) & 0xFF,
1212 tex_coord[0], tex_coord[1]);
1214 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1215 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1216 /* This is the 'slow path' but that should support all possible vertex formats out there...
1217 Note that people should write a fast path for all vertex formats out there...
1220 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1221 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1223 for (index = 0; index < dwIndexCount; index++) {
1224 int i = (dwIndices == NULL) ? index : dwIndices[index];
1227 if (d3dvtVertexType & D3DFVF_NORMAL) {
1229 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1230 handle_normal(normal);
1232 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1234 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1236 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1237 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1239 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1241 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1242 handle_specular(&(This->state_block), color_s, vertex_lighted);
1243 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1245 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1246 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1250 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1251 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1252 if (tex_index >= num_tex_index) {
1253 handle_textures((D3DVALUE *) no_index, tex_stage);
1255 D3DVALUE *tex_coord =
1256 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1257 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1258 handle_textures(tex_coord, tex_stage);
1262 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1263 D3DVALUE *position =
1264 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1265 handle_xyz(position);
1266 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1267 D3DVALUE *position =
1268 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1269 handle_xyzrhw(position);
1272 if (TRACE_ON(ddraw_geom)) {
1275 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1276 D3DVALUE *position =
1277 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1278 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1279 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1280 D3DVALUE *position =
1281 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1282 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1284 if (d3dvtVertexType & D3DFVF_NORMAL) {
1286 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1287 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1289 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1291 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1292 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1293 (*color_d >> 16) & 0xFF,
1294 (*color_d >> 8) & 0xFF,
1295 (*color_d >> 0) & 0xFF,
1296 (*color_d >> 24) & 0xFF);
1298 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1300 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1301 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1302 (*color_s >> 16) & 0xFF,
1303 (*color_s >> 8) & 0xFF,
1304 (*color_s >> 0) & 0xFF,
1305 (*color_s >> 24) & 0xFF);
1307 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1308 D3DVALUE *tex_coord =
1309 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1310 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1311 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1313 TRACE_(ddraw_geom)("\n");
1317 ERR(" matrix weighting not handled yet....\n");
1322 /* Whatever the case, disable the color material stuff */
1323 glDisable(GL_COLOR_MATERIAL);
1328 LeaveCriticalSection(&(This->crit));
1332 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1333 D3DPRIMITIVETYPE d3dptPrimitiveType,
1334 DWORD d3dvtVertexType,
1336 DWORD dwVertexCount,
1339 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1340 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1342 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1343 if (TRACE_ON(ddraw)) {
1344 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1347 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1348 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1354 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1355 D3DPRIMITIVETYPE d3dptPrimitiveType,
1356 DWORD d3dvtVertexType,
1358 DWORD dwVertexCount,
1363 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1364 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1366 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1367 if (TRACE_ON(ddraw)) {
1368 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1371 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1372 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1378 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1379 D3DPRIMITIVETYPE d3dptPrimitiveType,
1381 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1382 DWORD dwVertexCount,
1385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1387 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1388 if (TRACE_ON(ddraw)) {
1389 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1391 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1397 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1398 D3DPRIMITIVETYPE d3dptPrimitiveType,
1400 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1401 DWORD dwVertexCount,
1406 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1408 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1409 if (TRACE_ON(ddraw)) {
1410 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1413 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1419 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1420 D3DPRIMITIVETYPE d3dptPrimitiveType,
1421 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1422 DWORD dwStartVertex,
1423 DWORD dwNumVertices,
1426 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1427 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1428 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1430 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1431 if (TRACE_ON(ddraw)) {
1432 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1435 if (vb_impl->processed == TRUE) {
1436 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1437 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1439 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1440 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1441 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1443 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1444 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1447 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1448 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1455 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1456 D3DPRIMITIVETYPE d3dptPrimitiveType,
1457 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1458 DWORD dwStartVertex,
1459 DWORD dwNumVertices,
1464 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1465 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1466 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1468 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1469 if (TRACE_ON(ddraw)) {
1470 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1473 if (vb_impl->processed == TRUE) {
1474 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1475 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1477 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1478 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1479 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1481 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1482 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1485 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1486 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1493 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1497 if (dwMipState == D3DTFP_NONE) {
1498 switch (dwMinState) {
1499 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1500 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1501 default: gl_state = GL_LINEAR; break;
1503 } else if (dwMipState == D3DTFP_POINT) {
1504 switch (dwMinState) {
1505 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1506 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1507 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1510 switch (dwMinState) {
1511 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1512 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1513 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1520 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1526 gl_state = GL_NEAREST;
1529 gl_state = GL_LINEAR;
1532 gl_state = GL_LINEAR;
1538 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1540 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1542 BOOLEAN is_complement = FALSE;
1543 BOOLEAN is_alpha_replicate = FALSE;
1544 BOOLEAN handled = TRUE;
1546 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1550 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1551 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1556 if (tex_op == D3DTOP_SELECTARG2) {
1560 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1561 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1566 if (tex_op == D3DTOP_SELECTARG2) {
1571 if (dwState & D3DTA_COMPLEMENT) {
1572 is_complement = TRUE;
1574 if (dwState & D3DTA_ALPHAREPLICATE) {
1575 is_alpha_replicate = TRUE;
1577 dwState &= D3DTA_SELECTMASK;
1578 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1579 dwState = D3DTA_DIFFUSE;
1583 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1584 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1585 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1586 case D3DTA_TFACTOR: {
1587 /* Get the constant value from the current rendering state */
1589 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1591 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1592 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1593 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1594 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1595 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1597 src = GL_CONSTANT_EXT;
1599 default: src = GL_TEXTURE; handled = FALSE; break;
1603 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1604 if (is_alpha_replicate) {
1605 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1607 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1610 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1611 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1618 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1620 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1623 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1627 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1629 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1631 switch (d3dTexStageStateType) {
1632 #define GEN_CASE(a) case a: type = #a; break
1633 GEN_CASE(D3DTSS_COLOROP);
1634 GEN_CASE(D3DTSS_COLORARG1);
1635 GEN_CASE(D3DTSS_COLORARG2);
1636 GEN_CASE(D3DTSS_ALPHAOP);
1637 GEN_CASE(D3DTSS_ALPHAARG1);
1638 GEN_CASE(D3DTSS_ALPHAARG2);
1639 GEN_CASE(D3DTSS_BUMPENVMAT00);
1640 GEN_CASE(D3DTSS_BUMPENVMAT01);
1641 GEN_CASE(D3DTSS_BUMPENVMAT10);
1642 GEN_CASE(D3DTSS_BUMPENVMAT11);
1643 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1644 GEN_CASE(D3DTSS_ADDRESS);
1645 GEN_CASE(D3DTSS_ADDRESSU);
1646 GEN_CASE(D3DTSS_ADDRESSV);
1647 GEN_CASE(D3DTSS_BORDERCOLOR);
1648 GEN_CASE(D3DTSS_MAGFILTER);
1649 GEN_CASE(D3DTSS_MINFILTER);
1650 GEN_CASE(D3DTSS_MIPFILTER);
1651 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1652 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1653 GEN_CASE(D3DTSS_MAXANISOTROPY);
1654 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1655 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1656 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1658 default: type = "UNKNOWN";
1661 /* Store the values in the state array */
1662 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1663 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1664 /* Some special cases when one state modifies more than one... */
1665 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1666 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1667 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1670 switch (d3dTexStageStateType) {
1671 case D3DTSS_MINFILTER:
1672 case D3DTSS_MIPFILTER:
1673 if (TRACE_ON(ddraw)) {
1674 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1675 switch ((D3DTEXTUREMINFILTER) dwState) {
1676 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1677 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1678 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1681 switch ((D3DTEXTUREMIPFILTER) dwState) {
1682 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1683 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1684 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1685 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1690 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1691 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1692 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1695 case D3DTSS_MAGFILTER:
1696 if (TRACE_ON(ddraw)) {
1697 switch ((D3DTEXTUREMAGFILTER) dwState) {
1698 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1699 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1700 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1706 case D3DTSS_ADDRESS:
1707 case D3DTSS_ADDRESSU:
1708 case D3DTSS_ADDRESSV: {
1709 GLenum arg = GL_REPEAT; /* Default value */
1710 switch ((D3DTEXTUREADDRESS) dwState) {
1711 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1712 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1713 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1714 #if defined(GL_VERSION_1_4)
1715 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1716 #elif defined(GL_ARB_texture_mirrored_repeat)
1717 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1719 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1721 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1722 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1723 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1724 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1725 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1726 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1729 case D3DTSS_ALPHAOP:
1730 case D3DTSS_COLOROP: {
1732 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1737 #define GEN_CASE(a) case a: value = #a; break
1738 GEN_CASE(D3DTOP_DISABLE);
1739 GEN_CASE(D3DTOP_SELECTARG1);
1740 GEN_CASE(D3DTOP_SELECTARG2);
1741 GEN_CASE(D3DTOP_MODULATE);
1742 GEN_CASE(D3DTOP_MODULATE2X);
1743 GEN_CASE(D3DTOP_MODULATE4X);
1744 GEN_CASE(D3DTOP_ADD);
1745 GEN_CASE(D3DTOP_ADDSIGNED);
1746 GEN_CASE(D3DTOP_ADDSIGNED2X);
1747 GEN_CASE(D3DTOP_SUBTRACT);
1748 GEN_CASE(D3DTOP_ADDSMOOTH);
1749 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1750 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1751 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1752 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1753 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1754 GEN_CASE(D3DTOP_PREMODULATE);
1755 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1756 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1757 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1758 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1759 GEN_CASE(D3DTOP_BUMPENVMAP);
1760 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1761 GEN_CASE(D3DTOP_DOTPRODUCT3);
1762 GEN_CASE(D3DTOP_FORCE_DWORD);
1764 default: value = "UNKNOWN";
1767 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1768 glDisable(GL_TEXTURE_2D);
1769 TRACE(" disabling 2D texturing.\n");
1771 /* Re-enable texturing */
1772 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1773 glEnable(GL_TEXTURE_2D);
1774 TRACE(" enabling 2D texturing.\n");
1777 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1778 if (dwState != D3DTOP_DISABLE) {
1779 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1782 /* Now set up the operand correctly */
1784 case D3DTOP_DISABLE:
1785 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1786 and it works, so ignore this op */
1787 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1790 case D3DTOP_SELECTARG1:
1791 case D3DTOP_SELECTARG2:
1792 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1795 case D3DTOP_MODULATE4X:
1796 scale = scale * 2; /* Drop through */
1797 case D3DTOP_MODULATE2X:
1798 scale = scale * 2; /* Drop through */
1799 case D3DTOP_MODULATE:
1800 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1804 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1807 case D3DTOP_ADDSIGNED2X:
1808 scale = scale * 2; /* Drop through */
1809 case D3DTOP_ADDSIGNED:
1810 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1819 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1820 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1821 /* Switch the arguments if needed... */
1822 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1823 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1824 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1826 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1827 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1830 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1831 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1833 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1834 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1840 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1841 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1843 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1845 TRACE(" Stage type is : %s => %s\n", type, value);
1847 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1851 case D3DTSS_COLORARG1:
1852 case D3DTSS_COLORARG2:
1853 case D3DTSS_ALPHAARG1:
1854 case D3DTSS_ALPHAARG2: {
1855 const char *value, *value_comp = "", *value_alpha = "";
1857 D3DTEXTUREOP tex_op;
1859 switch (dwState & D3DTA_SELECTMASK) {
1860 #define GEN_CASE(a) case a: value = #a; break
1861 GEN_CASE(D3DTA_DIFFUSE);
1862 GEN_CASE(D3DTA_CURRENT);
1863 GEN_CASE(D3DTA_TEXTURE);
1864 GEN_CASE(D3DTA_TFACTOR);
1865 GEN_CASE(D3DTA_SPECULAR);
1867 default: value = "UNKNOWN";
1869 if (dwState & D3DTA_COMPLEMENT) {
1870 value_comp = " | D3DTA_COMPLEMENT";
1872 if (dwState & D3DTA_ALPHAREPLICATE) {
1873 value_alpha = " | D3DTA_ALPHAREPLICATE";
1876 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1877 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1879 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1882 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1885 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1887 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1891 case D3DTSS_MIPMAPLODBIAS: {
1892 D3DVALUE value = *((D3DVALUE *) &dwState);
1893 BOOLEAN handled = TRUE;
1899 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1901 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1905 case D3DTSS_MAXMIPLEVEL:
1907 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1909 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1913 case D3DTSS_BORDERCOLOR: {
1916 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1917 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1918 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1919 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1921 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1923 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1924 ((dwState >> 16) & 0xFF),
1925 ((dwState >> 8) & 0xFF),
1926 ((dwState >> 0) & 0xFF),
1927 ((dwState >> 24) & 0xFF));
1930 case D3DTSS_TEXCOORDINDEX: {
1931 BOOLEAN handled = TRUE;
1934 switch (dwState & 0xFFFF0000) {
1935 #define GEN_CASE(a) case a: value = #a; break
1936 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1937 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1938 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1939 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1941 default: value = "UNKNOWN";
1943 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1947 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1949 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1953 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1954 const char *projected = "", *value;
1955 BOOLEAN handled = TRUE;
1956 switch (dwState & 0xFF) {
1957 #define GEN_CASE(a) case a: value = #a; break
1958 GEN_CASE(D3DTTFF_DISABLE);
1959 GEN_CASE(D3DTTFF_COUNT1);
1960 GEN_CASE(D3DTTFF_COUNT2);
1961 GEN_CASE(D3DTTFF_COUNT3);
1962 GEN_CASE(D3DTTFF_COUNT4);
1964 default: value = "UNKNOWN";
1966 if (dwState & D3DTTFF_PROJECTED) {
1967 projected = " | D3DTTFF_PROJECTED";
1971 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1972 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1975 if (handled == TRUE) {
1976 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1978 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1983 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1991 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1993 LPDIRECTDRAWSURFACE7 lpTexture2)
1995 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1997 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1999 if (dwStage > 0) return DD_OK;
2001 if (This->current_texture[dwStage] != NULL) {
2002 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2006 if (lpTexture2 == NULL) {
2007 This->current_texture[dwStage] = NULL;
2009 TRACE(" disabling 2D texturing.\n");
2010 glBindTexture(GL_TEXTURE_2D, 0);
2011 glDisable(GL_TEXTURE_2D);
2013 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2014 GLint max_mip_level;
2016 This->current_texture[dwStage] = tex_impl;
2017 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2019 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2020 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2021 glEnable(GL_TEXTURE_2D);
2022 TRACE(" enabling 2D texturing.\n");
2024 gltex_upload_texture(tex_impl);
2026 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2029 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2032 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2033 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2035 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2036 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2037 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2045 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2046 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2048 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2049 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2051 fill_opengl_caps_7(lpD3DHELDevDesc);
2053 TRACE(" returning caps : no dump function yet.\n");
2059 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2060 LPD3DMATERIAL7 lpMat)
2062 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2063 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2065 if (TRACE_ON(ddraw)) {
2066 TRACE(" material is : \n");
2067 dump_D3DMATERIAL7(lpMat);
2070 This->current_material = *lpMat;
2072 glMaterialfv(GL_FRONT_AND_BACK,
2074 (float *) &(This->current_material.u.diffuse));
2075 glMaterialfv(GL_FRONT_AND_BACK,
2077 (float *) &(This->current_material.u1.ambient));
2078 glMaterialfv(GL_FRONT_AND_BACK,
2080 (float *) &(This->current_material.u2.specular));
2081 glMaterialfv(GL_FRONT_AND_BACK,
2083 (float *) &(This->current_material.u3.emissive));
2084 glMaterialf(GL_FRONT_AND_BACK,
2086 This->current_material.u4.power); /* Not sure about this... */
2093 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2095 LPD3DLIGHT7 lpLight)
2097 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2098 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2099 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2101 if (TRACE_ON(ddraw)) {
2102 TRACE(" setting light : \n");
2103 dump_D3DLIGHT7(lpLight);
2106 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2107 This->set_lights |= 0x00000001 << dwLightIndex;
2108 This->light_parameters[dwLightIndex] = *lpLight;
2110 /* Some checks to print out nice warnings :-) */
2111 switch (lpLight->dltType) {
2112 case D3DLIGHT_DIRECTIONAL:
2113 case D3DLIGHT_POINT:
2114 /* These are handled properly... */
2118 if ((lpLight->dvTheta != 0.0) ||
2119 (lpLight->dvTheta != lpLight->dvPhi)) {
2120 ERR("dvTheta not fully supported yet !\n");
2125 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2128 /* This will force the Light setting on next drawing of primitives */
2129 glThis->transform_state = GL_TRANSFORM_NONE;
2135 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2139 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2140 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2142 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2145 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2146 /* Set the default parameters.. */
2147 TRACE(" setting default light parameters...\n");
2148 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2150 glEnable(GL_LIGHT0 + dwLightIndex);
2151 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2152 /* This light gets active... Need to update its parameters to GL before the next drawing */
2153 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2155 This->active_lights |= 0x00000001 << dwLightIndex;
2156 glThis->transform_state = GL_TRANSFORM_NONE;
2159 glDisable(GL_LIGHT0 + dwLightIndex);
2160 This->active_lights &= ~(0x00000001 << dwLightIndex);
2167 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2169 ICOM_THIS(IDirect3DDeviceImpl,iface);
2170 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2172 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2174 if (dwIndex >= This->max_clipping_planes) {
2175 return DDERR_INVALIDPARAMS;
2178 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2180 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2182 /* This is to force the reset of the transformation matrices on the next drawing.
2183 * This is needed to use the correct matrices for the various clipping planes.
2185 glThis->transform_state = GL_TRANSFORM_NONE;
2191 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2192 LPD3DVIEWPORT7 lpData)
2194 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2195 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2197 if (TRACE_ON(ddraw)) {
2198 TRACE(" viewport is : \n");
2199 TRACE(" - dwX = %ld dwY = %ld\n",
2200 lpData->dwX, lpData->dwY);
2201 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2202 lpData->dwWidth, lpData->dwHeight);
2203 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2204 lpData->dvMinZ, lpData->dvMaxZ);
2206 This->active_viewport = *lpData;
2208 /* Set the viewport */
2209 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2210 glViewport(lpData->dwX,
2211 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2212 lpData->dwWidth, lpData->dwHeight);
2217 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2218 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2220 # define XCAST(fun) (void*)
2223 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2225 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2226 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2227 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2228 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2229 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2230 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2231 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2232 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2233 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2234 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2235 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2236 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2237 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2238 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2239 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2240 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2241 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2242 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2243 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2244 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2245 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2246 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2247 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2248 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2249 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2250 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2251 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2252 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2253 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2254 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2255 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2256 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2257 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2258 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2259 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2260 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2261 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2262 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2263 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2264 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2265 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2266 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2267 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2268 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2269 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2270 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2271 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2272 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2273 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2274 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2277 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2282 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2283 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2285 # define XCAST(fun) (void*)
2288 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2290 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2291 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2292 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2293 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2294 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2295 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2296 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2297 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2298 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2299 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2300 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2301 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2302 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2303 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2304 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2305 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2306 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2307 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2308 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2309 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2310 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2311 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2312 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2313 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2314 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2315 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2316 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2317 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2318 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2319 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2320 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2321 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2322 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2323 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2324 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2325 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2326 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2327 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2328 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2329 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2330 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2331 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2332 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2335 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2340 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2341 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2343 # define XCAST(fun) (void*)
2346 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2348 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2349 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2350 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2351 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2352 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2353 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2354 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2355 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2356 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2357 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2358 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2359 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2360 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2361 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2362 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2363 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2364 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2365 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2366 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2367 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2368 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2369 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2370 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2371 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2372 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2373 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2374 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2375 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2376 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2377 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2378 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2379 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2380 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2381 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2384 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2389 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2390 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2392 # define XCAST(fun) (void*)
2395 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2397 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2398 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2399 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2400 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2401 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2402 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2403 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2404 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2405 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2406 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2407 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2408 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2409 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2410 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2411 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2412 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2413 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2414 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2415 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2416 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2417 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2418 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2419 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2422 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2426 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2435 GLfloat old_z_clear_value;
2436 GLbitfield bitfield = 0;
2437 GLint old_stencil_clear_value;
2438 GLfloat old_color_clear_value[4];
2442 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2443 if (TRACE_ON(ddraw)) {
2446 TRACE(" rectangles : \n");
2447 for (i = 0; i < dwCount; i++) {
2448 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2454 /* Not sure if this is really needed... */
2458 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2459 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2463 /* Clears the screen */
2465 if (dwFlags & D3DCLEAR_ZBUFFER) {
2466 bitfield |= GL_DEPTH_BUFFER_BIT;
2467 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2468 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2469 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2471 TRACE(" depth value : %f\n", dvZ);
2473 if (dwFlags & D3DCLEAR_STENCIL) {
2474 bitfield |= GL_STENCIL_BUFFER_BIT;
2475 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2476 glClearStencil(dwStencil);
2477 TRACE(" stencil value : %ld\n", dwStencil);
2479 if (dwFlags & D3DCLEAR_TARGET) {
2480 bitfield |= GL_COLOR_BUFFER_BIT;
2481 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2482 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2483 ((dwColor >> 8) & 0xFF) / 255.0,
2484 ((dwColor >> 0) & 0xFF) / 255.0,
2485 ((dwColor >> 24) & 0xFF) / 255.0);
2486 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2489 glEnable(GL_SCISSOR_TEST);
2490 for (i = 0; i < dwCount; i++) {
2491 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2492 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2495 glDisable(GL_SCISSOR_TEST);
2497 if (dwFlags & D3DCLEAR_ZBUFFER) {
2499 glClearDepth(old_z_clear_value);
2501 if (dwFlags & D3DCLEAR_STENCIL) {
2502 bitfield |= GL_STENCIL_BUFFER_BIT;
2503 glClearStencil(old_stencil_clear_value);
2505 if (dwFlags & D3DCLEAR_TARGET) {
2506 bitfield |= GL_COLOR_BUFFER_BIT;
2507 glClearColor(old_color_clear_value[0],
2508 old_color_clear_value[1],
2509 old_color_clear_value[2],
2510 old_color_clear_value[3]);
2519 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2520 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2521 DWORD dwFlags, LPDDBLTFX lpbltfx)
2523 if (dwFlags & DDBLT_COLORFILL) {
2524 /* This is easy to handle for the D3D Device... */
2525 DWORD color = lpbltfx->u5.dwFillColor;
2528 TRACE(" executing D3D Device override.\n");
2531 rect.u1.x1 = rdst->left;
2532 rect.u2.y1 = rdst->top;
2533 rect.u3.x2 = rdst->right;
2534 rect.u4.y2 = rdst->bottom;
2536 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2539 return DDERR_INVALIDPARAMS;
2543 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2544 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2545 LPRECT rsrc, DWORD trans)
2547 return DDERR_INVALIDPARAMS;
2551 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2553 GLfloat height, width;
2554 GLfloat trans_mat[16];
2556 width = This->surface->surface_desc.dwWidth;
2557 height = This->surface->surface_desc.dwHeight;
2559 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2560 to OpenGL screen coordinates (ie the upper left corner is not the same).
2561 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2562 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2563 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2564 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2565 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2566 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2568 glMatrixMode(GL_MODELVIEW);
2570 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2571 Correctness Tips section).
2573 Basically, from what I understood, if the game does not filter the font texture,
2574 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2575 one and we will have strange artifacts (as the rounding and stuff may give different results
2576 for different pixels, ie sometimes take the left pixel, sometimes the right).
2578 glTranslatef(0.375, 0.375, 0);
2579 glMatrixMode(GL_PROJECTION);
2580 glLoadMatrixf(trans_mat);
2584 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2585 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2587 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2588 glMatrixMode(GL_MODELVIEW);
2589 glLoadMatrixf((float *) view_mat);
2591 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2592 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2595 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2596 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2599 plane[0] = This->clipping_planes[i].plane[0];
2600 plane[1] = This->clipping_planes[i].plane[1];
2601 plane[2] = This->clipping_planes[i].plane[2];
2602 plane[3] = This->clipping_planes[i].plane[3];
2604 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2608 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2612 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2613 if (runner & This->active_lights) {
2614 switch (This->light_parameters[i].dltType) {
2615 case D3DLIGHT_DIRECTIONAL: {
2617 float cut_off = 180.0;
2619 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2620 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2621 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2622 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2624 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2625 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2626 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2628 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2631 case D3DLIGHT_POINT: {
2633 float cut_off = 180.0;
2635 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2636 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2637 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2638 position[0] = This->light_parameters[i].dvPosition.u1.x;
2639 position[1] = This->light_parameters[i].dvPosition.u2.y;
2640 position[2] = This->light_parameters[i].dvPosition.u3.z;
2642 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2643 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2644 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2645 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2646 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2649 case D3DLIGHT_SPOT: {
2652 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2654 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2655 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2656 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
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_SPOT_DIRECTION, (float *) direction);
2663 position[0] = This->light_parameters[i].dvPosition.u1.x;
2664 position[1] = This->light_parameters[i].dvPosition.u2.y;
2665 position[2] = This->light_parameters[i].dvPosition.u3.z;
2667 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2668 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2669 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2670 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2671 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2672 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2676 /* No warning here as it's already done at light setting */
2683 glMultMatrixf((float *) world_mat);
2685 if ((matrices & PROJMAT_CHANGED) != 0) {
2686 glMatrixMode(GL_PROJECTION);
2687 glLoadMatrixf((float *) proj_mat);
2692 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2694 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2695 DWORD tex_mat, tex_stage;
2696 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2697 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2698 /* This will force an update of the transform state at the next drawing. */
2699 glThis->transform_state = GL_TRANSFORM_NONE;
2702 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2703 if (matrices & tex_mat) {
2704 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2705 if (tex_stage == 0) {
2706 /* No multi-texturing support for now ... */
2707 glMatrixMode(GL_TEXTURE);
2708 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2711 glMatrixMode(GL_TEXTURE);
2718 /* TODO for both these functions :
2719 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2720 by other OpenGL code in D3D
2721 - handle the case where no 'Begin / EndScene' was done between two locks
2722 - handle the rectangles in the unlock too
2723 - handle pitch correctly...
2725 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2727 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2728 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2731 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2733 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2736 ERR("Wrong surface type for locking !\n");
2740 /* Try to acquire the device critical section */
2741 EnterCriticalSection(&(d3d_dev->crit));
2743 if (((is_front == TRUE) && (gl_d3d_dev->front_state != SURFACE_MEMORY)) ||
2744 ((is_front == FALSE) && (gl_d3d_dev->state != SURFACE_MEMORY))) {
2745 /* If the surface is already in memory, no need to do anything here... */
2747 GLenum buffer_color;
2753 TRACE(" copying frame buffer to main memory.\n");
2755 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2756 may only write to the device... But when we will blit it back to the screen, we need
2757 also to blit correctly the parts the application did not overwrite... */
2761 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2764 if (is_front == TRUE)
2765 /* Application wants to lock the front buffer */
2766 glReadBuffer(GL_FRONT);
2768 /* Application wants to lock the back buffer */
2769 glReadBuffer(GL_BACK);
2771 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2772 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2773 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2774 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2775 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2776 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2777 buffer_color = GL_RGB;
2778 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2779 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2780 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2781 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2782 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2783 buffer_type = GL_UNSIGNED_BYTE;
2784 buffer_color = GL_BGRA;
2785 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2787 ERR(" unsupported pixel format at device locking.\n");
2792 /* Just a hack while waiting for proper rectangle support */
2794 if (pRect == NULL) {
2797 loc_rect.bottom = This->surface_desc.dwHeight;
2798 loc_rect.right = This->surface_desc.dwWidth;
2803 dst = ((char *)This->surface_desc.lpSurface) +
2804 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2805 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2806 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2808 glReadPixels(loc_rect.left, y,
2809 loc_rect.right - loc_rect.left, 1,
2810 buffer_color, buffer_type, dst);
2811 dst += This->surface_desc.u1.lPitch;
2814 glReadBuffer(prev_read);
2815 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2818 gl_d3d_dev->front_state = SURFACE_MEMORY;
2820 gl_d3d_dev->state = SURFACE_MEMORY;
2823 /* I keep this code here as it's very useful to debug :-) */
2825 static int flush_count = 0;
2829 if ((++flush_count % 50) == 0) {
2830 sprintf(buf, "lock_%06d.pnm", flush_count);
2831 f = fopen(buf, "wb");
2832 DDRAW_dump_surface_to_disk(This, f);
2841 #define UNLOCK_TEX_SIZE 256
2843 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2844 GLenum buffer_type, buffer_color;
2846 IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2847 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2848 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test;
2849 GLuint initial_texture;
2853 /* This is to prevent another thread to actually lock the buffer while we flush it on screen */
2854 EnterCriticalSection(&(d3d_dev->crit));
2858 loc_rect.bottom = surf->surface_desc.dwHeight;
2859 loc_rect.right = surf->surface_desc.dwWidth;
2861 TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
2863 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2864 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2865 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2866 glGetIntegerv(GL_CULL_FACE, &cull_face);
2867 glGetIntegerv(GL_LIGHTING, &lighting);
2868 glGetIntegerv(GL_BLEND, &blend);
2869 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2870 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2871 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2872 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2873 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2874 glMatrixMode(GL_TEXTURE);
2876 /* TODO: scissor test if ever we use it ! */
2878 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2879 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2880 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2881 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2882 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2883 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2884 buffer_color = GL_RGB;
2885 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2886 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2887 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2888 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2889 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2890 buffer_type = GL_UNSIGNED_BYTE;
2891 buffer_color = GL_BGRA;
2892 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2894 ERR(" unsupported pixel format at frame buffer flush.\n");
2895 LeaveCriticalSection(&(d3d_dev->crit));
2899 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2900 d3ddevice_set_ortho(d3d_dev);
2902 glDisable(GL_DEPTH_TEST);
2903 glEnable(GL_TEXTURE_2D);
2904 glEnable(GL_SCISSOR_TEST);
2905 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2906 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2908 if (gl_d3d_dev->unlock_tex == 0) {
2909 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2910 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2911 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2912 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2913 GL_RGB, buffer_type, NULL);
2915 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2917 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2919 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2920 glDisable(GL_LIGHTING);
2921 glDisable(GL_CULL_FACE);
2922 glDisable(GL_ALPHA_TEST);
2923 glDisable(GL_STENCIL_TEST);
2924 glDisable(GL_BLEND);
2925 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2926 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2928 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2929 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2930 /* First, upload the texture... */
2931 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2932 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2933 glTexSubImage2D(GL_TEXTURE_2D,
2939 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2941 glColor3ub(0xFF, 0xFF, 0xFF);
2942 glTexCoord2f(0.0, 0.0);
2943 glVertex3d(x, y, 0.5);
2944 glTexCoord2f(1.0, 0.0);
2945 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2946 glTexCoord2f(1.0, 1.0);
2947 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2948 glTexCoord2f(0.0, 1.0);
2949 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2955 /* And restore all the various states modified by this code */
2956 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2957 if (lighting != 0) glEnable(GL_LIGHTING);
2958 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2959 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2960 if (cull_face != 0) glEnable(GL_CULL_FACE);
2961 if (blend != 0) glEnable(GL_BLEND);
2962 glBindTexture(GL_TEXTURE_2D, initial_texture);
2963 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2964 glDisable(GL_SCISSOR_TEST);
2965 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2966 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
2967 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2968 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2969 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2970 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
2972 /* I keep this code here as it's very useful to debug :-) */
2974 static int flush_count = 0;
2978 if ((++flush_count % 50) == 0) {
2979 sprintf(buf, "flush_%06d.pnm", flush_count);
2980 f = fopen(buf, "wb");
2981 DDRAW_dump_surface_to_disk(surf, f);
2986 /* And leave the critical section... */
2987 LeaveCriticalSection(&(d3d_dev->crit));
2990 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2993 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2995 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2997 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3000 ERR("Wrong surface type for locking !\n");
3003 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3004 if (((This->lastlocktype & DDLOCK_READONLY) == 0) &&
3005 (is_front == TRUE)) {
3008 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3009 glDrawBuffer(GL_FRONT);
3010 d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
3011 glDrawBuffer(prev_draw);
3015 /* And 'frees' the device critical section */
3016 LeaveCriticalSection(&(d3d_dev->crit));
3020 apply_texture_state(IDirect3DDeviceImpl *This)
3024 /* Initialize texture stages states */
3025 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3026 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3027 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3028 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3029 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3036 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3038 IDirect3DDeviceImpl *object;
3039 IDirect3DDeviceGLImpl *gl_object;
3040 IDirectDrawSurfaceImpl *surf;
3045 XVisualInfo template;
3046 GLenum buffer = GL_FRONT;
3048 GLint max_clipping_planes = 0;
3050 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3051 if (object == NULL) return DDERR_OUTOFMEMORY;
3053 gl_object = (IDirect3DDeviceGLImpl *) object;
3057 object->surface = surface;
3058 object->set_context = set_context;
3059 object->clear = d3ddevice_clear;
3060 object->set_matrices = d3ddevice_set_matrices;
3061 object->matrices_updated = d3ddevice_matrices_updated;
3062 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3064 InitializeCriticalSection(&(object->crit));
3066 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3068 device_context = GetDC(surface->ddraw_owner->window);
3069 gl_object->display = get_display(device_context);
3070 gl_object->drawable = get_drawable(device_context);
3071 ReleaseDC(surface->ddraw_owner->window,device_context);
3074 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3075 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3077 HeapFree(GetProcessHeap(), 0, object);
3078 ERR("No visual found !\n");
3080 return DDERR_INVALIDPARAMS;
3082 TRACE(" visual found\n");
3085 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3088 if (gl_object->gl_context == NULL) {
3089 HeapFree(GetProcessHeap(), 0, object);
3090 ERR("Error in context creation !\n");
3092 return DDERR_INVALIDPARAMS;
3094 TRACE(" context created (%p)\n", gl_object->gl_context);
3097 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3098 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3099 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3100 surf->aux_ctx = (LPVOID) object;
3101 surf->aux_data = (LPVOID) gl_object->drawable;
3102 surf->aux_flip = opengl_flip;
3107 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3109 TRACE(" no double buffering : drawing on the front buffer\n");
3113 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3114 IDirectDrawSurfaceImpl *surf2;
3115 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3116 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3117 TRACE(" checking surface %p :", surf2);
3118 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3119 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3120 /* Override the Lock / Unlock function for all these surfaces */
3121 surf2->lock_update_prev = surf2->lock_update;
3122 surf2->lock_update = d3ddevice_lock_update;
3123 surf2->unlock_update_prev = surf2->unlock_update;
3124 surf2->unlock_update = d3ddevice_unlock_update;
3125 /* And install also the blt / bltfast overrides */
3126 surf2->aux_blt = d3ddevice_blt;
3127 surf2->aux_bltfast = d3ddevice_bltfast;
3129 TRACE(" overiding direct surface access.\n");
3131 TRACE(" no overide.\n");
3133 surf2->d3ddevice = object;
3137 /* Set the various light parameters */
3138 for (light = 0; light < MAX_LIGHTS; light++) {
3139 /* Only set the fields that are not zero-created */
3140 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3141 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3142 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3143 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3144 object->light_parameters[light].dvDirection.u3.z = 1.0;
3147 /* Allocate memory for the matrices */
3148 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3149 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3150 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3151 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3152 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3153 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3154 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3155 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3156 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3159 /* Initialisation */
3160 TRACE(" setting current context\n");
3162 object->set_context(object);
3164 TRACE(" current context set\n");
3166 /* allocate the clipping planes */
3167 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3168 if (max_clipping_planes>32) {
3169 object->max_clipping_planes=32;
3171 object->max_clipping_planes = max_clipping_planes;
3173 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3174 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3176 glHint(GL_FOG_HINT,GL_NICEST);
3178 glClearColor(0.0, 0.0, 0.0, 0.0);
3179 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3180 glDrawBuffer(buffer);
3181 glReadBuffer(buffer);
3182 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3185 gl_object->state = SURFACE_GL;
3187 /* fill_device_capabilities(d3d->ddraw); */
3189 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3190 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3191 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3192 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3196 TRACE(" creating implementation at %p.\n", *obj);
3198 /* And finally warn D3D that this device is now present */
3199 object->d3d->added_device(object->d3d, object);
3201 /* FIXME: Should handle other versions than just 7 */
3202 InitDefaultStateBlock(&object->state_block, 7);
3203 /* Apply default render state and texture stage state values */
3204 apply_render_state(object, &object->state_block);
3205 apply_texture_state(object);
3207 /* And fill the fog table with the default fog value */
3208 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);