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