Comment out/ifdef out unused code and variables.
[wine] / dlls / ddraw / d3ddevice / mesa.c
1 /* Direct3D Device
2    (c) 1998 Lionel ULMER
3    
4    This files contains the MESA implementation of all the D3D devices that
5    Wine supports. */
6
7 #include "config.h"
8
9 #include <string.h>
10
11 #include "windef.h"
12 #include "winerror.h"
13 #include "wine/obj_base.h"
14 #include "ddraw.h"
15 #include "d3d.h"
16 #include "debugtools.h"
17
18 #include "mesa_private.h"
19
20 DEFAULT_DEBUG_CHANNEL(ddraw);
21
22 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
23 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
24
25 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
26    on Mesa's home page) or version 3.1b.
27
28    Version 3.1b2 should correct this bug */
29 #undef HAVE_BUGGY_MESAGL
30
31 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
32
33 #ifndef HAVE_GLEXT_PROTOTYPES
34 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
35 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
36                                          GLsizei width, GLenum format, GLenum type,
37                                          const GLvoid *table);
38 #endif
39
40 static const float id_mat[16] = {
41   1.0, 0.0, 0.0, 0.0,
42   0.0, 1.0, 0.0, 0.0,
43   0.0, 0.0, 1.0, 0.0,
44   0.0, 0.0, 0.0, 1.0
45 };
46
47 /*******************************************************************************
48  *                              OpenGL static functions
49  */
50 static void set_context(IDirect3DDevice2Impl* This) {
51 #if COMPILABLE
52     D3DDPRIVATE(This);
53
54     if (glXMakeCurrent(gdi_display,ddpriv->drawable, odev->ctx) == False) {
55         ERR("Error in setting current context (context %p drawable %ld)!\n",
56             odev->ctx, ddpriv->drawable);
57     }
58 #endif
59 }
60
61 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
62 {
63   pc->dwSize = sizeof(*pc);
64   pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
65     D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
66   pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
67     D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
68   pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
69   pc->dwSrcBlendCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
70   pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
71   pc->dwAlphaCmpCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
72   pc->dwShadeCaps = 0xFFFFFFFF;     /* FIXME: need REAL values */
73   pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
74     D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
75   pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
76     D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
77   pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
78   pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
79   pc->dwStippleWidth = 32;
80   pc->dwStippleHeight = 32;
81 }
82
83 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
84 {
85   /* GLint maxlight; */
86   
87   d1->dwSize  = sizeof(*d1);
88   d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
89     | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
90   d1->dcmColorModel = D3DCOLOR_RGB;
91   d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
92     D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
93       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
94   d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
95   d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
96   d1->bClipping = TRUE;
97   d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
98   d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
99   d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
100   d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
101   fill_opengl_primcaps(&(d1->dpcLineCaps));
102   fill_opengl_primcaps(&(d1->dpcTriCaps));  
103   d1->dwDeviceRenderBitDepth  = DDBD_16;
104   d1->dwDeviceZBufferBitDepth = DDBD_16;
105   d1->dwMaxBufferSize = 0;
106   d1->dwMaxVertexCount = 65536;
107   d1->dwMinTextureWidth  = 1;
108   d1->dwMinTextureHeight = 1;
109   d1->dwMaxTextureWidth  = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
110   d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
111   d1->dwMinStippleWidth  = 1;
112   d1->dwMinStippleHeight = 1;
113   d1->dwMaxStippleWidth  = 32;
114   d1->dwMaxStippleHeight = 32;
115
116   d2->dwSize  = sizeof(*d2);
117   d2->dwFlags = 0;
118 }
119
120 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
121 #if COMPILABLE
122   x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
123   const char *ext_string;
124   Mesa_DeviceCapabilities *devcap;
125   
126   private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
127   devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
128   
129   ENTER_GL();
130   ext_string = glGetString(GL_EXTENSIONS);
131   /* Query for the ColorTable Extension */
132   if (strstr(ext_string, "GL_EXT_paletted_texture")) {
133     devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
134     TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
135   } else {
136     TRACE("Color table extension not found.\n");
137   }
138   LEAVE_GL();
139 #endif
140 }
141
142 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
143   D3DDEVICEDESC d1,d2;
144   TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL));
145   fill_opengl_caps(&d1, &d2);
146   return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context);
147 }
148
149 int
150 is_OpenGL(
151     REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
152     IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
153 ) {
154   mesa_d3dd_private *odev = NULL;
155
156   if (/* Default device */
157       (rguid == NULL) ||
158       /* HAL Device */
159       (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
160       /* OpenGL Device */
161       (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
162     
163     *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
164     (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
165     odev = (mesa_d3dd_private*)(*device)->private;
166     (*device)->ref = 1;
167     ICOM_VTBL(*device) = &OpenGL_vtable;
168     (*device)->d3d = d3d;
169     (*device)->surface = surface;
170     (*device)->viewport_list = NULL;
171     (*device)->current_viewport = NULL;
172     (*device)->set_context = set_context;
173     
174     TRACE("Creating OpenGL device for surface %p\n", surface);
175     /* Create the OpenGL context */
176 #if COMPILABLE
177     /* First get the correct visual */
178     ENTER_GL();
179     /* Create the context */
180     {
181       XVisualInfo *vis;
182       int num;
183       XVisualInfo template;
184
185       template.visualid = XVisualIDFromVisual(visual);
186       vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
187
188       odev->ctx = glXCreateContext(gdi_display, vis,
189                                    NULL, GL_TRUE);
190     }
191     
192     if (odev->ctx == NULL)
193       ERR("Error in context creation !\n");
194     else
195       TRACE("Context created (%p)\n", odev->ctx);
196     
197     /* Now override the surface's Flip method (if in double buffering) */
198     ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
199     {
200         int i;
201         struct _surface_chain *chain = surface->s.chain;
202         for (i=0;i<chain->nrofsurfaces;i++)
203           if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
204               ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
205     }
206 #endif
207
208     odev->rs.src = GL_ONE;
209     odev->rs.dst = GL_ZERO;
210     odev->rs.mag = GL_NEAREST;
211     odev->rs.min = GL_NEAREST;
212     odev->vt     = 0;
213
214     /* Allocate memory for the matrices */
215     odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
216     odev->view_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
217     odev->proj_mat  = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
218     
219     memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
220     memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
221     memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
222
223     /* Initialisation */
224     TRACE("Setting current context\n");
225     (*device)->set_context(*device);
226     TRACE("Current context set\n");
227     glClearColor(0.0, 0.0, 0.0, 0.0);
228     glColor3f(1.0, 1.0, 1.0);
229     LEAVE_GL();
230
231     fill_device_capabilities(d3d->ddraw);
232     
233     TRACE("OpenGL device created \n");
234     return 1;
235   }
236   FIXME("bad IID %s\n",debugstr_guid(rguid));
237   /* This is not the OpenGL UID */
238   return 0;
239 }
240
241 /*******************************************************************************
242  *                              MESA IDirect3DDevice2
243  */
244 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
245 {
246   ICOM_THIS(IDirect3DDevice2Impl,iface);
247   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
248   
249   if (!--(This->ref)) {
250 #if 0  /* broken for now */
251     D3DDPRIVATE(This);
252     ENTER_GL();
253     glXDestroyContext(gdi_display, odev->ctx);
254     LEAVE_GL();
255 #endif
256     This->private = NULL;
257     HeapFree(GetProcessHeap(),0,This);
258     return 0;
259   }
260   return This->ref;
261 }
262
263 /*** IDirect3DDevice2 methods ***/
264 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
265     LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
266     LPD3DDEVICEDESC lpdeschard
267 ) {
268   ICOM_THIS(IDirect3DDevice2Impl,iface);
269   FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
270   fill_opengl_caps(lpdescsoft, lpdeschard);
271   return DD_OK;
272 }
273
274 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
275                                           LPVOID context) {
276   DDSURFACEDESC sdesc;
277   LPDDPIXELFORMAT pformat;
278
279   /* Do the texture enumeration */
280   sdesc.dwSize = sizeof(DDSURFACEDESC);
281   sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
282   sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
283   pformat = &(sdesc.ddpfPixelFormat);
284   pformat->dwSize = sizeof(DDPIXELFORMAT);
285   pformat->dwFourCC = 0;
286   
287   TRACE("Enumerating GL_RGBA unpacked (32)\n");
288   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
289   pformat->u1.dwRGBBitCount = 32;
290   pformat->u2.dwRBitMask =         0xFF000000;
291   pformat->u3.dwGBitMask =         0x00FF0000;
292   pformat->u4.dwBBitMask =        0x0000FF00;
293   pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
294   if (cb(&sdesc, context) == 0)
295     return DD_OK;
296
297   TRACE("Enumerating GL_RGB unpacked (24)\n");
298   pformat->dwFlags = DDPF_RGB;
299   pformat->u1.dwRGBBitCount = 24;
300   pformat->u2.dwRBitMask =  0x00FF0000;
301   pformat->u3.dwGBitMask =  0x0000FF00;
302   pformat->u4.dwBBitMask = 0x000000FF;
303   pformat->u5.dwRGBAlphaBitMask = 0x00000000;
304   if (cb(&sdesc, context) == 0)
305     return DD_OK;
306
307 #ifndef HAVE_BUGGY_MESAGL
308   /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
309      so that future version will work great. */
310   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
311   pformat->dwFlags = DDPF_RGB;
312   pformat->u1.dwRGBBitCount = 16;
313   pformat->u2.dwRBitMask =  0x0000F800;
314   pformat->u3.dwGBitMask =  0x000007E0;
315   pformat->u4.dwBBitMask = 0x0000001F;
316   pformat->u5.dwRGBAlphaBitMask = 0x00000000;
317   if (cb(&sdesc, context) == 0)
318     return DD_OK;
319
320   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
321   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
322   pformat->u1.dwRGBBitCount = 16;
323   pformat->u2.dwRBitMask =         0x0000F800;
324   pformat->u3.dwGBitMask =         0x000007C0;
325   pformat->u4.dwBBitMask =        0x0000003E;
326   pformat->u5.dwRGBAlphaBitMask = 0x00000001;
327   if (cb(&sdesc, context) == 0)
328     return DD_OK;
329
330   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
331   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
332   pformat->u1.dwRGBBitCount = 16;
333   pformat->u2.dwRBitMask =         0x0000F000;
334   pformat->u3.dwGBitMask =         0x00000F00;
335   pformat->u4.dwBBitMask =        0x000000F0;
336   pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
337   if (cb(&sdesc, context) == 0)
338     return DD_OK;
339
340   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
341   pformat->dwFlags = DDPF_RGB;
342   pformat->u1.dwRGBBitCount = 8;
343   pformat->u2.dwRBitMask =         0x0000F800;
344   pformat->u3.dwGBitMask =         0x000007C0;
345   pformat->u4.dwBBitMask =        0x0000003E;
346   pformat->u5.dwRGBAlphaBitMask = 0x00000001;
347   if (cb(&sdesc, context) == 0)
348     return DD_OK;
349 #endif
350
351   TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
352   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
353   pformat->u1.dwRGBBitCount = 16;
354   pformat->u2.dwRBitMask =         0x00007C00;
355   pformat->u3.dwGBitMask =         0x000003E0;
356   pformat->u4.dwBBitMask =         0x0000001F;
357   pformat->u5.dwRGBAlphaBitMask =  0x00008000;
358   if (cb(&sdesc, context) == 0)
359     return DD_OK;  
360   
361   TRACE("Enumerating Paletted (8)\n");
362   pformat->dwFlags = DDPF_PALETTEINDEXED8;
363   pformat->u1.dwRGBBitCount = 8;
364   pformat->u2.dwRBitMask =  0x00000000;
365   pformat->u3.dwGBitMask =  0x00000000;
366   pformat->u4.dwBBitMask = 0x00000000;
367   pformat->u5.dwRGBAlphaBitMask = 0x00000000;
368   if (cb(&sdesc, context) == 0)
369     return DD_OK;
370   
371   TRACE("End of enumeration\n");
372   
373   return DD_OK;
374 }
375
376 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
377     LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
378 ) {
379   ICOM_THIS(IDirect3DDevice2Impl,iface);
380   FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
381   
382   return enum_texture_format_OpenGL(cb, context);
383 }
384
385 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
386     LPDIRECT3DDEVICE2 iface
387 ) {
388   ICOM_THIS(IDirect3DDevice2Impl,iface);
389   
390   FIXME("(%p)->(): stub\n", This);
391   
392   /* Here, we should get the DDraw surface and 'copy it' to the
393      OpenGL surface.... */
394   
395   return DD_OK;
396 }
397
398 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
399   ICOM_THIS(IDirect3DDevice2Impl,iface);
400
401   FIXME("(%p)->(): stub\n", This);
402
403   /* No need to do anything here... */
404   
405   return DD_OK;
406 }
407
408 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
409     LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
410     DWORD dwRenderState
411 ) {
412   ICOM_THIS(IDirect3DDevice2Impl,iface);
413   D3DDPRIVATE(This);
414
415   TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
416   
417   /* Call the render state functions */
418   set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
419   
420   return DD_OK;
421 }
422
423 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
424     LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
425     DWORD dwLightState
426 ) {
427   ICOM_THIS(IDirect3DDevice2Impl,iface);
428   FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
429   
430   switch (dwLightStateType) {
431   case D3DLIGHTSTATE_MATERIAL: {  /* 1 */
432     IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
433     
434     if (mat != NULL) {
435       ENTER_GL();
436       mat->activate(mat);
437       LEAVE_GL();
438     } else {
439       TRACE("Zoups !!!\n");
440     }
441   } break;
442     
443   case D3DLIGHTSTATE_AMBIENT: {   /* 2 */
444     float light[4];
445     
446     light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
447     light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
448     light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
449     light[3] = 1.0;
450     ENTER_GL();
451     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
452     LEAVE_GL();
453   } break;
454
455 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
456   UNSUP(COLORMODEL);
457   UNSUP(FOGMODE);
458   UNSUP(FOGSTART);
459   UNSUP(FOGEND);
460   UNSUP(FOGDENSITY);
461 #undef UNSUP
462   default:
463     TRACE("Unexpected Light State Type\n");
464     return DDERR_INVALIDPARAMS;
465   }
466   
467   return DD_OK;
468 }
469
470 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
471     LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
472     LPD3DMATRIX lpmatrix
473 ) {
474   ICOM_THIS(IDirect3DDevice2Impl,iface);
475   D3DDPRIVATE(This);
476   
477   FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
478   
479   ENTER_GL();
480   
481   /* Using a trial and failure approach, I found that the order of 
482      Direct3D transformations that works best is :
483
484      ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
485
486      As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
487      OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
488
489      If anyone has a good explanation of the three different matrices in
490      the SDK online documentation, feel free to point it to me. For example,
491      which matrices transform lights ? In OpenGL only the PROJECTION matrix
492      transform the lights, not the MODELVIEW. Using the matrix names, I 
493      supposed that PROJECTION and VIEW (all 'camera' related names) do
494      transform lights, but WORLD do not. It may be wrong though... */
495
496   /* After reading through both OpenGL and Direct3D documentations, I
497      thought that D3D matrices were written in 'line major mode' transposed
498      from OpenGL's 'column major mode'. But I found out that a simple memcpy
499      works fine to transfer one matrix format to the other (it did not work
500      when transposing)....
501
502      So :
503       1) are the documentations wrong
504       2) does the matrix work even if they are not read correctly
505       3) is Mesa's implementation of OpenGL not compliant regarding Matrix
506          loading using glLoadMatrix ?
507
508      Anyway, I always use 'conv_mat' to transfer the matrices from one format
509      to the other so that if I ever find out that I need to transpose them, I
510      will able to do it quickly, only by changing the macro conv_mat. */
511
512   switch (d3dts) {
513   case D3DTRANSFORMSTATE_WORLD: {
514     conv_mat(lpmatrix, odev->world_mat);
515     glMatrixMode(GL_MODELVIEW);
516     glLoadMatrixf((float *) odev->world_mat);
517   } break;
518     
519   case D3DTRANSFORMSTATE_VIEW: {
520     conv_mat(lpmatrix, odev->view_mat);
521     glMatrixMode(GL_PROJECTION);
522     glLoadMatrixf((float *) odev->proj_mat);
523     glMultMatrixf((float *) odev->view_mat);
524   } break;
525     
526   case D3DTRANSFORMSTATE_PROJECTION: {
527     conv_mat(lpmatrix, odev->proj_mat);
528     glMatrixMode(GL_PROJECTION);
529     glLoadMatrixf((float *) odev->proj_mat);
530     glMultMatrixf((float *) odev->view_mat);
531   } break;
532     
533   default:
534     break;
535   }
536   LEAVE_GL();
537   return DD_OK;
538 }
539
540 #define DRAW_PRIMITIVE(MAXVERT,INDEX)                                   \
541   /* Puts GL in the correct lighting mode */                            \
542   if (odev->vt != d3dv) {                                               \
543     if (odev->vt == D3DVT_TLVERTEX) {                                   \
544       /* Need to put the correct transformation again */                \
545       glMatrixMode(GL_MODELVIEW);                                       \
546       glLoadMatrixf((float *) odev->world_mat);                      \
547       glMatrixMode(GL_PROJECTION);                                      \
548       glLoadMatrixf((float *) odev->proj_mat);                  \
549       glMultMatrixf((float *) odev->view_mat);                  \
550     }                                                                   \
551                                                                         \
552     switch (d3dv) {                                                     \
553     case D3DVT_VERTEX:                                                  \
554       TRACE("Standard Vertex\n");                                       \
555       glEnable(GL_LIGHTING);                                            \
556       break;                                                            \
557                                                                         \
558     case D3DVT_LVERTEX:                                                 \
559       TRACE("Lighted Vertex\n");                                        \
560       glDisable(GL_LIGHTING);                                           \
561       break;                                                            \
562                                                                         \
563     case D3DVT_TLVERTEX: {                                              \
564       GLdouble height, width, minZ, maxZ;                               \
565                                                                         \
566       TRACE("Transformed - Lighted Vertex\n");                          \
567       /* First, disable lighting */                                     \
568       glDisable(GL_LIGHTING);                                           \
569                                                                         \
570       /* Then do not put any transformation matrixes */                 \
571       glMatrixMode(GL_MODELVIEW);                                       \
572       glLoadIdentity();                                                 \
573       glMatrixMode(GL_PROJECTION);                                      \
574       glLoadIdentity();                                                 \
575                                                                         \
576       if (This->current_viewport == NULL) {                             \
577         ERR("No current viewport !\n");                                 \
578         /* Using standard values */                                     \
579         height = 640.0;                                                 \
580         width = 480.0;                                                  \
581         minZ = -10.0;                                                   \
582         maxZ = 10.0;                                                    \
583       } else {                                                          \
584         if (This->current_viewport->use_vp2) {                          \
585           height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
586           width  = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
587           minZ   = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
588           maxZ   = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
589         } else {                                                        \
590           height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
591           width  = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
592           minZ   = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
593           maxZ   = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
594         }                                                               \
595       }                                                                 \
596                                                                         \
597       glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);                   \
598     } break;                                                            \
599                                                                         \
600     default:                                                            \
601       ERR("Unhandled vertex type\n");                                   \
602       break;                                                            \
603     }                                                                   \
604                                                                         \
605     odev->vt = d3dv;                                                    \
606   }                                                                     \
607                                                                         \
608   switch (d3dp) {                                                       \
609   case D3DPT_POINTLIST:                                                 \
610     TRACE("Start POINTS\n");                                            \
611     glBegin(GL_POINTS);                                                 \
612     break;                                                              \
613                                                                         \
614   case D3DPT_LINELIST:                                                  \
615     TRACE("Start LINES\n");                                             \
616     glBegin(GL_LINES);                                                  \
617     break;                                                              \
618                                                                         \
619   case D3DPT_LINESTRIP:                                                 \
620     TRACE("Start LINE_STRIP\n");                                        \
621     glBegin(GL_LINE_STRIP);                                             \
622     break;                                                              \
623                                                                         \
624   case D3DPT_TRIANGLELIST:                                              \
625     TRACE("Start TRIANGLES\n");                                         \
626     glBegin(GL_TRIANGLES);                                              \
627     break;                                                              \
628                                                                         \
629   case D3DPT_TRIANGLESTRIP:                                             \
630     TRACE("Start TRIANGLE_STRIP\n");                                    \
631     glBegin(GL_TRIANGLE_STRIP);                                         \
632     break;                                                              \
633                                                                         \
634   case D3DPT_TRIANGLEFAN:                                               \
635     TRACE("Start TRIANGLE_FAN\n");                                      \
636     glBegin(GL_TRIANGLE_FAN);                                           \
637     break;                                                              \
638                                                                         \
639   default:                                                              \
640     TRACE("Unhandled primitive\n");                                     \
641     break;                                                              \
642   }                                                                     \
643                                                                         \
644   /* Draw the primitives */                                             \
645   for (vx_index = 0; vx_index < MAXVERT; vx_index++) {                  \
646     switch (d3dv) {                                                     \
647     case D3DVT_VERTEX: {                                                \
648       D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX;                 \
649                                                                         \
650       glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);                      \
651       glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);                         \
652       TRACE("   V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);          \
653     } break;                                                            \
654                                                                         \
655     case D3DVT_LVERTEX: {                                               \
656       D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX;               \
657       DWORD col = vx->u4.color;                                         \
658                                                                         \
659       glColor3f(((col >> 16) & 0xFF) / 255.0,                           \
660                 ((col >>  8) & 0xFF) / 255.0,                           \
661                 ((col >>  0) & 0xFF) / 255.0);                          \
662       glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);                         \
663       TRACE("  LV: %f %f %f (%02lx %02lx %02lx)\n",                     \
664             vx->u1.x, vx->u2.y, vx->u3.z,                               \
665             ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF));\
666     } break;                                                            \
667                                                                         \
668     case D3DVT_TLVERTEX: {                                              \
669       D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX;             \
670       DWORD col = vx->u5.color;                                         \
671                                                                         \
672       glColor3f(((col >> 16) & 0xFF) / 255.0,                           \
673                 ((col >>  8) & 0xFF) / 255.0,                           \
674                 ((col >>  0) & 0xFF) / 255.0);                          \
675       glTexCoord2f(vx->u7.tu, vx->u8.tv);                               \
676       if (vx->u4.rhw < 0.01)                                            \
677         glVertex3f(vx->u1.sx,                                           \
678                    vx->u2.sy,                                           \
679                    vx->u3.sz);                                          \
680       else                                                              \
681         glVertex4f(vx->u1.sx / vx->u4.rhw,                              \
682                    vx->u2.sy / vx->u4.rhw,                              \
683                    vx->u3.sz / vx->u4.rhw,                              \
684                    1.0 / vx->u4.rhw);                                   \
685       TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",        \
686             vx->u1.sx, vx->u2.sy, vx->u3.sz,                            \
687             ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),\
688             vx->u7.tu, vx->u8.tv, vx->u4.rhw);                          \
689     } break;                                                            \
690                                                                         \
691     default:                                                            \
692       FIXME("Unhandled vertex type\n");                                 \
693       break;                                                            \
694     }                                                                   \
695   }                                                                     \
696                                                                         \
697   glEnd();                                                              \
698   TRACE("End\n");
699
700
701 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
702     LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
703     LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
704 ) {
705   ICOM_THIS(IDirect3DDevice2Impl,iface);
706   D3DDPRIVATE(This);
707   int vx_index;
708   
709   TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
710
711   ENTER_GL();
712   DRAW_PRIMITIVE(vertcount, vx_index);
713   LEAVE_GL();
714     
715   return D3D_OK;
716 }
717       
718 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
719     LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
720     LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
721     DWORD dwFlags
722 ) {
723   ICOM_THIS(IDirect3DDevice2Impl,iface);
724   D3DDPRIVATE(This);
725   int vx_index;
726   
727   TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
728   
729   ENTER_GL();
730   DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
731   LEAVE_GL();
732   
733   return D3D_OK;
734 }
735
736 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
737     LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
738     LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
739 ) {
740     ICOM_THIS(IDirect3DDeviceImpl,iface);
741     TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
742     *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
743     return DD_OK;
744 }
745
746
747 /*******************************************************************************
748  *                              OpenGL-specific IDirect3DDevice2
749  */
750
751 /*******************************************************************************
752  *                              OpenGL-specific VTable
753  */
754
755 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable = 
756 {
757   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
758   IDirect3DDevice2Impl_QueryInterface,
759   IDirect3DDevice2Impl_AddRef,
760   MESA_IDirect3DDevice2Impl_Release,
761   /*** IDirect3DDevice2 methods ***/
762   MESA_IDirect3DDevice2Impl_GetCaps,
763   IDirect3DDevice2Impl_SwapTextureHandles,
764   IDirect3DDevice2Impl_GetStats,
765   IDirect3DDevice2Impl_AddViewport,
766   IDirect3DDevice2Impl_DeleteViewport,
767   IDirect3DDevice2Impl_NextViewport,
768   MESA_IDirect3DDevice2Impl_EnumTextureFormats,
769   MESA_IDirect3DDevice2Impl_BeginScene,
770   MESA_IDirect3DDevice2Impl_EndScene,
771   IDirect3DDevice2Impl_GetDirect3D,
772   
773   /*** DrawPrimitive API ***/
774   IDirect3DDevice2Impl_SetCurrentViewport,
775   IDirect3DDevice2Impl_GetCurrentViewport,
776   
777   IDirect3DDevice2Impl_SetRenderTarget,
778   IDirect3DDevice2Impl_GetRenderTarget,
779   
780   IDirect3DDevice2Impl_Begin,
781   IDirect3DDevice2Impl_BeginIndexed,
782   IDirect3DDevice2Impl_Vertex,
783   IDirect3DDevice2Impl_Index,
784   IDirect3DDevice2Impl_End,
785   
786   IDirect3DDevice2Impl_GetRenderState,
787   MESA_IDirect3DDevice2Impl_SetRenderState,
788   IDirect3DDevice2Impl_GetLightState,
789   MESA_IDirect3DDevice2Impl_SetLightState,
790   MESA_IDirect3DDevice2Impl_SetTransform,
791   IDirect3DDevice2Impl_GetTransform,
792   IDirect3DDevice2Impl_MultiplyTransform,
793   
794   MESA_IDirect3DDevice2Impl_DrawPrimitive,
795   MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
796   
797   IDirect3DDevice2Impl_SetClipStatus,
798   IDirect3DDevice2Impl_GetClipStatus,
799 };
800
801 /*******************************************************************************
802  *                              Direct3DDevice
803  */
804 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
805   D3DDEVICEDESC d1,d2;
806   
807   TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
808   
809   fill_opengl_caps(&d1, &d2);
810   
811   return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
812 }
813
814 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
815 {
816   if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
817     mesa_d3dd_private *odev;
818 #if 0 /* See below */
819     int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
820     XVisualInfo *xvis;
821 #endif
822        
823     *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
824     (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
825     odev = (mesa_d3dd_private*)(*device)->private;
826     (*device)->ref = 1;
827     ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
828     (*device)->d3d = NULL;
829     (*device)->surface = surface;
830     
831     (*device)->viewport_list = NULL;
832     (*device)->current_viewport = NULL;
833     
834     (*device)->set_context = (void*)set_context;
835     
836     TRACE("OpenGL device created \n");
837     
838     /* Create the OpenGL context */
839     /* First get the correct visual */
840     /* if (surface->s.backbuffer == NULL)
841        attributeList[3] = None; */
842 #if 0 /* non working currently */
843     ENTER_GL();
844     xvis = glXChooseVisual(gdi_display,
845                            DefaultScreen(gdi_display),
846                            attributeList);
847     if (xvis == NULL)
848       ERR("No visual found !\n");
849     else
850       TRACE("Visual found\n");
851     /* Create the context */
852     odev->ctx = glXCreateContext(gdi_display,
853                                  xvis,
854                                  NULL,
855                                  GL_TRUE);
856     TRACE("Context created\n");
857     
858     /* Now override the surface's Flip method (if in double buffering) */
859     surface->s.d3d_device = (void *) odev;
860     {
861         int i;
862         struct _surface_chain *chain = surface->s.chain;
863         for (i=0;i<chain->nrofsurfaces;i++)
864           if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
865               chain->surfaces[i]->s.d3d_device = (void *) odev;
866     }
867 #endif
868     odev->rs.src = GL_ONE;
869     odev->rs.dst = GL_ZERO;
870     odev->rs.mag = GL_NEAREST;
871     odev->rs.min = GL_NEAREST;
872
873     odev->world_mat = (LPD3DMATRIX) &id_mat;
874     odev->view_mat  = (LPD3DMATRIX) &id_mat;
875     odev->proj_mat  = (LPD3DMATRIX) &id_mat;
876
877     /* Initialisation */
878     (*device)->set_context(*device);
879     glClearColor(0.0, 0.0, 0.0, 0.0);
880     glColor3f(1.0, 1.0, 1.0);
881     
882     fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner);
883
884     return 1;
885   }
886   
887   /* This is not the OpenGL UID */
888   return DD_OK;
889 }
890
891 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
892 {
893   ICOM_THIS(IDirect3DDeviceImpl,iface);
894   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
895   
896   if (!--(This->ref)) {
897 #if 0  /* broken for now */
898     D3DDPRIVATE(This);
899     ENTER_GL();
900     glXDestroyContext(gdi_display, odev->ctx);
901     LEAVE_GL();
902 #endif
903     This->private = NULL;
904     HeapFree(GetProcessHeap(),0,This);
905     return 0;
906   }
907   return This->ref;
908 }
909
910 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
911     LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
912     LPVOID lpArg)
913 {
914   ICOM_THIS(IDirect3DDeviceImpl,iface);
915   TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
916   
917   return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
918 }
919
920
921 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
922 {
923   ICOM_THIS(IDirect3DDeviceImpl,iface);
924   /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
925   
926   FIXME("(%p)->(): stub\n", This);
927   
928   /* We get the pointer to the surface (should be done on flip) */
929   /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */
930   
931   return DD_OK;
932 }
933
934
935 /* This is for the moment copy-pasted from IDirect3DDevice2...
936    Will make a common function ... */
937 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
938 {
939   ICOM_THIS(IDirect3DDeviceImpl,iface);
940   
941   FIXME("(%p)->(): stub\n", This);
942
943   /* No need to do anything here... */
944   
945   return DD_OK;  
946 }
947
948 /*******************************************************************************
949  *                              Direct3DDevice VTable
950  */
951 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = 
952 {
953   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
954   IDirect3DDeviceImpl_QueryInterface,
955   IDirect3DDeviceImpl_AddRef,
956   MESA_IDirect3DDeviceImpl_Release,
957   IDirect3DDeviceImpl_Initialize,
958   IDirect3DDeviceImpl_GetCaps,
959   IDirect3DDeviceImpl_SwapTextureHandles,
960   MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
961   IDirect3DDeviceImpl_GetStats,
962   IDirect3DDeviceImpl_Execute,
963   IDirect3DDeviceImpl_AddViewport,
964   IDirect3DDeviceImpl_DeleteViewport,
965   IDirect3DDeviceImpl_NextViewport,
966   IDirect3DDeviceImpl_Pick,
967   IDirect3DDeviceImpl_GetPickRecords,
968   MESA_IDirect3DDeviceImpl_EnumTextureFormats,
969   IDirect3DDeviceImpl_CreateMatrix,
970   IDirect3DDeviceImpl_SetMatrix,
971   IDirect3DDeviceImpl_GetMatrix,
972   IDirect3DDeviceImpl_DeleteMatrix,
973   MESA_IDirect3DDeviceImpl_BeginScene,
974   MESA_IDirect3DDeviceImpl_EndScene,
975   IDirect3DDeviceImpl_GetDirect3D,
976 };