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