Added fogging for transformed vertices.
[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 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winerror.h"
30 #include "objbase.h"
31 #include "ddraw.h"
32 #include "d3d.h"
33 #include "wine/debug.h"
34
35 #include "mesa_private.h"
36 #include "main.h"
37
38 #include "x11drv.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
41
42 /* They are non-static as they are used by Direct3D in the creation function */
43 const GUID IID_D3DDEVICE_OpenGL = {
44   0x31416d44,
45   0x86ae,
46   0x11d2,
47   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
48 };
49
50 #ifndef HAVE_GLEXT_PROTOTYPES
51 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
52 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
53                                          GLsizei width, GLenum format, GLenum type,
54                                          const GLvoid *table);
55 #endif
56
57 const float id_mat[16] = {
58     1.0, 0.0, 0.0, 0.0,
59     0.0, 1.0, 0.0, 0.0,
60     0.0, 0.0, 1.0, 0.0,
61     0.0, 0.0, 0.0, 1.0
62 };
63
64 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
65                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
66                                    DWORD d3dvtVertexType,
67                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
68                                    DWORD dwStartVertex,
69                                    DWORD dwVertexCount,
70                                    LPWORD dwIndices,
71                                    DWORD dwIndexCount,
72                                    DWORD dwFlags) ;
73
74 /* retrieve the X display to use on a given DC */
75 inline static Display *get_display( HDC hdc )
76 {
77     Display *display;
78     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
79
80     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
81                     sizeof(display), (LPSTR)&display )) display = NULL;
82
83     return display;
84 }
85
86
87 /* retrieve the X drawable to use on a given DC */
88 inline static Drawable get_drawable( HDC hdc )
89 {
90     Drawable drawable;
91     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
92
93     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
95
96     return drawable;
97 }
98
99
100 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
101 {
102     TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
103     ENTER_GL();
104     glXSwapBuffers((Display*)display,(Drawable)drawable);
105     LEAVE_GL();
106     return TRUE;
107 }
108
109
110 /*******************************************************************************
111  *                              OpenGL static functions
112  */
113 static void set_context(IDirect3DDeviceImpl* This)
114 {
115     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
116    
117     ENTER_GL();
118     TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
119     if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
120         ERR("Error in setting current context (context %p drawable %ld)!\n",
121             glThis->gl_context, glThis->drawable);
122     }
123     LEAVE_GL();
124 }
125
126 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
127 {
128     pc->dwSize = sizeof(*pc);
129     pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
130       D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
131     pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
132       D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
133     pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
134       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
135     pc->dwSrcBlendCaps  = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
136       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
137         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
138     pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
139       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
140         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
141     pc->dwAlphaCmpCaps  = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
142       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
143     pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
144       D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
145     pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
146       D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
147     pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
148       D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
149     pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
150       D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
151     pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
152     pc->dwStippleWidth = 32;
153     pc->dwStippleHeight = 32;
154 }
155
156 static void fill_opengl_caps(D3DDEVICEDESC *d1)
157 {
158     /* GLint maxlight; */
159
160     d1->dwSize  = sizeof(*d1);
161     d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
162       | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
163     d1->dcmColorModel = D3DCOLOR_RGB;
164     d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
165       D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
166       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
167       /* D3D 7 capabilities */
168       D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
169     d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
170     d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
171     d1->bClipping = TRUE;
172     d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
173     d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
174     d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
175     d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
176     fill_opengl_primcaps(&(d1->dpcLineCaps));
177     fill_opengl_primcaps(&(d1->dpcTriCaps));
178     d1->dwDeviceRenderBitDepth  = DDBD_16|DDBD_24|DDBD_32;
179     d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
180     d1->dwMaxBufferSize = 0;
181     d1->dwMaxVertexCount = 65536;
182     d1->dwMinTextureWidth  = 1;
183     d1->dwMinTextureHeight = 1;
184     d1->dwMaxTextureWidth  = 1024;
185     d1->dwMaxTextureHeight = 1024;
186     d1->dwMinStippleWidth  = 1;
187     d1->dwMinStippleHeight = 1;
188     d1->dwMaxStippleWidth  = 32;
189     d1->dwMaxStippleHeight = 32;
190     d1->dwMaxTextureRepeat = 16;
191     d1->dwMaxTextureAspectRatio = 1024;
192     d1->dwMaxAnisotropy = 0;
193     d1->dvGuardBandLeft = 0.0;
194     d1->dvGuardBandRight = 0.0;
195     d1->dvGuardBandTop = 0.0;
196     d1->dvGuardBandBottom = 0.0;
197     d1->dvExtentsAdjust = 0.0;
198     d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
199       D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
200     d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
201     d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
202     d1->wMaxTextureBlendStages = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
203     d1->wMaxSimultaneousTextures = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
204 }
205
206 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
207 {
208     D3DDEVICEDESC d1;
209
210     /* Copy first D3D1/2/3 capabilities */
211     fill_opengl_caps(&d1);
212
213     /* And fill the D3D7 one with it */
214     d->dwDevCaps = d1.dwDevCaps;
215     d->dpcLineCaps = d1.dpcLineCaps;
216     d->dpcTriCaps = d1.dpcTriCaps;
217     d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
218     d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
219     d->dwMinTextureWidth = d1.dwMinTextureWidth;
220     d->dwMinTextureHeight = d1.dwMinTextureHeight;
221     d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
222     d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
223     d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
224     d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
225     d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
226     d->dvGuardBandLeft = d1.dvGuardBandLeft;
227     d->dvGuardBandTop = d1.dvGuardBandTop;
228     d->dvGuardBandRight = d1.dvGuardBandRight;
229     d->dvGuardBandBottom = d1.dvGuardBandBottom;
230     d->dvExtentsAdjust = d1.dvExtentsAdjust;
231     d->dwStencilCaps = d1.dwStencilCaps;
232     d->dwFVFCaps = d1.dwFVFCaps;
233     d->dwTextureOpCaps = d1.dwTextureOpCaps;
234     d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
235     d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
236     d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
237     d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
238     d->deviceGUID = IID_IDirect3DTnLHalDevice;
239     d->wMaxUserClipPlanes = 1;
240     d->wMaxVertexBlendMatrices = 0;
241     d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
242       D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
243     d->dwReserved1 = 0;
244     d->dwReserved2 = 0;
245     d->dwReserved3 = 0;
246     d->dwReserved4 = 0;
247 }
248
249 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
250 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
251 {
252     x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
253     const char *ext_string;
254     Mesa_DeviceCapabilities *devcap;
255
256     private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
257     devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
258
259     ENTER_GL();
260     ext_string = glGetString(GL_EXTENSIONS);
261     /* Query for the ColorTable Extension */
262     if (strstr(ext_string, "GL_EXT_paletted_texture")) {
263         devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
264         TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
265     } else {
266         TRACE("Color table extension not found.\n");
267     }
268     LEAVE_GL();
269 }
270 #endif
271
272
273
274 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
275 {
276     D3DDEVICEDESC dref, d1, d2;
277     HRESULT ret_value;
278     
279     fill_opengl_caps(&dref);
280
281     TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
282     d1 = dref;
283     d2 = dref;
284     ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
285     if (ret_value != D3DENUMRET_OK)
286         return ret_value;
287
288     TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
289     d1 = dref;
290     d2 = dref;
291     ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
292     if (ret_value != D3DENUMRET_OK)
293         return ret_value;
294
295     return D3DENUMRET_OK;
296 }
297
298 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
299 {
300     D3DDEVICEDESC7 ddesc;
301
302     fill_opengl_caps_7(&ddesc);
303     
304     TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
305     
306     return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
307 }
308
309 ULONG WINAPI
310 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
311 {
312     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
313     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
314     
315     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
316     if (!--(This->ref)) {
317         int i;
318         /* Release texture associated with the device */ 
319         for (i = 0; i < MAX_TEXTURES; i++) 
320             if (This->current_texture[i] != NULL)
321                 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
322
323         /* And warn the D3D object that this device is no longer active... */
324         This->d3d->removed_device(This->d3d, This);
325
326         HeapFree(GetProcessHeap(), 0, This->world_mat);
327         HeapFree(GetProcessHeap(), 0, This->view_mat);
328         HeapFree(GetProcessHeap(), 0, This->proj_mat);
329
330         ENTER_GL();
331         glXDestroyContext(glThis->display, glThis->gl_context);
332         LEAVE_GL();
333         HeapFree(GetProcessHeap(), 0, This->clipping_planes);
334
335         HeapFree(GetProcessHeap(), 0, This);
336         return 0;
337     }
338     return This->ref;
339 }
340
341 HRESULT WINAPI
342 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
343                                        LPD3DDEVICEDESC lpD3DHWDevDesc,
344                                        LPD3DDEVICEDESC lpD3DHELDevDesc)
345 {
346     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
347     D3DDEVICEDESC desc;
348     DWORD dwSize;
349
350     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
351
352     fill_opengl_caps(&desc);
353     dwSize = lpD3DHWDevDesc->dwSize;
354     memset(lpD3DHWDevDesc, 0, dwSize);
355     memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
356
357     dwSize = lpD3DHELDevDesc->dwSize;
358     memset(lpD3DHELDevDesc, 0, dwSize);
359     memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
360
361     TRACE(" returning caps : (no dump function yet)\n");
362
363     return DD_OK;
364 }
365
366 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
367                                           LPD3DENUMPIXELFORMATSCALLBACK cb_2,
368                                           LPVOID context)
369 {
370     DDSURFACEDESC sdesc;
371     LPDDPIXELFORMAT pformat;
372
373     /* Do the texture enumeration */
374     sdesc.dwSize = sizeof(DDSURFACEDESC);
375     sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
376     sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
377     pformat = &(sdesc.ddpfPixelFormat);
378     pformat->dwSize = sizeof(DDPIXELFORMAT);
379     pformat->dwFourCC = 0;
380
381     TRACE("Enumerating GL_RGBA unpacked (32)\n");
382     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
383     pformat->u1.dwRGBBitCount = 32;
384     pformat->u2.dwRBitMask =        0xFF000000;
385     pformat->u3.dwGBitMask =        0x00FF0000;
386     pformat->u4.dwBBitMask =        0x0000FF00;
387     pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
388     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
389     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
390
391     TRACE("Enumerating GL_RGB unpacked (24)\n");
392     pformat->dwFlags = DDPF_RGB;
393     pformat->u1.dwRGBBitCount = 24;
394     pformat->u2.dwRBitMask = 0x00FF0000;
395     pformat->u3.dwGBitMask = 0x0000FF00;
396     pformat->u4.dwBBitMask = 0x000000FF;
397     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
398     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
399     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
400
401     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
402     pformat->dwFlags = DDPF_RGB;
403     pformat->u1.dwRGBBitCount = 16;
404     pformat->u2.dwRBitMask = 0x0000F800;
405     pformat->u3.dwGBitMask = 0x000007E0;
406     pformat->u4.dwBBitMask = 0x0000001F;
407     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
408     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
409     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
410
411     /* Note : even if this is an 'emulated' texture format, it needs to be first
412               as some dumb applications seem to rely on that. */
413     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (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 #if 0
434     /* This is a compromise : some games choose the first 16 bit texture format with alpha they
435        find enumerated, others the last one. And both want to have the ARGB one.
436        
437        So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
438     */
439     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
440     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
441     pformat->u1.dwRGBBitCount = 16;
442     pformat->u2.dwRBitMask =        0x0000F000;
443     pformat->u3.dwGBitMask =        0x00000F00;
444     pformat->u4.dwBBitMask =        0x000000F0;
445     pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
446     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
447     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
448
449     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
450     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
451     pformat->u1.dwRGBBitCount = 16;
452     pformat->u2.dwRBitMask =        0x0000F800;
453     pformat->u3.dwGBitMask =        0x000007C0;
454     pformat->u4.dwBBitMask =        0x0000003E;
455     pformat->u5.dwRGBAlphaBitMask = 0x00000001;
456     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
457     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
458 #endif
459
460     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
461     pformat->dwFlags = DDPF_RGB;
462     pformat->u1.dwRGBBitCount = 8;
463     pformat->u2.dwRBitMask =        0x000000E0;
464     pformat->u3.dwGBitMask =        0x0000001C;
465     pformat->u4.dwBBitMask =        0x00000003;
466     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
467     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
468     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
469
470     TRACE("Enumerating Paletted (8)\n");
471     pformat->dwFlags = DDPF_PALETTEINDEXED8;
472     pformat->u1.dwRGBBitCount = 8;
473     pformat->u2.dwRBitMask =        0x00000000;
474     pformat->u3.dwGBitMask =        0x00000000;
475     pformat->u4.dwBBitMask =        0x00000000;
476     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
477     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
478     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
479
480     TRACE("End of enumeration\n");
481     return DD_OK;
482 }
483
484
485 HRESULT
486 d3ddevice_find(IDirect3DImpl *d3d,
487                LPD3DFINDDEVICESEARCH lpD3DDFS,
488                LPD3DFINDDEVICERESULT lplpD3DDevice)
489 {
490     D3DDEVICEDESC desc;
491   
492     if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
493         (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
494         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
495         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
496     }
497     if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
498         TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
499         if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
500             (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
501             (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
502             TRACE(" no match for this GUID.\n");
503             return DDERR_INVALIDPARAMS;
504         }
505     }
506
507     /* Now return our own GUID */
508     lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
509     fill_opengl_caps(&desc);
510     lplpD3DDevice->ddHwDesc = desc;
511     lplpD3DDevice->ddSwDesc = desc;
512
513     TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
514     
515     return D3D_OK;
516 }
517
518 HRESULT WINAPI
519 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
520                                                LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
521                                                LPVOID lpArg)
522 {
523     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
524     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
525     return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
526 }
527
528 HRESULT WINAPI
529 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
530                                                LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
531                                                LPVOID lpArg)
532 {
533     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
534     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
535     return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
536 }
537
538 HRESULT WINAPI
539 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
540                                               D3DRENDERSTATETYPE dwRenderStateType,
541                                               DWORD dwRenderState)
542 {
543     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
544     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
545
546     /* Call the render state functions */
547     store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
548     set_render_state(This, dwRenderStateType, &This->state_block);
549
550     return DD_OK;
551 }
552
553 HRESULT WINAPI
554 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
555                                               D3DRENDERSTATETYPE dwRenderStateType,
556                                               LPDWORD lpdwRenderState)
557 {
558     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
559     TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
560
561     /* Call the render state functions */
562     get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
563
564     TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
565
566     return DD_OK;
567 }
568
569 HRESULT WINAPI
570 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
571                                           D3DLIGHTSTATETYPE dwLightStateType,
572                                           DWORD dwLightState)
573 {
574     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
575     
576     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
577
578     if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
579         TRACE("Unexpected Light State Type\n");
580         return DDERR_INVALIDPARAMS;
581         
582     if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
583         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
584
585         if (mat != NULL) {
586             ENTER_GL();
587             mat->activate(mat);
588             LEAVE_GL();
589         } else {
590             ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
591         }
592     } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
593         switch (dwLightState) {
594             case D3DCOLOR_MONO:
595                ERR("DDCOLOR_MONO should not happend!\n");
596                break;
597             case D3DCOLOR_RGB:
598                /* We are already in this mode */
599                break;
600             default:
601                ERR("Unknown color model!\n");
602                break;
603         }
604     } else {
605         D3DRENDERSTATETYPE rs;
606         switch (dwLightStateType) {
607
608             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
609                 rs = D3DRENDERSTATE_AMBIENT;
610                 break;          
611             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
612                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
613                 break;
614             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
615                 rs = D3DRENDERSTATE_FOGSTART;
616                 break;
617             case D3DLIGHTSTATE_FOGEND:        /* 6 */
618                 rs = D3DRENDERSTATE_FOGEND;
619                 break;
620             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
621                 rs = D3DRENDERSTATE_FOGDENSITY;
622                 break;
623             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
624                 rs = D3DRENDERSTATE_COLORVERTEX;
625                 break;
626             default:
627                 break;
628         }
629
630         IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
631                                         rs,dwLightState);
632     }
633
634     return DD_OK;
635 }
636
637 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
638 {
639     switch (d3dpt) {
640         case D3DPT_POINTLIST:
641             TRACE("Start POINTS\n");
642             glBegin(GL_POINTS);
643             break;
644
645         case D3DPT_LINELIST:
646             TRACE("Start LINES\n");
647             glBegin(GL_LINES);
648             break;
649
650         case D3DPT_LINESTRIP:
651             TRACE("Start LINE_STRIP\n");
652             glBegin(GL_LINE_STRIP);
653             break;
654
655         case D3DPT_TRIANGLELIST:
656             TRACE("Start TRIANGLES\n");
657             glBegin(GL_TRIANGLES);
658             break;
659
660         case D3DPT_TRIANGLESTRIP:
661             TRACE("Start TRIANGLE_STRIP\n");
662             glBegin(GL_TRIANGLE_STRIP);
663             break;
664
665         case D3DPT_TRIANGLEFAN:
666             TRACE("Start TRIANGLE_FAN\n");
667             glBegin(GL_TRIANGLE_FAN);
668             break;
669
670         default:
671             TRACE("Unhandled primitive\n");
672             break;
673     }
674 }
675
676 /* This function calculate the Z coordinate from Zproj */ 
677 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
678 {
679     float a,b,c,d;
680     /* Assume that X = Y = 0 and W = 1 */
681     a = This->proj_mat->_33;
682     b = This->proj_mat->_34;
683     c = This->proj_mat->_43;
684     d = This->proj_mat->_44;
685     /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
686      * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
687      * And finally Z = (d * Zproj - c) / (a - b * Zproj)
688      */
689     return (d*Zproj - c) / (a - b*Zproj);
690 }
691
692 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
693     int i;
694     
695     TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
696     
697     for (i = 0; i < 3; i++) {
698         BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
699         DWORD elt;
700         for (elt = 0; elt < 0x10000; elt++) {
701             /* We apply the fog transformation and cache the result */
702             DWORD fog_intensity = elt & 0xFF;
703             DWORD vertex_color = (elt >> 8) & 0xFF;
704             fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
705         }
706     }
707 }
708
709 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
710                                            BOOLEAN vertex_transformed,
711                                            BOOLEAN vertex_lit) {
712     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
713   
714     /* Puts GL in the correct lighting / transformation mode */
715     if ((vertex_transformed == FALSE) && 
716         (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
717         /* Need to put the correct transformation again if we go from Transformed
718            vertices to non-transformed ones.
719         */
720         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
721                            This->world_mat, This->view_mat, This->proj_mat);
722         glThis->transform_state = GL_TRANSFORM_NORMAL;
723
724     } else if ((vertex_transformed == TRUE) &&
725                (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
726         /* Set our orthographic projection */
727         glThis->transform_state = GL_TRANSFORM_ORTHO;
728         d3ddevice_set_ortho(This);
729     }
730
731     /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
732              if no fogging state change occured */
733     if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
734         if (vertex_transformed == TRUE) {
735             glDisable(GL_FOG);
736             /* Now check if our fog_table still corresponds to the current vertex color.
737                Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
738             if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  0) & 0xFF)) ||
739                 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  8) & 0xFF)) ||
740                 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
741                 /* We need to rebuild our fog table.... */
742                 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
743             }
744         } else {
745             if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
746                 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
747                     case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break; 
748                     case D3DFOG_EXP:    glFogi(GL_FOG_MODE, GL_EXP); break; 
749                     case D3DFOG_EXP2:   glFogi(GL_FOG_MODE, GL_EXP2); break;
750                 }
751                 if (vertex_lit == FALSE) {
752                     glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
753                     glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
754                 } else {
755                     /* Special case of 'pixel fog' */
756                     glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
757                     glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
758                 }
759                 glEnable(GL_FOG);
760             } else {
761                 glDisable(GL_FOG);
762             }
763         }
764     } else {
765         glDisable(GL_FOG);
766     }
767     
768     /* Handle the 'no-normal' case */
769     if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
770         glEnable(GL_LIGHTING);
771     else 
772         glDisable(GL_LIGHTING);
773
774     /* Handle the code for pre-vertex material properties */
775     if (vertex_transformed == FALSE) {
776         if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
777             if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
778                 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
779                 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
780                 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
781                 glEnable(GL_COLOR_MATERIAL);
782             }
783         }
784     }
785 }
786
787
788 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
789                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
790 {
791     D3DDRAWPRIMITIVESTRIDEDDATA strided;
792
793     switch (d3dvt) {
794         case D3DVT_VERTEX: {
795             strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
796             strided.position.dwStride = sizeof(D3DVERTEX);
797             strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
798             strided.normal.dwStride = sizeof(D3DVERTEX);
799             strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
800             strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
801             draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
802         } break;
803
804         case D3DVT_LVERTEX: {
805             strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
806             strided.position.dwStride = sizeof(D3DLVERTEX);
807             strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
808             strided.diffuse.dwStride = sizeof(D3DLVERTEX);
809             strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
810             strided.specular.dwStride = sizeof(D3DLVERTEX);
811             strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
812             strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
813             draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
814         } break;
815
816         case D3DVT_TLVERTEX: {
817             strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
818             strided.position.dwStride = sizeof(D3DTLVERTEX);
819             strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
820             strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
821             strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
822             strided.specular.dwStride = sizeof(D3DTLVERTEX);
823             strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
824             strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
825             draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0, 0 /* Unused */, index, maxvert, 0 /* Unused */);
826         } break;
827
828         default:
829             FIXME("Unhandled vertex type\n");
830             break;
831     }
832 }
833
834 HRESULT WINAPI
835 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
836                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
837                                        D3DVERTEXTYPE d3dvtVertexType,
838                                        LPVOID lpvVertices,
839                                        DWORD dwVertexCount,
840                                        DWORD dwFlags)
841 {
842     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
843
844     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
845     if (TRACE_ON(ddraw)) {
846         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
847     }
848
849     draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
850                    
851     return DD_OK;
852 }
853
854 HRESULT WINAPI
855 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
856                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
857                                               D3DVERTEXTYPE d3dvtVertexType,
858                                               LPVOID lpvVertices,
859                                               DWORD dwVertexCount,
860                                               LPWORD dwIndices,
861                                               DWORD dwIndexCount,
862                                               DWORD dwFlags)
863 {
864     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
865     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
866     if (TRACE_ON(ddraw)) {
867         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
868     }
869
870     draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
871     
872     return DD_OK;
873 }
874
875 HRESULT WINAPI
876 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
877                                              LPD3DEXECUTEBUFFERDESC lpDesc,
878                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
879                                              IUnknown* pUnkOuter)
880 {
881     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
882     IDirect3DExecuteBufferImpl *ret;
883     HRESULT ret_value;
884     
885     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
886
887     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
888     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
889
890     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
891     
892     return ret_value;
893 }
894
895 /* These are the various handler used in the generic path */
896 inline static void handle_xyz(D3DVALUE *coords) {
897     glVertex3fv(coords);
898 }
899 inline static void handle_xyzrhw(D3DVALUE *coords) {
900     if (coords[3] < 1e-8)
901         glVertex3fv(coords);
902     else {
903         GLfloat w = 1.0 / coords[3];
904         
905         glVertex4f(coords[0] * w,
906                    coords[1] * w,
907                    coords[2] * w,
908                    w);
909     }
910 }
911 inline static void handle_normal(D3DVALUE *coords) {
912     glNormal3fv(coords);
913 }
914
915 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
916     if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
917         (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
918         glColor4ub((*color >> 16) & 0xFF,
919                    (*color >>  8) & 0xFF,
920                    (*color >>  0) & 0xFF,
921                    (*color >> 24) & 0xFF);
922     } else {
923         glColor3ub((*color >> 16) & 0xFF,
924                    (*color >>  8) & 0xFF,
925                    (*color >>  0) & 0xFF);    
926     }
927 }
928
929 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
930     glColor4ub((*color >> 16) & 0xFF,
931                (*color >>  8) & 0xFF,
932                (*color >>  0) & 0xFF,
933                (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
934 }
935
936 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
937     if ((lighted == FALSE) &&
938         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
939         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
940             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
941             handle_diffuse_base(sb, color);
942         }
943         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
944             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
945             handle_diffuse_base(sb, color);
946         }
947         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
948             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
949             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
950             handle_diffuse_base(sb, color);
951         }
952         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
953             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
954             handle_diffuse_base(sb, color);
955         }
956     } else {
957         handle_diffuse_base(sb, color);
958     }    
959 }
960
961 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
962     if ((lighted == FALSE) &&
963         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
964         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
965             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
966             handle_specular_base(sb, color);
967         }
968         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
969             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
970             handle_specular_base(sb, color);
971         }
972         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
973             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
974             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
975             handle_specular_base(sb, color);
976         }
977         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
978             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
979             handle_specular_base(sb, color);
980         }
981     }
982     /* No else here as we do not know how to handle 'specular' on its own in any case.. */
983 }
984
985 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
986     if (lighted == TRUE) {
987         DWORD color = *color_d;
988         if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
989             /* Special case where the specular value is used to do fogging */
990             BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
991             color &= 0xFF000000; /* Only keep the alpha component */
992             color |= fog_table[((*color_d >>  0) & 0xFF) << 8 | fog_intensity] <<  0;
993             color |= fog_table[((*color_d >>  8) & 0xFF) << 8 | fog_intensity] <<  8;
994             color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
995         }
996         if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
997             /* Standard specular value in transformed mode. TODO */
998         }
999         handle_diffuse_base(sb, &color);
1000     } else {
1001         if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1002             handle_diffuse(sb, color_d, FALSE);
1003             handle_specular(sb, color_s, FALSE);
1004         } else {
1005             /* In that case, only put the diffuse color... */
1006             handle_diffuse_base(sb, color_d);
1007         }
1008     }
1009 }
1010
1011 inline static void handle_texture(D3DVALUE *coords) {
1012     glTexCoord2fv(coords);
1013 }
1014 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1015     /* For the moment, draw only the first texture.. */
1016     if (tex_index == 0) glTexCoord2fv(coords);
1017 }
1018
1019 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1020                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1021                                    DWORD d3dvtVertexType,
1022                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1023                                    DWORD dwStartVertex,
1024                                    DWORD dwVertexCount,
1025                                    LPWORD dwIndices,
1026                                    DWORD dwIndexCount,
1027                                    DWORD dwFlags)
1028 {
1029     BOOLEAN vertex_lighted = (d3dvtVertexType & D3DFVF_NORMAL) == 0;
1030     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1031
1032     if (TRACE_ON(ddraw)) {
1033         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1034     }
1035
1036     ENTER_GL();
1037     draw_primitive_handle_GL_state(This,
1038                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1039                                    vertex_lighted);
1040     draw_primitive_start_GL(d3dptPrimitiveType);
1041
1042     /* Some fast paths first before the generic case.... */
1043     if (d3dvtVertexType == D3DFVF_VERTEX) {
1044         int index;
1045         
1046         for (index = 0; index < dwIndexCount; index++) {
1047             int i = (dwIndices == NULL) ? index : dwIndices[index];
1048             D3DVALUE *normal = 
1049               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1050             D3DVALUE *tex_coord =
1051               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1052             D3DVALUE *position =
1053               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1054             
1055             handle_normal(normal);
1056             handle_texture(tex_coord);
1057             handle_xyz(position);
1058             
1059             TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1060                   position[0], position[1], position[2],
1061                   normal[0], normal[1], normal[2],
1062                   tex_coord[0], tex_coord[1]);
1063         }
1064     } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1065         int index;
1066         
1067         for (index = 0; index < dwIndexCount; index++) {
1068             int i = (dwIndices == NULL) ? index : dwIndices[index];
1069             DWORD *color_d = 
1070               (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1071             DWORD *color_s = 
1072               (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1073             D3DVALUE *tex_coord =
1074               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1075             D3DVALUE *position =
1076               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1077
1078             handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1079             handle_texture(tex_coord);
1080             handle_xyzrhw(position);
1081
1082             TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1083                   position[0], position[1], position[2], position[3], 
1084                   (*color_d >> 16) & 0xFF,
1085                   (*color_d >>  8) & 0xFF,
1086                   (*color_d >>  0) & 0xFF,
1087                   (*color_d >> 24) & 0xFF,
1088                   (*color_s >> 16) & 0xFF,
1089                   (*color_s >>  8) & 0xFF,
1090                   (*color_s >>  0) & 0xFF,
1091                   (*color_s >> 24) & 0xFF,
1092                   tex_coord[0], tex_coord[1]);
1093         } 
1094     } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1095                ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1096         /* This is the 'slow path' but that should support all possible vertex formats out there...
1097            Note that people should write a fast path for all vertex formats out there...
1098         */  
1099         int index;
1100         for (index = 0; index < dwIndexCount; index++) {
1101             int i = (dwIndices == NULL) ? index : dwIndices[index];         
1102
1103             if (d3dvtVertexType & D3DFVF_NORMAL) { 
1104                 D3DVALUE *normal = 
1105                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);         
1106                 handle_normal(normal);
1107             }
1108             if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1109                 DWORD *color_d = 
1110                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1111                 DWORD *color_s = 
1112                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1113                 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1114             } else {
1115                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1116                     DWORD *color_s = 
1117                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1118                     handle_specular(&(This->state_block), color_s, vertex_lighted);
1119                 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1120                     DWORD *color_d = 
1121                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1122                     handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1123                 }
1124             }
1125                 
1126             if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1127                 /* Special case for single texture... */
1128                 D3DVALUE *tex_coord =
1129                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1130                 handle_texture(tex_coord);
1131             } else {
1132                 int tex_index;
1133                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1134                     D3DVALUE *tex_coord =
1135                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1136                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1137                     handle_textures(tex_coord, tex_index);
1138                 }
1139             }
1140             if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1141                 D3DVALUE *position =
1142                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1143                 handle_xyz(position);
1144             } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1145                 D3DVALUE *position =
1146                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1147                 handle_xyzrhw(position);
1148             }
1149
1150             if (TRACE_ON(ddraw)) {
1151                 int tex_index;
1152
1153                 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1154                     D3DVALUE *position =
1155                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1156                     TRACE(" %f %f %f", position[0], position[1], position[2]);
1157                 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1158                     D3DVALUE *position =
1159                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1160                     TRACE(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1161                 }
1162                 if (d3dvtVertexType & D3DFVF_NORMAL) { 
1163                     D3DVALUE *normal = 
1164                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);     
1165                     DPRINTF(" / %f %f %f", normal[0], normal[1], normal[2]);
1166                 }
1167                 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1168                     DWORD *color_d = 
1169                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1170                     DPRINTF(" / %02lx %02lx %02lx %02lx",
1171                             (*color_d >> 16) & 0xFF,
1172                             (*color_d >>  8) & 0xFF,
1173                             (*color_d >>  0) & 0xFF,
1174                             (*color_d >> 24) & 0xFF);
1175                 }
1176                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1177                     DWORD *color_s = 
1178                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1179                     DPRINTF(" / %02lx %02lx %02lx %02lx",
1180                             (*color_s >> 16) & 0xFF,
1181                             (*color_s >>  8) & 0xFF,
1182                             (*color_s >>  0) & 0xFF,
1183                             (*color_s >> 24) & 0xFF);
1184                 }
1185                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1186                     D3DVALUE *tex_coord =
1187                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1188                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1189                     DPRINTF(" / %f %f", tex_coord[0], tex_coord[1]);
1190                 }
1191                 DPRINTF("\n");
1192             }
1193         }
1194     } else {
1195         ERR(" matrix weighting not handled yet....\n");
1196     }
1197     
1198     glEnd();
1199
1200     /* Whatever the case, disable the color material stuff */
1201     glDisable(GL_COLOR_MATERIAL);
1202
1203     LEAVE_GL();
1204     TRACE("End\n");    
1205 }
1206
1207 HRESULT WINAPI
1208 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1209                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1210                                           DWORD d3dvtVertexType,
1211                                           LPVOID lpvVertices,
1212                                           DWORD dwVertexCount,
1213                                           DWORD dwFlags)
1214 {
1215     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1216     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1217
1218     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1219     if (TRACE_ON(ddraw)) {
1220         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1221     }
1222
1223     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided);
1224     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1225     
1226     return DD_OK;
1227 }
1228
1229 HRESULT WINAPI
1230 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1231                                                  D3DPRIMITIVETYPE d3dptPrimitiveType,
1232                                                  DWORD d3dvtVertexType,
1233                                                  LPVOID lpvVertices,
1234                                                  DWORD dwVertexCount,
1235                                                  LPWORD dwIndices,
1236                                                  DWORD dwIndexCount,
1237                                                  DWORD dwFlags)
1238 {
1239     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1240     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1241
1242     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1243     if (TRACE_ON(ddraw)) {
1244         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1245     }
1246
1247     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided);
1248     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, 0, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1249     
1250     return DD_OK;
1251 }
1252
1253 HRESULT WINAPI
1254 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1255                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1256                                                    DWORD dwVertexType,
1257                                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1258                                                    DWORD dwVertexCount,
1259                                                    DWORD dwFlags)
1260 {
1261     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1262
1263     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1264     if (TRACE_ON(ddraw)) {
1265         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1266     }
1267     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, NULL, dwVertexCount, dwFlags);
1268
1269     return DD_OK;
1270 }
1271
1272 HRESULT WINAPI
1273 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1274                                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1275                                                           DWORD dwVertexType,
1276                                                           LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1277                                                           DWORD dwVertexCount,
1278                                                           LPWORD lpIndex,
1279                                                           DWORD dwIndexCount,
1280                                                           DWORD dwFlags)
1281 {
1282     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1283
1284     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1285     if (TRACE_ON(ddraw)) {
1286         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1287     }
1288
1289     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, 0, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1290
1291     return DD_OK;
1292 }
1293
1294 HRESULT WINAPI
1295 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1296                                             D3DPRIMITIVETYPE d3dptPrimitiveType,
1297                                             LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1298                                             DWORD dwStartVertex,
1299                                             DWORD dwNumVertices,
1300                                             DWORD dwFlags)
1301 {
1302     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1303     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1304     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1305
1306     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1307     if (TRACE_ON(ddraw)) {
1308         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1309     }
1310
1311     if (vb_impl->processed == TRUE) {
1312         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1313         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1314
1315         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1316         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1317                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1318
1319         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided);
1320         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwStartVertex, dwNumVertices, NULL, dwNumVertices, dwFlags);
1321
1322     } else {
1323         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided);
1324         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwStartVertex, dwNumVertices, NULL, dwNumVertices, dwFlags);
1325     }
1326
1327     return DD_OK;
1328 }
1329
1330 HRESULT WINAPI
1331 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1332                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1333                                                    LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1334                                                    DWORD dwStartVertex,
1335                                                    DWORD dwNumVertices,
1336                                                    LPWORD lpwIndices,
1337                                                    DWORD dwIndexCount,
1338                                                    DWORD dwFlags)
1339 {
1340     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1341     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1342     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1343     
1344     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1345     if (TRACE_ON(ddraw)) {
1346         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1347     }
1348
1349     if (vb_impl->processed == TRUE) {
1350         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1351         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1352
1353         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1354         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1355                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1356
1357         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided);
1358         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1359
1360     } else {
1361         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided);
1362         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1363     }
1364
1365     return DD_OK;
1366 }
1367
1368 static GLenum
1369 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwState)
1370 {
1371     GLenum gl_state;
1372
1373     switch (dwState) {
1374         case D3DTFN_POINT:
1375             gl_state = GL_NEAREST;
1376             break;
1377         case D3DTFN_LINEAR:
1378             gl_state = GL_LINEAR;
1379             break;
1380         default:
1381             gl_state = GL_LINEAR;
1382             break;
1383     }
1384     return gl_state;
1385 }
1386
1387 static GLenum
1388 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1389 {
1390     GLenum gl_state;
1391
1392     switch (dwState) {
1393         case D3DTFG_POINT:
1394             gl_state = GL_NEAREST;
1395             break;
1396         case D3DTFG_LINEAR:
1397             gl_state = GL_LINEAR;
1398             break;
1399         default:
1400             gl_state = GL_LINEAR;
1401             break;
1402     }
1403     return gl_state;
1404 }
1405
1406 HRESULT WINAPI
1407 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1408                                                  DWORD dwStage,
1409                                                  D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1410                                                  DWORD dwState)
1411 {
1412     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1413     
1414     TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1415
1416     if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1417
1418     if (TRACE_ON(ddraw)) {
1419         TRACE(" Stage type is : ");
1420         switch (d3dTexStageStateType) {
1421 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1422             GEN_CASE(D3DTSS_COLOROP);
1423             GEN_CASE(D3DTSS_COLORARG1);
1424             GEN_CASE(D3DTSS_COLORARG2);
1425             GEN_CASE(D3DTSS_ALPHAOP);
1426             GEN_CASE(D3DTSS_ALPHAARG1);
1427             GEN_CASE(D3DTSS_ALPHAARG2);
1428             GEN_CASE(D3DTSS_BUMPENVMAT00);
1429             GEN_CASE(D3DTSS_BUMPENVMAT01);
1430             GEN_CASE(D3DTSS_BUMPENVMAT10);
1431             GEN_CASE(D3DTSS_BUMPENVMAT11);
1432             GEN_CASE(D3DTSS_TEXCOORDINDEX);
1433             GEN_CASE(D3DTSS_ADDRESS);
1434             GEN_CASE(D3DTSS_ADDRESSU);
1435             GEN_CASE(D3DTSS_ADDRESSV);
1436             GEN_CASE(D3DTSS_BORDERCOLOR);
1437             GEN_CASE(D3DTSS_MAGFILTER);
1438             GEN_CASE(D3DTSS_MINFILTER);
1439             GEN_CASE(D3DTSS_MIPFILTER);
1440             GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1441             GEN_CASE(D3DTSS_MAXMIPLEVEL);
1442             GEN_CASE(D3DTSS_MAXANISOTROPY);
1443             GEN_CASE(D3DTSS_BUMPENVLSCALE);
1444             GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1445             GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1446 #undef GEN_CASE
1447             default: DPRINTF("UNKNOWN !!!");
1448         }
1449         DPRINTF(" => ");
1450     }
1451
1452     switch (d3dTexStageStateType) {
1453         case D3DTSS_MINFILTER:
1454             if (TRACE_ON(ddraw)) {
1455                 switch ((D3DTEXTUREMINFILTER) dwState) {
1456                     case D3DTFN_POINT:  DPRINTF("D3DTFN_POINT\n"); break;
1457                     case D3DTFN_LINEAR: DPRINTF("D3DTFN_LINEAR\n"); break;
1458                     default: DPRINTF(" state unhandled (%ld).\n", dwState); break;
1459                 }
1460             }
1461             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, convert_min_filter_to_GL(dwState));
1462             break;
1463             
1464         case D3DTSS_MAGFILTER:
1465             if (TRACE_ON(ddraw)) {
1466                 switch ((D3DTEXTUREMAGFILTER) dwState) {
1467                     case D3DTFG_POINT:  DPRINTF("D3DTFN_POINT\n"); break;
1468                     case D3DTFG_LINEAR: DPRINTF("D3DTFN_LINEAR\n"); break;
1469                     default: DPRINTF(" state unhandled (%ld).\n", dwState); break;
1470                 }
1471             }
1472             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1473             break;
1474
1475         case D3DTSS_ADDRESS:
1476         case D3DTSS_ADDRESSU:
1477         case D3DTSS_ADDRESSV: {
1478             GLenum arg = GL_REPEAT; /* Default value */
1479             switch ((D3DTEXTUREADDRESS) dwState) {
1480                 case D3DTADDRESS_WRAP:   if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_WRAP\n"); arg = GL_REPEAT; break;
1481                 case D3DTADDRESS_CLAMP:  if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_CLAMP\n"); arg = GL_CLAMP; break;
1482                 case D3DTADDRESS_BORDER: if (TRACE_ON(ddraw)) DPRINTF("D3DTADDRESS_BORDER\n"); arg = GL_CLAMP_TO_EDGE; break;
1483                 default: DPRINTF(" state unhandled (%ld).\n", dwState);
1484             }
1485             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1486                 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1487                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1488             if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1489                 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1490                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1491         } break;
1492             
1493         default:
1494             if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1495     }
1496    
1497     This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1498     /* Some special cases when one state modifies more than one... */
1499     if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1500         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1501         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1502     }
1503
1504     return DD_OK;
1505 }
1506
1507 HRESULT WINAPI
1508 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1509                                        DWORD dwStage,
1510                                        LPDIRECTDRAWSURFACE7 lpTexture2)
1511 {
1512     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1513     
1514     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1515     
1516     if (dwStage > 0) return DD_OK;
1517
1518     if (This->current_texture[dwStage] != NULL) {
1519         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1520     }
1521     
1522     ENTER_GL();
1523     if (lpTexture2 == NULL) {
1524         This->current_texture[dwStage] = NULL;
1525
1526         TRACE(" disabling 2D texturing.\n");
1527         glBindTexture(GL_TEXTURE_2D, 0);
1528         glDisable(GL_TEXTURE_2D);
1529     } else {
1530         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1531         
1532         This->current_texture[dwStage] = tex_impl;
1533         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1534         
1535         glEnable(GL_TEXTURE_2D);
1536         gltex_upload_texture(tex_impl);
1537
1538         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
1539                         convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
1540         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1541                         convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1]));
1542     }
1543     LEAVE_GL();
1544     
1545     return DD_OK;
1546 }
1547
1548 HRESULT WINAPI
1549 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1550                                  LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1551 {
1552     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1553     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1554
1555     fill_opengl_caps_7(lpD3DHELDevDesc);
1556
1557     TRACE(" returning caps : no dump function yet.\n");
1558
1559     return DD_OK;
1560 }
1561
1562 HRESULT WINAPI
1563 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
1564                                      LPD3DMATERIAL7 lpMat)
1565 {
1566     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1567     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
1568     
1569     if (TRACE_ON(ddraw)) {
1570         TRACE(" material is : \n");
1571         dump_D3DMATERIAL7(lpMat);
1572     }
1573     
1574     This->current_material = *lpMat;
1575
1576     glMaterialfv(GL_FRONT_AND_BACK,
1577                  GL_DIFFUSE,
1578                  (float *) &(This->current_material.u.diffuse));
1579     glMaterialfv(GL_FRONT_AND_BACK,
1580                  GL_AMBIENT,
1581                  (float *) &(This->current_material.u1.ambient));
1582     glMaterialfv(GL_FRONT_AND_BACK,
1583                  GL_SPECULAR,
1584                  (float *) &(This->current_material.u2.specular));
1585     glMaterialfv(GL_FRONT_AND_BACK,
1586                  GL_EMISSION,
1587                  (float *) &(This->current_material.u3.emissive));
1588     glMaterialf(GL_FRONT_AND_BACK,
1589                 GL_SHININESS,
1590                 This->current_material.u4.power); /* Not sure about this... */
1591
1592     return DD_OK;
1593 }
1594
1595
1596 HRESULT WINAPI
1597 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
1598                                   DWORD dwLightIndex,
1599                                   LPD3DLIGHT7 lpLight)
1600 {
1601     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1602     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
1603     
1604     if (TRACE_ON(ddraw)) {
1605         TRACE(" setting light : \n");
1606         dump_D3DLIGHT7(lpLight);
1607     }
1608     
1609     if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1610     This->set_lights |= 0x00000001 << dwLightIndex;
1611     This->light_parameters[dwLightIndex] = *lpLight;
1612
1613     switch (lpLight->dltType) {
1614         case D3DLIGHT_DIRECTIONAL: {
1615             float direction[4];
1616             float cut_off = 180.0;
1617             
1618             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1619             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1620             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1621             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1622
1623             direction[0] = lpLight->dvDirection.u1.x;
1624             direction[1] = lpLight->dvDirection.u2.y;
1625             direction[2] = lpLight->dvDirection.u3.z;
1626             direction[3] = 0.0;
1627             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
1628         } break;
1629
1630         case D3DLIGHT_POINT: {
1631             float position[4];
1632             float cut_off = 180.0;
1633
1634             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1635             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1636             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1637             position[0] = lpLight->dvPosition.u1.x;
1638             position[1] = lpLight->dvPosition.u2.y;
1639             position[2] = lpLight->dvPosition.u3.z;
1640             position[3] = 1.0;
1641             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1642             glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1643             glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1644             glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1645             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1646         } break;
1647
1648         case D3DLIGHT_SPOT: {
1649             float direction[4];
1650             float position[4];
1651             float cut_off = 90.0 * (lpLight->dvPhi / M_PI);
1652
1653             glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT,  (float *) &(lpLight->dcvAmbient));
1654             glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE,  (float *) &(lpLight->dcvDiffuse));
1655             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
1656
1657             direction[0] = lpLight->dvDirection.u1.x;
1658             direction[1] = lpLight->dvDirection.u2.y;
1659             direction[2] = lpLight->dvDirection.u3.z;
1660             direction[3] = 0.0;
1661             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_DIRECTION, (float *) direction);
1662             position[0] = lpLight->dvPosition.u1.x;
1663             position[1] = lpLight->dvPosition.u2.y;
1664             position[2] = lpLight->dvPosition.u3.z;
1665             position[3] = 1.0;
1666             glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) position);
1667             glLightfv(GL_LIGHT0 + dwLightIndex, GL_CONSTANT_ATTENUATION, &(lpLight->dvAttenuation0));
1668             glLightfv(GL_LIGHT0 + dwLightIndex, GL_LINEAR_ATTENUATION, &(lpLight->dvAttenuation1));
1669             glLightfv(GL_LIGHT0 + dwLightIndex, GL_QUADRATIC_ATTENUATION, &(lpLight->dvAttenuation2));
1670             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_CUTOFF, &cut_off);
1671             glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPOT_EXPONENT, &(lpLight->dvFalloff));
1672             if ((lpLight->dvTheta != 0.0) || (lpLight->dvTheta != lpLight->dvPhi)) {
1673                 WARN("dvTheta not fully supported yet !\n");
1674             }
1675         } break;
1676
1677         default: WARN(" light type not handled yet...\n");
1678     }
1679
1680     return DD_OK;
1681 }
1682
1683 HRESULT WINAPI
1684 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
1685                                      DWORD dwLightIndex,
1686                                      BOOL bEnable)
1687 {
1688     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1689     TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
1690     
1691     if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
1692
1693     if (bEnable) {
1694         if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
1695             /* Set the default parameters.. */
1696             TRACE(" setting default light parameters...\n");
1697             GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
1698         }
1699         glEnable(GL_LIGHT0 + dwLightIndex);
1700     } else {
1701         glDisable(GL_LIGHT0 + dwLightIndex);
1702     }
1703
1704     return DD_OK;
1705 }
1706
1707 HRESULT  WINAPI  
1708 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation) 
1709 {
1710     ICOM_THIS(IDirect3DDeviceImpl,iface);
1711     GLdouble plane[4];
1712
1713     TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
1714
1715     if (dwIndex>=This->max_clipping_planes) {
1716         return DDERR_INVALIDPARAMS;
1717     }
1718
1719     TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
1720
1721     memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
1722     plane[0] = pPlaneEquation[0];
1723     plane[1] = pPlaneEquation[1];
1724     plane[2] = pPlaneEquation[2];
1725     plane[3] = pPlaneEquation[3];
1726
1727     /* XXX: is here also code needed to handle the transformation of the world? */
1728     glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) );
1729
1730     return D3D_OK;
1731 }
1732
1733 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1734 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
1735 #else
1736 # define XCAST(fun)     (void*)
1737 #endif
1738
1739 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1740 {
1741     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1742     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1743     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1744     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1745     XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1746     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1747     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1748     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1749     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1750     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1751     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1752     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1753     XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1754     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1755     XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1756     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1757     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1758     XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
1759     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1760     XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
1761     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1762     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1763     XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1764     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1765     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1766     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1767     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1768     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1769     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1770     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1771     XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1772     XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1773     XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
1774     XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
1775     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1776     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
1777     XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
1778     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1779     XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1780     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1781     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1782     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1783     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1784     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1785     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1786     XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
1787     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1788     XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
1789     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1790     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1791 };
1792
1793 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1794 #undef XCAST
1795 #endif
1796
1797
1798 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1799 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
1800 #else
1801 # define XCAST(fun)     (void*)
1802 #endif
1803
1804 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1805 {
1806     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1807     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1808     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1809     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1810     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1811     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1812     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1813     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1814     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1815     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1816     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1817     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1818     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1819     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1820     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1821     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1822     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1823     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1824     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1825     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1826     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1827     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1828     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1829     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1830     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1831     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1832     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1833     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1834     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1835     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1836     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1837     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1838     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1839     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1840     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1841     XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1842     XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1843     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1844     XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
1845     XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
1846     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1847     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1848     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1849 };
1850
1851 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1852 #undef XCAST
1853 #endif
1854
1855
1856 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1857 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
1858 #else
1859 # define XCAST(fun)     (void*)
1860 #endif
1861
1862 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1863 {
1864     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1865     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1866     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1867     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1868     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1869     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
1870     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1871     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1872     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1873     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1874     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1875     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1876     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1877     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1878     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1879     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1880     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1881     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1882     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1883     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1884     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1885     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1886     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1887     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1888     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1889     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1890     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1891     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1892     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1893     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1894     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1895     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1896     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1897     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1898 };
1899
1900 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1901 #undef XCAST
1902 #endif
1903
1904
1905 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1906 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
1907 #else
1908 # define XCAST(fun)     (void*)
1909 #endif
1910
1911 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1912 {
1913     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1914     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1915     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1916     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1917     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1918     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1919     XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
1920     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1921     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1922     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1923     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1924     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1925     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1926     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1927     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1928     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1929     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1930     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1931     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1932     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1933     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1934     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1935     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1936 };
1937
1938 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1939 #undef XCAST
1940 #endif
1941
1942 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
1943                                DWORD dwCount,
1944                                LPD3DRECT lpRects,
1945                                DWORD dwFlags,
1946                                DWORD dwColor,
1947                                D3DVALUE dvZ,
1948                                DWORD dwStencil)
1949 {
1950     GLboolean ztest;
1951     GLfloat old_z_clear_value;
1952     GLbitfield bitfield = 0;
1953     GLint old_stencil_clear_value;
1954     GLfloat old_color_clear_value[4];
1955     
1956     TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1957     if (TRACE_ON(ddraw)) {
1958         if (dwCount > 0) {
1959             int i;
1960             TRACE(" rectangles : \n");
1961             for (i = 0; i < dwCount; i++) {
1962                 TRACE("  - %ld x %ld     %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
1963             }
1964         }
1965     }
1966
1967     if (dwCount > 1) {
1968         WARN("  Warning, this function only for now clears the whole screen...\n");
1969     }
1970
1971     /* Clears the screen */
1972     ENTER_GL();
1973     if (dwFlags & D3DCLEAR_ZBUFFER) {
1974         bitfield |= GL_DEPTH_BUFFER_BIT;
1975         glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
1976         glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
1977         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1978         glClearDepth(dvZ);
1979         TRACE(" depth value : %f\n", dvZ);
1980     }
1981     if (dwFlags & D3DCLEAR_STENCIL) {
1982         bitfield |= GL_STENCIL_BUFFER_BIT;
1983         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1984         glClearStencil(dwStencil);
1985         TRACE(" stencil value : %ld\n", dwStencil);
1986     }    
1987     if (dwFlags & D3DCLEAR_TARGET) {
1988         bitfield |= GL_COLOR_BUFFER_BIT;
1989         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1990         glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
1991                      ((dwColor >>  8) & 0xFF) / 255.0,
1992                      ((dwColor >>  0) & 0xFF) / 255.0,
1993                      ((dwColor >> 24) & 0xFF) / 255.0);
1994         TRACE(" color value (ARGB) : %08lx\n", dwColor);
1995     }
1996     
1997     glClear(bitfield);
1998     
1999     if (dwFlags & D3DCLEAR_ZBUFFER) {
2000         glDepthMask(ztest);
2001         glClearDepth(old_z_clear_value);
2002     }
2003      if (dwFlags & D3DCLEAR_STENCIL) {
2004         bitfield |= GL_STENCIL_BUFFER_BIT;
2005         glClearStencil(old_stencil_clear_value);
2006     }    
2007     if (dwFlags & D3DCLEAR_TARGET) {
2008         bitfield |= GL_COLOR_BUFFER_BIT;
2009         glClearColor(old_color_clear_value[0],
2010                      old_color_clear_value[1],
2011                      old_color_clear_value[2],
2012                      old_color_clear_value[3]);
2013     }
2014     
2015     LEAVE_GL();
2016     
2017     return DD_OK;
2018 }
2019
2020 HRESULT
2021 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2022               LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2023               DWORD dwFlags, LPDDBLTFX lpbltfx)
2024 {
2025     if (dwFlags & DDBLT_COLORFILL) {
2026         /* This is easy to handle for the D3D Device... */
2027         DWORD color = lpbltfx->u5.dwFillColor;
2028         TRACE(" executing D3D Device override.\n");
2029         d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2030         return DD_OK;
2031     }
2032     return DDERR_INVALIDPARAMS;
2033 }
2034
2035 HRESULT
2036 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2037                   DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2038                   LPRECT rsrc, DWORD trans)
2039 {
2040      return DDERR_INVALIDPARAMS;
2041 }
2042
2043 void
2044 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2045 {
2046     GLfloat height, width;
2047     GLfloat trans_mat[16];
2048     
2049     width = This->surface->surface_desc.dwWidth;
2050     height = This->surface->surface_desc.dwHeight;
2051     
2052     /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2053        to OpenGL screen coordinates (ie the upper left corner is not the same).
2054        For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2055        -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2056     trans_mat[ 0] = 2.0 / width;  trans_mat[ 4] = 0.0;  trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2057     trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] =  1.0;
2058     trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0;           trans_mat[14] = -1.0;
2059     trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0;           trans_mat[15] =  1.0;
2060     
2061     glMatrixMode(GL_MODELVIEW);
2062     glLoadIdentity();
2063     glMatrixMode(GL_PROJECTION);
2064     glLoadMatrixf(trans_mat);
2065 }
2066
2067 void
2068 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2069                        D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2070 {
2071     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2072         glMatrixMode(GL_MODELVIEW);
2073         glLoadMatrixf((float *) view_mat);
2074         glMultMatrixf((float *) world_mat);
2075     }
2076     if ((matrices & PROJMAT_CHANGED) != 0) {
2077         glMatrixMode(GL_PROJECTION);
2078         glLoadMatrixf((float *) proj_mat);
2079     }
2080 }
2081
2082 void
2083 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2084 {
2085     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2086     if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2087         /* This will force an update of the transform state at the next drawing. */
2088         glThis->transform_state = GL_TRANSFORM_NONE;
2089     }
2090 }
2091
2092 /* TODO for both these functions :
2093     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2094       by other OpenGL code in D3D
2095     - handle the case where no 'Begin / EndScene' was done between two locks
2096     - handle the rectangles in the unlock too
2097     - handle pitch correctly...
2098 */
2099 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2100 {
2101     /* First, check if we need to do anything */
2102     if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
2103         GLenum buffer_type;
2104         GLenum prev_read;
2105         RECT loc_rect;
2106
2107         ENTER_GL();
2108
2109         glGetIntegerv(GL_READ_BUFFER, &prev_read);
2110         glFlush();
2111         
2112         WARN(" application does a lock on a 3D surface - expect slow downs.\n");
2113         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2114             /* Application wants to lock the front buffer */
2115             glReadBuffer(GL_FRONT);
2116         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2117             /* Application wants to lock the back buffer */
2118             glReadBuffer(GL_BACK);
2119         } else {
2120             WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
2121         }
2122
2123         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2124             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2125         } else {
2126             WARN(" unsupported pixel format.\n");
2127             LEAVE_GL();
2128             return;
2129         }
2130         if (pRect == NULL) {
2131             loc_rect.top = 0;
2132             loc_rect.left = 0;
2133             loc_rect.bottom = This->surface_desc.dwHeight;
2134             loc_rect.right = This->surface_desc.dwWidth;
2135         } else {
2136             loc_rect = *pRect;
2137         }
2138         glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
2139                      GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
2140                                            + loc_rect.top * This->surface_desc.u1.lPitch
2141                                            + loc_rect.left * GET_BPP(This->surface_desc)));
2142         glReadBuffer(prev_read);
2143         LEAVE_GL();
2144     }
2145 }
2146
2147 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
2148 {
2149     /* First, check if we need to do anything */
2150     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
2151         GLenum buffer_type;
2152         GLenum prev_draw;
2153
2154         ENTER_GL();
2155
2156         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2157
2158         WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
2159         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2160             /* Application wants to lock the front buffer */
2161             glDrawBuffer(GL_FRONT);
2162         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2163             /* Application wants to lock the back buffer */
2164             glDrawBuffer(GL_BACK);
2165         } else {
2166             WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
2167         }
2168
2169         if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
2170             buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2171         } else {
2172             WARN(" unsupported pixel format.\n");
2173             LEAVE_GL();
2174             return;
2175         }
2176         glRasterPos2f(0.0, 0.0);
2177         glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight, 
2178                      GL_RGB, buffer_type, This->surface_desc.lpSurface);
2179         glDrawBuffer(prev_draw);
2180
2181         LEAVE_GL();
2182    }
2183 }
2184
2185 HRESULT
2186 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
2187 {
2188     IDirect3DDeviceImpl *object;
2189     IDirect3DDeviceGLImpl *gl_object;
2190     IDirectDrawSurfaceImpl *surf;
2191     HDC device_context;
2192     XVisualInfo *vis;
2193     int num;
2194     XVisualInfo template;
2195     GLenum buffer = GL_FRONT;
2196     int light;
2197     GLint max_clipping_planes = 0;
2198     
2199     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
2200     if (object == NULL) return DDERR_OUTOFMEMORY;
2201
2202     gl_object = (IDirect3DDeviceGLImpl *) object;
2203     
2204     object->ref = 1;
2205     object->d3d = d3d;
2206     object->surface = surface;
2207     object->set_context = set_context;
2208     object->clear = d3ddevice_clear;
2209     object->set_matrices = d3ddevice_set_matrices;
2210     object->matrices_updated = d3ddevice_matrices_updated;
2211
2212     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
2213
2214     device_context = GetDC(surface->ddraw_owner->window);
2215     gl_object->display = get_display(device_context);
2216     gl_object->drawable = get_drawable(device_context);
2217     ReleaseDC(surface->ddraw_owner->window,device_context);
2218
2219     ENTER_GL();
2220     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
2221     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
2222     if (vis == NULL) {
2223         HeapFree(GetProcessHeap(), 0, object);
2224         ERR("No visual found !\n");
2225         LEAVE_GL();
2226         return DDERR_INVALIDPARAMS;
2227     } else {
2228         TRACE(" visual found\n");
2229     }
2230
2231     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
2232                                              NULL, GL_TRUE);
2233
2234     if (gl_object->gl_context == NULL) {
2235         HeapFree(GetProcessHeap(), 0, object);
2236         ERR("Error in context creation !\n");
2237         LEAVE_GL();
2238         return DDERR_INVALIDPARAMS;
2239     } else {
2240         TRACE(" context created (%p)\n", gl_object->gl_context);
2241     }
2242     
2243     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
2244     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
2245         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
2246             surf->aux_ctx  = (LPVOID) gl_object->display;
2247             surf->aux_data = (LPVOID) gl_object->drawable;
2248             surf->aux_flip = opengl_flip;
2249             buffer =  GL_BACK;
2250             break;
2251         }
2252     }
2253     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
2254     if (surf == NULL) {
2255         TRACE(" no double buffering : drawing on the front buffer\n");
2256         buffer = GL_FRONT;
2257     }
2258     
2259     for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
2260     for (; surf != NULL; surf = surf->next_attached) {
2261         if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
2262             ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
2263             /* Override the Lock / Unlock function for all these surfaces */
2264             surf->lock_update = d3ddevice_lock_update;
2265             surf->unlock_update = d3ddevice_unlock_update;
2266             /* And install also the blt / bltfast overrides */
2267             surf->aux_blt = d3ddevice_blt;
2268             surf->aux_bltfast = d3ddevice_bltfast;
2269         }
2270         surf->d3ddevice = object;
2271     }
2272
2273     /* Set the various light parameters */
2274     for (light = 0; light < MAX_LIGHTS; light++) {
2275         /* Only set the fields that are not zero-created */
2276         object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
2277         object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
2278         object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
2279         object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
2280         object->light_parameters[light].dvDirection.u3.z = 1.0;
2281     }
2282     
2283     /* Allocate memory for the matrices */
2284     object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2285     object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2286     object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
2287     memcpy(object->world_mat, id_mat, 16 * sizeof(float));
2288     memcpy(object->view_mat , id_mat, 16 * sizeof(float));
2289     memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
2290
2291     /* allocate the clipping planes */
2292     glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
2293     if (max_clipping_planes>32) {
2294         object->max_clipping_planes=32;
2295     } else {
2296         object->max_clipping_planes = max_clipping_planes;
2297     }
2298     TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
2299     object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
2300
2301     /* Initialisation */
2302     TRACE(" setting current context\n");
2303     LEAVE_GL();
2304     object->set_context(object);
2305     ENTER_GL();
2306     TRACE(" current context set\n");
2307
2308     glHint(GL_FOG_HINT,GL_NICEST);
2309     glClearColor(0.0, 0.0, 0.0, 0.0);
2310     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2311     glDrawBuffer(buffer);
2312     glReadBuffer(buffer);
2313     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
2314     LEAVE_GL();
2315
2316     /* fill_device_capabilities(d3d->ddraw); */    
2317     
2318     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
2319     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
2320     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
2321     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
2322
2323     *obj = object;
2324
2325     TRACE(" creating implementation at %p.\n", *obj);
2326
2327     /* And finally warn D3D that this device is now present */
2328     object->d3d->added_device(object->d3d, object);
2329
2330     /* FIXME: Should handle other versions than just 7 */
2331     InitDefaultStateBlock(&object->state_block, 7);
2332     /* Apply default render state values */
2333     apply_render_state(object, &object->state_block);
2334     /* FIXME: do something similar for ligh_state and texture_stage_state */
2335
2336     /* And fill the fog table with the default fog value */
2337     build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
2338     
2339     return DD_OK;
2340 }