Fix the BLT COLOR_FILL case.
[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 #include <math.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "ddraw.h"
33 #include "d3d.h"
34 #include "wine/debug.h"
35
36 #include "mesa_private.h"
37 #include "main.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
41
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
45 {
46     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
47     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
48     X11DRV_GET_FONT,      /* get current X font for a DC */
49 };
50
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
53   0x31416d44,
54   0x86ae,
55   0x11d2,
56   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
57 };
58
59 const float id_mat[16] = {
60     1.0, 0.0, 0.0, 0.0,
61     0.0, 1.0, 0.0, 0.0,
62     0.0, 0.0, 1.0, 0.0,
63     0.0, 0.0, 0.0, 1.0
64 };
65
66 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
67                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
68                                    DWORD d3dvtVertexType,
69                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
70                                    DWORD dwVertexCount,
71                                    LPWORD dwIndices,
72                                    DWORD dwIndexCount,
73                                    DWORD dwFlags) ;
74
75 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
76
77 /* retrieve the X display to use on a given DC */
78 inline static Display *get_display( HDC hdc )
79 {
80     Display *display;
81     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
82
83     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
84                     sizeof(display), (LPSTR)&display )) display = NULL;
85
86     return display;
87 }
88
89
90 /* retrieve the X drawable to use on a given DC */
91 inline static Drawable get_drawable( HDC hdc )
92 {
93     Drawable drawable;
94     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
95
96     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
97                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
98
99     return drawable;
100 }
101
102
103 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
104 {
105     IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
106     IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
107
108     TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
109     ENTER_GL();
110     if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
111         d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
112     }
113     gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
114     gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
115     glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
116     LEAVE_GL();
117     
118     return TRUE;
119 }
120
121
122 /*******************************************************************************
123  *                              OpenGL static functions
124  */
125 static void set_context(IDirect3DDeviceImpl* This)
126 {
127     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
128    
129     TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
130     ENTER_GL();
131     if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
132         ERR("Error in setting current context (context %p drawable %ld)!\n",
133             glThis->gl_context, glThis->drawable);
134     }
135     LEAVE_GL();
136 }
137
138 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
139 {
140     pc->dwSize = sizeof(*pc);
141     pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
142       D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
143     pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
144       D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
145     pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
146       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
147     pc->dwSrcBlendCaps  = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
148       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
149         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
150     pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
151       D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
152         D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
153     pc->dwAlphaCmpCaps  = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
154       D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
155     pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
156       D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
157     pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
158       D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
159     pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
160       D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
161     pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
162       D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
163     pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
164     pc->dwStippleWidth = 32;
165     pc->dwStippleHeight = 32;
166 }
167
168 static void fill_opengl_caps(D3DDEVICEDESC *d1)
169 {
170     /* GLint maxlight; */
171
172     d1->dwSize  = sizeof(*d1);
173     d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
174       | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
175     d1->dcmColorModel = D3DCOLOR_RGB;
176     d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
177       D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
178       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
179       /* D3D 7 capabilities */
180       D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
181     d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
182     d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
183     d1->bClipping = TRUE;
184     d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
185     d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
186     d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
187     d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
188     fill_opengl_primcaps(&(d1->dpcLineCaps));
189     fill_opengl_primcaps(&(d1->dpcTriCaps));
190     d1->dwDeviceRenderBitDepth  = DDBD_16|DDBD_24|DDBD_32;
191     d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
192     d1->dwMaxBufferSize = 0;
193     d1->dwMaxVertexCount = 65536;
194     d1->dwMinTextureWidth  = 1;
195     d1->dwMinTextureHeight = 1;
196     d1->dwMaxTextureWidth  = 1024;
197     d1->dwMaxTextureHeight = 1024;
198     d1->dwMinStippleWidth  = 1;
199     d1->dwMinStippleHeight = 1;
200     d1->dwMaxStippleWidth  = 32;
201     d1->dwMaxStippleHeight = 32;
202     d1->dwMaxTextureRepeat = 16;
203     d1->dwMaxTextureAspectRatio = 1024;
204     d1->dwMaxAnisotropy = 0;
205     d1->dvGuardBandLeft = 0.0;
206     d1->dvGuardBandRight = 0.0;
207     d1->dvGuardBandTop = 0.0;
208     d1->dvGuardBandBottom = 0.0;
209     d1->dvExtentsAdjust = 0.0;
210     d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
211       D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
212     d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
213     d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
214     d1->wMaxTextureBlendStages = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
215     d1->wMaxSimultaneousTextures = 1;  /* TODO add proper caps according to OpenGL multi-texture stuff */
216 }
217
218 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
219 {
220     D3DDEVICEDESC d1;
221
222     /* Copy first D3D1/2/3 capabilities */
223     fill_opengl_caps(&d1);
224
225     /* And fill the D3D7 one with it */
226     d->dwDevCaps = d1.dwDevCaps;
227     d->dpcLineCaps = d1.dpcLineCaps;
228     d->dpcTriCaps = d1.dpcTriCaps;
229     d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
230     d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
231     d->dwMinTextureWidth = d1.dwMinTextureWidth;
232     d->dwMinTextureHeight = d1.dwMinTextureHeight;
233     d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
234     d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
235     d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
236     d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
237     d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
238     d->dvGuardBandLeft = d1.dvGuardBandLeft;
239     d->dvGuardBandTop = d1.dvGuardBandTop;
240     d->dvGuardBandRight = d1.dvGuardBandRight;
241     d->dvGuardBandBottom = d1.dvGuardBandBottom;
242     d->dvExtentsAdjust = d1.dvExtentsAdjust;
243     d->dwStencilCaps = d1.dwStencilCaps;
244     d->dwFVFCaps = d1.dwFVFCaps;
245     d->dwTextureOpCaps = d1.dwTextureOpCaps;
246     d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
247     d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
248     d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
249     d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
250     d->deviceGUID = IID_IDirect3DTnLHalDevice;
251     d->wMaxUserClipPlanes = 1;
252     d->wMaxVertexBlendMatrices = 0;
253     d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
254       D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
255     d->dwReserved1 = 0;
256     d->dwReserved2 = 0;
257     d->dwReserved3 = 0;
258     d->dwReserved4 = 0;
259 }
260
261 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
262 {
263     D3DDEVICEDESC dref, d1, d2;
264     HRESULT ret_value;
265
266     /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
267        Let's put the string in a sufficiently sized array in writable memory. */
268     char device_name[50];
269     strcpy(device_name,"direct3d");
270
271     fill_opengl_caps(&dref);
272
273     if (version > 1) {
274         /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
275         TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
276         d1 = dref;
277         d2 = dref;
278         ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
279         if (ret_value != D3DENUMRET_OK)
280             return ret_value;
281     }
282     
283     TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
284     d1 = dref;
285     d2 = dref;
286     ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
287     if (ret_value != D3DENUMRET_OK)
288         return ret_value;
289
290     return D3DENUMRET_OK;
291 }
292
293 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
294 {
295     D3DDEVICEDESC7 ddesc;
296
297     fill_opengl_caps_7(&ddesc);
298     
299     TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
300     
301     return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
302 }
303
304 ULONG WINAPI
305 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
306 {
307     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
308     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
309     
310     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
311     if (!--(This->ref)) {
312         int i;
313         IDirectDrawSurfaceImpl *surface = This->surface, *surf;
314         
315         /* Release texture associated with the device */ 
316         for (i = 0; i < MAX_TEXTURES; i++) {
317             if (This->current_texture[i] != NULL)
318                 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
319             HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
320         }
321
322         /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
323         for (surf = surface; surf != NULL; surf = surf->surface_owner) {
324             if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
325                 surf->aux_ctx  = NULL;
326                 surf->aux_data = NULL;
327                 surf->aux_flip = NULL;
328                 break;
329             }
330         }
331         for (surf = surface; surf != NULL; surf = surf->surface_owner) {
332             IDirectDrawSurfaceImpl *surf2;
333             for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
334             for (; surf2 != NULL; surf2 = surf2->next_attached) {
335                 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
336                     ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
337                     /* Override the Lock / Unlock function for all these surfaces */
338                     surf2->lock_update = surf2->lock_update_prev;
339                     surf2->unlock_update = surf2->unlock_update_prev;
340                     /* And install also the blt / bltfast overrides */
341                     surf2->aux_blt = NULL;
342                     surf2->aux_bltfast = NULL;
343                 }
344                 surf2->d3ddevice = NULL;
345             }
346         }
347         
348         /* And warn the D3D object that this device is no longer active... */
349         This->d3d->d3d_removed_device(This->d3d, This);
350
351         HeapFree(GetProcessHeap(), 0, This->world_mat);
352         HeapFree(GetProcessHeap(), 0, This->view_mat);
353         HeapFree(GetProcessHeap(), 0, This->proj_mat);
354
355         if (glThis->surface_ptr)
356             HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
357
358         DeleteCriticalSection(&(This->crit));
359         
360         ENTER_GL();
361         if (glThis->unlock_tex)
362             glDeleteTextures(1, &(glThis->unlock_tex));
363         glXDestroyContext(glThis->display, glThis->gl_context);
364         LEAVE_GL();
365         HeapFree(GetProcessHeap(), 0, This->clipping_planes);
366
367         HeapFree(GetProcessHeap(), 0, This);
368         return 0;
369     }
370     return This->ref;
371 }
372
373 HRESULT WINAPI
374 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
375                                        LPD3DDEVICEDESC lpD3DHWDevDesc,
376                                        LPD3DDEVICEDESC lpD3DHELDevDesc)
377 {
378     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
379     D3DDEVICEDESC desc;
380     DWORD dwSize;
381
382     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
383
384     fill_opengl_caps(&desc);
385     dwSize = lpD3DHWDevDesc->dwSize;
386     memset(lpD3DHWDevDesc, 0, dwSize);
387     memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
388
389     dwSize = lpD3DHELDevDesc->dwSize;
390     memset(lpD3DHELDevDesc, 0, dwSize);
391     memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
392
393     TRACE(" returning caps : (no dump function yet)\n");
394
395     return DD_OK;
396 }
397
398 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
399                                           LPD3DENUMPIXELFORMATSCALLBACK cb_2,
400                                           LPVOID context)
401 {
402     DDSURFACEDESC sdesc;
403     LPDDPIXELFORMAT pformat;
404
405     /* Do the texture enumeration */
406     sdesc.dwSize = sizeof(DDSURFACEDESC);
407     sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
408     sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
409     pformat = &(sdesc.ddpfPixelFormat);
410     pformat->dwSize = sizeof(DDPIXELFORMAT);
411     pformat->dwFourCC = 0;
412
413     TRACE("Enumerating GL_RGBA unpacked (32)\n");
414     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
415     pformat->u1.dwRGBBitCount = 32;
416     pformat->u2.dwRBitMask =        0x00FF0000;
417     pformat->u3.dwGBitMask =        0x0000FF00;
418     pformat->u4.dwBBitMask =        0x000000FF;
419     pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
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_RGB unpacked (32)\n");
424     pformat->dwFlags = DDPF_RGB;
425     pformat->u1.dwRGBBitCount = 32;
426     pformat->u2.dwRBitMask =        0x00FF0000;
427     pformat->u3.dwGBitMask =        0x0000FF00;
428     pformat->u4.dwBBitMask =        0x000000FF;
429     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
430     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
431     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
432     
433     TRACE("Enumerating GL_RGB unpacked (24)\n");
434     pformat->dwFlags = DDPF_RGB;
435     pformat->u1.dwRGBBitCount = 24;
436     pformat->u2.dwRBitMask = 0x00FF0000;
437     pformat->u3.dwGBitMask = 0x0000FF00;
438     pformat->u4.dwBBitMask = 0x000000FF;
439     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
440     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
441     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
442
443     /* Note : even if this is an 'emulated' texture format, it needs to be first
444               as some dumb applications seem to rely on that. */
445     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
446     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
447     pformat->u1.dwRGBBitCount = 16;
448     pformat->u2.dwRBitMask =        0x00007C00;
449     pformat->u3.dwGBitMask =        0x000003E0;
450     pformat->u4.dwBBitMask =        0x0000001F;
451     pformat->u5.dwRGBAlphaBitMask = 0x00008000;
452     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
453     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
454
455     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
456     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
457     pformat->u1.dwRGBBitCount = 16;
458     pformat->u2.dwRBitMask =        0x00000F00;
459     pformat->u3.dwGBitMask =        0x000000F0;
460     pformat->u4.dwBBitMask =        0x0000000F;
461     pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
462     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
463     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
464
465     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
466     pformat->dwFlags = DDPF_RGB;
467     pformat->u1.dwRGBBitCount = 16;
468     pformat->u2.dwRBitMask = 0x0000F800;
469     pformat->u3.dwGBitMask = 0x000007E0;
470     pformat->u4.dwBBitMask = 0x0000001F;
471     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
472     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
473     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
474
475     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
476     pformat->dwFlags = DDPF_RGB;
477     pformat->u1.dwRGBBitCount = 16;
478     pformat->u2.dwRBitMask = 0x00007C00;
479     pformat->u3.dwGBitMask = 0x000003E0;
480     pformat->u4.dwBBitMask = 0x0000001F;
481     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
482     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
483     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
484     
485 #if 0
486     /* This is a compromise : some games choose the first 16 bit texture format with alpha they
487        find enumerated, others the last one. And both want to have the ARGB one.
488        
489        So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
490     */
491     /* See argument about the RGBA format for 'packed' texture formats */
492     TRACE("Enumerating GL_RGBA unpacked (32)\n");
493     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
494     pformat->u1.dwRGBBitCount = 32;
495     pformat->u2.dwRBitMask =        0xFF000000;
496     pformat->u3.dwGBitMask =        0x00FF0000;
497     pformat->u4.dwBBitMask =        0x0000FF00;
498     pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
499     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
500     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
501     
502     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
503     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
504     pformat->u1.dwRGBBitCount = 16;
505     pformat->u2.dwRBitMask =        0x0000F000;
506     pformat->u3.dwGBitMask =        0x00000F00;
507     pformat->u4.dwBBitMask =        0x000000F0;
508     pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
509     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
510     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
511
512     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
513     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
514     pformat->u1.dwRGBBitCount = 16;
515     pformat->u2.dwRBitMask =        0x0000F800;
516     pformat->u3.dwGBitMask =        0x000007C0;
517     pformat->u4.dwBBitMask =        0x0000003E;
518     pformat->u5.dwRGBAlphaBitMask = 0x00000001;
519     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
520     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
521 #endif
522
523     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
524     pformat->dwFlags = DDPF_RGB;
525     pformat->u1.dwRGBBitCount = 8;
526     pformat->u2.dwRBitMask =        0x000000E0;
527     pformat->u3.dwGBitMask =        0x0000001C;
528     pformat->u4.dwBBitMask =        0x00000003;
529     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
530     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
531     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
532
533     TRACE("Enumerating Paletted (8)\n");
534     pformat->dwFlags = DDPF_PALETTEINDEXED8;
535     pformat->u1.dwRGBBitCount = 8;
536     pformat->u2.dwRBitMask =        0x00000000;
537     pformat->u3.dwGBitMask =        0x00000000;
538     pformat->u4.dwBBitMask =        0x00000000;
539     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
540     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
541     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
542
543     TRACE("End of enumeration\n");
544     return DD_OK;
545 }
546
547
548 HRESULT
549 d3ddevice_find(IDirectDrawImpl *d3d,
550                LPD3DFINDDEVICESEARCH lpD3DDFS,
551                LPD3DFINDDEVICERESULT lplpD3DDevice)
552 {
553     D3DDEVICEDESC desc;
554   
555     if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
556         (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
557         TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
558         return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
559     }
560     if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
561         TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
562         if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
563             (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
564             (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
565             TRACE(" no match for this GUID.\n");
566             return DDERR_INVALIDPARAMS;
567         }
568     }
569
570     /* Now return our own GUID */
571     lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
572     fill_opengl_caps(&desc);
573     lplpD3DDevice->ddHwDesc = desc;
574     lplpD3DDevice->ddSwDesc = desc;
575
576     TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
577     
578     return D3D_OK;
579 }
580
581 HRESULT WINAPI
582 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
583                                                LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
584                                                LPVOID lpArg)
585 {
586     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
587     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
588     return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
589 }
590
591 HRESULT WINAPI
592 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
593                                                LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
594                                                LPVOID lpArg)
595 {
596     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
597     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
598     return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
599 }
600
601 HRESULT WINAPI
602 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
603                                               D3DRENDERSTATETYPE dwRenderStateType,
604                                               DWORD dwRenderState)
605 {
606     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
607     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
608
609     /* Call the render state functions */
610     store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
611     set_render_state(This, dwRenderStateType, &This->state_block);
612
613     return DD_OK;
614 }
615
616 HRESULT WINAPI
617 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
618                                               D3DRENDERSTATETYPE dwRenderStateType,
619                                               LPDWORD lpdwRenderState)
620 {
621     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
622     TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
623
624     /* Call the render state functions */
625     get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
626
627     TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
628
629     return DD_OK;
630 }
631
632 HRESULT WINAPI
633 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
634                                           D3DLIGHTSTATETYPE dwLightStateType,
635                                           DWORD dwLightState)
636 {
637     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
638     
639     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
640
641     if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
642         TRACE("Unexpected Light State Type\n");
643         return DDERR_INVALIDPARAMS;
644         
645     if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
646         IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
647
648         if (mat != NULL) {
649             mat->activate(mat);
650         } else {
651             ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
652         }
653     } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
654         switch (dwLightState) {
655             case D3DCOLOR_MONO:
656                ERR("DDCOLOR_MONO should not happen!\n");
657                break;
658             case D3DCOLOR_RGB:
659                /* We are already in this mode */
660                break;
661             default:
662                ERR("Unknown color model!\n");
663                break;
664         }
665     } else {
666         D3DRENDERSTATETYPE rs;
667         switch (dwLightStateType) {
668
669             case D3DLIGHTSTATE_AMBIENT:       /* 2 */
670                 rs = D3DRENDERSTATE_AMBIENT;
671                 break;          
672             case D3DLIGHTSTATE_FOGMODE:       /* 4 */
673                 rs = D3DRENDERSTATE_FOGVERTEXMODE;
674                 break;
675             case D3DLIGHTSTATE_FOGSTART:      /* 5 */
676                 rs = D3DRENDERSTATE_FOGSTART;
677                 break;
678             case D3DLIGHTSTATE_FOGEND:        /* 6 */
679                 rs = D3DRENDERSTATE_FOGEND;
680                 break;
681             case D3DLIGHTSTATE_FOGDENSITY:    /* 7 */
682                 rs = D3DRENDERSTATE_FOGDENSITY;
683                 break;
684             case D3DLIGHTSTATE_COLORVERTEX:   /* 8 */
685                 rs = D3DRENDERSTATE_COLORVERTEX;
686                 break;
687             default:
688                 break;
689         }
690
691         IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
692                                         rs,dwLightState);
693     }
694
695     return DD_OK;
696 }
697
698 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
699 {
700     switch (d3dpt) {
701         case D3DPT_POINTLIST:
702             TRACE("Start POINTS\n");
703             glBegin(GL_POINTS);
704             break;
705
706         case D3DPT_LINELIST:
707             TRACE("Start LINES\n");
708             glBegin(GL_LINES);
709             break;
710
711         case D3DPT_LINESTRIP:
712             TRACE("Start LINE_STRIP\n");
713             glBegin(GL_LINE_STRIP);
714             break;
715
716         case D3DPT_TRIANGLELIST:
717             TRACE("Start TRIANGLES\n");
718             glBegin(GL_TRIANGLES);
719             break;
720
721         case D3DPT_TRIANGLESTRIP:
722             TRACE("Start TRIANGLE_STRIP\n");
723             glBegin(GL_TRIANGLE_STRIP);
724             break;
725
726         case D3DPT_TRIANGLEFAN:
727             TRACE("Start TRIANGLE_FAN\n");
728             glBegin(GL_TRIANGLE_FAN);
729             break;
730
731         default:
732             FIXME("Unhandled primitive %08x\n", d3dpt);
733             break;
734     }
735 }
736
737 /* This function calculate the Z coordinate from Zproj */ 
738 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
739 {
740     float a,b,c,d;
741     /* Assume that X = Y = 0 and W = 1 */
742     a = This->proj_mat->_33;
743     b = This->proj_mat->_34;
744     c = This->proj_mat->_43;
745     d = This->proj_mat->_44;
746     /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
747      * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
748      * And finally Z = (d * Zproj - c) / (a - b * Zproj)
749      */
750     return (d*Zproj - c) / (a - b*Zproj);
751 }
752
753 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
754     int i;
755     
756     TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
757     
758     for (i = 0; i < 3; i++) {
759         BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
760         DWORD elt;
761         for (elt = 0; elt < 0x10000; elt++) {
762             /* We apply the fog transformation and cache the result */
763             DWORD fog_intensity = elt & 0xFF;
764             DWORD vertex_color = (elt >> 8) & 0xFF;
765             fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
766         }
767     }
768 }
769
770 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
771                                            BOOLEAN vertex_transformed,
772                                            BOOLEAN vertex_lit) {
773     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
774   
775     /* Puts GL in the correct lighting / transformation mode */
776     if ((vertex_transformed == FALSE) && 
777         (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
778         /* Need to put the correct transformation again if we go from Transformed
779            vertices to non-transformed ones.
780         */
781         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
782                            This->world_mat, This->view_mat, This->proj_mat);
783         glThis->transform_state = GL_TRANSFORM_NORMAL;
784
785     } else if ((vertex_transformed == TRUE) &&
786                (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
787         /* Set our orthographic projection */
788         glThis->transform_state = GL_TRANSFORM_ORTHO;
789         d3ddevice_set_ortho(This);
790     }
791
792     /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
793              if no fogging state change occured */
794     if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
795         if (vertex_transformed == TRUE) {
796             glDisable(GL_FOG);
797             /* Now check if our fog_table still corresponds to the current vertex color.
798                Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
799             if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  0) & 0xFF)) ||
800                 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >>  8) & 0xFF)) ||
801                 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
802                 /* We need to rebuild our fog table.... */
803                 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
804             }
805         } else {
806             if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
807                 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
808                     case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break; 
809                     case D3DFOG_EXP:    glFogi(GL_FOG_MODE, GL_EXP); break; 
810                     case D3DFOG_EXP2:   glFogi(GL_FOG_MODE, GL_EXP2); break;
811                 }
812                 if (vertex_lit == FALSE) {
813                     glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
814                     glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
815                 } else {
816                     /* Special case of 'pixel fog' */
817                     glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
818                     glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
819                 }
820                 glEnable(GL_FOG);
821             } else {
822                 glDisable(GL_FOG);
823             }
824         }
825     } else {
826         glDisable(GL_FOG);
827     }
828     
829     /* Handle the 'no-normal' case */
830     if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
831         glEnable(GL_LIGHTING);
832     else 
833         glDisable(GL_LIGHTING);
834
835     /* Handle the code for pre-vertex material properties */
836     if (vertex_transformed == FALSE) {
837         if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
838             (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
839             if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
840                 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
841                 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
842                 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
843                 glEnable(GL_COLOR_MATERIAL);
844             }
845         }
846     }
847 }
848
849
850 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
851                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
852 {
853     D3DDRAWPRIMITIVESTRIDEDDATA strided;
854
855     switch (d3dvt) {
856         case D3DVT_VERTEX: {
857             strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
858             strided.position.dwStride = sizeof(D3DVERTEX);
859             strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
860             strided.normal.dwStride = sizeof(D3DVERTEX);
861             strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
862             strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
863             draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
864         } break;
865
866         case D3DVT_LVERTEX: {
867             strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
868             strided.position.dwStride = sizeof(D3DLVERTEX);
869             strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
870             strided.diffuse.dwStride = sizeof(D3DLVERTEX);
871             strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
872             strided.specular.dwStride = sizeof(D3DLVERTEX);
873             strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
874             strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
875             draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
876         } break;
877
878         case D3DVT_TLVERTEX: {
879             strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
880             strided.position.dwStride = sizeof(D3DTLVERTEX);
881             strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
882             strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
883             strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
884             strided.specular.dwStride = sizeof(D3DTLVERTEX);
885             strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
886             strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
887             draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
888         } break;
889
890         default:
891             FIXME("Unhandled vertex type %08x\n", d3dvt);
892             break;
893     }
894 }
895
896 HRESULT WINAPI
897 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
898                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
899                                        D3DVERTEXTYPE d3dvtVertexType,
900                                        LPVOID lpvVertices,
901                                        DWORD dwVertexCount,
902                                        DWORD dwFlags)
903 {
904     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
905
906     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
907     if (TRACE_ON(ddraw)) {
908         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
909     }
910
911     draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
912                    
913     return DD_OK;
914 }
915
916 HRESULT WINAPI
917 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
918                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
919                                               D3DVERTEXTYPE d3dvtVertexType,
920                                               LPVOID lpvVertices,
921                                               DWORD dwVertexCount,
922                                               LPWORD dwIndices,
923                                               DWORD dwIndexCount,
924                                               DWORD dwFlags)
925 {
926     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
927     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
928     if (TRACE_ON(ddraw)) {
929         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
930     }
931
932     draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
933     
934     return DD_OK;
935 }
936
937 HRESULT WINAPI
938 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
939                                              LPD3DEXECUTEBUFFERDESC lpDesc,
940                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
941                                              IUnknown* pUnkOuter)
942 {
943     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
944     IDirect3DExecuteBufferImpl *ret;
945     HRESULT ret_value;
946     
947     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
948
949     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
950     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
951
952     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
953     
954     return ret_value;
955 }
956
957 /* These are the various handler used in the generic path */
958 inline static void handle_xyz(D3DVALUE *coords) {
959     glVertex3fv(coords);
960 }
961 inline static void handle_xyzrhw(D3DVALUE *coords) {
962     if (coords[3] < 1e-8)
963         glVertex3fv(coords);
964     else {
965         GLfloat w = 1.0 / coords[3];
966         
967         glVertex4f(coords[0] * w,
968                    coords[1] * w,
969                    coords[2] * w,
970                    w);
971     }
972 }
973 inline static void handle_normal(D3DVALUE *coords) {
974     glNormal3fv(coords);
975 }
976
977 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
978     if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
979         (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
980         glColor4ub((*color >> 16) & 0xFF,
981                    (*color >>  8) & 0xFF,
982                    (*color >>  0) & 0xFF,
983                    (*color >> 24) & 0xFF);
984     } else {
985         glColor3ub((*color >> 16) & 0xFF,
986                    (*color >>  8) & 0xFF,
987                    (*color >>  0) & 0xFF);    
988     }
989 }
990
991 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
992     glColor4ub((*color >> 16) & 0xFF,
993                (*color >>  8) & 0xFF,
994                (*color >>  0) & 0xFF,
995                (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
996 }
997
998 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
999     if ((lighted == FALSE) &&
1000         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1001         (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1002         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1003             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1004             handle_diffuse_base(sb, color);
1005         }
1006         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1007             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1008             handle_diffuse_base(sb, color);
1009         }
1010         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1011             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1012             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1013             handle_diffuse_base(sb, color);
1014         }
1015         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1016             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1017             handle_diffuse_base(sb, color);
1018         }
1019     } else {
1020         handle_diffuse_base(sb, color);
1021     }    
1022 }
1023
1024 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1025     if ((lighted == FALSE) &&
1026         (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1027         (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1028         if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1029             glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1030             handle_specular_base(sb, color);
1031         }
1032         if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1033             glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1034             handle_specular_base(sb, color);
1035         }
1036         if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1037             (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1038             glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1039             handle_specular_base(sb, color);
1040         }
1041         if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1042             glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1043             handle_specular_base(sb, color);
1044         }
1045     }
1046     /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1047 }
1048
1049 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1050     if (lighted == TRUE) {
1051         DWORD color = *color_d;
1052         if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1053             /* Special case where the specular value is used to do fogging */
1054             BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1055             color &= 0xFF000000; /* Only keep the alpha component */
1056             color |= fog_table[((*color_d >>  0) & 0xFF) << 8 | fog_intensity] <<  0;
1057             color |= fog_table[((*color_d >>  8) & 0xFF) << 8 | fog_intensity] <<  8;
1058             color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1059         }
1060         if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1061             /* Standard specular value in transformed mode. TODO */
1062         }
1063         handle_diffuse_base(sb, &color);
1064     } else {
1065         if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1066             handle_diffuse(sb, color_d, FALSE);
1067             handle_specular(sb, color_s, FALSE);
1068         } else {
1069             /* In that case, only put the diffuse color... */
1070             handle_diffuse_base(sb, color_d);
1071         }
1072     }
1073 }
1074
1075 inline static void handle_texture(D3DVALUE *coords) {
1076     glTexCoord2fv(coords);
1077 }
1078 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1079     /* For the moment, draw only the first texture.. */
1080     if (tex_index == 0) glTexCoord2fv(coords);
1081 }
1082
1083 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1084                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1085                                    DWORD d3dvtVertexType,
1086                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1087                                    DWORD dwVertexCount,
1088                                    LPWORD dwIndices,
1089                                    DWORD dwIndexCount,
1090                                    DWORD dwFlags)
1091 {
1092     BOOLEAN vertex_lighted = FALSE;
1093     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1094     int num_active_stages = 0;
1095
1096     /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1097     if (TRACE_ON(ddraw)) {
1098         TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1099     }
1100
1101     /* This is to prevent 'thread contention' between a thread locking the device and another
1102        doing 3D display on it... */
1103     EnterCriticalSection(&(This->crit));   
1104     
1105     ENTER_GL();
1106     if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1107         This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1108     }
1109
1110     glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1111     
1112     /* Just a hack for now.. Will have to find better algorithm :-/ */
1113     if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1114         vertex_lighted = TRUE;
1115     } else {
1116         if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1117     }
1118     
1119     /* Compute the number of active texture stages and set the various texture parameters */
1120     num_active_stages = draw_primitive_handle_textures(This);
1121
1122     draw_primitive_handle_GL_state(This,
1123                                    (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1124                                    vertex_lighted);
1125     draw_primitive_start_GL(d3dptPrimitiveType);
1126
1127     /* Some fast paths first before the generic case.... */
1128     if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1129         int index;
1130         
1131         for (index = 0; index < dwIndexCount; index++) {
1132             int i = (dwIndices == NULL) ? index : dwIndices[index];
1133             D3DVALUE *normal = 
1134               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1135             D3DVALUE *tex_coord =
1136               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1137             D3DVALUE *position =
1138               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1139             
1140             handle_normal(normal);
1141             handle_texture(tex_coord);
1142             handle_xyz(position);
1143             
1144             TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1145                                position[0], position[1], position[2],
1146                                normal[0], normal[1], normal[2],
1147                                tex_coord[0], tex_coord[1]);
1148         }
1149     } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1150         int index;
1151         
1152         for (index = 0; index < dwIndexCount; index++) {
1153             int i = (dwIndices == NULL) ? index : dwIndices[index];
1154             DWORD *color_d = 
1155               (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1156             DWORD *color_s = 
1157               (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1158             D3DVALUE *tex_coord =
1159               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1160             D3DVALUE *position =
1161               (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1162
1163             handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1164             handle_texture(tex_coord);
1165             handle_xyzrhw(position);
1166
1167             TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1168                                position[0], position[1], position[2], position[3], 
1169                                (*color_d >> 16) & 0xFF,
1170                                (*color_d >>  8) & 0xFF,
1171                                (*color_d >>  0) & 0xFF,
1172                                (*color_d >> 24) & 0xFF,
1173                                (*color_s >> 16) & 0xFF,
1174                                (*color_s >>  8) & 0xFF,
1175                                (*color_s >>  0) & 0xFF,
1176                                (*color_s >> 24) & 0xFF,
1177                                tex_coord[0], tex_coord[1]);
1178         } 
1179     } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1180                ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1181         /* This is the 'slow path' but that should support all possible vertex formats out there...
1182            Note that people should write a fast path for all vertex formats out there...
1183         */  
1184         int index;
1185         int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1186         static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1187           
1188         for (index = 0; index < dwIndexCount; index++) {
1189             int i = (dwIndices == NULL) ? index : dwIndices[index];
1190             int tex_stage;
1191
1192             if (d3dvtVertexType & D3DFVF_NORMAL) { 
1193                 D3DVALUE *normal = 
1194                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);         
1195                 handle_normal(normal);
1196             }
1197             if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1198                 DWORD *color_d = 
1199                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1200                 DWORD *color_s = 
1201                   (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1202                 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1203             } else {
1204                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1205                     DWORD *color_s = 
1206                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1207                     handle_specular(&(This->state_block), color_s, vertex_lighted);
1208                 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1209                     DWORD *color_d = 
1210                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1211                     handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1212                 }
1213             }
1214
1215             for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1216                 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF0000;
1217                 if (tex_index >= num_tex_index) {
1218                     handle_textures((D3DVALUE *) no_index, tex_stage);
1219                  } else {
1220                      D3DVALUE *tex_coord =
1221                        (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1222                                      i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1223                      handle_textures(tex_coord, tex_stage);
1224                 }
1225             }
1226             
1227             if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1228                 D3DVALUE *position =
1229                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1230                 handle_xyz(position);
1231             } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1232                 D3DVALUE *position =
1233                   (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1234                 handle_xyzrhw(position);
1235             }
1236
1237             if (TRACE_ON(ddraw_geom)) {
1238                 int tex_index;
1239
1240                 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1241                     D3DVALUE *position =
1242                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1243                     TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1244                 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1245                     D3DVALUE *position =
1246                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1247                     TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1248                 }
1249                 if (d3dvtVertexType & D3DFVF_NORMAL) { 
1250                     D3DVALUE *normal = 
1251                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);     
1252                     TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1253                 }
1254                 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1255                     DWORD *color_d = 
1256                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1257                     TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1258                                        (*color_d >> 16) & 0xFF,
1259                                        (*color_d >>  8) & 0xFF,
1260                                        (*color_d >>  0) & 0xFF,
1261                                        (*color_d >> 24) & 0xFF);
1262                 }
1263                 if (d3dvtVertexType & D3DFVF_SPECULAR) { 
1264                     DWORD *color_s = 
1265                       (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1266                     TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1267                                        (*color_s >> 16) & 0xFF,
1268                                        (*color_s >>  8) & 0xFF,
1269                                        (*color_s >>  0) & 0xFF,
1270                                        (*color_s >> 24) & 0xFF);
1271                 }
1272                 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1273                     D3DVALUE *tex_coord =
1274                       (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) + 
1275                                     i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1276                     TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1277                 }
1278                 TRACE_(ddraw_geom)("\n");
1279             }
1280         }
1281     } else {
1282         ERR(" matrix weighting not handled yet....\n");
1283     }
1284     
1285     glEnd();
1286
1287     /* Whatever the case, disable the color material stuff */
1288     glDisable(GL_COLOR_MATERIAL);
1289
1290     LEAVE_GL();
1291     TRACE("End\n");    
1292
1293     LeaveCriticalSection(&(This->crit));
1294 }
1295
1296 HRESULT WINAPI
1297 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1298                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1299                                           DWORD d3dvtVertexType,
1300                                           LPVOID lpvVertices,
1301                                           DWORD dwVertexCount,
1302                                           DWORD dwFlags)
1303 {
1304     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1305     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1306
1307     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1308     if (TRACE_ON(ddraw)) {
1309         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1310     }
1311
1312     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1313     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1314     
1315     return DD_OK;
1316 }
1317
1318 HRESULT WINAPI
1319 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1320                                                  D3DPRIMITIVETYPE d3dptPrimitiveType,
1321                                                  DWORD d3dvtVertexType,
1322                                                  LPVOID lpvVertices,
1323                                                  DWORD dwVertexCount,
1324                                                  LPWORD dwIndices,
1325                                                  DWORD dwIndexCount,
1326                                                  DWORD dwFlags)
1327 {
1328     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1329     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1330
1331     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1332     if (TRACE_ON(ddraw)) {
1333         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1334     }
1335
1336     convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1337     draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1338     
1339     return DD_OK;
1340 }
1341
1342 HRESULT WINAPI
1343 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1344                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1345                                                    DWORD dwVertexType,
1346                                                    LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1347                                                    DWORD dwVertexCount,
1348                                                    DWORD dwFlags)
1349 {
1350     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1351
1352     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1353     if (TRACE_ON(ddraw)) {
1354         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1355     }
1356     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1357
1358     return DD_OK;
1359 }
1360
1361 HRESULT WINAPI
1362 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1363                                                           D3DPRIMITIVETYPE d3dptPrimitiveType,
1364                                                           DWORD dwVertexType,
1365                                                           LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1366                                                           DWORD dwVertexCount,
1367                                                           LPWORD lpIndex,
1368                                                           DWORD dwIndexCount,
1369                                                           DWORD dwFlags)
1370 {
1371     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1372
1373     TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1374     if (TRACE_ON(ddraw)) {
1375         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1376     }
1377
1378     draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1379
1380     return DD_OK;
1381 }
1382
1383 HRESULT WINAPI
1384 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1385                                             D3DPRIMITIVETYPE d3dptPrimitiveType,
1386                                             LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1387                                             DWORD dwStartVertex,
1388                                             DWORD dwNumVertices,
1389                                             DWORD dwFlags)
1390 {
1391     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1392     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1393     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1394
1395     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1396     if (TRACE_ON(ddraw)) {
1397         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1398     }
1399
1400     if (vb_impl->processed == TRUE) {
1401         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1402         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1403
1404         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1405         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1406                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1407
1408         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1409         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1410
1411     } else {
1412         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1413         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1414     }
1415
1416     return DD_OK;
1417 }
1418
1419 HRESULT WINAPI
1420 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1421                                                    D3DPRIMITIVETYPE d3dptPrimitiveType,
1422                                                    LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1423                                                    DWORD dwStartVertex,
1424                                                    DWORD dwNumVertices,
1425                                                    LPWORD lpwIndices,
1426                                                    DWORD dwIndexCount,
1427                                                    DWORD dwFlags)
1428 {
1429     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1430     IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1431     D3DDRAWPRIMITIVESTRIDEDDATA strided;
1432     
1433     TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1434     if (TRACE_ON(ddraw)) {
1435         TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1436     }
1437
1438     if (vb_impl->processed == TRUE) {
1439         IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1440         IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1441
1442         glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1443         This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1444                            &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1445
1446         convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1447         draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1448
1449     } else {
1450         convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1451         draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1452     }
1453
1454     return DD_OK;
1455 }
1456
1457 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1458 static BOOLEAN
1459 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1460 {
1461     BOOLEAN is_complement = FALSE;
1462     BOOLEAN is_alpha_replicate = FALSE;
1463     BOOLEAN handled = TRUE;
1464     GLenum src;
1465     BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1466     int num;
1467     
1468     if (is_color) {
1469         if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1470         else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1471         else {
1472             handled = FALSE;
1473             num = 0;
1474         }
1475         if (tex_op == D3DTOP_SELECTARG2) {
1476             num = 1 - num;
1477         }
1478     } else {
1479         if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1480         else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1481         else {
1482             handled = FALSE;
1483             num = 0;
1484         }
1485         if (tex_op == D3DTOP_SELECTARG2) {
1486             num = 1 - num;
1487         }
1488     }
1489     
1490     if (dwState & D3DTA_COMPLEMENT) {
1491         is_complement = TRUE;
1492     }
1493     if (dwState & D3DTA_ALPHAREPLICATE) {
1494         is_alpha_replicate = TRUE;
1495     }
1496     dwState &= D3DTA_SELECTMASK;
1497     if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1498         dwState = D3DTA_DIFFUSE;
1499     }
1500
1501     switch (dwState) {
1502         case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1503         case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1504         case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1505         case D3DTA_TFACTOR: {
1506             /* Get the constant value from the current rendering state */
1507             GLfloat color[4];
1508             DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1509             
1510             color[0] = ((col >> 16) & 0xFF) / 255.0f;
1511             color[1] = ((col >>  8) & 0xFF) / 255.0f;
1512             color[2] = ((col >>  0) & 0xFF) / 255.0f;
1513             color[3] = ((col >> 24) & 0xFF) / 255.0f;
1514             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1515             
1516             src = GL_CONSTANT_EXT;
1517         } break;
1518         default: src = GL_TEXTURE; handled = FALSE; break;
1519     }
1520
1521     if (is_color) {
1522         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1523         if (is_alpha_replicate) {
1524             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1525         } else {
1526             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1527         }
1528     } else {
1529         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1530         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1531     }
1532
1533     return handled;
1534 }
1535
1536 HRESULT WINAPI
1537 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1538                                                  DWORD dwStage,
1539                                                  D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1540                                                  DWORD dwState)
1541 {
1542     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1543     const char *type;
1544     DWORD prev_state;
1545     
1546     TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1547
1548     if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1549
1550     switch (d3dTexStageStateType) {
1551 #define GEN_CASE(a) case a: type = #a; break
1552         GEN_CASE(D3DTSS_COLOROP);
1553         GEN_CASE(D3DTSS_COLORARG1);
1554         GEN_CASE(D3DTSS_COLORARG2);
1555         GEN_CASE(D3DTSS_ALPHAOP);
1556         GEN_CASE(D3DTSS_ALPHAARG1);
1557         GEN_CASE(D3DTSS_ALPHAARG2);
1558         GEN_CASE(D3DTSS_BUMPENVMAT00);
1559         GEN_CASE(D3DTSS_BUMPENVMAT01);
1560         GEN_CASE(D3DTSS_BUMPENVMAT10);
1561         GEN_CASE(D3DTSS_BUMPENVMAT11);
1562         GEN_CASE(D3DTSS_TEXCOORDINDEX);
1563         GEN_CASE(D3DTSS_ADDRESS);
1564         GEN_CASE(D3DTSS_ADDRESSU);
1565         GEN_CASE(D3DTSS_ADDRESSV);
1566         GEN_CASE(D3DTSS_BORDERCOLOR);
1567         GEN_CASE(D3DTSS_MAGFILTER);
1568         GEN_CASE(D3DTSS_MINFILTER);
1569         GEN_CASE(D3DTSS_MIPFILTER);
1570         GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1571         GEN_CASE(D3DTSS_MAXMIPLEVEL);
1572         GEN_CASE(D3DTSS_MAXANISOTROPY);
1573         GEN_CASE(D3DTSS_BUMPENVLSCALE);
1574         GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1575         GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1576 #undef GEN_CASE
1577         default: type = "UNKNOWN";
1578     }
1579
1580     /* Store the values in the state array */
1581     prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1582     This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1583     /* Some special cases when one state modifies more than one... */
1584     if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1585         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1586         This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1587     }
1588
1589     ENTER_GL();
1590     
1591     switch (d3dTexStageStateType) {
1592         case D3DTSS_MINFILTER:
1593         case D3DTSS_MIPFILTER:
1594             if (TRACE_ON(ddraw)) {
1595                 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1596                     switch ((D3DTEXTUREMINFILTER) dwState) {
1597                         case D3DTFN_POINT:  TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1598                         case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1599                         default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1600                     }
1601                 } else {
1602                     switch ((D3DTEXTUREMIPFILTER) dwState) {
1603                         case D3DTFP_NONE:   TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1604                         case D3DTFP_POINT:  TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1605                         case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1606                         default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1607                     }
1608                 }
1609             }
1610             break;
1611             
1612         case D3DTSS_MAGFILTER:
1613             if (TRACE_ON(ddraw)) {
1614                 switch ((D3DTEXTUREMAGFILTER) dwState) {
1615                     case D3DTFG_POINT:  TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1616                     case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1617                     default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1618                 }
1619             }
1620             break;
1621
1622         case D3DTSS_ADDRESS:
1623         case D3DTSS_ADDRESSU:
1624         case D3DTSS_ADDRESSV: {
1625             switch ((D3DTEXTUREADDRESS) dwState) {
1626                 case D3DTADDRESS_WRAP:   TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1627                 case D3DTADDRESS_CLAMP:  TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1628                 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1629 #if defined(GL_VERSION_1_4)
1630                 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1631 #elif defined(GL_ARB_texture_mirrored_repeat)
1632                 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1633 #endif
1634                 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1635             }
1636         } break;
1637
1638         case D3DTSS_ALPHAOP:
1639         case D3DTSS_COLOROP: {
1640             int scale = 1;
1641             GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1642             const char *value;
1643             int handled = 1;
1644             
1645             switch (dwState) {
1646 #define GEN_CASE(a) case a: value = #a; break
1647                 GEN_CASE(D3DTOP_DISABLE);
1648                 GEN_CASE(D3DTOP_SELECTARG1);
1649                 GEN_CASE(D3DTOP_SELECTARG2);
1650                 GEN_CASE(D3DTOP_MODULATE);
1651                 GEN_CASE(D3DTOP_MODULATE2X);
1652                 GEN_CASE(D3DTOP_MODULATE4X);
1653                 GEN_CASE(D3DTOP_ADD);
1654                 GEN_CASE(D3DTOP_ADDSIGNED);
1655                 GEN_CASE(D3DTOP_ADDSIGNED2X);
1656                 GEN_CASE(D3DTOP_SUBTRACT);
1657                 GEN_CASE(D3DTOP_ADDSMOOTH);
1658                 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1659                 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1660                 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1661                 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1662                 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1663                 GEN_CASE(D3DTOP_PREMODULATE);
1664                 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1665                 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1666                 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1667                 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1668                 GEN_CASE(D3DTOP_BUMPENVMAP);
1669                 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1670                 GEN_CASE(D3DTOP_DOTPRODUCT3);
1671                 GEN_CASE(D3DTOP_FORCE_DWORD);
1672 #undef GEN_CASE
1673                 default: value = "UNKNOWN";
1674             }
1675
1676             if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1677                 glDisable(GL_TEXTURE_2D);
1678                 TRACE(" disabling 2D texturing.\n");
1679             } else {
1680                 /* Re-enable texturing */
1681                 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1682                     glEnable(GL_TEXTURE_2D);
1683                     TRACE(" enabling 2D texturing.\n");
1684                 }
1685                 
1686                 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1687                 if (dwState != D3DTOP_DISABLE) {
1688                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1689                 }
1690
1691                 /* Now set up the operand correctly */
1692                 switch (dwState) {
1693                     case D3DTOP_DISABLE:
1694                         /* Contrary to the docs, alpha can be disabled when colorop is enabled
1695                            and it works, so ignore this op */
1696                         TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1697                         break;
1698
1699                     case D3DTOP_SELECTARG1:
1700                     case D3DTOP_SELECTARG2:
1701                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1702                         break;
1703                         
1704                     case D3DTOP_MODULATE4X:
1705                         scale = scale * 2;  /* Drop through */
1706                     case D3DTOP_MODULATE2X:
1707                         scale = scale * 2;  /* Drop through */
1708                     case D3DTOP_MODULATE:
1709                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1710                         break;
1711
1712                     case D3DTOP_ADD:
1713                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1714                         break;
1715
1716                     case D3DTOP_ADDSIGNED2X:
1717                         scale = scale * 2;  /* Drop through */
1718                     case D3DTOP_ADDSIGNED:
1719                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1720                         break;
1721
1722                         /* For the four blending modes, use the Arg2 parameter */
1723                     case D3DTOP_BLENDDIFFUSEALPHA:
1724                     case D3DTOP_BLENDTEXTUREALPHA:
1725                     case D3DTOP_BLENDFACTORALPHA:
1726                     case D3DTOP_BLENDCURRENTALPHA: {
1727                         GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1728
1729                         switch (dwState) {
1730                             case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1731                             case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1732                             case D3DTOP_BLENDFACTORALPHA:  src = GL_CONSTANT_EXT;
1733                             case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1734                         }
1735                         
1736                         glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1737                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1738                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1739                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1740                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1741                     } break;
1742                         
1743                     default:
1744                         handled = FALSE;
1745                         break;
1746                 }
1747             }
1748
1749             if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1750                 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1751                 /* Switch the arguments if needed... */
1752                 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1753                     handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1754                                             This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1755                                             dwState);
1756                     handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1757                                             This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1758                                             dwState);
1759                 } else {
1760                     handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1761                                             This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1762                                             dwState);
1763                     handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1764                                             This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1765                                             dwState);
1766                 }
1767             }
1768             
1769             if (handled) {
1770                 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1771                     glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1772                 } else {
1773                     glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1774                 }                       
1775                 TRACE(" Stage type is : %s => %s\n", type, value);
1776             } else {
1777                 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1778             }
1779         } break;
1780
1781         case D3DTSS_COLORARG1:
1782         case D3DTSS_COLORARG2:
1783         case D3DTSS_ALPHAARG1:
1784         case D3DTSS_ALPHAARG2: {
1785             const char *value, *value_comp = "", *value_alpha = "";
1786             BOOLEAN handled;
1787             D3DTEXTUREOP tex_op;
1788             
1789             switch (dwState & D3DTA_SELECTMASK) {
1790 #define GEN_CASE(a) case a: value = #a; break
1791                 GEN_CASE(D3DTA_DIFFUSE);
1792                 GEN_CASE(D3DTA_CURRENT);
1793                 GEN_CASE(D3DTA_TEXTURE);
1794                 GEN_CASE(D3DTA_TFACTOR);
1795                 GEN_CASE(D3DTA_SPECULAR);
1796 #undef GEN_CASE
1797                 default: value = "UNKNOWN";
1798             }
1799             if (dwState & D3DTA_COMPLEMENT) {
1800                 value_comp = " | D3DTA_COMPLEMENT";
1801             }
1802             if (dwState & D3DTA_ALPHAREPLICATE) {
1803                 value_alpha = " | D3DTA_ALPHAREPLICATE";
1804             }
1805
1806             if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1807                 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1808             } else {
1809                 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1810             }
1811             
1812             handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1813             
1814             if (handled) {
1815                 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1816             } else {
1817                 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1818             }
1819         } break;
1820
1821         case D3DTSS_MIPMAPLODBIAS: {
1822             D3DVALUE value = *((D3DVALUE *) &dwState);
1823             BOOLEAN handled = TRUE;
1824             
1825             if (value != 0.0)
1826                 handled = FALSE;
1827
1828             if (handled) {
1829                 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1830             } else {
1831                 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1832             }
1833         } break;
1834
1835         case D3DTSS_MAXMIPLEVEL: 
1836             TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1837             break;
1838
1839         case D3DTSS_BORDERCOLOR:
1840             TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1841                   ((dwState >> 16) & 0xFF),
1842                   ((dwState >>  8) & 0xFF),
1843                   ((dwState >>  0) & 0xFF),
1844                   ((dwState >> 24) & 0xFF));
1845             break;
1846             
1847         case D3DTSS_TEXCOORDINDEX: {
1848             BOOLEAN handled = TRUE;
1849             const char *value;
1850             
1851             switch (dwState & 0xFFFF0000) {
1852 #define GEN_CASE(a) case a: value = #a; break
1853                 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1854                 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1855                 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1856                 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1857 #undef GEN_CASE
1858                 default: value = "UNKNOWN";
1859             }
1860             if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1861                 handled = FALSE;
1862
1863             if (handled) {
1864                 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1865             } else {
1866                 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1867             }
1868         } break;
1869             
1870         case D3DTSS_TEXTURETRANSFORMFLAGS: {
1871             const char *projected = "", *value;
1872             BOOLEAN handled = TRUE;
1873             switch (dwState & 0xFF) {
1874 #define GEN_CASE(a) case a: value = #a; break
1875                 GEN_CASE(D3DTTFF_DISABLE);
1876                 GEN_CASE(D3DTTFF_COUNT1);
1877                 GEN_CASE(D3DTTFF_COUNT2);
1878                 GEN_CASE(D3DTTFF_COUNT3);
1879                 GEN_CASE(D3DTTFF_COUNT4);
1880 #undef GEN_CASE
1881                 default: value = "UNKNOWN";
1882             }
1883             if (dwState & D3DTTFF_PROJECTED) {
1884                 projected = " | D3DTTFF_PROJECTED";
1885                 handled = FALSE;
1886             }
1887
1888             if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1889                 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1890             }
1891
1892             if (handled == TRUE) {
1893                 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1894             } else {
1895                 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1896             }
1897         } break;
1898             
1899         default:
1900             FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
1901             break;
1902     }
1903
1904     LEAVE_GL();
1905     
1906     return DD_OK;
1907 }
1908
1909 static DWORD
1910 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
1911 {
1912     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1913     DWORD stage;
1914     
1915     for (stage = 0; stage < MAX_TEXTURES; stage++) {
1916         IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
1917
1918         /* First check if we need to bind any other texture for this stage */
1919         if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
1920             if (This->current_texture[stage] == NULL) {
1921                 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
1922                 glBindTexture(GL_TEXTURE_2D, 0);
1923                 glDisable(GL_TEXTURE_2D);
1924             } else {
1925                 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
1926                 
1927                 if (glThis->current_bound_texture[stage] == NULL) {
1928                     if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
1929                         TRACE(" enabling 2D texturing and");
1930                         glEnable(GL_TEXTURE_2D);
1931                     }
1932                 }
1933                 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
1934                 glBindTexture(GL_TEXTURE_2D, tex_name);
1935             }
1936
1937             glThis->current_bound_texture[stage] = This->current_texture[stage];
1938         } else {
1939             if (glThis->current_bound_texture[stage] == NULL) {
1940                 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
1941             } else {
1942                 TRACE(" using already bound texture id %d for stage %ld.\n",
1943                       ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
1944             }
1945         }
1946
1947         /* If no texure valid for this stage, go out of the loop */
1948         if (This->current_texture[stage] == NULL) break;
1949
1950         /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
1951            This will also update the various texture parameters if needed.
1952         */
1953         gltex_upload_texture(surf_ptr, This, stage);
1954     }
1955
1956     return stage;
1957 }
1958
1959 HRESULT WINAPI
1960 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1961                                        DWORD dwStage,
1962                                        LPDIRECTDRAWSURFACE7 lpTexture2)
1963 {
1964     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1965     
1966     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1967     
1968     if (dwStage > 0) return DD_OK;
1969
1970     if (This->current_texture[dwStage] != NULL) {
1971         IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
1972     }
1973     
1974     if (lpTexture2 == NULL) {
1975         This->current_texture[dwStage] = NULL;
1976     } else {
1977         IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1978         IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
1979         This->current_texture[dwStage] = tex_impl;
1980     }
1981     
1982     return DD_OK;
1983 }
1984
1985 HRESULT WINAPI
1986 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1987                                  LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1988 {
1989     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1990     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1991
1992     fill_opengl_caps_7(lpD3DHELDevDesc);
1993
1994     TRACE(" returning caps : no dump function yet.\n");
1995
1996     return DD_OK;
1997 }
1998
1999 HRESULT WINAPI
2000 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2001                                      LPD3DMATERIAL7 lpMat)
2002 {
2003     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2004     TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2005     
2006     if (TRACE_ON(ddraw)) {
2007         TRACE(" material is : \n");
2008         dump_D3DMATERIAL7(lpMat);
2009     }
2010     
2011     This->current_material = *lpMat;
2012
2013     ENTER_GL();
2014     glMaterialfv(GL_FRONT_AND_BACK,
2015                  GL_DIFFUSE,
2016                  (float *) &(This->current_material.u.diffuse));
2017     glMaterialfv(GL_FRONT_AND_BACK,
2018                  GL_AMBIENT,
2019                  (float *) &(This->current_material.u1.ambient));
2020     glMaterialfv(GL_FRONT_AND_BACK,
2021                  GL_SPECULAR,
2022                  (float *) &(This->current_material.u2.specular));
2023     glMaterialfv(GL_FRONT_AND_BACK,
2024                  GL_EMISSION,
2025                  (float *) &(This->current_material.u3.emissive));
2026     glMaterialf(GL_FRONT_AND_BACK,
2027                 GL_SHININESS,
2028                 This->current_material.u4.power); /* Not sure about this... */
2029     LEAVE_GL();
2030
2031     return DD_OK;
2032 }
2033
2034
2035 HRESULT WINAPI
2036 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2037                                   DWORD dwLightIndex,
2038                                   LPD3DLIGHT7 lpLight)
2039 {
2040     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2041     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2042     TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2043     
2044     if (TRACE_ON(ddraw)) {
2045         TRACE(" setting light : \n");
2046         dump_D3DLIGHT7(lpLight);
2047     }
2048     
2049     if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2050     This->set_lights |= 0x00000001 << dwLightIndex;
2051     This->light_parameters[dwLightIndex] = *lpLight;
2052
2053     /* Some checks to print out nice warnings :-) */
2054     switch (lpLight->dltType) {
2055         case D3DLIGHT_DIRECTIONAL:
2056         case D3DLIGHT_POINT:
2057             /* These are handled properly... */
2058             break;
2059             
2060         case D3DLIGHT_SPOT:
2061             if ((lpLight->dvTheta != 0.0) ||
2062                 (lpLight->dvTheta != lpLight->dvPhi)) {
2063                 ERR("dvTheta not fully supported yet !\n");
2064             }
2065             break;
2066
2067         default:
2068             ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2069     }
2070     
2071     /* This will force the Light setting on next drawing of primitives */
2072     glThis->transform_state = GL_TRANSFORM_NONE;
2073     
2074     return DD_OK;
2075 }
2076
2077 HRESULT WINAPI
2078 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2079                                      DWORD dwLightIndex,
2080                                      BOOL bEnable)
2081 {
2082     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2083     TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2084     
2085     if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2086
2087     ENTER_GL();
2088     if (bEnable) {
2089         if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2090             /* Set the default parameters.. */
2091             TRACE(" setting default light parameters...\n");
2092             GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2093         }
2094         glEnable(GL_LIGHT0 + dwLightIndex);
2095         if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2096             /* This light gets active... Need to update its parameters to GL before the next drawing */
2097             IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2098             
2099             This->active_lights |= 0x00000001 << dwLightIndex;
2100             glThis->transform_state = GL_TRANSFORM_NONE;
2101         }
2102     } else {
2103         glDisable(GL_LIGHT0 + dwLightIndex);
2104         This->active_lights &= ~(0x00000001 << dwLightIndex);
2105     }
2106     LEAVE_GL();
2107
2108     return DD_OK;
2109 }
2110
2111 HRESULT  WINAPI  
2112 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation) 
2113 {
2114     ICOM_THIS(IDirect3DDeviceImpl,iface);
2115     IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2116
2117     TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2118
2119     if (dwIndex >= This->max_clipping_planes) {
2120         return DDERR_INVALIDPARAMS;
2121     }
2122
2123     TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2124
2125     memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2126     
2127     /* This is to force the reset of the transformation matrices on the next drawing.
2128      * This is needed to use the correct matrices for the various clipping planes.
2129      */
2130     glThis->transform_state = GL_TRANSFORM_NONE;
2131     
2132     return D3D_OK;
2133 }
2134
2135 HRESULT WINAPI
2136 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2137                                      LPD3DVIEWPORT7 lpData)
2138 {
2139     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2140     TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2141
2142     if (TRACE_ON(ddraw)) {
2143         TRACE(" viewport is : \n");
2144         TRACE("    - dwX = %ld   dwY = %ld\n",
2145               lpData->dwX, lpData->dwY);
2146         TRACE("    - dwWidth = %ld   dwHeight = %ld\n",
2147               lpData->dwWidth, lpData->dwHeight);
2148         TRACE("    - dvMinZ = %f   dvMaxZ = %f\n",
2149               lpData->dvMinZ, lpData->dvMaxZ);
2150     }
2151     This->active_viewport = *lpData;
2152
2153     ENTER_GL();
2154     
2155     /* Set the viewport */
2156     glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2157     glViewport(lpData->dwX,
2158                This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2159                lpData->dwWidth, lpData->dwHeight);
2160
2161     LEAVE_GL();
2162     
2163     return DD_OK;
2164 }
2165
2166 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2167 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
2168 #else
2169 # define XCAST(fun)     (void*)
2170 #endif
2171
2172 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2173 {
2174     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2175     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2176     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2177     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2178     XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2179     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2180     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2181     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2182     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2183     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2184     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2185     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2186     XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2187     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2188     XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2189     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2190     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2191     XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2192     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2193     XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2194     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2195     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2196     XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2197     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2198     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2199     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2200     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2201     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2202     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2203     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2204     XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2205     XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2206     XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2207     XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2208     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2209     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2210     XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2211     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2212     XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2213     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2214     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2215     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2216     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2217     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2218     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2219     XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2220     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2221     XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2222     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2223     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2224 };
2225
2226 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2227 #undef XCAST
2228 #endif
2229
2230
2231 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2232 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
2233 #else
2234 # define XCAST(fun)     (void*)
2235 #endif
2236
2237 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2238 {
2239     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2240     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2241     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2242     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2243     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2244     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2245     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2246     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2247     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2248     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2249     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2250     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2251     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2252     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2253     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2254     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2255     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2256     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2257     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2258     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2259     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2260     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2261     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2262     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2263     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2264     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2265     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2266     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2267     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2268     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2269     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2270     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2271     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2272     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2273     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2274     XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2275     XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2276     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2277     XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2278     XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2279     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2280     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2281     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2282 };
2283
2284 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2285 #undef XCAST
2286 #endif
2287
2288
2289 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2290 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
2291 #else
2292 # define XCAST(fun)     (void*)
2293 #endif
2294
2295 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2296 {
2297     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2298     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2299     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2300     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2301     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2302     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2303     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2304     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2305     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2306     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2307     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2308     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2309     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2310     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2311     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2312     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2313     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2314     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2315     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2316     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2317     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2318     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2319     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2320     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2321     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2322     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2323     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2324     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2325     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2326     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2327     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2328     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2329     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2330     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2331 };
2332
2333 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2334 #undef XCAST
2335 #endif
2336
2337
2338 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2339 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
2340 #else
2341 # define XCAST(fun)     (void*)
2342 #endif
2343
2344 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2345 {
2346     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2347     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2348     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2349     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2350     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2351     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2352     XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2353     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2354     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2355     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2356     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2357     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2358     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2359     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2360     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2361     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2362     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2363     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2364     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2365     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2366     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2367     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2368     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2369 };
2370
2371 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2372 #undef XCAST
2373 #endif
2374
2375 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2376                                DWORD dwCount,
2377                                LPD3DRECT lpRects,
2378                                DWORD dwFlags,
2379                                DWORD dwColor,
2380                                D3DVALUE dvZ,
2381                                DWORD dwStencil)
2382 {
2383     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2384     GLboolean ztest;
2385     GLfloat old_z_clear_value;
2386     GLbitfield bitfield = 0;
2387     GLint old_stencil_clear_value;
2388     GLfloat old_color_clear_value[4];
2389     D3DRECT rect;
2390     int i;
2391     
2392     TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2393     if (TRACE_ON(ddraw)) {
2394         if (dwCount > 0) {
2395             int i;
2396             TRACE(" rectangles : \n");
2397             for (i = 0; i < dwCount; i++) {
2398                 TRACE("  - %ld x %ld     %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2399             }
2400         }
2401     }
2402
2403     if (dwCount == 0) {
2404         /* Not sure if this is really needed... */
2405         dwCount = 1;
2406         rect.u1.x1 = 0;
2407         rect.u2.y1 = 0;
2408         rect.u3.x2 = This->surface->surface_desc.dwWidth;
2409         rect.u4.y2 = This->surface->surface_desc.dwHeight;
2410         lpRects = &rect;
2411     }
2412     
2413     /* Clears the screen */
2414     ENTER_GL();
2415
2416     if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
2417         /* TODO: optimize here the case where Clear changes all the screen... */
2418         This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
2419     }
2420     glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
2421
2422     if (dwFlags & D3DCLEAR_ZBUFFER) {
2423         bitfield |= GL_DEPTH_BUFFER_BIT;
2424         glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2425         glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2426         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2427         glClearDepth(dvZ);
2428         TRACE(" depth value : %f\n", dvZ);
2429     }
2430     if (dwFlags & D3DCLEAR_STENCIL) {
2431         bitfield |= GL_STENCIL_BUFFER_BIT;
2432         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2433         glClearStencil(dwStencil);
2434         TRACE(" stencil value : %ld\n", dwStencil);
2435     }    
2436     if (dwFlags & D3DCLEAR_TARGET) {
2437         bitfield |= GL_COLOR_BUFFER_BIT;
2438         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2439         glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2440                      ((dwColor >>  8) & 0xFF) / 255.0,
2441                      ((dwColor >>  0) & 0xFF) / 255.0,
2442                      ((dwColor >> 24) & 0xFF) / 255.0);
2443         TRACE(" color value (ARGB) : %08lx\n", dwColor);
2444     }
2445
2446     glEnable(GL_SCISSOR_TEST); 
2447     for (i = 0; i < dwCount; i++) {
2448         glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2449                   lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2450         glClear(bitfield);
2451     }
2452     glDisable(GL_SCISSOR_TEST); 
2453     
2454     if (dwFlags & D3DCLEAR_ZBUFFER) {
2455         glDepthMask(ztest);
2456         glClearDepth(old_z_clear_value);
2457     }
2458      if (dwFlags & D3DCLEAR_STENCIL) {
2459         bitfield |= GL_STENCIL_BUFFER_BIT;
2460         glClearStencil(old_stencil_clear_value);
2461     }    
2462     if (dwFlags & D3DCLEAR_TARGET) {
2463         bitfield |= GL_COLOR_BUFFER_BIT;
2464         glClearColor(old_color_clear_value[0],
2465                      old_color_clear_value[1],
2466                      old_color_clear_value[2],
2467                      old_color_clear_value[3]);
2468     }
2469     
2470     LEAVE_GL();
2471     
2472     return DD_OK;
2473 }
2474
2475 HRESULT
2476 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2477               LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2478               DWORD dwFlags, LPDDBLTFX lpbltfx)
2479 {
2480     if (dwFlags & DDBLT_COLORFILL) {
2481         /* This is easy to handle for the D3D Device... */
2482         DWORD color;
2483         D3DRECT rect;
2484         GLenum prev_draw;
2485         BOOL is_front;
2486         
2487         /* First check if we BLT to the backbuffer... */
2488         if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2489             is_front = FALSE;
2490         } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2491             is_front = TRUE;
2492         } else {
2493             ERR("Only BLT override to front or back-buffer is supported for now !\n");
2494             return DDERR_INVALIDPARAMS;
2495         }
2496         
2497         /* The color as given in the Blt function is in the format of the frame-buffer...
2498          * 'clear' expect it in ARGB format => we need to do some conversion :-)
2499          */
2500         if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2501             if (This->palette) {
2502                 color = ((0xFF000000) |
2503                          (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2504                          (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2505                          (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2506             } else {
2507                 color = 0xFF000000;
2508             }
2509         } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2510                    (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2511                     (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2512             if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2513                 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2514                 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2515                 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2516                 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2517                     color = 0xFFFFFFFF;
2518                 } else {
2519                     color = ((0xFF000000) |
2520                              ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2521                              ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2522                              ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2523                 }
2524             } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2525                         (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2526                        (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2527                        (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2528                        (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2529                 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2530             } else {
2531                 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2532                 return DDERR_INVALIDPARAMS;
2533             }
2534         } else {
2535             ERR("Wrong surface type for BLT override !\n");
2536             return DDERR_INVALIDPARAMS;
2537         }
2538         
2539         TRACE(" executing D3D Device override.\n");
2540         
2541         if (rdst) {
2542             rect.u1.x1 = rdst->left;
2543             rect.u2.y1 = rdst->top;
2544             rect.u3.x2 = rdst->right;
2545             rect.u4.y2 = rdst->bottom;
2546         }
2547         
2548         ENTER_GL();
2549
2550         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2551         if (is_front)
2552             glDrawBuffer(GL_FRONT);
2553         else
2554             glDrawBuffer(GL_BACK);
2555         
2556         d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2557         
2558         if ((( is_front) && (prev_draw == GL_BACK)) ||
2559             ((!is_front) && (prev_draw == GL_FRONT)))
2560             glDrawBuffer(prev_draw);
2561         
2562         LEAVE_GL();
2563         
2564         return DD_OK;
2565     }
2566     return DDERR_INVALIDPARAMS;
2567 }
2568
2569 HRESULT
2570 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2571                   DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2572                   LPRECT rsrc, DWORD trans)
2573 {
2574      return DDERR_INVALIDPARAMS;
2575 }
2576
2577 void
2578 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2579 {
2580     GLfloat height, width;
2581     GLfloat trans_mat[16];
2582
2583     TRACE("(%p)\n", This);
2584     
2585     width = This->surface->surface_desc.dwWidth;
2586     height = This->surface->surface_desc.dwHeight;
2587     
2588     /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2589        to OpenGL screen coordinates (ie the upper left corner is not the same).
2590        For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2591        -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2592     trans_mat[ 0] = 2.0 / width;  trans_mat[ 4] = 0.0;  trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2593     trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] =  1.0;
2594     trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0;           trans_mat[14] = -1.0;
2595     trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0;           trans_mat[15] =  1.0;
2596
2597     ENTER_GL();
2598     glMatrixMode(GL_MODELVIEW);
2599     glLoadIdentity();
2600     /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2601        Correctness Tips section).
2602        
2603        Basically, from what I understood, if the game does not filter the font texture,
2604        as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2605        one and we will have strange artifacts (as the rounding and stuff may give different results
2606        for different pixels, ie sometimes take the left pixel, sometimes the right).
2607     */
2608     glTranslatef(0.375, 0.375, 0);
2609     glMatrixMode(GL_PROJECTION);
2610     glLoadMatrixf(trans_mat);
2611     LEAVE_GL();
2612 }
2613
2614 void
2615 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2616                        D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2617 {
2618     TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
2619     
2620     ENTER_GL();
2621     if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2622         glMatrixMode(GL_MODELVIEW);
2623         glLoadMatrixf((float *) view_mat);
2624
2625         /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2626         if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2627             GLint i;
2628             DWORD runner;
2629             for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2630                 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2631                     GLdouble plane[4];
2632
2633                     plane[0] = This->clipping_planes[i].plane[0];
2634                     plane[1] = This->clipping_planes[i].plane[1];
2635                     plane[2] = This->clipping_planes[i].plane[2];
2636                     plane[3] = This->clipping_planes[i].plane[3];
2637                     
2638                     glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2639                 }
2640             }
2641         }
2642         if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2643             GLint i;
2644             DWORD runner;
2645
2646             for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2647                 if (runner & This->active_lights) {
2648                     switch (This->light_parameters[i].dltType) {
2649                         case D3DLIGHT_DIRECTIONAL: {
2650                             float direction[4];
2651                             float cut_off = 180.0;
2652                             
2653                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2654                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2655                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2656                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2657                             
2658                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2659                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2660                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2661                             direction[3] = 0.0;
2662                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2663                         } break;
2664
2665                         case D3DLIGHT_POINT: {
2666                             float position[4];
2667                             float cut_off = 180.0;
2668                             
2669                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2670                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2671                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2672                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2673                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2674                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2675                             position[3] = 1.0;
2676                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2677                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2678                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2679                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2680                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2681                         } break;
2682
2683                         case D3DLIGHT_SPOT: {
2684                             float direction[4];
2685                             float position[4];
2686                             float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2687                             
2688                             glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  (float *) &(This->light_parameters[i].dcvAmbient));
2689                             glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  (float *) &(This->light_parameters[i].dcvDiffuse));
2690                             glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2691                             
2692                             direction[0] = This->light_parameters[i].dvDirection.u1.x;
2693                             direction[1] = This->light_parameters[i].dvDirection.u2.y;
2694                             direction[2] = This->light_parameters[i].dvDirection.u3.z;
2695                             direction[3] = 0.0;
2696                             glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2697                             position[0] = This->light_parameters[i].dvPosition.u1.x;
2698                             position[1] = This->light_parameters[i].dvPosition.u2.y;
2699                             position[2] = This->light_parameters[i].dvPosition.u3.z;
2700                             position[3] = 1.0;
2701                             glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2702                             glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2703                             glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2704                             glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2705                             glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2706                             glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2707                         } break;
2708
2709                         default:
2710                             /* No warning here as it's already done at light setting */
2711                             break;
2712                     }
2713                 }
2714             }
2715         }
2716         
2717         glMultMatrixf((float *) world_mat);
2718     }
2719     if ((matrices & PROJMAT_CHANGED) != 0) {
2720         glMatrixMode(GL_PROJECTION);
2721         glLoadMatrixf((float *) proj_mat);
2722     }
2723     LEAVE_GL();
2724 }
2725
2726 void
2727 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2728 {
2729     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2730     DWORD tex_mat, tex_stage;
2731
2732     TRACE("(%p,%08lx)\n", This, matrices);
2733     
2734     if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
2735         if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2736             /* This will force an update of the transform state at the next drawing. */
2737             glThis->transform_state = GL_TRANSFORM_NONE;
2738         }
2739     }
2740     if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2741                     TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2742     {
2743         ENTER_GL();
2744         for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2745             if (matrices & tex_mat) {
2746                 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2747                     if (tex_stage == 0) {
2748                         /* No multi-texturing support for now ... */
2749                         glMatrixMode(GL_TEXTURE);
2750                         glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2751                     }
2752                 } else {
2753                     glMatrixMode(GL_TEXTURE);
2754                     glLoadIdentity();
2755                 }
2756             }
2757         }
2758         LEAVE_GL();
2759     }
2760 }
2761
2762 /* TODO for both these functions :
2763     - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2764       by other OpenGL code in D3D
2765     - handle the case where no 'Begin / EndScene' was done between two locks
2766     - handle the rectangles in the unlock too
2767     - handle pitch correctly...
2768 */
2769 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2770 {
2771     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2772     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2773     WINE_GL_BUFFER_TYPE buffer_type;
2774     RECT loc_rect;
2775     
2776     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2777         buffer_type = WINE_GL_BUFFER_FRONT;
2778         if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
2779             (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
2780             ERR("Change of front buffer.. Expect graphic corruptions !\n");
2781         }
2782         gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
2783     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2784         buffer_type = WINE_GL_BUFFER_BACK;
2785         if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
2786             (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
2787             ERR("Change of back buffer.. Expect graphic corruptions !\n");
2788         }
2789         gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
2790     } else {
2791         ERR("Wrong surface type for locking !\n");
2792         return;
2793     }
2794
2795     if (pRect == NULL) {
2796         loc_rect.top = 0;
2797         loc_rect.left = 0;
2798         loc_rect.bottom = This->surface_desc.dwHeight;
2799         loc_rect.right = This->surface_desc.dwWidth;
2800         pRect = &loc_rect;
2801     }
2802     
2803     /* Try to acquire the device critical section */
2804     EnterCriticalSection(&(d3d_dev->crit));
2805     
2806     if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
2807         ERR("Two consecutive locks on %s buffer... Expect problems !\n",
2808             (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
2809     }
2810     gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
2811     
2812     if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
2813         /* Check if the new rectangle is in the previous one or not.
2814            If it is not, flush first the previous locks on screen.
2815         */
2816         if ((pRect->top    < gl_d3d_dev->lock_rect[buffer_type].top) ||
2817             (pRect->left   < gl_d3d_dev->lock_rect[buffer_type].left) ||
2818             (pRect->right  > gl_d3d_dev->lock_rect[buffer_type].right) ||
2819             (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2820             if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2821                 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
2822                       (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
2823                       pRect->left, pRect->top, pRect->right, pRect->bottom,
2824                       gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
2825                       gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
2826                 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
2827             }
2828             gl_d3d_dev->state[buffer_type] = SURFACE_GL;
2829             gl_d3d_dev->lock_rect[buffer_type] = *pRect;
2830         }
2831         /* In the other case, do not upgrade the locking rectangle as it's no need... */
2832     } else {
2833         gl_d3d_dev->lock_rect[buffer_type] = *pRect;
2834     }
2835     
2836     if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
2837         /* If the surface is already in memory, no need to do anything here... */
2838         GLenum buffer_format;
2839         GLenum buffer_color;
2840         int y;
2841         char *dst;
2842
2843         TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
2844               pRect->left, pRect->top, pRect->right, pRect->bottom);
2845         
2846         /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2847            may only write to the device... But when we will blit it back to the screen, we need
2848            also to blit correctly the parts the application did not overwrite... */
2849
2850         if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
2851             (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2852              (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2853             if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2854                 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2855                 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2856                 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2857                 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
2858                 buffer_color = GL_RGB;
2859             } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
2860                        (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
2861                        (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
2862                        (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
2863                 buffer_format = GL_UNSIGNED_BYTE;
2864                 buffer_color = GL_RGB;
2865             } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2866                        (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2867                        (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2868                        (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2869                 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
2870                 buffer_color = GL_BGRA;
2871             } else {
2872                 ERR(" unsupported pixel format at device locking.\n");
2873                 return;
2874             }
2875         } else {
2876             ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
2877             return;
2878         }
2879
2880         ENTER_GL();
2881         
2882         if (buffer_type == WINE_GL_BUFFER_FRONT)
2883             /* Application wants to lock the front buffer */
2884             glReadBuffer(GL_FRONT);
2885         else 
2886             /* Application wants to lock the back buffer */
2887             glReadBuffer(GL_BACK);
2888
2889         dst = ((char *)This->surface_desc.lpSurface) +
2890           (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
2891         for (y = (This->surface_desc.dwHeight - pRect->top - 1);
2892              y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
2893              y--) {
2894             glReadPixels(pRect->left, y,
2895                          pRect->right - pRect->left, 1,
2896                          buffer_color, buffer_format, dst);
2897             dst += This->surface_desc.u1.lPitch;
2898         }
2899
2900         gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
2901         
2902 #if 0
2903         /* I keep this code here as it's very useful to debug :-) */
2904         {
2905             static int flush_count = 0;
2906             char buf[128];
2907             FILE *f;
2908             
2909             if ((++flush_count % 50) == 0) {
2910                 sprintf(buf, "lock_%06d.pnm", flush_count);
2911                 f = fopen(buf, "wb");
2912                 DDRAW_dump_surface_to_disk(This, f);
2913             }
2914         }
2915 #endif
2916         
2917         LEAVE_GL();
2918     }
2919 }
2920
2921 #define UNLOCK_TEX_SIZE 256
2922
2923 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2924     RECT loc_rect;
2925     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2926     GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog;
2927     int x, y;
2928     BOOLEAN initial = FALSE;
2929
2930     /* Note : no need here to lock the 'device critical section' as we are already protected by
2931        the GL critical section. */
2932
2933     if (pRect == NULL) {
2934         loc_rect.top = 0;
2935         loc_rect.left = 0;
2936         loc_rect.bottom = surf->surface_desc.dwHeight;
2937         loc_rect.right = surf->surface_desc.dwWidth;
2938         pRect = &loc_rect;
2939     }
2940     
2941     TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
2942
2943     /* This is a hack to prevent querying the current texture from GL */
2944     gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
2945
2946     if (gl_d3d_dev->unlock_tex == 0) {
2947         glGenTextures(1, &gl_d3d_dev->unlock_tex);
2948         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2949         initial = TRUE;
2950         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2951         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2952     } else {
2953         glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2954     }
2955
2956     
2957     if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
2958                                           initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2959         ERR(" unsupported pixel format at frame buffer flush.\n");
2960         return;
2961     }
2962         
2963     glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2964     glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2965     glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2966     glGetIntegerv(GL_CULL_FACE, &cull_face);
2967     glGetIntegerv(GL_LIGHTING, &lighting);
2968     glGetIntegerv(GL_BLEND, &blend);
2969     glGetIntegerv(GL_FOG, &fog);
2970     glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2971     glMatrixMode(GL_TEXTURE);
2972     glLoadIdentity();
2973     /* TODO: scissor test if ever we use it ! */
2974     
2975     gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2976     d3ddevice_set_ortho(d3d_dev);
2977     
2978     glDisable(GL_DEPTH_TEST);
2979     glEnable(GL_TEXTURE_2D);
2980     glEnable(GL_SCISSOR_TEST); 
2981     glDepthRange(0.0, 1.0);
2982     glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
2983     glScissor(pRect->left, surf->surface_desc.dwHeight - pRect->bottom,
2984               pRect->right - pRect->left, pRect->bottom - pRect->top);
2985     glDisable(GL_LIGHTING);
2986     glDisable(GL_CULL_FACE);
2987     glDisable(GL_ALPHA_TEST);
2988     glDisable(GL_STENCIL_TEST);
2989     glDisable(GL_BLEND);
2990     glDisable(GL_FOG);
2991     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2992     
2993     for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
2994         for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
2995             /* First, upload the texture... */
2996             RECT flush_rect;
2997
2998             flush_rect.left = x;
2999             flush_rect.top = y;
3000             flush_rect.right  = (x + UNLOCK_TEX_SIZE > pRect->right)  ? pRect->right  : (x + UNLOCK_TEX_SIZE);
3001             flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3002
3003             upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3004
3005             glBegin(GL_QUADS);
3006             glColor3ub(0xFF, 0xFF, 0xFF);
3007             glTexCoord2f(0.0, 0.0);
3008             glVertex3d(x, y, 0.5);
3009             glTexCoord2f(1.0, 0.0);
3010             glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3011             glTexCoord2f(1.0, 1.0);
3012             glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3013             glTexCoord2f(0.0, 1.0);
3014             glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3015             glEnd();
3016         }
3017     }
3018     
3019     upload_surface_to_tex_memory_release();
3020     
3021     /* And restore all the various states modified by this code */
3022     if (depth_test != 0) glEnable(GL_DEPTH_TEST);
3023     if (lighting != 0) glEnable(GL_LIGHTING);
3024     if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
3025     if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
3026     if (cull_face != 0) glEnable(GL_CULL_FACE);
3027     if (blend != 0) glEnable(GL_BLEND);
3028     if (fog != 0) glEnable(GL_FOG);
3029     glDisable(GL_SCISSOR_TEST);
3030     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3031     glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3032     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3033     glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
3034     glViewport(d3d_dev->active_viewport.dwX,
3035                d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
3036                d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
3037     d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3038 #if 0
3039     /* I keep this code here as it's very useful to debug :-) */
3040     {
3041         static int flush_count = 0;
3042         char buf[128];
3043         FILE *f;
3044
3045         if ((++flush_count % 50) == 0) {
3046             sprintf(buf, "flush_%06d.pnm", flush_count);
3047             f = fopen(buf, "wb");
3048             DDRAW_dump_surface_to_disk(surf, f);
3049         }
3050     }
3051 #endif
3052 }
3053
3054 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3055 {
3056     WINE_GL_BUFFER_TYPE buffer_type;
3057     IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3058     IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3059   
3060     if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3061         buffer_type = WINE_GL_BUFFER_FRONT;
3062     } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3063         buffer_type = WINE_GL_BUFFER_BACK;
3064     } else {
3065         ERR("Wrong surface type for locking !\n");
3066         return;
3067     }
3068
3069     if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3070         ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3071             (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3072     }
3073     gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3074     
3075     /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3076     if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3077         if (buffer_type == WINE_GL_BUFFER_FRONT) {
3078             GLenum prev_draw;
3079
3080             TRACE(" flushing front buffer immediatly on screen.\n");
3081             
3082             ENTER_GL();
3083             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3084             glDrawBuffer(GL_FRONT);
3085             /* Note: we do not use the application provided lock rectangle but our own stored at
3086                      lock time. This is because in old D3D versions, the 'lock' parameter did not
3087                      exist.
3088             */
3089             d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
3090             glDrawBuffer(prev_draw);
3091             LEAVE_GL();
3092         } else {
3093             gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3094         }
3095     }
3096
3097     /* And 'frees' the device critical section */
3098     LeaveCriticalSection(&(d3d_dev->crit));
3099 }
3100
3101 static void
3102 apply_texture_state(IDirect3DDeviceImpl *This)
3103 {
3104     int stage, state;
3105     
3106     /* Initialize texture stages states */
3107     for (stage = 0; stage < MAX_TEXTURES; stage++) {
3108        for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3109            if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3110                IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3111                                                      stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3112            }
3113        }
3114     }
3115 }     
3116
3117 HRESULT
3118 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3119 {
3120     IDirect3DDeviceImpl *object;
3121     IDirect3DDeviceGLImpl *gl_object;
3122     IDirectDrawSurfaceImpl *surf;
3123     HDC device_context;
3124     XVisualInfo *vis;
3125     int num;
3126     int tex_num;
3127     XVisualInfo template;
3128     GLenum buffer = GL_FRONT;
3129     int light;
3130     GLint max_clipping_planes = 0;
3131     
3132     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3133     if (object == NULL) return DDERR_OUTOFMEMORY;
3134
3135     gl_object = (IDirect3DDeviceGLImpl *) object;
3136     
3137     object->ref = 1;
3138     object->d3d = d3d;
3139     object->surface = surface;
3140     object->set_context = set_context;
3141     object->clear = d3ddevice_clear;
3142     object->set_matrices = d3ddevice_set_matrices;
3143     object->matrices_updated = d3ddevice_matrices_updated;
3144     object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3145     
3146     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3147
3148     InitializeCriticalSection(&(object->crit));
3149
3150     TRACE(" device critical section : %p\n", &(object->crit));
3151     
3152     device_context = GetDC(surface->ddraw_owner->window);
3153     gl_object->display = get_display(device_context);
3154     gl_object->drawable = get_drawable(device_context);
3155     ReleaseDC(surface->ddraw_owner->window,device_context);
3156
3157     ENTER_GL();
3158     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3159     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3160     if (vis == NULL) {
3161         HeapFree(GetProcessHeap(), 0, object);
3162         ERR("No visual found !\n");
3163         LEAVE_GL();
3164         return DDERR_INVALIDPARAMS;
3165     } else {
3166         TRACE(" visual found\n");
3167     }
3168
3169     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3170                                              NULL, GL_TRUE);
3171
3172     if (gl_object->gl_context == NULL) {
3173         HeapFree(GetProcessHeap(), 0, object);
3174         ERR("Error in context creation !\n");
3175         LEAVE_GL();
3176         return DDERR_INVALIDPARAMS;
3177     } else {
3178         TRACE(" context created (%p)\n", gl_object->gl_context);
3179     }
3180     
3181     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3182     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3183         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3184             surf->aux_ctx  = (LPVOID) object;
3185             surf->aux_data = (LPVOID) gl_object->drawable;
3186             surf->aux_flip = opengl_flip;
3187             buffer =  GL_BACK;
3188             break;
3189         }
3190     }
3191     /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3192     if (surf == NULL) {
3193         TRACE(" no double buffering : drawing on the front buffer\n");
3194         buffer = GL_FRONT;
3195     }
3196     
3197     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3198         IDirectDrawSurfaceImpl *surf2;
3199         for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3200         for (; surf2 != NULL; surf2 = surf2->next_attached) {
3201             TRACE(" checking surface %p :", surf2);
3202             if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3203                 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3204                 /* Override the Lock / Unlock function for all these surfaces */
3205                 surf2->lock_update_prev = surf2->lock_update;
3206                 surf2->lock_update = d3ddevice_lock_update;
3207                 surf2->unlock_update_prev = surf2->unlock_update;
3208                 surf2->unlock_update = d3ddevice_unlock_update;
3209                 /* And install also the blt / bltfast overrides */
3210                 surf2->aux_blt = d3ddevice_blt;
3211                 surf2->aux_bltfast = d3ddevice_bltfast;
3212                 
3213                 TRACE(" overiding direct surface access.\n");
3214             } else {
3215                 TRACE(" no overide.\n");
3216             }
3217             surf2->d3ddevice = object;
3218         }
3219     }
3220
3221     /* Set the various light parameters */
3222     for (light = 0; light < MAX_LIGHTS; light++) {
3223         /* Only set the fields that are not zero-created */
3224         object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3225         object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3226         object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3227         object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3228         object->light_parameters[light].dvDirection.u3.z = 1.0;
3229     }
3230     
3231     /* Allocate memory for the matrices */
3232     object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3233     object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3234     object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3235     memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3236     memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3237     memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3238     for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3239         object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3240         memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3241     }
3242     
3243     /* Initialisation */
3244     TRACE(" setting current context\n");
3245     object->set_context(object);
3246     TRACE(" current context set\n");
3247
3248     /* allocate the clipping planes */
3249     glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3250     if (max_clipping_planes>32) {
3251         object->max_clipping_planes=32;
3252     } else {
3253         object->max_clipping_planes = max_clipping_planes;
3254     }
3255     TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3256     object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3257
3258     glHint(GL_FOG_HINT,GL_NICEST);
3259     
3260     glClearColor(0.0, 0.0, 0.0, 0.0);
3261     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3262     glDrawBuffer(buffer);
3263     glReadBuffer(buffer);
3264     /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3265     LEAVE_GL();
3266
3267     gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3268     gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3269     
3270     /* fill_device_capabilities(d3d->ddraw); */    
3271     
3272     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
3273     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3274     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3275     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3276
3277     *obj = object;
3278
3279     TRACE(" creating implementation at %p.\n", *obj);
3280
3281     /* And finally warn D3D that this device is now present */
3282     object->d3d->d3d_added_device(object->d3d, object);
3283
3284     /* FIXME: Should handle other versions than just 7 */
3285     InitDefaultStateBlock(&object->state_block, 7);
3286     /* Apply default render state and texture stage state values */
3287     apply_render_state(object, &object->state_block);
3288     apply_texture_state(object);
3289
3290     /* And fill the fog table with the default fog value */
3291     build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3292     
3293     return DD_OK;
3294 }