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