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