Ian Ward
[wine] / graphics / d3ddevices.c
1 /* Direct3D Device
2    (c) 1998 Lionel ULMER
3    
4    This files contains all the D3D devices that Wine supports. For the moment
5    only the 'OpenGL' target is supported. */
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 "d3d_private.h"
18
19 DEFAULT_DEBUG_CHANNEL(ddraw)
20
21 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
22    on Mesa's home page) or version 3.1b.
23
24    Version 3.1b2 should correct this bug */
25 #undef HAVE_BUGGY_MESAGL
26
27 #ifdef HAVE_MESAGL
28
29 static GUID IID_D3DDEVICE2_OpenGL = {
30   0x39a0da38,
31   0x7e57,
32   0x11d2,
33   { 0x8b,0x7c,0x0e,0x4e,0xd8,0x3c,0x2b,0x3c }
34 };
35
36 static GUID IID_D3DDEVICE_OpenGL = {
37   0x31416d44,
38   0x86ae,
39   0x11d2,
40   { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
41 };
42
43
44 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
45 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
46
47 /*******************************************************************************
48  *                              OpenGL static functions
49  */
50 static void set_context(IDirect3DDevice2Impl* This) {
51   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
52
53 #ifdef USE_OSMESA
54   OSMesaMakeCurrent(odev->ctx, odev->buffer,
55                     GL_UNSIGNED_BYTE,
56                     This->surface->s.surface_desc.dwWidth,
57                     This->surface->s.surface_desc.dwHeight);
58 #else
59   if (glXMakeCurrent(display,
60                      odev->common.surface->s.ddraw->d.drawable,
61                      odev->ctx) == False) {
62     ERR("Error in setting current context (context %p drawable %ld)!\n",
63         odev->ctx, odev->common.surface->s.ddraw->d.drawable);
64 }
65 #endif
66 }
67
68 static void set_context_dx3(IDirect3DDeviceImpl* This) {
69   OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
70
71 #ifdef USE_OSMESA
72   OSMesaMakeCurrent(odev->ctx, odev->buffer,
73                     GL_UNSIGNED_BYTE,
74                     This->surface->s.surface_desc.dwWidth,
75                     This->surface->s.surface_desc.dwHeight);
76 #else
77   if (glXMakeCurrent(display,
78                      odev->common.surface->s.ddraw->d.drawable,
79                      odev->ctx) == False) {
80     ERR("Error in setting current context !\n");
81   }
82 #endif
83 }
84
85 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
86 {
87   pc->dwSize = sizeof(*pc);
88   pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
89     D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
90   pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
91     D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
92   pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
93   pc->dwSrcBlendCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
94   pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
95   pc->dwAlphaCmpCaps  = 0xFFFFFFFF; /* FIXME: need REAL values */
96   pc->dwShadeCaps = 0xFFFFFFFF;     /* FIXME: need REAL values */
97   pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
98     D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
99   pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
100     D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
101   pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
102   pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
103   pc->dwStippleWidth = 32;
104   pc->dwStippleHeight = 32;
105 }
106
107 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
108 {
109   /* GLint maxlight; */
110   
111   d1->dwSize  = sizeof(*d1);
112   d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
113     | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
114   d1->dcmColorModel = D3DCOLOR_RGB;
115   d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
116     D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
117       D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
118   d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
119   d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
120   d1->bClipping = TRUE;
121   d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
122   d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
123   d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
124   d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
125   fill_opengl_primcaps(&(d1->dpcLineCaps));
126   fill_opengl_primcaps(&(d1->dpcTriCaps));  
127   d1->dwDeviceRenderBitDepth  = DDBD_16;
128   d1->dwDeviceZBufferBitDepth = DDBD_16;
129   d1->dwMaxBufferSize = 0;
130   d1->dwMaxVertexCount = 65536;
131   d1->dwMinTextureWidth  = 1;
132   d1->dwMinTextureHeight = 1;
133   d1->dwMaxTextureWidth  = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
134   d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
135   d1->dwMinStippleWidth  = 1;
136   d1->dwMinStippleHeight = 1;
137   d1->dwMaxStippleWidth  = 32;
138   d1->dwMaxStippleHeight = 32;
139
140   d2->dwSize  = sizeof(*d2);
141   d2->dwFlags = 0;
142 }
143
144 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
145   D3DDEVICEDESC d1,d2;
146   
147   TRACE(" Enumerating OpenGL D3D device.\n");
148   
149   fill_opengl_caps(&d1, &d2);
150   
151   return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
152 }
153
154 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
155 {
156   if (/* Default device */
157       (rguid == NULL) ||
158       /* HAL Device */
159       (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
160       /* OpenGL Device */
161       (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
162     OpenGL_IDirect3DDevice2 *odev;
163     
164     const float id_mat[16] = {
165       1.0, 0.0, 0.0, 0.0,
166       0.0, 1.0, 0.0, 0.0,
167       0.0, 0.0, 1.0, 0.0,
168       0.0, 0.0, 0.0, 1.0
169     };
170 #ifndef USE_OSMESA
171     int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
172     XVisualInfo *xvis;
173 #endif
174     
175     *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
176     odev = (OpenGL_IDirect3DDevice2 *) (*device);
177     (*device)->ref = 1;
178     (*device)->lpvtbl = &OpenGL_vtable;
179     (*device)->d3d = d3d;
180     (*device)->surface = surface;
181     
182     (*device)->viewport_list = NULL;
183     (*device)->current_viewport = NULL;
184     
185     (*device)->set_context = set_context;
186     
187     TRACE("Creating OpenGL device for surface %p\n", surface);
188     
189     /* Create the OpenGL context */
190 #ifdef USE_OSMESA
191     odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
192     odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
193                              surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
194 #else
195     /* First get the correct visual */
196     /* if (surface->s.backbuffer == NULL)
197        attributeList[3] = None; */
198     ENTER_GL();
199     xvis = glXChooseVisual(display,
200                            DefaultScreen(display),
201                            attributeList);
202     if (xvis == NULL)
203       ERR("No visual found !\n");
204     else
205       TRACE("Visual found\n");
206     /* Create the context */
207     odev->ctx = glXCreateContext(display,
208                                  xvis,
209                                  NULL,
210                                  GL_TRUE);
211     if (odev->ctx == NULL)
212       ERR("Error in context creation !\n");
213     else
214       TRACE("Context created (%p)\n", odev->ctx);
215     
216     /* Now override the surface's Flip method (if in double buffering) */
217     surface->s.d3d_device = (void *) odev;
218     {
219         int i;
220         struct _surface_chain *chain = surface->s.chain;
221         for (i=0;i<chain->nrofsurfaces;i++)
222           if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
223               chain->surfaces[i]->s.d3d_device = (void *) odev;
224     }
225 #endif
226     odev->rs.src = GL_ONE;
227     odev->rs.dst = GL_ZERO;
228     odev->rs.mag = GL_NEAREST;
229     odev->rs.min = GL_NEAREST;
230     odev->vt     = 0;
231     
232     memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
233     memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
234     memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
235
236     /* Initialisation */
237     TRACE("Setting current context\n");
238     (*device)->set_context(*device);
239     TRACE("Current context set\n");
240     glClearColor(0.0, 0.0, 0.0, 0.0);
241     glColor3f(1.0, 1.0, 1.0);
242     LEAVE_GL();
243     
244     TRACE("OpenGL device created \n");
245     
246     return 1;
247   }
248   
249   /* This is not the OpenGL UID */
250   return 0;
251 }
252
253 /*******************************************************************************
254  *                              Common IDirect3DDevice2
255  */
256
257 static HRESULT WINAPI IDirect3DDevice2Impl_QueryInterface(LPDIRECT3DDEVICE2 iface,
258                                                       REFIID riid,
259                                                       LPVOID* ppvObj)
260 {
261   ICOM_THIS(IDirect3DDevice2Impl,iface);
262   char xrefiid[50];
263   
264   WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
265   FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
266   
267   return S_OK;
268 }
269
270
271
272 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
273 {
274   ICOM_THIS(IDirect3DDevice2Impl,iface);
275   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
276   
277   return ++(This->ref);
278 }
279
280
281
282 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
283 {
284   ICOM_THIS(IDirect3DDevice2Impl,iface);
285   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
286   
287   if (!--(This->ref)) {
288     OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
289
290 #ifdef USE_OSMESA
291     OSMesaDestroyContext(odev->ctx);
292 #else
293     ENTER_GL();
294     glXDestroyContext(display,
295                       odev->ctx);
296     LEAVE_GL();
297 #endif
298     
299     HeapFree(GetProcessHeap(),0,This);
300     return 0;
301   }
302   
303   return This->ref;
304 }
305
306
307 /*** IDirect3DDevice2 methods ***/
308 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
309                                                LPD3DDEVICEDESC lpdescsoft,
310                                                LPD3DDEVICEDESC lpdeschard)
311 {
312   ICOM_THIS(IDirect3DDevice2Impl,iface);
313   FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
314   
315   fill_opengl_caps(lpdescsoft, lpdeschard);
316   
317   return DD_OK;
318 }
319
320
321
322 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
323                                                           LPDIRECT3DTEXTURE2 lptex1,
324                                                           LPDIRECT3DTEXTURE2 lptex2)
325 {
326   ICOM_THIS(IDirect3DDevice2Impl,iface);
327   FIXME("(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
328   
329   return DD_OK;
330 }
331
332
333
334 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
335                                                 LPD3DSTATS lpstats)
336 {
337   ICOM_THIS(IDirect3DDevice2Impl,iface);
338   FIXME("(%p)->(%p): stub\n", This, lpstats);
339   
340   return DD_OK;
341 }
342
343
344
345 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
346                                                    LPDIRECT3DVIEWPORT2 lpvp)
347 {
348   ICOM_THIS(IDirect3DDevice2Impl,iface);
349   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
350   FIXME("(%p)->(%p): stub\n", This, ilpvp);
351   
352   /* Adds this viewport to the viewport list */
353   ilpvp->next = This->viewport_list;
354   This->viewport_list = ilpvp;
355   
356   return DD_OK;
357 }
358
359
360
361 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
362                                                       LPDIRECT3DVIEWPORT2 lpvp)
363 {
364   ICOM_THIS(IDirect3DDevice2Impl,iface);
365   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
366   IDirect3DViewport2Impl *cur, *prev;
367   FIXME("(%p)->(%p): stub\n", This, lpvp);
368   
369   /* Finds this viewport in the list */
370   prev = NULL;
371   cur = This->viewport_list;
372   while ((cur != NULL) && (cur != ilpvp)) {
373     prev = cur;
374     cur = cur->next;
375   }
376   if (cur == NULL)
377     return DDERR_INVALIDOBJECT;
378   
379   /* And remove it */
380   if (prev == NULL)
381     This->viewport_list = cur->next;
382   else
383     prev->next = cur->next;
384   
385   return DD_OK;
386 }
387
388
389
390 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
391                                                     LPDIRECT3DVIEWPORT2 lpvp,
392                                                     LPDIRECT3DVIEWPORT2* lplpvp,
393                                                     DWORD dwFlags)
394 {
395   ICOM_THIS(IDirect3DDevice2Impl,iface);
396   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
397   IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
398   FIXME("(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
399   
400   switch (dwFlags) {
401   case D3DNEXT_NEXT:
402     *ilplpvp = ilpvp->next;
403     break;
404     
405   case D3DNEXT_HEAD:
406     *ilplpvp = This->viewport_list;
407     break;
408     
409   case D3DNEXT_TAIL:
410     ilpvp = This->viewport_list;
411     while (ilpvp->next != NULL)
412       ilpvp = ilpvp->next;
413     
414     *ilplpvp = ilpvp;
415     break;
416     
417   default:
418     return DDERR_INVALIDPARAMS;
419   }
420   
421   return DD_OK;
422 }
423
424 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
425                                           LPVOID context) {
426   DDSURFACEDESC sdesc;
427   LPDDPIXELFORMAT pformat;
428
429   /* Do the texture enumeration */
430   sdesc.dwSize = sizeof(DDSURFACEDESC);
431   sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
432   sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
433   pformat = &(sdesc.ddpfPixelFormat);
434   pformat->dwSize = sizeof(DDPIXELFORMAT);
435   pformat->dwFourCC = 0;
436   
437   TRACE("Enumerating GL_RGBA unpacked (32)\n");
438   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
439   pformat->x.dwRGBBitCount = 32;
440   pformat->y.dwRBitMask =         0xFF000000;
441   pformat->z.dwGBitMask =         0x00FF0000;
442   pformat->xx.dwBBitMask =        0x0000FF00;
443   pformat->xy.dwRGBAlphaBitMask = 0x000000FF;
444   if (cb(&sdesc, context) == 0)
445     return DD_OK;
446
447   TRACE("Enumerating GL_RGB unpacked (24)\n");
448   pformat->dwFlags = DDPF_RGB;
449   pformat->x.dwRGBBitCount = 24;
450   pformat->y.dwRBitMask =  0x00FF0000;
451   pformat->z.dwGBitMask =  0x0000FF00;
452   pformat->xx.dwBBitMask = 0x000000FF;
453   pformat->xy.dwRGBAlphaBitMask = 0x00000000;
454   if (cb(&sdesc, context) == 0)
455     return DD_OK;
456
457 #ifndef HAVE_BUGGY_MESAGL
458   /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
459      so that future version will work great. */
460   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
461   pformat->dwFlags = DDPF_RGB;
462   pformat->x.dwRGBBitCount = 16;
463   pformat->y.dwRBitMask =  0x0000F800;
464   pformat->z.dwGBitMask =  0x000007E0;
465   pformat->xx.dwBBitMask = 0x0000001F;
466   pformat->xy.dwRGBAlphaBitMask = 0x00000000;
467   if (cb(&sdesc, context) == 0)
468     return DD_OK;
469
470   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
471   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
472   pformat->x.dwRGBBitCount = 16;
473   pformat->y.dwRBitMask =         0x0000F800;
474   pformat->z.dwGBitMask =         0x000007C0;
475   pformat->xx.dwBBitMask =        0x0000003E;
476   pformat->xy.dwRGBAlphaBitMask = 0x00000001;
477   if (cb(&sdesc, context) == 0)
478     return DD_OK;
479
480   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
481   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
482   pformat->x.dwRGBBitCount = 16;
483   pformat->y.dwRBitMask =         0x0000F000;
484   pformat->z.dwGBitMask =         0x00000F00;
485   pformat->xx.dwBBitMask =        0x000000F0;
486   pformat->xy.dwRGBAlphaBitMask = 0x0000000F;
487   if (cb(&sdesc, context) == 0)
488     return DD_OK;
489
490   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
491   pformat->dwFlags = DDPF_RGB;
492   pformat->x.dwRGBBitCount = 8;
493   pformat->y.dwRBitMask =         0x0000F800;
494   pformat->z.dwGBitMask =         0x000007C0;
495   pformat->xx.dwBBitMask =        0x0000003E;
496   pformat->xy.dwRGBAlphaBitMask = 0x00000001;
497   if (cb(&sdesc, context) == 0)
498     return DD_OK;
499 #endif
500   
501   TRACE("Enumerating Paletted (8)\n");
502   pformat->dwFlags = DDPF_PALETTEINDEXED8;
503   pformat->x.dwRGBBitCount = 8;
504   pformat->y.dwRBitMask =  0x00000000;
505   pformat->z.dwGBitMask =  0x00000000;
506   pformat->xx.dwBBitMask = 0x00000000;
507   pformat->xy.dwRGBAlphaBitMask = 0x00000000;
508   if (cb(&sdesc, context) == 0)
509     return DD_OK;
510   
511   TRACE("End of enumeration\n");
512   
513   return DD_OK;
514 }
515
516 static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
517                                                           LPD3DENUMTEXTUREFORMATSCALLBACK cb,
518                                                           LPVOID context)
519 {
520   ICOM_THIS(IDirect3DDevice2Impl,iface);
521   FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
522   
523   return enum_texture_format_OpenGL(cb, context);
524 }
525
526
527
528 static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
529 {
530   ICOM_THIS(IDirect3DDevice2Impl,iface);
531   /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
532   
533   FIXME("(%p)->(): stub\n", This);
534   
535   /* Here, we should get the DDraw surface and 'copy it' to the
536      OpenGL surface.... */
537   
538   return DD_OK;
539 }
540
541
542
543 static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
544 {
545   ICOM_THIS(IDirect3DDevice2Impl,iface);
546 #ifdef USE_OSMESA
547   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
548   LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
549   DDSURFACEDESC sdesc;
550   int x,y;
551   unsigned char *src;
552   unsigned short *dest;
553 #endif
554   
555   FIXME("(%p)->(): stub\n", This);
556
557 #ifdef USE_OSMESA
558   /* Here we copy back the OpenGL scene to the the DDraw surface */
559   /* First, lock the surface */
560   IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
561
562   /* The copy the OpenGL buffer to this surface */
563   
564   /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
565      I am currently working on a set of patches for Mesa to have OSMesa support
566      16 bpp surfaces => we will able to render directly onto the surface, no
567      need to do a bpp conversion */
568   dest = (unsigned short *) sdesc.y.lpSurface;
569   src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
570   for (y = 0; y < sdesc.dwHeight; y++) {
571     unsigned char *lsrc = src;
572     
573     for (x = 0; x < sdesc.dwWidth ; x++) {
574       unsigned char r =  *lsrc++;
575       unsigned char g =  *lsrc++;
576       unsigned char b =  *lsrc++;
577       lsrc++; /* Alpha */
578       *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
579       
580       dest++;
581     }
582
583     src -= 4 * sdesc.dwWidth;
584   }
585
586   /* Unlock the surface */
587   IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
588 #else
589   /* No need to do anything here... */
590 #endif
591   
592   return DD_OK;
593 }
594
595
596
597 static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
598 {
599   ICOM_THIS(IDirect3DDevice2Impl,iface);
600   TRACE("(%p)->(%p): stub\n", This, lpd3d2);
601   
602   *lpd3d2 = (LPDIRECT3D2)This->d3d;
603   
604   return DD_OK;
605 }
606
607
608
609 /*** DrawPrimitive API ***/
610 static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
611                                                           LPDIRECT3DVIEWPORT2 lpvp)
612 {
613   ICOM_THIS(IDirect3DDevice2Impl,iface);
614   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
615   FIXME("(%p)->(%p): stub\n", This, ilpvp);
616   
617   /* Should check if the viewport was added or not */
618   
619   /* Set this viewport as the current viewport */
620   This->current_viewport = ilpvp;
621   
622   /* Activate this viewport */
623   ilpvp->device.active_device2 = This;
624   ilpvp->activate(ilpvp);
625   
626   return DD_OK;
627 }
628
629
630
631 static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
632                                                           LPDIRECT3DVIEWPORT2 *lplpvp)
633 {
634   ICOM_THIS(IDirect3DDevice2Impl,iface);
635   FIXME("(%p)->(%p): stub\n", This, lplpvp);
636   
637   /* Returns the current viewport */
638   *lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
639   
640   return DD_OK;
641 }
642
643
644
645 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
646                                                        LPDIRECTDRAWSURFACE lpdds,
647                                                        DWORD dwFlags)
648 {
649   ICOM_THIS(IDirect3DDevice2Impl,iface);
650   FIXME("(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
651   
652   return DD_OK;
653 }
654
655
656
657 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
658                                                        LPDIRECTDRAWSURFACE *lplpdds)
659 {
660   ICOM_THIS(IDirect3DDevice2Impl,iface);
661   FIXME("(%p)->(%p): stub\n", This, lplpdds);
662   
663   /* Returns the current rendering target (the surface on wich we render) */
664   *lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
665   
666   return DD_OK;
667 }
668
669
670
671 static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
672                                              D3DPRIMITIVETYPE d3dp,
673                                              D3DVERTEXTYPE d3dv,
674                                              DWORD dwFlags)
675 {
676   ICOM_THIS(IDirect3DDevice2Impl,iface);
677   FIXME("(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
678   
679   return DD_OK;
680 }
681
682
683
684 static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
685                                                     D3DPRIMITIVETYPE d3dp,
686                                                     D3DVERTEXTYPE d3dv,
687                                                     LPVOID lpvert,
688                                                     DWORD numvert,
689                                                     DWORD dwFlags)
690 {
691   ICOM_THIS(IDirect3DDevice2Impl,iface);
692   FIXME("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
693   
694   return DD_OK;
695 }
696
697
698
699 static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
700                                               LPVOID lpvert)
701 {
702   ICOM_THIS(IDirect3DDevice2Impl,iface);
703   FIXME("(%p)->(%p): stub\n", This, lpvert);
704   
705   return DD_OK;
706 }
707
708
709
710 static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
711                                              WORD index)
712 {
713   ICOM_THIS(IDirect3DDevice2Impl,iface);
714   FIXME("(%p)->(%d): stub\n", This, index);
715   
716   return DD_OK;
717 }
718
719
720
721 static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
722                                            DWORD dwFlags)
723 {
724   ICOM_THIS(IDirect3DDevice2Impl,iface);
725   FIXME("(%p)->(%08lx): stub\n", This, dwFlags);
726   
727   return DD_OK;
728 }
729
730
731
732
733 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
734                                                       D3DRENDERSTATETYPE d3drs,
735                                                       LPDWORD lprstate)
736 {
737   ICOM_THIS(IDirect3DDevice2Impl,iface);
738   FIXME("(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
739   
740   return DD_OK;
741 }
742
743
744
745 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
746                                                       D3DRENDERSTATETYPE dwRenderStateType,
747                                                       DWORD dwRenderState)
748 {
749   ICOM_THIS(IDirect3DDevice2Impl,iface);
750   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
751
752   TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
753   
754   /* Call the render state functions */
755   set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
756   
757   return DD_OK;
758 }
759
760
761
762 static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
763                                                      D3DLIGHTSTATETYPE d3dls,
764                                                      LPDWORD lplstate)
765 {
766   ICOM_THIS(IDirect3DDevice2Impl,iface);
767   FIXME("(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
768   
769   return DD_OK;
770 }
771
772
773
774 static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
775                                                      D3DLIGHTSTATETYPE dwLightStateType,
776                                                      DWORD dwLightState)
777 {
778   ICOM_THIS(IDirect3DDevice2Impl,iface);
779   FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
780   
781   switch (dwLightStateType) {
782   case D3DLIGHTSTATE_MATERIAL: {  /* 1 */
783     IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
784     
785     if (mat != NULL) {
786       ENTER_GL();
787       mat->activate(mat);
788       LEAVE_GL();
789     } else {
790       TRACE("Zoups !!!\n");
791     }
792   } break;
793     
794   case D3DLIGHTSTATE_AMBIENT: {   /* 2 */
795     float light[4];
796     
797     light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
798     light[1] = ((dwLightState >>  8) & 0xFF) / 255.0;
799     light[2] = ((dwLightState >>  0) & 0xFF) / 255.0;
800     light[3] = 1.0;
801     ENTER_GL();
802     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
803     LEAVE_GL();
804   } break;
805     
806   case D3DLIGHTSTATE_COLORMODEL:  /* 3 */
807     break;
808     
809   case D3DLIGHTSTATE_FOGMODE:     /* 4 */
810     break;
811     
812   case D3DLIGHTSTATE_FOGSTART:    /* 5 */
813     break;
814     
815   case D3DLIGHTSTATE_FOGEND:      /* 6 */
816     break;
817     
818   case D3DLIGHTSTATE_FOGDENSITY:  /* 7 */
819     break;
820     
821   default:
822     TRACE("Unexpected Light State Type\n");
823     return DDERR_INVALIDPARAMS;
824   }
825   
826   return DD_OK;
827 }
828
829
830
831 static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
832                                                     D3DTRANSFORMSTATETYPE d3dts,
833                                                     LPD3DMATRIX lpmatrix)
834 {
835   ICOM_THIS(IDirect3DDevice2Impl,iface);
836   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
837   
838   FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
839   
840   ENTER_GL();
841   
842   /* Using a trial and failure approach, I found that the order of 
843      Direct3D transformations that works best is :
844
845      ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
846
847      As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
848      OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
849
850      If anyone has a good explanation of the three different matrices in
851      the SDK online documentation, feel free to point it to me. For example,
852      which matrices transform lights ? In OpenGL only the PROJECTION matrix
853      transform the lights, not the MODELVIEW. Using the matrix names, I 
854      supposed that PROJECTION and VIEW (all 'camera' related names) do
855      transform lights, but WORLD do not. It may be wrong though... */
856
857   /* After reading through both OpenGL and Direct3D documentations, I
858      thought that D3D matrices were written in 'line major mode' transposed
859      from OpenGL's 'column major mode'. But I found out that a simple memcpy
860      works fine to transfer one matrix format to the other (it did not work
861      when transposing)....
862
863      So :
864       1) are the documentations wrong
865       2) does the matrix work even if they are not read correctly
866       3) is Mesa's implementation of OpenGL not compliant regarding Matrix
867          loading using glLoadMatrix ?
868
869      Anyway, I always use 'conv_mat' to transfer the matrices from one format
870      to the other so that if I ever find out that I need to transpose them, I
871      will able to do it quickly, only by changing the macro conv_mat. */
872
873   switch (d3dts) {
874   case D3DTRANSFORMSTATE_WORLD: {
875     conv_mat(lpmatrix, odev->world_mat);
876     glMatrixMode(GL_MODELVIEW);
877     glLoadMatrixf((float *) &(odev->world_mat));
878   } break;
879     
880   case D3DTRANSFORMSTATE_VIEW: {
881     conv_mat(lpmatrix, odev->view_mat);
882     glMatrixMode(GL_PROJECTION);
883     glLoadMatrixf((float *) &(odev->proj_mat));
884     glMultMatrixf((float *) &(odev->view_mat));
885   } break;
886     
887   case D3DTRANSFORMSTATE_PROJECTION: {
888     conv_mat(lpmatrix, odev->proj_mat);
889     glMatrixMode(GL_PROJECTION);
890     glLoadMatrixf((float *) &(odev->proj_mat));
891     glMultMatrixf((float *) &(odev->view_mat));
892   } break;
893     
894   default:
895     break;
896   }
897   
898   LEAVE_GL();
899   
900   return DD_OK;
901 }
902
903
904
905 static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
906                                                     D3DTRANSFORMSTATETYPE d3dts,
907                                                     LPD3DMATRIX lpmatrix)
908 {
909   ICOM_THIS(IDirect3DDevice2Impl,iface);
910   FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
911   
912   return DD_OK;
913 }
914
915
916
917 static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
918                                                          D3DTRANSFORMSTATETYPE d3dts,
919                                                          LPD3DMATRIX lpmatrix)
920 {
921   ICOM_THIS(IDirect3DDevice2Impl,iface);
922   FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
923   
924   return DD_OK;
925 }
926
927 #define DRAW_PRIMITIVE(MAXVERT,INDEX)                                           \
928   /* Puts GL in the correct lighting mode */                                    \
929   if (odev->vt != d3dv) {                                                       \
930     if (odev->vt == D3DVT_TLVERTEX) {                                           \
931       /* Need to put the correct transformation again */                        \
932       glMatrixMode(GL_MODELVIEW);                                               \
933       glLoadMatrixf((float *) &(odev->world_mat));                              \
934       glMatrixMode(GL_PROJECTION);                                              \
935       glLoadMatrixf((float *) &(odev->proj_mat));                               \
936       glMultMatrixf((float *) &(odev->view_mat));                               \
937     }                                                                           \
938                                                                                 \
939     switch (d3dv) {                                                             \
940     case D3DVT_VERTEX:                                                          \
941       TRACE("Standard Vertex\n");                                       \
942       glEnable(GL_LIGHTING);                                                    \
943       break;                                                                    \
944                                                                                 \
945     case D3DVT_LVERTEX:                                                         \
946       TRACE("Lighted Vertex\n");                                                \
947       glDisable(GL_LIGHTING);                                                   \
948       break;                                                                    \
949                                                                                 \
950     case D3DVT_TLVERTEX: {                                                      \
951       GLdouble height, width, minZ, maxZ;                                       \
952                                                                                 \
953       TRACE("Transformed - Lighted Vertex\n");                          \
954       /* First, disable lighting */                                             \
955       glDisable(GL_LIGHTING);                                                   \
956                                                                                 \
957       /* Then do not put any transformation matrixes */                         \
958       glMatrixMode(GL_MODELVIEW);                                               \
959       glLoadIdentity();                                                         \
960       glMatrixMode(GL_PROJECTION);                                              \
961       glLoadIdentity();                                                         \
962                                                                                 \
963       if (This->current_viewport == NULL) {                                     \
964         ERR("No current viewport !\n");                                 \
965         /* Using standard values */                                             \
966         height = 640.0;                                                         \
967         width = 480.0;                                                          \
968         minZ = -10.0;                                                           \
969         maxZ = 10.0;                                                            \
970       } else {                                                                  \
971         if (This->current_viewport->use_vp2) {                                  \
972           height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;    \
973           width  = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;     \
974           minZ   = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;      \
975           maxZ   = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;      \
976         } else {                                                                \
977           height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;    \
978           width  = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;     \
979           minZ   = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;      \
980           maxZ   = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;      \
981         }                                                                       \
982       }                                                                         \
983                                                                                 \
984       glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);                           \
985     } break;                                                                    \
986                                                                                 \
987     default:                                                                    \
988       ERR("Unhandled vertex type\n");                                   \
989       break;                                                                    \
990     }                                                                           \
991                                                                                 \
992     odev->vt = d3dv;                                                            \
993   }                                                                             \
994                                                                                 \
995   switch (d3dp) {                                                               \
996   case D3DPT_POINTLIST:                                                         \
997     TRACE("Start POINTS\n");                                            \
998     glBegin(GL_POINTS);                                                         \
999     break;                                                                      \
1000                                                                                 \
1001   case D3DPT_LINELIST:                                                          \
1002     TRACE("Start LINES\n");                                             \
1003     glBegin(GL_LINES);                                                          \
1004     break;                                                                      \
1005                                                                                 \
1006   case D3DPT_LINESTRIP:                                                         \
1007     TRACE("Start LINE_STRIP\n");                                                \
1008     glBegin(GL_LINE_STRIP);                                                     \
1009     break;                                                                      \
1010                                                                                 \
1011   case D3DPT_TRIANGLELIST:                                                      \
1012     TRACE("Start TRIANGLES\n");                                         \
1013     glBegin(GL_TRIANGLES);                                                      \
1014     break;                                                                      \
1015                                                                                 \
1016   case D3DPT_TRIANGLESTRIP:                                                     \
1017     TRACE("Start TRIANGLE_STRIP\n");                                    \
1018     glBegin(GL_TRIANGLE_STRIP);                                                 \
1019     break;                                                                      \
1020                                                                                 \
1021   case D3DPT_TRIANGLEFAN:                                                       \
1022     TRACE("Start TRIANGLE_FAN\n");                                      \
1023     glBegin(GL_TRIANGLE_FAN);                                                   \
1024     break;                                                                      \
1025                                                                                 \
1026   default:                                                                      \
1027     TRACE("Unhandled primitive\n");                                     \
1028     break;                                                                      \
1029   }                                                                             \
1030                                                                                 \
1031   /* Draw the primitives */                                                     \
1032   for (vx_index = 0; vx_index < MAXVERT; vx_index++) {                          \
1033     switch (d3dv) {                                                             \
1034     case D3DVT_VERTEX: {                                                        \
1035       D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX;                         \
1036                                                                                 \
1037       glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz);                              \
1038       glVertex3f(vx->x.x, vx->y.y, vx->z.z);                                    \
1039       TRACE("   V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z);             \
1040     } break;                                                                    \
1041                                                                                 \
1042     case D3DVT_LVERTEX: {                                                       \
1043       D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX;                       \
1044       DWORD col = vx->c.color;                                                  \
1045                                                                                 \
1046       glColor3f(((col >> 16) & 0xFF) / 255.0,                                   \
1047                 ((col >>  8) & 0xFF) / 255.0,                                   \
1048                 ((col >>  0) & 0xFF) / 255.0);                                  \
1049       glVertex3f(vx->x.x, vx->y.y, vx->z.z);                                    \
1050       TRACE("  LV: %f %f %f (%02lx %02lx %02lx)\n",                     \
1051             vx->x.x, vx->y.y, vx->z.z,                                          \
1052             ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF));  \
1053     } break;                                                                    \
1054                                                                                 \
1055     case D3DVT_TLVERTEX: {                                                      \
1056       D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX;                     \
1057       DWORD col = vx->c.color;                                                  \
1058                                                                                 \
1059       glColor3f(((col >> 16) & 0xFF) / 255.0,                                   \
1060                 ((col >>  8) & 0xFF) / 255.0,                                   \
1061                 ((col >>  0) & 0xFF) / 255.0);                                  \
1062       glTexCoord2f(vx->u.tu, vx->v.tv);                                         \
1063       if (vx->r.rhw < 0.01)                                                     \
1064         glVertex3f(vx->x.sx,                                                    \
1065                    vx->y.sy,                                                    \
1066                    vx->z.sz);                                                   \
1067       else                                                                      \
1068         glVertex4f(vx->x.sx / vx->r.rhw,                                        \
1069                    vx->y.sy / vx->r.rhw,                                        \
1070                    vx->z.sz / vx->r.rhw,                                        \
1071                    1.0 / vx->r.rhw);                                            \
1072       TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",                \
1073             vx->x.sx, vx->y.sy, vx->z.sz,                                       \
1074             ((col >> 16) & 0xFF), ((col >>  8) & 0xFF), ((col >>  0) & 0xFF),   \
1075             vx->u.tu, vx->v.tv, vx->r.rhw);                                     \
1076     } break;                                                                    \
1077                                                                                 \
1078     default:                                                                    \
1079       TRACE("Unhandled vertex type\n");                                 \
1080       break;                                                                    \
1081     }                                                                           \
1082   }                                                                             \
1083                                                                                 \
1084   glEnd();                                                                      \
1085   TRACE("End\n");
1086
1087
1088 static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1089                                                      D3DPRIMITIVETYPE d3dp,
1090                                                      D3DVERTEXTYPE d3dv,
1091                                                      LPVOID lpvertex,
1092                                                      DWORD vertcount,
1093                                                      DWORD dwFlags)
1094 {
1095   ICOM_THIS(IDirect3DDevice2Impl,iface);
1096   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1097   int vx_index;
1098   
1099   TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
1100
1101   ENTER_GL();
1102   DRAW_PRIMITIVE(vertcount, vx_index);
1103   LEAVE_GL();
1104     
1105   return D3D_OK;
1106       }
1107     
1108
1109       
1110 static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1111                                                             D3DPRIMITIVETYPE d3dp,
1112                                                             D3DVERTEXTYPE d3dv,
1113                                                             LPVOID lpvertex,
1114                                                             DWORD vertcount,
1115                                                             LPWORD lpindexes,
1116                                                             DWORD indexcount,
1117                                                             DWORD dwFlags)
1118 {
1119   ICOM_THIS(IDirect3DDevice2Impl,iface);
1120   OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1121   int vx_index;
1122   
1123   TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1124   
1125   ENTER_GL();
1126   DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1127   LEAVE_GL();
1128   
1129   return D3D_OK;
1130 }
1131
1132
1133
1134 static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
1135                                                      LPD3DCLIPSTATUS lpcs)
1136 {
1137   ICOM_THIS(IDirect3DDevice2Impl,iface);
1138   FIXME("(%p)->(%p): stub\n", This, lpcs);
1139   
1140   return DD_OK;
1141 }
1142
1143
1144
1145 static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
1146                                                      LPD3DCLIPSTATUS lpcs)
1147 {
1148   ICOM_THIS(IDirect3DDevice2Impl,iface);
1149   FIXME("(%p)->(%p): stub\n", This, lpcs);
1150   
1151   return DD_OK;
1152 }
1153
1154
1155
1156 /*******************************************************************************
1157  *                              OpenGL-specific IDirect3DDevice2
1158  */
1159
1160 /*******************************************************************************
1161  *                              OpenGL-specific VTable
1162  */
1163
1164 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable = 
1165 {
1166   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1167   IDirect3DDevice2Impl_QueryInterface,
1168   IDirect3DDevice2Impl_AddRef,
1169   IDirect3DDevice2Impl_Release,
1170   /*** IDirect3DDevice2 methods ***/
1171   IDirect3DDevice2Impl_GetCaps,
1172   IDirect3DDevice2Impl_SwapTextureHandles,
1173   IDirect3DDevice2Impl_GetStats,
1174   IDirect3DDevice2Impl_AddViewport,
1175   IDirect3DDevice2Impl_DeleteViewport,
1176   IDirect3DDevice2Impl_NextViewport,
1177   IDirect3DDevice2Impl_EnumTextureFormats,
1178   IDirect3DDevice2Impl_BeginScene,
1179   IDirect3DDevice2Impl_EndScene,
1180   IDirect3DDevice2Impl_GetDirect3D,
1181   
1182   /*** DrawPrimitive API ***/
1183   IDirect3DDevice2Impl_SetCurrentViewport,
1184   IDirect3DDevice2Impl_GetCurrentViewport,
1185   
1186   IDirect3DDevice2Impl_SetRenderTarget,
1187   IDirect3DDevice2Impl_GetRenderTarget,
1188   
1189   IDirect3DDevice2Impl_Begin,
1190   IDirect3DDevice2Impl_BeginIndexed,
1191   IDirect3DDevice2Impl_Vertex,
1192   IDirect3DDevice2Impl_Index,
1193   IDirect3DDevice2Impl_End,
1194   
1195   IDirect3DDevice2Impl_GetRenderState,
1196   IDirect3DDevice2Impl_SetRenderState,
1197   IDirect3DDevice2Impl_GetLightState,
1198   IDirect3DDevice2Impl_SetLightState,
1199   IDirect3DDevice2Impl_SetTransform,
1200   IDirect3DDevice2Impl_GetTransform,
1201   IDirect3DDevice2Impl_MultiplyTransform,
1202   
1203   IDirect3DDevice2Impl_DrawPrimitive,
1204   IDirect3DDevice2Impl_DrawIndexedPrimitive,
1205   
1206   IDirect3DDevice2Impl_SetClipStatus,
1207   IDirect3DDevice2Impl_GetClipStatus,
1208 };
1209
1210 /*******************************************************************************
1211  *                              Direct3DDevice
1212  */
1213 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1214   D3DDEVICEDESC d1,d2;
1215   
1216   TRACE(" Enumerating OpenGL D3D device.\n");
1217   
1218   fill_opengl_caps(&d1, &d2);
1219   
1220   return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1221 }
1222
1223 float id_mat[16] = {
1224   1.0, 0.0, 0.0, 0.0,
1225   0.0, 1.0, 0.0, 0.0,
1226   0.0, 0.0, 1.0, 0.0,
1227   0.0, 0.0, 0.0, 1.0
1228 };
1229
1230 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1231 {
1232   if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1233     OpenGL_IDirect3DDevice *odev;
1234 #ifndef USE_OSMESA
1235     int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
1236     XVisualInfo *xvis;
1237 #endif
1238        
1239     *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1240     odev = (OpenGL_IDirect3DDevice *) (*device);
1241     (*device)->ref = 1;
1242     (*device)->lpvtbl = &OpenGL_vtable_dx3;
1243     (*device)->d3d = NULL;
1244     (*device)->surface = surface;
1245     
1246     (*device)->viewport_list = NULL;
1247     (*device)->current_viewport = NULL;
1248     
1249     (*device)->set_context = set_context_dx3;
1250     
1251     TRACE("OpenGL device created \n");
1252     
1253     /* Create the OpenGL context */
1254 #ifdef USE_OSMESA
1255     odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1256     odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1257                              surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1258 #else
1259     /* First get the correct visual */
1260     /* if (surface->s.backbuffer == NULL)
1261        attributeList[3] = None; */
1262     ENTER_GL();
1263     xvis = glXChooseVisual(display,
1264                            DefaultScreen(display),
1265                            attributeList);
1266     if (xvis == NULL)
1267       ERR("No visual found !\n");
1268     else
1269       TRACE("Visual found\n");
1270     /* Create the context */
1271     odev->ctx = glXCreateContext(display,
1272                                  xvis,
1273                                  NULL,
1274                                  GL_TRUE);
1275     TRACE("Context created\n");
1276     
1277     /* Now override the surface's Flip method (if in double buffering) */
1278     surface->s.d3d_device = (void *) odev;
1279     {
1280         int i;
1281         struct _surface_chain *chain = surface->s.chain;
1282         for (i=0;i<chain->nrofsurfaces;i++)
1283           if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
1284               chain->surfaces[i]->s.d3d_device = (void *) odev;
1285     }
1286 #endif
1287     odev->rs.src = GL_ONE;
1288     odev->rs.dst = GL_ZERO;
1289     odev->rs.mag = GL_NEAREST;
1290     odev->rs.min = GL_NEAREST;
1291
1292     odev->world_mat = (LPD3DMATRIX) &id_mat;
1293     odev->view_mat  = (LPD3DMATRIX) &id_mat;
1294     odev->proj_mat  = (LPD3DMATRIX) &id_mat;
1295
1296     /* Initialisation */
1297     (*device)->set_context(*device);
1298     glClearColor(0.0, 0.0, 0.0, 0.0);
1299     glColor3f(1.0, 1.0, 1.0);
1300     
1301     return 1;
1302   }
1303   
1304   /* This is not the OpenGL UID */
1305   return DD_OK;
1306 }
1307
1308
1309 /*******************************************************************************
1310  *                              Direct3DDevice
1311  */
1312 static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
1313                                                      REFIID riid,
1314                                                      LPVOID* ppvObj)
1315 {
1316   ICOM_THIS(IDirect3DDeviceImpl,iface);
1317   char xrefiid[50];
1318   
1319   WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1320   FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
1321   
1322   return S_OK;
1323 }
1324
1325
1326
1327 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1328 {
1329   ICOM_THIS(IDirect3DDeviceImpl,iface);
1330   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
1331   
1332   return ++(This->ref);
1333 }
1334
1335
1336
1337 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1338 {
1339   ICOM_THIS(IDirect3DDeviceImpl,iface);
1340   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
1341   
1342   if (!--(This->ref)) {
1343     OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1344
1345 #ifdef USE_OSMESA
1346     OSMesaDestroyContext(odev->ctx);
1347 #else
1348     ENTER_GL();
1349     glXDestroyContext(display,
1350                       odev->ctx);
1351     LEAVE_GL();
1352 #endif    
1353     
1354     HeapFree(GetProcessHeap(),0,This);
1355     return 0;
1356   }
1357   
1358   return This->ref;
1359 }
1360
1361 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1362                                                  LPDIRECT3D lpd3d,
1363                                                  LPGUID lpGUID,
1364                                                  LPD3DDEVICEDESC lpd3ddvdesc)
1365 {
1366   ICOM_THIS(IDirect3DDeviceImpl,iface);
1367   TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1368   
1369   return DDERR_ALREADYINITIALIZED;
1370 }
1371
1372
1373 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1374                                               LPD3DDEVICEDESC lpD3DHWDevDesc,
1375                                               LPD3DDEVICEDESC lpD3DSWDevDesc)
1376 {
1377   ICOM_THIS(IDirect3DDeviceImpl,iface);
1378   TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1379
1380   fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);  
1381   
1382   return DD_OK;
1383 }
1384
1385
1386 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1387                                                          LPDIRECT3DTEXTURE lpD3DTex1,
1388                                                          LPDIRECT3DTEXTURE lpD3DTex2)
1389 {
1390   ICOM_THIS(IDirect3DDeviceImpl,iface);
1391   TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1392   
1393   return DD_OK;
1394 }
1395
1396 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1397                                                           LPD3DEXECUTEBUFFERDESC lpDesc,
1398                                                           LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1399                                                           IUnknown *pUnkOuter)
1400 {
1401   ICOM_THIS(IDirect3DDeviceImpl,iface);
1402   TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1403
1404   *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1405   
1406   return DD_OK;
1407 }
1408
1409
1410 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1411                                                LPD3DSTATS lpD3DStats)
1412 {
1413   ICOM_THIS(IDirect3DDeviceImpl,iface);
1414   TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
1415   
1416   return DD_OK;
1417 }
1418
1419
1420 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1421                                               LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1422                                               LPDIRECT3DVIEWPORT lpDirect3DViewport,
1423                                               DWORD dwFlags)
1424 {
1425   ICOM_THIS(IDirect3DDeviceImpl,iface);
1426   TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1427
1428   /* Put this as the default context */
1429
1430   /* Execute... */
1431   ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1432   
1433   return DD_OK;
1434 }
1435
1436 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1437                                                   LPDIRECT3DVIEWPORT lpvp)
1438 {
1439   ICOM_THIS(IDirect3DDeviceImpl,iface);
1440   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1441   FIXME("(%p)->(%p): stub\n", This, ilpvp);
1442   
1443   /* Adds this viewport to the viewport list */
1444   ilpvp->next = This->viewport_list;
1445   This->viewport_list = ilpvp;
1446   
1447   return DD_OK;
1448 }
1449
1450
1451
1452 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1453                                                      LPDIRECT3DVIEWPORT lpvp)
1454 {
1455   ICOM_THIS(IDirect3DDeviceImpl,iface);
1456   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1457   IDirect3DViewport2Impl *cur, *prev;
1458   FIXME("(%p)->(%p): stub\n", This, lpvp);
1459   
1460   /* Finds this viewport in the list */
1461   prev = NULL;
1462   cur = This->viewport_list;
1463   while ((cur != NULL) && (cur != ilpvp)) {
1464     prev = cur;
1465     cur = cur->next;
1466   }
1467   if (cur == NULL)
1468     return DDERR_INVALIDOBJECT;
1469   
1470   /* And remove it */
1471   if (prev == NULL)
1472     This->viewport_list = cur->next;
1473   else
1474     prev->next = cur->next;
1475   
1476   return DD_OK;
1477 }
1478
1479
1480
1481 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1482                                                    LPDIRECT3DVIEWPORT lpvp,
1483                                                    LPDIRECT3DVIEWPORT* lplpvp,
1484                                                    DWORD dwFlags)
1485 {
1486   ICOM_THIS(IDirect3DDeviceImpl,iface);
1487   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1488   IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1489   FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1490   
1491   switch (dwFlags) {
1492   case D3DNEXT_NEXT:
1493     *ilplpvp = ilpvp->next;
1494     break;
1495     
1496   case D3DNEXT_HEAD:
1497     *ilplpvp = This->viewport_list;
1498     break;
1499     
1500   case D3DNEXT_TAIL:
1501     ilpvp = This->viewport_list;
1502     while (ilpvp->next != NULL)
1503       ilpvp = ilpvp->next;
1504     
1505     *ilplpvp = ilpvp;
1506     break;
1507     
1508   default:
1509     return DDERR_INVALIDPARAMS;
1510   }
1511   
1512   return DD_OK;
1513 }
1514
1515 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1516                                            LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1517                                            LPDIRECT3DVIEWPORT lpDirect3DViewport,
1518                                            DWORD dwFlags,
1519                                            LPD3DRECT lpRect)
1520 {
1521   ICOM_THIS(IDirect3DDeviceImpl,iface);
1522   TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1523         dwFlags, lpRect);
1524   
1525   return DD_OK;
1526 }
1527
1528
1529 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1530                                                      LPDWORD lpCount,
1531                                                      LPD3DPICKRECORD lpD3DPickRec)
1532 {
1533   ICOM_THIS(IDirect3DDeviceImpl,iface);
1534   TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1535   
1536   return DD_OK;
1537 }
1538
1539
1540 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1541                                                          LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1542                                                          LPVOID lpArg)
1543 {
1544   ICOM_THIS(IDirect3DDeviceImpl,iface);
1545   TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1546   
1547   return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1548 }
1549
1550
1551 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1552                                                    LPD3DMATRIXHANDLE lpD3DMatHandle)
1553 {
1554   ICOM_THIS(IDirect3DDeviceImpl,iface);
1555   TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
1556
1557   *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1558   
1559   return DD_OK;
1560 }
1561
1562
1563 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1564                                                 D3DMATRIXHANDLE d3dMatHandle,
1565                                                 const LPD3DMATRIX lpD3DMatrix)
1566 {
1567   ICOM_THIS(IDirect3DDeviceImpl,iface);
1568   TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1569
1570   dump_mat(lpD3DMatrix);
1571   
1572   *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1573   
1574   return DD_OK;
1575 }
1576
1577
1578 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1579                                                 D3DMATRIXHANDLE D3DMatHandle,
1580                                                 LPD3DMATRIX lpD3DMatrix)
1581 {
1582   ICOM_THIS(IDirect3DDeviceImpl,iface);
1583   TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1584
1585   *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1586   
1587   return DD_OK;
1588 }
1589
1590
1591 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1592                                                    D3DMATRIXHANDLE d3dMatHandle)
1593 {
1594   ICOM_THIS(IDirect3DDeviceImpl,iface);
1595   TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
1596
1597   HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1598   
1599   return DD_OK;
1600 }
1601
1602
1603 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1604 {
1605   ICOM_THIS(IDirect3DDeviceImpl,iface);
1606   /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1607   
1608   FIXME("(%p)->(): stub\n", This);
1609   
1610   /* We get the pointer to the surface (should be done on flip) */
1611   /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1612   
1613   return DD_OK;
1614 }
1615
1616
1617 /* This is for the moment copy-pasted from IDirect3DDevice2...
1618    Will make a common function ... */
1619 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1620 {
1621   ICOM_THIS(IDirect3DDeviceImpl,iface);
1622 #ifdef USE_OSMESA
1623   OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1624   LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1625   DDSURFACEDESC sdesc;
1626   int x,y;
1627   unsigned char *src;
1628   unsigned short *dest;
1629 #endif
1630   
1631   FIXME("(%p)->(): stub\n", This);
1632
1633 #ifdef USE_OSMESA
1634   /* Here we copy back the OpenGL scene to the the DDraw surface */
1635   /* First, lock the surface */
1636   IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1637
1638   /* The copy the OpenGL buffer to this surface */
1639   
1640   /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1641      I am currently working on a set of patches for Mesa to have OSMesa support
1642      16 bpp surfaces => we will able to render directly onto the surface, no
1643      need to do a bpp conversion */
1644   dest = (unsigned short *) sdesc.y.lpSurface;
1645   src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1646   for (y = 0; y < sdesc.dwHeight; y++) {
1647     unsigned char *lsrc = src;
1648     
1649     for (x = 0; x < sdesc.dwWidth ; x++) {
1650       unsigned char r =  *lsrc++;
1651       unsigned char g =  *lsrc++;
1652       unsigned char b =  *lsrc++;
1653       lsrc++; /* Alpha */
1654
1655       *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1656       
1657       dest++;
1658     }
1659
1660     src -= 4 * sdesc.dwWidth;
1661   }
1662
1663   /* Unlock the surface */
1664   IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1665 #else
1666   /* No need to do anything here... */
1667 #endif
1668   
1669   return DD_OK;  
1670 }
1671
1672
1673 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1674                                                   LPDIRECT3D *lpDirect3D)
1675 {
1676   ICOM_THIS(IDirect3DDeviceImpl,iface);
1677   TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
1678
1679   return DD_OK;
1680 }
1681
1682
1683
1684 /*******************************************************************************
1685  *                              Direct3DDevice VTable
1686  */
1687 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = 
1688 {
1689   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1690   IDirect3DDeviceImpl_QueryInterface,
1691   IDirect3DDeviceImpl_AddRef,
1692   IDirect3DDeviceImpl_Release,
1693   IDirect3DDeviceImpl_Initialize,
1694   IDirect3DDeviceImpl_GetCaps,
1695   IDirect3DDeviceImpl_SwapTextureHandles,
1696   IDirect3DDeviceImpl_CreateExecuteBuffer,
1697   IDirect3DDeviceImpl_GetStats,
1698   IDirect3DDeviceImpl_Execute,
1699   IDirect3DDeviceImpl_AddViewport,
1700   IDirect3DDeviceImpl_DeleteViewport,
1701   IDirect3DDeviceImpl_NextViewport,
1702   IDirect3DDeviceImpl_Pick,
1703   IDirect3DDeviceImpl_GetPickRecords,
1704   IDirect3DDeviceImpl_EnumTextureFormats,
1705   IDirect3DDeviceImpl_CreateMatrix,
1706   IDirect3DDeviceImpl_SetMatrix,
1707   IDirect3DDeviceImpl_GetMatrix,
1708   IDirect3DDeviceImpl_DeleteMatrix,
1709   IDirect3DDeviceImpl_BeginScene,
1710   IDirect3DDeviceImpl_EndScene,
1711   IDirect3DDeviceImpl_GetDirect3D,
1712 };
1713
1714 #else /* HAVE_MESAGL */
1715
1716 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1717   return 0;
1718 }
1719
1720 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1721 {
1722   return 0;
1723 }
1724
1725 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1726   return 0;
1727 }
1728
1729 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1730 {
1731   return 0;
1732 }
1733
1734 #endif /* HAVE_MESAGL */