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