ErrorInfo functions need to be in ole32, not oleaut32.
[wine.git] / graphics / d3ddevices.c
blobefe730ea41fba2c5942747f06f7e8978d1dd0ce4
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 "debugtools.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.1b2 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 #ifdef USE_OSMESA
54 OSMesaMakeCurrent(odev->ctx, odev->buffer,
55 GL_UNSIGNED_BYTE,
56 This->surface->s.surface_desc.dwWidth,
57 This->surface->s.surface_desc.dwHeight);
58 #else
59 if (glXMakeCurrent(display,
60 odev->common.surface->s.ddraw->d.drawable,
61 odev->ctx) == False) {
62 ERR("Error in setting current context (context %p drawable %ld)!\n",
63 odev->ctx, odev->common.surface->s.ddraw->d.drawable);
65 #endif
68 static void set_context_dx3(IDirect3DDeviceImpl* This) {
69 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
71 #ifdef USE_OSMESA
72 OSMesaMakeCurrent(odev->ctx, odev->buffer,
73 GL_UNSIGNED_BYTE,
74 This->surface->s.surface_desc.dwWidth,
75 This->surface->s.surface_desc.dwHeight);
76 #else
77 if (glXMakeCurrent(display,
78 odev->common.surface->s.ddraw->d.drawable,
79 odev->ctx) == False) {
80 ERR("Error in setting current context !\n");
82 #endif
85 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
87 pc->dwSize = sizeof(*pc);
88 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
89 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
90 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
91 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
92 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
93 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
94 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
95 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
96 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
97 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
98 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
99 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
100 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
101 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
102 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
103 pc->dwStippleWidth = 32;
104 pc->dwStippleHeight = 32;
107 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
109 /* GLint maxlight; */
111 d1->dwSize = sizeof(*d1);
112 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
113 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
114 d1->dcmColorModel = D3DCOLOR_RGB;
115 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
116 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
117 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
118 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
119 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
120 d1->bClipping = TRUE;
121 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
122 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
123 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
124 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
125 fill_opengl_primcaps(&(d1->dpcLineCaps));
126 fill_opengl_primcaps(&(d1->dpcTriCaps));
127 d1->dwDeviceRenderBitDepth = DDBD_16;
128 d1->dwDeviceZBufferBitDepth = DDBD_16;
129 d1->dwMaxBufferSize = 0;
130 d1->dwMaxVertexCount = 65536;
131 d1->dwMinTextureWidth = 1;
132 d1->dwMinTextureHeight = 1;
133 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
134 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
135 d1->dwMinStippleWidth = 1;
136 d1->dwMinStippleHeight = 1;
137 d1->dwMaxStippleWidth = 32;
138 d1->dwMaxStippleHeight = 32;
140 d2->dwSize = sizeof(*d2);
141 d2->dwFlags = 0;
144 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
145 D3DDEVICEDESC d1,d2;
147 TRACE(" Enumerating OpenGL D3D device.\n");
149 fill_opengl_caps(&d1, &d2);
151 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
154 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
156 if (/* Default device */
157 (rguid == NULL) ||
158 /* HAL Device */
159 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
160 /* OpenGL Device */
161 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
162 OpenGL_IDirect3DDevice2 *odev;
164 const float id_mat[16] = {
165 1.0, 0.0, 0.0, 0.0,
166 0.0, 1.0, 0.0, 0.0,
167 0.0, 0.0, 1.0, 0.0,
168 0.0, 0.0, 0.0, 1.0
170 #ifndef USE_OSMESA
171 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
172 XVisualInfo *xvis;
173 #endif
175 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice2));
176 odev = (OpenGL_IDirect3DDevice2 *) (*device);
177 (*device)->ref = 1;
178 ICOM_VTBL(*device) = &OpenGL_vtable;
179 (*device)->d3d = d3d;
180 (*device)->surface = surface;
182 (*device)->viewport_list = NULL;
183 (*device)->current_viewport = NULL;
185 (*device)->set_context = set_context;
187 TRACE("Creating OpenGL device for surface %p\n", surface);
189 /* Create the OpenGL context */
190 #ifdef USE_OSMESA
191 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
192 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
193 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
194 #else
195 /* First get the correct visual */
196 /* if (surface->s.backbuffer == NULL)
197 attributeList[3] = None; */
198 ENTER_GL();
199 xvis = glXChooseVisual(display,
200 DefaultScreen(display),
201 attributeList);
202 if (xvis == NULL)
203 ERR("No visual found !\n");
204 else
205 TRACE("Visual found\n");
206 /* Create the context */
207 odev->ctx = glXCreateContext(display,
208 xvis,
209 NULL,
210 GL_TRUE);
211 if (odev->ctx == NULL)
212 ERR("Error in context creation !\n");
213 else
214 TRACE("Context created (%p)\n", odev->ctx);
216 /* Now override the surface's Flip method (if in double buffering) */
217 surface->s.d3d_device = (void *) odev;
219 int i;
220 struct _surface_chain *chain = surface->s.chain;
221 for (i=0;i<chain->nrofsurfaces;i++)
222 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
223 chain->surfaces[i]->s.d3d_device = (void *) odev;
225 #endif
226 odev->rs.src = GL_ONE;
227 odev->rs.dst = GL_ZERO;
228 odev->rs.mag = GL_NEAREST;
229 odev->rs.min = GL_NEAREST;
230 odev->vt = 0;
232 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
233 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
234 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
236 /* Initialisation */
237 TRACE("Setting current context\n");
238 (*device)->set_context(*device);
239 TRACE("Current context set\n");
240 glClearColor(0.0, 0.0, 0.0, 0.0);
241 glColor3f(1.0, 1.0, 1.0);
242 LEAVE_GL();
244 TRACE("OpenGL device created \n");
246 return 1;
249 /* This is not the OpenGL UID */
250 return 0;
253 /*******************************************************************************
254 * Common IDirect3DDevice2
257 static HRESULT WINAPI IDirect3DDevice2Impl_QueryInterface(LPDIRECT3DDEVICE2 iface,
258 REFIID riid,
259 LPVOID* ppvObj)
261 ICOM_THIS(IDirect3DDevice2Impl,iface);
263 FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
265 return S_OK;
270 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
272 ICOM_THIS(IDirect3DDevice2Impl,iface);
273 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
275 return ++(This->ref);
280 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
282 ICOM_THIS(IDirect3DDevice2Impl,iface);
283 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
285 if (!--(This->ref)) {
286 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
288 #ifdef USE_OSMESA
289 OSMesaDestroyContext(odev->ctx);
290 #else
291 ENTER_GL();
292 glXDestroyContext(display,
293 odev->ctx);
294 LEAVE_GL();
295 #endif
297 HeapFree(GetProcessHeap(),0,This);
298 return 0;
301 return This->ref;
305 /*** IDirect3DDevice2 methods ***/
306 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
307 LPD3DDEVICEDESC lpdescsoft,
308 LPD3DDEVICEDESC lpdeschard)
310 ICOM_THIS(IDirect3DDevice2Impl,iface);
311 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
313 fill_opengl_caps(lpdescsoft, lpdeschard);
315 return DD_OK;
320 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
321 LPDIRECT3DTEXTURE2 lptex1,
322 LPDIRECT3DTEXTURE2 lptex2)
324 ICOM_THIS(IDirect3DDevice2Impl,iface);
325 FIXME("(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
327 return DD_OK;
332 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
333 LPD3DSTATS lpstats)
335 ICOM_THIS(IDirect3DDevice2Impl,iface);
336 FIXME("(%p)->(%p): stub\n", This, lpstats);
338 return DD_OK;
343 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
344 LPDIRECT3DVIEWPORT2 lpvp)
346 ICOM_THIS(IDirect3DDevice2Impl,iface);
347 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
348 FIXME("(%p)->(%p): stub\n", This, ilpvp);
350 /* Adds this viewport to the viewport list */
351 ilpvp->next = This->viewport_list;
352 This->viewport_list = ilpvp;
354 return DD_OK;
359 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
360 LPDIRECT3DVIEWPORT2 lpvp)
362 ICOM_THIS(IDirect3DDevice2Impl,iface);
363 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
364 IDirect3DViewport2Impl *cur, *prev;
365 FIXME("(%p)->(%p): stub\n", This, lpvp);
367 /* Finds this viewport in the list */
368 prev = NULL;
369 cur = This->viewport_list;
370 while ((cur != NULL) && (cur != ilpvp)) {
371 prev = cur;
372 cur = cur->next;
374 if (cur == NULL)
375 return DDERR_INVALIDOBJECT;
377 /* And remove it */
378 if (prev == NULL)
379 This->viewport_list = cur->next;
380 else
381 prev->next = cur->next;
383 return DD_OK;
388 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
389 LPDIRECT3DVIEWPORT2 lpvp,
390 LPDIRECT3DVIEWPORT2* lplpvp,
391 DWORD dwFlags)
393 ICOM_THIS(IDirect3DDevice2Impl,iface);
394 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
395 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
396 FIXME("(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
398 switch (dwFlags) {
399 case D3DNEXT_NEXT:
400 *ilplpvp = ilpvp->next;
401 break;
403 case D3DNEXT_HEAD:
404 *ilplpvp = This->viewport_list;
405 break;
407 case D3DNEXT_TAIL:
408 ilpvp = This->viewport_list;
409 while (ilpvp->next != NULL)
410 ilpvp = ilpvp->next;
412 *ilplpvp = ilpvp;
413 break;
415 default:
416 return DDERR_INVALIDPARAMS;
419 return DD_OK;
422 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
423 LPVOID context) {
424 DDSURFACEDESC sdesc;
425 LPDDPIXELFORMAT pformat;
427 /* Do the texture enumeration */
428 sdesc.dwSize = sizeof(DDSURFACEDESC);
429 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
430 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
431 pformat = &(sdesc.ddpfPixelFormat);
432 pformat->dwSize = sizeof(DDPIXELFORMAT);
433 pformat->dwFourCC = 0;
435 TRACE("Enumerating GL_RGBA unpacked (32)\n");
436 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
437 pformat->u.dwRGBBitCount = 32;
438 pformat->u1.dwRBitMask = 0xFF000000;
439 pformat->u2.dwGBitMask = 0x00FF0000;
440 pformat->u3.dwBBitMask = 0x0000FF00;
441 pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
442 if (cb(&sdesc, context) == 0)
443 return DD_OK;
445 TRACE("Enumerating GL_RGB unpacked (24)\n");
446 pformat->dwFlags = DDPF_RGB;
447 pformat->u.dwRGBBitCount = 24;
448 pformat->u1.dwRBitMask = 0x00FF0000;
449 pformat->u2.dwGBitMask = 0x0000FF00;
450 pformat->u3.dwBBitMask = 0x000000FF;
451 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
452 if (cb(&sdesc, context) == 0)
453 return DD_OK;
455 #ifndef HAVE_BUGGY_MESAGL
456 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
457 so that future version will work great. */
458 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
459 pformat->dwFlags = DDPF_RGB;
460 pformat->u.dwRGBBitCount = 16;
461 pformat->u1.dwRBitMask = 0x0000F800;
462 pformat->u2.dwGBitMask = 0x000007E0;
463 pformat->u3.dwBBitMask = 0x0000001F;
464 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
465 if (cb(&sdesc, context) == 0)
466 return DD_OK;
468 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
469 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
470 pformat->u.dwRGBBitCount = 16;
471 pformat->u1.dwRBitMask = 0x0000F800;
472 pformat->u2.dwGBitMask = 0x000007C0;
473 pformat->u3.dwBBitMask = 0x0000003E;
474 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
475 if (cb(&sdesc, context) == 0)
476 return DD_OK;
478 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
479 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
480 pformat->u.dwRGBBitCount = 16;
481 pformat->u1.dwRBitMask = 0x0000F000;
482 pformat->u2.dwGBitMask = 0x00000F00;
483 pformat->u3.dwBBitMask = 0x000000F0;
484 pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
485 if (cb(&sdesc, context) == 0)
486 return DD_OK;
488 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
489 pformat->dwFlags = DDPF_RGB;
490 pformat->u.dwRGBBitCount = 8;
491 pformat->u1.dwRBitMask = 0x0000F800;
492 pformat->u2.dwGBitMask = 0x000007C0;
493 pformat->u3.dwBBitMask = 0x0000003E;
494 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
495 if (cb(&sdesc, context) == 0)
496 return DD_OK;
497 #endif
499 #if defined(HAVE_GL_COLOR_TABLE) && defined(HAVE_GL_PALETTED_TEXTURE)
500 TRACE("Enumerating Paletted (8)\n");
501 pformat->dwFlags = DDPF_PALETTEINDEXED8;
502 pformat->u.dwRGBBitCount = 8;
503 pformat->u1.dwRBitMask = 0x00000000;
504 pformat->u2.dwGBitMask = 0x00000000;
505 pformat->u3.dwBBitMask = 0x00000000;
506 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
507 if (cb(&sdesc, context) == 0)
508 return DD_OK;
509 #endif
511 TRACE("End of enumeration\n");
513 return DD_OK;
516 static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
517 LPD3DENUMTEXTUREFORMATSCALLBACK cb,
518 LPVOID context)
520 ICOM_THIS(IDirect3DDevice2Impl,iface);
521 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
523 return enum_texture_format_OpenGL(cb, context);
528 static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
530 ICOM_THIS(IDirect3DDevice2Impl,iface);
531 /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
533 FIXME("(%p)->(): stub\n", This);
535 /* Here, we should get the DDraw surface and 'copy it' to the
536 OpenGL surface.... */
538 return DD_OK;
543 static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
545 ICOM_THIS(IDirect3DDevice2Impl,iface);
546 #ifdef USE_OSMESA
547 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
548 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
549 DDSURFACEDESC sdesc;
550 int x,y;
551 unsigned char *src;
552 unsigned short *dest;
553 #endif
555 FIXME("(%p)->(): stub\n", This);
557 #ifdef USE_OSMESA
558 /* Here we copy back the OpenGL scene to the the DDraw surface */
559 /* First, lock the surface */
560 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
562 /* The copy the OpenGL buffer to this surface */
564 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
565 I am currently working on a set of patches for Mesa to have OSMesa support
566 16 bpp surfaces => we will able to render directly onto the surface, no
567 need to do a bpp conversion */
568 dest = (unsigned short *) sdesc.y.lpSurface;
569 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
570 for (y = 0; y < sdesc.dwHeight; y++) {
571 unsigned char *lsrc = src;
573 for (x = 0; x < sdesc.dwWidth ; x++) {
574 unsigned char r = *lsrc++;
575 unsigned char g = *lsrc++;
576 unsigned char b = *lsrc++;
577 lsrc++; /* Alpha */
578 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
580 dest++;
583 src -= 4 * sdesc.dwWidth;
586 /* Unlock the surface */
587 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
588 #else
589 /* No need to do anything here... */
590 #endif
592 return DD_OK;
597 static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
599 ICOM_THIS(IDirect3DDevice2Impl,iface);
600 TRACE("(%p)->(%p): stub\n", This, lpd3d2);
602 *lpd3d2 = (LPDIRECT3D2)This->d3d;
604 return DD_OK;
609 /*** DrawPrimitive API ***/
610 static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
611 LPDIRECT3DVIEWPORT2 lpvp)
613 ICOM_THIS(IDirect3DDevice2Impl,iface);
614 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
615 FIXME("(%p)->(%p): stub\n", This, ilpvp);
617 /* Should check if the viewport was added or not */
619 /* Set this viewport as the current viewport */
620 This->current_viewport = ilpvp;
622 /* Activate this viewport */
623 ilpvp->device.active_device2 = This;
624 ilpvp->activate(ilpvp);
626 return DD_OK;
631 static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
632 LPDIRECT3DVIEWPORT2 *lplpvp)
634 ICOM_THIS(IDirect3DDevice2Impl,iface);
635 FIXME("(%p)->(%p): stub\n", This, lplpvp);
637 /* Returns the current viewport */
638 *lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
640 return DD_OK;
645 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
646 LPDIRECTDRAWSURFACE lpdds,
647 DWORD dwFlags)
649 ICOM_THIS(IDirect3DDevice2Impl,iface);
650 FIXME("(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
652 return DD_OK;
657 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
658 LPDIRECTDRAWSURFACE *lplpdds)
660 ICOM_THIS(IDirect3DDevice2Impl,iface);
661 FIXME("(%p)->(%p): stub\n", This, lplpdds);
663 /* Returns the current rendering target (the surface on wich we render) */
664 *lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
666 return DD_OK;
671 static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
672 D3DPRIMITIVETYPE d3dp,
673 D3DVERTEXTYPE d3dv,
674 DWORD dwFlags)
676 ICOM_THIS(IDirect3DDevice2Impl,iface);
677 FIXME("(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
679 return DD_OK;
684 static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
685 D3DPRIMITIVETYPE d3dp,
686 D3DVERTEXTYPE d3dv,
687 LPVOID lpvert,
688 DWORD numvert,
689 DWORD dwFlags)
691 ICOM_THIS(IDirect3DDevice2Impl,iface);
692 FIXME("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
694 return DD_OK;
699 static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
700 LPVOID lpvert)
702 ICOM_THIS(IDirect3DDevice2Impl,iface);
703 FIXME("(%p)->(%p): stub\n", This, lpvert);
705 return DD_OK;
710 static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
711 WORD index)
713 ICOM_THIS(IDirect3DDevice2Impl,iface);
714 FIXME("(%p)->(%d): stub\n", This, index);
716 return DD_OK;
721 static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
722 DWORD dwFlags)
724 ICOM_THIS(IDirect3DDevice2Impl,iface);
725 FIXME("(%p)->(%08lx): stub\n", This, dwFlags);
727 return DD_OK;
733 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
734 D3DRENDERSTATETYPE d3drs,
735 LPDWORD lprstate)
737 ICOM_THIS(IDirect3DDevice2Impl,iface);
738 FIXME("(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
740 return DD_OK;
745 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
746 D3DRENDERSTATETYPE dwRenderStateType,
747 DWORD dwRenderState)
749 ICOM_THIS(IDirect3DDevice2Impl,iface);
750 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
752 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
754 /* Call the render state functions */
755 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
757 return DD_OK;
762 static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
763 D3DLIGHTSTATETYPE d3dls,
764 LPDWORD lplstate)
766 ICOM_THIS(IDirect3DDevice2Impl,iface);
767 FIXME("(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
769 return DD_OK;
774 static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
775 D3DLIGHTSTATETYPE dwLightStateType,
776 DWORD dwLightState)
778 ICOM_THIS(IDirect3DDevice2Impl,iface);
779 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
781 switch (dwLightStateType) {
782 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
783 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
785 if (mat != NULL) {
786 ENTER_GL();
787 mat->activate(mat);
788 LEAVE_GL();
789 } else {
790 TRACE("Zoups !!!\n");
792 } break;
794 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
795 float light[4];
797 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
798 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
799 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
800 light[3] = 1.0;
801 ENTER_GL();
802 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
803 LEAVE_GL();
804 } break;
806 case D3DLIGHTSTATE_COLORMODEL: /* 3 */
807 break;
809 case D3DLIGHTSTATE_FOGMODE: /* 4 */
810 break;
812 case D3DLIGHTSTATE_FOGSTART: /* 5 */
813 break;
815 case D3DLIGHTSTATE_FOGEND: /* 6 */
816 break;
818 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
819 break;
821 default:
822 TRACE("Unexpected Light State Type\n");
823 return DDERR_INVALIDPARAMS;
826 return DD_OK;
831 static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
832 D3DTRANSFORMSTATETYPE d3dts,
833 LPD3DMATRIX lpmatrix)
835 ICOM_THIS(IDirect3DDevice2Impl,iface);
836 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
838 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
840 ENTER_GL();
842 /* Using a trial and failure approach, I found that the order of
843 Direct3D transformations that works best is :
845 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
847 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
848 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
850 If anyone has a good explanation of the three different matrices in
851 the SDK online documentation, feel free to point it to me. For example,
852 which matrices transform lights ? In OpenGL only the PROJECTION matrix
853 transform the lights, not the MODELVIEW. Using the matrix names, I
854 supposed that PROJECTION and VIEW (all 'camera' related names) do
855 transform lights, but WORLD do not. It may be wrong though... */
857 /* After reading through both OpenGL and Direct3D documentations, I
858 thought that D3D matrices were written in 'line major mode' transposed
859 from OpenGL's 'column major mode'. But I found out that a simple memcpy
860 works fine to transfer one matrix format to the other (it did not work
861 when transposing)....
863 So :
864 1) are the documentations wrong
865 2) does the matrix work even if they are not read correctly
866 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
867 loading using glLoadMatrix ?
869 Anyway, I always use 'conv_mat' to transfer the matrices from one format
870 to the other so that if I ever find out that I need to transpose them, I
871 will able to do it quickly, only by changing the macro conv_mat. */
873 switch (d3dts) {
874 case D3DTRANSFORMSTATE_WORLD: {
875 conv_mat(lpmatrix, odev->world_mat);
876 glMatrixMode(GL_MODELVIEW);
877 glLoadMatrixf((float *) &(odev->world_mat));
878 } break;
880 case D3DTRANSFORMSTATE_VIEW: {
881 conv_mat(lpmatrix, odev->view_mat);
882 glMatrixMode(GL_PROJECTION);
883 glLoadMatrixf((float *) &(odev->proj_mat));
884 glMultMatrixf((float *) &(odev->view_mat));
885 } break;
887 case D3DTRANSFORMSTATE_PROJECTION: {
888 conv_mat(lpmatrix, odev->proj_mat);
889 glMatrixMode(GL_PROJECTION);
890 glLoadMatrixf((float *) &(odev->proj_mat));
891 glMultMatrixf((float *) &(odev->view_mat));
892 } break;
894 default:
895 break;
898 LEAVE_GL();
900 return DD_OK;
905 static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
906 D3DTRANSFORMSTATETYPE d3dts,
907 LPD3DMATRIX lpmatrix)
909 ICOM_THIS(IDirect3DDevice2Impl,iface);
910 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
912 return DD_OK;
917 static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
918 D3DTRANSFORMSTATETYPE d3dts,
919 LPD3DMATRIX lpmatrix)
921 ICOM_THIS(IDirect3DDevice2Impl,iface);
922 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
924 return DD_OK;
927 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
928 /* Puts GL in the correct lighting mode */ \
929 if (odev->vt != d3dv) { \
930 if (odev->vt == D3DVT_TLVERTEX) { \
931 /* Need to put the correct transformation again */ \
932 glMatrixMode(GL_MODELVIEW); \
933 glLoadMatrixf((float *) &(odev->world_mat)); \
934 glMatrixMode(GL_PROJECTION); \
935 glLoadMatrixf((float *) &(odev->proj_mat)); \
936 glMultMatrixf((float *) &(odev->view_mat)); \
939 switch (d3dv) { \
940 case D3DVT_VERTEX: \
941 TRACE("Standard Vertex\n"); \
942 glEnable(GL_LIGHTING); \
943 break; \
945 case D3DVT_LVERTEX: \
946 TRACE("Lighted Vertex\n"); \
947 glDisable(GL_LIGHTING); \
948 break; \
950 case D3DVT_TLVERTEX: { \
951 GLdouble height, width, minZ, maxZ; \
953 TRACE("Transformed - Lighted Vertex\n"); \
954 /* First, disable lighting */ \
955 glDisable(GL_LIGHTING); \
957 /* Then do not put any transformation matrixes */ \
958 glMatrixMode(GL_MODELVIEW); \
959 glLoadIdentity(); \
960 glMatrixMode(GL_PROJECTION); \
961 glLoadIdentity(); \
963 if (This->current_viewport == NULL) { \
964 ERR("No current viewport !\n"); \
965 /* Using standard values */ \
966 height = 640.0; \
967 width = 480.0; \
968 minZ = -10.0; \
969 maxZ = 10.0; \
970 } else { \
971 if (This->current_viewport->use_vp2) { \
972 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight; \
973 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth; \
974 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ; \
975 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ; \
976 } else { \
977 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight; \
978 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth; \
979 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ; \
980 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ; \
984 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
985 } break; \
987 default: \
988 ERR("Unhandled vertex type\n"); \
989 break; \
992 odev->vt = d3dv; \
995 switch (d3dp) { \
996 case D3DPT_POINTLIST: \
997 TRACE("Start POINTS\n"); \
998 glBegin(GL_POINTS); \
999 break; \
1001 case D3DPT_LINELIST: \
1002 TRACE("Start LINES\n"); \
1003 glBegin(GL_LINES); \
1004 break; \
1006 case D3DPT_LINESTRIP: \
1007 TRACE("Start LINE_STRIP\n"); \
1008 glBegin(GL_LINE_STRIP); \
1009 break; \
1011 case D3DPT_TRIANGLELIST: \
1012 TRACE("Start TRIANGLES\n"); \
1013 glBegin(GL_TRIANGLES); \
1014 break; \
1016 case D3DPT_TRIANGLESTRIP: \
1017 TRACE("Start TRIANGLE_STRIP\n"); \
1018 glBegin(GL_TRIANGLE_STRIP); \
1019 break; \
1021 case D3DPT_TRIANGLEFAN: \
1022 TRACE("Start TRIANGLE_FAN\n"); \
1023 glBegin(GL_TRIANGLE_FAN); \
1024 break; \
1026 default: \
1027 TRACE("Unhandled primitive\n"); \
1028 break; \
1031 /* Draw the primitives */ \
1032 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
1033 switch (d3dv) { \
1034 case D3DVT_VERTEX: { \
1035 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
1037 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
1038 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
1039 TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
1040 } break; \
1042 case D3DVT_LVERTEX: { \
1043 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
1044 DWORD col = vx->c.color; \
1046 glColor3f(((col >> 16) & 0xFF) / 255.0, \
1047 ((col >> 8) & 0xFF) / 255.0, \
1048 ((col >> 0) & 0xFF) / 255.0); \
1049 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
1050 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
1051 vx->x.x, vx->y.y, vx->z.z, \
1052 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
1053 } break; \
1055 case D3DVT_TLVERTEX: { \
1056 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
1057 DWORD col = vx->c.color; \
1059 glColor3f(((col >> 16) & 0xFF) / 255.0, \
1060 ((col >> 8) & 0xFF) / 255.0, \
1061 ((col >> 0) & 0xFF) / 255.0); \
1062 glTexCoord2f(vx->u.tu, vx->v.tv); \
1063 if (vx->r.rhw < 0.01) \
1064 glVertex3f(vx->x.sx, \
1065 vx->y.sy, \
1066 vx->z.sz); \
1067 else \
1068 glVertex4f(vx->x.sx / vx->r.rhw, \
1069 vx->y.sy / vx->r.rhw, \
1070 vx->z.sz / vx->r.rhw, \
1071 1.0 / vx->r.rhw); \
1072 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
1073 vx->x.sx, vx->y.sy, vx->z.sz, \
1074 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
1075 vx->u.tu, vx->v.tv, vx->r.rhw); \
1076 } break; \
1078 default: \
1079 TRACE("Unhandled vertex type\n"); \
1080 break; \
1084 glEnd(); \
1085 TRACE("End\n");
1088 static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1089 D3DPRIMITIVETYPE d3dp,
1090 D3DVERTEXTYPE d3dv,
1091 LPVOID lpvertex,
1092 DWORD vertcount,
1093 DWORD dwFlags)
1095 ICOM_THIS(IDirect3DDevice2Impl,iface);
1096 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1097 int vx_index;
1099 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
1101 ENTER_GL();
1102 DRAW_PRIMITIVE(vertcount, vx_index);
1103 LEAVE_GL();
1105 return D3D_OK;
1110 static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1111 D3DPRIMITIVETYPE d3dp,
1112 D3DVERTEXTYPE d3dv,
1113 LPVOID lpvertex,
1114 DWORD vertcount,
1115 LPWORD lpindexes,
1116 DWORD indexcount,
1117 DWORD dwFlags)
1119 ICOM_THIS(IDirect3DDevice2Impl,iface);
1120 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1121 int vx_index;
1123 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1125 ENTER_GL();
1126 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1127 LEAVE_GL();
1129 return D3D_OK;
1134 static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
1135 LPD3DCLIPSTATUS lpcs)
1137 ICOM_THIS(IDirect3DDevice2Impl,iface);
1138 FIXME("(%p)->(%p): stub\n", This, lpcs);
1140 return DD_OK;
1145 static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
1146 LPD3DCLIPSTATUS lpcs)
1148 ICOM_THIS(IDirect3DDevice2Impl,iface);
1149 FIXME("(%p)->(%p): stub\n", This, lpcs);
1151 return DD_OK;
1156 /*******************************************************************************
1157 * OpenGL-specific IDirect3DDevice2
1160 /*******************************************************************************
1161 * OpenGL-specific VTable
1164 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
1166 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1167 IDirect3DDevice2Impl_QueryInterface,
1168 IDirect3DDevice2Impl_AddRef,
1169 IDirect3DDevice2Impl_Release,
1170 /*** IDirect3DDevice2 methods ***/
1171 IDirect3DDevice2Impl_GetCaps,
1172 IDirect3DDevice2Impl_SwapTextureHandles,
1173 IDirect3DDevice2Impl_GetStats,
1174 IDirect3DDevice2Impl_AddViewport,
1175 IDirect3DDevice2Impl_DeleteViewport,
1176 IDirect3DDevice2Impl_NextViewport,
1177 IDirect3DDevice2Impl_EnumTextureFormats,
1178 IDirect3DDevice2Impl_BeginScene,
1179 IDirect3DDevice2Impl_EndScene,
1180 IDirect3DDevice2Impl_GetDirect3D,
1182 /*** DrawPrimitive API ***/
1183 IDirect3DDevice2Impl_SetCurrentViewport,
1184 IDirect3DDevice2Impl_GetCurrentViewport,
1186 IDirect3DDevice2Impl_SetRenderTarget,
1187 IDirect3DDevice2Impl_GetRenderTarget,
1189 IDirect3DDevice2Impl_Begin,
1190 IDirect3DDevice2Impl_BeginIndexed,
1191 IDirect3DDevice2Impl_Vertex,
1192 IDirect3DDevice2Impl_Index,
1193 IDirect3DDevice2Impl_End,
1195 IDirect3DDevice2Impl_GetRenderState,
1196 IDirect3DDevice2Impl_SetRenderState,
1197 IDirect3DDevice2Impl_GetLightState,
1198 IDirect3DDevice2Impl_SetLightState,
1199 IDirect3DDevice2Impl_SetTransform,
1200 IDirect3DDevice2Impl_GetTransform,
1201 IDirect3DDevice2Impl_MultiplyTransform,
1203 IDirect3DDevice2Impl_DrawPrimitive,
1204 IDirect3DDevice2Impl_DrawIndexedPrimitive,
1206 IDirect3DDevice2Impl_SetClipStatus,
1207 IDirect3DDevice2Impl_GetClipStatus,
1210 /*******************************************************************************
1211 * Direct3DDevice
1213 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1214 D3DDEVICEDESC d1,d2;
1216 TRACE(" Enumerating OpenGL D3D device.\n");
1218 fill_opengl_caps(&d1, &d2);
1220 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1223 float id_mat[16] = {
1224 1.0, 0.0, 0.0, 0.0,
1225 0.0, 1.0, 0.0, 0.0,
1226 0.0, 0.0, 1.0, 0.0,
1227 0.0, 0.0, 0.0, 1.0
1230 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1232 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1233 OpenGL_IDirect3DDevice *odev;
1234 #ifndef USE_OSMESA
1235 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
1236 XVisualInfo *xvis;
1237 #endif
1239 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1240 odev = (OpenGL_IDirect3DDevice *) (*device);
1241 (*device)->ref = 1;
1242 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
1243 (*device)->d3d = NULL;
1244 (*device)->surface = surface;
1246 (*device)->viewport_list = NULL;
1247 (*device)->current_viewport = NULL;
1249 (*device)->set_context = set_context_dx3;
1251 TRACE("OpenGL device created \n");
1253 /* Create the OpenGL context */
1254 #ifdef USE_OSMESA
1255 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1256 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1257 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1258 #else
1259 /* First get the correct visual */
1260 /* if (surface->s.backbuffer == NULL)
1261 attributeList[3] = None; */
1262 ENTER_GL();
1263 xvis = glXChooseVisual(display,
1264 DefaultScreen(display),
1265 attributeList);
1266 if (xvis == NULL)
1267 ERR("No visual found !\n");
1268 else
1269 TRACE("Visual found\n");
1270 /* Create the context */
1271 odev->ctx = glXCreateContext(display,
1272 xvis,
1273 NULL,
1274 GL_TRUE);
1275 TRACE("Context created\n");
1277 /* Now override the surface's Flip method (if in double buffering) */
1278 surface->s.d3d_device = (void *) odev;
1280 int i;
1281 struct _surface_chain *chain = surface->s.chain;
1282 for (i=0;i<chain->nrofsurfaces;i++)
1283 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
1284 chain->surfaces[i]->s.d3d_device = (void *) odev;
1286 #endif
1287 odev->rs.src = GL_ONE;
1288 odev->rs.dst = GL_ZERO;
1289 odev->rs.mag = GL_NEAREST;
1290 odev->rs.min = GL_NEAREST;
1292 odev->world_mat = (LPD3DMATRIX) &id_mat;
1293 odev->view_mat = (LPD3DMATRIX) &id_mat;
1294 odev->proj_mat = (LPD3DMATRIX) &id_mat;
1296 /* Initialisation */
1297 (*device)->set_context(*device);
1298 glClearColor(0.0, 0.0, 0.0, 0.0);
1299 glColor3f(1.0, 1.0, 1.0);
1301 return 1;
1304 /* This is not the OpenGL UID */
1305 return DD_OK;
1309 /*******************************************************************************
1310 * Direct3DDevice
1312 static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
1313 REFIID riid,
1314 LPVOID* ppvObj)
1316 ICOM_THIS(IDirect3DDeviceImpl,iface);
1318 FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
1320 return S_OK;
1325 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1327 ICOM_THIS(IDirect3DDeviceImpl,iface);
1328 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
1330 return ++(This->ref);
1335 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1337 ICOM_THIS(IDirect3DDeviceImpl,iface);
1338 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
1340 if (!--(This->ref)) {
1341 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1343 #ifdef USE_OSMESA
1344 OSMesaDestroyContext(odev->ctx);
1345 #else
1346 ENTER_GL();
1347 glXDestroyContext(display,
1348 odev->ctx);
1349 LEAVE_GL();
1350 #endif
1352 HeapFree(GetProcessHeap(),0,This);
1353 return 0;
1356 return This->ref;
1359 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1360 LPDIRECT3D lpd3d,
1361 LPGUID lpGUID,
1362 LPD3DDEVICEDESC lpd3ddvdesc)
1364 ICOM_THIS(IDirect3DDeviceImpl,iface);
1365 TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1367 return DDERR_ALREADYINITIALIZED;
1371 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1372 LPD3DDEVICEDESC lpD3DHWDevDesc,
1373 LPD3DDEVICEDESC lpD3DSWDevDesc)
1375 ICOM_THIS(IDirect3DDeviceImpl,iface);
1376 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1378 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1380 return DD_OK;
1384 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1385 LPDIRECT3DTEXTURE lpD3DTex1,
1386 LPDIRECT3DTEXTURE lpD3DTex2)
1388 ICOM_THIS(IDirect3DDeviceImpl,iface);
1389 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1391 return DD_OK;
1394 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1395 LPD3DEXECUTEBUFFERDESC lpDesc,
1396 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1397 IUnknown *pUnkOuter)
1399 ICOM_THIS(IDirect3DDeviceImpl,iface);
1400 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1402 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1404 return DD_OK;
1408 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1409 LPD3DSTATS lpD3DStats)
1411 ICOM_THIS(IDirect3DDeviceImpl,iface);
1412 TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
1414 return DD_OK;
1418 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1419 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1420 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1421 DWORD dwFlags)
1423 ICOM_THIS(IDirect3DDeviceImpl,iface);
1424 TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1426 /* Put this as the default context */
1428 /* Execute... */
1429 ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1431 return DD_OK;
1434 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1435 LPDIRECT3DVIEWPORT lpvp)
1437 ICOM_THIS(IDirect3DDeviceImpl,iface);
1438 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1439 FIXME("(%p)->(%p): stub\n", This, ilpvp);
1441 /* Adds this viewport to the viewport list */
1442 ilpvp->next = This->viewport_list;
1443 This->viewport_list = ilpvp;
1445 return DD_OK;
1450 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1451 LPDIRECT3DVIEWPORT lpvp)
1453 ICOM_THIS(IDirect3DDeviceImpl,iface);
1454 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1455 IDirect3DViewport2Impl *cur, *prev;
1456 FIXME("(%p)->(%p): stub\n", This, lpvp);
1458 /* Finds this viewport in the list */
1459 prev = NULL;
1460 cur = This->viewport_list;
1461 while ((cur != NULL) && (cur != ilpvp)) {
1462 prev = cur;
1463 cur = cur->next;
1465 if (cur == NULL)
1466 return DDERR_INVALIDOBJECT;
1468 /* And remove it */
1469 if (prev == NULL)
1470 This->viewport_list = cur->next;
1471 else
1472 prev->next = cur->next;
1474 return DD_OK;
1479 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1480 LPDIRECT3DVIEWPORT lpvp,
1481 LPDIRECT3DVIEWPORT* lplpvp,
1482 DWORD dwFlags)
1484 ICOM_THIS(IDirect3DDeviceImpl,iface);
1485 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1486 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1487 FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1489 switch (dwFlags) {
1490 case D3DNEXT_NEXT:
1491 *ilplpvp = ilpvp->next;
1492 break;
1494 case D3DNEXT_HEAD:
1495 *ilplpvp = This->viewport_list;
1496 break;
1498 case D3DNEXT_TAIL:
1499 ilpvp = This->viewport_list;
1500 while (ilpvp->next != NULL)
1501 ilpvp = ilpvp->next;
1503 *ilplpvp = ilpvp;
1504 break;
1506 default:
1507 return DDERR_INVALIDPARAMS;
1510 return DD_OK;
1513 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1514 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1515 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1516 DWORD dwFlags,
1517 LPD3DRECT lpRect)
1519 ICOM_THIS(IDirect3DDeviceImpl,iface);
1520 TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1521 dwFlags, lpRect);
1523 return DD_OK;
1527 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1528 LPDWORD lpCount,
1529 LPD3DPICKRECORD lpD3DPickRec)
1531 ICOM_THIS(IDirect3DDeviceImpl,iface);
1532 TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1534 return DD_OK;
1538 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1539 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1540 LPVOID lpArg)
1542 ICOM_THIS(IDirect3DDeviceImpl,iface);
1543 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1545 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1549 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1550 LPD3DMATRIXHANDLE lpD3DMatHandle)
1552 ICOM_THIS(IDirect3DDeviceImpl,iface);
1553 TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
1555 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1557 return DD_OK;
1561 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1562 D3DMATRIXHANDLE d3dMatHandle,
1563 const LPD3DMATRIX lpD3DMatrix)
1565 ICOM_THIS(IDirect3DDeviceImpl,iface);
1566 TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1568 dump_mat(lpD3DMatrix);
1570 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1572 return DD_OK;
1576 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1577 D3DMATRIXHANDLE D3DMatHandle,
1578 LPD3DMATRIX lpD3DMatrix)
1580 ICOM_THIS(IDirect3DDeviceImpl,iface);
1581 TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1583 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1585 return DD_OK;
1589 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1590 D3DMATRIXHANDLE d3dMatHandle)
1592 ICOM_THIS(IDirect3DDeviceImpl,iface);
1593 TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
1595 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1597 return DD_OK;
1601 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1603 ICOM_THIS(IDirect3DDeviceImpl,iface);
1604 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1606 FIXME("(%p)->(): stub\n", This);
1608 /* We get the pointer to the surface (should be done on flip) */
1609 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1611 return DD_OK;
1615 /* This is for the moment copy-pasted from IDirect3DDevice2...
1616 Will make a common function ... */
1617 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1619 ICOM_THIS(IDirect3DDeviceImpl,iface);
1620 #ifdef USE_OSMESA
1621 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1622 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1623 DDSURFACEDESC sdesc;
1624 int x,y;
1625 unsigned char *src;
1626 unsigned short *dest;
1627 #endif
1629 FIXME("(%p)->(): stub\n", This);
1631 #ifdef USE_OSMESA
1632 /* Here we copy back the OpenGL scene to the the DDraw surface */
1633 /* First, lock the surface */
1634 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1636 /* The copy the OpenGL buffer to this surface */
1638 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1639 I am currently working on a set of patches for Mesa to have OSMesa support
1640 16 bpp surfaces => we will able to render directly onto the surface, no
1641 need to do a bpp conversion */
1642 dest = (unsigned short *) sdesc.y.lpSurface;
1643 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1644 for (y = 0; y < sdesc.dwHeight; y++) {
1645 unsigned char *lsrc = src;
1647 for (x = 0; x < sdesc.dwWidth ; x++) {
1648 unsigned char r = *lsrc++;
1649 unsigned char g = *lsrc++;
1650 unsigned char b = *lsrc++;
1651 lsrc++; /* Alpha */
1653 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1655 dest++;
1658 src -= 4 * sdesc.dwWidth;
1661 /* Unlock the surface */
1662 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1663 #else
1664 /* No need to do anything here... */
1665 #endif
1667 return DD_OK;
1671 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1672 LPDIRECT3D *lpDirect3D)
1674 ICOM_THIS(IDirect3DDeviceImpl,iface);
1675 TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
1677 return DD_OK;
1682 /*******************************************************************************
1683 * Direct3DDevice VTable
1685 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1687 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1688 IDirect3DDeviceImpl_QueryInterface,
1689 IDirect3DDeviceImpl_AddRef,
1690 IDirect3DDeviceImpl_Release,
1691 IDirect3DDeviceImpl_Initialize,
1692 IDirect3DDeviceImpl_GetCaps,
1693 IDirect3DDeviceImpl_SwapTextureHandles,
1694 IDirect3DDeviceImpl_CreateExecuteBuffer,
1695 IDirect3DDeviceImpl_GetStats,
1696 IDirect3DDeviceImpl_Execute,
1697 IDirect3DDeviceImpl_AddViewport,
1698 IDirect3DDeviceImpl_DeleteViewport,
1699 IDirect3DDeviceImpl_NextViewport,
1700 IDirect3DDeviceImpl_Pick,
1701 IDirect3DDeviceImpl_GetPickRecords,
1702 IDirect3DDeviceImpl_EnumTextureFormats,
1703 IDirect3DDeviceImpl_CreateMatrix,
1704 IDirect3DDeviceImpl_SetMatrix,
1705 IDirect3DDeviceImpl_GetMatrix,
1706 IDirect3DDeviceImpl_DeleteMatrix,
1707 IDirect3DDeviceImpl_BeginScene,
1708 IDirect3DDeviceImpl_EndScene,
1709 IDirect3DDeviceImpl_GetDirect3D,
1712 #else /* HAVE_MESAGL */
1714 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1715 return 0;
1718 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1720 return 0;
1723 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1724 return 0;
1727 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1729 return 0;
1732 #endif /* HAVE_MESAGL */