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