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