- fix bug in 'Blt DEPTH_FILL' override
[wine] / dlls / ddraw / d3ddevice / mesa.c
1 /* Direct3D Device
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains the MESA implementation of all the D3D devices that
5  * Wine supports.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25 #include <math.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "ddraw.h"
33 #include "d3d.h"
34 #include "wine/debug.h"
35
36 #include "mesa_private.h"
37 #include "main.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
41
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
45 {
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 */
49 };
50
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
53   0x31416d44,
54   0x86ae,
55   0x11d2,
56   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
57 };
58
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,
63                                          const GLvoid *table);
64 #endif
65
66 const float id_mat[16] = {
67     1.0, 0.0, 0.0, 0.0,
68     0.0, 1.0, 0.0, 0.0,
69     0.0, 0.0, 1.0, 0.0,
70     0.0, 0.0, 0.0, 1.0
71 };
72
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
75                                    DWORD d3dvtVertexType,
76                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
77                                    DWORD dwVertexCount,
78                                    LPWORD dwIndices,
79                                    DWORD dwIndexCount,
80                                    DWORD dwFlags) ;
81
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
84 {
85     Display *display;
86     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
87
88     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
89                     sizeof(display), (LPSTR)&display )) display = NULL;
90
91     return display;
92 }
93
94
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
97 {
98     Drawable drawable;
99     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
100
101     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
102                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
103
104     return drawable;
105 }
106
107
108 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
109 {
110     IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
111     IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
112
113     TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
114     ENTER_GL();
115     if (gl_d3d_dev->state == SURFACE_MEMORY) {
116         d3d_dev->flush_to_framebuffer(d3d_dev, NULL);
117     }
118     gl_d3d_dev->state = SURFACE_GL;
119     gl_d3d_dev->front_state = SURFACE_GL;
120     glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
121     LEAVE_GL();
122     
123     return TRUE;
124 }
125
126
127 /*******************************************************************************
128  *                              OpenGL static functions
129  */
130 static void set_context(IDirect3DDeviceImpl* This)
131 {
132     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
133    
134     ENTER_GL();
135     TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
136     if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
137         ERR("Error in setting current context (context %p drawable %ld)!\n",
138             glThis->gl_context, glThis->drawable);
139     }
140     LEAVE_GL();
141 }
142
143 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
144 {
145     pc->dwSize = sizeof(*pc);
146     pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
147       D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
148     pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
149       D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
150     pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
151       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
152     pc->dwSrcBlendCaps  = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
153       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
154         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
155     pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
156       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
157         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
158     pc->dwAlphaCmpCaps  = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
159       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
160     pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
161       D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
162     pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
163       D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
164     pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
165       D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
166     pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
167       D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
168     pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
169     pc->dwStippleWidth = 32;
170     pc->dwStippleHeight = 32;
171 }
172
173 static void fill_opengl_caps(D3DDEVICEDESC *d1)
174 {
175     /* GLint maxlight; */
176
177     d1->dwSize  = sizeof(*d1);
178     d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
179       | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
180     d1->dcmColorModel = D3DCOLOR_RGB;
181     d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
182       D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
183       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
184       /* D3D 7 capabilities */
185       D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
186     d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
187     d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
188     d1->bClipping = TRUE;
189     d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
190     d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
191     d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
192     d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
193     fill_opengl_primcaps(&(d1->dpcLineCaps));
194     fill_opengl_primcaps(&(d1->dpcTriCaps));
195     d1->dwDeviceRenderBitDepth  = DDBD_16|DDBD_24|DDBD_32;
196     d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
197     d1->dwMaxBufferSize = 0;
198     d1->dwMaxVertexCount = 65536;
199     d1->dwMinTextureWidth  = 1;
200     d1->dwMinTextureHeight = 1;
201     d1->dwMaxTextureWidth  = 1024;
202     d1->dwMaxTextureHeight = 1024;
203     d1->dwMinStippleWidth  = 1;
204     d1->dwMinStippleHeight = 1;
205     d1->dwMaxStippleWidth  = 32;
206     d1->dwMaxStippleHeight = 32;
207     d1->dwMaxTextureRepeat = 16;
208     d1->dwMaxTextureAspectRatio = 1024;
209     d1->dwMaxAnisotropy = 0;
210     d1->dvGuardBandLeft = 0.0;
211     d1->dvGuardBandRight = 0.0;
212     d1->dvGuardBandTop = 0.0;
213     d1->dvGuardBandBottom = 0.0;
214     d1->dvExtentsAdjust = 0.0;
215     d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
216       D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
217     d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
218     d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
219     d1->wMaxTextureBlendStages = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
220     d1->wMaxSimultaneousTextures = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
221 }
222
223 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
224 {
225     D3DDEVICEDESC d1;
226
227     /* Copy first D3D1/2/3 capabilities */
228     fill_opengl_caps(&d1);
229
230     /* And fill the D3D7 one with it */
231     d->dwDevCaps = d1.dwDevCaps;
232     d->dpcLineCaps = d1.dpcLineCaps;
233     d->dpcTriCaps = d1.dpcTriCaps;
234     d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
235     d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
236     d->dwMinTextureWidth = d1.dwMinTextureWidth;
237     d->dwMinTextureHeight = d1.dwMinTextureHeight;
238     d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
239     d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
240     d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
241     d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
242     d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
243     d->dvGuardBandLeft = d1.dvGuardBandLeft;
244     d->dvGuardBandTop = d1.dvGuardBandTop;
245     d->dvGuardBandRight = d1.dvGuardBandRight;
246     d->dvGuardBandBottom = d1.dvGuardBandBottom;
247     d->dvExtentsAdjust = d1.dvExtentsAdjust;
248     d->dwStencilCaps = d1.dwStencilCaps;
249     d->dwFVFCaps = d1.dwFVFCaps;
250     d->dwTextureOpCaps = d1.dwTextureOpCaps;
251     d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
252     d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
253     d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
254     d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
255     d->deviceGUID = IID_IDirect3DTnLHalDevice;
256     d->wMaxUserClipPlanes = 1;
257     d->wMaxVertexBlendMatrices = 0;
258     d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
259       D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
260     d->dwReserved1 = 0;
261     d->dwReserved2 = 0;
262     d->dwReserved3 = 0;
263     d->dwReserved4 = 0;
264 }
265
266 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
267 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
268 {
269     x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
270     const char *ext_string;
271     Mesa_DeviceCapabilities *devcap;
272
273     private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
274     devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
275
276     ENTER_GL();
277     ext_string = glGetString(GL_EXTENSIONS);
278     /* Query for the ColorTable Extension */
279     if (strstr(ext_string, "GL_EXT_paletted_texture")) {
280         devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
281         TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
282     } else {
283         TRACE("Color table extension not found.\n");
284     }
285     LEAVE_GL();
286 }
287 #endif
288
289
290
291 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
292 {
293     D3DDEVICEDESC dref, d1, d2;
294     HRESULT ret_value;
295
296     /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
297        Let's put the string in a sufficiently sized array in writable memory. */
298     char device_name[50];
299     strcpy(device_name,"direct3d");
300
301     fill_opengl_caps(&dref);
302
303     if (version > 1) {
304         /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
305         TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
306         d1 = dref;
307         d2 = dref;
308         ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
309         if (ret_value != D3DENUMRET_OK)
310             return ret_value;
311     }
312     
313     TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
314     d1 = dref;
315     d2 = dref;
316     ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
317     if (ret_value != D3DENUMRET_OK)
318         return ret_value;
319
320     return D3DENUMRET_OK;
321 }
322
323 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
324 {
325     D3DDEVICEDESC7 ddesc;
326
327     fill_opengl_caps_7(&ddesc);
328     
329     TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
330     
331     return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
332 }
333
334 ULONG WINAPI
335 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
336 {
337     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
338     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
339     
340     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
341     if (!--(This->ref)) {
342         int i;
343         IDirectDrawSurfaceImpl *surface = This->surface, *surf;
344         
345         /* Release texture associated with the device */ 
346         for (i = 0; i < MAX_TEXTURES; i++) {
347             if (This->current_texture[i] != NULL)
348                 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
349             HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
350         }
351
352         /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
353         for (surf = surface; surf != NULL; surf = surf->surface_owner) {
354             if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
355                 surf->aux_ctx  = NULL;
356                 surf->aux_data = NULL;
357                 surf->aux_flip = NULL;
358                 break;
359             }
360         }
361         for (surf = surface; surf != NULL; surf = surf->surface_owner) {
362             IDirectDrawSurfaceImpl *surf2;
363             for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
364             for (; surf2 != NULL; surf2 = surf2->next_attached) {
365                 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
366                     ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
367                     /* Override the Lock / Unlock function for all these surfaces */
368                     surf2->lock_update = surf2->lock_update_prev;
369                     surf2->unlock_update = surf2->unlock_update_prev;
370                     /* And install also the blt / bltfast overrides */
371                     surf2->aux_blt = NULL;
372                     surf2->aux_bltfast = NULL;
373                 }
374                 surf2->d3ddevice = NULL;
375             }
376         }
377         
378         /* And warn the D3D object that this device is no longer active... */
379         This->d3d->removed_device(This->d3d, This);
380
381         HeapFree(GetProcessHeap(), 0, This->world_mat);
382         HeapFree(GetProcessHeap(), 0, This->view_mat);
383         HeapFree(GetProcessHeap(), 0, This->proj_mat);
384
385         DeleteCriticalSection(&(This->crit));
386         
387         ENTER_GL();
388         if (glThis->unlock_tex)
389             glDeleteTextures(1, &(glThis->unlock_tex));
390         glXDestroyContext(glThis->display, glThis->gl_context);
391         LEAVE_GL();
392         HeapFree(GetProcessHeap(), 0, This->clipping_planes);
393
394         HeapFree(GetProcessHeap(), 0, This);
395         return 0;
396     }
397     return This->ref;
398 }
399
400 HRESULT WINAPI
401 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
402                                        LPD3DDEVICEDESC lpD3DHWDevDesc,
403                                        LPD3DDEVICEDESC lpD3DHELDevDesc)
404 {
405     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
406     D3DDEVICEDESC desc;
407     DWORD dwSize;
408
409     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
410
411     fill_opengl_caps(&desc);
412     dwSize = lpD3DHWDevDesc->dwSize;
413     memset(lpD3DHWDevDesc, 0, dwSize);
414     memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
415
416     dwSize = lpD3DHELDevDesc->dwSize;
417     memset(lpD3DHELDevDesc, 0, dwSize);
418     memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
419
420     TRACE(" returning caps : (no dump function yet)\n");
421
422     return DD_OK;
423 }
424
425 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
426                                           LPD3DENUMPIXELFORMATSCALLBACK cb_2,
427                                           LPVOID context)
428 {
429     DDSURFACEDESC sdesc;
430     LPDDPIXELFORMAT pformat;
431
432     /* Do the texture enumeration */
433     sdesc.dwSize = sizeof(DDSURFACEDESC);
434     sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
435     sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
436     pformat = &(sdesc.ddpfPixelFormat);
437     pformat->dwSize = sizeof(DDPIXELFORMAT);
438     pformat->dwFourCC = 0;
439
440 #if 0
441     /* See argument about the RGBA format for 'packed' texture formats */
442     TRACE("Enumerating GL_RGBA unpacked (32)\n");
443     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
444     pformat->u1.dwRGBBitCount = 32;
445     pformat->u2.dwRBitMask =        0xFF000000;
446     pformat->u3.dwGBitMask =        0x00FF0000;
447     pformat->u4.dwBBitMask =        0x0000FF00;
448     pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
449     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
450     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
451 #endif
452     
453     TRACE("Enumerating GL_RGBA unpacked (32)\n");
454     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
455     pformat->u1.dwRGBBitCount = 32;
456     pformat->u2.dwRBitMask =        0x00FF0000;
457     pformat->u3.dwGBitMask =        0x0000FF00;
458     pformat->u4.dwBBitMask =        0x000000FF;
459     pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
460     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
461     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
462
463 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
464     TRACE("Enumerating GL_RGB unpacked (32)\n");
465     pformat->dwFlags = DDPF_RGB;
466     pformat->u1.dwRGBBitCount = 32;
467     pformat->u2.dwRBitMask =        0x00FF0000;
468     pformat->u3.dwGBitMask =        0x0000FF00;
469     pformat->u4.dwBBitMask =        0x000000FF;
470     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
471     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
472     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
473 #endif
474     
475     TRACE("Enumerating GL_RGB unpacked (24)\n");
476     pformat->dwFlags = DDPF_RGB;
477     pformat->u1.dwRGBBitCount = 24;
478     pformat->u2.dwRBitMask = 0x00FF0000;
479     pformat->u3.dwGBitMask = 0x0000FF00;
480     pformat->u4.dwBBitMask = 0x000000FF;
481     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
482     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
483     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
484
485     /* Note : even if this is an 'emulated' texture format, it needs to be first
486               as some dumb applications seem to rely on that. */
487     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
488     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
489     pformat->u1.dwRGBBitCount = 16;
490     pformat->u2.dwRBitMask =        0x00007C00;
491     pformat->u3.dwGBitMask =        0x000003E0;
492     pformat->u4.dwBBitMask =        0x0000001F;
493     pformat->u5.dwRGBAlphaBitMask = 0x00008000;
494     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
495     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
496
497     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
498     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499     pformat->u1.dwRGBBitCount = 16;
500     pformat->u2.dwRBitMask =        0x00000F00;
501     pformat->u3.dwGBitMask =        0x000000F0;
502     pformat->u4.dwBBitMask =        0x0000000F;
503     pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
504     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
505     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
506
507     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
508     pformat->dwFlags = DDPF_RGB;
509     pformat->u1.dwRGBBitCount = 16;
510     pformat->u2.dwRBitMask = 0x0000F800;
511     pformat->u3.dwGBitMask = 0x000007E0;
512     pformat->u4.dwBBitMask = 0x0000001F;
513     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
514     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
515     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
516
517     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
518     pformat->dwFlags = DDPF_RGB;
519     pformat->u1.dwRGBBitCount = 16;
520     pformat->u2.dwRBitMask = 0x00007C00;
521     pformat->u3.dwGBitMask = 0x000003E0;
522     pformat->u4.dwBBitMask = 0x0000001F;
523     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
524     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
525     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
526     
527 #if 0
528     /* This is a compromise : some games choose the first 16 bit texture format with alpha they
529        find enumerated, others the last one. And both want to have the ARGB one.
530        
531        So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
532     */
533     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
534     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
535     pformat->u1.dwRGBBitCount = 16;
536     pformat->u2.dwRBitMask =        0x0000F000;
537     pformat->u3.dwGBitMask =        0x00000F00;
538     pformat->u4.dwBBitMask =        0x000000F0;
539     pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
540     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
541     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
542
543     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
544     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
545     pformat->u1.dwRGBBitCount = 16;
546     pformat->u2.dwRBitMask =        0x0000F800;
547     pformat->u3.dwGBitMask =        0x000007C0;
548     pformat->u4.dwBBitMask =        0x0000003E;
549     pformat->u5.dwRGBAlphaBitMask = 0x00000001;
550     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
551     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
552 #endif
553
554     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
555     pformat->dwFlags = DDPF_RGB;
556     pformat->u1.dwRGBBitCount = 8;
557     pformat->u2.dwRBitMask =        0x000000E0;
558     pformat->u3.dwGBitMask =        0x0000001C;
559     pformat->u4.dwBBitMask =        0x00000003;
560     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
563
564     TRACE("Enumerating Paletted (8)\n");
565     pformat->dwFlags = DDPF_PALETTEINDEXED8;
566     pformat->u1.dwRGBBitCount = 8;
567     pformat->u2.dwRBitMask =        0x00000000;
568     pformat->u3.dwGBitMask =        0x00000000;
569     pformat->u4.dwBBitMask =        0x00000000;
570     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
571     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
572     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
573
574     TRACE("End of enumeration\n");
575     return DD_OK;
576 }
577
578
579 HRESULT
580 d3ddevice_find(IDirect3DImpl *d3d,
581                LPD3DFINDDEVICESEARCH lpD3DDFS,
582                LPD3DFINDDEVICERESULT lplpD3DDevice)
583 {
584     D3DDEVICEDESC desc;
585   
586     if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
587         (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
588         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
589         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
590     }
591     if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
592         TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
593         if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
594             (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
595             (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
596             TRACE(" no match for this GUID.\n");
597             return DDERR_INVALIDPARAMS;
598         }
599     }
600
601     /* Now return our own GUID */
602     lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
603     fill_opengl_caps(&desc);
604     lplpD3DDevice->ddHwDesc = desc;
605     lplpD3DDevice->ddSwDesc = desc;
606
607     TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
608     
609     return D3D_OK;
610 }
611
612 HRESULT WINAPI
613 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
614                                                LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
615                                                LPVOID lpArg)
616 {
617     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
618     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
619     return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
620 }
621
622 HRESULT WINAPI
623 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
624                                                LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
625                                                LPVOID lpArg)
626 {
627     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
628     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
629     return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
630 }
631
632 HRESULT WINAPI
633 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
634                                               D3DRENDERSTATETYPE dwRenderStateType,
635                                               DWORD dwRenderState)
636 {
637     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
638     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
639
640     /* Call the render state functions */
641     store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
642     set_render_state(This, dwRenderStateType, &This->state_block);
643
644     return DD_OK;
645 }
646
647 HRESULT WINAPI
648 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
649                                               D3DRENDERSTATETYPE dwRenderStateType,
650                                               LPDWORD lpdwRenderState)
651 {
652     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
653     TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
654
655     /* Call the render state functions */
656     get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
657
658     TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
659
660     return DD_OK;
661 }
662
663 HRESULT WINAPI
664 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
665                                           D3DLIGHTSTATETYPE dwLightStateType,
666                                           DWORD dwLightState)
667 {
668     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
669     
670     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
671
672     if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
673         TRACE("Unexpected Light State Type\n");
674         return DDERR_INVALIDPARAMS;
675         
676     if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
677         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
678
679         if (mat != NULL) {
680             ENTER_GL();
681             mat->activate(mat);
682             LEAVE_GL();
683         } else {
684             ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
685         }
686     } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
687         switch (dwLightState) {
688             case D3DCOLOR_MONO:
689                ERR("DDCOLOR_MONO should not happen!\n");
690                break;
691             case D3DCOLOR_RGB:
692                /* We are already in this mode */
693                break;
694             default:
695                ERR("Unknown color model!\n");
696                break;
697         }
698     } else {
699         D3DRENDERSTATETYPE rs;
700         switch (dwLightStateType) {
701
702             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
703                 rs = D3DRENDERSTATE_AMBIENT;
704                 break;          
705             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
706                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
707                 break;
708             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
709                 rs = D3DRENDERSTATE_FOGSTART;
710                 break;
711             case D3DLIGHTSTATE_FOGEND:        /* 6 */
712                 rs = D3DRENDERSTATE_FOGEND;
713                 break;
714             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
715                 rs = D3DRENDERSTATE_FOGDENSITY;
716                 break;
717             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
718                 rs = D3DRENDERSTATE_COLORVERTEX;
719                 break;
720             default:
721                 break;
722         }
723
724         IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
725                                         rs,dwLightState);
726     }
727
728     return DD_OK;
729 }
730
731 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
732 {
733     switch (d3dpt) {
734         case D3DPT_POINTLIST:
735             TRACE("Start POINTS\n");
736             glBegin(GL_POINTS);
737             break;
738
739         case D3DPT_LINELIST:
740             TRACE("Start LINES\n");
741             glBegin(GL_LINES);
742             break;
743
744         case D3DPT_LINESTRIP:
745             TRACE("Start LINE_STRIP\n");
746             glBegin(GL_LINE_STRIP);
747             break;
748
749         case D3DPT_TRIANGLELIST:
750             TRACE("Start TRIANGLES\n");
751             glBegin(GL_TRIANGLES);
752             break;
753
754         case D3DPT_TRIANGLESTRIP:
755             TRACE("Start TRIANGLE_STRIP\n");
756             glBegin(GL_TRIANGLE_STRIP);
757             break;
758
759         case D3DPT_TRIANGLEFAN:
760             TRACE("Start TRIANGLE_FAN\n");
761             glBegin(GL_TRIANGLE_FAN);
762             break;
763
764         default:
765             FIXME("Unhandled primitive %08x\n", d3dpt);
766             break;
767     }
768 }
769
770 /* This function calculate the Z coordinate from Zproj */ 
771 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
772 {
773     float a,b,c,d;
774     /* Assume that X = Y = 0 and W = 1 */
775     a = This->proj_mat->_33;
776     b = This->proj_mat->_34;
777     c = This->proj_mat->_43;
778     d = This->proj_mat->_44;
779     /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
780      * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
781      * And finally Z = (d * Zproj - c) / (a - b * Zproj)
782      */
783     return (d*Zproj - c) / (a - b*Zproj);
784 }
785
786 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
787     int i;
788     
789     TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
790     
791     for (i = 0; i < 3; i++) {
792         BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
793         DWORD elt;
794         for (elt = 0; elt < 0x10000; elt++) {
795             /* We apply the fog transformation and cache the result */
796             DWORD fog_intensity = elt & 0xFF;
797             DWORD vertex_color = (elt >> 8) & 0xFF;
798             fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
799         }
800     }
801 }
802
803 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
804                                            BOOLEAN vertex_transformed,
805                                            BOOLEAN vertex_lit) {
806     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
807   
808     /* Puts GL in the correct lighting / transformation mode */
809     if ((vertex_transformed == FALSE) && 
810         (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
811         /* Need to put the correct transformation again if we go from Transformed
812            vertices to non-transformed ones.
813         */
814         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
815                            This->world_mat, This->view_mat, This->proj_mat);
816         glThis->transform_state = GL_TRANSFORM_NORMAL;
817
818     } else if ((vertex_transformed == TRUE) &&
819                (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
820         /* Set our orthographic projection */
821         glThis->transform_state = GL_TRANSFORM_ORTHO;
822         d3ddevice_set_ortho(This);
823     }
824
825     /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
826              if no fogging state change occured */
827     if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
828         if (vertex_transformed == TRUE) {
829             glDisable(GL_FOG);
830             /* Now check if our fog_table still corresponds to the current vertex color.
831                Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
832             if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  0) & 0xFF)) ||
833                 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  8) & 0xFF)) ||
834                 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
835                 /* We need to rebuild our fog table.... */
836                 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
837             }
838         } else {
839             if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
840                 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
841                     case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break; 
842                     case D3DFOG_EXP:    glFogi(GL_FOG_MODE, GL_EXP); break; 
843                     case D3DFOG_EXP2:   glFogi(GL_FOG_MODE, GL_EXP2); break;
844                 }
845                 if (vertex_lit == FALSE) {
846                     glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
847                     glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
848                 } else {
849                     /* Special case of 'pixel fog' */
850                     glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
851                     glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
852                 }
853                 glEnable(GL_FOG);
854             } else {
855                 glDisable(GL_FOG);
856             }
857         }
858     } else {
859         glDisable(GL_FOG);
860     }
861     
862     /* Handle the 'no-normal' case */
863     if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
864         glEnable(GL_LIGHTING);
865     else 
866         glDisable(GL_LIGHTING);
867
868     /* Handle the code for pre-vertex material properties */
869     if (vertex_transformed == FALSE) {
870         if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
871             (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
872             if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
873                 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
874                 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
875                 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
876                 glEnable(GL_COLOR_MATERIAL);
877             }
878         }
879     }
880 }
881
882
883 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
884                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
885 {
886     D3DDRAWPRIMITIVESTRIDEDDATA strided;
887
888     switch (d3dvt) {
889         case D3DVT_VERTEX: {
890             strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
891             strided.position.dwStride = sizeof(D3DVERTEX);
892             strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
893             strided.normal.dwStride = sizeof(D3DVERTEX);
894             strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
895             strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
896             draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
897         } break;
898
899         case D3DVT_LVERTEX: {
900             strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
901             strided.position.dwStride = sizeof(D3DLVERTEX);
902             strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
903             strided.diffuse.dwStride = sizeof(D3DLVERTEX);
904             strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
905             strided.specular.dwStride = sizeof(D3DLVERTEX);
906             strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
907             strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
908             draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
909         } break;
910
911         case D3DVT_TLVERTEX: {
912             strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
913             strided.position.dwStride = sizeof(D3DTLVERTEX);
914             strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
915             strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
916             strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
917             strided.specular.dwStride = sizeof(D3DTLVERTEX);
918             strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
919             strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
920             draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
921         } break;
922
923         default:
924             FIXME("Unhandled vertex type %08x\n", d3dvt);
925             break;
926     }
927 }
928
929 HRESULT WINAPI
930 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
931                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
932                                        D3DVERTEXTYPE d3dvtVertexType,
933                                        LPVOID lpvVertices,
934                                        DWORD dwVertexCount,
935                                        DWORD dwFlags)
936 {
937     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
938
939     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
940     if (TRACE_ON(ddraw)) {
941         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
942     }
943
944     draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
945                    
946     return DD_OK;
947 }
948
949 HRESULT WINAPI
950 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
951                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
952                                               D3DVERTEXTYPE d3dvtVertexType,
953                                               LPVOID lpvVertices,
954                                               DWORD dwVertexCount,
955                                               LPWORD dwIndices,
956                                               DWORD dwIndexCount,
957                                               DWORD dwFlags)
958 {
959     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
960     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
961     if (TRACE_ON(ddraw)) {
962         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
963     }
964
965     draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
966     
967     return DD_OK;
968 }
969
970 HRESULT WINAPI
971 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
972                                              LPD3DEXECUTEBUFFERDESC lpDesc,
973                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
974                                              IUnknown* pUnkOuter)
975 {
976     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
977     IDirect3DExecuteBufferImpl *ret;
978     HRESULT ret_value;
979     
980     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
981
982     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
983     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
984
985     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
986     
987     return ret_value;
988 }
989
990 /* These are the various handler used in the generic path */
991 inline static void handle_xyz(D3DVALUE *coords) {
992     glVertex3fv(coords);
993 }
994 inline static void handle_xyzrhw(D3DVALUE *coords) {
995     if (coords[3] < 1e-8)
996         glVertex3fv(coords);
997     else {
998         GLfloat w = 1.0 / coords[3];
999         
1000         glVertex4f(coords[0] * w,
1001                    coords[1] * w,
1002                    coords[2] * w,
1003                    w);
1004     }
1005 }
1006 inline static void handle_normal(D3DVALUE *coords) {
1007     glNormal3fv(coords);
1008 }
1009
1010 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1011     if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1012         (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1013         glColor4ub((*color >> 16) & 0xFF,
1014                    (*color >>  8) & 0xFF,
1015                    (*color >>  0) & 0xFF,
1016                    (*color >> 24) & 0xFF);
1017     } else {
1018         glColor3ub((*color >> 16) & 0xFF,
1019                    (*color >>  8) & 0xFF,
1020                    (*color >>  0) & 0xFF);    
1021     }
1022 }
1023
1024 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1025     glColor4ub((*color >> 16) & 0xFF,
1026                (*color >>  8) & 0xFF,
1027                (*color >>  0) & 0xFF,
1028                (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1029 }
1030
1031 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1032     if ((lighted == FALSE) &&
1033         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1034         (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1035         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1036             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1037             handle_diffuse_base(sb, color);
1038         }
1039         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1040             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1041             handle_diffuse_base(sb, color);
1042         }
1043         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1044             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1045             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1046             handle_diffuse_base(sb, color);
1047         }
1048         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1049             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1050             handle_diffuse_base(sb, color);
1051         }
1052     } else {
1053         handle_diffuse_base(sb, color);
1054     }    
1055 }
1056
1057 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1058     if ((lighted == FALSE) &&
1059         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1060         (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1061         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1062             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1063             handle_specular_base(sb, color);
1064         }
1065         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1066             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1067             handle_specular_base(sb, color);
1068         }
1069         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1070             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1071             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1072             handle_specular_base(sb, color);
1073         }
1074         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1075             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1076             handle_specular_base(sb, color);
1077         }
1078     }
1079     /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1080 }
1081
1082 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1083     if (lighted == TRUE) {
1084         DWORD color = *color_d;
1085         if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1086             /* Special case where the specular value is used to do fogging */
1087             BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1088             color &= 0xFF000000; /* Only keep the alpha component */
1089             color |= fog_table[((*color_d >>  0) & 0xFF) << 8 | fog_intensity] <<  0;
1090             color |= fog_table[((*color_d >>  8) & 0xFF) << 8 | fog_intensity] <<  8;
1091             color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1092         }
1093         if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1094             /* Standard specular value in transformed mode. TODO */
1095         }
1096         handle_diffuse_base(sb, &color);
1097     } else {
1098         if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1099             handle_diffuse(sb, color_d, FALSE);
1100             handle_specular(sb, color_s, FALSE);
1101         } else {
1102             /* In that case, only put the diffuse color... */
1103             handle_diffuse_base(sb, color_d);
1104         }
1105     }
1106 }
1107
1108 inline static void handle_texture(D3DVALUE *coords) {
1109     glTexCoord2fv(coords);
1110 }
1111 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1112     /* For the moment, draw only the first texture.. */
1113     if (tex_index == 0) glTexCoord2fv(coords);
1114 }
1115
1116 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1117                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1118                                    DWORD d3dvtVertexType,
1119                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1120                                    DWORD dwVertexCount,
1121                                    LPWORD dwIndices,
1122                                    DWORD dwIndexCount,
1123                                    DWORD dwFlags)
1124 {
1125     BOOLEAN vertex_lighted = FALSE;
1126     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1127     int num_active_stages = 0;
1128
1129     ENTER_GL();
1130     if (glThis->state == SURFACE_MEMORY) {
1131         This->flush_to_framebuffer(This, NULL);
1132     }
1133     LEAVE_GL();
1134
1135     glThis->state = SURFACE_GL;
1136     
1137     /* Compute the number of active texture stages */
1138     while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1139
1140     /* This is to prevent 'thread contention' between a thread locking the device and another
1141        doing 3D display on it... */
1142     EnterCriticalSection(&(This->crit));   
1143     
1144     if (TRACE_ON(ddraw)) {
1145         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1146     }
1147
1148     ENTER_GL();
1149     
1150     /* Just a hack for now.. Will have to find better algorithm :-/ */
1151     if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1152         vertex_lighted = TRUE;
1153     } else {
1154         if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1155     }
1156     
1157     draw_primitive_handle_GL_state(This,
1158                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1159                                    vertex_lighted);
1160     draw_primitive_start_GL(d3dptPrimitiveType);
1161
1162     /* Some fast paths first before the generic case.... */
1163     if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1164         int index;
1165         
1166         for (index = 0; index < dwIndexCount; index++) {
1167             int i = (dwIndices == NULL) ? index : dwIndices[index];
1168             D3DVALUE *normal = 
1169               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1170             D3DVALUE *tex_coord =
1171               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1172             D3DVALUE *position =
1173               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1174             
1175             handle_normal(normal);
1176             handle_texture(tex_coord);
1177             handle_xyz(position);
1178             
1179             TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1180                                position[0], position[1], position[2],
1181                                normal[0], normal[1], normal[2],
1182                                tex_coord[0], tex_coord[1]);
1183         }
1184     } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1185         int index;
1186         
1187         for (index = 0; index < dwIndexCount; index++) {
1188             int i = (dwIndices == NULL) ? index : dwIndices[index];
1189             DWORD *color_d = 
1190               (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1191             DWORD *color_s = 
1192               (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1193             D3DVALUE *tex_coord =
1194               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1195             D3DVALUE *position =
1196               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1197
1198             handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1199             handle_texture(tex_coord);
1200             handle_xyzrhw(position);
1201
1202             TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1203                                position[0], position[1], position[2], position[3], 
1204                                (*color_d >> 16) & 0xFF,
1205                                (*color_d >>  8) & 0xFF,
1206                                (*color_d >>  0) & 0xFF,
1207                                (*color_d >> 24) & 0xFF,
1208                                (*color_s >> 16) & 0xFF,
1209                                (*color_s >>  8) & 0xFF,
1210                                (*color_s >>  0) & 0xFF,
1211                                (*color_s >> 24) & 0xFF,
1212                                tex_coord[0], tex_coord[1]);
1213         } 
1214     } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1215                ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1216         /* This is the 'slow path' but that should support all possible vertex formats out there...
1217            Note that people should write a fast path for all vertex formats out there...
1218         */  
1219         int index;
1220         int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1221         static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1222           
1223         for (index = 0; index < dwIndexCount; index++) {
1224             int i = (dwIndices == NULL) ? index : dwIndices[index];
1225             int tex_stage;
1226
1227             if (d3dvtVertexType & D3DFVF_NORMAL) { 
1228                 D3DVALUE *normal = 
1229                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);         
1230                 handle_normal(normal);
1231             }
1232             if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1233                 DWORD *color_d = 
1234                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1235                 DWORD *color_s = 
1236                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1237                 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1238             } else {
1239                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1240                     DWORD *color_s = 
1241                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1242                     handle_specular(&(This->state_block), color_s, vertex_lighted);
1243                 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1244                     DWORD *color_d = 
1245                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1246                     handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1247                 }
1248             }
1249
1250             for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1251                 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1252                 if (tex_index >= num_tex_index) {
1253                     handle_textures((D3DVALUE *) no_index, tex_stage);
1254                  } else {
1255                      D3DVALUE *tex_coord =
1256                        (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1257                                      i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1258                      handle_textures(tex_coord, tex_stage);
1259                 }
1260             }
1261             
1262             if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1263                 D3DVALUE *position =
1264                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1265                 handle_xyz(position);
1266             } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1267                 D3DVALUE *position =
1268                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1269                 handle_xyzrhw(position);
1270             }
1271
1272             if (TRACE_ON(ddraw_geom)) {
1273                 int tex_index;
1274
1275                 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1276                     D3DVALUE *position =
1277                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1278                     TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1279                 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1280                     D3DVALUE *position =
1281                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1282                     TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1283                 }
1284                 if (d3dvtVertexType & D3DFVF_NORMAL) { 
1285                     D3DVALUE *normal = 
1286                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);     
1287                     TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1288                 }
1289                 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1290                     DWORD *color_d = 
1291                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1292                     TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1293                                        (*color_d >> 16) & 0xFF,
1294                                        (*color_d >>  8) & 0xFF,
1295                                        (*color_d >>  0) & 0xFF,
1296                                        (*color_d >> 24) & 0xFF);
1297                 }
1298                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1299                     DWORD *color_s = 
1300                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1301                     TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1302                                        (*color_s >> 16) & 0xFF,
1303                                        (*color_s >>  8) & 0xFF,
1304                                        (*color_s >>  0) & 0xFF,
1305                                        (*color_s >> 24) & 0xFF);
1306                 }
1307                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1308                     D3DVALUE *tex_coord =
1309                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1310                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1311                     TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1312                 }
1313                 TRACE_(ddraw_geom)("\n");
1314             }
1315         }
1316     } else {
1317         ERR(" matrix weighting not handled yet....\n");
1318     }
1319     
1320     glEnd();
1321
1322     /* Whatever the case, disable the color material stuff */
1323     glDisable(GL_COLOR_MATERIAL);
1324
1325     LEAVE_GL();
1326     TRACE("End\n");    
1327
1328     LeaveCriticalSection(&(This->crit));
1329 }
1330
1331 HRESULT WINAPI
1332 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1333                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1334                                           DWORD d3dvtVertexType,
1335                                           LPVOID lpvVertices,
1336                                           DWORD dwVertexCount,
1337                                           DWORD dwFlags)
1338 {
1339     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1340     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1341
1342     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1343     if (TRACE_ON(ddraw)) {
1344         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1345     }
1346
1347     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1348     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1349     
1350     return DD_OK;
1351 }
1352
1353 HRESULT WINAPI
1354 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1355                                                  D3DPRIMITIVETYPE d3dptPrimitiveType,
1356                                                  DWORD d3dvtVertexType,
1357                                                  LPVOID lpvVertices,
1358                                                  DWORD dwVertexCount,
1359                                                  LPWORD dwIndices,
1360                                                  DWORD dwIndexCount,
1361                                                  DWORD dwFlags)
1362 {
1363     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1364     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1365
1366     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1367     if (TRACE_ON(ddraw)) {
1368         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1369     }
1370
1371     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1372     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1373     
1374     return DD_OK;
1375 }
1376
1377 HRESULT WINAPI
1378 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1379                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1380                                                    DWORD dwVertexType,
1381                                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1382                                                    DWORD dwVertexCount,
1383                                                    DWORD dwFlags)
1384 {
1385     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1386
1387     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1388     if (TRACE_ON(ddraw)) {
1389         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1390     }
1391     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1392
1393     return DD_OK;
1394 }
1395
1396 HRESULT WINAPI
1397 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1398                                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1399                                                           DWORD dwVertexType,
1400                                                           LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1401                                                           DWORD dwVertexCount,
1402                                                           LPWORD lpIndex,
1403                                                           DWORD dwIndexCount,
1404                                                           DWORD dwFlags)
1405 {
1406     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1407
1408     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1409     if (TRACE_ON(ddraw)) {
1410         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1411     }
1412
1413     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1414
1415     return DD_OK;
1416 }
1417
1418 HRESULT WINAPI
1419 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1420                                             D3DPRIMITIVETYPE d3dptPrimitiveType,
1421                                             LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1422                                             DWORD dwStartVertex,
1423                                             DWORD dwNumVertices,
1424                                             DWORD dwFlags)
1425 {
1426     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1427     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1428     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1429
1430     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1431     if (TRACE_ON(ddraw)) {
1432         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1433     }
1434
1435     if (vb_impl->processed == TRUE) {
1436         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1437         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1438
1439         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1440         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1441                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1442
1443         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1444         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1445
1446     } else {
1447         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1448         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1449     }
1450
1451     return DD_OK;
1452 }
1453
1454 HRESULT WINAPI
1455 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1456                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1457                                                    LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1458                                                    DWORD dwStartVertex,
1459                                                    DWORD dwNumVertices,
1460                                                    LPWORD lpwIndices,
1461                                                    DWORD dwIndexCount,
1462                                                    DWORD dwFlags)
1463 {
1464     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1465     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1466     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1467     
1468     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1469     if (TRACE_ON(ddraw)) {
1470         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1471     }
1472
1473     if (vb_impl->processed == TRUE) {
1474         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1475         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1476
1477         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1478         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1479                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1480
1481         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1482         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1483
1484     } else {
1485         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1486         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1487     }
1488
1489     return DD_OK;
1490 }
1491
1492 static GLenum
1493 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1494 {
1495     GLenum gl_state;
1496
1497     if (dwMipState == D3DTFP_NONE) {
1498         switch (dwMinState) {
1499             case D3DTFN_POINT:  gl_state = GL_NEAREST; break;
1500             case D3DTFN_LINEAR: gl_state = GL_LINEAR;  break;
1501             default:            gl_state = GL_LINEAR;  break;
1502         }
1503     } else if (dwMipState == D3DTFP_POINT) {
1504         switch (dwMinState) {
1505             case D3DTFN_POINT:  gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1506             case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST;  break;
1507             default:            gl_state = GL_LINEAR_MIPMAP_NEAREST;  break;
1508         }
1509     } else {
1510         switch (dwMinState) {
1511             case D3DTFN_POINT:  gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1512             case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR;  break;
1513             default:            gl_state = GL_LINEAR_MIPMAP_LINEAR;  break;
1514         }
1515     }
1516     return gl_state;
1517 }
1518
1519 static GLenum
1520 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1521 {
1522     GLenum gl_state;
1523
1524     switch (dwState) {
1525         case D3DTFG_POINT:
1526             gl_state = GL_NEAREST;
1527             break;
1528         case D3DTFG_LINEAR:
1529             gl_state = GL_LINEAR;
1530             break;
1531         default:
1532             gl_state = GL_LINEAR;
1533             break;
1534     }
1535     return gl_state;
1536 }
1537
1538 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1539 static BOOLEAN
1540 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1541 {
1542     BOOLEAN is_complement = FALSE;
1543     BOOLEAN is_alpha_replicate = FALSE;
1544     BOOLEAN handled = TRUE;
1545     GLenum src;
1546     BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1547     int num;
1548     
1549     if (is_color) {
1550         if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1551         else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1552         else {
1553             handled = FALSE;
1554             num = 0;
1555         }
1556         if (tex_op == D3DTOP_SELECTARG2) {
1557             num = 1 - num;
1558         }
1559     } else {
1560         if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1561         else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1562         else {
1563             handled = FALSE;
1564             num = 0;
1565         }
1566         if (tex_op == D3DTOP_SELECTARG2) {
1567             num = 1 - num;
1568         }
1569     }
1570     
1571     if (dwState & D3DTA_COMPLEMENT) {
1572         is_complement = TRUE;
1573     }
1574     if (dwState & D3DTA_ALPHAREPLICATE) {
1575         is_alpha_replicate = TRUE;
1576     }
1577     dwState &= D3DTA_SELECTMASK;
1578     if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1579         dwState = D3DTA_DIFFUSE;
1580     }
1581
1582     switch (dwState) {
1583         case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1584         case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1585         case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1586         case D3DTA_TFACTOR: {
1587             /* Get the constant value from the current rendering state */
1588             GLfloat color[4];
1589             DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1590             
1591             color[0] = ((col >> 16) & 0xFF) / 255.0f;
1592             color[1] = ((col >>  8) & 0xFF) / 255.0f;
1593             color[2] = ((col >>  0) & 0xFF) / 255.0f;
1594             color[3] = ((col >> 24) & 0xFF) / 255.0f;
1595             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1596             
1597             src = GL_CONSTANT_EXT;
1598         } break;
1599         default: src = GL_TEXTURE; handled = FALSE; break;
1600     }
1601
1602     if (is_color) {
1603         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1604         if (is_alpha_replicate) {
1605             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1606         } else {
1607             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1608         }
1609     } else {
1610         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1611         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1612     }
1613
1614     return handled;
1615 }
1616
1617 HRESULT WINAPI
1618 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1619                                                  DWORD dwStage,
1620                                                  D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1621                                                  DWORD dwState)
1622 {
1623     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1624     const char *type;
1625     DWORD prev_state;
1626     
1627     TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1628
1629     if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1630
1631     switch (d3dTexStageStateType) {
1632 #define GEN_CASE(a) case a: type = #a; break
1633         GEN_CASE(D3DTSS_COLOROP);
1634         GEN_CASE(D3DTSS_COLORARG1);
1635         GEN_CASE(D3DTSS_COLORARG2);
1636         GEN_CASE(D3DTSS_ALPHAOP);
1637         GEN_CASE(D3DTSS_ALPHAARG1);
1638         GEN_CASE(D3DTSS_ALPHAARG2);
1639         GEN_CASE(D3DTSS_BUMPENVMAT00);
1640         GEN_CASE(D3DTSS_BUMPENVMAT01);
1641         GEN_CASE(D3DTSS_BUMPENVMAT10);
1642         GEN_CASE(D3DTSS_BUMPENVMAT11);
1643         GEN_CASE(D3DTSS_TEXCOORDINDEX);
1644         GEN_CASE(D3DTSS_ADDRESS);
1645         GEN_CASE(D3DTSS_ADDRESSU);
1646         GEN_CASE(D3DTSS_ADDRESSV);
1647         GEN_CASE(D3DTSS_BORDERCOLOR);
1648         GEN_CASE(D3DTSS_MAGFILTER);
1649         GEN_CASE(D3DTSS_MINFILTER);
1650         GEN_CASE(D3DTSS_MIPFILTER);
1651         GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1652         GEN_CASE(D3DTSS_MAXMIPLEVEL);
1653         GEN_CASE(D3DTSS_MAXANISOTROPY);
1654         GEN_CASE(D3DTSS_BUMPENVLSCALE);
1655         GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1656         GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1657 #undef GEN_CASE
1658         default: type = "UNKNOWN";
1659     }
1660
1661     /* Store the values in the state array */
1662     prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1663     This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1664     /* Some special cases when one state modifies more than one... */
1665     if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1666         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1667         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1668     }
1669     
1670     switch (d3dTexStageStateType) {
1671         case D3DTSS_MINFILTER:
1672         case D3DTSS_MIPFILTER:
1673             if (TRACE_ON(ddraw)) {
1674                 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1675                     switch ((D3DTEXTUREMINFILTER) dwState) {
1676                         case D3DTFN_POINT:  TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1677                         case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1678                         default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1679                     }
1680                 } else {
1681                     switch ((D3DTEXTUREMIPFILTER) dwState) {
1682                         case D3DTFP_NONE:   TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1683                         case D3DTFP_POINT:  TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1684                         case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1685                         default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1686                     }
1687                 }
1688             }
1689
1690             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1691                             convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1692                                                      This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1693             break;
1694             
1695         case D3DTSS_MAGFILTER:
1696             if (TRACE_ON(ddraw)) {
1697                 switch ((D3DTEXTUREMAGFILTER) dwState) {
1698                     case D3DTFG_POINT:  TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1699                     case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1700                     default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1701                 }
1702             }
1703             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1704             break;
1705
1706         case D3DTSS_ADDRESS:
1707         case D3DTSS_ADDRESSU:
1708         case D3DTSS_ADDRESSV: {
1709             GLenum arg = GL_REPEAT; /* Default value */
1710             switch ((D3DTEXTUREADDRESS) dwState) {
1711                 case D3DTADDRESS_WRAP:   TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break;
1712                 case D3DTADDRESS_CLAMP:  TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break;
1713                 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break;
1714 #if defined(GL_VERSION_1_4)
1715                 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break;
1716 #elif defined(GL_ARB_texture_mirrored_repeat)
1717                 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break;
1718 #endif
1719                 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1720             }
1721             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1722                 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1723                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1724             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1725                 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1726                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1727         } break;
1728
1729         case D3DTSS_ALPHAOP:
1730         case D3DTSS_COLOROP: {
1731             int scale = 1;
1732             GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1733             const char *value;
1734             int handled = 1;
1735             
1736             switch (dwState) {
1737 #define GEN_CASE(a) case a: value = #a; break
1738                 GEN_CASE(D3DTOP_DISABLE);
1739                 GEN_CASE(D3DTOP_SELECTARG1);
1740                 GEN_CASE(D3DTOP_SELECTARG2);
1741                 GEN_CASE(D3DTOP_MODULATE);
1742                 GEN_CASE(D3DTOP_MODULATE2X);
1743                 GEN_CASE(D3DTOP_MODULATE4X);
1744                 GEN_CASE(D3DTOP_ADD);
1745                 GEN_CASE(D3DTOP_ADDSIGNED);
1746                 GEN_CASE(D3DTOP_ADDSIGNED2X);
1747                 GEN_CASE(D3DTOP_SUBTRACT);
1748                 GEN_CASE(D3DTOP_ADDSMOOTH);
1749                 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1750                 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1751                 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1752                 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1753                 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1754                 GEN_CASE(D3DTOP_PREMODULATE);
1755                 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1756                 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1757                 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1758                 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1759                 GEN_CASE(D3DTOP_BUMPENVMAP);
1760                 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1761                 GEN_CASE(D3DTOP_DOTPRODUCT3);
1762                 GEN_CASE(D3DTOP_FORCE_DWORD);
1763 #undef GEN_CASE
1764                 default: value = "UNKNOWN";
1765             }
1766
1767             if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1768                 glDisable(GL_TEXTURE_2D);
1769                 TRACE(" disabling 2D texturing.\n");
1770             } else {
1771                 /* Re-enable texturing */
1772                 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1773                     glEnable(GL_TEXTURE_2D);
1774                     TRACE(" enabling 2D texturing.\n");
1775                 }
1776                 
1777                 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1778                 if (dwState != D3DTOP_DISABLE) {
1779                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1780                 }
1781
1782                 /* Now set up the operand correctly */
1783                 switch (dwState) {
1784                     case D3DTOP_DISABLE:
1785                         /* Contrary to the docs, alpha can be disabled when colorop is enabled
1786                            and it works, so ignore this op */
1787                         TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1788                         break;
1789
1790                     case D3DTOP_SELECTARG1:
1791                     case D3DTOP_SELECTARG2:
1792                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1793                         break;
1794                         
1795                     case D3DTOP_MODULATE4X:
1796                         scale = scale * 2;  /* Drop through */
1797                     case D3DTOP_MODULATE2X:
1798                         scale = scale * 2;  /* Drop through */
1799                     case D3DTOP_MODULATE:
1800                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1801                         break;
1802
1803                     case D3DTOP_ADD:
1804                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1805                         break;
1806
1807                     case D3DTOP_ADDSIGNED2X:
1808                         scale = scale * 2;  /* Drop through */
1809                     case D3DTOP_ADDSIGNED:
1810                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1811                         break;
1812
1813                     default:
1814                         handled = FALSE;
1815                         break;
1816                 }
1817             }
1818
1819             if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1820                 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1821                 /* Switch the arguments if needed... */
1822                 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1823                     handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1824                                             This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1825                                             dwState);
1826                     handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1827                                             This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1828                                             dwState);
1829                 } else {
1830                     handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1831                                             This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1832                                             dwState);
1833                     handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1834                                             This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1835                                             dwState);
1836                 }
1837             }
1838             
1839             if (handled) {
1840                 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1841                     glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1842                 } else {
1843                     glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1844                 }                       
1845                 TRACE(" Stage type is : %s => %s\n", type, value);
1846             } else {
1847                 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1848             }
1849         } break;
1850
1851         case D3DTSS_COLORARG1:
1852         case D3DTSS_COLORARG2:
1853         case D3DTSS_ALPHAARG1:
1854         case D3DTSS_ALPHAARG2: {
1855             const char *value, *value_comp = "", *value_alpha = "";
1856             BOOLEAN handled;
1857             D3DTEXTUREOP tex_op;
1858             
1859             switch (dwState & D3DTA_SELECTMASK) {
1860 #define GEN_CASE(a) case a: value = #a; break
1861                 GEN_CASE(D3DTA_DIFFUSE);
1862                 GEN_CASE(D3DTA_CURRENT);
1863                 GEN_CASE(D3DTA_TEXTURE);
1864                 GEN_CASE(D3DTA_TFACTOR);
1865                 GEN_CASE(D3DTA_SPECULAR);
1866 #undef GEN_CASE
1867                 default: value = "UNKNOWN";
1868             }
1869             if (dwState & D3DTA_COMPLEMENT) {
1870                 value_comp = " | D3DTA_COMPLEMENT";
1871             }
1872             if (dwState & D3DTA_ALPHAREPLICATE) {
1873                 value_alpha = " | D3DTA_ALPHAREPLICATE";
1874             }
1875
1876             if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1877                 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1878             } else {
1879                 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1880             }
1881             
1882             handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1883             
1884             if (handled) {
1885                 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1886             } else {
1887                 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1888             }
1889         } break;
1890
1891         case D3DTSS_MIPMAPLODBIAS: {
1892             D3DVALUE value = *((D3DVALUE *) &dwState);
1893             BOOLEAN handled = TRUE;
1894             
1895             if (value != 0.0)
1896                 handled = FALSE;
1897
1898             if (handled) {
1899                 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1900             } else {
1901                 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1902             }
1903         } break;
1904
1905         case D3DTSS_MAXMIPLEVEL: 
1906             if (dwState == 0) {
1907                 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1908             } else {
1909                 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1910             }
1911             break;
1912
1913         case D3DTSS_BORDERCOLOR: {
1914             GLfloat color[4];
1915
1916             color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1917             color[1] = ((dwState >>  8) & 0xFF) / 255.0;
1918             color[2] = ((dwState >>  0) & 0xFF) / 255.0;
1919             color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1920
1921             glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1922
1923             TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1924                   ((dwState >> 16) & 0xFF),
1925                   ((dwState >>  8) & 0xFF),
1926                   ((dwState >>  0) & 0xFF),
1927                   ((dwState >> 24) & 0xFF));
1928         } break;
1929             
1930         case D3DTSS_TEXCOORDINDEX: {
1931             BOOLEAN handled = TRUE;
1932             const char *value;
1933             
1934             switch (dwState & 0xFFFF0000) {
1935 #define GEN_CASE(a) case a: value = #a; break
1936                 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1937                 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1938                 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1939                 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1940 #undef GEN_CASE
1941                 default: value = "UNKNOWN";
1942             }
1943             if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1944                 handled = FALSE;
1945
1946             if (handled) {
1947                 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1948             } else {
1949                 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1950             }
1951         } break;
1952             
1953         case D3DTSS_TEXTURETRANSFORMFLAGS: {
1954             const char *projected = "", *value;
1955             BOOLEAN handled = TRUE;
1956             switch (dwState & 0xFF) {
1957 #define GEN_CASE(a) case a: value = #a; break
1958                 GEN_CASE(D3DTTFF_DISABLE);
1959                 GEN_CASE(D3DTTFF_COUNT1);
1960                 GEN_CASE(D3DTTFF_COUNT2);
1961                 GEN_CASE(D3DTTFF_COUNT3);
1962                 GEN_CASE(D3DTTFF_COUNT4);
1963 #undef GEN_CASE
1964                 default: value = "UNKNOWN";
1965             }
1966             if (dwState & D3DTTFF_PROJECTED) {
1967                 projected = " | D3DTTFF_PROJECTED";
1968                 handled = FALSE;
1969             }
1970
1971             if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1972                 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1973             }
1974
1975             if (handled == TRUE) {
1976                 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1977             } else {
1978                 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1979             }
1980         } break;
1981             
1982         default:
1983             FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1984             break;
1985     }
1986    
1987     return DD_OK;
1988 }
1989
1990 HRESULT WINAPI
1991 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1992                                        DWORD dwStage,
1993                                        LPDIRECTDRAWSURFACE7 lpTexture2)
1994 {
1995     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1996     
1997     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1998     
1999     if (dwStage > 0) return DD_OK;
2000
2001     if (This->current_texture[dwStage] != NULL) {
2002         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2003     }
2004     
2005     ENTER_GL();
2006     if (lpTexture2 == NULL) {
2007         This->current_texture[dwStage] = NULL;
2008
2009         TRACE(" disabling 2D texturing.\n");
2010         glBindTexture(GL_TEXTURE_2D, 0);
2011         glDisable(GL_TEXTURE_2D);
2012     } else {
2013         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2014         GLint max_mip_level;
2015         
2016         This->current_texture[dwStage] = tex_impl;
2017         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2018
2019         if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2020             /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2021             glEnable(GL_TEXTURE_2D);
2022             TRACE(" enabling 2D texturing.\n");
2023         }
2024         gltex_upload_texture(tex_impl);
2025
2026         if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2027             max_mip_level = 0;
2028         } else {
2029             max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2030         }
2031         
2032         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
2033                         convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2034         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2035                         convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2036                                                   This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2037         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2038     }
2039     LEAVE_GL();
2040     
2041     return DD_OK;
2042 }
2043
2044 HRESULT WINAPI
2045 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2046                                  LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2047 {
2048     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2049     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2050
2051     fill_opengl_caps_7(lpD3DHELDevDesc);
2052
2053     TRACE(" returning caps : no dump function yet.\n");
2054
2055     return DD_OK;
2056 }
2057
2058 HRESULT WINAPI
2059 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2060                                      LPD3DMATERIAL7 lpMat)
2061 {
2062     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2063     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2064     
2065     if (TRACE_ON(ddraw)) {
2066         TRACE(" material is : \n");
2067         dump_D3DMATERIAL7(lpMat);
2068     }
2069     
2070     This->current_material = *lpMat;
2071
2072     glMaterialfv(GL_FRONT_AND_BACK,
2073                  GL_DIFFUSE,
2074                  (float *) &(This->current_material.u.diffuse));
2075     glMaterialfv(GL_FRONT_AND_BACK,
2076                  GL_AMBIENT,
2077                  (float *) &(This->current_material.u1.ambient));
2078     glMaterialfv(GL_FRONT_AND_BACK,
2079                  GL_SPECULAR,
2080                  (float *) &(This->current_material.u2.specular));
2081     glMaterialfv(GL_FRONT_AND_BACK,
2082                  GL_EMISSION,
2083                  (float *) &(This->current_material.u3.emissive));
2084     glMaterialf(GL_FRONT_AND_BACK,
2085                 GL_SHININESS,
2086                 This->current_material.u4.power); /* Not sure about this... */
2087
2088     return DD_OK;
2089 }
2090
2091
2092 HRESULT WINAPI
2093 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2094                                   DWORD dwLightIndex,
2095                                   LPD3DLIGHT7 lpLight)
2096 {
2097     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2098     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2099     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2100     
2101     if (TRACE_ON(ddraw)) {
2102         TRACE(" setting light : \n");
2103         dump_D3DLIGHT7(lpLight);
2104     }
2105     
2106     if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2107     This->set_lights |= 0x00000001 << dwLightIndex;
2108     This->light_parameters[dwLightIndex] = *lpLight;
2109
2110     /* Some checks to print out nice warnings :-) */
2111     switch (lpLight->dltType) {
2112         case D3DLIGHT_DIRECTIONAL:
2113         case D3DLIGHT_POINT:
2114             /* These are handled properly... */
2115             break;
2116             
2117         case D3DLIGHT_SPOT:
2118             if ((lpLight->dvTheta != 0.0) ||
2119                 (lpLight->dvTheta != lpLight->dvPhi)) {
2120                 ERR("dvTheta not fully supported yet !\n");
2121             }
2122             break;
2123
2124         default:
2125             ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2126     }
2127     
2128     /* This will force the Light setting on next drawing of primitives */
2129     glThis->transform_state = GL_TRANSFORM_NONE;
2130     
2131     return DD_OK;
2132 }
2133
2134 HRESULT WINAPI
2135 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2136                                      DWORD dwLightIndex,
2137                                      BOOL bEnable)
2138 {
2139     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2140     TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2141     
2142     if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2143
2144     if (bEnable) {
2145         if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2146             /* Set the default parameters.. */
2147             TRACE(" setting default light parameters...\n");
2148             GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2149         }
2150         glEnable(GL_LIGHT0 + dwLightIndex);
2151         if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2152             /* This light gets active... Need to update its parameters to GL before the next drawing */
2153             IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2154             
2155             This->active_lights |= 0x00000001 << dwLightIndex;
2156             glThis->transform_state = GL_TRANSFORM_NONE;
2157         }
2158     } else {
2159         glDisable(GL_LIGHT0 + dwLightIndex);
2160         This->active_lights &= ~(0x00000001 << dwLightIndex);
2161     }
2162
2163     return DD_OK;
2164 }
2165
2166 HRESULT  WINAPI  
2167 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation) 
2168 {
2169     ICOM_THIS(IDirect3DDeviceImpl,iface);
2170     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2171
2172     TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2173
2174     if (dwIndex >= This->max_clipping_planes) {
2175         return DDERR_INVALIDPARAMS;
2176     }
2177
2178     TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2179
2180     memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2181     
2182     /* This is to force the reset of the transformation matrices on the next drawing.
2183      * This is needed to use the correct matrices for the various clipping planes.
2184      */
2185     glThis->transform_state = GL_TRANSFORM_NONE;
2186     
2187     return D3D_OK;
2188 }
2189
2190 HRESULT WINAPI
2191 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2192                                      LPD3DVIEWPORT7 lpData)
2193 {
2194     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2195     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2196
2197     if (TRACE_ON(ddraw)) {
2198         TRACE(" viewport is : \n");
2199         TRACE("    - dwX = %ld   dwY = %ld\n",
2200               lpData->dwX, lpData->dwY);
2201         TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
2202               lpData->dwWidth, lpData->dwHeight);
2203         TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
2204               lpData->dvMinZ, lpData->dvMaxZ);
2205     }
2206     This->active_viewport = *lpData;
2207
2208     /* Set the viewport */
2209     glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2210     glViewport(lpData->dwX,
2211                This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2212                lpData->dwWidth, lpData->dwHeight);
2213     
2214     return DD_OK;
2215 }
2216
2217 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2218 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
2219 #else
2220 # define XCAST(fun)     (void*)
2221 #endif
2222
2223 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2224 {
2225     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2226     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2227     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2228     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2229     XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2230     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2231     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2232     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2233     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2234     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2235     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2236     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2237     XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2238     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2239     XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2240     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2241     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2242     XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2243     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2244     XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2245     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2246     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2247     XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2248     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2249     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2250     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2251     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2252     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2253     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2254     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2255     XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2256     XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2257     XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2258     XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2259     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2260     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2261     XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2262     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2263     XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2264     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2265     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2266     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2267     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2268     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2269     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2270     XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2271     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2272     XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2273     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2274     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2275 };
2276
2277 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2278 #undef XCAST
2279 #endif
2280
2281
2282 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2283 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
2284 #else
2285 # define XCAST(fun)     (void*)
2286 #endif
2287
2288 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2289 {
2290     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2291     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2292     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2293     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2294     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2295     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2296     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2297     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2298     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2299     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2300     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2301     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2302     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2303     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2304     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2305     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2306     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2307     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2308     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2309     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2310     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2311     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2312     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2313     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2314     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2315     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2316     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2317     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2318     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2319     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2320     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2321     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2322     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2323     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2324     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2325     XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2326     XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2327     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2328     XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2329     XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2330     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2331     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2332     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2333 };
2334
2335 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2336 #undef XCAST
2337 #endif
2338
2339
2340 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2341 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
2342 #else
2343 # define XCAST(fun)     (void*)
2344 #endif
2345
2346 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2347 {
2348     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2349     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2350     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2351     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2352     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2353     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2354     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2355     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2356     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2357     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2358     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2359     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2360     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2361     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2362     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2363     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2364     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2365     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2366     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2367     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2368     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2369     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2370     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2371     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2372     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2373     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2374     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2375     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2376     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2377     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2378     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2379     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2380     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2381     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2382 };
2383
2384 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2385 #undef XCAST
2386 #endif
2387
2388
2389 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2390 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
2391 #else
2392 # define XCAST(fun)     (void*)
2393 #endif
2394
2395 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2396 {
2397     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2398     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2399     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2400     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2401     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2402     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2403     XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2404     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2405     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2406     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2407     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2408     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2409     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2410     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2411     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2412     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2413     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2414     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2415     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2416     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2417     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2418     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2419     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2420 };
2421
2422 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2423 #undef XCAST
2424 #endif
2425
2426 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2427                                DWORD dwCount,
2428                                LPD3DRECT lpRects,
2429                                DWORD dwFlags,
2430                                DWORD dwColor,
2431                                D3DVALUE dvZ,
2432                                DWORD dwStencil)
2433 {
2434     GLboolean ztest;
2435     GLfloat old_z_clear_value;
2436     GLbitfield bitfield = 0;
2437     GLint old_stencil_clear_value;
2438     GLfloat old_color_clear_value[4];
2439     D3DRECT rect;
2440     int i;
2441     
2442     TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2443     if (TRACE_ON(ddraw)) {
2444         if (dwCount > 0) {
2445             int i;
2446             TRACE(" rectangles : \n");
2447             for (i = 0; i < dwCount; i++) {
2448                 TRACE("  - %ld x %ld     %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2449             }
2450         }
2451     }
2452
2453     if (dwCount == 0) {
2454         /* Not sure if this is really needed... */
2455         dwCount = 1;
2456         rect.u1.x1 = 0;
2457         rect.u2.y1 = 0;
2458         rect.u3.x2 = This->surface->surface_desc.dwWidth;
2459         rect.u4.y2 = This->surface->surface_desc.dwHeight;
2460         lpRects = &rect;
2461     }
2462     
2463     /* Clears the screen */
2464     ENTER_GL();
2465     if (dwFlags & D3DCLEAR_ZBUFFER) {
2466         bitfield |= GL_DEPTH_BUFFER_BIT;
2467         glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2468         glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2469         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2470         glClearDepth(dvZ);
2471         TRACE(" depth value : %f\n", dvZ);
2472     }
2473     if (dwFlags & D3DCLEAR_STENCIL) {
2474         bitfield |= GL_STENCIL_BUFFER_BIT;
2475         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2476         glClearStencil(dwStencil);
2477         TRACE(" stencil value : %ld\n", dwStencil);
2478     }    
2479     if (dwFlags & D3DCLEAR_TARGET) {
2480         bitfield |= GL_COLOR_BUFFER_BIT;
2481         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2482         glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2483                      ((dwColor >>  8) & 0xFF) / 255.0,
2484                      ((dwColor >>  0) & 0xFF) / 255.0,
2485                      ((dwColor >> 24) & 0xFF) / 255.0);
2486         TRACE(" color value (ARGB) : %08lx\n", dwColor);
2487     }
2488
2489     glEnable(GL_SCISSOR_TEST); 
2490     for (i = 0; i < dwCount; i++) {
2491         glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2492                   lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2493         glClear(bitfield);
2494     }
2495     glDisable(GL_SCISSOR_TEST); 
2496     
2497     if (dwFlags & D3DCLEAR_ZBUFFER) {
2498         glDepthMask(ztest);
2499         glClearDepth(old_z_clear_value);
2500     }
2501      if (dwFlags & D3DCLEAR_STENCIL) {
2502         bitfield |= GL_STENCIL_BUFFER_BIT;
2503         glClearStencil(old_stencil_clear_value);
2504     }    
2505     if (dwFlags & D3DCLEAR_TARGET) {
2506         bitfield |= GL_COLOR_BUFFER_BIT;
2507         glClearColor(old_color_clear_value[0],
2508                      old_color_clear_value[1],
2509                      old_color_clear_value[2],
2510                      old_color_clear_value[3]);
2511     }
2512     
2513     LEAVE_GL();
2514     
2515     return DD_OK;
2516 }
2517
2518 HRESULT
2519 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2520               LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2521               DWORD dwFlags, LPDDBLTFX lpbltfx)
2522 {
2523     if (dwFlags & DDBLT_COLORFILL) {
2524         /* This is easy to handle for the D3D Device... */
2525         DWORD color = lpbltfx->u5.dwFillColor;
2526         D3DRECT rect;
2527         
2528         TRACE(" executing D3D Device override.\n");
2529
2530         if (rdst) {
2531             rect.u1.x1 = rdst->left;
2532             rect.u2.y1 = rdst->top;
2533             rect.u3.x2 = rdst->right;
2534             rect.u4.y2 = rdst->bottom;
2535         }
2536         d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2537         return DD_OK;
2538     }
2539     return DDERR_INVALIDPARAMS;
2540 }
2541
2542 HRESULT
2543 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2544                   DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2545                   LPRECT rsrc, DWORD trans)
2546 {
2547      return DDERR_INVALIDPARAMS;
2548 }
2549
2550 void
2551 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2552 {
2553     GLfloat height, width;
2554     GLfloat trans_mat[16];
2555     
2556     width = This->surface->surface_desc.dwWidth;
2557     height = This->surface->surface_desc.dwHeight;
2558     
2559     /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2560        to OpenGL screen coordinates (ie the upper left corner is not the same).
2561        For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2562        -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2563     trans_mat[ 0] = 2.0 / width;  trans_mat[ 4] = 0.0;  trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2564     trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] =  1.0;
2565     trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0;           trans_mat[14] = -1.0;
2566     trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0;           trans_mat[15] =  1.0;
2567     
2568     glMatrixMode(GL_MODELVIEW);
2569     glLoadIdentity();
2570     /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2571        Correctness Tips section).
2572        
2573        Basically, from what I understood, if the game does not filter the font texture,
2574        as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2575        one and we will have strange artifacts (as the rounding and stuff may give different results
2576        for different pixels, ie sometimes take the left pixel, sometimes the right).
2577     */
2578     glTranslatef(0.375, 0.375, 0);
2579     glMatrixMode(GL_PROJECTION);
2580     glLoadMatrixf(trans_mat);
2581 }
2582
2583 void
2584 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2585                        D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2586 {
2587     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2588         glMatrixMode(GL_MODELVIEW);
2589         glLoadMatrixf((float *) view_mat);
2590
2591         /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2592         if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2593             GLint i;
2594             DWORD runner;
2595             for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2596                 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2597                     GLdouble plane[4];
2598
2599                     plane[0] = This->clipping_planes[i].plane[0];
2600                     plane[1] = This->clipping_planes[i].plane[1];
2601                     plane[2] = This->clipping_planes[i].plane[2];
2602                     plane[3] = This->clipping_planes[i].plane[3];
2603                     
2604                     glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2605                 }
2606             }
2607         }
2608         if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2609             GLint i;
2610             DWORD runner;
2611
2612             for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2613                 if (runner & This->active_lights) {
2614                     switch (This->light_parameters[i].dltType) {
2615                         case D3DLIGHT_DIRECTIONAL: {
2616                             float direction[4];
2617                             float cut_off = 180.0;
2618                             
2619                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2620                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2621                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2622                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2623                             
2624                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2625                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2626                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2627                             direction[3] = 0.0;
2628                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2629                         } break;
2630
2631                         case D3DLIGHT_POINT: {
2632                             float position[4];
2633                             float cut_off = 180.0;
2634                             
2635                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2636                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2637                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2638                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2639                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2640                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2641                             position[3] = 1.0;
2642                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2643                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2644                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2645                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2646                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2647                         } break;
2648
2649                         case D3DLIGHT_SPOT: {
2650                             float direction[4];
2651                             float position[4];
2652                             float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2653                             
2654                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2655                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2656                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2657                             
2658                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2659                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2660                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2661                             direction[3] = 0.0;
2662                             glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2663                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2664                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2665                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2666                             position[3] = 1.0;
2667                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2668                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2669                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2670                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2671                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2672                             glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2673                         } break;
2674
2675                         default:
2676                             /* No warning here as it's already done at light setting */
2677                             break;
2678                     }
2679                 }
2680             }
2681         }
2682         
2683         glMultMatrixf((float *) world_mat);
2684     }
2685     if ((matrices & PROJMAT_CHANGED) != 0) {
2686         glMatrixMode(GL_PROJECTION);
2687         glLoadMatrixf((float *) proj_mat);
2688     }
2689 }
2690
2691 void
2692 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2693 {
2694     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2695     DWORD tex_mat, tex_stage;
2696     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2697         if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2698             /* This will force an update of the transform state at the next drawing. */
2699             glThis->transform_state = GL_TRANSFORM_NONE;
2700         }
2701     }
2702     for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2703         if (matrices & tex_mat) {
2704             if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2705                 if (tex_stage == 0) {
2706                     /* No multi-texturing support for now ... */
2707                     glMatrixMode(GL_TEXTURE);
2708                     glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2709                 }
2710             } else {
2711                 glMatrixMode(GL_TEXTURE);
2712                 glLoadIdentity();
2713             }
2714         }
2715     }
2716 }
2717
2718 /* TODO for both these functions :
2719     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2720       by other OpenGL code in D3D
2721     - handle the case where no 'Begin / EndScene' was done between two locks
2722     - handle the rectangles in the unlock too
2723     - handle pitch correctly...
2724 */
2725 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2726 {
2727     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2728     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2729     BOOLEAN is_front;
2730     
2731     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2732         is_front = TRUE;
2733     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2734         is_front = FALSE;
2735     } else {
2736         ERR("Wrong surface type for locking !\n");
2737         return;
2738     }
2739
2740     /* Try to acquire the device critical section */
2741     EnterCriticalSection(&(d3d_dev->crit));
2742     
2743     if (((is_front == TRUE)  && (gl_d3d_dev->front_state != SURFACE_MEMORY)) ||
2744         ((is_front == FALSE) && (gl_d3d_dev->state       != SURFACE_MEMORY))) {
2745         /* If the surface is already in memory, no need to do anything here... */
2746         GLenum buffer_type;
2747         GLenum buffer_color;
2748         GLenum prev_read;
2749         RECT loc_rect;
2750         int y;
2751         char *dst;
2752
2753         TRACE(" copying frame buffer to main memory.\n");
2754         
2755         /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2756            may only write to the device... But when we will blit it back to the screen, we need
2757            also to blit correctly the parts the application did not overwrite... */
2758         
2759         ENTER_GL();
2760         
2761         glGetIntegerv(GL_READ_BUFFER, &prev_read);
2762         glFlush();
2763         
2764         if (is_front == TRUE)
2765             /* Application wants to lock the front buffer */
2766             glReadBuffer(GL_FRONT);
2767         else 
2768             /* Application wants to lock the back buffer */
2769             glReadBuffer(GL_BACK);
2770
2771         if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2772             (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0xF800) &&
2773             (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x07E0) &&
2774             (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x001F) &&
2775             (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2776             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2777             buffer_color = GL_RGB;
2778         } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2779                    (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0x00FF0000) &&
2780                    (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x0000FF00) &&
2781                    (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x000000FF) &&
2782                    (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2783             buffer_type = GL_UNSIGNED_BYTE;
2784             buffer_color = GL_BGRA;
2785             glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2786         } else {
2787             ERR(" unsupported pixel format at device locking.\n");
2788             LEAVE_GL();
2789             return;
2790         }
2791
2792         /* Just a hack while waiting for proper rectangle support */
2793         pRect = NULL;
2794         if (pRect == NULL) {
2795             loc_rect.top = 0;
2796             loc_rect.left = 0;
2797             loc_rect.bottom = This->surface_desc.dwHeight;
2798             loc_rect.right = This->surface_desc.dwWidth;
2799         } else {
2800             loc_rect = *pRect;
2801         }
2802         
2803         dst = ((char *)This->surface_desc.lpSurface) +
2804           (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2805         for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2806              y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2807              y--) {
2808             glReadPixels(loc_rect.left, y,
2809                          loc_rect.right - loc_rect.left, 1,
2810                          buffer_color, buffer_type, dst);
2811             dst += This->surface_desc.u1.lPitch;
2812         }
2813
2814         glReadBuffer(prev_read);
2815         glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2816         
2817         if (is_front)
2818             gl_d3d_dev->front_state = SURFACE_MEMORY;
2819         else
2820             gl_d3d_dev->state = SURFACE_MEMORY;
2821         
2822 #if 0
2823         /* I keep this code here as it's very useful to debug :-) */
2824         {
2825             static int flush_count = 0;
2826             char buf[128];
2827             FILE *f;
2828             
2829             if ((++flush_count % 50) == 0) {
2830                 sprintf(buf, "lock_%06d.pnm", flush_count);
2831                 f = fopen(buf, "wb");
2832                 DDRAW_dump_surface_to_disk(This, f);
2833             }
2834         }
2835 #endif
2836         
2837         LEAVE_GL();
2838     }
2839 }
2840
2841 #define UNLOCK_TEX_SIZE 256
2842
2843 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2844     GLenum buffer_type, buffer_color;
2845     RECT loc_rect;
2846     IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2847     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2848     GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test;
2849     GLuint initial_texture;
2850     GLint tex_state;
2851     int x, y;
2852
2853     /* This is to prevent another thread to actually lock the buffer while we flush it on screen */
2854     EnterCriticalSection(&(d3d_dev->crit));
2855     
2856     loc_rect.top = 0;
2857     loc_rect.left = 0;
2858     loc_rect.bottom = surf->surface_desc.dwHeight;
2859     loc_rect.right = surf->surface_desc.dwWidth;
2860
2861     TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
2862         
2863     glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2864     glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2865     glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2866     glGetIntegerv(GL_CULL_FACE, &cull_face);
2867     glGetIntegerv(GL_LIGHTING, &lighting);
2868     glGetIntegerv(GL_BLEND, &blend);
2869     glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2870     glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2871     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2872     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2873     glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2874     glMatrixMode(GL_TEXTURE);
2875     glLoadIdentity();
2876     /* TODO: scissor test if ever we use it ! */
2877     
2878     if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2879         (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0xF800) &&
2880         (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x07E0) &&
2881         (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x001F) &&
2882         (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2883         buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2884         buffer_color = GL_RGB;
2885     } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2886                (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0x00FF0000) &&
2887                (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x0000FF00) &&
2888                (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x000000FF) &&
2889                (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2890         buffer_type = GL_UNSIGNED_BYTE;
2891         buffer_color = GL_BGRA;
2892         glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2893     } else {
2894         ERR(" unsupported pixel format at frame buffer flush.\n");
2895         LeaveCriticalSection(&(d3d_dev->crit));
2896         return;
2897     }
2898
2899     gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2900     d3ddevice_set_ortho(d3d_dev);
2901     
2902     glDisable(GL_DEPTH_TEST);
2903     glEnable(GL_TEXTURE_2D);
2904     glEnable(GL_SCISSOR_TEST); 
2905     glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2906               loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2907     
2908     if (gl_d3d_dev->unlock_tex == 0) {
2909         glGenTextures(1, &gl_d3d_dev->unlock_tex);
2910         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2911         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2912                      UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2913                      GL_RGB, buffer_type, NULL);
2914     } else {
2915         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2916     }
2917     glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2918     
2919     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2920     glDisable(GL_LIGHTING);
2921     glDisable(GL_CULL_FACE);
2922     glDisable(GL_ALPHA_TEST);
2923     glDisable(GL_STENCIL_TEST);
2924     glDisable(GL_BLEND);
2925     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2926     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2927
2928     for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2929         for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2930             /* First, upload the texture... */
2931             int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth)  ? (surf->surface_desc.dwWidth - x)  : UNLOCK_TEX_SIZE;
2932             int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2933             glTexSubImage2D(GL_TEXTURE_2D,
2934                             0,
2935                             0, 0,
2936                             w, h,
2937                             buffer_color,
2938                             buffer_type,
2939                             ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2940             glBegin(GL_QUADS);
2941             glColor3ub(0xFF, 0xFF, 0xFF);
2942             glTexCoord2f(0.0, 0.0);
2943             glVertex3d(x, y, 0.5);
2944             glTexCoord2f(1.0, 0.0);
2945             glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2946             glTexCoord2f(1.0, 1.0);
2947             glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2948             glTexCoord2f(0.0, 1.0);
2949             glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2950             glEnd();
2951         }
2952     }
2953     
2954     
2955     /* And restore all the various states modified by this code */
2956     if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2957     if (lighting != 0) glEnable(GL_LIGHTING);
2958     if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2959     if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2960     if (cull_face != 0) glEnable(GL_CULL_FACE);
2961     if (blend != 0) glEnable(GL_BLEND);
2962     glBindTexture(GL_TEXTURE_2D, initial_texture);
2963     if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2964     glDisable(GL_SCISSOR_TEST);
2965     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2966     glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
2967     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2968     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2969     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2970     d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
2971 #if 0
2972     /* I keep this code here as it's very useful to debug :-) */
2973     {
2974         static int flush_count = 0;
2975         char buf[128];
2976         FILE *f;
2977
2978         if ((++flush_count % 50) == 0) {
2979             sprintf(buf, "flush_%06d.pnm", flush_count);
2980             f = fopen(buf, "wb");
2981             DDRAW_dump_surface_to_disk(surf, f);
2982         }
2983     }
2984 #endif
2985
2986     /* And leave the critical section... */
2987     LeaveCriticalSection(&(d3d_dev->crit));
2988 }
2989
2990 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2991 {
2992     BOOLEAN is_front;
2993     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2994   
2995     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2996         is_front = TRUE;
2997     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2998         is_front = FALSE;
2999     } else {
3000         ERR("Wrong surface type for locking !\n");
3001         return;
3002     }
3003     /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3004     if (((This->lastlocktype & DDLOCK_READONLY) == 0) &&
3005         (is_front == TRUE)) {
3006         GLenum prev_draw;
3007         ENTER_GL();
3008         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3009         glDrawBuffer(GL_FRONT);
3010         d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
3011         glDrawBuffer(prev_draw);
3012         LEAVE_GL();
3013     }
3014
3015     /* And 'frees' the device critical section */
3016     LeaveCriticalSection(&(d3d_dev->crit));
3017 }
3018
3019 static void
3020 apply_texture_state(IDirect3DDeviceImpl *This)
3021 {
3022     int stage, state;
3023     
3024     /* Initialize texture stages states */
3025     for (stage = 0; stage < MAX_TEXTURES; stage++) {
3026        for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3027            if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3028                IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3029                                                      stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3030            }
3031        }
3032     }
3033 }     
3034
3035 HRESULT
3036 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3037 {
3038     IDirect3DDeviceImpl *object;
3039     IDirect3DDeviceGLImpl *gl_object;
3040     IDirectDrawSurfaceImpl *surf;
3041     HDC device_context;
3042     XVisualInfo *vis;
3043     int num;
3044     int tex_num;
3045     XVisualInfo template;
3046     GLenum buffer = GL_FRONT;
3047     int light;
3048     GLint max_clipping_planes = 0;
3049     
3050     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3051     if (object == NULL) return DDERR_OUTOFMEMORY;
3052
3053     gl_object = (IDirect3DDeviceGLImpl *) object;
3054     
3055     object->ref = 1;
3056     object->d3d = d3d;
3057     object->surface = surface;
3058     object->set_context = set_context;
3059     object->clear = d3ddevice_clear;
3060     object->set_matrices = d3ddevice_set_matrices;
3061     object->matrices_updated = d3ddevice_matrices_updated;
3062     object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3063     
3064     InitializeCriticalSection(&(object->crit));
3065     
3066     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3067
3068     device_context = GetDC(surface->ddraw_owner->window);
3069     gl_object->display = get_display(device_context);
3070     gl_object->drawable = get_drawable(device_context);
3071     ReleaseDC(surface->ddraw_owner->window,device_context);
3072
3073     ENTER_GL();
3074     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3075     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3076     if (vis == NULL) {
3077         HeapFree(GetProcessHeap(), 0, object);
3078         ERR("No visual found !\n");
3079         LEAVE_GL();
3080         return DDERR_INVALIDPARAMS;
3081     } else {
3082         TRACE(" visual found\n");
3083     }
3084
3085     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3086                                              NULL, GL_TRUE);
3087
3088     if (gl_object->gl_context == NULL) {
3089         HeapFree(GetProcessHeap(), 0, object);
3090         ERR("Error in context creation !\n");
3091         LEAVE_GL();
3092         return DDERR_INVALIDPARAMS;
3093     } else {
3094         TRACE(" context created (%p)\n", gl_object->gl_context);
3095     }
3096     
3097     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3098     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3099         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3100             surf->aux_ctx  = (LPVOID) object;
3101             surf->aux_data = (LPVOID) gl_object->drawable;
3102             surf->aux_flip = opengl_flip;
3103             buffer =  GL_BACK;
3104             break;
3105         }
3106     }
3107     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3108     if (surf == NULL) {
3109         TRACE(" no double buffering : drawing on the front buffer\n");
3110         buffer = GL_FRONT;
3111     }
3112     
3113     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3114         IDirectDrawSurfaceImpl *surf2;
3115         for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3116         for (; surf2 != NULL; surf2 = surf2->next_attached) {
3117             TRACE(" checking surface %p :", surf2);
3118             if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3119                 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3120                 /* Override the Lock / Unlock function for all these surfaces */
3121                 surf2->lock_update_prev = surf2->lock_update;
3122                 surf2->lock_update = d3ddevice_lock_update;
3123                 surf2->unlock_update_prev = surf2->unlock_update;
3124                 surf2->unlock_update = d3ddevice_unlock_update;
3125                 /* And install also the blt / bltfast overrides */
3126                 surf2->aux_blt = d3ddevice_blt;
3127                 surf2->aux_bltfast = d3ddevice_bltfast;
3128                 
3129                 TRACE(" overiding direct surface access.\n");
3130             } else {
3131                 TRACE(" no overide.\n");
3132             }
3133             surf2->d3ddevice = object;
3134         }
3135     }
3136
3137     /* Set the various light parameters */
3138     for (light = 0; light < MAX_LIGHTS; light++) {
3139         /* Only set the fields that are not zero-created */
3140         object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3141         object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3142         object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3143         object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3144         object->light_parameters[light].dvDirection.u3.z = 1.0;
3145     }
3146     
3147     /* Allocate memory for the matrices */
3148     object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3149     object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3150     object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3151     memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3152     memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3153     memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3154     for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3155         object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3156         memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3157     }
3158     
3159     /* Initialisation */
3160     TRACE(" setting current context\n");
3161     LEAVE_GL();
3162     object->set_context(object);
3163     ENTER_GL();
3164     TRACE(" current context set\n");
3165
3166     /* allocate the clipping planes */
3167     glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3168     if (max_clipping_planes>32) {
3169         object->max_clipping_planes=32;
3170     } else {
3171         object->max_clipping_planes = max_clipping_planes;
3172     }
3173     TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3174     object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3175
3176     glHint(GL_FOG_HINT,GL_NICEST);
3177     
3178     glClearColor(0.0, 0.0, 0.0, 0.0);
3179     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3180     glDrawBuffer(buffer);
3181     glReadBuffer(buffer);
3182     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3183     LEAVE_GL();
3184
3185     gl_object->state = SURFACE_GL;
3186     
3187     /* fill_device_capabilities(d3d->ddraw); */    
3188     
3189     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
3190     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3191     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3192     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3193
3194     *obj = object;
3195
3196     TRACE(" creating implementation at %p.\n", *obj);
3197
3198     /* And finally warn D3D that this device is now present */
3199     object->d3d->added_device(object->d3d, object);
3200
3201     /* FIXME: Should handle other versions than just 7 */
3202     InitDefaultStateBlock(&object->state_block, 7);
3203     /* Apply default render state and texture stage state values */
3204     apply_render_state(object, &object->state_block);
3205     apply_texture_state(object);
3206
3207     /* And fill the fog table with the default fog value */
3208     build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3209     
3210     return DD_OK;
3211 }