Implement vertex and pixel fog.
[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 + b) / (c * 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 draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
693                                            BOOLEAN vertex_transformed,
694                                            BOOLEAN vertex_lit) {
695     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
696   
697     /* Puts GL in the correct lighting / transformation mode */
698     if ((vertex_transformed == FALSE) && 
699         (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
700         /* Need to put the correct transformation again if we go from Transformed
701            vertices to non-transformed ones.
702         */
703         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
704                            This->world_mat, This->view_mat, This->proj_mat);
705         glThis->transform_state = GL_TRANSFORM_NORMAL;
706
707     } else if ((vertex_transformed == TRUE) &&
708                (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
709         /* Set our orthographic projection */
710         glThis->transform_state = GL_TRANSFORM_ORTHO;
711         d3ddevice_set_ortho(This);
712     }
713     if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {glHint(GL_FOG_HINT,GL_NICEST);
714         if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
715             switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
716                 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE,GL_LINEAR); break; 
717                 case D3DFOG_EXP:    glFogi(GL_FOG_MODE,GL_EXP); break; 
718                 case D3DFOG_EXP2:   glFogi(GL_FOG_MODE,GL_EXP2); break;
719             }
720             glFogf(GL_FOG_START,ZfromZproj(This,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
721             glFogf(GL_FOG_END,ZfromZproj(This,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
722             glEnable(GL_FOG);
723         } else if ( (This->state_block.render_state[D3DRENDERSTATE_FOGVERTEXMODE - 1] != D3DFOG_NONE) &&
724                     (vertex_lit == FALSE) && (vertex_transformed == FALSE) ) {
725             /* D3DFOG_EXP and D3DFOG_EXP2 are treated as D3DFOG_LINEAR */
726             glFogi(GL_FOG_MODE,GL_LINEAR);
727             glFogf(GL_FOG_START,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
728             glFogf(GL_FOG_END,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
729             glEnable(GL_FOG);          
730         } else
731             glDisable(GL_FOG);
732     }
733     else
734         glDisable(GL_FOG);
735
736     /* Handle the 'no-normal' case */
737     if (vertex_lit == TRUE)
738         glDisable(GL_LIGHTING);
739     else if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)
740         glEnable(GL_LIGHTING);
741
742     /* Handle the code for pre-vertex material properties */
743     if (vertex_transformed == FALSE) {
744         if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
745             if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
746                 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
747                 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
748                 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
749                 glEnable(GL_COLOR_MATERIAL);
750             }
751         }
752     }
753 }
754
755
756 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
757                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
758 {
759     D3DDRAWPRIMITIVESTRIDEDDATA strided;
760
761     switch (d3dvt) {
762         case D3DVT_VERTEX: {
763             strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
764             strided.position.dwStride = sizeof(D3DVERTEX);
765             strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
766             strided.normal.dwStride = sizeof(D3DVERTEX);
767             strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
768             strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
769             draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
770         } break;
771
772         case D3DVT_LVERTEX: {
773             strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
774             strided.position.dwStride = sizeof(D3DLVERTEX);
775             strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
776             strided.diffuse.dwStride = sizeof(D3DLVERTEX);
777             strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
778             strided.specular.dwStride = sizeof(D3DLVERTEX);
779             strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
780             strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
781             draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
782         } break;
783
784         case D3DVT_TLVERTEX: {
785             strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
786             strided.position.dwStride = sizeof(D3DTLVERTEX);
787             strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
788             strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
789             strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
790             strided.specular.dwStride = sizeof(D3DTLVERTEX);
791             strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
792             strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
793             draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
794         } break;
795
796         default:
797             FIXME("Unhandled vertex type\n");
798             break;
799     }
800 }
801
802 HRESULT WINAPI
803 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
804                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
805                                        D3DVERTEXTYPE d3dvtVertexType,
806                                        LPVOID lpvVertices,
807                                        DWORD dwVertexCount,
808                                        DWORD dwFlags)
809 {
810     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
811
812     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
813     if (TRACE_ON(ddraw)) {
814         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
815     }
816
817     draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
818                    
819     return DD_OK;
820 }
821
822 HRESULT WINAPI
823 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
824                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
825                                               D3DVERTEXTYPE d3dvtVertexType,
826                                               LPVOID lpvVertices,
827                                               DWORD dwVertexCount,
828                                               LPWORD dwIndices,
829                                               DWORD dwIndexCount,
830                                               DWORD dwFlags)
831 {
832     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
833     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
834     if (TRACE_ON(ddraw)) {
835         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
836     }
837
838     draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
839     
840     return DD_OK;
841 }
842
843 HRESULT WINAPI
844 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
845                                              LPD3DEXECUTEBUFFERDESC lpDesc,
846                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
847                                              IUnknown* pUnkOuter)
848 {
849     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
850     IDirect3DExecuteBufferImpl *ret;
851     HRESULT ret_value;
852     
853     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
854
855     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
856     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
857
858     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
859     
860     return ret_value;
861 }
862
863 /* These are the various handler used in the generic path */
864 inline static void handle_xyz(D3DVALUE *coords) {
865     glVertex3fv(coords);
866 }
867 inline static void handle_xyzrhw(D3DVALUE *coords) {
868     if (coords[3] < 1e-8)
869         glVertex3fv(coords);
870     else {
871         GLfloat w = 1.0 / coords[3];
872         
873         glVertex4f(coords[0] * w,
874                    coords[1] * w,
875                    coords[2] * w,
876                    w);
877     }
878 }
879 inline static void handle_normal(D3DVALUE *coords) {
880     glNormal3fv(coords);
881 }
882
883 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
884     if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
885         (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
886         glColor4ub((*color >> 16) & 0xFF,
887                    (*color >>  8) & 0xFF,
888                    (*color >>  0) & 0xFF,
889                    (*color >> 24) & 0xFF);
890     } else {
891         glColor3ub((*color >> 16) & 0xFF,
892                    (*color >>  8) & 0xFF,
893                    (*color >>  0) & 0xFF);    
894     }
895 }
896
897 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
898     glColor4ub((*color >> 16) & 0xFF,
899                (*color >>  8) & 0xFF,
900                (*color >>  0) & 0xFF,
901                (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
902 }
903
904 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
905     if ((lighted == FALSE) &&
906         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
907         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
908             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
909             handle_diffuse_base(sb, color);
910         }
911         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
912             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
913             handle_diffuse_base(sb, color);
914         }
915         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
916             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
917             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
918             handle_diffuse_base(sb, color);
919         }
920         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
921             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
922             handle_diffuse_base(sb, color);
923         }
924     } else {
925         handle_diffuse_base(sb, color);
926     }    
927 }
928
929 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
930     if ((lighted == FALSE) &&
931         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
932         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
933             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
934             handle_specular_base(sb, color);
935         }
936         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
937             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
938             handle_specular_base(sb, color);
939         }
940         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
941             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
942             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
943             handle_specular_base(sb, color);
944         }
945         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
946             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
947             handle_specular_base(sb, color);
948         }
949     }
950     /* No else here as we do not know how to handle 'specular' on its own in any case.. */
951 }
952
953 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
954     if (lighted == TRUE) {
955         if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
956             /* Special case where the specular value is used to do fogging. TODO */
957         }
958         if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
959             /* Standard specular value in transformed mode. TODO */
960         }
961         handle_diffuse_base(sb, color_d);
962     } else {
963         if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
964             handle_diffuse(sb, color_d, FALSE);
965             handle_specular(sb, color_s, FALSE);
966         } else {
967             /* In that case, only put the diffuse color... */
968             handle_diffuse_base(sb, color_d);
969         }
970     }
971 }
972
973 inline static void handle_texture(D3DVALUE *coords) {
974     glTexCoord2fv(coords);
975 }
976 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
977     /* For the moment, draw only the first texture.. */
978     if (tex_index == 0) glTexCoord2fv(coords);
979 }
980
981 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
982                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
983                                    DWORD d3dvtVertexType,
984                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
985                                    DWORD dwStartVertex,
986                                    DWORD dwVertexCount,
987                                    LPWORD dwIndices,
988                                    DWORD dwIndexCount,
989                                    DWORD dwFlags)
990 {
991     BOOLEAN vertex_lighted = (d3dvtVertexType & D3DFVF_NORMAL) == 0;
992   
993     if (TRACE_ON(ddraw)) {
994         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
995     }
996
997     ENTER_GL();
998     draw_primitive_handle_GL_state(This,
999                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1000                                    vertex_lighted);
1001     draw_primitive_start_GL(d3dptPrimitiveType);
1002
1003     /* Some fast paths first before the generic case.... */
1004     if (d3dvtVertexType == D3DFVF_VERTEX) {
1005         int index;
1006         
1007         for (index = 0; index < dwIndexCount; index++) {
1008             int i = (dwIndices == NULL) ? index : dwIndices[index];
1009             D3DVALUE *normal = 
1010               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1011             D3DVALUE *tex_coord =
1012               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1013             D3DVALUE *position =
1014               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1015             
1016             handle_normal(normal);
1017             handle_texture(tex_coord);
1018             handle_xyz(position);
1019             
1020             TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1021                   position[0], position[1], position[2],
1022                   normal[0], normal[1], normal[2],
1023                   tex_coord[0], tex_coord[1]);
1024         }
1025     } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1026         int index;
1027         
1028         for (index = 0; index < dwIndexCount; index++) {
1029             int i = (dwIndices == NULL) ? index : dwIndices[index];
1030             DWORD *color_d = 
1031               (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1032             DWORD *color_s = 
1033               (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1034             D3DVALUE *tex_coord =
1035               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1036             D3DVALUE *position =
1037               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1038
1039             handle_diffuse_and_specular(&(This->state_block), color_d, color_s, TRUE);
1040             handle_texture(tex_coord);
1041             handle_xyzrhw(position);
1042
1043             TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1044                   position[0], position[1], position[2], position[3], 
1045                   (*color_d >> 16) & 0xFF,
1046                   (*color_d >>  8) & 0xFF,
1047                   (*color_d >>  0) & 0xFF,
1048                   (*color_d >> 24) & 0xFF,
1049                   (*color_s >> 16) & 0xFF,
1050                   (*color_s >>  8) & 0xFF,
1051                   (*color_s >>  0) & 0xFF,
1052                   (*color_s >> 24) & 0xFF,
1053                   tex_coord[0], tex_coord[1]);
1054         } 
1055     } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1056                ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1057         /* This is the 'slow path' but that should support all possible vertex formats out there...
1058            Note that people should write a fast path for all vertex formats out there...
1059         */  
1060         int index;
1061         for (index = 0; index < dwIndexCount; index++) {
1062             int i = (dwIndices == NULL) ? index : dwIndices[index];         
1063
1064             if (d3dvtVertexType & D3DFVF_NORMAL) { 
1065                 D3DVALUE *normal = 
1066                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);         
1067                 handle_normal(normal);
1068             }
1069             if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1070                 DWORD *color_d = 
1071                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1072                 DWORD *color_s = 
1073                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1074                 handle_diffuse_and_specular(&(This->state_block), color_d, color_s, vertex_lighted);
1075             } else {
1076                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1077                     DWORD *color_s = 
1078                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1079                     handle_specular(&(This->state_block), color_s, vertex_lighted);
1080                 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1081                     DWORD *color_d = 
1082                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1083                     handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1084                 }
1085             }
1086                 
1087             if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1088                 /* Special case for single texture... */
1089                 D3DVALUE *tex_coord =
1090                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1091                 handle_texture(tex_coord);
1092             } else {
1093                 int tex_index;
1094                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1095                     D3DVALUE *tex_coord =
1096                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1097                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1098                     handle_textures(tex_coord, tex_index);
1099                 }
1100             }
1101             if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1102                 D3DVALUE *position =
1103                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1104                 handle_xyz(position);
1105             } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1106                 D3DVALUE *position =
1107                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1108                 handle_xyzrhw(position);
1109             }
1110
1111             if (TRACE_ON(ddraw)) {
1112                 int tex_index;
1113
1114                 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1115                     D3DVALUE *position =
1116                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1117                     TRACE(" %f %f %f", position[0], position[1], position[2]);
1118                 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1119                     D3DVALUE *position =
1120                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1121                     TRACE(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1122                 }
1123                 if (d3dvtVertexType & D3DFVF_NORMAL) { 
1124                     D3DVALUE *normal = 
1125                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);     
1126                     DPRINTF(" / %f %f %f", normal[0], normal[1], normal[2]);
1127                 }
1128                 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1129                     DWORD *color_d = 
1130                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1131                     DPRINTF(" / %02lx %02lx %02lx %02lx",
1132                             (*color_d >> 16) & 0xFF,
1133                             (*color_d >>  8) & 0xFF,
1134                             (*color_d >>  0) & 0xFF,
1135                             (*color_d >> 24) & 0xFF);
1136                 }
1137                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1138                     DWORD *color_s = 
1139                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1140                     DPRINTF(" / %02lx %02lx %02lx %02lx",
1141                             (*color_s >> 16) & 0xFF,
1142                             (*color_s >>  8) & 0xFF,
1143                             (*color_s >>  0) & 0xFF,
1144                             (*color_s >> 24) & 0xFF);
1145                 }
1146                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1147                     D3DVALUE *tex_coord =
1148                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1149                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1150                     DPRINTF(" / %f %f", tex_coord[0], tex_coord[1]);
1151                 }
1152                 DPRINTF("\n");
1153             }
1154         }
1155     } else {
1156         ERR(" matrix weighting not handled yet....\n");
1157     }
1158     
1159     glEnd();
1160
1161     /* Whatever the case, disable the color material stuff */
1162     glDisable(GL_COLOR_MATERIAL);
1163
1164     LEAVE_GL();
1165     TRACE("End\n");    
1166 }
1167
1168 HRESULT WINAPI
1169 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1170                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1171                                           DWORD d3dvtVertexType,
1172                                           LPVOID lpvVertices,
1173                                           DWORD dwVertexCount,
1174                                           DWORD dwFlags)
1175 {
1176     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1177     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1178
1179     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1180     if (TRACE_ON(ddraw)) {
1181         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1182     }
1183
1184     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided);
1185     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1186     
1187     return DD_OK;
1188 }
1189
1190 HRESULT WINAPI
1191 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1192                                                  D3DPRIMITIVETYPE d3dptPrimitiveType,
1193                                                  DWORD d3dvtVertexType,
1194                                                  LPVOID lpvVertices,
1195                                                  DWORD dwVertexCount,
1196                                                  LPWORD dwIndices,
1197                                                  DWORD dwIndexCount,
1198                                                  DWORD dwFlags)
1199 {
1200     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1201     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1202
1203     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1204     if (TRACE_ON(ddraw)) {
1205         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1206     }
1207
1208     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided);
1209     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, 0, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1210     
1211     return DD_OK;
1212 }
1213
1214 HRESULT WINAPI
1215 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1216                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1217                                                    DWORD dwVertexType,
1218                                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1219                                                    DWORD dwVertexCount,
1220                                                    DWORD dwFlags)
1221 {
1222     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1223
1224     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1225     if (TRACE_ON(ddraw)) {
1226         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1227     }
1228     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1229
1230     return DD_OK;
1231 }
1232
1233 HRESULT WINAPI
1234 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1235                                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1236                                                           DWORD dwVertexType,
1237                                                           LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1238                                                           DWORD dwVertexCount,
1239                                                           LPWORD lpIndex,
1240                                                           DWORD dwIndexCount,
1241                                                           DWORD dwFlags)
1242 {
1243     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1244
1245     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1246     if (TRACE_ON(ddraw)) {
1247         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1248     }
1249
1250     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1251
1252     return DD_OK;
1253 }
1254
1255 HRESULT WINAPI
1256 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1257                                             D3DPRIMITIVETYPE d3dptPrimitiveType,
1258                                             LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1259                                             DWORD dwStartVertex,
1260                                             DWORD dwNumVertices,
1261                                             DWORD dwFlags)
1262 {
1263     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1264     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1265     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1266
1267     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1268     if (TRACE_ON(ddraw)) {
1269         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1270     }
1271
1272     if (vb_impl->processed == TRUE) {
1273         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1274         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1275
1276         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1277         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1278                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1279
1280         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided);
1281         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwStartVertex, dwNumVertices, NULL, dwNumVertices, dwFlags);
1282
1283     } else {
1284         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided);
1285         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwStartVertex, dwNumVertices, NULL, dwNumVertices, dwFlags);
1286     }
1287
1288     return DD_OK;
1289 }
1290
1291 HRESULT WINAPI
1292 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1293                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1294                                                    LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1295                                                    DWORD dwStartVertex,
1296                                                    DWORD dwNumVertices,
1297                                                    LPWORD lpwIndices,
1298                                                    DWORD dwIndexCount,
1299                                                    DWORD dwFlags)
1300 {
1301     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1302     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1303     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1304     
1305     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1306     if (TRACE_ON(ddraw)) {
1307         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1308     }
1309
1310     if (vb_impl->processed == TRUE) {
1311         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1312         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1313
1314         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1315         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1316                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1317
1318         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided);
1319         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1320
1321     } else {
1322         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided);
1323         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1324     }
1325
1326     return DD_OK;
1327 }
1328
1329 static GLenum
1330 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwState)
1331 {
1332     GLenum gl_state;
1333
1334     switch (dwState) {
1335         case D3DTFN_POINT:
1336             gl_state = GL_NEAREST;
1337             break;
1338         case D3DTFN_LINEAR:
1339             gl_state = GL_LINEAR;
1340             break;
1341         default:
1342             gl_state = GL_LINEAR;
1343             break;
1344     }
1345     return gl_state;
1346 }
1347
1348 static GLenum
1349 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1350 {
1351     GLenum gl_state;
1352
1353     switch (dwState) {
1354         case D3DTFG_POINT:
1355             gl_state = GL_NEAREST;
1356             break;
1357         case D3DTFG_LINEAR:
1358             gl_state = GL_LINEAR;
1359             break;
1360         default:
1361             gl_state = GL_LINEAR;
1362             break;
1363     }
1364     return gl_state;
1365 }
1366
1367 HRESULT WINAPI
1368 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1369                                                  DWORD dwStage,
1370                                                  D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1371                                                  DWORD dwState)
1372 {
1373     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1374     
1375     TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1376
1377     if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1378
1379     if (TRACE_ON(ddraw)) {
1380         TRACE(" Stage type is : ");
1381         switch (d3dTexStageStateType) {
1382 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1383             GEN_CASE(D3DTSS_COLOROP);
1384             GEN_CASE(D3DTSS_COLORARG1);
1385             GEN_CASE(D3DTSS_COLORARG2);
1386             GEN_CASE(D3DTSS_ALPHAOP);
1387             GEN_CASE(D3DTSS_ALPHAARG1);
1388             GEN_CASE(D3DTSS_ALPHAARG2);
1389             GEN_CASE(D3DTSS_BUMPENVMAT00);
1390             GEN_CASE(D3DTSS_BUMPENVMAT01);
1391             GEN_CASE(D3DTSS_BUMPENVMAT10);
1392             GEN_CASE(D3DTSS_BUMPENVMAT11);
1393             GEN_CASE(D3DTSS_TEXCOORDINDEX);
1394             GEN_CASE(D3DTSS_ADDRESS);
1395             GEN_CASE(D3DTSS_ADDRESSU);
1396             GEN_CASE(D3DTSS_ADDRESSV);
1397             GEN_CASE(D3DTSS_BORDERCOLOR);
1398             GEN_CASE(D3DTSS_MAGFILTER);
1399             GEN_CASE(D3DTSS_MINFILTER);
1400             GEN_CASE(D3DTSS_MIPFILTER);
1401             GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1402             GEN_CASE(D3DTSS_MAXMIPLEVEL);
1403             GEN_CASE(D3DTSS_MAXANISOTROPY);
1404             GEN_CASE(D3DTSS_BUMPENVLSCALE);
1405             GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1406             GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1407 #undef GEN_CASE
1408             default: DPRINTF("UNKNOWN !!!");
1409         }
1410         DPRINTF(" => ");
1411     }
1412
1413     switch (d3dTexStageStateType) {
1414         case D3DTSS_MINFILTER:
1415             if (TRACE_ON(ddraw)) {
1416                 switch ((D3DTEXTUREMINFILTER) dwState) {
1417                     case D3DTFN_POINT:  DPRINTF("D3DTFN_POINT\n"); break;
1418                     case D3DTFN_LINEAR: DPRINTF("D3DTFN_LINEAR\n"); break;
1419                     default: DPRINTF(" state unhandled (%ld).\n", dwState); break;
1420                 }
1421             }
1422             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, convert_min_filter_to_GL(dwState));
1423             break;
1424             
1425         case D3DTSS_MAGFILTER:
1426             if (TRACE_ON(ddraw)) {
1427                 switch ((D3DTEXTUREMAGFILTER) dwState) {
1428                     case D3DTFG_POINT:  DPRINTF("D3DTFN_POINT\n"); break;
1429                     case D3DTFG_LINEAR: DPRINTF("D3DTFN_LINEAR\n"); break;
1430                     default: DPRINTF(" state unhandled (%ld).\n", dwState); break;
1431                 }
1432             }
1433             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1434             break;
1435
1436         case D3DTSS_ADDRESS:
1437         case D3DTSS_ADDRESSU:
1438         case D3DTSS_ADDRESSV: {
1439             GLenum arg = GL_REPEAT; /* Default value */
1440             switch ((D3DTEXTUREADDRESS) dwState) {
1441                 case D3DTADDRESS_WRAP:   if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_WRAP\n"); arg = GL_REPEAT; break;
1442                 case D3DTADDRESS_CLAMP:  if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_CLAMP\n"); arg = GL_CLAMP; break;
1443                 case D3DTADDRESS_BORDER: if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_BORDER\n"); arg = GL_CLAMP_TO_EDGE; break;
1444                 default: DPRINTF(" state unhandled (%ld).\n", dwState);
1445             }
1446             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1447                 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1448                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1449             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1450                 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1451                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1452         } break;
1453             
1454         default:
1455             if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1456     }
1457    
1458     This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1459     /* Some special cases when one state modifies more than one... */
1460     if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1461         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1462         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1463     }
1464
1465     return DD_OK;
1466 }
1467
1468 HRESULT WINAPI
1469 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1470                                        DWORD dwStage,
1471                                        LPDIRECTDRAWSURFACE7 lpTexture2)
1472 {
1473     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1474     
1475     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1476     
1477     if (dwStage > 0) return DD_OK;
1478
1479     if (This->current_texture[dwStage] != NULL) {
1480         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1481     }
1482     
1483     ENTER_GL();
1484     if (lpTexture2 == NULL) {
1485         This->current_texture[dwStage] = NULL;
1486
1487         TRACE(" disabling 2D texturing.\n");
1488         glBindTexture(GL_TEXTURE_2D, 0);
1489         glDisable(GL_TEXTURE_2D);
1490     } else {
1491         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1492         
1493         This->current_texture[dwStage] = tex_impl;
1494         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1495         
1496         glEnable(GL_TEXTURE_2D);
1497         gltex_upload_texture(tex_impl);
1498
1499         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
1500                         convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
1501         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1502                         convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1]));
1503     }
1504     LEAVE_GL();
1505     
1506     return DD_OK;
1507 }
1508
1509 HRESULT WINAPI
1510 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1511                                  LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1512 {
1513     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1514     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1515
1516     fill_opengl_caps_7(lpD3DHELDevDesc);
1517
1518     TRACE(" returning caps : no dump function yet.\n");
1519
1520     return DD_OK;
1521 }
1522
1523 HRESULT WINAPI
1524 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
1525                                      LPD3DMATERIAL7 lpMat)
1526 {
1527     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1528     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
1529     
1530     if (TRACE_ON(ddraw)) {
1531         TRACE(" material is : \n");
1532         dump_D3DMATERIAL7(lpMat);
1533     }
1534     
1535     This->current_material = *lpMat;
1536
1537     glMaterialfv(GL_FRONT_AND_BACK,
1538                  GL_DIFFUSE,
1539                  (float *) &(This->current_material.u.diffuse));
1540     glMaterialfv(GL_FRONT_AND_BACK,
1541                  GL_AMBIENT,
1542                  (float *) &(This->current_material.u1.ambient));
1543     glMaterialfv(GL_FRONT_AND_BACK,
1544                  GL_SPECULAR,
1545                  (float *) &(This->current_material.u2.specular));
1546     glMaterialfv(GL_FRONT_AND_BACK,
1547                  GL_EMISSION,
1548                  (float *) &(This->current_material.u3.emissive));
1549     glMaterialf(GL_FRONT_AND_BACK,
1550                 GL_SHININESS,
1551                 This->current_material.u4.power); /* Not sure about this... */
1552
1553     return DD_OK;
1554 }
1555
1556
1557 HRESULT WINAPI
1558 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
1559                                   DWORD dwLightIndex,
1560                                   LPD3DLIGHT7 lpLight)
1561 {
1562     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1563     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
1564     
1565     if (TRACE_ON(ddraw)) {
1566         TRACE(" setting light : \n");
1567         dump_D3DLIGHT7(lpLight);
1568     }
1569     
1570     if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1571     This->set_lights |= 0x00000001 << dwLightIndex;
1572     This->light_parameters[dwLightIndex] = *lpLight;
1573
1574     switch (lpLight->dltType) {
1575         case D3DLIGHT_DIRECTIONAL: {
1576             float direction[4];
1577             float cut_off = 180.0;
1578             
1579             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1580             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1581             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1582             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1583
1584             direction[0] = lpLight->dvDirection.u1.x;
1585             direction[1] = lpLight->dvDirection.u2.y;
1586             direction[2] = lpLight->dvDirection.u3.z;
1587             direction[3] = 0.0;
1588             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
1589         } break;
1590
1591         case D3DLIGHT_POINT: {
1592             float position[4];
1593             float cut_off = 180.0;
1594
1595             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1596             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1597             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1598             position[0] = lpLight->dvPosition.u1.x;
1599             position[1] = lpLight->dvPosition.u2.y;
1600             position[2] = lpLight->dvPosition.u3.z;
1601             position[3] = 1.0;
1602             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1603             glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1604             glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1605             glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1606             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1607         } break;
1608
1609         case D3DLIGHT_SPOT: {
1610             float direction[4];
1611             float position[4];
1612             float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
1613
1614             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1615             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1616             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1617
1618             direction[0] = lpLight->dvDirection.u1.x;
1619             direction[1] = lpLight->dvDirection.u2.y;
1620             direction[2] = lpLight->dvDirection.u3.z;
1621             direction[3] = 0.0;
1622             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
1623             position[0] = lpLight->dvPosition.u1.x;
1624             position[1] = lpLight->dvPosition.u2.y;
1625             position[2] = lpLight->dvPosition.u3.z;
1626             position[3] = 1.0;
1627             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1628             glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1629             glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1630             glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1631             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1632             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
1633             if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
1634                 WARN("dvTheta not fully supported yet !\n");
1635             }
1636         } break;
1637
1638         default: WARN(" light type not handled yet...\n");
1639     }
1640
1641     return DD_OK;
1642 }
1643
1644 HRESULT WINAPI
1645 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
1646                                      DWORD dwLightIndex,
1647                                      BOOL bEnable)
1648 {
1649     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1650     TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
1651     
1652     if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1653
1654     if (bEnable) {
1655         if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
1656             /* Set the default parameters.. */
1657             TRACE(" setting default light parameters...\n");
1658             GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
1659         }
1660         glEnable(GL_LIGHT0 + dwLightIndex);
1661     } else {
1662         glDisable(GL_LIGHT0 + dwLightIndex);
1663     }
1664
1665     return DD_OK;
1666 }
1667
1668 HRESULT  WINAPI  
1669 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation) 
1670 {
1671     ICOM_THIS(IDirect3DDeviceImpl,iface);
1672     GLdouble plane[4];
1673
1674     TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
1675
1676     if (dwIndex>=This->max_clipping_planes) {
1677         return DDERR_INVALIDPARAMS;
1678     }
1679
1680     TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
1681
1682     memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
1683     plane[0] = pPlaneEquation[0];
1684     plane[1] = pPlaneEquation[1];
1685     plane[2] = pPlaneEquation[2];
1686     plane[3] = pPlaneEquation[3];
1687
1688     /* XXX: is here also code needed to handle the transformation of the world? */
1689     glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
1690
1691     return D3D_OK;
1692 }
1693
1694 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1695 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
1696 #else
1697 # define XCAST(fun)     (void*)
1698 #endif
1699
1700 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1701 {
1702     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1703     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1704     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1705     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1706     XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1707     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1708     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1709     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1710     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1711     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1712     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1713     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1714     XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1715     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1716     XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1717     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1718     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1719     XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
1720     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1721     XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
1722     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1723     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1724     XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1725     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1726     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1727     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1728     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1729     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1730     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1731     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1732     XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1733     XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1734     XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
1735     XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
1736     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1737     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
1738     XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
1739     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1740     XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1741     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1742     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1743     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1744     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1745     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1746     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1747     XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
1748     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1749     XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
1750     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1751     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1752 };
1753
1754 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1755 #undef XCAST
1756 #endif
1757
1758
1759 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1760 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
1761 #else
1762 # define XCAST(fun)     (void*)
1763 #endif
1764
1765 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1766 {
1767     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1768     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1769     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1770     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1771     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1772     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1773     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1774     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1775     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1776     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1777     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1778     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1779     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1780     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1781     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1782     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1783     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1784     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1785     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1786     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1787     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1788     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1789     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1790     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1791     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1792     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1793     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1794     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1795     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1796     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1797     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1798     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1799     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1800     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1801     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1802     XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1803     XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1804     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1805     XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
1806     XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
1807     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1808     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1809     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1810 };
1811
1812 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1813 #undef XCAST
1814 #endif
1815
1816
1817 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1818 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
1819 #else
1820 # define XCAST(fun)     (void*)
1821 #endif
1822
1823 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1824 {
1825     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1826     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1827     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1828     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1829     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1830     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
1831     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1832     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1833     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1834     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1835     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1836     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1837     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1838     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1839     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1840     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1841     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1842     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1843     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1844     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1845     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1846     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1847     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1848     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1849     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1850     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1851     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1852     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1853     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1854     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1855     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1856     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1857     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1858     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1859 };
1860
1861 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1862 #undef XCAST
1863 #endif
1864
1865
1866 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1867 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
1868 #else
1869 # define XCAST(fun)     (void*)
1870 #endif
1871
1872 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1873 {
1874     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1875     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1876     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1877     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1878     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1879     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1880     XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
1881     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1882     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1883     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1884     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1885     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1886     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1887     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1888     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1889     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1890     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1891     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1892     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1893     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1894     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1895     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1896     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1897 };
1898
1899 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1900 #undef XCAST
1901 #endif
1902
1903 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
1904                                DWORD dwCount,
1905                                LPD3DRECT lpRects,
1906                                DWORD dwFlags,
1907                                DWORD dwColor,
1908                                D3DVALUE dvZ,
1909                                DWORD dwStencil)
1910 {
1911     GLboolean ztest;
1912     GLfloat old_z_clear_value;
1913     GLbitfield bitfield = 0;
1914     GLint old_stencil_clear_value;
1915     GLfloat old_color_clear_value[4];
1916     
1917     TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1918     if (TRACE_ON(ddraw)) {
1919         if (dwCount > 0) {
1920             int i;
1921             TRACE(" rectangles : \n");
1922             for (i = 0; i < dwCount; i++) {
1923                 TRACE("  - %ld x %ld     %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
1924             }
1925         }
1926     }
1927
1928     if (dwCount > 1) {
1929         WARN("  Warning, this function only for now clears the whole screen...\n");
1930     }
1931
1932     /* Clears the screen */
1933     ENTER_GL();
1934     if (dwFlags & D3DCLEAR_ZBUFFER) {
1935         bitfield |= GL_DEPTH_BUFFER_BIT;
1936         glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
1937         glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
1938         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1939         glClearDepth(dvZ);
1940         TRACE(" depth value : %f\n", dvZ);
1941     }
1942     if (dwFlags & D3DCLEAR_STENCIL) {
1943         bitfield |= GL_STENCIL_BUFFER_BIT;
1944         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1945         glClearStencil(dwStencil);
1946         TRACE(" stencil value : %ld\n", dwStencil);
1947     }    
1948     if (dwFlags & D3DCLEAR_TARGET) {
1949         bitfield |= GL_COLOR_BUFFER_BIT;
1950         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1951         glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
1952                      ((dwColor >>  8) & 0xFF) / 255.0,
1953                      ((dwColor >>  0) & 0xFF) / 255.0,
1954                      ((dwColor >> 24) & 0xFF) / 255.0);
1955         TRACE(" color value (ARGB) : %08lx\n", dwColor);
1956     }
1957     
1958     glClear(bitfield);
1959     
1960     if (dwFlags & D3DCLEAR_ZBUFFER) {
1961         glDepthMask(ztest);
1962         glClearDepth(old_z_clear_value);
1963     }
1964      if (dwFlags & D3DCLEAR_STENCIL) {
1965         bitfield |= GL_STENCIL_BUFFER_BIT;
1966         glClearStencil(old_stencil_clear_value);
1967     }    
1968     if (dwFlags & D3DCLEAR_TARGET) {
1969         bitfield |= GL_COLOR_BUFFER_BIT;
1970         glClearColor(old_color_clear_value[0],
1971                      old_color_clear_value[1],
1972                      old_color_clear_value[2],
1973                      old_color_clear_value[3]);
1974     }
1975     
1976     LEAVE_GL();
1977     
1978     return DD_OK;
1979 }
1980
1981 HRESULT
1982 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
1983               LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
1984               DWORD dwFlags, LPDDBLTFX lpbltfx)
1985 {
1986     if (dwFlags & DDBLT_COLORFILL) {
1987         /* This is easy to handle for the D3D Device... */
1988         DWORD color = lpbltfx->u5.dwFillColor;
1989         TRACE(" executing D3D Device override.\n");
1990         d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
1991         return DD_OK;
1992     }
1993     return DDERR_INVALIDPARAMS;
1994 }
1995
1996 HRESULT
1997 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
1998                   DWORD dsty, LPDIRECTDRAWSURFACE7 src,
1999                   LPRECT rsrc, DWORD trans)
2000 {
2001      return DDERR_INVALIDPARAMS;
2002 }
2003
2004 void
2005 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2006 {
2007     GLfloat height, width;
2008     GLfloat trans_mat[16];
2009     
2010     width = This->surface->surface_desc.dwWidth;
2011     height = This->surface->surface_desc.dwHeight;
2012     
2013     /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2014        to OpenGL screen coordinates (ie the upper left corner is not the same).
2015        For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2016        -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2017     trans_mat[ 0] = 2.0 / width;  trans_mat[ 4] = 0.0;  trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2018     trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] =  1.0;
2019     trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0;           trans_mat[14] = -1.0;
2020     trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0;           trans_mat[15] =  1.0;
2021     
2022     glMatrixMode(GL_MODELVIEW);
2023     glLoadIdentity();
2024     glMatrixMode(GL_PROJECTION);
2025     glLoadMatrixf(trans_mat);
2026 }
2027
2028 void
2029 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2030                        D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2031 {
2032     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2033         glMatrixMode(GL_MODELVIEW);
2034         glLoadMatrixf((float *) view_mat);
2035         glMultMatrixf((float *) world_mat);
2036     }
2037     if ((matrices & PROJMAT_CHANGED) != 0) {
2038         glMatrixMode(GL_PROJECTION);
2039         glLoadMatrixf((float *) proj_mat);
2040     }
2041 }
2042
2043 void
2044 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2045 {
2046     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2047     if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2048         /* This will force an update of the transform state at the next drawing. */
2049         glThis->transform_state = GL_TRANSFORM_NONE;
2050     }
2051 }
2052
2053 /* TODO for both these functions :
2054     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2055       by other OpenGL code in D3D
2056     - handle the case where no 'Begin / EndScene' was done between two locks
2057     - handle the rectangles in the unlock too
2058     - handle pitch correctly...
2059 */
2060 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2061 {
2062     /* First, check if we need to do anything */
2063     if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
2064         GLenum buffer_type;
2065         GLenum prev_read;
2066         RECT loc_rect;
2067
2068         ENTER_GL();
2069
2070         glGetIntegerv(GL_READ_BUFFER, &prev_read);
2071         glFlush();
2072         
2073         WARN(" application does a lock on a 3D surface - expect slow downs.\n");
2074         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2075             /* Application wants to lock the front buffer */
2076             glReadBuffer(GL_FRONT);
2077         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2078             /* Application wants to lock the back buffer */
2079             glReadBuffer(GL_BACK);
2080         } else {
2081             WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
2082         }
2083
2084         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2085             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2086         } else {
2087             WARN(" unsupported pixel format.\n");
2088             LEAVE_GL();
2089             return;
2090         }
2091         if (pRect == NULL) {
2092             loc_rect.top = 0;
2093             loc_rect.left = 0;
2094             loc_rect.bottom = This->surface_desc.dwHeight;
2095             loc_rect.right = This->surface_desc.dwWidth;
2096         } else {
2097             loc_rect = *pRect;
2098         }
2099         glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
2100                      GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
2101                                            + loc_rect.top * This->surface_desc.u1.lPitch
2102                                            + loc_rect.left * GET_BPP(This->surface_desc)));
2103         glReadBuffer(prev_read);
2104         LEAVE_GL();
2105     }
2106 }
2107
2108 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2109 {
2110     /* First, check if we need to do anything */
2111     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
2112         GLenum buffer_type;
2113         GLenum prev_draw;
2114
2115         ENTER_GL();
2116
2117         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2118
2119         WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
2120         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2121             /* Application wants to lock the front buffer */
2122             glDrawBuffer(GL_FRONT);
2123         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2124             /* Application wants to lock the back buffer */
2125             glDrawBuffer(GL_BACK);
2126         } else {
2127             WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
2128         }
2129
2130         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2131             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2132         } else {
2133             WARN(" unsupported pixel format.\n");
2134             LEAVE_GL();
2135             return;
2136         }
2137         glRasterPos2f(0.0, 0.0);
2138         glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight, 
2139                      GL_RGB, buffer_type, This->surface_desc.lpSurface);
2140         glDrawBuffer(prev_draw);
2141
2142         LEAVE_GL();
2143    }
2144 }
2145
2146 HRESULT
2147 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2148 {
2149     IDirect3DDeviceImpl *object;
2150     IDirect3DDeviceGLImpl *gl_object;
2151     IDirectDrawSurfaceImpl *surf;
2152     HDC device_context;
2153     XVisualInfo *vis;
2154     int num;
2155     XVisualInfo template;
2156     GLenum buffer = GL_FRONT;
2157     int light;
2158     GLint max_clipping_planes = 0;
2159     
2160     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2161     if (object == NULL) return DDERR_OUTOFMEMORY;
2162
2163     gl_object = (IDirect3DDeviceGLImpl *) object;
2164     
2165     object->ref = 1;
2166     object->d3d = d3d;
2167     object->surface = surface;
2168     object->set_context = set_context;
2169     object->clear = d3ddevice_clear;
2170     object->set_matrices = d3ddevice_set_matrices;
2171     object->matrices_updated = d3ddevice_matrices_updated;
2172
2173     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2174
2175     device_context = GetDC(surface->ddraw_owner->window);
2176     gl_object->display = get_display(device_context);
2177     gl_object->drawable = get_drawable(device_context);
2178     ReleaseDC(surface->ddraw_owner->window,device_context);
2179
2180     ENTER_GL();
2181     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2182     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2183     if (vis == NULL) {
2184         HeapFree(GetProcessHeap(), 0, object);
2185         ERR("No visual found !\n");
2186         LEAVE_GL();
2187         return DDERR_INVALIDPARAMS;
2188     } else {
2189         TRACE(" visual found\n");
2190     }
2191
2192     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2193                                              NULL, GL_TRUE);
2194
2195     if (gl_object->gl_context == NULL) {
2196         HeapFree(GetProcessHeap(), 0, object);
2197         ERR("Error in context creation !\n");
2198         LEAVE_GL();
2199         return DDERR_INVALIDPARAMS;
2200     } else {
2201         TRACE(" context created (%p)\n", gl_object->gl_context);
2202     }
2203     
2204     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2205     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2206         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2207             surf->aux_ctx  = (LPVOID) gl_object->display;
2208             surf->aux_data = (LPVOID) gl_object->drawable;
2209             surf->aux_flip = opengl_flip;
2210             buffer =  GL_BACK;
2211             break;
2212         }
2213     }
2214     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2215     if (surf == NULL) {
2216         TRACE(" no double buffering : drawing on the front buffer\n");
2217         buffer = GL_FRONT;
2218     }
2219     
2220     for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
2221     for (; surf != NULL; surf = surf->next_attached) {
2222         if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2223             ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2224             /* Override the Lock / Unlock function for all these surfaces */
2225             surf->lock_update = d3ddevice_lock_update;
2226             surf->unlock_update = d3ddevice_unlock_update;
2227             /* And install also the blt / bltfast overrides */
2228             surf->aux_blt = d3ddevice_blt;
2229             surf->aux_bltfast = d3ddevice_bltfast;
2230         }
2231         surf->d3ddevice = object;
2232     }
2233
2234     /* Set the various light parameters */
2235     for (light = 0; light < MAX_LIGHTS; light++) {
2236         /* Only set the fields that are not zero-created */
2237         object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2238         object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2239         object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2240         object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2241         object->light_parameters[light].dvDirection.u3.z = 1.0;
2242     }
2243     
2244     /* Allocate memory for the matrices */
2245     object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2246     object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2247     object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2248     memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2249     memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2250     memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2251
2252     /* allocate the clipping planes */
2253     glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
2254     if (max_clipping_planes>32) {
2255         object->max_clipping_planes=32;
2256     } else {
2257         object->max_clipping_planes = max_clipping_planes;
2258     }
2259     TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
2260     object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
2261
2262     /* Initialisation */
2263     TRACE(" setting current context\n");
2264     LEAVE_GL();
2265     object->set_context(object);
2266     ENTER_GL();
2267     TRACE(" current context set\n");
2268
2269     glClearColor(0.0, 0.0, 0.0, 0.0);
2270     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2271     glDrawBuffer(buffer);
2272     glReadBuffer(buffer);
2273     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2274     LEAVE_GL();
2275
2276     /* fill_device_capabilities(d3d->ddraw); */    
2277     
2278     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
2279     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2280     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2281     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2282
2283     *obj = object;
2284
2285     TRACE(" creating implementation at %p.\n", *obj);
2286
2287     /* And finally warn D3D that this device is now present */
2288     object->d3d->added_device(object->d3d, object);
2289
2290     /* FIXME: Should handle other versions than just 7 */
2291     InitDefaultStateBlock(&object->state_block, 7);
2292     /* Apply default render state values */
2293     apply_render_state(object, &object->state_block);
2294     /* FIXME: do something similar for ligh_state and texture_stage_state */
2295
2296     return DD_OK;
2297 }