Added new CLIENT_DebuggerRequest routine, implemented support for
[wine/wine-kai.git] / graphics / d3ddevices.c
blob8ab7d53475cae0aa2c8847e35c7fa425c951b11f
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 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
20 on Mesa's home page) or version 3.1b.
22 Version 3.2b should correct this bug */
23 #undef HAVE_BUGGY_MESAGL
25 #ifdef HAVE_MESAGL
27 static GUID IID_D3DDEVICE2_OpenGL = {
28 0x39a0da38,
29 0x7e57,
30 0x11d2,
31 { 0x8b,0x7c,0x0e,0x4e,0xd8,0x3c,0x2b,0x3c }
34 static GUID IID_D3DDEVICE_OpenGL = {
35 0x31416d44,
36 0x86ae,
37 0x11d2,
38 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
42 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
43 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
45 /*******************************************************************************
46 * OpenGL static functions
48 static void set_context(IDirect3DDevice2Impl* This) {
49 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
51 OSMesaMakeCurrent(odev->ctx, odev->buffer,
52 GL_UNSIGNED_BYTE,
53 This->surface->s.surface_desc.dwWidth,
54 This->surface->s.surface_desc.dwHeight);
57 static void set_context_dx3(IDirect3DDeviceImpl* This) {
58 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
60 OSMesaMakeCurrent(odev->ctx, odev->buffer,
61 GL_UNSIGNED_BYTE,
62 This->surface->s.surface_desc.dwWidth,
63 This->surface->s.surface_desc.dwHeight);
66 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
68 pc->dwSize = sizeof(*pc);
69 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
70 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
71 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
72 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
73 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
74 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
75 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
76 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
77 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
78 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
79 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
80 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
81 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
82 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
83 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
84 pc->dwStippleWidth = 32;
85 pc->dwStippleHeight = 32;
88 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
90 /* GLint maxlight; */
92 d1->dwSize = sizeof(*d1);
93 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
94 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
95 d1->dcmColorModel = D3DCOLOR_RGB;
96 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
97 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
98 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
99 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
100 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
101 d1->bClipping = TRUE;
102 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
103 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
104 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
105 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
106 fill_opengl_primcaps(&(d1->dpcLineCaps));
107 fill_opengl_primcaps(&(d1->dpcTriCaps));
108 d1->dwDeviceRenderBitDepth = DDBD_16;
109 d1->dwDeviceZBufferBitDepth = DDBD_16;
110 d1->dwMaxBufferSize = 0;
111 d1->dwMaxVertexCount = 65536;
112 d1->dwMinTextureWidth = 1;
113 d1->dwMinTextureHeight = 1;
114 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
115 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
116 d1->dwMinStippleWidth = 1;
117 d1->dwMinStippleHeight = 1;
118 d1->dwMaxStippleWidth = 32;
119 d1->dwMaxStippleHeight = 32;
121 d2->dwSize = sizeof(*d2);
122 d2->dwFlags = 0;
125 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
126 D3DDEVICEDESC d1,d2;
128 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
130 fill_opengl_caps(&d1, &d2);
132 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
135 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
137 if (/* Default device */
138 (rguid == NULL) ||
139 /* HAL Device */
140 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
141 /* OpenGL Device */
142 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
143 OpenGL_IDirect3DDevice2 *odev;
145 const float id_mat[16] = {
146 1.0, 0.0, 0.0, 0.0,
147 0.0, 1.0, 0.0, 0.0,
148 0.0, 0.0, 1.0, 0.0,
149 0.0, 0.0, 0.0, 1.0
152 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
153 odev = (OpenGL_IDirect3DDevice2 *) (*device);
154 (*device)->ref = 1;
155 (*device)->lpvtbl = &OpenGL_vtable;
156 (*device)->d3d = d3d;
157 (*device)->surface = surface;
159 (*device)->viewport_list = NULL;
160 (*device)->current_viewport = NULL;
162 (*device)->set_context = set_context;
164 TRACE(ddraw, "OpenGL device created \n");
166 /* Create the OpenGL context */
167 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
168 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
169 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
170 odev->rs.src = GL_ONE;
171 odev->rs.dst = GL_ZERO;
172 odev->rs.mag = GL_NEAREST;
173 odev->rs.min = GL_NEAREST;
174 odev->vt = 0;
176 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
177 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
178 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
180 /* Initialisation */
181 (*device)->set_context(*device);
182 glClearColor(0.0, 0.0, 0.0, 0.0);
183 glColor3f(1.0, 1.0, 1.0);
185 return 1;
188 /* This is not the OpenGL UID */
189 return 0;
192 /*******************************************************************************
193 * Common IDirect3DDevice2
196 static HRESULT WINAPI IDirect3DDevice2Impl_QueryInterface(LPDIRECT3DDEVICE2 iface,
197 REFIID riid,
198 LPVOID* ppvObj)
200 ICOM_THIS(IDirect3DDevice2Impl,iface);
201 char xrefiid[50];
203 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
204 FIXME(ddraw, "(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
206 return S_OK;
211 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
213 ICOM_THIS(IDirect3DDevice2Impl,iface);
214 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", This, This->ref );
216 return ++(This->ref);
221 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
223 ICOM_THIS(IDirect3DDevice2Impl,iface);
224 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
226 if (!--(This->ref)) {
227 HeapFree(GetProcessHeap(),0,This);
228 return 0;
231 return This->ref;
235 /*** IDirect3DDevice2 methods ***/
236 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
237 LPD3DDEVICEDESC lpdescsoft,
238 LPD3DDEVICEDESC lpdeschard)
240 ICOM_THIS(IDirect3DDevice2Impl,iface);
241 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
243 fill_opengl_caps(lpdescsoft, lpdeschard);
245 return DD_OK;
250 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
251 LPDIRECT3DTEXTURE2 lptex1,
252 LPDIRECT3DTEXTURE2 lptex2)
254 ICOM_THIS(IDirect3DDevice2Impl,iface);
255 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
257 return DD_OK;
262 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
263 LPD3DSTATS lpstats)
265 ICOM_THIS(IDirect3DDevice2Impl,iface);
266 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpstats);
268 return DD_OK;
273 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
274 LPDIRECT3DVIEWPORT2 lpvp)
276 ICOM_THIS(IDirect3DDevice2Impl,iface);
277 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
278 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
280 /* Adds this viewport to the viewport list */
281 ilpvp->next = This->viewport_list;
282 This->viewport_list = ilpvp;
284 return DD_OK;
289 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
290 LPDIRECT3DVIEWPORT2 lpvp)
292 ICOM_THIS(IDirect3DDevice2Impl,iface);
293 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
294 IDirect3DViewport2Impl *cur, *prev;
295 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvp);
297 /* Finds this viewport in the list */
298 prev = NULL;
299 cur = This->viewport_list;
300 while ((cur != NULL) && (cur != ilpvp)) {
301 prev = cur;
302 cur = cur->next;
304 if (cur == NULL)
305 return DDERR_INVALIDOBJECT;
307 /* And remove it */
308 if (prev == NULL)
309 This->viewport_list = cur->next;
310 else
311 prev->next = cur->next;
313 return DD_OK;
318 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
319 LPDIRECT3DVIEWPORT2 lpvp,
320 LPDIRECT3DVIEWPORT2* lplpvp,
321 DWORD dwFlags)
323 ICOM_THIS(IDirect3DDevice2Impl,iface);
324 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
325 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
326 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
328 switch (dwFlags) {
329 case D3DNEXT_NEXT:
330 *ilplpvp = ilpvp->next;
331 break;
333 case D3DNEXT_HEAD:
334 *ilplpvp = This->viewport_list;
335 break;
337 case D3DNEXT_TAIL:
338 ilpvp = This->viewport_list;
339 while (ilpvp->next != NULL)
340 ilpvp = ilpvp->next;
342 *ilplpvp = ilpvp;
343 break;
345 default:
346 return DDERR_INVALIDPARAMS;
349 return DD_OK;
352 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
353 LPVOID context) {
354 DDSURFACEDESC sdesc;
355 LPDDPIXELFORMAT pformat;
357 /* Do the texture enumeration */
358 sdesc.dwSize = sizeof(DDSURFACEDESC);
359 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
360 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
361 pformat = &(sdesc.ddpfPixelFormat);
362 pformat->dwSize = sizeof(DDPIXELFORMAT);
363 pformat->dwFourCC = 0;
365 TRACE(ddraw, "Enumerating GL_RGBA unpacked (32)\n");
366 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
367 pformat->x.dwRGBBitCount = 32;
368 pformat->y.dwRBitMask = 0xFF000000;
369 pformat->z.dwGBitMask = 0x00FF0000;
370 pformat->xx.dwBBitMask = 0x0000FF00;
371 pformat->xy.dwRGBAlphaBitMask = 0x000000FF;
372 if (cb(&sdesc, context) == 0)
373 return DD_OK;
375 TRACE(ddraw, "Enumerating GL_RGB unpacked (24)\n");
376 pformat->dwFlags = DDPF_RGB;
377 pformat->x.dwRGBBitCount = 24;
378 pformat->y.dwRBitMask = 0x00FF0000;
379 pformat->z.dwGBitMask = 0x0000FF00;
380 pformat->xx.dwBBitMask = 0x000000FF;
381 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
382 if (cb(&sdesc, context) == 0)
383 return DD_OK;
385 #ifndef HAVE_BUGGY_MESAGL
386 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
387 so that future version will work great. */
388 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
389 pformat->dwFlags = DDPF_RGB;
390 pformat->x.dwRGBBitCount = 16;
391 pformat->y.dwRBitMask = 0x0000F800;
392 pformat->z.dwGBitMask = 0x000007E0;
393 pformat->xx.dwBBitMask = 0x0000001F;
394 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
395 if (cb(&sdesc, context) == 0)
396 return DD_OK;
398 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
399 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
400 pformat->x.dwRGBBitCount = 16;
401 pformat->y.dwRBitMask = 0x0000F800;
402 pformat->z.dwGBitMask = 0x000007C0;
403 pformat->xx.dwBBitMask = 0x0000003E;
404 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
405 if (cb(&sdesc, context) == 0)
406 return DD_OK;
408 TRACE(ddraw, "Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
409 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
410 pformat->x.dwRGBBitCount = 16;
411 pformat->y.dwRBitMask = 0x0000F000;
412 pformat->z.dwGBitMask = 0x00000F00;
413 pformat->xx.dwBBitMask = 0x000000F0;
414 pformat->xy.dwRGBAlphaBitMask = 0x0000000F;
415 if (cb(&sdesc, context) == 0)
416 return DD_OK;
418 TRACE(ddraw, "Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
419 pformat->dwFlags = DDPF_RGB;
420 pformat->x.dwRGBBitCount = 8;
421 pformat->y.dwRBitMask = 0x0000F800;
422 pformat->z.dwGBitMask = 0x000007C0;
423 pformat->xx.dwBBitMask = 0x0000003E;
424 pformat->xy.dwRGBAlphaBitMask = 0x00000001;
425 if (cb(&sdesc, context) == 0)
426 return DD_OK;
427 #endif
429 TRACE(ddraw, "Enumerating Paletted (8)\n");
430 pformat->dwFlags = DDPF_PALETTEINDEXED8;
431 pformat->x.dwRGBBitCount = 8;
432 pformat->y.dwRBitMask = 0x00000000;
433 pformat->z.dwGBitMask = 0x00000000;
434 pformat->xx.dwBBitMask = 0x00000000;
435 pformat->xy.dwRGBAlphaBitMask = 0x00000000;
436 if (cb(&sdesc, context) == 0)
437 return DD_OK;
439 TRACE(ddraw, "End of enumeration\n");
441 return DD_OK;
444 static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
445 LPD3DENUMTEXTUREFORMATSCALLBACK cb,
446 LPVOID context)
448 ICOM_THIS(IDirect3DDevice2Impl,iface);
449 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, cb, context);
451 return enum_texture_format_OpenGL(cb, context);
456 static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
458 ICOM_THIS(IDirect3DDevice2Impl,iface);
459 /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
461 FIXME(ddraw, "(%p)->(): stub\n", This);
463 /* Here, we should get the DDraw surface and 'copy it' to the
464 OpenGL surface.... */
466 return DD_OK;
471 static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
473 ICOM_THIS(IDirect3DDevice2Impl,iface);
474 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
475 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
476 DDSURFACEDESC sdesc;
477 int x,y;
478 unsigned char *src;
479 unsigned short *dest;
481 FIXME(ddraw, "(%p)->(): stub\n", This);
483 /* Here we copy back the OpenGL scene to the the DDraw surface */
484 /* First, lock the surface */
485 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
487 /* The copy the OpenGL buffer to this surface */
489 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
490 I am currently working on a set of patches for Mesa to have OSMesa support
491 16 bpp surfaces => we will able to render directly onto the surface, no
492 need to do a bpp conversion */
493 dest = (unsigned short *) sdesc.y.lpSurface;
494 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
495 for (y = 0; y < sdesc.dwHeight; y++) {
496 unsigned char *lsrc = src;
498 for (x = 0; x < sdesc.dwWidth ; x++) {
499 unsigned char r = *lsrc++;
500 unsigned char g = *lsrc++;
501 unsigned char b = *lsrc++;
502 lsrc++; /* Alpha */
503 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
505 dest++;
508 src -= 4 * sdesc.dwWidth;
511 /* Unlock the surface */
512 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
514 return DD_OK;
519 static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
521 ICOM_THIS(IDirect3DDevice2Impl,iface);
522 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpd3d2);
524 *lpd3d2 = (LPDIRECT3D2)This->d3d;
526 return DD_OK;
531 /*** DrawPrimitive API ***/
532 static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
533 LPDIRECT3DVIEWPORT2 lpvp)
535 ICOM_THIS(IDirect3DDevice2Impl,iface);
536 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
537 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
539 /* Should check if the viewport was added or not */
541 /* Set this viewport as the current viewport */
542 This->current_viewport = ilpvp;
544 /* Activate this viewport */
545 ilpvp->device.active_device2 = This;
546 ilpvp->activate(ilpvp);
548 return DD_OK;
553 static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
554 LPDIRECT3DVIEWPORT2 *lplpvp)
556 ICOM_THIS(IDirect3DDevice2Impl,iface);
557 FIXME(ddraw, "(%p)->(%p): stub\n", This, lplpvp);
559 /* Returns the current viewport */
560 *lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
562 return DD_OK;
567 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
568 LPDIRECTDRAWSURFACE lpdds,
569 DWORD dwFlags)
571 ICOM_THIS(IDirect3DDevice2Impl,iface);
572 FIXME(ddraw, "(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
574 return DD_OK;
579 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
580 LPDIRECTDRAWSURFACE *lplpdds)
582 ICOM_THIS(IDirect3DDevice2Impl,iface);
583 FIXME(ddraw, "(%p)->(%p): stub\n", This, lplpdds);
585 /* Returns the current rendering target (the surface on wich we render) */
586 *lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
588 return DD_OK;
593 static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
594 D3DPRIMITIVETYPE d3dp,
595 D3DVERTEXTYPE d3dv,
596 DWORD dwFlags)
598 ICOM_THIS(IDirect3DDevice2Impl,iface);
599 FIXME(ddraw, "(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
601 return DD_OK;
606 static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
607 D3DPRIMITIVETYPE d3dp,
608 D3DVERTEXTYPE d3dv,
609 LPVOID lpvert,
610 DWORD numvert,
611 DWORD dwFlags)
613 ICOM_THIS(IDirect3DDevice2Impl,iface);
614 FIXME(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
616 return DD_OK;
621 static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
622 LPVOID lpvert)
624 ICOM_THIS(IDirect3DDevice2Impl,iface);
625 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvert);
627 return DD_OK;
632 static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
633 WORD index)
635 ICOM_THIS(IDirect3DDevice2Impl,iface);
636 FIXME(ddraw, "(%p)->(%d): stub\n", This, index);
638 return DD_OK;
643 static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
644 DWORD dwFlags)
646 ICOM_THIS(IDirect3DDevice2Impl,iface);
647 FIXME(ddraw, "(%p)->(%08lx): stub\n", This, dwFlags);
649 return DD_OK;
655 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
656 D3DRENDERSTATETYPE d3drs,
657 LPDWORD lprstate)
659 ICOM_THIS(IDirect3DDevice2Impl,iface);
660 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
662 return DD_OK;
667 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
668 D3DRENDERSTATETYPE dwRenderStateType,
669 DWORD dwRenderState)
671 ICOM_THIS(IDirect3DDevice2Impl,iface);
672 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
674 TRACE(ddraw, "(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
676 /* Call the render state functions */
677 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
679 return DD_OK;
684 static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
685 D3DLIGHTSTATETYPE d3dls,
686 LPDWORD lplstate)
688 ICOM_THIS(IDirect3DDevice2Impl,iface);
689 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
691 return DD_OK;
696 static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
697 D3DLIGHTSTATETYPE dwLightStateType,
698 DWORD dwLightState)
700 ICOM_THIS(IDirect3DDevice2Impl,iface);
701 FIXME(ddraw, "(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
703 switch (dwLightStateType) {
704 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
705 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
707 if (mat != NULL) {
708 mat->activate(mat);
709 } else {
710 TRACE(ddraw, "Zoups !!!\n");
712 } break;
714 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
715 float light[4];
717 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
718 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
719 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
720 light[3] = 1.0;
721 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
722 } break;
724 case D3DLIGHTSTATE_COLORMODEL: /* 3 */
725 break;
727 case D3DLIGHTSTATE_FOGMODE: /* 4 */
728 break;
730 case D3DLIGHTSTATE_FOGSTART: /* 5 */
731 break;
733 case D3DLIGHTSTATE_FOGEND: /* 6 */
734 break;
736 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
737 break;
739 default:
740 TRACE(ddraw, "Unexpected Light State Type\n");
741 return DDERR_INVALIDPARAMS;
744 return DD_OK;
749 static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
750 D3DTRANSFORMSTATETYPE d3dts,
751 LPD3DMATRIX lpmatrix)
753 ICOM_THIS(IDirect3DDevice2Impl,iface);
754 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
756 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
758 /* Using a trial and failure approach, I found that the order of
759 Direct3D transformations that works best is :
761 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
763 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
764 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
766 If anyone has a good explanation of the three different matrices in
767 the SDK online documentation, feel free to point it to me. For example,
768 which matrices transform lights ? In OpenGL only the PROJECTION matrix
769 transform the lights, not the MODELVIEW. Using the matrix names, I
770 supposed that PROJECTION and VIEW (all 'camera' related names) do
771 transform lights, but WORLD do not. It may be wrong though... */
773 /* After reading through both OpenGL and Direct3D documentations, I
774 thought that D3D matrices were written in 'line major mode' transposed
775 from OpenGL's 'column major mode'. But I found out that a simple memcpy
776 works fine to transfer one matrix format to the other (it did not work
777 when transposing)....
779 So :
780 1) are the documentations wrong
781 2) does the matrix work even if they are not read correctly
782 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
783 loading using glLoadMatrix ?
785 Anyway, I always use 'conv_mat' to transfer the matrices from one format
786 to the other so that if I ever find out that I need to transpose them, I
787 will able to do it quickly, only by changing the macro conv_mat. */
789 switch (d3dts) {
790 case D3DTRANSFORMSTATE_WORLD: {
791 conv_mat(lpmatrix, odev->world_mat);
792 glMatrixMode(GL_MODELVIEW);
793 glLoadMatrixf((float *) &(odev->world_mat));
794 } break;
796 case D3DTRANSFORMSTATE_VIEW: {
797 conv_mat(lpmatrix, odev->view_mat);
798 glMatrixMode(GL_PROJECTION);
799 glLoadMatrixf((float *) &(odev->proj_mat));
800 glMultMatrixf((float *) &(odev->view_mat));
801 } break;
803 case D3DTRANSFORMSTATE_PROJECTION: {
804 conv_mat(lpmatrix, odev->proj_mat);
805 glMatrixMode(GL_PROJECTION);
806 glLoadMatrixf((float *) &(odev->proj_mat));
807 glMultMatrixf((float *) &(odev->view_mat));
808 } break;
810 default:
811 break;
814 return DD_OK;
819 static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
820 D3DTRANSFORMSTATETYPE d3dts,
821 LPD3DMATRIX lpmatrix)
823 ICOM_THIS(IDirect3DDevice2Impl,iface);
824 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
826 return DD_OK;
831 static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
832 D3DTRANSFORMSTATETYPE d3dts,
833 LPD3DMATRIX lpmatrix)
835 ICOM_THIS(IDirect3DDevice2Impl,iface);
836 FIXME(ddraw, "(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
838 return DD_OK;
841 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
842 /* Puts GL in the correct lighting mode */ \
843 if (odev->vt != d3dv) { \
844 if (odev->vt == D3DVT_TLVERTEX) { \
845 /* Need to put the correct transformation again */ \
846 glMatrixMode(GL_MODELVIEW); \
847 glLoadMatrixf((float *) &(odev->world_mat)); \
848 glMatrixMode(GL_PROJECTION); \
849 glLoadMatrixf((float *) &(odev->proj_mat)); \
850 glMultMatrixf((float *) &(odev->view_mat)); \
853 switch (d3dv) { \
854 case D3DVT_VERTEX: \
855 TRACE(ddraw, "Standard Vertex\n"); \
856 glEnable(GL_LIGHTING); \
857 break; \
859 case D3DVT_LVERTEX: \
860 TRACE(ddraw, "Lighted Vertex\n"); \
861 glDisable(GL_LIGHTING); \
862 break; \
864 case D3DVT_TLVERTEX: { \
865 GLdouble height, width, minZ, maxZ; \
867 TRACE(ddraw, "Transformed - Lighted Vertex\n"); \
868 /* First, disable lighting */ \
869 glDisable(GL_LIGHTING); \
871 /* Then do not put any transformation matrixes */ \
872 glMatrixMode(GL_MODELVIEW); \
873 glLoadIdentity(); \
874 glMatrixMode(GL_PROJECTION); \
875 glLoadIdentity(); \
877 if (This->current_viewport == NULL) { \
878 ERR(ddraw, "No current viewport !\n"); \
879 /* Using standard values */ \
880 height = 640.0; \
881 width = 480.0; \
882 minZ = -10.0; \
883 maxZ = 10.0; \
884 } else { \
885 if (This->current_viewport->use_vp2) { \
886 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight; \
887 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth; \
888 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ; \
889 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ; \
890 } else { \
891 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight; \
892 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth; \
893 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ; \
894 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ; \
898 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
899 } break; \
901 default: \
902 ERR(ddraw, "Unhandled vertex type\n"); \
903 break; \
906 odev->vt = d3dv; \
909 switch (d3dp) { \
910 case D3DPT_POINTLIST: \
911 TRACE(ddraw, "Start POINTS\n"); \
912 glBegin(GL_POINTS); \
913 break; \
915 case D3DPT_LINELIST: \
916 TRACE(ddraw, "Start LINES\n"); \
917 glBegin(GL_LINES); \
918 break; \
920 case D3DPT_LINESTRIP: \
921 TRACE(ddraw, "Start LINE_STRIP\n"); \
922 glBegin(GL_LINE_STRIP); \
923 break; \
925 case D3DPT_TRIANGLELIST: \
926 TRACE(ddraw, "Start TRIANGLES\n"); \
927 glBegin(GL_TRIANGLES); \
928 break; \
930 case D3DPT_TRIANGLESTRIP: \
931 TRACE(ddraw, "Start TRIANGLE_STRIP\n"); \
932 glBegin(GL_TRIANGLE_STRIP); \
933 break; \
935 case D3DPT_TRIANGLEFAN: \
936 TRACE(ddraw, "Start TRIANGLE_FAN\n"); \
937 glBegin(GL_TRIANGLE_FAN); \
938 break; \
940 default: \
941 TRACE(ddraw, "Unhandled primitive\n"); \
942 break; \
945 /* Draw the primitives */ \
946 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
947 switch (d3dv) { \
948 case D3DVT_VERTEX: { \
949 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
951 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
952 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
953 TRACE(ddraw, " V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
954 } break; \
956 case D3DVT_LVERTEX: { \
957 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
958 DWORD col = vx->c.color; \
960 glColor3f(((col >> 16) & 0xFF) / 255.0, \
961 ((col >> 8) & 0xFF) / 255.0, \
962 ((col >> 0) & 0xFF) / 255.0); \
963 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
964 TRACE(ddraw, " LV: %f %f %f (%02lx %02lx %02lx)\n", \
965 vx->x.x, vx->y.y, vx->z.z, \
966 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
967 } break; \
969 case D3DVT_TLVERTEX: { \
970 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
971 DWORD col = vx->c.color; \
973 glColor3f(((col >> 16) & 0xFF) / 255.0, \
974 ((col >> 8) & 0xFF) / 255.0, \
975 ((col >> 0) & 0xFF) / 255.0); \
976 glTexCoord2f(vx->u.tu, vx->v.tv); \
977 if (vx->r.rhw < 0.01) \
978 glVertex3f(vx->x.sx, \
979 vx->y.sy, \
980 vx->z.sz); \
981 else \
982 glVertex4f(vx->x.sx / vx->r.rhw, \
983 vx->y.sy / vx->r.rhw, \
984 vx->z.sz / vx->r.rhw, \
985 1.0 / vx->r.rhw); \
986 TRACE(ddraw, " TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
987 vx->x.sx, vx->y.sy, vx->z.sz, \
988 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
989 vx->u.tu, vx->v.tv, vx->r.rhw); \
990 } break; \
992 default: \
993 TRACE(ddraw, "Unhandled vertex type\n"); \
994 break; \
998 glEnd(); \
999 TRACE(ddraw, "End\n");
1002 static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1003 D3DPRIMITIVETYPE d3dp,
1004 D3DVERTEXTYPE d3dv,
1005 LPVOID lpvertex,
1006 DWORD vertcount,
1007 DWORD dwFlags)
1009 ICOM_THIS(IDirect3DDevice2Impl,iface);
1010 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1011 int vx_index;
1013 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
1015 DRAW_PRIMITIVE(vertcount, vx_index);
1017 return D3D_OK;
1022 static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1023 D3DPRIMITIVETYPE d3dp,
1024 D3DVERTEXTYPE d3dv,
1025 LPVOID lpvertex,
1026 DWORD vertcount,
1027 LPWORD lpindexes,
1028 DWORD indexcount,
1029 DWORD dwFlags)
1031 ICOM_THIS(IDirect3DDevice2Impl,iface);
1032 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1033 int vx_index;
1035 TRACE(ddraw, "(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1037 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1039 return D3D_OK;
1044 static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
1045 LPD3DCLIPSTATUS lpcs)
1047 ICOM_THIS(IDirect3DDevice2Impl,iface);
1048 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpcs);
1050 return DD_OK;
1055 static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
1056 LPD3DCLIPSTATUS lpcs)
1058 ICOM_THIS(IDirect3DDevice2Impl,iface);
1059 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpcs);
1061 return DD_OK;
1066 /*******************************************************************************
1067 * OpenGL-specific IDirect3DDevice2
1070 /*******************************************************************************
1071 * OpenGL-specific VTable
1074 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable = {
1075 IDirect3DDevice2Impl_QueryInterface,
1076 IDirect3DDevice2Impl_AddRef,
1077 IDirect3DDevice2Impl_Release,
1078 /*** IDirect3DDevice2 methods ***/
1079 IDirect3DDevice2Impl_GetCaps,
1080 IDirect3DDevice2Impl_SwapTextureHandles,
1081 IDirect3DDevice2Impl_GetStats,
1082 IDirect3DDevice2Impl_AddViewport,
1083 IDirect3DDevice2Impl_DeleteViewport,
1084 IDirect3DDevice2Impl_NextViewport,
1085 IDirect3DDevice2Impl_EnumTextureFormats,
1086 IDirect3DDevice2Impl_BeginScene,
1087 IDirect3DDevice2Impl_EndScene,
1088 IDirect3DDevice2Impl_GetDirect3D,
1090 /*** DrawPrimitive API ***/
1091 IDirect3DDevice2Impl_SetCurrentViewport,
1092 IDirect3DDevice2Impl_GetCurrentViewport,
1094 IDirect3DDevice2Impl_SetRenderTarget,
1095 IDirect3DDevice2Impl_GetRenderTarget,
1097 IDirect3DDevice2Impl_Begin,
1098 IDirect3DDevice2Impl_BeginIndexed,
1099 IDirect3DDevice2Impl_Vertex,
1100 IDirect3DDevice2Impl_Index,
1101 IDirect3DDevice2Impl_End,
1103 IDirect3DDevice2Impl_GetRenderState,
1104 IDirect3DDevice2Impl_SetRenderState,
1105 IDirect3DDevice2Impl_GetLightState,
1106 IDirect3DDevice2Impl_SetLightState,
1107 IDirect3DDevice2Impl_SetTransform,
1108 IDirect3DDevice2Impl_GetTransform,
1109 IDirect3DDevice2Impl_MultiplyTransform,
1111 IDirect3DDevice2Impl_DrawPrimitive,
1112 IDirect3DDevice2Impl_DrawIndexedPrimitive,
1114 IDirect3DDevice2Impl_SetClipStatus,
1115 IDirect3DDevice2Impl_GetClipStatus,
1118 /*******************************************************************************
1119 * Direct3DDevice
1121 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1122 D3DDEVICEDESC d1,d2;
1124 TRACE(ddraw," Enumerating OpenGL D3D device.\n");
1126 fill_opengl_caps(&d1, &d2);
1128 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1131 float id_mat[16] = {
1132 1.0, 0.0, 0.0, 0.0,
1133 0.0, 1.0, 0.0, 0.0,
1134 0.0, 0.0, 1.0, 0.0,
1135 0.0, 0.0, 0.0, 1.0
1138 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1140 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1141 OpenGL_IDirect3DDevice *odev;
1143 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1144 odev = (OpenGL_IDirect3DDevice *) (*device);
1145 (*device)->ref = 1;
1146 (*device)->lpvtbl = &OpenGL_vtable_dx3;
1147 (*device)->d3d = NULL;
1148 (*device)->surface = surface;
1150 (*device)->viewport_list = NULL;
1151 (*device)->current_viewport = NULL;
1153 (*device)->set_context = set_context_dx3;
1155 TRACE(ddraw, "OpenGL device created \n");
1157 /* Create the OpenGL context */
1158 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1159 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1160 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1161 odev->rs.src = GL_ONE;
1162 odev->rs.dst = GL_ZERO;
1163 odev->rs.mag = GL_NEAREST;
1164 odev->rs.min = GL_NEAREST;
1166 odev->world_mat = (LPD3DMATRIX) &id_mat;
1167 odev->view_mat = (LPD3DMATRIX) &id_mat;
1168 odev->proj_mat = (LPD3DMATRIX) &id_mat;
1170 /* Initialisation */
1171 (*device)->set_context(*device);
1172 glClearColor(0.0, 0.0, 0.0, 0.0);
1173 glColor3f(1.0, 1.0, 1.0);
1175 return 1;
1178 /* This is not the OpenGL UID */
1179 return DD_OK;
1183 /*******************************************************************************
1184 * Direct3DDevice
1186 static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
1187 REFIID riid,
1188 LPVOID* ppvObj)
1190 ICOM_THIS(IDirect3DDeviceImpl,iface);
1191 char xrefiid[50];
1193 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1194 FIXME(ddraw, "(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
1196 return S_OK;
1201 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1203 ICOM_THIS(IDirect3DDeviceImpl,iface);
1204 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", This, This->ref );
1206 return ++(This->ref);
1211 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1213 ICOM_THIS(IDirect3DDeviceImpl,iface);
1214 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
1216 if (!--(This->ref)) {
1217 HeapFree(GetProcessHeap(),0,This);
1218 return 0;
1221 return This->ref;
1224 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1225 LPDIRECT3D lpd3d,
1226 LPGUID lpGUID,
1227 LPD3DDEVICEDESC lpd3ddvdesc)
1229 ICOM_THIS(IDirect3DDeviceImpl,iface);
1230 TRACE(ddraw, "(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1232 return DDERR_ALREADYINITIALIZED;
1236 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1237 LPD3DDEVICEDESC lpD3DHWDevDesc,
1238 LPD3DDEVICEDESC lpD3DSWDevDesc)
1240 ICOM_THIS(IDirect3DDeviceImpl,iface);
1241 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1243 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1245 return DD_OK;
1249 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1250 LPDIRECT3DTEXTURE lpD3DTex1,
1251 LPDIRECT3DTEXTURE lpD3DTex2)
1253 ICOM_THIS(IDirect3DDeviceImpl,iface);
1254 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1256 return DD_OK;
1259 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1260 LPD3DEXECUTEBUFFERDESC lpDesc,
1261 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1262 IUnknown *pUnkOuter)
1264 ICOM_THIS(IDirect3DDeviceImpl,iface);
1265 TRACE(ddraw, "(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1267 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1269 return DD_OK;
1273 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1274 LPD3DSTATS lpD3DStats)
1276 ICOM_THIS(IDirect3DDeviceImpl,iface);
1277 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpD3DStats);
1279 return DD_OK;
1283 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1284 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1285 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1286 DWORD dwFlags)
1288 ICOM_THIS(IDirect3DDeviceImpl,iface);
1289 TRACE(ddraw, "(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1291 /* Put this as the default context */
1293 /* Execute... */
1294 ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1296 return DD_OK;
1299 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1300 LPDIRECT3DVIEWPORT lpvp)
1302 ICOM_THIS(IDirect3DDeviceImpl,iface);
1303 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1304 FIXME(ddraw, "(%p)->(%p): stub\n", This, ilpvp);
1306 /* Adds this viewport to the viewport list */
1307 ilpvp->next = This->viewport_list;
1308 This->viewport_list = ilpvp;
1310 return DD_OK;
1315 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1316 LPDIRECT3DVIEWPORT lpvp)
1318 ICOM_THIS(IDirect3DDeviceImpl,iface);
1319 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1320 IDirect3DViewport2Impl *cur, *prev;
1321 FIXME(ddraw, "(%p)->(%p): stub\n", This, lpvp);
1323 /* Finds this viewport in the list */
1324 prev = NULL;
1325 cur = This->viewport_list;
1326 while ((cur != NULL) && (cur != ilpvp)) {
1327 prev = cur;
1328 cur = cur->next;
1330 if (cur == NULL)
1331 return DDERR_INVALIDOBJECT;
1333 /* And remove it */
1334 if (prev == NULL)
1335 This->viewport_list = cur->next;
1336 else
1337 prev->next = cur->next;
1339 return DD_OK;
1344 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1345 LPDIRECT3DVIEWPORT lpvp,
1346 LPDIRECT3DVIEWPORT* lplpvp,
1347 DWORD dwFlags)
1349 ICOM_THIS(IDirect3DDeviceImpl,iface);
1350 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1351 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1352 FIXME(ddraw, "(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1354 switch (dwFlags) {
1355 case D3DNEXT_NEXT:
1356 *ilplpvp = ilpvp->next;
1357 break;
1359 case D3DNEXT_HEAD:
1360 *ilplpvp = This->viewport_list;
1361 break;
1363 case D3DNEXT_TAIL:
1364 ilpvp = This->viewport_list;
1365 while (ilpvp->next != NULL)
1366 ilpvp = ilpvp->next;
1368 *ilplpvp = ilpvp;
1369 break;
1371 default:
1372 return DDERR_INVALIDPARAMS;
1375 return DD_OK;
1378 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1379 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1380 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1381 DWORD dwFlags,
1382 LPD3DRECT lpRect)
1384 ICOM_THIS(IDirect3DDeviceImpl,iface);
1385 TRACE(ddraw, "(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1386 dwFlags, lpRect);
1388 return DD_OK;
1392 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1393 LPDWORD lpCount,
1394 LPD3DPICKRECORD lpD3DPickRec)
1396 ICOM_THIS(IDirect3DDeviceImpl,iface);
1397 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1399 return DD_OK;
1403 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1404 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1405 LPVOID lpArg)
1407 ICOM_THIS(IDirect3DDeviceImpl,iface);
1408 TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1410 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1414 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1415 LPD3DMATRIXHANDLE lpD3DMatHandle)
1417 ICOM_THIS(IDirect3DDeviceImpl,iface);
1418 TRACE(ddraw, "(%p)->(%p)\n", This, lpD3DMatHandle);
1420 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1422 return DD_OK;
1426 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1427 D3DMATRIXHANDLE d3dMatHandle,
1428 const LPD3DMATRIX lpD3DMatrix)
1430 ICOM_THIS(IDirect3DDeviceImpl,iface);
1431 TRACE(ddraw, "(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1433 dump_mat(lpD3DMatrix);
1435 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1437 return DD_OK;
1441 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1442 D3DMATRIXHANDLE D3DMatHandle,
1443 LPD3DMATRIX lpD3DMatrix)
1445 ICOM_THIS(IDirect3DDeviceImpl,iface);
1446 TRACE(ddraw, "(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1448 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1450 return DD_OK;
1454 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1455 D3DMATRIXHANDLE d3dMatHandle)
1457 ICOM_THIS(IDirect3DDeviceImpl,iface);
1458 TRACE(ddraw, "(%p)->(%08lx)\n", This, d3dMatHandle);
1460 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1462 return DD_OK;
1466 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1468 ICOM_THIS(IDirect3DDeviceImpl,iface);
1469 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1471 FIXME(ddraw, "(%p)->(): stub\n", This);
1473 /* We get the pointer to the surface (should be done on flip) */
1474 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1476 return DD_OK;
1480 /* This is for the moment copy-pasted from IDirect3DDevice2...
1481 Will make a common function ... */
1482 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1484 ICOM_THIS(IDirect3DDeviceImpl,iface);
1485 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1486 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1487 DDSURFACEDESC sdesc;
1488 int x,y;
1489 unsigned char *src;
1490 unsigned short *dest;
1492 FIXME(ddraw, "(%p)->(): stub\n", This);
1494 /* Here we copy back the OpenGL scene to the the DDraw surface */
1495 /* First, lock the surface */
1496 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1498 /* The copy the OpenGL buffer to this surface */
1500 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1501 I am currently working on a set of patches for Mesa to have OSMesa support
1502 16 bpp surfaces => we will able to render directly onto the surface, no
1503 need to do a bpp conversion */
1504 dest = (unsigned short *) sdesc.y.lpSurface;
1505 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1506 for (y = 0; y < sdesc.dwHeight; y++) {
1507 unsigned char *lsrc = src;
1509 for (x = 0; x < sdesc.dwWidth ; x++) {
1510 unsigned char r = *lsrc++;
1511 unsigned char g = *lsrc++;
1512 unsigned char b = *lsrc++;
1513 lsrc++; /* Alpha */
1515 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1517 dest++;
1520 src -= 4 * sdesc.dwWidth;
1523 /* Unlock the surface */
1524 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1526 return DD_OK;
1530 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1531 LPDIRECT3D *lpDirect3D)
1533 ICOM_THIS(IDirect3DDeviceImpl,iface);
1534 TRACE(ddraw, "(%p)->(%p): stub\n", This, lpDirect3D);
1536 return DD_OK;
1541 /*******************************************************************************
1542 * Direct3DDevice VTable
1544 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 = {
1545 IDirect3DDeviceImpl_QueryInterface,
1546 IDirect3DDeviceImpl_AddRef,
1547 IDirect3DDeviceImpl_Release,
1548 IDirect3DDeviceImpl_Initialize,
1549 IDirect3DDeviceImpl_GetCaps,
1550 IDirect3DDeviceImpl_SwapTextureHandles,
1551 IDirect3DDeviceImpl_CreateExecuteBuffer,
1552 IDirect3DDeviceImpl_GetStats,
1553 IDirect3DDeviceImpl_Execute,
1554 IDirect3DDeviceImpl_AddViewport,
1555 IDirect3DDeviceImpl_DeleteViewport,
1556 IDirect3DDeviceImpl_NextViewport,
1557 IDirect3DDeviceImpl_Pick,
1558 IDirect3DDeviceImpl_GetPickRecords,
1559 IDirect3DDeviceImpl_EnumTextureFormats,
1560 IDirect3DDeviceImpl_CreateMatrix,
1561 IDirect3DDeviceImpl_SetMatrix,
1562 IDirect3DDeviceImpl_GetMatrix,
1563 IDirect3DDeviceImpl_DeleteMatrix,
1564 IDirect3DDeviceImpl_BeginScene,
1565 IDirect3DDeviceImpl_EndScene,
1566 IDirect3DDeviceImpl_GetDirect3D,
1569 #else /* HAVE_MESAGL */
1571 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1572 return 0;
1575 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1577 return 0;
1580 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1581 return 0;
1584 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1586 return 0;
1589 #endif /* HAVE_MESAGL */