Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbejy@wpi.edu>
[wine/multimedia.git] / graphics / d3ddevices.c
blob5dc30718dc73b97f3213bca0a108e8f2ce3eb585
1 /* Direct3D Device
2 (c) 1998 Lionel ULMER
4 This files contains all the D3D devices that Wine supports. For the moment
5 only the 'OpenGL' target is supported. */
7 #include <string.h>
8 #include "config.h"
9 #include "windef.h"
10 #include "winerror.h"
11 #include "wine/obj_base.h"
12 #include "heap.h"
13 #include "ddraw.h"
14 #include "d3d.h"
15 #include "debug.h"
17 #include "d3d_private.h"
19 DEFAULT_DEBUG_CHANNEL(ddraw)
21 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
22 on Mesa's home page) or version 3.1b.
24 Version 3.2b should correct this bug */
25 #undef HAVE_BUGGY_MESAGL
27 #ifdef HAVE_MESAGL
29 static GUID IID_D3DDEVICE2_OpenGL = {
30 0x39a0da38,
31 0x7e57,
32 0x11d2,
33 { 0x8b,0x7c,0x0e,0x4e,0xd8,0x3c,0x2b,0x3c }
36 static GUID IID_D3DDEVICE_OpenGL = {
37 0x31416d44,
38 0x86ae,
39 0x11d2,
40 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
44 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
45 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
47 /*******************************************************************************
48 * OpenGL static functions
50 static void set_context(IDirect3DDevice2Impl* This) {
51 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
53 OSMesaMakeCurrent(odev->ctx, odev->buffer,
54 GL_UNSIGNED_BYTE,
55 This->surface->s.surface_desc.dwWidth,
56 This->surface->s.surface_desc.dwHeight);
59 static void set_context_dx3(IDirect3DDeviceImpl* This) {
60 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
62 OSMesaMakeCurrent(odev->ctx, odev->buffer,
63 GL_UNSIGNED_BYTE,
64 This->surface->s.surface_desc.dwWidth,
65 This->surface->s.surface_desc.dwHeight);
68 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
70 pc->dwSize = sizeof(*pc);
71 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
72 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
73 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
74 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
75 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
76 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
77 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
78 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
79 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
80 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
81 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
82 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
83 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
84 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
85 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
86 pc->dwStippleWidth = 32;
87 pc->dwStippleHeight = 32;
90 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
92 /* GLint maxlight; */
94 d1->dwSize = sizeof(*d1);
95 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
96 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
97 d1->dcmColorModel = D3DCOLOR_RGB;
98 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
99 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
100 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
101 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
102 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
103 d1->bClipping = TRUE;
104 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
105 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
106 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
107 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
108 fill_opengl_primcaps(&(d1->dpcLineCaps));
109 fill_opengl_primcaps(&(d1->dpcTriCaps));
110 d1->dwDeviceRenderBitDepth = DDBD_16;
111 d1->dwDeviceZBufferBitDepth = DDBD_16;
112 d1->dwMaxBufferSize = 0;
113 d1->dwMaxVertexCount = 65536;
114 d1->dwMinTextureWidth = 1;
115 d1->dwMinTextureHeight = 1;
116 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
117 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
118 d1->dwMinStippleWidth = 1;
119 d1->dwMinStippleHeight = 1;
120 d1->dwMaxStippleWidth = 32;
121 d1->dwMaxStippleHeight = 32;
123 d2->dwSize = sizeof(*d2);
124 d2->dwFlags = 0;
127 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
128 D3DDEVICEDESC d1,d2;
130 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
132 fill_opengl_caps(&d1, &d2);
134 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
137 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
139 if (/* Default device */
140 (rguid == NULL) ||
141 /* HAL Device */
142 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
143 /* OpenGL Device */
144 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
145 OpenGL_IDirect3DDevice2 *odev;
147 const float id_mat[16] = {
148 1.0, 0.0, 0.0, 0.0,
149 0.0, 1.0, 0.0, 0.0,
150 0.0, 0.0, 1.0, 0.0,
151 0.0, 0.0, 0.0, 1.0
154 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
155 odev = (OpenGL_IDirect3DDevice2 *) (*device);
156 (*device)->ref = 1;
157 (*device)->lpvtbl = &OpenGL_vtable;
158 (*device)->d3d = d3d;
159 (*device)->surface = surface;
161 (*device)->viewport_list = NULL;
162 (*device)->current_viewport = NULL;
164 (*device)->set_context = set_context;
166 TRACE(ddraw, "OpenGL device created \n");
168 /* Create the OpenGL context */
169 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
170 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
171 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
172 odev->rs.src = GL_ONE;
173 odev->rs.dst = GL_ZERO;
174 odev->rs.mag = GL_NEAREST;
175 odev->rs.min = GL_NEAREST;
176 odev->vt = 0;
178 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
179 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
180 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
182 /* Initialisation */
183 (*device)->set_context(*device);
184 glClearColor(0.0, 0.0, 0.0, 0.0);
185 glColor3f(1.0, 1.0, 1.0);
187 return 1;
190 /* This is not the OpenGL UID */
191 return 0;
194 /*******************************************************************************
195 * Common IDirect3DDevice2
198 static HRESULT WINAPI IDirect3DDevice2Impl_QueryInterface(LPDIRECT3DDEVICE2 iface,
199 REFIID riid,
200 LPVOID* ppvObj)
202 ICOM_THIS(IDirect3DDevice2Impl,iface);
203 char xrefiid[50];
205 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
206 FIXME(ddraw, "(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
208 return S_OK;
213 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
215 ICOM_THIS(IDirect3DDevice2Impl,iface);
216 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", This, This->ref );
218 return ++(This->ref);
223 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
225 ICOM_THIS(IDirect3DDevice2Impl,iface);
226 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
228 if (!--(This->ref)) {
229 HeapFree(GetProcessHeap(),0,This);
230 return 0;
233 return This->ref;
237 /*** IDirect3DDevice2 methods ***/
238 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
239 LPD3DDEVICEDESC lpdescsoft,
240 LPD3DDEVICEDESC lpdeschard)
242 ICOM_THIS(IDirect3DDevice2Impl,iface);
243 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
245 fill_opengl_caps(lpdescsoft, lpdeschard);
247 return DD_OK;
252 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
253 LPDIRECT3DTEXTURE2 lptex1,
254 LPDIRECT3DTEXTURE2 lptex2)
256 ICOM_THIS(IDirect3DDevice2Impl,iface);
257 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
259 return DD_OK;
264 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
265 LPD3DSTATS lpstats)
267 ICOM_THIS(IDirect3DDevice2Impl,iface);
268 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpstats);
270 return DD_OK;
275 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
276 LPDIRECT3DVIEWPORT2 lpvp)
278 ICOM_THIS(IDirect3DDevice2Impl,iface);
279 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
280 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
282 /* Adds this viewport to the viewport list */
283 ilpvp->next = This->viewport_list;
284 This->viewport_list = ilpvp;
286 return DD_OK;
291 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
292 LPDIRECT3DVIEWPORT2 lpvp)
294 ICOM_THIS(IDirect3DDevice2Impl,iface);
295 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
296 IDirect3DViewport2Impl *cur, *prev;
297 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvp);
299 /* Finds this viewport in the list */
300 prev = NULL;
301 cur = This->viewport_list;
302 while ((cur != NULL) && (cur != ilpvp)) {
303 prev = cur;
304 cur = cur->next;
306 if (cur == NULL)
307 return DDERR_INVALIDOBJECT;
309 /* And remove it */
310 if (prev == NULL)
311 This->viewport_list = cur->next;
312 else
313 prev->next = cur->next;
315 return DD_OK;
320 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
321 LPDIRECT3DVIEWPORT2 lpvp,
322 LPDIRECT3DVIEWPORT2* lplpvp,
323 DWORD dwFlags)
325 ICOM_THIS(IDirect3DDevice2Impl,iface);
326 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
327 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
328 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
330 switch (dwFlags) {
331 case D3DNEXT_NEXT:
332 *ilplpvp = ilpvp->next;
333 break;
335 case D3DNEXT_HEAD:
336 *ilplpvp = This->viewport_list;
337 break;
339 case D3DNEXT_TAIL:
340 ilpvp = This->viewport_list;
341 while (ilpvp->next != NULL)
342 ilpvp = ilpvp->next;
344 *ilplpvp = ilpvp;
345 break;
347 default:
348 return DDERR_INVALIDPARAMS;
351 return DD_OK;
354 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
355 LPVOID context) {
356 DDSURFACEDESC sdesc;
357 LPDDPIXELFORMAT pformat;
359 /* Do the texture enumeration */
360 sdesc.dwSize = sizeof(DDSURFACEDESC);
361 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
362 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
363 pformat = &(sdesc.ddpfPixelFormat);
364 pformat->dwSize = sizeof(DDPIXELFORMAT);
365 pformat->dwFourCC = 0;
367 TRACE(ddraw, "Enumerating GL_RGBA unpacked (32)\n");
368 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
369 pformat->x.dwRGBBitCount = 32;
370 pformat->y.dwRBitMask = 0xFF000000;
371 pformat->z.dwGBitMask = 0x00FF0000;
372 pformat->xx.dwBBitMask = 0x0000FF00;
373 pformat->xy.dwRGBAlphaBitMask = 0x000000FF;
374 if (cb(&sdesc, context) == 0)
375 return DD_OK;
377 TRACE(ddraw, "Enumerating GL_RGB unpacked (24)\n");
378 pformat->dwFlags = DDPF_RGB;
379 pformat->x.dwRGBBitCount = 24;
380 pformat->y.dwRBitMask = 0x00FF0000;
381 pformat->z.dwGBitMask = 0x0000FF00;
382 pformat->xx.dwBBitMask = 0x000000FF;
383 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
384 if (cb(&sdesc, context) == 0)
385 return DD_OK;
387 #ifndef HAVE_BUGGY_MESAGL
388 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
389 so that future version will work great. */
390 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
391 pformat->dwFlags = DDPF_RGB;
392 pformat->x.dwRGBBitCount = 16;
393 pformat->y.dwRBitMask = 0x0000F800;
394 pformat->z.dwGBitMask = 0x000007E0;
395 pformat->xx.dwBBitMask = 0x0000001F;
396 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
397 if (cb(&sdesc, context) == 0)
398 return DD_OK;
400 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
401 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
402 pformat->x.dwRGBBitCount = 16;
403 pformat->y.dwRBitMask = 0x0000F800;
404 pformat->z.dwGBitMask = 0x000007C0;
405 pformat->xx.dwBBitMask = 0x0000003E;
406 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
407 if (cb(&sdesc, context) == 0)
408 return DD_OK;
410 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
411 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
412 pformat->x.dwRGBBitCount = 16;
413 pformat->y.dwRBitMask = 0x0000F000;
414 pformat->z.dwGBitMask = 0x00000F00;
415 pformat->xx.dwBBitMask = 0x000000F0;
416 pformat->xy.dwRGBAlphaBitMask = 0x0000000F;
417 if (cb(&sdesc, context) == 0)
418 return DD_OK;
420 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
421 pformat->dwFlags = DDPF_RGB;
422 pformat->x.dwRGBBitCount = 8;
423 pformat->y.dwRBitMask = 0x0000F800;
424 pformat->z.dwGBitMask = 0x000007C0;
425 pformat->xx.dwBBitMask = 0x0000003E;
426 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
427 if (cb(&sdesc, context) == 0)
428 return DD_OK;
429 #endif
431 TRACE(ddraw, "Enumerating Paletted (8)\n");
432 pformat->dwFlags = DDPF_PALETTEINDEXED8;
433 pformat->x.dwRGBBitCount = 8;
434 pformat->y.dwRBitMask = 0x00000000;
435 pformat->z.dwGBitMask = 0x00000000;
436 pformat->xx.dwBBitMask = 0x00000000;
437 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
438 if (cb(&sdesc, context) == 0)
439 return DD_OK;
441 TRACE(ddraw, "End of enumeration\n");
443 return DD_OK;
446 static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
447 LPD3DENUMTEXTUREFORMATSCALLBACK cb,
448 LPVOID context)
450 ICOM_THIS(IDirect3DDevice2Impl,iface);
451 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, cb, context);
453 return enum_texture_format_OpenGL(cb, context);
458 static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
460 ICOM_THIS(IDirect3DDevice2Impl,iface);
461 /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
463 FIXME(ddraw, "(%p)->(): stub\n", This);
465 /* Here, we should get the DDraw surface and 'copy it' to the
466 OpenGL surface.... */
468 return DD_OK;
473 static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
475 ICOM_THIS(IDirect3DDevice2Impl,iface);
476 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
477 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
478 DDSURFACEDESC sdesc;
479 int x,y;
480 unsigned char *src;
481 unsigned short *dest;
483 FIXME(ddraw, "(%p)->(): stub\n", This);
485 /* Here we copy back the OpenGL scene to the the DDraw surface */
486 /* First, lock the surface */
487 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
489 /* The copy the OpenGL buffer to this surface */
491 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
492 I am currently working on a set of patches for Mesa to have OSMesa support
493 16 bpp surfaces => we will able to render directly onto the surface, no
494 need to do a bpp conversion */
495 dest = (unsigned short *) sdesc.y.lpSurface;
496 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
497 for (y = 0; y < sdesc.dwHeight; y++) {
498 unsigned char *lsrc = src;
500 for (x = 0; x < sdesc.dwWidth ; x++) {
501 unsigned char r = *lsrc++;
502 unsigned char g = *lsrc++;
503 unsigned char b = *lsrc++;
504 lsrc++; /* Alpha */
505 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
507 dest++;
510 src -= 4 * sdesc.dwWidth;
513 /* Unlock the surface */
514 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
516 return DD_OK;
521 static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
523 ICOM_THIS(IDirect3DDevice2Impl,iface);
524 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpd3d2);
526 *lpd3d2 = (LPDIRECT3D2)This->d3d;
528 return DD_OK;
533 /*** DrawPrimitive API ***/
534 static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
535 LPDIRECT3DVIEWPORT2 lpvp)
537 ICOM_THIS(IDirect3DDevice2Impl,iface);
538 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
539 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
541 /* Should check if the viewport was added or not */
543 /* Set this viewport as the current viewport */
544 This->current_viewport = ilpvp;
546 /* Activate this viewport */
547 ilpvp->device.active_device2 = This;
548 ilpvp->activate(ilpvp);
550 return DD_OK;
555 static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
556 LPDIRECT3DVIEWPORT2 *lplpvp)
558 ICOM_THIS(IDirect3DDevice2Impl,iface);
559 FIXME(ddraw, "(%p)->(%p): stub\n", This, lplpvp);
561 /* Returns the current viewport */
562 *lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
564 return DD_OK;
569 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
570 LPDIRECTDRAWSURFACE lpdds,
571 DWORD dwFlags)
573 ICOM_THIS(IDirect3DDevice2Impl,iface);
574 FIXME(ddraw, "(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
576 return DD_OK;
581 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
582 LPDIRECTDRAWSURFACE *lplpdds)
584 ICOM_THIS(IDirect3DDevice2Impl,iface);
585 FIXME(ddraw, "(%p)->(%p): stub\n", This, lplpdds);
587 /* Returns the current rendering target (the surface on wich we render) */
588 *lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
590 return DD_OK;
595 static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
596 D3DPRIMITIVETYPE d3dp,
597 D3DVERTEXTYPE d3dv,
598 DWORD dwFlags)
600 ICOM_THIS(IDirect3DDevice2Impl,iface);
601 FIXME(ddraw, "(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
603 return DD_OK;
608 static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
609 D3DPRIMITIVETYPE d3dp,
610 D3DVERTEXTYPE d3dv,
611 LPVOID lpvert,
612 DWORD numvert,
613 DWORD dwFlags)
615 ICOM_THIS(IDirect3DDevice2Impl,iface);
616 FIXME(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
618 return DD_OK;
623 static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
624 LPVOID lpvert)
626 ICOM_THIS(IDirect3DDevice2Impl,iface);
627 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvert);
629 return DD_OK;
634 static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
635 WORD index)
637 ICOM_THIS(IDirect3DDevice2Impl,iface);
638 FIXME(ddraw, "(%p)->(%d): stub\n", This, index);
640 return DD_OK;
645 static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
646 DWORD dwFlags)
648 ICOM_THIS(IDirect3DDevice2Impl,iface);
649 FIXME(ddraw, "(%p)->(%08lx): stub\n", This, dwFlags);
651 return DD_OK;
657 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
658 D3DRENDERSTATETYPE d3drs,
659 LPDWORD lprstate)
661 ICOM_THIS(IDirect3DDevice2Impl,iface);
662 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
664 return DD_OK;
669 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
670 D3DRENDERSTATETYPE dwRenderStateType,
671 DWORD dwRenderState)
673 ICOM_THIS(IDirect3DDevice2Impl,iface);
674 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
676 TRACE(ddraw, "(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
678 /* Call the render state functions */
679 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
681 return DD_OK;
686 static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
687 D3DLIGHTSTATETYPE d3dls,
688 LPDWORD lplstate)
690 ICOM_THIS(IDirect3DDevice2Impl,iface);
691 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
693 return DD_OK;
698 static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
699 D3DLIGHTSTATETYPE dwLightStateType,
700 DWORD dwLightState)
702 ICOM_THIS(IDirect3DDevice2Impl,iface);
703 FIXME(ddraw, "(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
705 switch (dwLightStateType) {
706 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
707 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
709 if (mat != NULL) {
710 mat->activate(mat);
711 } else {
712 TRACE(ddraw, "Zoups !!!\n");
714 } break;
716 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
717 float light[4];
719 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
720 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
721 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
722 light[3] = 1.0;
723 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
724 } break;
726 case D3DLIGHTSTATE_COLORMODEL: /* 3 */
727 break;
729 case D3DLIGHTSTATE_FOGMODE: /* 4 */
730 break;
732 case D3DLIGHTSTATE_FOGSTART: /* 5 */
733 break;
735 case D3DLIGHTSTATE_FOGEND: /* 6 */
736 break;
738 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
739 break;
741 default:
742 TRACE(ddraw, "Unexpected Light State Type\n");
743 return DDERR_INVALIDPARAMS;
746 return DD_OK;
751 static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
752 D3DTRANSFORMSTATETYPE d3dts,
753 LPD3DMATRIX lpmatrix)
755 ICOM_THIS(IDirect3DDevice2Impl,iface);
756 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
758 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
760 /* Using a trial and failure approach, I found that the order of
761 Direct3D transformations that works best is :
763 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
765 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
766 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
768 If anyone has a good explanation of the three different matrices in
769 the SDK online documentation, feel free to point it to me. For example,
770 which matrices transform lights ? In OpenGL only the PROJECTION matrix
771 transform the lights, not the MODELVIEW. Using the matrix names, I
772 supposed that PROJECTION and VIEW (all 'camera' related names) do
773 transform lights, but WORLD do not. It may be wrong though... */
775 /* After reading through both OpenGL and Direct3D documentations, I
776 thought that D3D matrices were written in 'line major mode' transposed
777 from OpenGL's 'column major mode'. But I found out that a simple memcpy
778 works fine to transfer one matrix format to the other (it did not work
779 when transposing)....
781 So :
782 1) are the documentations wrong
783 2) does the matrix work even if they are not read correctly
784 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
785 loading using glLoadMatrix ?
787 Anyway, I always use 'conv_mat' to transfer the matrices from one format
788 to the other so that if I ever find out that I need to transpose them, I
789 will able to do it quickly, only by changing the macro conv_mat. */
791 switch (d3dts) {
792 case D3DTRANSFORMSTATE_WORLD: {
793 conv_mat(lpmatrix, odev->world_mat);
794 glMatrixMode(GL_MODELVIEW);
795 glLoadMatrixf((float *) &(odev->world_mat));
796 } break;
798 case D3DTRANSFORMSTATE_VIEW: {
799 conv_mat(lpmatrix, odev->view_mat);
800 glMatrixMode(GL_PROJECTION);
801 glLoadMatrixf((float *) &(odev->proj_mat));
802 glMultMatrixf((float *) &(odev->view_mat));
803 } break;
805 case D3DTRANSFORMSTATE_PROJECTION: {
806 conv_mat(lpmatrix, odev->proj_mat);
807 glMatrixMode(GL_PROJECTION);
808 glLoadMatrixf((float *) &(odev->proj_mat));
809 glMultMatrixf((float *) &(odev->view_mat));
810 } break;
812 default:
813 break;
816 return DD_OK;
821 static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
822 D3DTRANSFORMSTATETYPE d3dts,
823 LPD3DMATRIX lpmatrix)
825 ICOM_THIS(IDirect3DDevice2Impl,iface);
826 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
828 return DD_OK;
833 static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
834 D3DTRANSFORMSTATETYPE d3dts,
835 LPD3DMATRIX lpmatrix)
837 ICOM_THIS(IDirect3DDevice2Impl,iface);
838 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
840 return DD_OK;
843 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
844 /* Puts GL in the correct lighting mode */ \
845 if (odev->vt != d3dv) { \
846 if (odev->vt == D3DVT_TLVERTEX) { \
847 /* Need to put the correct transformation again */ \
848 glMatrixMode(GL_MODELVIEW); \
849 glLoadMatrixf((float *) &(odev->world_mat)); \
850 glMatrixMode(GL_PROJECTION); \
851 glLoadMatrixf((float *) &(odev->proj_mat)); \
852 glMultMatrixf((float *) &(odev->view_mat)); \
855 switch (d3dv) { \
856 case D3DVT_VERTEX: \
857 TRACE(ddraw, "Standard Vertex\n"); \
858 glEnable(GL_LIGHTING); \
859 break; \
861 case D3DVT_LVERTEX: \
862 TRACE(ddraw, "Lighted Vertex\n"); \
863 glDisable(GL_LIGHTING); \
864 break; \
866 case D3DVT_TLVERTEX: { \
867 GLdouble height, width, minZ, maxZ; \
869 TRACE(ddraw, "Transformed - Lighted Vertex\n"); \
870 /* First, disable lighting */ \
871 glDisable(GL_LIGHTING); \
873 /* Then do not put any transformation matrixes */ \
874 glMatrixMode(GL_MODELVIEW); \
875 glLoadIdentity(); \
876 glMatrixMode(GL_PROJECTION); \
877 glLoadIdentity(); \
879 if (This->current_viewport == NULL) { \
880 ERR(ddraw, "No current viewport !\n"); \
881 /* Using standard values */ \
882 height = 640.0; \
883 width = 480.0; \
884 minZ = -10.0; \
885 maxZ = 10.0; \
886 } else { \
887 if (This->current_viewport->use_vp2) { \
888 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight; \
889 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth; \
890 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ; \
891 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ; \
892 } else { \
893 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight; \
894 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth; \
895 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ; \
896 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ; \
900 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
901 } break; \
903 default: \
904 ERR(ddraw, "Unhandled vertex type\n"); \
905 break; \
908 odev->vt = d3dv; \
911 switch (d3dp) { \
912 case D3DPT_POINTLIST: \
913 TRACE(ddraw, "Start POINTS\n"); \
914 glBegin(GL_POINTS); \
915 break; \
917 case D3DPT_LINELIST: \
918 TRACE(ddraw, "Start LINES\n"); \
919 glBegin(GL_LINES); \
920 break; \
922 case D3DPT_LINESTRIP: \
923 TRACE(ddraw, "Start LINE_STRIP\n"); \
924 glBegin(GL_LINE_STRIP); \
925 break; \
927 case D3DPT_TRIANGLELIST: \
928 TRACE(ddraw, "Start TRIANGLES\n"); \
929 glBegin(GL_TRIANGLES); \
930 break; \
932 case D3DPT_TRIANGLESTRIP: \
933 TRACE(ddraw, "Start TRIANGLE_STRIP\n"); \
934 glBegin(GL_TRIANGLE_STRIP); \
935 break; \
937 case D3DPT_TRIANGLEFAN: \
938 TRACE(ddraw, "Start TRIANGLE_FAN\n"); \
939 glBegin(GL_TRIANGLE_FAN); \
940 break; \
942 default: \
943 TRACE(ddraw, "Unhandled primitive\n"); \
944 break; \
947 /* Draw the primitives */ \
948 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
949 switch (d3dv) { \
950 case D3DVT_VERTEX: { \
951 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
953 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
954 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
955 TRACE(ddraw, " V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
956 } break; \
958 case D3DVT_LVERTEX: { \
959 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
960 DWORD col = vx->c.color; \
962 glColor3f(((col >> 16) & 0xFF) / 255.0, \
963 ((col >> 8) & 0xFF) / 255.0, \
964 ((col >> 0) & 0xFF) / 255.0); \
965 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
966 TRACE(ddraw, " LV: %f %f %f (%02lx %02lx %02lx)\n", \
967 vx->x.x, vx->y.y, vx->z.z, \
968 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
969 } break; \
971 case D3DVT_TLVERTEX: { \
972 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
973 DWORD col = vx->c.color; \
975 glColor3f(((col >> 16) & 0xFF) / 255.0, \
976 ((col >> 8) & 0xFF) / 255.0, \
977 ((col >> 0) & 0xFF) / 255.0); \
978 glTexCoord2f(vx->u.tu, vx->v.tv); \
979 if (vx->r.rhw < 0.01) \
980 glVertex3f(vx->x.sx, \
981 vx->y.sy, \
982 vx->z.sz); \
983 else \
984 glVertex4f(vx->x.sx / vx->r.rhw, \
985 vx->y.sy / vx->r.rhw, \
986 vx->z.sz / vx->r.rhw, \
987 1.0 / vx->r.rhw); \
988 TRACE(ddraw, " TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
989 vx->x.sx, vx->y.sy, vx->z.sz, \
990 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
991 vx->u.tu, vx->v.tv, vx->r.rhw); \
992 } break; \
994 default: \
995 TRACE(ddraw, "Unhandled vertex type\n"); \
996 break; \
1000 glEnd(); \
1001 TRACE(ddraw, "End\n");
1004 static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1005 D3DPRIMITIVETYPE d3dp,
1006 D3DVERTEXTYPE d3dv,
1007 LPVOID lpvertex,
1008 DWORD vertcount,
1009 DWORD dwFlags)
1011 ICOM_THIS(IDirect3DDevice2Impl,iface);
1012 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1013 int vx_index;
1015 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
1017 DRAW_PRIMITIVE(vertcount, vx_index);
1019 return D3D_OK;
1024 static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1025 D3DPRIMITIVETYPE d3dp,
1026 D3DVERTEXTYPE d3dv,
1027 LPVOID lpvertex,
1028 DWORD vertcount,
1029 LPWORD lpindexes,
1030 DWORD indexcount,
1031 DWORD dwFlags)
1033 ICOM_THIS(IDirect3DDevice2Impl,iface);
1034 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1035 int vx_index;
1037 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1039 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1041 return D3D_OK;
1046 static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
1047 LPD3DCLIPSTATUS lpcs)
1049 ICOM_THIS(IDirect3DDevice2Impl,iface);
1050 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpcs);
1052 return DD_OK;
1057 static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
1058 LPD3DCLIPSTATUS lpcs)
1060 ICOM_THIS(IDirect3DDevice2Impl,iface);
1061 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpcs);
1063 return DD_OK;
1068 /*******************************************************************************
1069 * OpenGL-specific IDirect3DDevice2
1072 /*******************************************************************************
1073 * OpenGL-specific VTable
1076 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable = {
1077 IDirect3DDevice2Impl_QueryInterface,
1078 IDirect3DDevice2Impl_AddRef,
1079 IDirect3DDevice2Impl_Release,
1080 /*** IDirect3DDevice2 methods ***/
1081 IDirect3DDevice2Impl_GetCaps,
1082 IDirect3DDevice2Impl_SwapTextureHandles,
1083 IDirect3DDevice2Impl_GetStats,
1084 IDirect3DDevice2Impl_AddViewport,
1085 IDirect3DDevice2Impl_DeleteViewport,
1086 IDirect3DDevice2Impl_NextViewport,
1087 IDirect3DDevice2Impl_EnumTextureFormats,
1088 IDirect3DDevice2Impl_BeginScene,
1089 IDirect3DDevice2Impl_EndScene,
1090 IDirect3DDevice2Impl_GetDirect3D,
1092 /*** DrawPrimitive API ***/
1093 IDirect3DDevice2Impl_SetCurrentViewport,
1094 IDirect3DDevice2Impl_GetCurrentViewport,
1096 IDirect3DDevice2Impl_SetRenderTarget,
1097 IDirect3DDevice2Impl_GetRenderTarget,
1099 IDirect3DDevice2Impl_Begin,
1100 IDirect3DDevice2Impl_BeginIndexed,
1101 IDirect3DDevice2Impl_Vertex,
1102 IDirect3DDevice2Impl_Index,
1103 IDirect3DDevice2Impl_End,
1105 IDirect3DDevice2Impl_GetRenderState,
1106 IDirect3DDevice2Impl_SetRenderState,
1107 IDirect3DDevice2Impl_GetLightState,
1108 IDirect3DDevice2Impl_SetLightState,
1109 IDirect3DDevice2Impl_SetTransform,
1110 IDirect3DDevice2Impl_GetTransform,
1111 IDirect3DDevice2Impl_MultiplyTransform,
1113 IDirect3DDevice2Impl_DrawPrimitive,
1114 IDirect3DDevice2Impl_DrawIndexedPrimitive,
1116 IDirect3DDevice2Impl_SetClipStatus,
1117 IDirect3DDevice2Impl_GetClipStatus,
1120 /*******************************************************************************
1121 * Direct3DDevice
1123 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1124 D3DDEVICEDESC d1,d2;
1126 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
1128 fill_opengl_caps(&d1, &d2);
1130 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1133 float id_mat[16] = {
1134 1.0, 0.0, 0.0, 0.0,
1135 0.0, 1.0, 0.0, 0.0,
1136 0.0, 0.0, 1.0, 0.0,
1137 0.0, 0.0, 0.0, 1.0
1140 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1142 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1143 OpenGL_IDirect3DDevice *odev;
1145 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1146 odev = (OpenGL_IDirect3DDevice *) (*device);
1147 (*device)->ref = 1;
1148 (*device)->lpvtbl = &OpenGL_vtable_dx3;
1149 (*device)->d3d = NULL;
1150 (*device)->surface = surface;
1152 (*device)->viewport_list = NULL;
1153 (*device)->current_viewport = NULL;
1155 (*device)->set_context = set_context_dx3;
1157 TRACE(ddraw, "OpenGL device created \n");
1159 /* Create the OpenGL context */
1160 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1161 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1162 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1163 odev->rs.src = GL_ONE;
1164 odev->rs.dst = GL_ZERO;
1165 odev->rs.mag = GL_NEAREST;
1166 odev->rs.min = GL_NEAREST;
1168 odev->world_mat = (LPD3DMATRIX) &id_mat;
1169 odev->view_mat = (LPD3DMATRIX) &id_mat;
1170 odev->proj_mat = (LPD3DMATRIX) &id_mat;
1172 /* Initialisation */
1173 (*device)->set_context(*device);
1174 glClearColor(0.0, 0.0, 0.0, 0.0);
1175 glColor3f(1.0, 1.0, 1.0);
1177 return 1;
1180 /* This is not the OpenGL UID */
1181 return DD_OK;
1185 /*******************************************************************************
1186 * Direct3DDevice
1188 static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
1189 REFIID riid,
1190 LPVOID* ppvObj)
1192 ICOM_THIS(IDirect3DDeviceImpl,iface);
1193 char xrefiid[50];
1195 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1196 FIXME(ddraw, "(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
1198 return S_OK;
1203 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1205 ICOM_THIS(IDirect3DDeviceImpl,iface);
1206 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", This, This->ref );
1208 return ++(This->ref);
1213 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1215 ICOM_THIS(IDirect3DDeviceImpl,iface);
1216 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
1218 if (!--(This->ref)) {
1219 HeapFree(GetProcessHeap(),0,This);
1220 return 0;
1223 return This->ref;
1226 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1227 LPDIRECT3D lpd3d,
1228 LPGUID lpGUID,
1229 LPD3DDEVICEDESC lpd3ddvdesc)
1231 ICOM_THIS(IDirect3DDeviceImpl,iface);
1232 TRACE(ddraw, "(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1234 return DDERR_ALREADYINITIALIZED;
1238 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1239 LPD3DDEVICEDESC lpD3DHWDevDesc,
1240 LPD3DDEVICEDESC lpD3DSWDevDesc)
1242 ICOM_THIS(IDirect3DDeviceImpl,iface);
1243 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1245 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1247 return DD_OK;
1251 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1252 LPDIRECT3DTEXTURE lpD3DTex1,
1253 LPDIRECT3DTEXTURE lpD3DTex2)
1255 ICOM_THIS(IDirect3DDeviceImpl,iface);
1256 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1258 return DD_OK;
1261 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1262 LPD3DEXECUTEBUFFERDESC lpDesc,
1263 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1264 IUnknown *pUnkOuter)
1266 ICOM_THIS(IDirect3DDeviceImpl,iface);
1267 TRACE(ddraw, "(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1269 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1271 return DD_OK;
1275 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1276 LPD3DSTATS lpD3DStats)
1278 ICOM_THIS(IDirect3DDeviceImpl,iface);
1279 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpD3DStats);
1281 return DD_OK;
1285 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1286 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1287 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1288 DWORD dwFlags)
1290 ICOM_THIS(IDirect3DDeviceImpl,iface);
1291 TRACE(ddraw, "(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1293 /* Put this as the default context */
1295 /* Execute... */
1296 ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1298 return DD_OK;
1301 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1302 LPDIRECT3DVIEWPORT lpvp)
1304 ICOM_THIS(IDirect3DDeviceImpl,iface);
1305 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1306 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
1308 /* Adds this viewport to the viewport list */
1309 ilpvp->next = This->viewport_list;
1310 This->viewport_list = ilpvp;
1312 return DD_OK;
1317 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1318 LPDIRECT3DVIEWPORT lpvp)
1320 ICOM_THIS(IDirect3DDeviceImpl,iface);
1321 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1322 IDirect3DViewport2Impl *cur, *prev;
1323 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvp);
1325 /* Finds this viewport in the list */
1326 prev = NULL;
1327 cur = This->viewport_list;
1328 while ((cur != NULL) && (cur != ilpvp)) {
1329 prev = cur;
1330 cur = cur->next;
1332 if (cur == NULL)
1333 return DDERR_INVALIDOBJECT;
1335 /* And remove it */
1336 if (prev == NULL)
1337 This->viewport_list = cur->next;
1338 else
1339 prev->next = cur->next;
1341 return DD_OK;
1346 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1347 LPDIRECT3DVIEWPORT lpvp,
1348 LPDIRECT3DVIEWPORT* lplpvp,
1349 DWORD dwFlags)
1351 ICOM_THIS(IDirect3DDeviceImpl,iface);
1352 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1353 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1354 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1356 switch (dwFlags) {
1357 case D3DNEXT_NEXT:
1358 *ilplpvp = ilpvp->next;
1359 break;
1361 case D3DNEXT_HEAD:
1362 *ilplpvp = This->viewport_list;
1363 break;
1365 case D3DNEXT_TAIL:
1366 ilpvp = This->viewport_list;
1367 while (ilpvp->next != NULL)
1368 ilpvp = ilpvp->next;
1370 *ilplpvp = ilpvp;
1371 break;
1373 default:
1374 return DDERR_INVALIDPARAMS;
1377 return DD_OK;
1380 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1381 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1382 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1383 DWORD dwFlags,
1384 LPD3DRECT lpRect)
1386 ICOM_THIS(IDirect3DDeviceImpl,iface);
1387 TRACE(ddraw, "(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1388 dwFlags, lpRect);
1390 return DD_OK;
1394 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1395 LPDWORD lpCount,
1396 LPD3DPICKRECORD lpD3DPickRec)
1398 ICOM_THIS(IDirect3DDeviceImpl,iface);
1399 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1401 return DD_OK;
1405 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1406 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1407 LPVOID lpArg)
1409 ICOM_THIS(IDirect3DDeviceImpl,iface);
1410 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1412 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1416 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1417 LPD3DMATRIXHANDLE lpD3DMatHandle)
1419 ICOM_THIS(IDirect3DDeviceImpl,iface);
1420 TRACE(ddraw, "(%p)->(%p)\n", This, lpD3DMatHandle);
1422 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1424 return DD_OK;
1428 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1429 D3DMATRIXHANDLE d3dMatHandle,
1430 const LPD3DMATRIX lpD3DMatrix)
1432 ICOM_THIS(IDirect3DDeviceImpl,iface);
1433 TRACE(ddraw, "(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1435 dump_mat(lpD3DMatrix);
1437 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1439 return DD_OK;
1443 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1444 D3DMATRIXHANDLE D3DMatHandle,
1445 LPD3DMATRIX lpD3DMatrix)
1447 ICOM_THIS(IDirect3DDeviceImpl,iface);
1448 TRACE(ddraw, "(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1450 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1452 return DD_OK;
1456 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1457 D3DMATRIXHANDLE d3dMatHandle)
1459 ICOM_THIS(IDirect3DDeviceImpl,iface);
1460 TRACE(ddraw, "(%p)->(%08lx)\n", This, d3dMatHandle);
1462 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1464 return DD_OK;
1468 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1470 ICOM_THIS(IDirect3DDeviceImpl,iface);
1471 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1473 FIXME(ddraw, "(%p)->(): stub\n", This);
1475 /* We get the pointer to the surface (should be done on flip) */
1476 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1478 return DD_OK;
1482 /* This is for the moment copy-pasted from IDirect3DDevice2...
1483 Will make a common function ... */
1484 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1486 ICOM_THIS(IDirect3DDeviceImpl,iface);
1487 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1488 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1489 DDSURFACEDESC sdesc;
1490 int x,y;
1491 unsigned char *src;
1492 unsigned short *dest;
1494 FIXME(ddraw, "(%p)->(): stub\n", This);
1496 /* Here we copy back the OpenGL scene to the the DDraw surface */
1497 /* First, lock the surface */
1498 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1500 /* The copy the OpenGL buffer to this surface */
1502 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1503 I am currently working on a set of patches for Mesa to have OSMesa support
1504 16 bpp surfaces => we will able to render directly onto the surface, no
1505 need to do a bpp conversion */
1506 dest = (unsigned short *) sdesc.y.lpSurface;
1507 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1508 for (y = 0; y < sdesc.dwHeight; y++) {
1509 unsigned char *lsrc = src;
1511 for (x = 0; x < sdesc.dwWidth ; x++) {
1512 unsigned char r = *lsrc++;
1513 unsigned char g = *lsrc++;
1514 unsigned char b = *lsrc++;
1515 lsrc++; /* Alpha */
1517 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1519 dest++;
1522 src -= 4 * sdesc.dwWidth;
1525 /* Unlock the surface */
1526 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1528 return DD_OK;
1532 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1533 LPDIRECT3D *lpDirect3D)
1535 ICOM_THIS(IDirect3DDeviceImpl,iface);
1536 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpDirect3D);
1538 return DD_OK;
1543 /*******************************************************************************
1544 * Direct3DDevice VTable
1546 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = {
1547 IDirect3DDeviceImpl_QueryInterface,
1548 IDirect3DDeviceImpl_AddRef,
1549 IDirect3DDeviceImpl_Release,
1550 IDirect3DDeviceImpl_Initialize,
1551 IDirect3DDeviceImpl_GetCaps,
1552 IDirect3DDeviceImpl_SwapTextureHandles,
1553 IDirect3DDeviceImpl_CreateExecuteBuffer,
1554 IDirect3DDeviceImpl_GetStats,
1555 IDirect3DDeviceImpl_Execute,
1556 IDirect3DDeviceImpl_AddViewport,
1557 IDirect3DDeviceImpl_DeleteViewport,
1558 IDirect3DDeviceImpl_NextViewport,
1559 IDirect3DDeviceImpl_Pick,
1560 IDirect3DDeviceImpl_GetPickRecords,
1561 IDirect3DDeviceImpl_EnumTextureFormats,
1562 IDirect3DDeviceImpl_CreateMatrix,
1563 IDirect3DDeviceImpl_SetMatrix,
1564 IDirect3DDeviceImpl_GetMatrix,
1565 IDirect3DDeviceImpl_DeleteMatrix,
1566 IDirect3DDeviceImpl_BeginScene,
1567 IDirect3DDeviceImpl_EndScene,
1568 IDirect3DDeviceImpl_GetDirect3D,
1571 #else /* HAVE_MESAGL */
1573 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1574 return 0;
1577 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1579 return 0;
1582 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1583 return 0;
1586 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1588 return 0;
1591 #endif /* HAVE_MESAGL */