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