No need to flush the surface back if last lock was a RO lock.
[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_DIRTY) {
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_DIRTY) {
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     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2435     GLboolean ztest;
2436     GLfloat old_z_clear_value;
2437     GLbitfield bitfield = 0;
2438     GLint old_stencil_clear_value;
2439     GLfloat old_color_clear_value[4];
2440     D3DRECT rect;
2441     int i;
2442     
2443     TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2444     if (TRACE_ON(ddraw)) {
2445         if (dwCount > 0) {
2446             int i;
2447             TRACE(" rectangles : \n");
2448             for (i = 0; i < dwCount; i++) {
2449                 TRACE("  - %ld x %ld     %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2450             }
2451         }
2452     }
2453
2454     if (dwCount == 0) {
2455         /* Not sure if this is really needed... */
2456         dwCount = 1;
2457         rect.u1.x1 = 0;
2458         rect.u2.y1 = 0;
2459         rect.u3.x2 = This->surface->surface_desc.dwWidth;
2460         rect.u4.y2 = This->surface->surface_desc.dwHeight;
2461         lpRects = &rect;
2462     }
2463     
2464     /* Clears the screen */
2465     ENTER_GL();
2466
2467     if (glThis->state == SURFACE_MEMORY_DIRTY) {
2468         /* TODO: optimize here the case where Clear changes all the screen... */
2469         This->flush_to_framebuffer(This, NULL);
2470     }
2471     glThis->state = SURFACE_GL;
2472
2473     if (dwFlags & D3DCLEAR_ZBUFFER) {
2474         bitfield |= GL_DEPTH_BUFFER_BIT;
2475         glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2476         glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2477         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2478         glClearDepth(dvZ);
2479         TRACE(" depth value : %f\n", dvZ);
2480     }
2481     if (dwFlags & D3DCLEAR_STENCIL) {
2482         bitfield |= GL_STENCIL_BUFFER_BIT;
2483         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2484         glClearStencil(dwStencil);
2485         TRACE(" stencil value : %ld\n", dwStencil);
2486     }    
2487     if (dwFlags & D3DCLEAR_TARGET) {
2488         bitfield |= GL_COLOR_BUFFER_BIT;
2489         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2490         glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2491                      ((dwColor >>  8) & 0xFF) / 255.0,
2492                      ((dwColor >>  0) & 0xFF) / 255.0,
2493                      ((dwColor >> 24) & 0xFF) / 255.0);
2494         TRACE(" color value (ARGB) : %08lx\n", dwColor);
2495     }
2496
2497     glEnable(GL_SCISSOR_TEST); 
2498     for (i = 0; i < dwCount; i++) {
2499         glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2500                   lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2501         glClear(bitfield);
2502     }
2503     glDisable(GL_SCISSOR_TEST); 
2504     
2505     if (dwFlags & D3DCLEAR_ZBUFFER) {
2506         glDepthMask(ztest);
2507         glClearDepth(old_z_clear_value);
2508     }
2509      if (dwFlags & D3DCLEAR_STENCIL) {
2510         bitfield |= GL_STENCIL_BUFFER_BIT;
2511         glClearStencil(old_stencil_clear_value);
2512     }    
2513     if (dwFlags & D3DCLEAR_TARGET) {
2514         bitfield |= GL_COLOR_BUFFER_BIT;
2515         glClearColor(old_color_clear_value[0],
2516                      old_color_clear_value[1],
2517                      old_color_clear_value[2],
2518                      old_color_clear_value[3]);
2519     }
2520     
2521     LEAVE_GL();
2522     
2523     return DD_OK;
2524 }
2525
2526 HRESULT
2527 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2528               LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2529               DWORD dwFlags, LPDDBLTFX lpbltfx)
2530 {
2531     if (dwFlags & DDBLT_COLORFILL) {
2532         /* This is easy to handle for the D3D Device... */
2533         DWORD color = lpbltfx->u5.dwFillColor;
2534         D3DRECT rect;
2535         
2536         TRACE(" executing D3D Device override.\n");
2537
2538         if (rdst) {
2539             rect.u1.x1 = rdst->left;
2540             rect.u2.y1 = rdst->top;
2541             rect.u3.x2 = rdst->right;
2542             rect.u4.y2 = rdst->bottom;
2543         }
2544         d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2545         return DD_OK;
2546     }
2547     return DDERR_INVALIDPARAMS;
2548 }
2549
2550 HRESULT
2551 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2552                   DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2553                   LPRECT rsrc, DWORD trans)
2554 {
2555      return DDERR_INVALIDPARAMS;
2556 }
2557
2558 void
2559 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2560 {
2561     GLfloat height, width;
2562     GLfloat trans_mat[16];
2563     
2564     width = This->surface->surface_desc.dwWidth;
2565     height = This->surface->surface_desc.dwHeight;
2566     
2567     /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2568        to OpenGL screen coordinates (ie the upper left corner is not the same).
2569        For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2570        -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2571     trans_mat[ 0] = 2.0 / width;  trans_mat[ 4] = 0.0;  trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2572     trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] =  1.0;
2573     trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0;           trans_mat[14] = -1.0;
2574     trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0;           trans_mat[15] =  1.0;
2575     
2576     glMatrixMode(GL_MODELVIEW);
2577     glLoadIdentity();
2578     /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2579        Correctness Tips section).
2580        
2581        Basically, from what I understood, if the game does not filter the font texture,
2582        as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2583        one and we will have strange artifacts (as the rounding and stuff may give different results
2584        for different pixels, ie sometimes take the left pixel, sometimes the right).
2585     */
2586     glTranslatef(0.375, 0.375, 0);
2587     glMatrixMode(GL_PROJECTION);
2588     glLoadMatrixf(trans_mat);
2589 }
2590
2591 void
2592 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2593                        D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2594 {
2595     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2596         glMatrixMode(GL_MODELVIEW);
2597         glLoadMatrixf((float *) view_mat);
2598
2599         /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2600         if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2601             GLint i;
2602             DWORD runner;
2603             for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2604                 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2605                     GLdouble plane[4];
2606
2607                     plane[0] = This->clipping_planes[i].plane[0];
2608                     plane[1] = This->clipping_planes[i].plane[1];
2609                     plane[2] = This->clipping_planes[i].plane[2];
2610                     plane[3] = This->clipping_planes[i].plane[3];
2611                     
2612                     glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2613                 }
2614             }
2615         }
2616         if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2617             GLint i;
2618             DWORD runner;
2619
2620             for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2621                 if (runner & This->active_lights) {
2622                     switch (This->light_parameters[i].dltType) {
2623                         case D3DLIGHT_DIRECTIONAL: {
2624                             float direction[4];
2625                             float cut_off = 180.0;
2626                             
2627                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2628                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2629                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2630                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2631                             
2632                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2633                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2634                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2635                             direction[3] = 0.0;
2636                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2637                         } break;
2638
2639                         case D3DLIGHT_POINT: {
2640                             float position[4];
2641                             float cut_off = 180.0;
2642                             
2643                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2644                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2645                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2646                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2647                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2648                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2649                             position[3] = 1.0;
2650                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2651                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2652                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2653                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2654                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2655                         } break;
2656
2657                         case D3DLIGHT_SPOT: {
2658                             float direction[4];
2659                             float position[4];
2660                             float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2661                             
2662                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2663                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2664                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2665                             
2666                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2667                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2668                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2669                             direction[3] = 0.0;
2670                             glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2671                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2672                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2673                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2674                             position[3] = 1.0;
2675                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2676                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2677                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2678                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2679                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2680                             glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2681                         } break;
2682
2683                         default:
2684                             /* No warning here as it's already done at light setting */
2685                             break;
2686                     }
2687                 }
2688             }
2689         }
2690         
2691         glMultMatrixf((float *) world_mat);
2692     }
2693     if ((matrices & PROJMAT_CHANGED) != 0) {
2694         glMatrixMode(GL_PROJECTION);
2695         glLoadMatrixf((float *) proj_mat);
2696     }
2697 }
2698
2699 void
2700 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2701 {
2702     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2703     DWORD tex_mat, tex_stage;
2704     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2705         if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2706             /* This will force an update of the transform state at the next drawing. */
2707             glThis->transform_state = GL_TRANSFORM_NONE;
2708         }
2709     }
2710     for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2711         if (matrices & tex_mat) {
2712             if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2713                 if (tex_stage == 0) {
2714                     /* No multi-texturing support for now ... */
2715                     glMatrixMode(GL_TEXTURE);
2716                     glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2717                 }
2718             } else {
2719                 glMatrixMode(GL_TEXTURE);
2720                 glLoadIdentity();
2721             }
2722         }
2723     }
2724 }
2725
2726 /* TODO for both these functions :
2727     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2728       by other OpenGL code in D3D
2729     - handle the case where no 'Begin / EndScene' was done between two locks
2730     - handle the rectangles in the unlock too
2731     - handle pitch correctly...
2732 */
2733 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2734 {
2735     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2736     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2737     BOOLEAN is_front;
2738     
2739     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2740         is_front = TRUE;
2741     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2742         is_front = FALSE;
2743     } else {
2744         ERR("Wrong surface type for locking !\n");
2745         return;
2746     }
2747
2748     /* Try to acquire the device critical section */
2749     EnterCriticalSection(&(d3d_dev->crit));
2750     
2751     if (((is_front == TRUE)  && (gl_d3d_dev->front_state == SURFACE_GL)) ||
2752         ((is_front == FALSE) && (gl_d3d_dev->state       == SURFACE_GL))) {
2753         /* If the surface is already in memory, no need to do anything here... */
2754         GLenum buffer_type;
2755         GLenum buffer_color;
2756         GLenum prev_read;
2757         RECT loc_rect;
2758         int y;
2759         char *dst;
2760
2761         TRACE(" copying frame buffer to main memory.\n");
2762         
2763         /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2764            may only write to the device... But when we will blit it back to the screen, we need
2765            also to blit correctly the parts the application did not overwrite... */
2766         
2767         ENTER_GL();
2768         
2769         glGetIntegerv(GL_READ_BUFFER, &prev_read);
2770         glFlush();
2771         
2772         if (is_front == TRUE)
2773             /* Application wants to lock the front buffer */
2774             glReadBuffer(GL_FRONT);
2775         else 
2776             /* Application wants to lock the back buffer */
2777             glReadBuffer(GL_BACK);
2778
2779         if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2780             (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0xF800) &&
2781             (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x07E0) &&
2782             (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x001F) &&
2783             (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2784             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2785             buffer_color = GL_RGB;
2786         } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2787                    (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0x00FF0000) &&
2788                    (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x0000FF00) &&
2789                    (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x000000FF) &&
2790                    (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2791             buffer_type = GL_UNSIGNED_BYTE;
2792             buffer_color = GL_BGRA;
2793             glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2794         } else {
2795             ERR(" unsupported pixel format at device locking.\n");
2796             LEAVE_GL();
2797             return;
2798         }
2799
2800         /* Just a hack while waiting for proper rectangle support */
2801         pRect = NULL;
2802         if (pRect == NULL) {
2803             loc_rect.top = 0;
2804             loc_rect.left = 0;
2805             loc_rect.bottom = This->surface_desc.dwHeight;
2806             loc_rect.right = This->surface_desc.dwWidth;
2807         } else {
2808             loc_rect = *pRect;
2809         }
2810         
2811         dst = ((char *)This->surface_desc.lpSurface) +
2812           (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2813         for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2814              y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2815              y--) {
2816             glReadPixels(loc_rect.left, y,
2817                          loc_rect.right - loc_rect.left, 1,
2818                          buffer_color, buffer_type, dst);
2819             dst += This->surface_desc.u1.lPitch;
2820         }
2821
2822         glReadBuffer(prev_read);
2823         glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2824         
2825         if (is_front)
2826             gl_d3d_dev->front_state = SURFACE_MEMORY;
2827         else
2828             gl_d3d_dev->state = SURFACE_MEMORY;
2829         
2830 #if 0
2831         /* I keep this code here as it's very useful to debug :-) */
2832         {
2833             static int flush_count = 0;
2834             char buf[128];
2835             FILE *f;
2836             
2837             if ((++flush_count % 50) == 0) {
2838                 sprintf(buf, "lock_%06d.pnm", flush_count);
2839                 f = fopen(buf, "wb");
2840                 DDRAW_dump_surface_to_disk(This, f);
2841             }
2842         }
2843 #endif
2844         
2845         LEAVE_GL();
2846     }
2847 }
2848
2849 #define UNLOCK_TEX_SIZE 256
2850
2851 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect) {
2852     GLenum buffer_type, buffer_color;
2853     RECT loc_rect;
2854     IDirectDrawSurfaceImpl *surf = d3d_dev->surface;
2855     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2856     GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test;
2857     GLuint initial_texture;
2858     GLint tex_state;
2859     int x, y;
2860
2861     /* This is to prevent another thread to actually lock the buffer while we flush it on screen */
2862     EnterCriticalSection(&(d3d_dev->crit));
2863     
2864     loc_rect.top = 0;
2865     loc_rect.left = 0;
2866     loc_rect.bottom = surf->surface_desc.dwHeight;
2867     loc_rect.right = surf->surface_desc.dwWidth;
2868
2869     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);
2870         
2871     glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2872     glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2873     glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2874     glGetIntegerv(GL_CULL_FACE, &cull_face);
2875     glGetIntegerv(GL_LIGHTING, &lighting);
2876     glGetIntegerv(GL_BLEND, &blend);
2877     glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2878     glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2879     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2880     glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2881     glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2882     glMatrixMode(GL_TEXTURE);
2883     glLoadIdentity();
2884     /* TODO: scissor test if ever we use it ! */
2885     
2886     if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2887         (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0xF800) &&
2888         (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x07E0) &&
2889         (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x001F) &&
2890         (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2891         buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2892         buffer_color = GL_RGB;
2893     } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2894                (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask ==        0x00FF0000) &&
2895                (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask ==        0x0000FF00) &&
2896                (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask ==        0x000000FF) &&
2897                (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2898         buffer_type = GL_UNSIGNED_BYTE;
2899         buffer_color = GL_BGRA;
2900         glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2901     } else {
2902         ERR(" unsupported pixel format at frame buffer flush.\n");
2903         LeaveCriticalSection(&(d3d_dev->crit));
2904         return;
2905     }
2906
2907     gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2908     d3ddevice_set_ortho(d3d_dev);
2909     
2910     glDisable(GL_DEPTH_TEST);
2911     glEnable(GL_TEXTURE_2D);
2912     glEnable(GL_SCISSOR_TEST); 
2913     glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2914               loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2915     
2916     if (gl_d3d_dev->unlock_tex == 0) {
2917         glGenTextures(1, &gl_d3d_dev->unlock_tex);
2918         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2919         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2920                      UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2921                      GL_RGB, buffer_type, NULL);
2922     } else {
2923         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2924     }
2925     glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
2926     
2927     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2928     glDisable(GL_LIGHTING);
2929     glDisable(GL_CULL_FACE);
2930     glDisable(GL_ALPHA_TEST);
2931     glDisable(GL_STENCIL_TEST);
2932     glDisable(GL_BLEND);
2933     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2934     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2935
2936     for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2937         for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2938             /* First, upload the texture... */
2939             int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth)  ? (surf->surface_desc.dwWidth - x)  : UNLOCK_TEX_SIZE;
2940             int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
2941             glTexSubImage2D(GL_TEXTURE_2D,
2942                             0,
2943                             0, 0,
2944                             w, h,
2945                             buffer_color,
2946                             buffer_type,
2947                             ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
2948             glBegin(GL_QUADS);
2949             glColor3ub(0xFF, 0xFF, 0xFF);
2950             glTexCoord2f(0.0, 0.0);
2951             glVertex3d(x, y, 0.5);
2952             glTexCoord2f(1.0, 0.0);
2953             glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2954             glTexCoord2f(1.0, 1.0);
2955             glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2956             glTexCoord2f(0.0, 1.0);
2957             glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2958             glEnd();
2959         }
2960     }
2961     
2962     
2963     /* And restore all the various states modified by this code */
2964     if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2965     if (lighting != 0) glEnable(GL_LIGHTING);
2966     if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2967     if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2968     if (cull_face != 0) glEnable(GL_CULL_FACE);
2969     if (blend != 0) glEnable(GL_BLEND);
2970     glBindTexture(GL_TEXTURE_2D, initial_texture);
2971     if (tex_state == 0) glDisable(GL_TEXTURE_2D);
2972     glDisable(GL_SCISSOR_TEST);
2973     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2974     glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
2975     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex);
2976     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex);
2977     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
2978     d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
2979 #if 0
2980     /* I keep this code here as it's very useful to debug :-) */
2981     {
2982         static int flush_count = 0;
2983         char buf[128];
2984         FILE *f;
2985
2986         if ((++flush_count % 50) == 0) {
2987             sprintf(buf, "flush_%06d.pnm", flush_count);
2988             f = fopen(buf, "wb");
2989             DDRAW_dump_surface_to_disk(surf, f);
2990         }
2991     }
2992 #endif
2993
2994     /* And leave the critical section... */
2995     LeaveCriticalSection(&(d3d_dev->crit));
2996 }
2997
2998 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2999 {
3000     BOOLEAN is_front;
3001     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3002     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3003   
3004     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3005         is_front = TRUE;
3006     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3007         is_front = FALSE;
3008     } else {
3009         ERR("Wrong surface type for locking !\n");
3010         return;
3011     }
3012     /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3013     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3014         if (is_front == TRUE) {
3015             GLenum prev_draw;
3016             ENTER_GL();
3017             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3018             glDrawBuffer(GL_FRONT);
3019             d3d_dev->flush_to_framebuffer(d3d_dev, pRect);
3020             glDrawBuffer(prev_draw);
3021             LEAVE_GL();
3022         } else {
3023             gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
3024         }
3025     }
3026
3027     /* And 'frees' the device critical section */
3028     LeaveCriticalSection(&(d3d_dev->crit));
3029 }
3030
3031 static void
3032 apply_texture_state(IDirect3DDeviceImpl *This)
3033 {
3034     int stage, state;
3035     
3036     /* Initialize texture stages states */
3037     for (stage = 0; stage < MAX_TEXTURES; stage++) {
3038        for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3039            if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3040                IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3041                                                      stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3042            }
3043        }
3044     }
3045 }     
3046
3047 HRESULT
3048 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3049 {
3050     IDirect3DDeviceImpl *object;
3051     IDirect3DDeviceGLImpl *gl_object;
3052     IDirectDrawSurfaceImpl *surf;
3053     HDC device_context;
3054     XVisualInfo *vis;
3055     int num;
3056     int tex_num;
3057     XVisualInfo template;
3058     GLenum buffer = GL_FRONT;
3059     int light;
3060     GLint max_clipping_planes = 0;
3061     
3062     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3063     if (object == NULL) return DDERR_OUTOFMEMORY;
3064
3065     gl_object = (IDirect3DDeviceGLImpl *) object;
3066     
3067     object->ref = 1;
3068     object->d3d = d3d;
3069     object->surface = surface;
3070     object->set_context = set_context;
3071     object->clear = d3ddevice_clear;
3072     object->set_matrices = d3ddevice_set_matrices;
3073     object->matrices_updated = d3ddevice_matrices_updated;
3074     object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3075     
3076     InitializeCriticalSection(&(object->crit));
3077     
3078     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3079
3080     device_context = GetDC(surface->ddraw_owner->window);
3081     gl_object->display = get_display(device_context);
3082     gl_object->drawable = get_drawable(device_context);
3083     ReleaseDC(surface->ddraw_owner->window,device_context);
3084
3085     ENTER_GL();
3086     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3087     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3088     if (vis == NULL) {
3089         HeapFree(GetProcessHeap(), 0, object);
3090         ERR("No visual found !\n");
3091         LEAVE_GL();
3092         return DDERR_INVALIDPARAMS;
3093     } else {
3094         TRACE(" visual found\n");
3095     }
3096
3097     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3098                                              NULL, GL_TRUE);
3099
3100     if (gl_object->gl_context == NULL) {
3101         HeapFree(GetProcessHeap(), 0, object);
3102         ERR("Error in context creation !\n");
3103         LEAVE_GL();
3104         return DDERR_INVALIDPARAMS;
3105     } else {
3106         TRACE(" context created (%p)\n", gl_object->gl_context);
3107     }
3108     
3109     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3110     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3111         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3112             surf->aux_ctx  = (LPVOID) object;
3113             surf->aux_data = (LPVOID) gl_object->drawable;
3114             surf->aux_flip = opengl_flip;
3115             buffer =  GL_BACK;
3116             break;
3117         }
3118     }
3119     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3120     if (surf == NULL) {
3121         TRACE(" no double buffering : drawing on the front buffer\n");
3122         buffer = GL_FRONT;
3123     }
3124     
3125     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3126         IDirectDrawSurfaceImpl *surf2;
3127         for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3128         for (; surf2 != NULL; surf2 = surf2->next_attached) {
3129             TRACE(" checking surface %p :", surf2);
3130             if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3131                 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3132                 /* Override the Lock / Unlock function for all these surfaces */
3133                 surf2->lock_update_prev = surf2->lock_update;
3134                 surf2->lock_update = d3ddevice_lock_update;
3135                 surf2->unlock_update_prev = surf2->unlock_update;
3136                 surf2->unlock_update = d3ddevice_unlock_update;
3137                 /* And install also the blt / bltfast overrides */
3138                 surf2->aux_blt = d3ddevice_blt;
3139                 surf2->aux_bltfast = d3ddevice_bltfast;
3140                 
3141                 TRACE(" overiding direct surface access.\n");
3142             } else {
3143                 TRACE(" no overide.\n");
3144             }
3145             surf2->d3ddevice = object;
3146         }
3147     }
3148
3149     /* Set the various light parameters */
3150     for (light = 0; light < MAX_LIGHTS; light++) {
3151         /* Only set the fields that are not zero-created */
3152         object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3153         object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3154         object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3155         object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3156         object->light_parameters[light].dvDirection.u3.z = 1.0;
3157     }
3158     
3159     /* Allocate memory for the matrices */
3160     object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3161     object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3162     object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3163     memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3164     memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3165     memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3166     for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3167         object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3168         memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3169     }
3170     
3171     /* Initialisation */
3172     TRACE(" setting current context\n");
3173     LEAVE_GL();
3174     object->set_context(object);
3175     ENTER_GL();
3176     TRACE(" current context set\n");
3177
3178     /* allocate the clipping planes */
3179     glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3180     if (max_clipping_planes>32) {
3181         object->max_clipping_planes=32;
3182     } else {
3183         object->max_clipping_planes = max_clipping_planes;
3184     }
3185     TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3186     object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3187
3188     glHint(GL_FOG_HINT,GL_NICEST);
3189     
3190     glClearColor(0.0, 0.0, 0.0, 0.0);
3191     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3192     glDrawBuffer(buffer);
3193     glReadBuffer(buffer);
3194     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3195     LEAVE_GL();
3196
3197     gl_object->state = SURFACE_GL;
3198     
3199     /* fill_device_capabilities(d3d->ddraw); */    
3200     
3201     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
3202     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3203     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3204     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3205
3206     *obj = object;
3207
3208     TRACE(" creating implementation at %p.\n", *obj);
3209
3210     /* And finally warn D3D that this device is now present */
3211     object->d3d->added_device(object->d3d, object);
3212
3213     /* FIXME: Should handle other versions than just 7 */
3214     InitDefaultStateBlock(&object->state_block, 7);
3215     /* Apply default render state and texture stage state values */
3216     apply_render_state(object, &object->state_block);
3217     apply_texture_state(object);
3218
3219     /* And fill the fog table with the default fog value */
3220     build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3221     
3222     return DD_OK;
3223 }