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