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