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