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