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