fdopen: don't rewind the file after creating the FILE* handle. Added
[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 #include "windef.h"
27 #include "winerror.h"
28 #include "objbase.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
32
33 #include "mesa_private.h"
34 #include "main.h"
35
36 #include "x11drv.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39
40 /* They are non-static as they are used by Direct3D in the creation function */
41 const GUID IID_D3DDEVICE_OpenGL = {
42   0x31416d44,
43   0x86ae,
44   0x11d2,
45   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
46 };
47
48 #ifndef HAVE_GLEXT_PROTOTYPES
49 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
50 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
51                                          GLsizei width, GLenum format, GLenum type,
52                                          const GLvoid *table);
53 #endif
54
55 static const float id_mat[16] = {
56     1.0, 0.0, 0.0, 0.0,
57     0.0, 1.0, 0.0, 0.0,
58     0.0, 0.0, 1.0, 0.0,
59     0.0, 0.0, 0.0, 1.0
60 };
61
62 /* retrieve the X display to use on a given DC */
63 inline static Display *get_display( HDC hdc )
64 {
65     Display *display;
66     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
67
68     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69                     sizeof(display), (LPSTR)&display )) display = NULL;
70
71     return display;
72 }
73
74
75 /* retrieve the X drawable to use on a given DC */
76 inline static Drawable get_drawable( HDC hdc )
77 {
78     Drawable drawable;
79     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
80
81     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
82                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
83
84     return drawable;
85 }
86
87
88 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
89 {
90     TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
91     ENTER_GL();
92     glXSwapBuffers((Display*)display,(Drawable)drawable);
93     LEAVE_GL();
94     return TRUE;
95 }
96
97
98 /*******************************************************************************
99  *                              OpenGL static functions
100  */
101 static void set_context(IDirect3DDeviceImpl* This)
102 {
103     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
104    
105     ENTER_GL();
106     TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
107     if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
108         ERR("Error in setting current context (context %p drawable %ld)!\n",
109             glThis->gl_context, glThis->drawable);
110     }
111     LEAVE_GL();
112 }
113
114 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
115 {
116     pc->dwSize = sizeof(*pc);
117     pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
118       D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
119     pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
120       D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
121     pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
122     pc->dwSrcBlendCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
123     pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
124     pc->dwAlphaCmpCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
125     pc->dwShadeCaps = 0xFFFFFFFF;     /* FIXME: need REAL values */
126     pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
127       D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
128     pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
129       D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
130     pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
131     pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
132     pc->dwStippleWidth = 32;
133     pc->dwStippleHeight = 32;
134 }
135
136 static void fill_opengl_caps(D3DDEVICEDESC *d1)
137 {
138     /* GLint maxlight; */
139
140     d1->dwSize  = sizeof(*d1);
141     d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
142       | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
143     d1->dcmColorModel = D3DCOLOR_RGB;
144     d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
145       D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
146       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
147     d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
148     d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
149     d1->bClipping = TRUE;
150     d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
151     d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
152     d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
153     d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
154     fill_opengl_primcaps(&(d1->dpcLineCaps));
155     fill_opengl_primcaps(&(d1->dpcTriCaps));
156     d1->dwDeviceRenderBitDepth  = DDBD_16|DDBD_24|DDBD_32;
157     d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
158     d1->dwMaxBufferSize = 0;
159     d1->dwMaxVertexCount = 65536;
160     d1->dwMinTextureWidth  = 1;
161     d1->dwMinTextureHeight = 1;
162     d1->dwMaxTextureWidth  = 1024;
163     d1->dwMaxTextureHeight = 1024;
164     d1->dwMinStippleWidth  = 1;
165     d1->dwMinStippleHeight = 1;
166     d1->dwMaxStippleWidth  = 32;
167     d1->dwMaxStippleHeight = 32;
168     d1->dwMaxTextureRepeat = 16;
169     d1->dwMaxTextureAspectRatio = 1024;
170     d1->dwMaxAnisotropy = 0;
171     d1->dvGuardBandLeft = 0.0;
172     d1->dvGuardBandRight = 0.0;
173     d1->dvGuardBandTop = 0.0;
174     d1->dvGuardBandBottom = 0.0;
175     d1->dvExtentsAdjust = 0.0;
176     d1->dwStencilCaps = 0; /* TODO add proper caps according to what OpenGL can do */
177     d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
178     d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
179     d1->wMaxTextureBlendStages = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
180     d1->wMaxSimultaneousTextures = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
181 }
182
183 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
184 {
185     D3DDEVICEDESC d1;
186
187     /* Copy first D3D1/2/3 capabilities */
188     fill_opengl_caps(&d1);
189
190     /* And fill the D3D7 one with it */
191     d->dwDevCaps = d1.dwDevCaps;
192     d->dpcLineCaps = d1.dpcLineCaps;
193     d->dpcTriCaps = d1.dpcTriCaps;
194     d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
195     d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
196     d->dwMinTextureWidth = d1.dwMinTextureWidth;
197     d->dwMinTextureHeight = d1.dwMinTextureHeight;
198     d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
199     d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
200     d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
201     d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
202     d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
203     d->dvGuardBandLeft = d1.dvGuardBandLeft;
204     d->dvGuardBandTop = d1.dvGuardBandTop;
205     d->dvGuardBandRight = d1.dvGuardBandRight;
206     d->dvGuardBandBottom = d1.dvGuardBandBottom;
207     d->dvExtentsAdjust = d1.dvExtentsAdjust;
208     d->dwStencilCaps = d1.dwStencilCaps;
209     d->dwFVFCaps = d1.dwFVFCaps;
210     d->dwTextureOpCaps = d1.dwTextureOpCaps;
211     d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
212     d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
213     d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
214     d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
215     d->deviceGUID = IID_IDirect3DTnLHalDevice;
216     d->wMaxUserClipPlanes = 1;
217     d->wMaxVertexBlendMatrices = 0;
218     d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
219       D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
220     d->dwReserved1 = 0;
221     d->dwReserved2 = 0;
222     d->dwReserved3 = 0;
223     d->dwReserved4 = 0;
224 }
225
226 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
227 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
228 {
229     x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
230     const char *ext_string;
231     Mesa_DeviceCapabilities *devcap;
232
233     private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
234     devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
235
236     ENTER_GL();
237     ext_string = glGetString(GL_EXTENSIONS);
238     /* Query for the ColorTable Extension */
239     if (strstr(ext_string, "GL_EXT_paletted_texture")) {
240         devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
241         TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
242     } else {
243         TRACE("Color table extension not found.\n");
244     }
245     LEAVE_GL();
246 }
247 #endif
248
249
250
251 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
252 {
253     D3DDEVICEDESC d1, d2;
254
255     fill_opengl_caps(&d1);
256     d2 = d1;
257
258     TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
259     return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
260 }
261
262 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
263 {
264     D3DDEVICEDESC7 ddesc;
265
266     fill_opengl_caps_7(&ddesc);
267     
268     TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
269     
270     return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
271 }
272
273 ULONG WINAPI
274 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
275 {
276     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
277     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
278     
279     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
280     if (!--(This->ref)) {
281         /* Release texture associated with the device */ 
282         if (This->current_texture[0] != NULL)
283             IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
284
285         if (glThis->handler) HeapFree(GetProcessHeap(), 0, This);
286         
287         ENTER_GL();
288         glXDestroyContext(glThis->display, glThis->gl_context);
289         LEAVE_GL();
290
291         HeapFree(GetProcessHeap(), 0, This);
292         return 0;
293     }
294     return This->ref;
295 }
296
297 HRESULT WINAPI
298 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
299                                        LPD3DDEVICEDESC lpD3DHWDevDesc,
300                                        LPD3DDEVICEDESC lpD3DHELDevDesc)
301 {
302     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
303     D3DDEVICEDESC desc;
304     DWORD dwSize;
305
306     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
307
308     fill_opengl_caps(&desc);
309     dwSize = lpD3DHWDevDesc->dwSize;
310     memset(lpD3DHWDevDesc, 0, dwSize);
311     memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
312
313     dwSize = lpD3DHELDevDesc->dwSize;
314     memset(lpD3DHELDevDesc, 0, dwSize);
315     memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
316
317     TRACE(" returning caps : (no dump function yet)\n");
318
319     return DD_OK;
320 }
321
322 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
323                                           LPD3DENUMPIXELFORMATSCALLBACK cb_2,
324                                           LPVOID context)
325 {
326     DDSURFACEDESC sdesc;
327     LPDDPIXELFORMAT pformat;
328
329     /* Do the texture enumeration */
330     sdesc.dwSize = sizeof(DDSURFACEDESC);
331     sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
332     sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
333     pformat = &(sdesc.ddpfPixelFormat);
334     pformat->dwSize = sizeof(DDPIXELFORMAT);
335     pformat->dwFourCC = 0;
336
337     TRACE("Enumerating GL_RGBA unpacked (32)\n");
338     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
339     pformat->u1.dwRGBBitCount = 32;
340     pformat->u2.dwRBitMask =         0xFF000000;
341     pformat->u3.dwGBitMask =         0x00FF0000;
342     pformat->u4.dwBBitMask =        0x0000FF00;
343     pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
344     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
345     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
346
347     TRACE("Enumerating GL_RGB unpacked (24)\n");
348     pformat->dwFlags = DDPF_RGB;
349     pformat->u1.dwRGBBitCount = 24;
350     pformat->u2.dwRBitMask =  0x00FF0000;
351     pformat->u3.dwGBitMask =  0x0000FF00;
352     pformat->u4.dwBBitMask = 0x000000FF;
353     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
354     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
355     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
356
357     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
358     pformat->dwFlags = DDPF_RGB;
359     pformat->u1.dwRGBBitCount = 16;
360     pformat->u2.dwRBitMask =  0x0000F800;
361     pformat->u3.dwGBitMask =  0x000007E0;
362     pformat->u4.dwBBitMask = 0x0000001F;
363     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
364     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
365     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
366
367     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
368     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
369     pformat->u1.dwRGBBitCount = 16;
370     pformat->u2.dwRBitMask =        0x0000F800;
371     pformat->u3.dwGBitMask =        0x000007C0;
372     pformat->u4.dwBBitMask =        0x0000003E;
373     pformat->u5.dwRGBAlphaBitMask = 0x00000001;
374     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
375     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
376
377     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
378     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
379     pformat->u1.dwRGBBitCount = 16;
380     pformat->u2.dwRBitMask =        0x0000F000;
381     pformat->u3.dwGBitMask =        0x00000F00;
382     pformat->u4.dwBBitMask =        0x000000F0;
383     pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
384     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
385     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
386
387     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (16)\n");
388     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
389     pformat->u1.dwRGBBitCount = 16;
390     pformat->u2.dwRBitMask =        0x00007C00;
391     pformat->u3.dwGBitMask =        0x000003E0;
392     pformat->u4.dwBBitMask =        0x0000001F;
393     pformat->u5.dwRGBAlphaBitMask = 0x00008000;
394     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
395     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
396
397     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
398     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
399     pformat->u1.dwRGBBitCount = 16;
400     pformat->u2.dwRBitMask =        0x00000F00;
401     pformat->u3.dwGBitMask =        0x000000F0;
402     pformat->u4.dwBBitMask =        0x0000000F;
403     pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
404     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
405     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
406
407     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
408     pformat->dwFlags = DDPF_RGB;
409     pformat->u1.dwRGBBitCount = 8;
410     pformat->u2.dwRBitMask =        0x000000E0;
411     pformat->u3.dwGBitMask =        0x0000001C;
412     pformat->u4.dwBBitMask =        0x00000003;
413     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
414     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
415     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
416
417     TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
418     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
419     pformat->u1.dwRGBBitCount = 16;
420     pformat->u2.dwRBitMask =         0x00007C00;
421     pformat->u3.dwGBitMask =         0x000003E0;
422     pformat->u4.dwBBitMask =         0x0000001F;
423     pformat->u5.dwRGBAlphaBitMask =  0x00008000;
424     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
425     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
426
427     TRACE("Enumerating Paletted (8)\n");
428     pformat->dwFlags = DDPF_PALETTEINDEXED8;
429     pformat->u1.dwRGBBitCount = 8;
430     pformat->u2.dwRBitMask =  0x00000000;
431     pformat->u3.dwGBitMask =  0x00000000;
432     pformat->u4.dwBBitMask = 0x00000000;
433     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
434     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
435     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
436
437     TRACE("End of enumeration\n");
438     return DD_OK;
439 }
440
441
442 HRESULT
443 d3ddevice_find(IDirect3DImpl *d3d,
444                LPD3DFINDDEVICESEARCH lpD3DDFS,
445                LPD3DFINDDEVICERESULT lplpD3DDevice)
446 {
447     DWORD dwSize;
448     D3DDEVICEDESC desc;
449   
450     if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
451         (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
452         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
453         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
454     }
455     if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
456         TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
457         if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
458             (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
459             TRACE(" no match for this GUID.\n");
460             return DDERR_INVALIDPARAMS;
461         }
462     }
463
464     /* Now return our own GUID */
465     lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
466     fill_opengl_caps(&desc);
467     dwSize = lplpD3DDevice->ddHwDesc.dwSize;
468     memset(&(lplpD3DDevice->ddHwDesc), 0, dwSize);
469     memcpy(&(lplpD3DDevice->ddHwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
470     dwSize = lplpD3DDevice->ddSwDesc.dwSize;
471     memset(&(lplpD3DDevice->ddSwDesc), 0, dwSize);
472     memcpy(&(lplpD3DDevice->ddSwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
473     
474     return D3D_OK;
475 }
476
477 HRESULT WINAPI
478 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
479                                                LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
480                                                LPVOID lpArg)
481 {
482     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
483     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
484     return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
485 }
486
487 HRESULT WINAPI
488 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
489                                                LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
490                                                LPVOID lpArg)
491 {
492     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
493     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
494     return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
495 }
496
497 HRESULT WINAPI
498 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
499                                               D3DRENDERSTATETYPE dwRenderStateType,
500                                               DWORD dwRenderState)
501 {
502     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
503     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
504     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
505
506     /* Call the render state functions */
507     set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
508
509     return DD_OK;
510 }
511
512 HRESULT WINAPI
513 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
514                                           D3DLIGHTSTATETYPE dwLightStateType,
515                                           DWORD dwLightState)
516 {
517     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
518     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
519
520     switch (dwLightStateType) {
521         case D3DLIGHTSTATE_MATERIAL: {  /* 1 */
522             IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
523
524             if (mat != NULL) {
525                 ENTER_GL();
526                 mat->activate(mat);
527                 LEAVE_GL();
528             } else {
529                 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
530             }
531         } break;
532
533         case D3DLIGHTSTATE_AMBIENT: {   /* 2 */
534             float light[4];
535
536             light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
537             light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
538             light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
539             light[3] = 1.0;
540             ENTER_GL();
541             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
542             LEAVE_GL();
543         } break;
544
545 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
546         UNSUP(COLORMODEL);
547         UNSUP(FOGMODE);
548         UNSUP(FOGSTART);
549         UNSUP(FOGEND);
550         UNSUP(FOGDENSITY);
551         UNSUP(COLORVERTEX);
552 #undef UNSUP
553
554         default:
555             TRACE("Unexpected Light State Type\n");
556             return DDERR_INVALIDPARAMS;
557     }
558
559     return DD_OK;
560 }
561
562 HRESULT WINAPI
563 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
564                                             D3DTRANSFORMSTATETYPE dtstTransformStateType,
565                                             LPD3DMATRIX lpD3DMatrix)
566 {
567     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
568     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
569
570     TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
571
572     ENTER_GL();
573
574     /* Using a trial and failure approach, I found that the order of
575        Direct3D transformations that works best is :
576
577        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
578
579        As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
580        OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
581
582        If anyone has a good explanation of the three different matrices in
583        the SDK online documentation, feel free to point it to me. For example,
584        which matrices transform lights ? In OpenGL only the PROJECTION matrix
585        transform the lights, not the MODELVIEW. Using the matrix names, I
586        supposed that PROJECTION and VIEW (all 'camera' related names) do
587        transform lights, but WORLD do not. It may be wrong though... */
588
589     /* After reading through both OpenGL and Direct3D documentations, I
590        thought that D3D matrices were written in 'line major mode' transposed
591        from OpenGL's 'column major mode'. But I found out that a simple memcpy
592        works fine to transfer one matrix format to the other (it did not work
593        when transposing)....
594
595        So :
596          1) are the documentations wrong
597          2) does the matrix work even if they are not read correctly
598          3) is Mesa's implementation of OpenGL not compliant regarding Matrix
599             loading using glLoadMatrix ?
600
601        Anyway, I always use 'conv_mat' to transfer the matrices from one format
602        to the other so that if I ever find out that I need to transpose them, I
603        will able to do it quickly, only by changing the macro conv_mat. */
604
605     switch (dtstTransformStateType) {
606         case D3DTRANSFORMSTATE_WORLD: {
607             TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
608             conv_mat(lpD3DMatrix, glThis->world_mat);
609             glMatrixMode(GL_MODELVIEW);
610             glLoadMatrixf((float *) glThis->view_mat);
611             glMultMatrixf((float *) glThis->world_mat);
612         } break;
613
614         case D3DTRANSFORMSTATE_VIEW: {
615             TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
616             conv_mat(lpD3DMatrix, glThis->view_mat);
617             glMatrixMode(GL_MODELVIEW);
618             glLoadMatrixf((float *) glThis->view_mat);
619             glMultMatrixf((float *) glThis->world_mat);
620         } break;
621
622         case D3DTRANSFORMSTATE_PROJECTION: {
623             TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
624             conv_mat(lpD3DMatrix, glThis->proj_mat);
625             glMatrixMode(GL_PROJECTION);
626             glLoadMatrixf((float *) glThis->proj_mat);
627         } break;
628
629         default:
630             ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
631             break;
632     }
633     LEAVE_GL();
634
635     return DD_OK;
636 }
637
638 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
639 {
640     switch (d3dpt) {
641         case D3DPT_POINTLIST:
642             TRACE("Start POINTS\n");
643             glBegin(GL_POINTS);
644             break;
645
646         case D3DPT_LINELIST:
647             TRACE("Start LINES\n");
648             glBegin(GL_LINES);
649             break;
650
651         case D3DPT_LINESTRIP:
652             TRACE("Start LINE_STRIP\n");
653             glBegin(GL_LINE_STRIP);
654             break;
655
656         case D3DPT_TRIANGLELIST:
657             TRACE("Start TRIANGLES\n");
658             glBegin(GL_TRIANGLES);
659             break;
660
661         case D3DPT_TRIANGLESTRIP:
662             TRACE("Start TRIANGLE_STRIP\n");
663             glBegin(GL_TRIANGLE_STRIP);
664             break;
665
666         case D3DPT_TRIANGLEFAN:
667             TRACE("Start TRIANGLE_FAN\n");
668             glBegin(GL_TRIANGLE_FAN);
669             break;
670
671         default:
672             TRACE("Unhandled primitive\n");
673             break;
674     }
675 }
676
677 static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
678                                            BOOLEAN vertex_transformed,
679                                            BOOLEAN vertex_lit) {
680     /* Puts GL in the correct lighting / transformation mode */
681     if ((glThis->last_vertices_transformed == TRUE) && (vertex_transformed == FALSE)) {
682         /* Need to put the correct transformation again if we go from Transformed
683            vertices to non-transformed ones.
684         */
685         glMatrixMode(GL_MODELVIEW);
686         glLoadMatrixf((float *) glThis->view_mat);
687         glMultMatrixf((float *) glThis->world_mat);
688         glMatrixMode(GL_PROJECTION);
689         glLoadMatrixf((float *) glThis->proj_mat);
690     } else if ((glThis->last_vertices_transformed == FALSE) && (vertex_transformed == TRUE)) {
691         GLdouble height, width, minZ, maxZ;
692       
693         glMatrixMode(GL_MODELVIEW);
694         glLoadIdentity();
695         glMatrixMode(GL_PROJECTION);
696         glLoadIdentity();
697         
698         if (glThis->parent.current_viewport == NULL) {
699             ERR("No current viewport !\n");
700             /* Using standard values */
701             height = 640.0;
702             width = 480.0;
703             minZ = -10.0;
704             maxZ = 10.0;
705         } else {
706             if (glThis->parent.current_viewport->use_vp2 == 1) {
707                 height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
708                 width  = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
709                 minZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
710                 maxZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
711             } else {
712                 height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
713                 width  = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
714                 minZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
715                 maxZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
716             }
717         }
718         glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
719     }
720     
721     if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
722         glEnable(GL_LIGHTING);
723     } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
724         glDisable(GL_LIGHTING);
725     }
726
727     /* And save the current state */
728     glThis->last_vertices_transformed = vertex_transformed;
729     glThis->last_vertices_lit = vertex_lit;
730 }
731
732
733 inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
734                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
735 {
736     DWORD vx_index;
737   
738     draw_primitive_handle_GL_state(glThis, d3dvt == D3DVT_TLVERTEX, d3dvt != D3DVT_VERTEX);
739     draw_primitive_start_GL(d3dpt);
740     
741     /* Draw the primitives */
742     for (vx_index = 0; vx_index < maxvert; vx_index++) {
743         switch (d3dvt) {
744             case D3DVT_VERTEX: {
745                 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
746
747                 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
748                 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
749                 TRACE("   V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
750             } break;
751
752             case D3DVT_LVERTEX: {
753                 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
754                 DWORD col = vx->u4.color;
755
756                 glColor4ub((col >> 16) & 0xFF,
757                            (col >>  8) & 0xFF,
758                            (col >>  0) & 0xFF,
759                            (col >> 24) & 0xFF);
760                 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
761                 TRACE("  LV: %f %f %f (%02lx %02lx %02lx %02lx)\n",
762                       vx->u1.x, vx->u2.y, vx->u3.z,
763                       ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF), ((col >> 24) & 0xFF));
764             } break;
765
766             case D3DVT_TLVERTEX: {
767                 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
768                 DWORD col = vx->u5.color;
769
770                 glColor4ub((col >> 16) & 0xFF,
771                            (col >>  8) & 0xFF,
772                            (col >>  0) & 0xFF,
773                            (col >> 24) & 0xFF);
774                 glTexCoord2f(vx->u7.tu, vx->u8.tv);
775                 if (vx->u4.rhw < 0.01)
776                     glVertex3f(vx->u1.sx,
777                                vx->u2.sy,
778                                vx->u3.sz);
779                 else
780                     glVertex4f(vx->u1.sx / vx->u4.rhw,
781                                vx->u2.sy / vx->u4.rhw,
782                                vx->u3.sz / vx->u4.rhw,
783                                1.0 / vx->u4.rhw);
784                 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx %02lx) (%f %f) (%f)\n",
785                       vx->u1.sx, vx->u2.sy, vx->u3.sz,
786                       ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF), ((col >> 24) & 0xFF),
787                       vx->u7.tu, vx->u8.tv, vx->u4.rhw);
788             } break;
789
790             default:
791                 FIXME("Unhandled vertex type\n");
792                 break;
793         }
794     }
795
796     glEnd();
797     TRACE("End\n");
798 }
799
800 HRESULT WINAPI
801 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
802                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
803                                        D3DVERTEXTYPE d3dvtVertexType,
804                                        LPVOID lpvVertices,
805                                        DWORD dwVertexCount,
806                                        DWORD dwFlags)
807 {
808     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
809     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
810
811     ENTER_GL();
812     draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
813     LEAVE_GL();
814                    
815     return DD_OK;
816 }
817
818 HRESULT WINAPI
819 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
820                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
821                                               D3DVERTEXTYPE d3dvtVertexType,
822                                               LPVOID lpvVertices,
823                                               DWORD dwVertexCount,
824                                               LPWORD dwIndices,
825                                               DWORD dwIndexCount,
826                                               DWORD dwFlags)
827 {
828     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
829     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
830
831     ENTER_GL();
832     draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
833     LEAVE_GL();
834     
835     return DD_OK;
836 }
837
838 HRESULT WINAPI
839 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
840                                              LPD3DEXECUTEBUFFERDESC lpDesc,
841                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
842                                              IUnknown* pUnkOuter)
843 {
844     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
845     IDirect3DExecuteBufferImpl *ret;
846     HRESULT ret_value;
847     
848     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
849
850     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
851     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
852
853     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
854     
855     return ret_value;
856 }
857
858 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements)
859 {
860     DWORD size = 0;
861     DWORD elts = 0;
862     
863     if (d3dvtVertexType & D3DFVF_NORMAL) { size += 3 * sizeof(D3DVALUE); elts += 1; }
864     if (d3dvtVertexType & D3DFVF_DIFFUSE) { size += sizeof(DWORD); elts += 1; }
865     if (d3dvtVertexType & D3DFVF_SPECULAR) { size += sizeof(DWORD); elts += 1; }
866     switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
867         case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); elts += 1; break;
868         case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); elts += 1; break;
869         default: TRACE(" matrix weighting not handled yet...\n");
870     }
871     size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
872     elts += (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
873
874     if (elements) *elements = elts;
875
876     return size;
877 }
878
879 void dump_flexible_vertex(DWORD d3dvtVertexType)
880 {
881     static const flag_info flags[] = {
882         FE(D3DFVF_NORMAL),
883         FE(D3DFVF_RESERVED1),
884         FE(D3DFVF_DIFFUSE),
885         FE(D3DFVF_SPECULAR)
886     };
887     if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
888     switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
889 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
890         GEN_CASE(D3DFVF_XYZ);
891         GEN_CASE(D3DFVF_XYZRHW);
892         GEN_CASE(D3DFVF_XYZB1);
893         GEN_CASE(D3DFVF_XYZB2);
894         GEN_CASE(D3DFVF_XYZB3);
895         GEN_CASE(D3DFVF_XYZB4);
896         GEN_CASE(D3DFVF_XYZB5);
897     }
898     DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
899     switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
900         GEN_CASE(D3DFVF_TEX0);
901         GEN_CASE(D3DFVF_TEX1);
902         GEN_CASE(D3DFVF_TEX2);
903         GEN_CASE(D3DFVF_TEX3);
904         GEN_CASE(D3DFVF_TEX4);
905         GEN_CASE(D3DFVF_TEX5);
906         GEN_CASE(D3DFVF_TEX6);
907         GEN_CASE(D3DFVF_TEX7);
908         GEN_CASE(D3DFVF_TEX8);
909     }
910 #undef GEN_CASE
911     DPRINTF("\n");
912 }
913
914 /* Some types used by the fast paths... */
915 typedef struct {
916     float x, y, z;
917     float nx, ny, nz;
918     float tu1, tv1;
919 } D3DFVF_VERTEX_1;
920
921 typedef struct {
922     float x, y, z, rhw;
923     DWORD diffuse;
924     DWORD specular;
925     float tu1, tv1;
926 } D3DFVF_TLVERTEX_1;
927
928 /* These are the various handler used in the generic path */
929 static void handle_xyz(char *vertex, int offset, int extra) {
930     glVertex3fv((float *) (vertex + offset));
931 }
932 static void handle_xyzrhw(char *vertex, int offset, int extra) {
933     float *coords = (float *) (vertex + offset);
934     if (coords[3] < 0.00001)
935         glVertex3f(coords[0], coords[1], coords[2]);
936     else
937         glVertex4f(coords[0] / coords[3],
938                    coords[1] / coords[3],
939                    coords[2] / coords[3],
940                    1.0 / coords[3]);
941 }
942 static void handle_normal(char *vertex, int offset, int extra) {
943     glNormal3fv((float *) (vertex + offset));
944 }
945 static void handle_specular(char *vertex, int offset, int extra) {
946     /* Specular not handled yet properly... */
947 }
948 static void handle_diffuse(char *vertex, int offset, int extra) {
949     DWORD color = *((DWORD *) (vertex + offset));
950     glColor4ub((color >> 16) & 0xFF,
951                (color >>  8) & 0xFF,
952                (color >>  0) & 0xFF,
953                (color >> 24) & 0xFF);
954 }
955 static void handle_texture(char *vertex, int offset, int extra) {
956     if (extra == 0xFF) {
957         /* Special case for single texture... */
958         glTexCoord2fv((float *) (vertex + offset));
959     } else {
960         /* Multitexturing not handled yet */
961     }
962 }
963
964 static void draw_primitive_7(IDirect3DDeviceImpl *This,
965                              D3DPRIMITIVETYPE d3dptPrimitiveType,
966                              DWORD d3dvtVertexType,
967                              LPVOID lpvVertices,
968                              DWORD dwVertexCount,
969                              LPWORD dwIndices,
970                              DWORD dwIndexCount,
971                              DWORD dwFlags)
972 {
973     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
974     if (TRACE_ON(ddraw)) {
975         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
976     }
977
978     ENTER_GL();
979     draw_primitive_handle_GL_state(glThis,
980                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
981                                    (d3dvtVertexType & D3DFVF_NORMAL) == 0);
982     draw_primitive_start_GL(d3dptPrimitiveType);
983
984     /* Some fast paths first before the generic case.... */
985     if (d3dvtVertexType == D3DFVF_VERTEX) {
986         D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
987         int index;
988         
989         for (index = 0; index < dwIndexCount; index++) {
990             int i = (dwIndices == NULL) ? index : dwIndices[index];
991           
992             glNormal3fv(&(vertices[i].nx));
993             glTexCoord2fv(&(vertices[i].tu1));
994             glVertex3fv(&(vertices[i].x));
995             TRACE(" %f %f %f / %f %f %f (%f %f)\n",
996                   vertices[i].x, vertices[i].y, vertices[i].z,
997                   vertices[i].nx, vertices[i].ny, vertices[i].nz,
998                   vertices[i].tu1, vertices[i].tv1);
999         }
1000     } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1001         D3DFVF_TLVERTEX_1 *vertices = (D3DFVF_TLVERTEX_1 *) lpvVertices;
1002         int index;
1003         
1004         for (index = 0; index < dwIndexCount; index++) {
1005             int i = (dwIndices == NULL) ? index : dwIndices[index];
1006             
1007             glColor4ub((vertices[i].diffuse >> 16) & 0xFF,
1008                        (vertices[i].diffuse >>  8) & 0xFF,
1009                        (vertices[i].diffuse >>  0) & 0xFF,
1010                        (vertices[i].diffuse >> 24) & 0xFF);
1011             /* Todo : handle specular... */
1012             glTexCoord2fv(&(vertices[i].tu1));
1013             if (vertices[i].rhw < 0.00001)
1014                 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
1015             else
1016                 glVertex4f(vertices[i].x / vertices[i].rhw,
1017                            vertices[i].y / vertices[i].rhw,
1018                            vertices[i].z / vertices[i].rhw,
1019                            1.0 / vertices[i].rhw);
1020             TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1021                   vertices[i].x, vertices[i].y, vertices[i].z, vertices[i].rhw,
1022                   (vertices[i].diffuse >> 16) & 0xFF,
1023                   (vertices[i].diffuse >>  8) & 0xFF,
1024                   (vertices[i].diffuse >>  0) & 0xFF,
1025                   (vertices[i].diffuse >> 24) & 0xFF,
1026                   (vertices[i].specular >> 16) & 0xFF,
1027                   (vertices[i].specular >>  8) & 0xFF,
1028                   (vertices[i].specular >>  0) & 0xFF,
1029                   (vertices[i].specular >> 24) & 0xFF,
1030                   vertices[i].tu1, vertices[i].tv1);
1031         } 
1032     } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1033                ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1034         /* This is the 'slow path' but that should support all possible vertex formats out there...
1035            Note that people should write a fast path for all vertex formats out there...
1036         */
1037         DWORD elements;
1038         DWORD size;
1039         char *vertices = (char *) lpvVertices;
1040         int index;
1041         int current_offset = 0;
1042         int current_position = 0;
1043         D3DFVF_GENERIC *handler;
1044
1045         if ((glThis->last_vertex_format != d3dvtVertexType) ||
1046             (glThis->handler == NULL)) {
1047             if (glThis->handler == NULL) HeapFree(GetProcessHeap(), 0, glThis->handler);
1048             size = get_flexible_vertex_size(d3dvtVertexType, &elements);
1049             
1050             glThis->handler = handler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, elements * sizeof(D3DFVF_GENERIC));
1051             glThis->last_vertex_format = d3dvtVertexType;
1052             glThis->last_vertex_format_size = size;
1053             glThis->last_vertex_format_elements = elements;
1054             
1055             if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1056                 handler[elements - 1].handler = handle_xyz;
1057                 handler[elements - 1].offset = current_offset;
1058                 current_offset += 3 * sizeof(D3DVALUE);
1059             } else {
1060                 handler[elements - 1].handler = handle_xyzrhw;
1061                 handler[elements - 1].offset = current_offset;
1062                 current_offset += 4 * sizeof(D3DVALUE);
1063             }
1064             if (d3dvtVertexType & D3DFVF_NORMAL) { 
1065                 handler[current_position].handler = handle_normal;
1066                 handler[current_position].offset = current_offset;
1067                 current_position += 1;
1068                 current_offset += 3 * sizeof(D3DVALUE);
1069             }
1070             if (d3dvtVertexType & D3DFVF_DIFFUSE) { 
1071                 handler[current_position].handler = handle_diffuse;
1072                 handler[current_position].offset = current_offset;
1073                 current_position += 1;
1074                 current_offset += sizeof(DWORD);
1075             }
1076             if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1077                 handler[current_position].handler = handle_specular;
1078                 handler[current_position].offset = current_offset;
1079                 current_position += 1;
1080                 current_offset += sizeof(DWORD);
1081             }
1082             if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1083                 handler[current_position].handler = handle_texture;
1084                 handler[current_position].offset = current_offset;
1085                 handler[current_position].extra = 0xFF;
1086                 current_position += 1;
1087                 current_offset += 2 * sizeof(D3DVALUE);
1088             } else {
1089                 int tex_index;
1090                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1091                     handler[current_position].handler = handle_texture;
1092                     handler[current_position].offset = current_offset;
1093                     handler[current_position].extra = tex_index;
1094                     current_position += 1;
1095                     current_offset += 2 * sizeof(D3DVALUE);
1096                 }
1097             }
1098         } else {
1099             handler = glThis->handler;
1100             size = glThis->last_vertex_format_size;
1101             elements = glThis->last_vertex_format_elements;
1102         }
1103         
1104         WARN(" using draw_primitive generic path - for better performance, add a fast path for your vertex case !\n");
1105         
1106         for (index = 0; index < dwIndexCount; index++) {
1107             int i = (dwIndices == NULL) ? index : dwIndices[index];
1108             int elt;
1109             char *vertex = vertices + (i * size);
1110
1111             for (elt = 0; elt < elements; elt++) {
1112                 handler[elt].handler(vertex, handler[elt].offset, handler[elt].extra);
1113             }
1114         }
1115     } else {
1116         ERR(" matrix weighting not handled yet....\n");
1117     }
1118     
1119     glEnd();
1120     LEAVE_GL();
1121     TRACE("End\n");    
1122 }
1123
1124 #define CPNT(cpnt,i,n,type) ((type*)(lpD3DDrawPrimStrideData->cpnt.lpvData+i*lpD3DDrawPrimStrideData->cpnt.dwStride))[n]
1125
1126 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
1127                              D3DPRIMITIVETYPE d3dptPrimitiveType,
1128                              DWORD d3dvtVertexType,
1129                              LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1130                              DWORD dwVertexCount,
1131                              LPWORD dwIndices,
1132                              DWORD dwIndexCount,
1133                              DWORD dwFlags)
1134 {
1135     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1136     if (TRACE_ON(ddraw)) {
1137         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1138     }
1139
1140     ENTER_GL();
1141     draw_primitive_handle_GL_state(glThis,
1142                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1143                                    (d3dvtVertexType & D3DFVF_NORMAL) == 0);
1144     draw_primitive_start_GL(d3dptPrimitiveType);
1145
1146     /* Some fast paths first before the generic case.... */
1147     if (d3dvtVertexType == D3DFVF_VERTEX) {
1148         int index;
1149         
1150         for (index = 0; index < dwIndexCount; index++) {
1151             int i = (dwIndices == NULL) ? index : dwIndices[index];
1152           
1153             glNormal3f(CPNT(normal,i,0,D3DVALUE),CPNT(normal,i,1,D3DVALUE),CPNT(normal,i,2,D3DVALUE));
1154             glTexCoord2f(CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1155             glVertex3f(CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE));
1156             TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1157                   CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE),
1158                   CPNT(normal,i,0,D3DVALUE),CPNT(normal,i,1,D3DVALUE),CPNT(normal,i,2,D3DVALUE),
1159                   CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1160             
1161         }
1162     } else if (d3dvtVertexType == D3DFVF_LVERTEX) {
1163         int index;
1164         
1165         for (index = 0; index < dwIndexCount; index++) {
1166             int i = (dwIndices == NULL) ? index : dwIndices[index];
1167             
1168             glColor4ub((CPNT(diffuse,i,0,DWORD) >> 16) & 0xFF,
1169                        (CPNT(diffuse,i,0,DWORD) >>  8) & 0xFF,
1170                        (CPNT(diffuse,i,0,DWORD) >>  0) & 0xFF,
1171                        (CPNT(diffuse,i,0,DWORD) >> 24) & 0xFF);
1172             /* Todo : handle specular... */
1173             glTexCoord2f(CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1174             glVertex3f(CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE));
1175             TRACE(" %f %f %f  / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1176                   CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE),
1177                   (CPNT(diffuse,i,0,DWORD) >> 16) & 0xFF,
1178                   (CPNT(diffuse,i,0,DWORD) >>  8) & 0xFF,
1179                   (CPNT(diffuse,i,0,DWORD) >>  0) & 0xFF,
1180                   (CPNT(diffuse,i,0,DWORD) >> 24) & 0xFF,
1181                   (CPNT(specular,i,0,DWORD) >> 16) & 0xFF,
1182                   (CPNT(specular,i,0,DWORD) >>  8) & 0xFF,
1183                   (CPNT(specular,i,0,DWORD) >>  0) & 0xFF,
1184                   (CPNT(specular,i,0,DWORD) >> 24) & 0xFF,
1185                   CPNT(textureCoords[0],i,0,D3DVALUE),CPNT(textureCoords[0],i,1,D3DVALUE));
1186         } 
1187     }
1188     
1189     glEnd();
1190     LEAVE_GL();
1191     TRACE("End\n");    
1192 }
1193
1194 #undef CPNT
1195
1196 HRESULT WINAPI
1197 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1198                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1199                                           DWORD d3dvtVertexType,
1200                                           LPVOID lpvVertices,
1201                                           DWORD dwVertexCount,
1202                                           DWORD dwFlags)
1203 {
1204     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1205     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1206
1207     draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1208     
1209     return DD_OK;
1210 }
1211
1212 HRESULT WINAPI
1213 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1214                                                  D3DPRIMITIVETYPE d3dptPrimitiveType,
1215                                                  DWORD d3dvtVertexType,
1216                                                  LPVOID lpvVertices,
1217                                                  DWORD dwVertexCount,
1218                                                  LPWORD dwIndices,
1219                                                  DWORD dwIndexCount,
1220                                                  DWORD dwFlags)
1221 {
1222     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1223     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1224
1225     draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1226     
1227     return DD_OK;
1228 }
1229
1230 HRESULT WINAPI
1231 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1232                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1233                                                    DWORD dwVertexType,
1234                                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1235                                                    DWORD dwVertexCount,
1236                                                    DWORD dwFlags)
1237 {
1238     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1239     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1240     draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1241     return DD_OK;
1242 }
1243
1244 HRESULT WINAPI
1245 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1246                                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1247                                                           DWORD dwVertexType,
1248                                                           LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1249                                                           DWORD dwVertexCount,
1250                                                           LPWORD lpIndex,
1251                                                           DWORD dwIndexCount,
1252                                                           DWORD dwFlags)
1253 {
1254     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1255     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1256     draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1257     return DD_OK;
1258 }
1259
1260 HRESULT WINAPI
1261 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1262                                                  DWORD dwStage,
1263                                                  D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1264                                                  DWORD dwState)
1265 {
1266     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1267     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1268     GLenum gl_state;
1269     
1270     TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1271
1272     if (TRACE_ON(ddraw)) {
1273         TRACE(" Stage type is : ");
1274         switch (d3dTexStageStateType) {
1275 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1276             GEN_CASE(D3DTSS_COLOROP);
1277             GEN_CASE(D3DTSS_COLORARG1);
1278             GEN_CASE(D3DTSS_COLORARG2);
1279             GEN_CASE(D3DTSS_ALPHAOP);
1280             GEN_CASE(D3DTSS_ALPHAARG1);
1281             GEN_CASE(D3DTSS_ALPHAARG2);
1282             GEN_CASE(D3DTSS_BUMPENVMAT00);
1283             GEN_CASE(D3DTSS_BUMPENVMAT01);
1284             GEN_CASE(D3DTSS_BUMPENVMAT10);
1285             GEN_CASE(D3DTSS_BUMPENVMAT11);
1286             GEN_CASE(D3DTSS_TEXCOORDINDEX);
1287             GEN_CASE(D3DTSS_ADDRESS);
1288             GEN_CASE(D3DTSS_ADDRESSU);
1289             GEN_CASE(D3DTSS_ADDRESSV);
1290             GEN_CASE(D3DTSS_BORDERCOLOR);
1291             GEN_CASE(D3DTSS_MAGFILTER);
1292             GEN_CASE(D3DTSS_MINFILTER);
1293             GEN_CASE(D3DTSS_MIPFILTER);
1294             GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1295             GEN_CASE(D3DTSS_MAXMIPLEVEL);
1296             GEN_CASE(D3DTSS_MAXANISOTROPY);
1297             GEN_CASE(D3DTSS_BUMPENVLSCALE);
1298             GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1299             GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1300 #undef GEN_CASE
1301             default: DPRINTF("UNKNOWN !!!");
1302         }
1303         DPRINTF(" => ");
1304     }
1305
1306     switch (d3dTexStageStateType) {
1307         case D3DTSS_MINFILTER:
1308             switch ((D3DTEXTUREMINFILTER) dwState) {
1309                 case D3DTFN_POINT:
1310                     if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1311                     gl_state = GL_NEAREST;
1312                     break;
1313                 case D3DTFN_LINEAR:
1314                     if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1315                     gl_state = GL_LINEAR;
1316                     break;
1317                 default:
1318                     if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1319                     gl_state = GL_LINEAR;
1320                     break;
1321             }
1322             glThis->render_state.min = gl_state;
1323             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1324             break;
1325             
1326         case D3DTSS_MAGFILTER:
1327             switch ((D3DTEXTUREMAGFILTER) dwState) {
1328                 case D3DTFG_POINT:
1329                     if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1330                     gl_state = GL_NEAREST;
1331                     break;
1332                 case D3DTFG_LINEAR:
1333                     if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1334                     gl_state = GL_LINEAR;
1335                     break;
1336                 default:
1337                     if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1338                     gl_state = GL_LINEAR;
1339                     break;
1340             }
1341             glThis->render_state.mag = gl_state;
1342             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1343             break;
1344             
1345         default:
1346             if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1347     }
1348     
1349     return DD_OK;
1350 }
1351
1352 HRESULT WINAPI
1353 GL_IDirect3DDeviceImpl_3_SetTexture(LPDIRECT3DDEVICE3 iface,
1354                                     DWORD dwStage,
1355                                     LPDIRECT3DTEXTURE2 lpTexture2)
1356 {
1357     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1358     
1359     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1360     
1361     if (This->current_texture[dwStage] != NULL) {
1362         /* Seems that this is not right... Need to test in real Windows
1363            IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1364     }
1365     
1366     ENTER_GL();
1367     if (lpTexture2 == NULL) {
1368         TRACE(" disabling 2D texturing.\n");
1369         glBindTexture(GL_TEXTURE_2D, 0);
1370         glDisable(GL_TEXTURE_2D);
1371     } else {
1372         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpTexture2);
1373         IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
1374         
1375         This->current_texture[dwStage] = tex_impl;
1376         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
1377
1378         TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1379         
1380         glEnable(GL_TEXTURE_2D);
1381         glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1382     }
1383     LEAVE_GL();
1384     
1385     return DD_OK;
1386 }
1387
1388 HRESULT WINAPI
1389 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1390                                  LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1391 {
1392     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1393     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1394
1395     fill_opengl_caps_7(lpD3DHELDevDesc);
1396
1397     TRACE(" returning caps : no dump function yet.\n");
1398
1399     return DD_OK;
1400 }
1401
1402 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1403 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
1404 #else
1405 # define XCAST(fun)     (void*)
1406 #endif
1407
1408 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1409 {
1410     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1411     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1412     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1413     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1414     XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1415     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1416     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1417     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1418     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1419     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1420     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1421     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1422     XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1423     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1424     XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1425     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1426     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1427     XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1428     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1429     XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1430     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1431     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1432     XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1433     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1434     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1435     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1436     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1437     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1438     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1439     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1440     XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1441     XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1442     XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1443     XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1444     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1445     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1446     XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
1447     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1448     XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1449     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1450     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1451     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1452     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1453     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1454     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1455     XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1456     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1457     XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1458     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1459     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1460 };
1461
1462 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1463 #undef XCAST
1464 #endif
1465
1466
1467 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1468 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
1469 #else
1470 # define XCAST(fun)     (void*)
1471 #endif
1472
1473 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1474 {
1475     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1476     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1477     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1478     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1479     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1480     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1481     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1482     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1483     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1484     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1485     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1486     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1487     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1488     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1489     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1490     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1491     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1492     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1493     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1494     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1495     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1496     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1497     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1498     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1499     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1500     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1501     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1502     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1503     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1504     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1505     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1506     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1507     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1508     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1509     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1510     XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1511     XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1512     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1513     XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
1514     XCAST(SetTexture) GL_IDirect3DDeviceImpl_3_SetTexture,
1515     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1516     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1517     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1518 };
1519
1520 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1521 #undef XCAST
1522 #endif
1523
1524
1525 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1526 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
1527 #else
1528 # define XCAST(fun)     (void*)
1529 #endif
1530
1531 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1532 {
1533     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1534     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1535     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1536     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1537     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1538     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1539     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1540     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1541     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1542     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1543     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1544     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1545     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1546     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1547     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1548     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1549     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1550     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1551     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1552     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1553     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1554     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1555     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1556     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1557     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1558     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1559     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1560     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1561     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1562     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1563     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1564     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1565     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1566     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1567 };
1568
1569 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1570 #undef XCAST
1571 #endif
1572
1573
1574 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1575 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
1576 #else
1577 # define XCAST(fun)     (void*)
1578 #endif
1579
1580 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1581 {
1582     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1583     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1584     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1585     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1586     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1587     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1588     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1589     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1590     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1591     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1592     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1593     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1594     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1595     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1596     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1597     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1598     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1599     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1600     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1601     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1602     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1603     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1604     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1605 };
1606
1607 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1608 #undef XCAST
1609 #endif
1610
1611 /* TODO for both these functions :
1612     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1613       by other OpenGL code in D3D
1614     - handle the case where no 'Begin / EndScene' was done between two locks
1615     - handle the rectangles in the unlock too
1616     - handle pitch correctly...
1617 */
1618 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1619 {
1620     /* First, check if we need to do anything */
1621     if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1622         GLenum buffer_type;
1623         GLenum prev_read;
1624         RECT loc_rect;
1625
1626         ENTER_GL();
1627
1628         glGetIntegerv(GL_READ_BUFFER, &prev_read);
1629         glFlush();
1630         
1631         WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1632         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1633             /* Application wants to lock the front buffer */
1634             glReadBuffer(GL_FRONT);
1635         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1636             /* Application wants to lock the back buffer */
1637             glReadBuffer(GL_BACK);
1638         } else {
1639             WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1640         }
1641
1642         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1643             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1644         } else {
1645             WARN(" unsupported pixel format.\n");
1646             LEAVE_GL();
1647             return;
1648         }
1649         if (pRect == NULL) {
1650             loc_rect.top = 0;
1651             loc_rect.left = 0;
1652             loc_rect.bottom = This->surface_desc.dwHeight;
1653             loc_rect.right = This->surface_desc.dwWidth;
1654         } else {
1655             loc_rect = *pRect;
1656         }
1657         glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1658                      GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1659                                            + loc_rect.top * This->surface_desc.u1.lPitch
1660                                            + loc_rect.left * GET_BPP(This->surface_desc)));
1661         glReadBuffer(prev_read);
1662         LEAVE_GL();
1663     }
1664 }
1665
1666 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1667 {
1668     /* First, check if we need to do anything */
1669     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1670         GLenum buffer_type;
1671         GLenum prev_draw;
1672
1673         ENTER_GL();
1674
1675         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1676
1677         WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1678         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1679             /* Application wants to lock the front buffer */
1680             glDrawBuffer(GL_FRONT);
1681         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1682             /* Application wants to lock the back buffer */
1683             glDrawBuffer(GL_BACK);
1684         } else {
1685             WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1686         }
1687
1688         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1689             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1690         } else {
1691             WARN(" unsupported pixel format.\n");
1692             LEAVE_GL();
1693             return;
1694         }
1695         glRasterPos2f(0.0, 0.0);
1696         glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight, 
1697                      GL_RGB, buffer_type, This->surface_desc.lpSurface);
1698         glDrawBuffer(prev_draw);
1699
1700         LEAVE_GL();
1701    }
1702 }
1703
1704 HRESULT
1705 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1706 {
1707     IDirect3DDeviceImpl *object;
1708     IDirect3DDeviceGLImpl *gl_object;
1709     IDirectDrawSurfaceImpl *surf;
1710     HDC device_context;
1711     XVisualInfo *vis;
1712     int num;
1713     XVisualInfo template;
1714     GLenum buffer;
1715     
1716     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1717     if (object == NULL) return DDERR_OUTOFMEMORY;
1718
1719     gl_object = (IDirect3DDeviceGLImpl *) object;
1720     
1721     object->ref = 1;
1722     object->d3d = d3d;
1723     object->surface = surface;
1724     object->set_context = set_context;
1725
1726     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1727
1728     device_context = GetDC(surface->ddraw_owner->window);
1729     gl_object->display = get_display(device_context);
1730     gl_object->drawable = get_drawable(device_context);
1731     ReleaseDC(surface->ddraw_owner->window,device_context);
1732
1733     ENTER_GL();
1734     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1735     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1736     if (vis == NULL) {
1737         HeapFree(GetProcessHeap(), 0, object);
1738         ERR("No visual found !\n");
1739         LEAVE_GL();
1740         return DDERR_INVALIDPARAMS;
1741     } else {
1742         TRACE(" visual found\n");
1743     }
1744
1745     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1746                                              NULL, GL_TRUE);
1747
1748     if (gl_object->gl_context == NULL) {
1749         HeapFree(GetProcessHeap(), 0, object);
1750         ERR("Error in context creation !\n");
1751         LEAVE_GL();
1752         return DDERR_INVALIDPARAMS;
1753     } else {
1754         TRACE(" context created (%p)\n", gl_object->gl_context);
1755     }
1756     
1757     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1758     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1759         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1760             surf->aux_ctx  = (LPVOID) gl_object->display;
1761             surf->aux_data = (LPVOID) gl_object->drawable;
1762             surf->aux_flip = opengl_flip;
1763             buffer =  GL_BACK;
1764             break;
1765         }
1766     }
1767     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1768     if (surf == NULL) {
1769         TRACE(" no double buffering : drawing on the front buffer\n");
1770         buffer = GL_FRONT;
1771     }
1772     
1773     for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1774     for (; surf != NULL; surf = surf->next_attached) {
1775         if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1776             ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1777             /* Override the Lock / Unlock function for all these surfaces */
1778             surf->lock_update = d3ddevice_lock_update;
1779             surf->unlock_update = d3ddevice_unlock_update;
1780         }
1781         surf->d3ddevice = object;
1782     }
1783     
1784     gl_object->render_state.src = GL_ONE;
1785     gl_object->render_state.dst = GL_ZERO;
1786     gl_object->render_state.mag = GL_NEAREST;
1787     gl_object->render_state.min = GL_NEAREST;
1788     gl_object->render_state.alpha_ref = 0.0; /* No actual idea about the real default value... */
1789     gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */
1790     
1791     /* Allocate memory for the matrices */
1792     gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1793     gl_object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1794     gl_object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1795
1796     memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1797     memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1798     memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1799
1800     /* Initialisation */
1801     TRACE(" setting current context\n");
1802     LEAVE_GL();
1803     object->set_context(object);
1804     ENTER_GL();
1805     TRACE(" current context set\n");
1806     glClearColor(0.0, 0.0, 0.0, 0.0);
1807     glColor3f(1.0, 1.0, 1.0);
1808     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1809     glDrawBuffer(buffer);
1810     glReadBuffer(buffer);
1811     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1812     LEAVE_GL();
1813
1814     /* fill_device_capabilities(d3d->ddraw); */    
1815     
1816     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
1817     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1818     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1819     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1820
1821     *obj = object;
1822
1823     TRACE(" creating implementation at %p.\n", *obj);
1824     
1825     return DD_OK;
1826 }