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