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