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