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