No longer directly accessing debuggee memory.
[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     ICOM_VTBL(*device) = &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   
263   FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
264   
265   return S_OK;
266 }
267
268
269
270 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
271 {
272   ICOM_THIS(IDirect3DDevice2Impl,iface);
273   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
274   
275   return ++(This->ref);
276 }
277
278
279
280 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
281 {
282   ICOM_THIS(IDirect3DDevice2Impl,iface);
283   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
284   
285   if (!--(This->ref)) {
286     OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
287
288 #ifdef USE_OSMESA
289     OSMesaDestroyContext(odev->ctx);
290 #else
291     ENTER_GL();
292     glXDestroyContext(display,
293                       odev->ctx);
294     LEAVE_GL();
295 #endif
296     
297     HeapFree(GetProcessHeap(),0,This);
298     return 0;
299   }
300   
301   return This->ref;
302 }
303
304
305 /*** IDirect3DDevice2 methods ***/
306 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
307                                                LPD3DDEVICEDESC lpdescsoft,
308                                                LPD3DDEVICEDESC lpdeschard)
309 {
310   ICOM_THIS(IDirect3DDevice2Impl,iface);
311   FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
312   
313   fill_opengl_caps(lpdescsoft, lpdeschard);
314   
315   return DD_OK;
316 }
317
318
319
320 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
321                                                           LPDIRECT3DTEXTURE2 lptex1,
322                                                           LPDIRECT3DTEXTURE2 lptex2)
323 {
324   ICOM_THIS(IDirect3DDevice2Impl,iface);
325   FIXME("(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
326   
327   return DD_OK;
328 }
329
330
331
332 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
333                                                 LPD3DSTATS lpstats)
334 {
335   ICOM_THIS(IDirect3DDevice2Impl,iface);
336   FIXME("(%p)->(%p): stub\n", This, lpstats);
337   
338   return DD_OK;
339 }
340
341
342
343 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
344                                                    LPDIRECT3DVIEWPORT2 lpvp)
345 {
346   ICOM_THIS(IDirect3DDevice2Impl,iface);
347   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
348   FIXME("(%p)->(%p): stub\n", This, ilpvp);
349   
350   /* Adds this viewport to the viewport list */
351   ilpvp->next = This->viewport_list;
352   This->viewport_list = ilpvp;
353   
354   return DD_OK;
355 }
356
357
358
359 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
360                                                       LPDIRECT3DVIEWPORT2 lpvp)
361 {
362   ICOM_THIS(IDirect3DDevice2Impl,iface);
363   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
364   IDirect3DViewport2Impl *cur, *prev;
365   FIXME("(%p)->(%p): stub\n", This, lpvp);
366   
367   /* Finds this viewport in the list */
368   prev = NULL;
369   cur = This->viewport_list;
370   while ((cur != NULL) && (cur != ilpvp)) {
371     prev = cur;
372     cur = cur->next;
373   }
374   if (cur == NULL)
375     return DDERR_INVALIDOBJECT;
376   
377   /* And remove it */
378   if (prev == NULL)
379     This->viewport_list = cur->next;
380   else
381     prev->next = cur->next;
382   
383   return DD_OK;
384 }
385
386
387
388 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
389                                                     LPDIRECT3DVIEWPORT2 lpvp,
390                                                     LPDIRECT3DVIEWPORT2* lplpvp,
391                                                     DWORD dwFlags)
392 {
393   ICOM_THIS(IDirect3DDevice2Impl,iface);
394   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
395   IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
396   FIXME("(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
397   
398   switch (dwFlags) {
399   case D3DNEXT_NEXT:
400     *ilplpvp = ilpvp->next;
401     break;
402     
403   case D3DNEXT_HEAD:
404     *ilplpvp = This->viewport_list;
405     break;
406     
407   case D3DNEXT_TAIL:
408     ilpvp = This->viewport_list;
409     while (ilpvp->next != NULL)
410       ilpvp = ilpvp->next;
411     
412     *ilplpvp = ilpvp;
413     break;
414     
415   default:
416     return DDERR_INVALIDPARAMS;
417   }
418   
419   return DD_OK;
420 }
421
422 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
423                                           LPVOID context) {
424   DDSURFACEDESC sdesc;
425   LPDDPIXELFORMAT pformat;
426
427   /* Do the texture enumeration */
428   sdesc.dwSize = sizeof(DDSURFACEDESC);
429   sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
430   sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
431   pformat = &(sdesc.ddpfPixelFormat);
432   pformat->dwSize = sizeof(DDPIXELFORMAT);
433   pformat->dwFourCC = 0;
434   
435   TRACE("Enumerating GL_RGBA unpacked (32)\n");
436   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
437   pformat->u.dwRGBBitCount = 32;
438   pformat->u1.dwRBitMask =         0xFF000000;
439   pformat->u2.dwGBitMask =         0x00FF0000;
440   pformat->u3.dwBBitMask =        0x0000FF00;
441   pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
442   if (cb(&sdesc, context) == 0)
443     return DD_OK;
444
445   TRACE("Enumerating GL_RGB unpacked (24)\n");
446   pformat->dwFlags = DDPF_RGB;
447   pformat->u.dwRGBBitCount = 24;
448   pformat->u1.dwRBitMask =  0x00FF0000;
449   pformat->u2.dwGBitMask =  0x0000FF00;
450   pformat->u3.dwBBitMask = 0x000000FF;
451   pformat->u4.dwRGBAlphaBitMask = 0x00000000;
452   if (cb(&sdesc, context) == 0)
453     return DD_OK;
454
455 #ifndef HAVE_BUGGY_MESAGL
456   /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
457      so that future version will work great. */
458   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
459   pformat->dwFlags = DDPF_RGB;
460   pformat->u.dwRGBBitCount = 16;
461   pformat->u1.dwRBitMask =  0x0000F800;
462   pformat->u2.dwGBitMask =  0x000007E0;
463   pformat->u3.dwBBitMask = 0x0000001F;
464   pformat->u4.dwRGBAlphaBitMask = 0x00000000;
465   if (cb(&sdesc, context) == 0)
466     return DD_OK;
467
468   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
469   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
470   pformat->u.dwRGBBitCount = 16;
471   pformat->u1.dwRBitMask =         0x0000F800;
472   pformat->u2.dwGBitMask =         0x000007C0;
473   pformat->u3.dwBBitMask =        0x0000003E;
474   pformat->u4.dwRGBAlphaBitMask = 0x00000001;
475   if (cb(&sdesc, context) == 0)
476     return DD_OK;
477
478   TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
479   pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
480   pformat->u.dwRGBBitCount = 16;
481   pformat->u1.dwRBitMask =         0x0000F000;
482   pformat->u2.dwGBitMask =         0x00000F00;
483   pformat->u3.dwBBitMask =        0x000000F0;
484   pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
485   if (cb(&sdesc, context) == 0)
486     return DD_OK;
487
488   TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
489   pformat->dwFlags = DDPF_RGB;
490   pformat->u.dwRGBBitCount = 8;
491   pformat->u1.dwRBitMask =         0x0000F800;
492   pformat->u2.dwGBitMask =         0x000007C0;
493   pformat->u3.dwBBitMask =        0x0000003E;
494   pformat->u4.dwRGBAlphaBitMask = 0x00000001;
495   if (cb(&sdesc, context) == 0)
496     return DD_OK;
497 #endif
498
499 #if defined(HAVE_GL_COLOR_TABLE) && defined(HAVE_GL_PALETTED_TEXTURE)
500   TRACE("Enumerating Paletted (8)\n");
501   pformat->dwFlags = DDPF_PALETTEINDEXED8;
502   pformat->u.dwRGBBitCount = 8;
503   pformat->u1.dwRBitMask =  0x00000000;
504   pformat->u2.dwGBitMask =  0x00000000;
505   pformat->u3.dwBBitMask = 0x00000000;
506   pformat->u4.dwRGBAlphaBitMask = 0x00000000;
507   if (cb(&sdesc, context) == 0)
508     return DD_OK;
509 #endif
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     ICOM_VTBL(*device) = &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   
1318   FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
1319   
1320   return S_OK;
1321 }
1322
1323
1324
1325 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1326 {
1327   ICOM_THIS(IDirect3DDeviceImpl,iface);
1328   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
1329   
1330   return ++(This->ref);
1331 }
1332
1333
1334
1335 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1336 {
1337   ICOM_THIS(IDirect3DDeviceImpl,iface);
1338   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
1339   
1340   if (!--(This->ref)) {
1341     OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1342
1343 #ifdef USE_OSMESA
1344     OSMesaDestroyContext(odev->ctx);
1345 #else
1346     ENTER_GL();
1347     glXDestroyContext(display,
1348                       odev->ctx);
1349     LEAVE_GL();
1350 #endif    
1351     
1352     HeapFree(GetProcessHeap(),0,This);
1353     return 0;
1354   }
1355   
1356   return This->ref;
1357 }
1358
1359 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1360                                                  LPDIRECT3D lpd3d,
1361                                                  LPGUID lpGUID,
1362                                                  LPD3DDEVICEDESC lpd3ddvdesc)
1363 {
1364   ICOM_THIS(IDirect3DDeviceImpl,iface);
1365   TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1366   
1367   return DDERR_ALREADYINITIALIZED;
1368 }
1369
1370
1371 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1372                                               LPD3DDEVICEDESC lpD3DHWDevDesc,
1373                                               LPD3DDEVICEDESC lpD3DSWDevDesc)
1374 {
1375   ICOM_THIS(IDirect3DDeviceImpl,iface);
1376   TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1377
1378   fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);  
1379   
1380   return DD_OK;
1381 }
1382
1383
1384 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1385                                                          LPDIRECT3DTEXTURE lpD3DTex1,
1386                                                          LPDIRECT3DTEXTURE lpD3DTex2)
1387 {
1388   ICOM_THIS(IDirect3DDeviceImpl,iface);
1389   TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1390   
1391   return DD_OK;
1392 }
1393
1394 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1395                                                           LPD3DEXECUTEBUFFERDESC lpDesc,
1396                                                           LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1397                                                           IUnknown *pUnkOuter)
1398 {
1399   ICOM_THIS(IDirect3DDeviceImpl,iface);
1400   TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1401
1402   *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1403   
1404   return DD_OK;
1405 }
1406
1407
1408 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1409                                                LPD3DSTATS lpD3DStats)
1410 {
1411   ICOM_THIS(IDirect3DDeviceImpl,iface);
1412   TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
1413   
1414   return DD_OK;
1415 }
1416
1417
1418 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1419                                               LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1420                                               LPDIRECT3DVIEWPORT lpDirect3DViewport,
1421                                               DWORD dwFlags)
1422 {
1423   ICOM_THIS(IDirect3DDeviceImpl,iface);
1424   TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1425
1426   /* Put this as the default context */
1427
1428   /* Execute... */
1429   ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1430   
1431   return DD_OK;
1432 }
1433
1434 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1435                                                   LPDIRECT3DVIEWPORT lpvp)
1436 {
1437   ICOM_THIS(IDirect3DDeviceImpl,iface);
1438   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1439   FIXME("(%p)->(%p): stub\n", This, ilpvp);
1440   
1441   /* Adds this viewport to the viewport list */
1442   ilpvp->next = This->viewport_list;
1443   This->viewport_list = ilpvp;
1444   
1445   return DD_OK;
1446 }
1447
1448
1449
1450 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1451                                                      LPDIRECT3DVIEWPORT lpvp)
1452 {
1453   ICOM_THIS(IDirect3DDeviceImpl,iface);
1454   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1455   IDirect3DViewport2Impl *cur, *prev;
1456   FIXME("(%p)->(%p): stub\n", This, lpvp);
1457   
1458   /* Finds this viewport in the list */
1459   prev = NULL;
1460   cur = This->viewport_list;
1461   while ((cur != NULL) && (cur != ilpvp)) {
1462     prev = cur;
1463     cur = cur->next;
1464   }
1465   if (cur == NULL)
1466     return DDERR_INVALIDOBJECT;
1467   
1468   /* And remove it */
1469   if (prev == NULL)
1470     This->viewport_list = cur->next;
1471   else
1472     prev->next = cur->next;
1473   
1474   return DD_OK;
1475 }
1476
1477
1478
1479 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1480                                                    LPDIRECT3DVIEWPORT lpvp,
1481                                                    LPDIRECT3DVIEWPORT* lplpvp,
1482                                                    DWORD dwFlags)
1483 {
1484   ICOM_THIS(IDirect3DDeviceImpl,iface);
1485   IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1486   IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1487   FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1488   
1489   switch (dwFlags) {
1490   case D3DNEXT_NEXT:
1491     *ilplpvp = ilpvp->next;
1492     break;
1493     
1494   case D3DNEXT_HEAD:
1495     *ilplpvp = This->viewport_list;
1496     break;
1497     
1498   case D3DNEXT_TAIL:
1499     ilpvp = This->viewport_list;
1500     while (ilpvp->next != NULL)
1501       ilpvp = ilpvp->next;
1502     
1503     *ilplpvp = ilpvp;
1504     break;
1505     
1506   default:
1507     return DDERR_INVALIDPARAMS;
1508   }
1509   
1510   return DD_OK;
1511 }
1512
1513 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1514                                            LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1515                                            LPDIRECT3DVIEWPORT lpDirect3DViewport,
1516                                            DWORD dwFlags,
1517                                            LPD3DRECT lpRect)
1518 {
1519   ICOM_THIS(IDirect3DDeviceImpl,iface);
1520   TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1521         dwFlags, lpRect);
1522   
1523   return DD_OK;
1524 }
1525
1526
1527 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1528                                                      LPDWORD lpCount,
1529                                                      LPD3DPICKRECORD lpD3DPickRec)
1530 {
1531   ICOM_THIS(IDirect3DDeviceImpl,iface);
1532   TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1533   
1534   return DD_OK;
1535 }
1536
1537
1538 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1539                                                          LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1540                                                          LPVOID lpArg)
1541 {
1542   ICOM_THIS(IDirect3DDeviceImpl,iface);
1543   TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1544   
1545   return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1546 }
1547
1548
1549 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1550                                                    LPD3DMATRIXHANDLE lpD3DMatHandle)
1551 {
1552   ICOM_THIS(IDirect3DDeviceImpl,iface);
1553   TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
1554
1555   *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1556   
1557   return DD_OK;
1558 }
1559
1560
1561 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1562                                                 D3DMATRIXHANDLE d3dMatHandle,
1563                                                 const LPD3DMATRIX lpD3DMatrix)
1564 {
1565   ICOM_THIS(IDirect3DDeviceImpl,iface);
1566   TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1567
1568   dump_mat(lpD3DMatrix);
1569   
1570   *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1571   
1572   return DD_OK;
1573 }
1574
1575
1576 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1577                                                 D3DMATRIXHANDLE D3DMatHandle,
1578                                                 LPD3DMATRIX lpD3DMatrix)
1579 {
1580   ICOM_THIS(IDirect3DDeviceImpl,iface);
1581   TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1582
1583   *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1584   
1585   return DD_OK;
1586 }
1587
1588
1589 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1590                                                    D3DMATRIXHANDLE d3dMatHandle)
1591 {
1592   ICOM_THIS(IDirect3DDeviceImpl,iface);
1593   TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
1594
1595   HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1596   
1597   return DD_OK;
1598 }
1599
1600
1601 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1602 {
1603   ICOM_THIS(IDirect3DDeviceImpl,iface);
1604   /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1605   
1606   FIXME("(%p)->(): stub\n", This);
1607   
1608   /* We get the pointer to the surface (should be done on flip) */
1609   /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1610   
1611   return DD_OK;
1612 }
1613
1614
1615 /* This is for the moment copy-pasted from IDirect3DDevice2...
1616    Will make a common function ... */
1617 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1618 {
1619   ICOM_THIS(IDirect3DDeviceImpl,iface);
1620 #ifdef USE_OSMESA
1621   OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1622   LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1623   DDSURFACEDESC sdesc;
1624   int x,y;
1625   unsigned char *src;
1626   unsigned short *dest;
1627 #endif
1628   
1629   FIXME("(%p)->(): stub\n", This);
1630
1631 #ifdef USE_OSMESA
1632   /* Here we copy back the OpenGL scene to the the DDraw surface */
1633   /* First, lock the surface */
1634   IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1635
1636   /* The copy the OpenGL buffer to this surface */
1637   
1638   /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1639      I am currently working on a set of patches for Mesa to have OSMesa support
1640      16 bpp surfaces => we will able to render directly onto the surface, no
1641      need to do a bpp conversion */
1642   dest = (unsigned short *) sdesc.y.lpSurface;
1643   src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1644   for (y = 0; y < sdesc.dwHeight; y++) {
1645     unsigned char *lsrc = src;
1646     
1647     for (x = 0; x < sdesc.dwWidth ; x++) {
1648       unsigned char r =  *lsrc++;
1649       unsigned char g =  *lsrc++;
1650       unsigned char b =  *lsrc++;
1651       lsrc++; /* Alpha */
1652
1653       *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1654       
1655       dest++;
1656     }
1657
1658     src -= 4 * sdesc.dwWidth;
1659   }
1660
1661   /* Unlock the surface */
1662   IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1663 #else
1664   /* No need to do anything here... */
1665 #endif
1666   
1667   return DD_OK;  
1668 }
1669
1670
1671 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1672                                                   LPDIRECT3D *lpDirect3D)
1673 {
1674   ICOM_THIS(IDirect3DDeviceImpl,iface);
1675   TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
1676
1677   return DD_OK;
1678 }
1679
1680
1681
1682 /*******************************************************************************
1683  *                              Direct3DDevice VTable
1684  */
1685 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = 
1686 {
1687   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1688   IDirect3DDeviceImpl_QueryInterface,
1689   IDirect3DDeviceImpl_AddRef,
1690   IDirect3DDeviceImpl_Release,
1691   IDirect3DDeviceImpl_Initialize,
1692   IDirect3DDeviceImpl_GetCaps,
1693   IDirect3DDeviceImpl_SwapTextureHandles,
1694   IDirect3DDeviceImpl_CreateExecuteBuffer,
1695   IDirect3DDeviceImpl_GetStats,
1696   IDirect3DDeviceImpl_Execute,
1697   IDirect3DDeviceImpl_AddViewport,
1698   IDirect3DDeviceImpl_DeleteViewport,
1699   IDirect3DDeviceImpl_NextViewport,
1700   IDirect3DDeviceImpl_Pick,
1701   IDirect3DDeviceImpl_GetPickRecords,
1702   IDirect3DDeviceImpl_EnumTextureFormats,
1703   IDirect3DDeviceImpl_CreateMatrix,
1704   IDirect3DDeviceImpl_SetMatrix,
1705   IDirect3DDeviceImpl_GetMatrix,
1706   IDirect3DDeviceImpl_DeleteMatrix,
1707   IDirect3DDeviceImpl_BeginScene,
1708   IDirect3DDeviceImpl_EndScene,
1709   IDirect3DDeviceImpl_GetDirect3D,
1710 };
1711
1712 #else /* HAVE_MESAGL */
1713
1714 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1715   return 0;
1716 }
1717
1718 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1719 {
1720   return 0;
1721 }
1722
1723 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1724   return 0;
1725 }
1726
1727 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1728 {
1729   return 0;
1730 }
1731
1732 #endif /* HAVE_MESAGL */