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