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