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 display, LPVOID drawable)
110 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
112 glXSwapBuffers((Display*)display,(Drawable)drawable);
118 /*******************************************************************************
119 * OpenGL static functions
121 static void set_context(IDirect3DDeviceImpl* This)
123 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
126 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
127 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
128 ERR("Error in setting current context (context %p drawable %ld)!\n",
129 glThis->gl_context, glThis->drawable);
134 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
136 pc->dwSize = sizeof(*pc);
137 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
138 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
139 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
140 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
141 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
142 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
143 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
144 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
145 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
146 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
147 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
148 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
149 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
150 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
151 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
152 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
153 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
154 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
155 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
156 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
157 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
158 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
159 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
160 pc->dwStippleWidth = 32;
161 pc->dwStippleHeight = 32;
164 static void fill_opengl_caps(D3DDEVICEDESC *d1)
166 /* GLint maxlight; */
168 d1->dwSize = sizeof(*d1);
169 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
170 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
171 d1->dcmColorModel = D3DCOLOR_RGB;
172 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
173 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
174 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
175 /* D3D 7 capabilities */
176 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
177 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
178 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
179 d1->bClipping = TRUE;
180 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
181 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
182 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
183 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
184 fill_opengl_primcaps(&(d1->dpcLineCaps));
185 fill_opengl_primcaps(&(d1->dpcTriCaps));
186 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
187 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
188 d1->dwMaxBufferSize = 0;
189 d1->dwMaxVertexCount = 65536;
190 d1->dwMinTextureWidth = 1;
191 d1->dwMinTextureHeight = 1;
192 d1->dwMaxTextureWidth = 1024;
193 d1->dwMaxTextureHeight = 1024;
194 d1->dwMinStippleWidth = 1;
195 d1->dwMinStippleHeight = 1;
196 d1->dwMaxStippleWidth = 32;
197 d1->dwMaxStippleHeight = 32;
198 d1->dwMaxTextureRepeat = 16;
199 d1->dwMaxTextureAspectRatio = 1024;
200 d1->dwMaxAnisotropy = 0;
201 d1->dvGuardBandLeft = 0.0;
202 d1->dvGuardBandRight = 0.0;
203 d1->dvGuardBandTop = 0.0;
204 d1->dvGuardBandBottom = 0.0;
205 d1->dvExtentsAdjust = 0.0;
206 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
207 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
208 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
209 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
210 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
211 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
214 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
218 /* Copy first D3D1/2/3 capabilities */
219 fill_opengl_caps(&d1);
221 /* And fill the D3D7 one with it */
222 d->dwDevCaps = d1.dwDevCaps;
223 d->dpcLineCaps = d1.dpcLineCaps;
224 d->dpcTriCaps = d1.dpcTriCaps;
225 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
226 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
227 d->dwMinTextureWidth = d1.dwMinTextureWidth;
228 d->dwMinTextureHeight = d1.dwMinTextureHeight;
229 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
230 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
231 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
232 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
233 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
234 d->dvGuardBandLeft = d1.dvGuardBandLeft;
235 d->dvGuardBandTop = d1.dvGuardBandTop;
236 d->dvGuardBandRight = d1.dvGuardBandRight;
237 d->dvGuardBandBottom = d1.dvGuardBandBottom;
238 d->dvExtentsAdjust = d1.dvExtentsAdjust;
239 d->dwStencilCaps = d1.dwStencilCaps;
240 d->dwFVFCaps = d1.dwFVFCaps;
241 d->dwTextureOpCaps = d1.dwTextureOpCaps;
242 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
243 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
244 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
245 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
246 d->deviceGUID = IID_IDirect3DTnLHalDevice;
247 d->wMaxUserClipPlanes = 1;
248 d->wMaxVertexBlendMatrices = 0;
249 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
250 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
257 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
258 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
260 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
261 const char *ext_string;
262 Mesa_DeviceCapabilities *devcap;
264 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
265 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
268 ext_string = glGetString(GL_EXTENSIONS);
269 /* Query for the ColorTable Extension */
270 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
271 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
272 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
274 TRACE("Color table extension not found.\n");
282 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
284 D3DDEVICEDESC dref, d1, d2;
287 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
288 Let's put the string in a sufficiently sized array in writable memory. */
289 char device_name[50];
290 strcpy(device_name,"direct3d");
292 fill_opengl_caps(&dref);
295 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
296 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
299 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
300 if (ret_value != D3DENUMRET_OK)
304 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
307 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
308 if (ret_value != D3DENUMRET_OK)
311 return D3DENUMRET_OK;
314 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
316 D3DDEVICEDESC7 ddesc;
318 fill_opengl_caps_7(&ddesc);
320 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
322 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
326 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
328 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
329 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
331 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
332 if (!--(This->ref)) {
334 /* Release texture associated with the device */
335 for (i = 0; i < MAX_TEXTURES; i++)
336 if (This->current_texture[i] != NULL)
337 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
339 /* TODO: remove the 'callbacks' for Flip and Lock/Unlock */
341 /* And warn the D3D object that this device is no longer active... */
342 This->d3d->removed_device(This->d3d, This);
344 HeapFree(GetProcessHeap(), 0, This->world_mat);
345 HeapFree(GetProcessHeap(), 0, This->view_mat);
346 HeapFree(GetProcessHeap(), 0, This->proj_mat);
348 DeleteCriticalSection(&(This->crit));
351 glXDestroyContext(glThis->display, glThis->gl_context);
353 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
355 HeapFree(GetProcessHeap(), 0, This);
362 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
363 LPD3DDEVICEDESC lpD3DHWDevDesc,
364 LPD3DDEVICEDESC lpD3DHELDevDesc)
366 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
370 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
372 fill_opengl_caps(&desc);
373 dwSize = lpD3DHWDevDesc->dwSize;
374 memset(lpD3DHWDevDesc, 0, dwSize);
375 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
377 dwSize = lpD3DHELDevDesc->dwSize;
378 memset(lpD3DHELDevDesc, 0, dwSize);
379 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
381 TRACE(" returning caps : (no dump function yet)\n");
386 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
387 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
391 LPDDPIXELFORMAT pformat;
393 /* Do the texture enumeration */
394 sdesc.dwSize = sizeof(DDSURFACEDESC);
395 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
396 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
397 pformat = &(sdesc.ddpfPixelFormat);
398 pformat->dwSize = sizeof(DDPIXELFORMAT);
399 pformat->dwFourCC = 0;
402 /* See argument about the RGBA format for 'packed' texture formats */
403 TRACE("Enumerating GL_RGBA unpacked (32)\n");
404 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
405 pformat->u1.dwRGBBitCount = 32;
406 pformat->u2.dwRBitMask = 0xFF000000;
407 pformat->u3.dwGBitMask = 0x00FF0000;
408 pformat->u4.dwBBitMask = 0x0000FF00;
409 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
410 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
411 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
414 TRACE("Enumerating GL_RGBA unpacked (32)\n");
415 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
416 pformat->u1.dwRGBBitCount = 32;
417 pformat->u2.dwRBitMask = 0x00FF0000;
418 pformat->u3.dwGBitMask = 0x0000FF00;
419 pformat->u4.dwBBitMask = 0x000000FF;
420 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
421 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
422 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
424 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
425 TRACE("Enumerating GL_RGB unpacked (32)\n");
426 pformat->dwFlags = DDPF_RGB;
427 pformat->u1.dwRGBBitCount = 32;
428 pformat->u2.dwRBitMask = 0x00FF0000;
429 pformat->u3.dwGBitMask = 0x0000FF00;
430 pformat->u4.dwBBitMask = 0x000000FF;
431 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
432 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
433 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
436 TRACE("Enumerating GL_RGB unpacked (24)\n");
437 pformat->dwFlags = DDPF_RGB;
438 pformat->u1.dwRGBBitCount = 24;
439 pformat->u2.dwRBitMask = 0x00FF0000;
440 pformat->u3.dwGBitMask = 0x0000FF00;
441 pformat->u4.dwBBitMask = 0x000000FF;
442 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
443 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
444 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
446 /* Note : even if this is an 'emulated' texture format, it needs to be first
447 as some dumb applications seem to rely on that. */
448 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
449 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
450 pformat->u1.dwRGBBitCount = 16;
451 pformat->u2.dwRBitMask = 0x00007C00;
452 pformat->u3.dwGBitMask = 0x000003E0;
453 pformat->u4.dwBBitMask = 0x0000001F;
454 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
455 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
456 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
458 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
459 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
460 pformat->u1.dwRGBBitCount = 16;
461 pformat->u2.dwRBitMask = 0x00000F00;
462 pformat->u3.dwGBitMask = 0x000000F0;
463 pformat->u4.dwBBitMask = 0x0000000F;
464 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
465 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
466 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
468 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
469 pformat->dwFlags = DDPF_RGB;
470 pformat->u1.dwRGBBitCount = 16;
471 pformat->u2.dwRBitMask = 0x0000F800;
472 pformat->u3.dwGBitMask = 0x000007E0;
473 pformat->u4.dwBBitMask = 0x0000001F;
474 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
475 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
476 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
478 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
479 pformat->dwFlags = DDPF_RGB;
480 pformat->u1.dwRGBBitCount = 16;
481 pformat->u2.dwRBitMask = 0x00007C00;
482 pformat->u3.dwGBitMask = 0x000003E0;
483 pformat->u4.dwBBitMask = 0x0000001F;
484 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
485 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
486 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
489 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
490 find enumerated, others the last one. And both want to have the ARGB one.
492 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
494 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
495 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
496 pformat->u1.dwRGBBitCount = 16;
497 pformat->u2.dwRBitMask = 0x0000F000;
498 pformat->u3.dwGBitMask = 0x00000F00;
499 pformat->u4.dwBBitMask = 0x000000F0;
500 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
501 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
502 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
504 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
505 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
506 pformat->u1.dwRGBBitCount = 16;
507 pformat->u2.dwRBitMask = 0x0000F800;
508 pformat->u3.dwGBitMask = 0x000007C0;
509 pformat->u4.dwBBitMask = 0x0000003E;
510 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
511 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
512 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
515 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
516 pformat->dwFlags = DDPF_RGB;
517 pformat->u1.dwRGBBitCount = 8;
518 pformat->u2.dwRBitMask = 0x000000E0;
519 pformat->u3.dwGBitMask = 0x0000001C;
520 pformat->u4.dwBBitMask = 0x00000003;
521 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
522 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
523 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
525 TRACE("Enumerating Paletted (8)\n");
526 pformat->dwFlags = DDPF_PALETTEINDEXED8;
527 pformat->u1.dwRGBBitCount = 8;
528 pformat->u2.dwRBitMask = 0x00000000;
529 pformat->u3.dwGBitMask = 0x00000000;
530 pformat->u4.dwBBitMask = 0x00000000;
531 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
532 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
533 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
535 TRACE("End of enumeration\n");
541 d3ddevice_find(IDirect3DImpl *d3d,
542 LPD3DFINDDEVICESEARCH lpD3DDFS,
543 LPD3DFINDDEVICERESULT lplpD3DDevice)
547 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
548 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
549 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
550 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
552 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
553 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
554 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
555 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
556 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
557 TRACE(" no match for this GUID.\n");
558 return DDERR_INVALIDPARAMS;
562 /* Now return our own GUID */
563 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
564 fill_opengl_caps(&desc);
565 lplpD3DDevice->ddHwDesc = desc;
566 lplpD3DDevice->ddSwDesc = desc;
568 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
574 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
575 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
578 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
579 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
580 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
584 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
585 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
588 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
589 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
590 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
594 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
595 D3DRENDERSTATETYPE dwRenderStateType,
598 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
599 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
601 /* Call the render state functions */
602 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
603 set_render_state(This, dwRenderStateType, &This->state_block);
609 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
610 D3DRENDERSTATETYPE dwRenderStateType,
611 LPDWORD lpdwRenderState)
613 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
614 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
616 /* Call the render state functions */
617 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
619 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
625 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
626 D3DLIGHTSTATETYPE dwLightStateType,
629 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
631 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
633 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
634 TRACE("Unexpected Light State Type\n");
635 return DDERR_INVALIDPARAMS;
637 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
638 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
645 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
647 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
648 switch (dwLightState) {
650 ERR("DDCOLOR_MONO should not happen!\n");
653 /* We are already in this mode */
656 ERR("Unknown color model!\n");
660 D3DRENDERSTATETYPE rs;
661 switch (dwLightStateType) {
663 case D3DLIGHTSTATE_AMBIENT: /* 2 */
664 rs = D3DRENDERSTATE_AMBIENT;
666 case D3DLIGHTSTATE_FOGMODE: /* 4 */
667 rs = D3DRENDERSTATE_FOGVERTEXMODE;
669 case D3DLIGHTSTATE_FOGSTART: /* 5 */
670 rs = D3DRENDERSTATE_FOGSTART;
672 case D3DLIGHTSTATE_FOGEND: /* 6 */
673 rs = D3DRENDERSTATE_FOGEND;
675 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
676 rs = D3DRENDERSTATE_FOGDENSITY;
678 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
679 rs = D3DRENDERSTATE_COLORVERTEX;
685 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
692 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
695 case D3DPT_POINTLIST:
696 TRACE("Start POINTS\n");
701 TRACE("Start LINES\n");
705 case D3DPT_LINESTRIP:
706 TRACE("Start LINE_STRIP\n");
707 glBegin(GL_LINE_STRIP);
710 case D3DPT_TRIANGLELIST:
711 TRACE("Start TRIANGLES\n");
712 glBegin(GL_TRIANGLES);
715 case D3DPT_TRIANGLESTRIP:
716 TRACE("Start TRIANGLE_STRIP\n");
717 glBegin(GL_TRIANGLE_STRIP);
720 case D3DPT_TRIANGLEFAN:
721 TRACE("Start TRIANGLE_FAN\n");
722 glBegin(GL_TRIANGLE_FAN);
726 TRACE("Unhandled primitive\n");
731 /* This function calculate the Z coordinate from Zproj */
732 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
735 /* Assume that X = Y = 0 and W = 1 */
736 a = This->proj_mat->_33;
737 b = This->proj_mat->_34;
738 c = This->proj_mat->_43;
739 d = This->proj_mat->_44;
740 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
741 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
742 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
744 return (d*Zproj - c) / (a - b*Zproj);
747 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
750 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
752 for (i = 0; i < 3; i++) {
753 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
755 for (elt = 0; elt < 0x10000; elt++) {
756 /* We apply the fog transformation and cache the result */
757 DWORD fog_intensity = elt & 0xFF;
758 DWORD vertex_color = (elt >> 8) & 0xFF;
759 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
764 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
765 BOOLEAN vertex_transformed,
766 BOOLEAN vertex_lit) {
767 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
769 /* Puts GL in the correct lighting / transformation mode */
770 if ((vertex_transformed == FALSE) &&
771 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
772 /* Need to put the correct transformation again if we go from Transformed
773 vertices to non-transformed ones.
775 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
776 This->world_mat, This->view_mat, This->proj_mat);
777 glThis->transform_state = GL_TRANSFORM_NORMAL;
779 } else if ((vertex_transformed == TRUE) &&
780 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
781 /* Set our orthographic projection */
782 glThis->transform_state = GL_TRANSFORM_ORTHO;
783 d3ddevice_set_ortho(This);
786 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
787 if no fogging state change occured */
788 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
789 if (vertex_transformed == TRUE) {
791 /* Now check if our fog_table still corresponds to the current vertex color.
792 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
793 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
794 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
795 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
796 /* We need to rebuild our fog table.... */
797 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
800 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
801 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
802 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
803 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
804 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
806 if (vertex_lit == FALSE) {
807 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
808 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
810 /* Special case of 'pixel fog' */
811 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
812 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
823 /* Handle the 'no-normal' case */
824 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
825 glEnable(GL_LIGHTING);
827 glDisable(GL_LIGHTING);
829 /* Handle the code for pre-vertex material properties */
830 if (vertex_transformed == FALSE) {
831 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
832 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
833 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
834 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
835 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
836 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
837 glEnable(GL_COLOR_MATERIAL);
844 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
845 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
847 D3DDRAWPRIMITIVESTRIDEDDATA strided;
851 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
852 strided.position.dwStride = sizeof(D3DVERTEX);
853 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
854 strided.normal.dwStride = sizeof(D3DVERTEX);
855 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
856 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
857 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
860 case D3DVT_LVERTEX: {
861 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
862 strided.position.dwStride = sizeof(D3DLVERTEX);
863 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
864 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
865 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
866 strided.specular.dwStride = sizeof(D3DLVERTEX);
867 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
868 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
869 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
872 case D3DVT_TLVERTEX: {
873 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
874 strided.position.dwStride = sizeof(D3DTLVERTEX);
875 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
876 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
877 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
878 strided.specular.dwStride = sizeof(D3DTLVERTEX);
879 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
880 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
881 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
885 FIXME("Unhandled vertex type %08x\n", d3dvt);
891 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
892 D3DPRIMITIVETYPE d3dptPrimitiveType,
893 D3DVERTEXTYPE d3dvtVertexType,
898 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
900 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
901 if (TRACE_ON(ddraw)) {
902 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
905 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
911 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
912 D3DPRIMITIVETYPE d3dptPrimitiveType,
913 D3DVERTEXTYPE d3dvtVertexType,
920 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
921 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
922 if (TRACE_ON(ddraw)) {
923 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
926 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
932 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
933 LPD3DEXECUTEBUFFERDESC lpDesc,
934 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
937 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
938 IDirect3DExecuteBufferImpl *ret;
941 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
943 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
944 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
946 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
951 /* These are the various handler used in the generic path */
952 inline static void handle_xyz(D3DVALUE *coords) {
955 inline static void handle_xyzrhw(D3DVALUE *coords) {
956 if (coords[3] < 1e-8)
959 GLfloat w = 1.0 / coords[3];
961 glVertex4f(coords[0] * w,
967 inline static void handle_normal(D3DVALUE *coords) {
971 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
972 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
973 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
974 glColor4ub((*color >> 16) & 0xFF,
975 (*color >> 8) & 0xFF,
976 (*color >> 0) & 0xFF,
977 (*color >> 24) & 0xFF);
979 glColor3ub((*color >> 16) & 0xFF,
980 (*color >> 8) & 0xFF,
981 (*color >> 0) & 0xFF);
985 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
986 glColor4ub((*color >> 16) & 0xFF,
987 (*color >> 8) & 0xFF,
988 (*color >> 0) & 0xFF,
989 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
992 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
993 if ((lighted == FALSE) &&
994 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
995 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
996 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
997 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
998 handle_diffuse_base(sb, color);
1000 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1001 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1002 handle_diffuse_base(sb, color);
1004 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1005 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1006 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1007 handle_diffuse_base(sb, color);
1009 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1010 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1011 handle_diffuse_base(sb, color);
1014 handle_diffuse_base(sb, color);
1018 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1019 if ((lighted == FALSE) &&
1020 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1021 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1022 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1023 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1024 handle_specular_base(sb, color);
1026 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1027 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1028 handle_specular_base(sb, color);
1030 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1031 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1032 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1033 handle_specular_base(sb, color);
1035 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1036 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1037 handle_specular_base(sb, color);
1040 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1043 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1044 if (lighted == TRUE) {
1045 DWORD color = *color_d;
1046 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1047 /* Special case where the specular value is used to do fogging */
1048 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1049 color &= 0xFF000000; /* Only keep the alpha component */
1050 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1051 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1052 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1054 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1055 /* Standard specular value in transformed mode. TODO */
1057 handle_diffuse_base(sb, &color);
1059 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1060 handle_diffuse(sb, color_d, FALSE);
1061 handle_specular(sb, color_s, FALSE);
1063 /* In that case, only put the diffuse color... */
1064 handle_diffuse_base(sb, color_d);
1069 inline static void handle_texture(D3DVALUE *coords) {
1070 glTexCoord2fv(coords);
1072 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1073 /* For the moment, draw only the first texture.. */
1074 if (tex_index == 0) glTexCoord2fv(coords);
1077 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1078 D3DPRIMITIVETYPE d3dptPrimitiveType,
1079 DWORD d3dvtVertexType,
1080 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1081 DWORD dwVertexCount,
1086 BOOLEAN vertex_lighted = FALSE;
1087 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1088 int num_active_stages = 0;
1090 /* Compute the number of active texture stages */
1091 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1093 /* This is to prevent 'thread contention' between a thread locking the device and another
1094 doing 3D display on it... */
1095 EnterCriticalSection(&(This->crit));
1097 if (TRACE_ON(ddraw)) {
1098 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1103 /* Just a hack for now.. Will have to find better algorithm :-/ */
1104 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1105 vertex_lighted = TRUE;
1107 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1110 draw_primitive_handle_GL_state(This,
1111 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1113 draw_primitive_start_GL(d3dptPrimitiveType);
1115 /* Some fast paths first before the generic case.... */
1116 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1119 for (index = 0; index < dwIndexCount; index++) {
1120 int i = (dwIndices == NULL) ? index : dwIndices[index];
1122 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1123 D3DVALUE *tex_coord =
1124 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1125 D3DVALUE *position =
1126 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1128 handle_normal(normal);
1129 handle_texture(tex_coord);
1130 handle_xyz(position);
1132 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1133 position[0], position[1], position[2],
1134 normal[0], normal[1], normal[2],
1135 tex_coord[0], tex_coord[1]);
1137 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1140 for (index = 0; index < dwIndexCount; index++) {
1141 int i = (dwIndices == NULL) ? index : dwIndices[index];
1143 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1145 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1146 D3DVALUE *tex_coord =
1147 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1148 D3DVALUE *position =
1149 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1151 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1152 handle_texture(tex_coord);
1153 handle_xyzrhw(position);
1155 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1156 position[0], position[1], position[2], position[3],
1157 (*color_d >> 16) & 0xFF,
1158 (*color_d >> 8) & 0xFF,
1159 (*color_d >> 0) & 0xFF,
1160 (*color_d >> 24) & 0xFF,
1161 (*color_s >> 16) & 0xFF,
1162 (*color_s >> 8) & 0xFF,
1163 (*color_s >> 0) & 0xFF,
1164 (*color_s >> 24) & 0xFF,
1165 tex_coord[0], tex_coord[1]);
1167 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1168 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1169 /* This is the 'slow path' but that should support all possible vertex formats out there...
1170 Note that people should write a fast path for all vertex formats out there...
1173 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1174 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1176 for (index = 0; index < dwIndexCount; index++) {
1177 int i = (dwIndices == NULL) ? index : dwIndices[index];
1180 if (d3dvtVertexType & D3DFVF_NORMAL) {
1182 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1183 handle_normal(normal);
1185 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1187 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1190 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1192 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1194 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1195 handle_specular(&(This->state_block), color_s, vertex_lighted);
1196 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1198 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1199 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1203 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1204 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1205 if (tex_index >= num_tex_index) {
1206 handle_textures((D3DVALUE *) no_index, tex_stage);
1208 D3DVALUE *tex_coord =
1209 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1210 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1211 handle_textures(tex_coord, tex_stage);
1215 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1216 D3DVALUE *position =
1217 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1218 handle_xyz(position);
1219 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1220 D3DVALUE *position =
1221 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1222 handle_xyzrhw(position);
1225 if (TRACE_ON(ddraw_geom)) {
1228 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1229 D3DVALUE *position =
1230 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1231 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1232 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1233 D3DVALUE *position =
1234 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1235 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1237 if (d3dvtVertexType & D3DFVF_NORMAL) {
1239 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1240 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1242 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1244 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1245 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1246 (*color_d >> 16) & 0xFF,
1247 (*color_d >> 8) & 0xFF,
1248 (*color_d >> 0) & 0xFF,
1249 (*color_d >> 24) & 0xFF);
1251 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1253 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1254 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1255 (*color_s >> 16) & 0xFF,
1256 (*color_s >> 8) & 0xFF,
1257 (*color_s >> 0) & 0xFF,
1258 (*color_s >> 24) & 0xFF);
1260 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1261 D3DVALUE *tex_coord =
1262 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1263 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1264 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1266 TRACE_(ddraw_geom)("\n");
1270 ERR(" matrix weighting not handled yet....\n");
1275 /* Whatever the case, disable the color material stuff */
1276 glDisable(GL_COLOR_MATERIAL);
1281 LeaveCriticalSection(&(This->crit));
1285 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1286 D3DPRIMITIVETYPE d3dptPrimitiveType,
1287 DWORD d3dvtVertexType,
1289 DWORD dwVertexCount,
1292 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1293 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1295 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1296 if (TRACE_ON(ddraw)) {
1297 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1300 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1301 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1307 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1308 D3DPRIMITIVETYPE d3dptPrimitiveType,
1309 DWORD d3dvtVertexType,
1311 DWORD dwVertexCount,
1316 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1317 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1319 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1320 if (TRACE_ON(ddraw)) {
1321 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1324 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1325 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1331 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1332 D3DPRIMITIVETYPE d3dptPrimitiveType,
1334 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1335 DWORD dwVertexCount,
1338 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1340 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1341 if (TRACE_ON(ddraw)) {
1342 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1344 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1350 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1351 D3DPRIMITIVETYPE d3dptPrimitiveType,
1353 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1354 DWORD dwVertexCount,
1359 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1361 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1362 if (TRACE_ON(ddraw)) {
1363 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1366 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1372 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1373 D3DPRIMITIVETYPE d3dptPrimitiveType,
1374 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1375 DWORD dwStartVertex,
1376 DWORD dwNumVertices,
1379 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1380 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1381 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1383 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1384 if (TRACE_ON(ddraw)) {
1385 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1388 if (vb_impl->processed == TRUE) {
1389 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1390 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1392 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1393 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1394 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1396 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1397 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1400 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1401 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1408 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1409 D3DPRIMITIVETYPE d3dptPrimitiveType,
1410 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1411 DWORD dwStartVertex,
1412 DWORD dwNumVertices,
1417 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1418 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1419 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1421 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1422 if (TRACE_ON(ddraw)) {
1423 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1426 if (vb_impl->processed == TRUE) {
1427 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1428 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1430 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1431 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1432 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1434 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1435 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1438 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1439 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1446 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1450 if (dwMipState == D3DTFP_NONE) {
1451 switch (dwMinState) {
1452 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1453 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1454 default: gl_state = GL_LINEAR; break;
1456 } else if (dwMipState == D3DTFP_POINT) {
1457 switch (dwMinState) {
1458 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1459 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1460 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1463 switch (dwMinState) {
1464 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1465 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1466 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1473 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1479 gl_state = GL_NEAREST;
1482 gl_state = GL_LINEAR;
1485 gl_state = GL_LINEAR;
1491 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1493 handle_color_alpha_args(DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1495 BOOLEAN is_complement = FALSE;
1496 BOOLEAN is_alpha_replicate = FALSE;
1497 BOOLEAN handled = TRUE;
1499 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1503 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1504 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1509 if (tex_op == D3DTOP_SELECTARG2) {
1513 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1514 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1519 if (tex_op == D3DTOP_SELECTARG2) {
1524 if (dwState & D3DTA_COMPLEMENT) {
1525 is_complement = TRUE;
1527 if (dwState & D3DTA_ALPHAREPLICATE) {
1528 is_alpha_replicate = TRUE;
1530 dwState &= D3DTA_SELECTMASK;
1531 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1532 dwState = D3DTA_DIFFUSE;
1536 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1537 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1538 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1539 case D3DTA_TFACTOR: src = GL_CONSTANT_EXT; FIXME(" no handling yet of setting of constant value !\n"); break;
1540 default: src = GL_TEXTURE; handled = FALSE; break;
1544 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1545 if (is_alpha_replicate) {
1546 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1548 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1551 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1552 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1559 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1561 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1564 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1568 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1570 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1572 switch (d3dTexStageStateType) {
1573 #define GEN_CASE(a) case a: type = #a; break
1574 GEN_CASE(D3DTSS_COLOROP);
1575 GEN_CASE(D3DTSS_COLORARG1);
1576 GEN_CASE(D3DTSS_COLORARG2);
1577 GEN_CASE(D3DTSS_ALPHAOP);
1578 GEN_CASE(D3DTSS_ALPHAARG1);
1579 GEN_CASE(D3DTSS_ALPHAARG2);
1580 GEN_CASE(D3DTSS_BUMPENVMAT00);
1581 GEN_CASE(D3DTSS_BUMPENVMAT01);
1582 GEN_CASE(D3DTSS_BUMPENVMAT10);
1583 GEN_CASE(D3DTSS_BUMPENVMAT11);
1584 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1585 GEN_CASE(D3DTSS_ADDRESS);
1586 GEN_CASE(D3DTSS_ADDRESSU);
1587 GEN_CASE(D3DTSS_ADDRESSV);
1588 GEN_CASE(D3DTSS_BORDERCOLOR);
1589 GEN_CASE(D3DTSS_MAGFILTER);
1590 GEN_CASE(D3DTSS_MINFILTER);
1591 GEN_CASE(D3DTSS_MIPFILTER);
1592 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1593 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1594 GEN_CASE(D3DTSS_MAXANISOTROPY);
1595 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1596 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1597 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1599 default: type = "UNKNOWN";
1602 /* Store the values in the state array */
1603 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1604 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1605 /* Some special cases when one state modifies more than one... */
1606 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1607 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1608 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1611 switch (d3dTexStageStateType) {
1612 case D3DTSS_MINFILTER:
1613 case D3DTSS_MIPFILTER:
1614 if (TRACE_ON(ddraw)) {
1615 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1616 switch ((D3DTEXTUREMINFILTER) dwState) {
1617 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1618 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1619 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1622 switch ((D3DTEXTUREMIPFILTER) dwState) {
1623 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1624 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1625 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1626 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1631 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1632 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1633 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1636 case D3DTSS_MAGFILTER:
1637 if (TRACE_ON(ddraw)) {
1638 switch ((D3DTEXTUREMAGFILTER) dwState) {
1639 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1640 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1641 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1644 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1647 case D3DTSS_ADDRESS:
1648 case D3DTSS_ADDRESSU:
1649 case D3DTSS_ADDRESSV: {
1650 GLenum arg = GL_REPEAT; /* Default value */
1651 switch ((D3DTEXTUREADDRESS) dwState) {
1652 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1653 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1654 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1655 #if defined(GL_VERSION_1_4)
1656 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1657 #elif defined(GL_ARB_texture_mirrored_repeat)
1658 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1660 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1662 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1663 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1664 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1665 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1666 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1670 case D3DTSS_ALPHAOP:
1671 case D3DTSS_COLOROP: {
1673 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1678 #define GEN_CASE(a) case a: value = #a; break
1679 GEN_CASE(D3DTOP_DISABLE);
1680 GEN_CASE(D3DTOP_SELECTARG1);
1681 GEN_CASE(D3DTOP_SELECTARG2);
1682 GEN_CASE(D3DTOP_MODULATE);
1683 GEN_CASE(D3DTOP_MODULATE2X);
1684 GEN_CASE(D3DTOP_MODULATE4X);
1685 GEN_CASE(D3DTOP_ADD);
1686 GEN_CASE(D3DTOP_ADDSIGNED);
1687 GEN_CASE(D3DTOP_ADDSIGNED2X);
1688 GEN_CASE(D3DTOP_SUBTRACT);
1689 GEN_CASE(D3DTOP_ADDSMOOTH);
1690 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1691 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1692 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1693 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1694 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1695 GEN_CASE(D3DTOP_PREMODULATE);
1696 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1697 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1698 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1699 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1700 GEN_CASE(D3DTOP_BUMPENVMAP);
1701 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1702 GEN_CASE(D3DTOP_DOTPRODUCT3);
1703 GEN_CASE(D3DTOP_FORCE_DWORD);
1705 default: value = "UNKNOWN";
1708 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1709 glDisable(GL_TEXTURE_2D);
1710 TRACE(" disabling 2D texturing.\n");
1712 /* Re-enable texturing */
1713 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1714 glEnable(GL_TEXTURE_2D);
1715 TRACE(" enabling 2D texturing.\n");
1718 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1719 if (dwState != D3DTOP_DISABLE) {
1720 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1723 /* Now set up the operand correctly */
1725 case D3DTOP_DISABLE:
1726 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1727 and it works, so ignore this op */
1728 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1731 case D3DTOP_SELECTARG1:
1732 case D3DTOP_SELECTARG2:
1733 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1736 case D3DTOP_MODULATE4X:
1737 scale = scale * 2; /* Drop through */
1738 case D3DTOP_MODULATE2X:
1739 scale = scale * 2; /* Drop through */
1740 case D3DTOP_MODULATE:
1741 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1745 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1748 case D3DTOP_ADDSIGNED2X:
1749 scale = scale * 2; /* Drop through */
1750 case D3DTOP_ADDSIGNED:
1751 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1760 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1761 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1762 /* Switch the arguments if needed... */
1763 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1764 handle_color_alpha_args(dwStage, D3DTSS_COLORARG1,
1765 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1767 handle_color_alpha_args(dwStage, D3DTSS_COLORARG2,
1768 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1771 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG1,
1772 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1774 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG2,
1775 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1781 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1782 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1784 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1786 TRACE(" Stage type is : %s => %s\n", type, value);
1788 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1792 case D3DTSS_COLORARG1:
1793 case D3DTSS_COLORARG2:
1794 case D3DTSS_ALPHAARG1:
1795 case D3DTSS_ALPHAARG2: {
1796 const char *value, *value_comp = "", *value_alpha = "";
1798 D3DTEXTUREOP tex_op;
1800 switch (dwState & D3DTA_SELECTMASK) {
1801 #define GEN_CASE(a) case a: value = #a; break
1802 GEN_CASE(D3DTA_DIFFUSE);
1803 GEN_CASE(D3DTA_CURRENT);
1804 GEN_CASE(D3DTA_TEXTURE);
1805 GEN_CASE(D3DTA_TFACTOR);
1806 GEN_CASE(D3DTA_SPECULAR);
1808 default: value = "UNKNOWN";
1810 if (dwState & D3DTA_COMPLEMENT) {
1811 value_comp = " | D3DTA_COMPLEMENT";
1813 if (dwState & D3DTA_ALPHAREPLICATE) {
1814 value_alpha = " | D3DTA_ALPHAREPLICATE";
1817 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1818 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1820 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1823 handled = handle_color_alpha_args(dwStage, d3dTexStageStateType, dwState, tex_op);
1826 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1828 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1832 case D3DTSS_MIPMAPLODBIAS: {
1833 D3DVALUE value = *((D3DVALUE *) &dwState);
1834 BOOLEAN handled = TRUE;
1840 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1842 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1846 case D3DTSS_MAXMIPLEVEL:
1848 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1850 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1854 case D3DTSS_BORDERCOLOR: {
1857 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1858 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1859 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1860 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1862 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1865 case D3DTSS_TEXCOORDINDEX: {
1866 BOOLEAN handled = TRUE;
1869 switch (dwState & 0xFFFF0000) {
1870 #define GEN_CASE(a) case a: value = #a; break
1871 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1872 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1873 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1874 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1876 default: value = "UNKNOWN";
1878 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1882 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1884 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1888 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1889 const char *projected = "", *value;
1890 BOOLEAN handled = TRUE;
1891 switch (dwState & 0xFF) {
1892 #define GEN_CASE(a) case a: value = #a; break
1893 GEN_CASE(D3DTTFF_DISABLE);
1894 GEN_CASE(D3DTTFF_COUNT1);
1895 GEN_CASE(D3DTTFF_COUNT2);
1896 GEN_CASE(D3DTTFF_COUNT3);
1897 GEN_CASE(D3DTTFF_COUNT4);
1899 default: value = "UNKNOWN";
1901 if (dwState & D3DTTFF_PROJECTED)
1902 projected = " | D3DTTFF_PROJECTED";
1904 if (dwState != D3DTTFF_DISABLE)
1907 if (handled == TRUE) {
1908 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1910 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1915 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1923 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1925 LPDIRECTDRAWSURFACE7 lpTexture2)
1927 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1929 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1931 if (dwStage > 0) return DD_OK;
1933 if (This->current_texture[dwStage] != NULL) {
1934 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1938 if (lpTexture2 == NULL) {
1939 This->current_texture[dwStage] = NULL;
1941 TRACE(" disabling 2D texturing.\n");
1942 glBindTexture(GL_TEXTURE_2D, 0);
1943 glDisable(GL_TEXTURE_2D);
1945 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1946 GLint max_mip_level;
1948 This->current_texture[dwStage] = tex_impl;
1949 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1951 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
1952 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
1953 glEnable(GL_TEXTURE_2D);
1954 TRACE(" enabling 2D texturing.\n");
1956 gltex_upload_texture(tex_impl);
1958 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
1961 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
1964 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
1965 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
1966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1967 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1968 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1969 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
1977 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1978 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1980 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1981 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1983 fill_opengl_caps_7(lpD3DHELDevDesc);
1985 TRACE(" returning caps : no dump function yet.\n");
1991 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
1992 LPD3DMATERIAL7 lpMat)
1994 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1995 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
1997 if (TRACE_ON(ddraw)) {
1998 TRACE(" material is : \n");
1999 dump_D3DMATERIAL7(lpMat);
2002 This->current_material = *lpMat;
2004 glMaterialfv(GL_FRONT_AND_BACK,
2006 (float *) &(This->current_material.u.diffuse));
2007 glMaterialfv(GL_FRONT_AND_BACK,
2009 (float *) &(This->current_material.u1.ambient));
2010 glMaterialfv(GL_FRONT_AND_BACK,
2012 (float *) &(This->current_material.u2.specular));
2013 glMaterialfv(GL_FRONT_AND_BACK,
2015 (float *) &(This->current_material.u3.emissive));
2016 glMaterialf(GL_FRONT_AND_BACK,
2018 This->current_material.u4.power); /* Not sure about this... */
2025 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2027 LPD3DLIGHT7 lpLight)
2029 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2030 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2032 if (TRACE_ON(ddraw)) {
2033 TRACE(" setting light : \n");
2034 dump_D3DLIGHT7(lpLight);
2037 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2038 This->set_lights |= 0x00000001 << dwLightIndex;
2039 This->light_parameters[dwLightIndex] = *lpLight;
2041 switch (lpLight->dltType) {
2042 case D3DLIGHT_DIRECTIONAL: {
2044 float cut_off = 180.0;
2046 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2047 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2048 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2049 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2051 direction[0] = lpLight->dvDirection.u1.x;
2052 direction[1] = lpLight->dvDirection.u2.y;
2053 direction[2] = lpLight->dvDirection.u3.z;
2055 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
2058 case D3DLIGHT_POINT: {
2060 float cut_off = 180.0;
2062 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2063 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2064 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2065 position[0] = lpLight->dvPosition.u1.x;
2066 position[1] = lpLight->dvPosition.u2.y;
2067 position[2] = lpLight->dvPosition.u3.z;
2069 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2070 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2071 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2072 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2073 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2076 case D3DLIGHT_SPOT: {
2079 float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
2081 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2082 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2083 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2085 direction[0] = lpLight->dvDirection.u1.x;
2086 direction[1] = lpLight->dvDirection.u2.y;
2087 direction[2] = lpLight->dvDirection.u3.z;
2089 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
2090 position[0] = lpLight->dvPosition.u1.x;
2091 position[1] = lpLight->dvPosition.u2.y;
2092 position[2] = lpLight->dvPosition.u3.z;
2094 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2095 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2096 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2097 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2098 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2099 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
2100 if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
2101 WARN("dvTheta not fully supported yet !\n");
2105 default: WARN(" light type not handled yet...\n");
2112 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2116 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2117 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2119 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2122 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2123 /* Set the default parameters.. */
2124 TRACE(" setting default light parameters...\n");
2125 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2127 glEnable(GL_LIGHT0 + dwLightIndex);
2129 glDisable(GL_LIGHT0 + dwLightIndex);
2136 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2138 ICOM_THIS(IDirect3DDeviceImpl,iface);
2141 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2143 if (dwIndex>=This->max_clipping_planes) {
2144 return DDERR_INVALIDPARAMS;
2147 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2149 memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2150 plane[0] = pPlaneEquation[0];
2151 plane[1] = pPlaneEquation[1];
2152 plane[2] = pPlaneEquation[2];
2153 plane[3] = pPlaneEquation[3];
2155 /* XXX: is here also code needed to handle the transformation of the world? */
2156 glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
2161 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2162 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2164 # define XCAST(fun) (void*)
2167 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2169 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2170 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2171 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2172 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2173 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2174 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2175 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2176 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2177 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2178 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2179 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2180 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2181 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2182 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2183 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
2184 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2185 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2186 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2187 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2188 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2189 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2190 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2191 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2192 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2193 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2194 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2195 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2196 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2197 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2198 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2199 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2200 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2201 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2202 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2203 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2204 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2205 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2206 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2207 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2208 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2209 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2210 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2211 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2212 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2213 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2214 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2215 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2216 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2217 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2218 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2221 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2226 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2227 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2229 # define XCAST(fun) (void*)
2232 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2234 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2235 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2236 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2237 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2238 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2239 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2240 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2241 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2242 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2243 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2244 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2245 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2246 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2247 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2248 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2249 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2250 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2251 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2252 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2253 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2254 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2255 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2256 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2257 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2258 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2259 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2260 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2261 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2262 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2263 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2264 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2265 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2266 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2267 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2268 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2269 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2270 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2271 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2272 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2273 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2274 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2275 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2276 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2279 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2284 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2285 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2287 # define XCAST(fun) (void*)
2290 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2292 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2293 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2294 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2295 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2296 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2297 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2298 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2299 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2300 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2301 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2302 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2303 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2304 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2305 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2306 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2307 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2308 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2309 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2310 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2311 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2312 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2313 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2314 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2315 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2316 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2317 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2318 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2319 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2320 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2321 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2322 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2323 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2324 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2325 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2328 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2333 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2334 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2336 # define XCAST(fun) (void*)
2339 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2341 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2342 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2343 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2344 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2345 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2346 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2347 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2348 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2349 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2350 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2351 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2352 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2353 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2354 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2355 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2356 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2357 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2358 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2359 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2360 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2361 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2362 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2363 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2366 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2370 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2379 GLfloat old_z_clear_value;
2380 GLbitfield bitfield = 0;
2381 GLint old_stencil_clear_value;
2382 GLfloat old_color_clear_value[4];
2384 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2385 if (TRACE_ON(ddraw)) {
2388 TRACE(" rectangles : \n");
2389 for (i = 0; i < dwCount; i++) {
2390 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2396 WARN(" Warning, this function only for now clears the whole screen...\n");
2399 /* Clears the screen */
2401 if (dwFlags & D3DCLEAR_ZBUFFER) {
2402 bitfield |= GL_DEPTH_BUFFER_BIT;
2403 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2404 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2405 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2407 TRACE(" depth value : %f\n", dvZ);
2409 if (dwFlags & D3DCLEAR_STENCIL) {
2410 bitfield |= GL_STENCIL_BUFFER_BIT;
2411 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2412 glClearStencil(dwStencil);
2413 TRACE(" stencil value : %ld\n", dwStencil);
2415 if (dwFlags & D3DCLEAR_TARGET) {
2416 bitfield |= GL_COLOR_BUFFER_BIT;
2417 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2418 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2419 ((dwColor >> 8) & 0xFF) / 255.0,
2420 ((dwColor >> 0) & 0xFF) / 255.0,
2421 ((dwColor >> 24) & 0xFF) / 255.0);
2422 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2427 if (dwFlags & D3DCLEAR_ZBUFFER) {
2429 glClearDepth(old_z_clear_value);
2431 if (dwFlags & D3DCLEAR_STENCIL) {
2432 bitfield |= GL_STENCIL_BUFFER_BIT;
2433 glClearStencil(old_stencil_clear_value);
2435 if (dwFlags & D3DCLEAR_TARGET) {
2436 bitfield |= GL_COLOR_BUFFER_BIT;
2437 glClearColor(old_color_clear_value[0],
2438 old_color_clear_value[1],
2439 old_color_clear_value[2],
2440 old_color_clear_value[3]);
2449 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2450 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2451 DWORD dwFlags, LPDDBLTFX lpbltfx)
2453 if (dwFlags & DDBLT_COLORFILL) {
2454 /* This is easy to handle for the D3D Device... */
2455 DWORD color = lpbltfx->u5.dwFillColor;
2456 TRACE(" executing D3D Device override.\n");
2457 d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2460 return DDERR_INVALIDPARAMS;
2464 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2465 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2466 LPRECT rsrc, DWORD trans)
2468 return DDERR_INVALIDPARAMS;
2472 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2474 GLfloat height, width;
2475 GLfloat trans_mat[16];
2477 width = This->surface->surface_desc.dwWidth;
2478 height = This->surface->surface_desc.dwHeight;
2480 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2481 to OpenGL screen coordinates (ie the upper left corner is not the same).
2482 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2483 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2484 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2485 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2486 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2487 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2489 glMatrixMode(GL_MODELVIEW);
2491 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2492 Correctness Tips section).
2494 Basically, from what I understood, if the game does not filter the font texture,
2495 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2496 one and we will have strange artifacts (as the rounding and stuff may give different results
2497 for different pixels, ie sometimes take the left pixel, sometimes the right).
2499 glTranslatef(0.375, 0.375, 0);
2500 glMatrixMode(GL_PROJECTION);
2501 glLoadMatrixf(trans_mat);
2505 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2506 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2508 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2509 glMatrixMode(GL_MODELVIEW);
2510 glLoadMatrixf((float *) view_mat);
2511 glMultMatrixf((float *) world_mat);
2513 if ((matrices & PROJMAT_CHANGED) != 0) {
2514 glMatrixMode(GL_PROJECTION);
2515 glLoadMatrixf((float *) proj_mat);
2520 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2522 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2523 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2524 /* This will force an update of the transform state at the next drawing. */
2525 glThis->transform_state = GL_TRANSFORM_NONE;
2529 /* TODO for both these functions :
2530 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2531 by other OpenGL code in D3D
2532 - handle the case where no 'Begin / EndScene' was done between two locks
2533 - handle the rectangles in the unlock too
2534 - handle pitch correctly...
2536 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2538 /* Try to acquire the device critical section */
2539 EnterCriticalSection(&(This->d3ddevice->crit));
2541 /* Then check if we need to do anything */
2542 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
2547 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
2551 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2554 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2555 /* Application wants to lock the front buffer */
2556 glReadBuffer(GL_FRONT);
2557 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2558 /* Application wants to lock the back buffer */
2559 glReadBuffer(GL_BACK);
2561 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
2564 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2565 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2567 WARN(" unsupported pixel format.\n");
2571 if (pRect == NULL) {
2574 loc_rect.bottom = This->surface_desc.dwHeight;
2575 loc_rect.right = This->surface_desc.dwWidth;
2580 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
2581 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
2582 + loc_rect.top * This->surface_desc.u1.lPitch
2583 + loc_rect.left * GET_BPP(This->surface_desc)));
2585 glReadBuffer(prev_read);
2590 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2592 /* First, check if we need to do anything */
2593 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
2597 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
2601 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2603 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2604 /* Application wants to lock the front buffer */
2605 glDrawBuffer(GL_FRONT);
2606 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2607 /* Application wants to lock the back buffer */
2608 glDrawBuffer(GL_BACK);
2610 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
2613 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2614 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2616 WARN(" unsupported pixel format.\n");
2619 /* And 'frees' the device critical section */
2620 LeaveCriticalSection(&(This->d3ddevice->crit));
2623 glRasterPos2f(0.0, 0.0);
2625 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
2626 GL_RGB, buffer_type, This->surface_desc.lpSurface);
2628 glDrawBuffer(prev_draw);
2633 /* And 'frees' the device critical section */
2634 LeaveCriticalSection(&(This->d3ddevice->crit));
2638 apply_texture_state(IDirect3DDeviceImpl *This)
2642 /* Initialize texture stages states */
2643 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2644 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
2645 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
2646 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
2647 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
2654 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2656 IDirect3DDeviceImpl *object;
2657 IDirect3DDeviceGLImpl *gl_object;
2658 IDirectDrawSurfaceImpl *surf;
2662 XVisualInfo template;
2663 GLenum buffer = GL_FRONT;
2665 GLint max_clipping_planes = 0;
2667 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2668 if (object == NULL) return DDERR_OUTOFMEMORY;
2670 gl_object = (IDirect3DDeviceGLImpl *) object;
2674 object->surface = surface;
2675 object->set_context = set_context;
2676 object->clear = d3ddevice_clear;
2677 object->set_matrices = d3ddevice_set_matrices;
2678 object->matrices_updated = d3ddevice_matrices_updated;
2680 InitializeCriticalSection(&(object->crit));
2682 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2684 device_context = GetDC(surface->ddraw_owner->window);
2685 gl_object->display = get_display(device_context);
2686 gl_object->drawable = get_drawable(device_context);
2687 ReleaseDC(surface->ddraw_owner->window,device_context);
2690 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2691 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2693 HeapFree(GetProcessHeap(), 0, object);
2694 ERR("No visual found !\n");
2696 return DDERR_INVALIDPARAMS;
2698 TRACE(" visual found\n");
2701 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2704 if (gl_object->gl_context == NULL) {
2705 HeapFree(GetProcessHeap(), 0, object);
2706 ERR("Error in context creation !\n");
2708 return DDERR_INVALIDPARAMS;
2710 TRACE(" context created (%p)\n", gl_object->gl_context);
2713 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2714 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2715 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2716 surf->aux_ctx = (LPVOID) gl_object->display;
2717 surf->aux_data = (LPVOID) gl_object->drawable;
2718 surf->aux_flip = opengl_flip;
2723 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2725 TRACE(" no double buffering : drawing on the front buffer\n");
2729 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2730 IDirectDrawSurfaceImpl *surf2;
2731 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
2732 for (; surf2 != NULL; surf2 = surf2->next_attached) {
2733 TRACE(" checking surface %p :", surf2);
2734 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2735 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2736 /* Override the Lock / Unlock function for all these surfaces */
2737 surf2->lock_update = d3ddevice_lock_update;
2738 surf2->unlock_update = d3ddevice_unlock_update;
2739 /* And install also the blt / bltfast overrides */
2740 surf2->aux_blt = d3ddevice_blt;
2741 surf2->aux_bltfast = d3ddevice_bltfast;
2743 TRACE(" overiding direct surface access.\n");
2745 TRACE(" no overide.\n");
2747 surf2->d3ddevice = object;
2751 /* Set the various light parameters */
2752 for (light = 0; light < MAX_LIGHTS; light++) {
2753 /* Only set the fields that are not zero-created */
2754 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2755 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2756 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2757 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2758 object->light_parameters[light].dvDirection.u3.z = 1.0;
2761 /* Allocate memory for the matrices */
2762 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2763 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2764 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2765 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2766 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2767 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2769 /* Initialisation */
2770 TRACE(" setting current context\n");
2772 object->set_context(object);
2774 TRACE(" current context set\n");
2776 /* allocate the clipping planes */
2777 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
2778 if (max_clipping_planes>32) {
2779 object->max_clipping_planes=32;
2781 object->max_clipping_planes = max_clipping_planes;
2783 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
2784 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
2786 glHint(GL_FOG_HINT,GL_NICEST);
2788 glClearColor(0.0, 0.0, 0.0, 0.0);
2789 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2790 glDrawBuffer(buffer);
2791 glReadBuffer(buffer);
2792 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2795 /* fill_device_capabilities(d3d->ddraw); */
2797 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
2798 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2799 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2800 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2804 TRACE(" creating implementation at %p.\n", *obj);
2806 /* And finally warn D3D that this device is now present */
2807 object->d3d->added_device(object->d3d, object);
2809 /* FIXME: Should handle other versions than just 7 */
2810 InitDefaultStateBlock(&object->state_block, 7);
2811 /* Apply default render state and texture stage state values */
2812 apply_render_state(object, &object->state_block);
2813 apply_texture_state(object);
2815 /* And fill the fog table with the default fog value */
2816 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);