2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 #include "mesa_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
56 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
59 #ifndef HAVE_GLEXT_PROTOTYPES
60 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
61 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
62 GLsizei width, GLenum format, GLenum type,
66 const float id_mat[16] = {
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74 D3DPRIMITIVETYPE d3dptPrimitiveType,
75 DWORD d3dvtVertexType,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
86 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
88 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
89 sizeof(display), (LPSTR)&display )) display = NULL;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
99 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
101 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
102 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
108 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
110 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
111 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
113 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
115 if (gl_d3d_dev->state == SURFACE_MEMORY) {
116 d3d_dev->flush_to_framebuffer(d3d_dev, NULL);
118 gl_d3d_dev->state = SURFACE_GL;
119 gl_d3d_dev->front_state = SURFACE_GL;
120 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
126 /*******************************************************************************
127 * OpenGL static functions
129 static void set_context(IDirect3DDeviceImpl* This)
131 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
134 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
135 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
136 ERR("Error in setting current context (context %p drawable %ld)!\n",
137 glThis->gl_context, glThis->drawable);
142 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
144 pc->dwSize = sizeof(*pc);
145 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
146 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
147 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
148 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
149 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
150 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
151 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
152 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
153 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
154 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
155 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
156 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
157 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
158 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
159 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
160 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
161 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
162 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
163 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
164 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
165 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
166 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
167 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
168 pc->dwStippleWidth = 32;
169 pc->dwStippleHeight = 32;
172 static void fill_opengl_caps(D3DDEVICEDESC *d1)
174 /* GLint maxlight; */
176 d1->dwSize = sizeof(*d1);
177 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
178 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
179 d1->dcmColorModel = D3DCOLOR_RGB;
180 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
181 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
182 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
183 /* D3D 7 capabilities */
184 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
185 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
186 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
187 d1->bClipping = TRUE;
188 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
189 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
190 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
191 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
192 fill_opengl_primcaps(&(d1->dpcLineCaps));
193 fill_opengl_primcaps(&(d1->dpcTriCaps));
194 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
195 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
196 d1->dwMaxBufferSize = 0;
197 d1->dwMaxVertexCount = 65536;
198 d1->dwMinTextureWidth = 1;
199 d1->dwMinTextureHeight = 1;
200 d1->dwMaxTextureWidth = 1024;
201 d1->dwMaxTextureHeight = 1024;
202 d1->dwMinStippleWidth = 1;
203 d1->dwMinStippleHeight = 1;
204 d1->dwMaxStippleWidth = 32;
205 d1->dwMaxStippleHeight = 32;
206 d1->dwMaxTextureRepeat = 16;
207 d1->dwMaxTextureAspectRatio = 1024;
208 d1->dwMaxAnisotropy = 0;
209 d1->dvGuardBandLeft = 0.0;
210 d1->dvGuardBandRight = 0.0;
211 d1->dvGuardBandTop = 0.0;
212 d1->dvGuardBandBottom = 0.0;
213 d1->dvExtentsAdjust = 0.0;
214 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
215 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
216 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
217 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
218 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
222 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
226 /* Copy first D3D1/2/3 capabilities */
227 fill_opengl_caps(&d1);
229 /* And fill the D3D7 one with it */
230 d->dwDevCaps = d1.dwDevCaps;
231 d->dpcLineCaps = d1.dpcLineCaps;
232 d->dpcTriCaps = d1.dpcTriCaps;
233 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
234 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
235 d->dwMinTextureWidth = d1.dwMinTextureWidth;
236 d->dwMinTextureHeight = d1.dwMinTextureHeight;
237 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
238 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
239 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
240 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
241 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
242 d->dvGuardBandLeft = d1.dvGuardBandLeft;
243 d->dvGuardBandTop = d1.dvGuardBandTop;
244 d->dvGuardBandRight = d1.dvGuardBandRight;
245 d->dvGuardBandBottom = d1.dvGuardBandBottom;
246 d->dvExtentsAdjust = d1.dvExtentsAdjust;
247 d->dwStencilCaps = d1.dwStencilCaps;
248 d->dwFVFCaps = d1.dwFVFCaps;
249 d->dwTextureOpCaps = d1.dwTextureOpCaps;
250 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
251 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
252 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
253 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
254 d->deviceGUID = IID_IDirect3DTnLHalDevice;
255 d->wMaxUserClipPlanes = 1;
256 d->wMaxVertexBlendMatrices = 0;
257 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
258 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
265 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
266 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
268 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
269 const char *ext_string;
270 Mesa_DeviceCapabilities *devcap;
272 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
273 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
276 ext_string = glGetString(GL_EXTENSIONS);
277 /* Query for the ColorTable Extension */
278 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
279 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
280 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
282 TRACE("Color table extension not found.\n");
290 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
292 D3DDEVICEDESC dref, d1, d2;
295 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
296 Let's put the string in a sufficiently sized array in writable memory. */
297 char device_name[50];
298 strcpy(device_name,"direct3d");
300 fill_opengl_caps(&dref);
303 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
304 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
307 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
308 if (ret_value != D3DENUMRET_OK)
312 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
315 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
316 if (ret_value != D3DENUMRET_OK)
319 return D3DENUMRET_OK;
322 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
324 D3DDEVICEDESC7 ddesc;
326 fill_opengl_caps_7(&ddesc);
328 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
330 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
334 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
337 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
339 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
340 if (!--(This->ref)) {
342 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
344 /* Release texture associated with the device */
345 for (i = 0; i < MAX_TEXTURES; i++)
346 if (This->current_texture[i] != NULL)
347 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
349 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
350 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
351 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
352 surf->aux_ctx = NULL;
353 surf->aux_data = NULL;
354 surf->aux_flip = NULL;
358 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
359 IDirectDrawSurfaceImpl *surf2;
360 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
361 for (; surf2 != NULL; surf2 = surf2->next_attached) {
362 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
363 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
364 /* Override the Lock / Unlock function for all these surfaces */
365 surf2->lock_update = surf2->lock_update_prev;
366 surf2->unlock_update = surf2->unlock_update_prev;
367 /* And install also the blt / bltfast overrides */
368 surf2->aux_blt = NULL;
369 surf2->aux_bltfast = NULL;
371 surf2->d3ddevice = NULL;
375 /* And warn the D3D object that this device is no longer active... */
376 This->d3d->removed_device(This->d3d, This);
378 HeapFree(GetProcessHeap(), 0, This->world_mat);
379 HeapFree(GetProcessHeap(), 0, This->view_mat);
380 HeapFree(GetProcessHeap(), 0, This->proj_mat);
382 DeleteCriticalSection(&(This->crit));
385 if (glThis->unlock_tex)
386 glDeleteTextures(1, &(glThis->unlock_tex));
387 glXDestroyContext(glThis->display, glThis->gl_context);
389 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
391 HeapFree(GetProcessHeap(), 0, This);
398 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
399 LPD3DDEVICEDESC lpD3DHWDevDesc,
400 LPD3DDEVICEDESC lpD3DHELDevDesc)
402 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
406 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
408 fill_opengl_caps(&desc);
409 dwSize = lpD3DHWDevDesc->dwSize;
410 memset(lpD3DHWDevDesc, 0, dwSize);
411 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
413 dwSize = lpD3DHELDevDesc->dwSize;
414 memset(lpD3DHELDevDesc, 0, dwSize);
415 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
417 TRACE(" returning caps : (no dump function yet)\n");
422 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
423 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
427 LPDDPIXELFORMAT pformat;
429 /* Do the texture enumeration */
430 sdesc.dwSize = sizeof(DDSURFACEDESC);
431 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
432 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
433 pformat = &(sdesc.ddpfPixelFormat);
434 pformat->dwSize = sizeof(DDPIXELFORMAT);
435 pformat->dwFourCC = 0;
438 /* See argument about the RGBA format for 'packed' texture formats */
439 TRACE("Enumerating GL_RGBA unpacked (32)\n");
440 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
441 pformat->u1.dwRGBBitCount = 32;
442 pformat->u2.dwRBitMask = 0xFF000000;
443 pformat->u3.dwGBitMask = 0x00FF0000;
444 pformat->u4.dwBBitMask = 0x0000FF00;
445 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
446 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
447 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
450 TRACE("Enumerating GL_RGBA unpacked (32)\n");
451 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
452 pformat->u1.dwRGBBitCount = 32;
453 pformat->u2.dwRBitMask = 0x00FF0000;
454 pformat->u3.dwGBitMask = 0x0000FF00;
455 pformat->u4.dwBBitMask = 0x000000FF;
456 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
457 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
458 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
460 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
461 TRACE("Enumerating GL_RGB unpacked (32)\n");
462 pformat->dwFlags = DDPF_RGB;
463 pformat->u1.dwRGBBitCount = 32;
464 pformat->u2.dwRBitMask = 0x00FF0000;
465 pformat->u3.dwGBitMask = 0x0000FF00;
466 pformat->u4.dwBBitMask = 0x000000FF;
467 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
468 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
469 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
472 TRACE("Enumerating GL_RGB unpacked (24)\n");
473 pformat->dwFlags = DDPF_RGB;
474 pformat->u1.dwRGBBitCount = 24;
475 pformat->u2.dwRBitMask = 0x00FF0000;
476 pformat->u3.dwGBitMask = 0x0000FF00;
477 pformat->u4.dwBBitMask = 0x000000FF;
478 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
479 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
480 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
482 /* Note : even if this is an 'emulated' texture format, it needs to be first
483 as some dumb applications seem to rely on that. */
484 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
485 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
486 pformat->u1.dwRGBBitCount = 16;
487 pformat->u2.dwRBitMask = 0x00007C00;
488 pformat->u3.dwGBitMask = 0x000003E0;
489 pformat->u4.dwBBitMask = 0x0000001F;
490 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
491 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
492 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
494 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
495 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
496 pformat->u1.dwRGBBitCount = 16;
497 pformat->u2.dwRBitMask = 0x00000F00;
498 pformat->u3.dwGBitMask = 0x000000F0;
499 pformat->u4.dwBBitMask = 0x0000000F;
500 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
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_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
505 pformat->dwFlags = DDPF_RGB;
506 pformat->u1.dwRGBBitCount = 16;
507 pformat->u2.dwRBitMask = 0x0000F800;
508 pformat->u3.dwGBitMask = 0x000007E0;
509 pformat->u4.dwBBitMask = 0x0000001F;
510 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
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;
514 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
515 pformat->dwFlags = DDPF_RGB;
516 pformat->u1.dwRGBBitCount = 16;
517 pformat->u2.dwRBitMask = 0x00007C00;
518 pformat->u3.dwGBitMask = 0x000003E0;
519 pformat->u4.dwBBitMask = 0x0000001F;
520 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
521 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
522 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
525 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
526 find enumerated, others the last one. And both want to have the ARGB one.
528 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
530 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
531 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
532 pformat->u1.dwRGBBitCount = 16;
533 pformat->u2.dwRBitMask = 0x0000F000;
534 pformat->u3.dwGBitMask = 0x00000F00;
535 pformat->u4.dwBBitMask = 0x000000F0;
536 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
537 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
538 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
540 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
541 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
542 pformat->u1.dwRGBBitCount = 16;
543 pformat->u2.dwRBitMask = 0x0000F800;
544 pformat->u3.dwGBitMask = 0x000007C0;
545 pformat->u4.dwBBitMask = 0x0000003E;
546 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
547 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
548 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
551 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
552 pformat->dwFlags = DDPF_RGB;
553 pformat->u1.dwRGBBitCount = 8;
554 pformat->u2.dwRBitMask = 0x000000E0;
555 pformat->u3.dwGBitMask = 0x0000001C;
556 pformat->u4.dwBBitMask = 0x00000003;
557 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
558 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
559 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
561 TRACE("Enumerating Paletted (8)\n");
562 pformat->dwFlags = DDPF_PALETTEINDEXED8;
563 pformat->u1.dwRGBBitCount = 8;
564 pformat->u2.dwRBitMask = 0x00000000;
565 pformat->u3.dwGBitMask = 0x00000000;
566 pformat->u4.dwBBitMask = 0x00000000;
567 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
568 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
569 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
571 TRACE("End of enumeration\n");
577 d3ddevice_find(IDirect3DImpl *d3d,
578 LPD3DFINDDEVICESEARCH lpD3DDFS,
579 LPD3DFINDDEVICERESULT lplpD3DDevice)
583 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
584 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
585 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
586 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
588 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
589 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
590 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
591 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
592 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
593 TRACE(" no match for this GUID.\n");
594 return DDERR_INVALIDPARAMS;
598 /* Now return our own GUID */
599 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
600 fill_opengl_caps(&desc);
601 lplpD3DDevice->ddHwDesc = desc;
602 lplpD3DDevice->ddSwDesc = desc;
604 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
610 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
611 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
614 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
615 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
616 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
620 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
621 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
624 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
625 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
626 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
630 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
631 D3DRENDERSTATETYPE dwRenderStateType,
634 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
635 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
637 /* Call the render state functions */
638 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
639 set_render_state(This, dwRenderStateType, &This->state_block);
645 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
646 D3DRENDERSTATETYPE dwRenderStateType,
647 LPDWORD lpdwRenderState)
649 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
650 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
652 /* Call the render state functions */
653 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
655 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
661 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
662 D3DLIGHTSTATETYPE dwLightStateType,
665 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
667 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
669 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
670 TRACE("Unexpected Light State Type\n");
671 return DDERR_INVALIDPARAMS;
673 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
674 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
681 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
683 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
684 switch (dwLightState) {
686 ERR("DDCOLOR_MONO should not happen!\n");
689 /* We are already in this mode */
692 ERR("Unknown color model!\n");
696 D3DRENDERSTATETYPE rs;
697 switch (dwLightStateType) {
699 case D3DLIGHTSTATE_AMBIENT: /* 2 */
700 rs = D3DRENDERSTATE_AMBIENT;
702 case D3DLIGHTSTATE_FOGMODE: /* 4 */
703 rs = D3DRENDERSTATE_FOGVERTEXMODE;
705 case D3DLIGHTSTATE_FOGSTART: /* 5 */
706 rs = D3DRENDERSTATE_FOGSTART;
708 case D3DLIGHTSTATE_FOGEND: /* 6 */
709 rs = D3DRENDERSTATE_FOGEND;
711 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
712 rs = D3DRENDERSTATE_FOGDENSITY;
714 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
715 rs = D3DRENDERSTATE_COLORVERTEX;
721 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
728 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
731 case D3DPT_POINTLIST:
732 TRACE("Start POINTS\n");
737 TRACE("Start LINES\n");
741 case D3DPT_LINESTRIP:
742 TRACE("Start LINE_STRIP\n");
743 glBegin(GL_LINE_STRIP);
746 case D3DPT_TRIANGLELIST:
747 TRACE("Start TRIANGLES\n");
748 glBegin(GL_TRIANGLES);
751 case D3DPT_TRIANGLESTRIP:
752 TRACE("Start TRIANGLE_STRIP\n");
753 glBegin(GL_TRIANGLE_STRIP);
756 case D3DPT_TRIANGLEFAN:
757 TRACE("Start TRIANGLE_FAN\n");
758 glBegin(GL_TRIANGLE_FAN);
762 FIXME("Unhandled primitive %08x\n", d3dpt);
767 /* This function calculate the Z coordinate from Zproj */
768 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
771 /* Assume that X = Y = 0 and W = 1 */
772 a = This->proj_mat->_33;
773 b = This->proj_mat->_34;
774 c = This->proj_mat->_43;
775 d = This->proj_mat->_44;
776 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
777 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
778 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
780 return (d*Zproj - c) / (a - b*Zproj);
783 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
786 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
788 for (i = 0; i < 3; i++) {
789 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
791 for (elt = 0; elt < 0x10000; elt++) {
792 /* We apply the fog transformation and cache the result */
793 DWORD fog_intensity = elt & 0xFF;
794 DWORD vertex_color = (elt >> 8) & 0xFF;
795 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
800 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
801 BOOLEAN vertex_transformed,
802 BOOLEAN vertex_lit) {
803 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
805 /* Puts GL in the correct lighting / transformation mode */
806 if ((vertex_transformed == FALSE) &&
807 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
808 /* Need to put the correct transformation again if we go from Transformed
809 vertices to non-transformed ones.
811 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
812 This->world_mat, This->view_mat, This->proj_mat);
813 glThis->transform_state = GL_TRANSFORM_NORMAL;
815 } else if ((vertex_transformed == TRUE) &&
816 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
817 /* Set our orthographic projection */
818 glThis->transform_state = GL_TRANSFORM_ORTHO;
819 d3ddevice_set_ortho(This);
822 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
823 if no fogging state change occured */
824 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
825 if (vertex_transformed == TRUE) {
827 /* Now check if our fog_table still corresponds to the current vertex color.
828 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
829 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
830 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
831 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
832 /* We need to rebuild our fog table.... */
833 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
836 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
837 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
838 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
839 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
840 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
842 if (vertex_lit == FALSE) {
843 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
844 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
846 /* Special case of 'pixel fog' */
847 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
848 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
859 /* Handle the 'no-normal' case */
860 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
861 glEnable(GL_LIGHTING);
863 glDisable(GL_LIGHTING);
865 /* Handle the code for pre-vertex material properties */
866 if (vertex_transformed == FALSE) {
867 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
868 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
869 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
870 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
871 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
872 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
873 glEnable(GL_COLOR_MATERIAL);
880 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
881 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
883 D3DDRAWPRIMITIVESTRIDEDDATA strided;
887 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
888 strided.position.dwStride = sizeof(D3DVERTEX);
889 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
890 strided.normal.dwStride = sizeof(D3DVERTEX);
891 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
892 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
893 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
896 case D3DVT_LVERTEX: {
897 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
898 strided.position.dwStride = sizeof(D3DLVERTEX);
899 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
900 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
901 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
902 strided.specular.dwStride = sizeof(D3DLVERTEX);
903 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
904 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
905 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
908 case D3DVT_TLVERTEX: {
909 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
910 strided.position.dwStride = sizeof(D3DTLVERTEX);
911 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
912 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
913 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
914 strided.specular.dwStride = sizeof(D3DTLVERTEX);
915 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
916 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
917 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
921 FIXME("Unhandled vertex type %08x\n", d3dvt);
927 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
928 D3DPRIMITIVETYPE d3dptPrimitiveType,
929 D3DVERTEXTYPE d3dvtVertexType,
934 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
936 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
937 if (TRACE_ON(ddraw)) {
938 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
941 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
947 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
948 D3DPRIMITIVETYPE d3dptPrimitiveType,
949 D3DVERTEXTYPE d3dvtVertexType,
956 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
957 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
958 if (TRACE_ON(ddraw)) {
959 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
962 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
968 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
969 LPD3DEXECUTEBUFFERDESC lpDesc,
970 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
973 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
974 IDirect3DExecuteBufferImpl *ret;
977 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
979 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
980 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
982 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
987 /* These are the various handler used in the generic path */
988 inline static void handle_xyz(D3DVALUE *coords) {
991 inline static void handle_xyzrhw(D3DVALUE *coords) {
992 if (coords[3] < 1e-8)
995 GLfloat w = 1.0 / coords[3];
997 glVertex4f(coords[0] * w,
1003 inline static void handle_normal(D3DVALUE *coords) {
1004 glNormal3fv(coords);
1007 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1008 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1009 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1010 glColor4ub((*color >> 16) & 0xFF,
1011 (*color >> 8) & 0xFF,
1012 (*color >> 0) & 0xFF,
1013 (*color >> 24) & 0xFF);
1015 glColor3ub((*color >> 16) & 0xFF,
1016 (*color >> 8) & 0xFF,
1017 (*color >> 0) & 0xFF);
1021 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1022 glColor4ub((*color >> 16) & 0xFF,
1023 (*color >> 8) & 0xFF,
1024 (*color >> 0) & 0xFF,
1025 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1028 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1029 if ((lighted == FALSE) &&
1030 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1031 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1032 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1033 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1034 handle_diffuse_base(sb, color);
1036 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1037 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1038 handle_diffuse_base(sb, color);
1040 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1041 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1042 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1043 handle_diffuse_base(sb, color);
1045 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1046 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1047 handle_diffuse_base(sb, color);
1050 handle_diffuse_base(sb, color);
1054 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1055 if ((lighted == FALSE) &&
1056 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1057 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1058 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1059 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1060 handle_specular_base(sb, color);
1062 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1063 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1064 handle_specular_base(sb, color);
1066 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1067 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1068 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1069 handle_specular_base(sb, color);
1071 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1072 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1073 handle_specular_base(sb, color);
1076 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1079 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1080 if (lighted == TRUE) {
1081 DWORD color = *color_d;
1082 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1083 /* Special case where the specular value is used to do fogging */
1084 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1085 color &= 0xFF000000; /* Only keep the alpha component */
1086 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1087 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1088 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1090 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1091 /* Standard specular value in transformed mode. TODO */
1093 handle_diffuse_base(sb, &color);
1095 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1096 handle_diffuse(sb, color_d, FALSE);
1097 handle_specular(sb, color_s, FALSE);
1099 /* In that case, only put the diffuse color... */
1100 handle_diffuse_base(sb, color_d);
1105 inline static void handle_texture(D3DVALUE *coords) {
1106 glTexCoord2fv(coords);
1108 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1109 /* For the moment, draw only the first texture.. */
1110 if (tex_index == 0) glTexCoord2fv(coords);
1113 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1114 D3DPRIMITIVETYPE d3dptPrimitiveType,
1115 DWORD d3dvtVertexType,
1116 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1117 DWORD dwVertexCount,
1122 BOOLEAN vertex_lighted = FALSE;
1123 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1124 int num_active_stages = 0;
1127 if (glThis->state == SURFACE_MEMORY) {
1128 This->flush_to_framebuffer(This, NULL);
1132 glThis->state = SURFACE_GL;
1134 /* Compute the number of active texture stages */
1135 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1137 /* This is to prevent 'thread contention' between a thread locking the device and another
1138 doing 3D display on it... */
1139 EnterCriticalSection(&(This->crit));
1141 if (TRACE_ON(ddraw)) {
1142 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1147 /* Just a hack for now.. Will have to find better algorithm :-/ */
1148 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1149 vertex_lighted = TRUE;
1151 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1154 draw_primitive_handle_GL_state(This,
1155 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1157 draw_primitive_start_GL(d3dptPrimitiveType);
1159 /* Some fast paths first before the generic case.... */
1160 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1163 for (index = 0; index < dwIndexCount; index++) {
1164 int i = (dwIndices == NULL) ? index : dwIndices[index];
1166 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1167 D3DVALUE *tex_coord =
1168 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1169 D3DVALUE *position =
1170 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1172 handle_normal(normal);
1173 handle_texture(tex_coord);
1174 handle_xyz(position);
1176 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1177 position[0], position[1], position[2],
1178 normal[0], normal[1], normal[2],
1179 tex_coord[0], tex_coord[1]);
1181 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1184 for (index = 0; index < dwIndexCount; index++) {
1185 int i = (dwIndices == NULL) ? index : dwIndices[index];
1187 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1190 D3DVALUE *tex_coord =
1191 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1192 D3DVALUE *position =
1193 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1195 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1196 handle_texture(tex_coord);
1197 handle_xyzrhw(position);
1199 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1200 position[0], position[1], position[2], position[3],
1201 (*color_d >> 16) & 0xFF,
1202 (*color_d >> 8) & 0xFF,
1203 (*color_d >> 0) & 0xFF,
1204 (*color_d >> 24) & 0xFF,
1205 (*color_s >> 16) & 0xFF,
1206 (*color_s >> 8) & 0xFF,
1207 (*color_s >> 0) & 0xFF,
1208 (*color_s >> 24) & 0xFF,
1209 tex_coord[0], tex_coord[1]);
1211 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1212 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1213 /* This is the 'slow path' but that should support all possible vertex formats out there...
1214 Note that people should write a fast path for all vertex formats out there...
1217 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1218 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1220 for (index = 0; index < dwIndexCount; index++) {
1221 int i = (dwIndices == NULL) ? index : dwIndices[index];
1224 if (d3dvtVertexType & D3DFVF_NORMAL) {
1226 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1227 handle_normal(normal);
1229 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1231 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1233 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1234 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1236 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1238 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1239 handle_specular(&(This->state_block), color_s, vertex_lighted);
1240 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1242 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1243 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1247 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1248 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1249 if (tex_index >= num_tex_index) {
1250 handle_textures((D3DVALUE *) no_index, tex_stage);
1252 D3DVALUE *tex_coord =
1253 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1254 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1255 handle_textures(tex_coord, tex_stage);
1259 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1260 D3DVALUE *position =
1261 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1262 handle_xyz(position);
1263 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1264 D3DVALUE *position =
1265 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1266 handle_xyzrhw(position);
1269 if (TRACE_ON(ddraw_geom)) {
1272 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1273 D3DVALUE *position =
1274 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1275 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1276 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1277 D3DVALUE *position =
1278 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1279 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1281 if (d3dvtVertexType & D3DFVF_NORMAL) {
1283 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1284 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1286 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1288 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1289 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1290 (*color_d >> 16) & 0xFF,
1291 (*color_d >> 8) & 0xFF,
1292 (*color_d >> 0) & 0xFF,
1293 (*color_d >> 24) & 0xFF);
1295 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1297 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1298 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1299 (*color_s >> 16) & 0xFF,
1300 (*color_s >> 8) & 0xFF,
1301 (*color_s >> 0) & 0xFF,
1302 (*color_s >> 24) & 0xFF);
1304 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1305 D3DVALUE *tex_coord =
1306 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1307 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1308 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1310 TRACE_(ddraw_geom)("\n");
1314 ERR(" matrix weighting not handled yet....\n");
1319 /* Whatever the case, disable the color material stuff */
1320 glDisable(GL_COLOR_MATERIAL);
1325 LeaveCriticalSection(&(This->crit));
1329 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1330 D3DPRIMITIVETYPE d3dptPrimitiveType,
1331 DWORD d3dvtVertexType,
1333 DWORD dwVertexCount,
1336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1337 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1339 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1340 if (TRACE_ON(ddraw)) {
1341 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1344 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1345 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1351 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1352 D3DPRIMITIVETYPE d3dptPrimitiveType,
1353 DWORD d3dvtVertexType,
1355 DWORD dwVertexCount,
1360 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1361 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1363 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1364 if (TRACE_ON(ddraw)) {
1365 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1368 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1369 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1375 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1376 D3DPRIMITIVETYPE d3dptPrimitiveType,
1378 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1379 DWORD dwVertexCount,
1382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1384 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1385 if (TRACE_ON(ddraw)) {
1386 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1388 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1394 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1395 D3DPRIMITIVETYPE d3dptPrimitiveType,
1397 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1398 DWORD dwVertexCount,
1403 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1405 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1406 if (TRACE_ON(ddraw)) {
1407 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1410 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1416 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1417 D3DPRIMITIVETYPE d3dptPrimitiveType,
1418 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1419 DWORD dwStartVertex,
1420 DWORD dwNumVertices,
1423 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1424 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1425 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1427 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1428 if (TRACE_ON(ddraw)) {
1429 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1432 if (vb_impl->processed == TRUE) {
1433 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1434 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1436 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1437 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1438 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1440 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1441 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1444 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1445 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1452 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1453 D3DPRIMITIVETYPE d3dptPrimitiveType,
1454 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1455 DWORD dwStartVertex,
1456 DWORD dwNumVertices,
1461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1462 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1463 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1465 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1466 if (TRACE_ON(ddraw)) {
1467 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1470 if (vb_impl->processed == TRUE) {
1471 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1472 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1474 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1475 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1476 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1478 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1479 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1482 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1483 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1490 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1494 if (dwMipState == D3DTFP_NONE) {
1495 switch (dwMinState) {
1496 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1497 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1498 default: gl_state = GL_LINEAR; break;
1500 } else if (dwMipState == D3DTFP_POINT) {
1501 switch (dwMinState) {
1502 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1503 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1504 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1507 switch (dwMinState) {
1508 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1509 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1510 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1517 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1523 gl_state = GL_NEAREST;
1526 gl_state = GL_LINEAR;
1529 gl_state = GL_LINEAR;
1535 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1537 handle_color_alpha_args(DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1539 BOOLEAN is_complement = FALSE;
1540 BOOLEAN is_alpha_replicate = FALSE;
1541 BOOLEAN handled = TRUE;
1543 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1547 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1548 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1553 if (tex_op == D3DTOP_SELECTARG2) {
1557 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1558 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1563 if (tex_op == D3DTOP_SELECTARG2) {
1568 if (dwState & D3DTA_COMPLEMENT) {
1569 is_complement = TRUE;
1571 if (dwState & D3DTA_ALPHAREPLICATE) {
1572 is_alpha_replicate = TRUE;
1574 dwState &= D3DTA_SELECTMASK;
1575 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1576 dwState = D3DTA_DIFFUSE;
1580 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1581 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1582 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1583 case D3DTA_TFACTOR: src = GL_CONSTANT_EXT; FIXME(" no handling yet of setting of constant value !\n"); break;
1584 default: src = GL_TEXTURE; handled = FALSE; break;
1588 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1589 if (is_alpha_replicate) {
1590 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1592 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1595 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1596 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1603 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1605 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1608 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1612 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1614 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1616 switch (d3dTexStageStateType) {
1617 #define GEN_CASE(a) case a: type = #a; break
1618 GEN_CASE(D3DTSS_COLOROP);
1619 GEN_CASE(D3DTSS_COLORARG1);
1620 GEN_CASE(D3DTSS_COLORARG2);
1621 GEN_CASE(D3DTSS_ALPHAOP);
1622 GEN_CASE(D3DTSS_ALPHAARG1);
1623 GEN_CASE(D3DTSS_ALPHAARG2);
1624 GEN_CASE(D3DTSS_BUMPENVMAT00);
1625 GEN_CASE(D3DTSS_BUMPENVMAT01);
1626 GEN_CASE(D3DTSS_BUMPENVMAT10);
1627 GEN_CASE(D3DTSS_BUMPENVMAT11);
1628 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1629 GEN_CASE(D3DTSS_ADDRESS);
1630 GEN_CASE(D3DTSS_ADDRESSU);
1631 GEN_CASE(D3DTSS_ADDRESSV);
1632 GEN_CASE(D3DTSS_BORDERCOLOR);
1633 GEN_CASE(D3DTSS_MAGFILTER);
1634 GEN_CASE(D3DTSS_MINFILTER);
1635 GEN_CASE(D3DTSS_MIPFILTER);
1636 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1637 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1638 GEN_CASE(D3DTSS_MAXANISOTROPY);
1639 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1640 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1641 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1643 default: type = "UNKNOWN";
1646 /* Store the values in the state array */
1647 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1648 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1649 /* Some special cases when one state modifies more than one... */
1650 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1651 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1652 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1655 switch (d3dTexStageStateType) {
1656 case D3DTSS_MINFILTER:
1657 case D3DTSS_MIPFILTER:
1658 if (TRACE_ON(ddraw)) {
1659 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1660 switch ((D3DTEXTUREMINFILTER) dwState) {
1661 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1662 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1663 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1666 switch ((D3DTEXTUREMIPFILTER) dwState) {
1667 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1668 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1669 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1670 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1676 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1677 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1680 case D3DTSS_MAGFILTER:
1681 if (TRACE_ON(ddraw)) {
1682 switch ((D3DTEXTUREMAGFILTER) dwState) {
1683 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1684 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1685 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1688 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1691 case D3DTSS_ADDRESS:
1692 case D3DTSS_ADDRESSU:
1693 case D3DTSS_ADDRESSV: {
1694 GLenum arg = GL_REPEAT; /* Default value */
1695 switch ((D3DTEXTUREADDRESS) dwState) {
1696 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1697 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1698 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1699 #if defined(GL_VERSION_1_4)
1700 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1701 #elif defined(GL_ARB_texture_mirrored_repeat)
1702 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1704 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1706 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1707 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1708 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1709 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1710 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1711 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1714 case D3DTSS_ALPHAOP:
1715 case D3DTSS_COLOROP: {
1717 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1722 #define GEN_CASE(a) case a: value = #a; break
1723 GEN_CASE(D3DTOP_DISABLE);
1724 GEN_CASE(D3DTOP_SELECTARG1);
1725 GEN_CASE(D3DTOP_SELECTARG2);
1726 GEN_CASE(D3DTOP_MODULATE);
1727 GEN_CASE(D3DTOP_MODULATE2X);
1728 GEN_CASE(D3DTOP_MODULATE4X);
1729 GEN_CASE(D3DTOP_ADD);
1730 GEN_CASE(D3DTOP_ADDSIGNED);
1731 GEN_CASE(D3DTOP_ADDSIGNED2X);
1732 GEN_CASE(D3DTOP_SUBTRACT);
1733 GEN_CASE(D3DTOP_ADDSMOOTH);
1734 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1735 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1736 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1737 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1738 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1739 GEN_CASE(D3DTOP_PREMODULATE);
1740 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1741 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1742 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1743 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1744 GEN_CASE(D3DTOP_BUMPENVMAP);
1745 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1746 GEN_CASE(D3DTOP_DOTPRODUCT3);
1747 GEN_CASE(D3DTOP_FORCE_DWORD);
1749 default: value = "UNKNOWN";
1752 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1753 glDisable(GL_TEXTURE_2D);
1754 TRACE(" disabling 2D texturing.\n");
1756 /* Re-enable texturing */
1757 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1758 glEnable(GL_TEXTURE_2D);
1759 TRACE(" enabling 2D texturing.\n");
1762 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1763 if (dwState != D3DTOP_DISABLE) {
1764 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1767 /* Now set up the operand correctly */
1769 case D3DTOP_DISABLE:
1770 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1771 and it works, so ignore this op */
1772 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1775 case D3DTOP_SELECTARG1:
1776 case D3DTOP_SELECTARG2:
1777 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1780 case D3DTOP_MODULATE4X:
1781 scale = scale * 2; /* Drop through */
1782 case D3DTOP_MODULATE2X:
1783 scale = scale * 2; /* Drop through */
1784 case D3DTOP_MODULATE:
1785 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1789 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1792 case D3DTOP_ADDSIGNED2X:
1793 scale = scale * 2; /* Drop through */
1794 case D3DTOP_ADDSIGNED:
1795 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1804 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1805 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1806 /* Switch the arguments if needed... */
1807 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1808 handle_color_alpha_args(dwStage, D3DTSS_COLORARG1,
1809 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1811 handle_color_alpha_args(dwStage, D3DTSS_COLORARG2,
1812 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1815 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG1,
1816 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1818 handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG2,
1819 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1825 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1826 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1828 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1830 TRACE(" Stage type is : %s => %s\n", type, value);
1832 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1836 case D3DTSS_COLORARG1:
1837 case D3DTSS_COLORARG2:
1838 case D3DTSS_ALPHAARG1:
1839 case D3DTSS_ALPHAARG2: {
1840 const char *value, *value_comp = "", *value_alpha = "";
1842 D3DTEXTUREOP tex_op;
1844 switch (dwState & D3DTA_SELECTMASK) {
1845 #define GEN_CASE(a) case a: value = #a; break
1846 GEN_CASE(D3DTA_DIFFUSE);
1847 GEN_CASE(D3DTA_CURRENT);
1848 GEN_CASE(D3DTA_TEXTURE);
1849 GEN_CASE(D3DTA_TFACTOR);
1850 GEN_CASE(D3DTA_SPECULAR);
1852 default: value = "UNKNOWN";
1854 if (dwState & D3DTA_COMPLEMENT) {
1855 value_comp = " | D3DTA_COMPLEMENT";
1857 if (dwState & D3DTA_ALPHAREPLICATE) {
1858 value_alpha = " | D3DTA_ALPHAREPLICATE";
1861 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1862 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1864 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1867 handled = handle_color_alpha_args(dwStage, d3dTexStageStateType, dwState, tex_op);
1870 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1872 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1876 case D3DTSS_MIPMAPLODBIAS: {
1877 D3DVALUE value = *((D3DVALUE *) &dwState);
1878 BOOLEAN handled = TRUE;
1884 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1886 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1890 case D3DTSS_MAXMIPLEVEL:
1892 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1894 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1898 case D3DTSS_BORDERCOLOR: {
1901 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1902 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1903 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1904 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1906 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1908 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1909 ((dwState >> 16) & 0xFF),
1910 ((dwState >> 8) & 0xFF),
1911 ((dwState >> 0) & 0xFF),
1912 ((dwState >> 24) & 0xFF));
1915 case D3DTSS_TEXCOORDINDEX: {
1916 BOOLEAN handled = TRUE;
1919 switch (dwState & 0xFFFF0000) {
1920 #define GEN_CASE(a) case a: value = #a; break
1921 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1922 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1923 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1924 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1926 default: value = "UNKNOWN";
1928 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1932 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1934 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1938 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1939 const char *projected = "", *value;
1940 BOOLEAN handled = TRUE;
1941 switch (dwState & 0xFF) {
1942 #define GEN_CASE(a) case a: value = #a; break
1943 GEN_CASE(D3DTTFF_DISABLE);
1944 GEN_CASE(D3DTTFF_COUNT1);
1945 GEN_CASE(D3DTTFF_COUNT2);
1946 GEN_CASE(D3DTTFF_COUNT3);
1947 GEN_CASE(D3DTTFF_COUNT4);
1949 default: value = "UNKNOWN";
1951 if (dwState & D3DTTFF_PROJECTED)
1952 projected = " | D3DTTFF_PROJECTED";
1954 if (dwState != D3DTTFF_DISABLE)
1957 if (handled == TRUE) {
1958 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1960 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1965 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1973 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1975 LPDIRECTDRAWSURFACE7 lpTexture2)
1977 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1979 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1981 if (dwStage > 0) return DD_OK;
1983 if (This->current_texture[dwStage] != NULL) {
1984 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1988 if (lpTexture2 == NULL) {
1989 This->current_texture[dwStage] = NULL;
1991 TRACE(" disabling 2D texturing.\n");
1992 glBindTexture(GL_TEXTURE_2D, 0);
1993 glDisable(GL_TEXTURE_2D);
1995 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1996 GLint max_mip_level;
1998 This->current_texture[dwStage] = tex_impl;
1999 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2001 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2002 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2003 glEnable(GL_TEXTURE_2D);
2004 TRACE(" enabling 2D texturing.\n");
2006 gltex_upload_texture(tex_impl);
2008 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2011 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2014 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2015 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2016 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2017 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2018 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2019 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2027 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2028 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2030 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2031 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2033 fill_opengl_caps_7(lpD3DHELDevDesc);
2035 TRACE(" returning caps : no dump function yet.\n");
2041 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2042 LPD3DMATERIAL7 lpMat)
2044 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2045 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2047 if (TRACE_ON(ddraw)) {
2048 TRACE(" material is : \n");
2049 dump_D3DMATERIAL7(lpMat);
2052 This->current_material = *lpMat;
2054 glMaterialfv(GL_FRONT_AND_BACK,
2056 (float *) &(This->current_material.u.diffuse));
2057 glMaterialfv(GL_FRONT_AND_BACK,
2059 (float *) &(This->current_material.u1.ambient));
2060 glMaterialfv(GL_FRONT_AND_BACK,
2062 (float *) &(This->current_material.u2.specular));
2063 glMaterialfv(GL_FRONT_AND_BACK,
2065 (float *) &(This->current_material.u3.emissive));
2066 glMaterialf(GL_FRONT_AND_BACK,
2068 This->current_material.u4.power); /* Not sure about this... */
2075 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2077 LPD3DLIGHT7 lpLight)
2079 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2080 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2082 if (TRACE_ON(ddraw)) {
2083 TRACE(" setting light : \n");
2084 dump_D3DLIGHT7(lpLight);
2087 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2088 This->set_lights |= 0x00000001 << dwLightIndex;
2089 This->light_parameters[dwLightIndex] = *lpLight;
2091 switch (lpLight->dltType) {
2092 case D3DLIGHT_DIRECTIONAL: {
2094 float cut_off = 180.0;
2096 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2097 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2098 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2099 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2101 direction[0] = lpLight->dvDirection.u1.x;
2102 direction[1] = lpLight->dvDirection.u2.y;
2103 direction[2] = lpLight->dvDirection.u3.z;
2105 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
2108 case D3DLIGHT_POINT: {
2110 float cut_off = 180.0;
2112 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2113 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2114 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2115 position[0] = lpLight->dvPosition.u1.x;
2116 position[1] = lpLight->dvPosition.u2.y;
2117 position[2] = lpLight->dvPosition.u3.z;
2119 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2120 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2121 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2122 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2123 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2126 case D3DLIGHT_SPOT: {
2129 float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
2131 glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
2132 glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
2133 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
2135 direction[0] = lpLight->dvDirection.u1.x;
2136 direction[1] = lpLight->dvDirection.u2.y;
2137 direction[2] = lpLight->dvDirection.u3.z;
2139 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
2140 position[0] = lpLight->dvPosition.u1.x;
2141 position[1] = lpLight->dvPosition.u2.y;
2142 position[2] = lpLight->dvPosition.u3.z;
2144 glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
2145 glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
2146 glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
2147 glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
2148 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
2149 glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
2150 if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
2151 WARN("dvTheta not fully supported yet !\n");
2155 default: WARN(" light type not handled yet...\n");
2162 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2167 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2169 if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2172 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2173 /* Set the default parameters.. */
2174 TRACE(" setting default light parameters...\n");
2175 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2177 glEnable(GL_LIGHT0 + dwLightIndex);
2179 glDisable(GL_LIGHT0 + dwLightIndex);
2186 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2188 ICOM_THIS(IDirect3DDeviceImpl,iface);
2191 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2193 if (dwIndex>=This->max_clipping_planes) {
2194 return DDERR_INVALIDPARAMS;
2197 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2199 memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2200 plane[0] = pPlaneEquation[0];
2201 plane[1] = pPlaneEquation[1];
2202 plane[2] = pPlaneEquation[2];
2203 plane[3] = pPlaneEquation[3];
2205 /* XXX: is here also code needed to handle the transformation of the world? */
2206 glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
2211 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2212 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2214 # define XCAST(fun) (void*)
2217 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2219 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2220 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2221 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2222 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2223 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2224 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2225 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2226 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2227 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2228 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2229 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2230 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2231 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2232 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2233 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
2234 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2235 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2236 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2237 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2238 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2239 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2240 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2241 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2242 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2243 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2244 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2245 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2246 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2247 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2248 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2249 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2250 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2251 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2252 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2253 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2254 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2255 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2256 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2257 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2258 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2259 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2260 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2261 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2262 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2263 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2264 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2265 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2266 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2267 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2268 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2271 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2276 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2277 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2279 # define XCAST(fun) (void*)
2282 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2284 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2285 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2286 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2287 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2288 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2289 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2290 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2291 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2292 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2293 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2294 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2295 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2296 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2297 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2298 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2299 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2300 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2301 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2302 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2303 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2304 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2305 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2306 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2307 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2308 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2309 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2310 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2311 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2312 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2313 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2314 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2315 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2316 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2317 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2318 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2319 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2320 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2321 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2322 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2323 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2324 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2325 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2326 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2329 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2334 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2335 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2337 # define XCAST(fun) (void*)
2340 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2342 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2343 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2344 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2345 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2346 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2347 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2348 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2349 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2350 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2351 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2352 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2353 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2354 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2355 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2356 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2357 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2358 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2359 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2360 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2361 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2362 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2363 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2364 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2365 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2366 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2367 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2368 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2369 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2370 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2371 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2372 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2373 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2374 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2375 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2378 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2383 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2384 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2386 # define XCAST(fun) (void*)
2389 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2391 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2392 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2393 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2394 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2395 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2396 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2397 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2398 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2399 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2400 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2401 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2402 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2403 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2404 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2405 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2406 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2407 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2408 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2409 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2410 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2411 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2412 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2413 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2416 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2420 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2429 GLfloat old_z_clear_value;
2430 GLbitfield bitfield = 0;
2431 GLint old_stencil_clear_value;
2432 GLfloat old_color_clear_value[4];
2434 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2435 if (TRACE_ON(ddraw)) {
2438 TRACE(" rectangles : \n");
2439 for (i = 0; i < dwCount; i++) {
2440 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2446 WARN(" Warning, this function only for now clears the whole screen...\n");
2449 /* Clears the screen */
2451 if (dwFlags & D3DCLEAR_ZBUFFER) {
2452 bitfield |= GL_DEPTH_BUFFER_BIT;
2453 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2454 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2455 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2457 TRACE(" depth value : %f\n", dvZ);
2459 if (dwFlags & D3DCLEAR_STENCIL) {
2460 bitfield |= GL_STENCIL_BUFFER_BIT;
2461 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2462 glClearStencil(dwStencil);
2463 TRACE(" stencil value : %ld\n", dwStencil);
2465 if (dwFlags & D3DCLEAR_TARGET) {
2466 bitfield |= GL_COLOR_BUFFER_BIT;
2467 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2468 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2469 ((dwColor >> 8) & 0xFF) / 255.0,
2470 ((dwColor >> 0) & 0xFF) / 255.0,
2471 ((dwColor >> 24) & 0xFF) / 255.0);
2472 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2477 if (dwFlags & D3DCLEAR_ZBUFFER) {
2479 glClearDepth(old_z_clear_value);
2481 if (dwFlags & D3DCLEAR_STENCIL) {
2482 bitfield |= GL_STENCIL_BUFFER_BIT;
2483 glClearStencil(old_stencil_clear_value);
2485 if (dwFlags & D3DCLEAR_TARGET) {
2486 bitfield |= GL_COLOR_BUFFER_BIT;
2487 glClearColor(old_color_clear_value[0],
2488 old_color_clear_value[1],
2489 old_color_clear_value[2],
2490 old_color_clear_value[3]);
2499 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2500 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2501 DWORD dwFlags, LPDDBLTFX lpbltfx)
2503 if (dwFlags & DDBLT_COLORFILL) {
2504 /* This is easy to handle for the D3D Device... */
2505 DWORD color = lpbltfx->u5.dwFillColor;
2506 TRACE(" executing D3D Device override.\n");
2507 d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2510 return DDERR_INVALIDPARAMS;
2514 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2515 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2516 LPRECT rsrc, DWORD trans)
2518 return DDERR_INVALIDPARAMS;
2522 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2524 GLfloat height, width;
2525 GLfloat trans_mat[16];
2527 width = This->surface->surface_desc.dwWidth;
2528 height = This->surface->surface_desc.dwHeight;
2530 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2531 to OpenGL screen coordinates (ie the upper left corner is not the same).
2532 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2533 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2534 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2535 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2536 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2537 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2539 glMatrixMode(GL_MODELVIEW);
2541 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2542 Correctness Tips section).
2544 Basically, from what I understood, if the game does not filter the font texture,
2545 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2546 one and we will have strange artifacts (as the rounding and stuff may give different results
2547 for different pixels, ie sometimes take the left pixel, sometimes the right).
2549 glTranslatef(0.375, 0.375, 0);
2550 glMatrixMode(GL_PROJECTION);
2551 glLoadMatrixf(trans_mat);
2555 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2556 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2558 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2559 glMatrixMode(GL_MODELVIEW);
2560 glLoadMatrixf((float *) view_mat);
2561 glMultMatrixf((float *) world_mat);
2563 if ((matrices & PROJMAT_CHANGED) != 0) {
2564 glMatrixMode(GL_PROJECTION);
2565 glLoadMatrixf((float *) proj_mat);
2570 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2572 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2573 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2574 /* This will force an update of the transform state at the next drawing. */
2575 glThis->transform_state = GL_TRANSFORM_NONE;
2579 /* TODO for both these functions :
2580 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2581 by other OpenGL code in D3D
2582 - handle the case where no 'Begin / EndScene' was done between two locks
2583 - handle the rectangles in the unlock too
2584 - handle pitch correctly...
2586 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2588 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2589 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2592 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2594 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2597 ERR("Wrong surface type for locking !\n");
2601 /* Try to acquire the device critical section */
2602 EnterCriticalSection(&(d3d_dev->crit));
2604 if (((is_front == TRUE) && (gl_d3d_dev->front_state != SURFACE_MEMORY)) ||
2605 ((is_front == FALSE) && (gl_d3d_dev->state != SURFACE_MEMORY))) {
2606 /* If the surface is already in memory, no need to do anything here... */
2608 GLenum buffer_color;
2614 TRACE(" copying frame buffer to main memory.\n");
2616 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2617 may only write to the device... But when we will blit it back to the screen, we need
2618 also to blit correctly the parts the application did not overwrite... */
2622 glGetIntegerv(GL_READ_BUFFER, &prev_read);
2625 if (is_front == TRUE)
2626 /* Application wants to lock the front buffer */
2627 glReadBuffer(GL_FRONT);
2629 /* Application wants to lock the back buffer */
2630 glReadBuffer(GL_BACK);
2632 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2633 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2634 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2635 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2636 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2637 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2638 buffer_color = GL_RGB;
2639 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2640 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2641 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2642 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2643 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2644 buffer_type = GL_UNSIGNED_BYTE;
2645 buffer_color = GL_BGRA;
2646 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2648 ERR(" unsupported pixel format at device locking.\n");
2653 /* Just a hack while waiting for proper rectangle support */
2655 if (pRect == NULL) {
2658 loc_rect.bottom = This->surface_desc.dwHeight;
2659 loc_rect.right = This->surface_desc.dwWidth;
2664 dst = ((char *)This->surface_desc.lpSurface) +
2665 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2666 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2667 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2669 glReadPixels(loc_rect.left, y,
2670 loc_rect.right - loc_rect.left, 1,
2671 buffer_color, buffer_type, dst);
2672 dst += This->surface_desc.u1.lPitch;
2675 glReadBuffer(prev_read);
2676 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2679 gl_d3d_dev->front_state = SURFACE_MEMORY;
2681 gl_d3d_dev->state = SURFACE_MEMORY;
2684 /* I keep this code here as it's very useful to debug :-) */
2686 static int flush_count = 0;
2690 if ((++flush_count % 50) == 0) {
2691 sprintf(buf, "lock_%06d.pnm", flush_count);
2692 f = fopen(buf, "wb");
2693 DDRAW_dump_surface_to_disk(This, f);
2702 #define UNLOCK_TEX_SIZE 256
2704 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2705 GLenum buffer_type, buffer_color;
2707 IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2708 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2709 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test;
2710 GLuint initial_texture;
2716 loc_rect.bottom = surf->surface_desc.dwHeight;
2717 loc_rect.right = surf->surface_desc.dwWidth;
2719 TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
2721 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2722 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2723 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2724 glGetIntegerv(GL_CULL_FACE, &cull_face);
2725 glGetIntegerv(GL_LIGHTING, &lighting);
2726 glGetIntegerv(GL_BLEND, &blend);
2727 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2728 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2729 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2730 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2731 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2732 /* TODO: scissor test if ever we use it ! */
2734 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2735 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2736 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2737 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2738 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2739 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2740 buffer_color = GL_RGB;
2741 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2742 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2743 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2744 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2745 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2746 buffer_type = GL_UNSIGNED_BYTE;
2747 buffer_color = GL_BGRA;
2748 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2750 ERR(" unsupported pixel format at frame buffer flush.\n");
2754 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2755 d3ddevice_set_ortho(d3d_dev);
2757 glDisable(GL_DEPTH_TEST);
2758 glEnable(GL_TEXTURE_2D);
2759 glEnable(GL_SCISSOR_TEST);
2760 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2761 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2763 if (gl_d3d_dev->unlock_tex == 0) {
2764 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2765 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2766 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2767 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2768 GL_RGB, buffer_type, NULL);
2770 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2772 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2774 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2775 glDisable(GL_LIGHTING);
2776 glDisable(GL_CULL_FACE);
2777 glDisable(GL_ALPHA_TEST);
2778 glDisable(GL_STENCIL_TEST);
2779 glDisable(GL_BLEND);
2780 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2781 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2783 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2784 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2785 /* First, upload the texture... */
2786 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
2787 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2788 glTexSubImage2D(GL_TEXTURE_2D,
2794 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2796 glColor3ub(0xFF, 0xFF, 0xFF);
2797 glTexCoord2f(0.0, 0.0);
2798 glVertex3d(x, y, 0.5);
2799 glTexCoord2f(1.0, 0.0);
2800 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2801 glTexCoord2f(1.0, 1.0);
2802 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2803 glTexCoord2f(0.0, 1.0);
2804 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2810 /* And restore all the various states modified by this code */
2811 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2812 if (lighting != 0) glEnable(GL_LIGHTING);
2813 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2814 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2815 if (cull_face != 0) glEnable(GL_CULL_FACE);
2816 if (blend != 0) glEnable(GL_BLEND);
2817 glBindTexture(GL_TEXTURE_2D, initial_texture);
2818 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2819 glDisable(GL_SCISSOR_TEST);
2820 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2821 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
2822 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2824 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2827 /* I keep this code here as it's very useful to debug :-) */
2829 static int flush_count = 0;
2833 if ((++flush_count % 50) == 0) {
2834 sprintf(buf, "flush_%06d.pnm", flush_count);
2835 f = fopen(buf, "wb");
2836 DDRAW_dump_surface_to_disk(surf, f);
2842 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2845 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2847 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2849 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2852 ERR("Wrong surface type for locking !\n");
2855 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
2856 if (((This->lastlocktype & DDLOCK_READONLY) == 0) &&
2857 (is_front == TRUE)) {
2860 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2861 glDrawBuffer(GL_FRONT);
2862 d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
2863 glDrawBuffer(prev_draw);
2867 /* And 'frees' the device critical section */
2868 LeaveCriticalSection(&(d3d_dev->crit));
2872 apply_texture_state(IDirect3DDeviceImpl *This)
2876 /* Initialize texture stages states */
2877 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2878 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
2879 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
2880 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
2881 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
2888 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2890 IDirect3DDeviceImpl *object;
2891 IDirect3DDeviceGLImpl *gl_object;
2892 IDirectDrawSurfaceImpl *surf;
2896 XVisualInfo template;
2897 GLenum buffer = GL_FRONT;
2899 GLint max_clipping_planes = 0;
2901 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2902 if (object == NULL) return DDERR_OUTOFMEMORY;
2904 gl_object = (IDirect3DDeviceGLImpl *) object;
2908 object->surface = surface;
2909 object->set_context = set_context;
2910 object->clear = d3ddevice_clear;
2911 object->set_matrices = d3ddevice_set_matrices;
2912 object->matrices_updated = d3ddevice_matrices_updated;
2913 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
2915 InitializeCriticalSection(&(object->crit));
2917 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2919 device_context = GetDC(surface->ddraw_owner->window);
2920 gl_object->display = get_display(device_context);
2921 gl_object->drawable = get_drawable(device_context);
2922 ReleaseDC(surface->ddraw_owner->window,device_context);
2925 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2926 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2928 HeapFree(GetProcessHeap(), 0, object);
2929 ERR("No visual found !\n");
2931 return DDERR_INVALIDPARAMS;
2933 TRACE(" visual found\n");
2936 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2939 if (gl_object->gl_context == NULL) {
2940 HeapFree(GetProcessHeap(), 0, object);
2941 ERR("Error in context creation !\n");
2943 return DDERR_INVALIDPARAMS;
2945 TRACE(" context created (%p)\n", gl_object->gl_context);
2948 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2949 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2950 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2951 surf->aux_ctx = (LPVOID) object;
2952 surf->aux_data = (LPVOID) gl_object->drawable;
2953 surf->aux_flip = opengl_flip;
2958 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2960 TRACE(" no double buffering : drawing on the front buffer\n");
2964 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2965 IDirectDrawSurfaceImpl *surf2;
2966 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
2967 for (; surf2 != NULL; surf2 = surf2->next_attached) {
2968 TRACE(" checking surface %p :", surf2);
2969 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2970 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2971 /* Override the Lock / Unlock function for all these surfaces */
2972 surf2->lock_update_prev = surf2->lock_update;
2973 surf2->lock_update = d3ddevice_lock_update;
2974 surf2->unlock_update_prev = surf2->unlock_update;
2975 surf2->unlock_update = d3ddevice_unlock_update;
2976 /* And install also the blt / bltfast overrides */
2977 surf2->aux_blt = d3ddevice_blt;
2978 surf2->aux_bltfast = d3ddevice_bltfast;
2980 TRACE(" overiding direct surface access.\n");
2982 TRACE(" no overide.\n");
2984 surf2->d3ddevice = object;
2988 /* Set the various light parameters */
2989 for (light = 0; light < MAX_LIGHTS; light++) {
2990 /* Only set the fields that are not zero-created */
2991 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2992 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2993 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2994 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2995 object->light_parameters[light].dvDirection.u3.z = 1.0;
2998 /* Allocate memory for the matrices */
2999 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3000 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3001 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3002 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3003 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3004 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3006 /* Initialisation */
3007 TRACE(" setting current context\n");
3009 object->set_context(object);
3011 TRACE(" current context set\n");
3013 /* allocate the clipping planes */
3014 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3015 if (max_clipping_planes>32) {
3016 object->max_clipping_planes=32;
3018 object->max_clipping_planes = max_clipping_planes;
3020 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3021 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3023 glHint(GL_FOG_HINT,GL_NICEST);
3025 glClearColor(0.0, 0.0, 0.0, 0.0);
3026 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3027 glDrawBuffer(buffer);
3028 glReadBuffer(buffer);
3029 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3032 gl_object->state = SURFACE_GL;
3034 /* fill_device_capabilities(d3d->ddraw); */
3036 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3037 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3038 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3039 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3043 TRACE(" creating implementation at %p.\n", *obj);
3045 /* And finally warn D3D that this device is now present */
3046 object->d3d->added_device(object->d3d, object);
3048 /* FIXME: Should handle other versions than just 7 */
3049 InitDefaultStateBlock(&object->state_block, 7);
3050 /* Apply default render state and texture stage state values */
3051 apply_render_state(object, &object->state_block);
3052 apply_texture_state(object);
3054 /* And fill the fog table with the default fog value */
3055 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);