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