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