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