- Clean up all the D3D COM handling (but the underlaying code is still
[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
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winerror.h"
28 #include "wine/obj_base.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
32
33 #include "mesa_private.h"
34 #include "main.h"
35
36 #include "x11drv.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39
40 /* They are non-static as they are used by Direct3D in the creation function */
41 const GUID IID_D3DDEVICE_OpenGL = {
42   0x31416d44,
43   0x86ae,
44   0x11d2,
45   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
46 };
47
48 const GUID IID_D3DDEVICE2_OpenGL = {
49   0x31416d44,
50   0x86ae,
51   0x11d2,
52   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfb }
53 };
54
55 const GUID IID_D3DDEVICE3_OpenGL = {
56   0x31416d44,
57   0x86ae,
58   0x11d2,
59   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfc }
60 };
61
62 const GUID IID_D3DDEVICE7_OpenGL = {
63   0x31416d44,
64   0x86ae,
65   0x11d2,
66   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfd }
67 };
68
69 const GUID IID_D3DDEVICE_Default = {
70   0x00000000,
71   0x0000,
72   0x0000,
73   { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
74 };
75
76 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
77    on Mesa's home page) or version 3.1b.
78
79    Version 3.1b2 should correct this bug */
80 #undef HAVE_BUGGY_MESAGL
81
82 #ifndef HAVE_GLEXT_PROTOTYPES
83 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
84 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
85                                          GLsizei width, GLenum format, GLenum type,
86                                          const GLvoid *table);
87 #endif
88
89 static const float id_mat[16] = {
90     1.0, 0.0, 0.0, 0.0,
91     0.0, 1.0, 0.0, 0.0,
92     0.0, 0.0, 1.0, 0.0,
93     0.0, 0.0, 0.0, 1.0
94 };
95
96 /* retrieve the X display to use on a given DC */
97 inline static Display *get_display( HDC hdc )
98 {
99     Display *display;
100     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
101
102     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
103                     sizeof(display), (LPSTR)&display )) display = NULL;
104
105     return display;
106 }
107
108
109 /* retrieve the X drawable to use on a given DC */
110 inline static Drawable get_drawable( HDC hdc )
111 {
112     Drawable drawable;
113     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
114
115     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
116                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
117
118     return drawable;
119 }
120
121
122 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
123 {
124     TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
125     ENTER_GL();
126     glXSwapBuffers((Display*)display,(Drawable)drawable);
127     LEAVE_GL();
128     return TRUE;
129 }
130
131
132 /*******************************************************************************
133  *                              OpenGL static functions
134  */
135 static void set_context(IDirect3DDeviceImpl* This) {
136 #if 0
137     D3DDPRIVATE(This);
138
139     ENTER_GL();
140     TRACE("glxMakeCurrent %p, %ld, %p\n",odev->gdi_display,odev->drawable, odev->ctx);
141     if (glXMakeCurrent(odev->gdi_display,odev->drawable, odev->ctx) == False) {
142         ERR("Error in setting current context (context %p drawable %ld)!\n",
143             odev->ctx, odev->drawable);
144     }
145     LEAVE_GL();
146 #else
147     ERR("This function should not be called in the current state of the code...\n");
148 #endif
149 }
150
151 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
152 {
153     pc->dwSize = sizeof(*pc);
154     pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
155       D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
156     pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
157       D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
158     pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
159     pc->dwSrcBlendCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
160     pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
161     pc->dwAlphaCmpCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
162     pc->dwShadeCaps = 0xFFFFFFFF;     /* FIXME: need REAL values */
163     pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
164       D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
165     pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
166       D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
167     pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
168     pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
169     pc->dwStippleWidth = 32;
170     pc->dwStippleHeight = 32;
171 }
172
173 static void fill_opengl_caps(D3DDEVICEDESC *d1)
174 {
175     /* GLint maxlight; */
176
177     d1->dwSize  = sizeof(*d1);
178     d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
179       | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
180     d1->dcmColorModel = D3DCOLOR_RGB;
181     d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
182       D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
183       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
184     d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
185     d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
186     d1->bClipping = TRUE;
187     d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
188     d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
189     d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
190     d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
191     fill_opengl_primcaps(&(d1->dpcLineCaps));
192     fill_opengl_primcaps(&(d1->dpcTriCaps));
193     d1->dwDeviceRenderBitDepth  = DDBD_16;
194     d1->dwDeviceZBufferBitDepth = DDBD_16;
195     d1->dwMaxBufferSize = 0;
196     d1->dwMaxVertexCount = 65536;
197     d1->dwMinTextureWidth  = 1;
198     d1->dwMinTextureHeight = 1;
199     d1->dwMaxTextureWidth  = 1024;
200     d1->dwMaxTextureHeight = 1024;
201     d1->dwMinStippleWidth  = 1;
202     d1->dwMinStippleHeight = 1;
203     d1->dwMaxStippleWidth  = 32;
204     d1->dwMaxStippleHeight = 32;
205 }
206
207 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
208 {
209 #if 0 /* TODO : fix this... */
210     x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
211     const char *ext_string;
212     Mesa_DeviceCapabilities *devcap;
213
214     private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
215     devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
216
217     ENTER_GL();
218     ext_string = glGetString(GL_EXTENSIONS);
219     /* Query for the ColorTable Extension */
220     if (strstr(ext_string, "GL_EXT_paletted_texture")) {
221         devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
222         TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
223     } else {
224         TRACE("Color table extension not found.\n");
225     }
226     LEAVE_GL();
227 #endif
228 }
229
230
231
232 HRESULT d3device_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD interface_version)
233 {
234     D3DDEVICEDESC d1, d2;
235     char buf[256];
236     const void *iid = NULL;
237
238     switch (interface_version) {
239         case 1: iid = &IID_D3DDEVICE_OpenGL; break;
240         case 2: iid = &IID_D3DDEVICE2_OpenGL; break;
241         case 3: iid = &IID_D3DDEVICE3_OpenGL; break;
242         case 7: iid = &IID_D3DDEVICE7_OpenGL; break;
243     }
244     strcpy(buf, "WINE Direct3DX using OpenGL");
245     buf[13] = '0' + interface_version;
246
247     fill_opengl_caps(&d1);
248     d2 = d1;
249
250     TRACE(" enumerating OpenGL D3DDevice%ld interface (IID %s).\n", interface_version, debugstr_guid(iid));
251     return cb((LPGUID) iid, buf, "direct3d", &d1, &d2, context);
252 }
253
254 ULONG WINAPI
255 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
256 {
257     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
258     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
259     
260     TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
261     if (!--(This->ref)) {
262         /* Release texture associated with the device */ 
263         if (This->current_texture != NULL)
264             IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture, IDirect3DTexture2));
265                   
266         ENTER_GL();
267         glXDestroyContext(glThis->display, glThis->gl_context);
268         LEAVE_GL();
269
270         HeapFree(GetProcessHeap(), 0, This);
271         return 0;
272     }
273     return This->ref;
274 }
275
276 HRESULT WINAPI
277 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
278                                        LPD3DDEVICEDESC lpD3DHWDevDesc,
279                                        LPD3DDEVICEDESC lpD3DHELDevDesc)
280 {
281     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
282     D3DDEVICEDESC desc;
283     DWORD dwSize;
284
285     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
286
287     fill_opengl_caps(&desc);
288     dwSize = lpD3DHWDevDesc->dwSize;
289     memset(lpD3DHWDevDesc, 0, dwSize);
290     memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
291
292     dwSize = lpD3DHELDevDesc->dwSize;
293     memset(lpD3DHELDevDesc, 0, dwSize);
294     memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
295
296     TRACE(" returning caps : TODO\n");
297
298     return DD_OK;
299 }
300
301 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
302                                           LPD3DENUMPIXELFORMATSCALLBACK cb_2,
303                                           LPVOID context)
304 {
305     DDSURFACEDESC sdesc;
306     LPDDPIXELFORMAT pformat;
307
308     /* Do the texture enumeration */
309     sdesc.dwSize = sizeof(DDSURFACEDESC);
310     sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
311     sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
312     pformat = &(sdesc.ddpfPixelFormat);
313     pformat->dwSize = sizeof(DDPIXELFORMAT);
314     pformat->dwFourCC = 0;
315
316     TRACE("Enumerating GL_RGBA unpacked (32)\n");
317     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
318     pformat->u1.dwRGBBitCount = 32;
319     pformat->u2.dwRBitMask =         0xFF000000;
320     pformat->u3.dwGBitMask =         0x00FF0000;
321     pformat->u4.dwBBitMask =        0x0000FF00;
322     pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
323     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
324     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
325
326     TRACE("Enumerating GL_RGB unpacked (24)\n");
327     pformat->dwFlags = DDPF_RGB;
328     pformat->u1.dwRGBBitCount = 24;
329     pformat->u2.dwRBitMask =  0x00FF0000;
330     pformat->u3.dwGBitMask =  0x0000FF00;
331     pformat->u4.dwBBitMask = 0x000000FF;
332     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
333     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
334     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
335
336 #ifndef HAVE_BUGGY_MESAGL
337     /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
338        so that future version will work great. */
339     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
340     pformat->dwFlags = DDPF_RGB;
341     pformat->u1.dwRGBBitCount = 16;
342     pformat->u2.dwRBitMask =  0x0000F800;
343     pformat->u3.dwGBitMask =  0x000007E0;
344     pformat->u4.dwBBitMask = 0x0000001F;
345     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
346     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
347     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
348
349     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
350     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
351     pformat->u1.dwRGBBitCount = 16;
352     pformat->u2.dwRBitMask =         0x0000F800;
353     pformat->u3.dwGBitMask =         0x000007C0;
354     pformat->u4.dwBBitMask =        0x0000003E;
355     pformat->u5.dwRGBAlphaBitMask = 0x00000001;
356     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
357     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
358
359     TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
360     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
361     pformat->u1.dwRGBBitCount = 16;
362     pformat->u2.dwRBitMask =         0x0000F000;
363     pformat->u3.dwGBitMask =         0x00000F00;
364     pformat->u4.dwBBitMask =        0x000000F0;
365     pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
366     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
367     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
368
369     TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
370     pformat->dwFlags = DDPF_RGB;
371     pformat->u1.dwRGBBitCount = 8;
372     pformat->u2.dwRBitMask =        0x000000E0;
373     pformat->u3.dwGBitMask =        0x0000001C;
374     pformat->u4.dwBBitMask =        0x00000003;
375     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
376     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
377     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
378 #endif
379
380     TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
381     pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
382     pformat->u1.dwRGBBitCount = 16;
383     pformat->u2.dwRBitMask =         0x00007C00;
384     pformat->u3.dwGBitMask =         0x000003E0;
385     pformat->u4.dwBBitMask =         0x0000001F;
386     pformat->u5.dwRGBAlphaBitMask =  0x00008000;
387     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
388     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
389
390     TRACE("Enumerating Paletted (8)\n");
391     pformat->dwFlags = DDPF_PALETTEINDEXED8;
392     pformat->u1.dwRGBBitCount = 8;
393     pformat->u2.dwRBitMask =  0x00000000;
394     pformat->u3.dwGBitMask =  0x00000000;
395     pformat->u4.dwBBitMask = 0x00000000;
396     pformat->u5.dwRGBAlphaBitMask = 0x00000000;
397     if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
398     if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
399
400     TRACE("End of enumeration\n");
401     return DD_OK;
402 }
403
404 HRESULT WINAPI
405 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
406                                                LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
407                                                LPVOID lpArg)
408 {
409     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
410     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
411     return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
412 }
413
414 HRESULT WINAPI
415 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
416                                                LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
417                                                LPVOID lpArg)
418 {
419     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
420     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
421     return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
422 }
423
424 HRESULT WINAPI
425 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
426                                               D3DRENDERSTATETYPE dwRenderStateType,
427                                               DWORD dwRenderState)
428 {
429     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
430     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
431     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
432
433     /* Call the render state functions */
434     set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
435
436     return DD_OK;
437 }
438
439 HRESULT WINAPI
440 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
441                                           D3DLIGHTSTATETYPE dwLightStateType,
442                                           DWORD dwLightState)
443 {
444     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
445     TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
446
447     switch (dwLightStateType) {
448         case D3DLIGHTSTATE_MATERIAL: {  /* 1 */
449             IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
450
451             if (mat != NULL) {
452                 ENTER_GL();
453                 mat->activate(mat);
454                 LEAVE_GL();
455             } else {
456                 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
457             }
458         } break;
459
460         case D3DLIGHTSTATE_AMBIENT: {   /* 2 */
461             float light[4];
462
463             light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
464             light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
465             light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
466             light[3] = 1.0;
467             ENTER_GL();
468             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
469             LEAVE_GL();
470         } break;
471
472 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
473         UNSUP(COLORMODEL);
474         UNSUP(FOGMODE);
475         UNSUP(FOGSTART);
476         UNSUP(FOGEND);
477         UNSUP(FOGDENSITY);
478 #undef UNSUP
479
480         default:
481             TRACE("Unexpected Light State Type\n");
482             return DDERR_INVALIDPARAMS;
483     }
484
485     return DD_OK;
486 }
487
488 HRESULT WINAPI
489 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
490                                             D3DTRANSFORMSTATETYPE dtstTransformStateType,
491                                             LPD3DMATRIX lpD3DMatrix)
492 {
493     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
494     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
495
496     TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
497
498     ENTER_GL();
499
500     /* Using a trial and failure approach, I found that the order of
501        Direct3D transformations that works best is :
502
503        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
504
505        As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
506        OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
507
508        If anyone has a good explanation of the three different matrices in
509        the SDK online documentation, feel free to point it to me. For example,
510        which matrices transform lights ? In OpenGL only the PROJECTION matrix
511        transform the lights, not the MODELVIEW. Using the matrix names, I
512        supposed that PROJECTION and VIEW (all 'camera' related names) do
513        transform lights, but WORLD do not. It may be wrong though... */
514
515     /* After reading through both OpenGL and Direct3D documentations, I
516        thought that D3D matrices were written in 'line major mode' transposed
517        from OpenGL's 'column major mode'. But I found out that a simple memcpy
518        works fine to transfer one matrix format to the other (it did not work
519        when transposing)....
520
521        So :
522          1) are the documentations wrong
523          2) does the matrix work even if they are not read correctly
524          3) is Mesa's implementation of OpenGL not compliant regarding Matrix
525             loading using glLoadMatrix ?
526
527        Anyway, I always use 'conv_mat' to transfer the matrices from one format
528        to the other so that if I ever find out that I need to transpose them, I
529        will able to do it quickly, only by changing the macro conv_mat. */
530
531     switch (dtstTransformStateType) {
532         case D3DTRANSFORMSTATE_WORLD: {
533             conv_mat(lpD3DMatrix, glThis->world_mat);
534             glMatrixMode(GL_MODELVIEW);
535             glLoadMatrixf((float *) glThis->world_mat);
536         } break;
537
538         case D3DTRANSFORMSTATE_VIEW: {
539             conv_mat(lpD3DMatrix, glThis->view_mat);
540             glMatrixMode(GL_PROJECTION);
541             glLoadMatrixf((float *) glThis->proj_mat);
542             glMultMatrixf((float *) glThis->view_mat);
543         } break;
544
545         case D3DTRANSFORMSTATE_PROJECTION: {
546             conv_mat(lpD3DMatrix, glThis->proj_mat);
547             glMatrixMode(GL_PROJECTION);
548             glLoadMatrixf((float *) glThis->proj_mat);
549             glMultMatrixf((float *) glThis->view_mat);
550         } break;
551
552         default:
553             ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
554             break;
555     }
556     LEAVE_GL();
557
558     return DD_OK;
559 }
560
561 inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
562                                   D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
563 {
564     DWORD vx_index;
565   
566     /* Puts GL in the correct lighting mode */
567     if (glThis->vertex_type != d3dvt) {
568         if (glThis->vertex_type == D3DVT_TLVERTEX) {
569             /* Need to put the correct transformation again */
570             glMatrixMode(GL_MODELVIEW);
571             glLoadMatrixf((float *) glThis->world_mat);
572             glMatrixMode(GL_PROJECTION);
573             glLoadMatrixf((float *) glThis->proj_mat);
574             glMultMatrixf((float *) glThis->view_mat);
575         }
576
577         switch (d3dvt) {
578             case D3DVT_VERTEX:
579                 TRACE("Standard Vertex\n");
580                 glEnable(GL_LIGHTING);
581                 break;
582
583             case D3DVT_LVERTEX:
584                 TRACE("Lighted Vertex\n");
585                 glDisable(GL_LIGHTING);
586                 break;
587
588             case D3DVT_TLVERTEX: {
589                 GLdouble height, width, minZ, maxZ;
590
591                 TRACE("Transformed - Lighted Vertex\n");
592                 /* First, disable lighting */
593                 glDisable(GL_LIGHTING);
594
595                 /* Then do not put any transformation matrixes */
596                 glMatrixMode(GL_MODELVIEW);
597                 glLoadIdentity();
598                 glMatrixMode(GL_PROJECTION);
599                 glLoadIdentity();
600
601                 if (glThis->parent.current_viewport == NULL) {
602                     ERR("No current viewport !\n");
603                     /* Using standard values */
604                     height = 640.0;
605                     width = 480.0;
606                     minZ = -10.0;
607                     maxZ = 10.0;
608                 } else {
609                     if (glThis->parent.current_viewport->use_vp2 == 1) {
610                         height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
611                         width  = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
612                         minZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
613                         maxZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
614                     } else {
615                         height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
616                         width  = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
617                         minZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
618                         maxZ   = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
619                     }
620                 }
621
622                 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
623             } break;
624
625             default:
626                 ERR("Unhandled vertex type\n");
627                 break;
628         }
629
630         glThis->vertex_type = d3dvt;
631     }
632
633     switch (d3dpt) {
634         case D3DPT_POINTLIST:
635             TRACE("Start POINTS\n");
636             glBegin(GL_POINTS);
637             break;
638
639         case D3DPT_LINELIST:
640             TRACE("Start LINES\n");
641             glBegin(GL_LINES);
642             break;
643
644         case D3DPT_LINESTRIP:
645             TRACE("Start LINE_STRIP\n");
646             glBegin(GL_LINE_STRIP);
647             break;
648
649         case D3DPT_TRIANGLELIST:
650             TRACE("Start TRIANGLES\n");
651             glBegin(GL_TRIANGLES);
652             break;
653
654         case D3DPT_TRIANGLESTRIP:
655             TRACE("Start TRIANGLE_STRIP\n");
656             glBegin(GL_TRIANGLE_STRIP);
657             break;
658
659         case D3DPT_TRIANGLEFAN:
660             TRACE("Start TRIANGLE_FAN\n");
661             glBegin(GL_TRIANGLE_FAN);
662             break;
663
664         default:
665             TRACE("Unhandled primitive\n");
666             break;
667     }
668
669     /* Draw the primitives */
670     for (vx_index = 0; vx_index < maxvert; vx_index++) {
671         switch (d3dvt) {
672             case D3DVT_VERTEX: {
673                 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
674
675                 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
676                 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
677                 TRACE("   V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
678             } break;
679
680             case D3DVT_LVERTEX: {
681                 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
682                 DWORD col = vx->u4.color;
683
684                 glColor3f(((col >> 16) & 0xFF) / 255.0,
685                           ((col >>  8) & 0xFF) / 255.0,
686                           ((col >>  0) & 0xFF) / 255.0);
687                 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
688                 TRACE("  LV: %f %f %f (%02lx %02lx %02lx)\n",
689                       vx->u1.x, vx->u2.y, vx->u3.z,
690                       ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF));
691             } break;
692
693             case D3DVT_TLVERTEX: {
694                 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
695                 DWORD col = vx->u5.color;
696
697                 glColor3f(((col >> 16) & 0xFF) / 255.0,
698                           ((col >>  8) & 0xFF) / 255.0,
699                           ((col >>  0) & 0xFF) / 255.0);
700                 glTexCoord2f(vx->u7.tu, vx->u8.tv);
701                 if (vx->u4.rhw < 0.01)
702                     glVertex3f(vx->u1.sx,
703                                vx->u2.sy,
704                                vx->u3.sz);
705                 else
706                     glVertex4f(vx->u1.sx / vx->u4.rhw,
707                                vx->u2.sy / vx->u4.rhw,
708                                vx->u3.sz / vx->u4.rhw,
709                                1.0 / vx->u4.rhw);
710                 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",
711                       vx->u1.sx, vx->u2.sy, vx->u3.sz,
712                       ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),
713                       vx->u7.tu, vx->u8.tv, vx->u4.rhw);
714             } break;
715
716             default:
717                 FIXME("Unhandled vertex type\n");
718                 break;
719         }
720     }
721
722     glEnd();
723     TRACE("End\n");
724 }
725
726 HRESULT WINAPI
727 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
728                                        D3DPRIMITIVETYPE d3dptPrimitiveType,
729                                        D3DVERTEXTYPE d3dvtVertexType,
730                                        LPVOID lpvVertices,
731                                        DWORD dwVertexCount,
732                                        DWORD dwFlags)
733 {
734     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
735     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
736
737     ENTER_GL();
738     draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
739     LEAVE_GL();
740                    
741     return DD_OK;
742 }
743
744 HRESULT WINAPI
745 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
746                                               D3DPRIMITIVETYPE d3dptPrimitiveType,
747                                               D3DVERTEXTYPE d3dvtVertexType,
748                                               LPVOID lpvVertices,
749                                               DWORD dwVertexCount,
750                                               LPWORD dwIndices,
751                                               DWORD dwIndexCount,
752                                               DWORD dwFlags)
753 {
754     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
755     TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
756
757     ENTER_GL();
758     draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
759     LEAVE_GL();
760     
761     return DD_OK;
762 }
763
764 HRESULT WINAPI
765 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
766                                              LPD3DEXECUTEBUFFERDESC lpDesc,
767                                              LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
768                                              IUnknown* pUnkOuter)
769 {
770     ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
771     IDirect3DExecuteBufferImpl *ret;
772     HRESULT ret_value;
773     
774     TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
775
776     ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
777     *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
778
779     TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
780     
781     return ret_value;
782 }
783
784 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
785 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice7.fun))
786 #else
787 # define XCAST(fun)     (void*)
788 #endif
789
790 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
791 {
792     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
793     XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
794     XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
795     XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
796     XCAST(GetCaps) Main_IDirect3DDeviceImpl_7_GetCaps,
797     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
798     XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
799     XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
800     XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
801     XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
802     XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
803     XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
804     XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
805     XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
806     XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
807     XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
808     XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
809     XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
810     XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
811     XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
812     XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
813     XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
814     XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
815     XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
816     XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
817     XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
818     XCAST(DrawPrimitive) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
819     XCAST(DrawIndexedPrimitive) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
820     XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
821     XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
822     XCAST(DrawPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
823     XCAST(DrawIndexedPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
824     XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
825     XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
826     XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
827     XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
828     XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
829     XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
830     XCAST(SetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
831     XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
832     XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
833     XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
834     XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
835     XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
836     XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
837     XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
838     XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
839     XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
840     XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
841     XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
842 };
843
844 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
845 #undef XCAST
846 #endif
847
848
849 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
850 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice3.fun))
851 #else
852 # define XCAST(fun)     (void*)
853 #endif
854
855 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
856 {
857     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
858     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
859     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
860     XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
861     XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
862     XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
863     XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
864     XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
865     XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
866     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
867     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
868     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
869     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
870     XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
871     XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
872     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
873     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
874     XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
875     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
876     XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
877     XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
878     XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
879     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
880     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
881     XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
882     XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
883     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
884     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
885     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
886     XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
887     XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
888     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
889     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
890     XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
891     XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
892     XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
893     XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
894     XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
895     XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
896     XCAST(SetTexture) Main_IDirect3DDeviceImpl_3_SetTexture,
897     XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
898     XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
899     XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
900 };
901
902 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
903 #undef XCAST
904 #endif
905
906
907 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
908 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice2.fun))
909 #else
910 # define XCAST(fun)     (void*)
911 #endif
912
913 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
914 {
915     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
916     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
917     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
918     XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
919     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
920     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
921     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
922     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
923     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
924     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
925     XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
926     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
927     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
928     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
929     XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
930     XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
931     XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
932     XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
933     XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
934     XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
935     XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
936     XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
937     XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
938     XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
939     XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
940     XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
941     XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
942     XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
943     XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
944     XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
945     XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
946     XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
947     XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
948     XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
949 };
950
951 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
952 #undef XCAST
953 #endif
954
955
956 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
957 # define XCAST(fun)     (typeof(VTABLE_IDirect3DDevice.fun))
958 #else
959 # define XCAST(fun)     (void*)
960 #endif
961
962 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
963 {
964     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
965     XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
966     XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
967     XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
968     XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
969     XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
970     XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
971     XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
972     XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
973     XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
974     XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
975     XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
976     XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
977     XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
978     XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
979     XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
980     XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
981     XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
982     XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
983     XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
984     XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
985     XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
986     XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
987 };
988
989 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
990 #undef XCAST
991 #endif
992
993
994
995
996 HRESULT
997 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
998 {
999     IDirect3DDeviceImpl *object;
1000     IDirect3DDeviceGLImpl *gl_object;
1001     IDirectDrawSurfaceImpl *surf;
1002     HDC device_context;
1003     XVisualInfo *vis;
1004     int num;
1005     XVisualInfo template;
1006     
1007     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1008     if (object == NULL) return DDERR_OUTOFMEMORY;
1009
1010     gl_object = (IDirect3DDeviceGLImpl *) object;
1011     
1012     object->ref = 1;
1013     object->d3d = d3d;
1014     object->surface = surface;
1015     object->viewport_list = NULL;
1016     object->current_viewport = NULL;
1017     object->current_texture = NULL;
1018     object->set_context = set_context;
1019     
1020     TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1021
1022     device_context = GetDC(surface->ddraw_owner->window);
1023     gl_object->display = get_display(device_context);
1024     gl_object->drawable = get_drawable(device_context);
1025     ReleaseDC(surface->ddraw_owner->window,device_context);
1026     
1027     ENTER_GL();
1028     template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1029     vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1030     if (vis == NULL) {
1031         HeapFree(GetProcessHeap(), 0, object);
1032         ERR("No visual found !\n");
1033         LEAVE_GL();
1034         return DDERR_INVALIDPARAMS;
1035     } else {
1036         TRACE(" visual found\n");
1037     }
1038
1039     gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1040                                              NULL, GL_TRUE);
1041
1042     if (gl_object->gl_context == NULL) {
1043         HeapFree(GetProcessHeap(), 0, object);
1044         ERR("Error in context creation !\n");
1045         LEAVE_GL();
1046         return DDERR_INVALIDPARAMS;
1047     } else {
1048         TRACE(" context created (%p)\n", gl_object->gl_context);
1049     }
1050     
1051     /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1052     for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1053         if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1054             surface->surface_owner->aux_ctx  = (LPVOID) gl_object->display;
1055             surface->surface_owner->aux_data = (LPVOID) gl_object->drawable;
1056             surface->surface_owner->aux_flip = opengl_flip;
1057             break;
1058         }
1059     }
1060     
1061     gl_object->render_state.src = GL_ONE;
1062     gl_object->render_state.dst = GL_ZERO;
1063     gl_object->render_state.mag = GL_NEAREST;
1064     gl_object->render_state.min = GL_NEAREST;
1065     gl_object->vertex_type = 0;
1066
1067     /* Allocate memory for the matrices */
1068     gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1069     gl_object->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1070     gl_object->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1071
1072     memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1073     memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1074     memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1075
1076     /* Initialisation */
1077     TRACE(" setting current context\n");
1078     LEAVE_GL();
1079     object->set_context(object);
1080     ENTER_GL();
1081     TRACE(" current context set\n");
1082     glClearColor(0.0, 0.0, 0.0, 0.0);
1083     glColor3f(1.0, 1.0, 1.0);
1084     LEAVE_GL();
1085
1086     fill_device_capabilities(d3d->ddraw);    
1087     
1088     ICOM_INIT_INTERFACE(object, IDirect3DDevice,  VTABLE_IDirect3DDevice);
1089     ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1090     ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1091     ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1092
1093     *obj = object;
1094
1095     TRACE(" creating implementation at %p.\n", *obj);
1096     
1097     return DD_OK;
1098 }