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