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