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