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