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