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