Show use of undocumented messages.
[wine/dcerpc.git] / graphics / d3ddevices.c
blob4dde9e8b17e11ad0efcf9649e749a6654c2d9757
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);
262 char xrefiid[50];
264 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
265 FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
267 return S_OK;
272 static ULONG WINAPI IDirect3DDevice2Impl_AddRef(LPDIRECT3DDEVICE2 iface)
274 ICOM_THIS(IDirect3DDevice2Impl,iface);
275 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
277 return ++(This->ref);
282 static ULONG WINAPI IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
284 ICOM_THIS(IDirect3DDevice2Impl,iface);
285 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
287 if (!--(This->ref)) {
288 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
290 #ifdef USE_OSMESA
291 OSMesaDestroyContext(odev->ctx);
292 #else
293 ENTER_GL();
294 glXDestroyContext(display,
295 odev->ctx);
296 LEAVE_GL();
297 #endif
299 HeapFree(GetProcessHeap(),0,This);
300 return 0;
303 return This->ref;
307 /*** IDirect3DDevice2 methods ***/
308 static HRESULT WINAPI IDirect3DDevice2Impl_GetCaps(LPDIRECT3DDEVICE2 iface,
309 LPD3DDEVICEDESC lpdescsoft,
310 LPD3DDEVICEDESC lpdeschard)
312 ICOM_THIS(IDirect3DDevice2Impl,iface);
313 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
315 fill_opengl_caps(lpdescsoft, lpdeschard);
317 return DD_OK;
322 static HRESULT WINAPI IDirect3DDevice2Impl_SwapTextureHandles(LPDIRECT3DDEVICE2 iface,
323 LPDIRECT3DTEXTURE2 lptex1,
324 LPDIRECT3DTEXTURE2 lptex2)
326 ICOM_THIS(IDirect3DDevice2Impl,iface);
327 FIXME("(%p)->(%p,%p): stub\n", This, lptex1, lptex2);
329 return DD_OK;
334 static HRESULT WINAPI IDirect3DDevice2Impl_GetStats(LPDIRECT3DDEVICE2 iface,
335 LPD3DSTATS lpstats)
337 ICOM_THIS(IDirect3DDevice2Impl,iface);
338 FIXME("(%p)->(%p): stub\n", This, lpstats);
340 return DD_OK;
345 static HRESULT WINAPI IDirect3DDevice2Impl_AddViewport(LPDIRECT3DDEVICE2 iface,
346 LPDIRECT3DVIEWPORT2 lpvp)
348 ICOM_THIS(IDirect3DDevice2Impl,iface);
349 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
350 FIXME("(%p)->(%p): stub\n", This, ilpvp);
352 /* Adds this viewport to the viewport list */
353 ilpvp->next = This->viewport_list;
354 This->viewport_list = ilpvp;
356 return DD_OK;
361 static HRESULT WINAPI IDirect3DDevice2Impl_DeleteViewport(LPDIRECT3DDEVICE2 iface,
362 LPDIRECT3DVIEWPORT2 lpvp)
364 ICOM_THIS(IDirect3DDevice2Impl,iface);
365 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
366 IDirect3DViewport2Impl *cur, *prev;
367 FIXME("(%p)->(%p): stub\n", This, lpvp);
369 /* Finds this viewport in the list */
370 prev = NULL;
371 cur = This->viewport_list;
372 while ((cur != NULL) && (cur != ilpvp)) {
373 prev = cur;
374 cur = cur->next;
376 if (cur == NULL)
377 return DDERR_INVALIDOBJECT;
379 /* And remove it */
380 if (prev == NULL)
381 This->viewport_list = cur->next;
382 else
383 prev->next = cur->next;
385 return DD_OK;
390 static HRESULT WINAPI IDirect3DDevice2Impl_NextViewport(LPDIRECT3DDEVICE2 iface,
391 LPDIRECT3DVIEWPORT2 lpvp,
392 LPDIRECT3DVIEWPORT2* lplpvp,
393 DWORD dwFlags)
395 ICOM_THIS(IDirect3DDevice2Impl,iface);
396 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
397 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
398 FIXME("(%p)->(%p,%p,%08lx): stub\n", This, lpvp, lpvp, dwFlags);
400 switch (dwFlags) {
401 case D3DNEXT_NEXT:
402 *ilplpvp = ilpvp->next;
403 break;
405 case D3DNEXT_HEAD:
406 *ilplpvp = This->viewport_list;
407 break;
409 case D3DNEXT_TAIL:
410 ilpvp = This->viewport_list;
411 while (ilpvp->next != NULL)
412 ilpvp = ilpvp->next;
414 *ilplpvp = ilpvp;
415 break;
417 default:
418 return DDERR_INVALIDPARAMS;
421 return DD_OK;
424 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
425 LPVOID context) {
426 DDSURFACEDESC sdesc;
427 LPDDPIXELFORMAT pformat;
429 /* Do the texture enumeration */
430 sdesc.dwSize = sizeof(DDSURFACEDESC);
431 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
432 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
433 pformat = &(sdesc.ddpfPixelFormat);
434 pformat->dwSize = sizeof(DDPIXELFORMAT);
435 pformat->dwFourCC = 0;
437 TRACE("Enumerating GL_RGBA unpacked (32)\n");
438 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
439 pformat->u.dwRGBBitCount = 32;
440 pformat->u1.dwRBitMask = 0xFF000000;
441 pformat->u2.dwGBitMask = 0x00FF0000;
442 pformat->u3.dwBBitMask = 0x0000FF00;
443 pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
444 if (cb(&sdesc, context) == 0)
445 return DD_OK;
447 TRACE("Enumerating GL_RGB unpacked (24)\n");
448 pformat->dwFlags = DDPF_RGB;
449 pformat->u.dwRGBBitCount = 24;
450 pformat->u1.dwRBitMask = 0x00FF0000;
451 pformat->u2.dwGBitMask = 0x0000FF00;
452 pformat->u3.dwBBitMask = 0x000000FF;
453 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
454 if (cb(&sdesc, context) == 0)
455 return DD_OK;
457 #ifndef HAVE_BUGGY_MESAGL
458 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
459 so that future version will work great. */
460 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
461 pformat->dwFlags = DDPF_RGB;
462 pformat->u.dwRGBBitCount = 16;
463 pformat->u1.dwRBitMask = 0x0000F800;
464 pformat->u2.dwGBitMask = 0x000007E0;
465 pformat->u3.dwBBitMask = 0x0000001F;
466 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
467 if (cb(&sdesc, context) == 0)
468 return DD_OK;
470 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
471 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
472 pformat->u.dwRGBBitCount = 16;
473 pformat->u1.dwRBitMask = 0x0000F800;
474 pformat->u2.dwGBitMask = 0x000007C0;
475 pformat->u3.dwBBitMask = 0x0000003E;
476 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
477 if (cb(&sdesc, context) == 0)
478 return DD_OK;
480 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
481 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
482 pformat->u.dwRGBBitCount = 16;
483 pformat->u1.dwRBitMask = 0x0000F000;
484 pformat->u2.dwGBitMask = 0x00000F00;
485 pformat->u3.dwBBitMask = 0x000000F0;
486 pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
487 if (cb(&sdesc, context) == 0)
488 return DD_OK;
490 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
491 pformat->dwFlags = DDPF_RGB;
492 pformat->u.dwRGBBitCount = 8;
493 pformat->u1.dwRBitMask = 0x0000F800;
494 pformat->u2.dwGBitMask = 0x000007C0;
495 pformat->u3.dwBBitMask = 0x0000003E;
496 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
497 if (cb(&sdesc, context) == 0)
498 return DD_OK;
499 #endif
501 TRACE("Enumerating Paletted (8)\n");
502 pformat->dwFlags = DDPF_PALETTEINDEXED8;
503 pformat->u.dwRGBBitCount = 8;
504 pformat->u1.dwRBitMask = 0x00000000;
505 pformat->u2.dwGBitMask = 0x00000000;
506 pformat->u3.dwBBitMask = 0x00000000;
507 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
508 if (cb(&sdesc, context) == 0)
509 return DD_OK;
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);
1317 char xrefiid[50];
1319 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1320 FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
1322 return S_OK;
1327 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1329 ICOM_THIS(IDirect3DDeviceImpl,iface);
1330 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
1332 return ++(This->ref);
1337 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1339 ICOM_THIS(IDirect3DDeviceImpl,iface);
1340 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
1342 if (!--(This->ref)) {
1343 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1345 #ifdef USE_OSMESA
1346 OSMesaDestroyContext(odev->ctx);
1347 #else
1348 ENTER_GL();
1349 glXDestroyContext(display,
1350 odev->ctx);
1351 LEAVE_GL();
1352 #endif
1354 HeapFree(GetProcessHeap(),0,This);
1355 return 0;
1358 return This->ref;
1361 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1362 LPDIRECT3D lpd3d,
1363 LPGUID lpGUID,
1364 LPD3DDEVICEDESC lpd3ddvdesc)
1366 ICOM_THIS(IDirect3DDeviceImpl,iface);
1367 TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1369 return DDERR_ALREADYINITIALIZED;
1373 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1374 LPD3DDEVICEDESC lpD3DHWDevDesc,
1375 LPD3DDEVICEDESC lpD3DSWDevDesc)
1377 ICOM_THIS(IDirect3DDeviceImpl,iface);
1378 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1380 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1382 return DD_OK;
1386 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1387 LPDIRECT3DTEXTURE lpD3DTex1,
1388 LPDIRECT3DTEXTURE lpD3DTex2)
1390 ICOM_THIS(IDirect3DDeviceImpl,iface);
1391 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1393 return DD_OK;
1396 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1397 LPD3DEXECUTEBUFFERDESC lpDesc,
1398 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1399 IUnknown *pUnkOuter)
1401 ICOM_THIS(IDirect3DDeviceImpl,iface);
1402 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1404 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1406 return DD_OK;
1410 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1411 LPD3DSTATS lpD3DStats)
1413 ICOM_THIS(IDirect3DDeviceImpl,iface);
1414 TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
1416 return DD_OK;
1420 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1421 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1422 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1423 DWORD dwFlags)
1425 ICOM_THIS(IDirect3DDeviceImpl,iface);
1426 TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1428 /* Put this as the default context */
1430 /* Execute... */
1431 ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1433 return DD_OK;
1436 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1437 LPDIRECT3DVIEWPORT lpvp)
1439 ICOM_THIS(IDirect3DDeviceImpl,iface);
1440 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1441 FIXME("(%p)->(%p): stub\n", This, ilpvp);
1443 /* Adds this viewport to the viewport list */
1444 ilpvp->next = This->viewport_list;
1445 This->viewport_list = ilpvp;
1447 return DD_OK;
1452 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1453 LPDIRECT3DVIEWPORT lpvp)
1455 ICOM_THIS(IDirect3DDeviceImpl,iface);
1456 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1457 IDirect3DViewport2Impl *cur, *prev;
1458 FIXME("(%p)->(%p): stub\n", This, lpvp);
1460 /* Finds this viewport in the list */
1461 prev = NULL;
1462 cur = This->viewport_list;
1463 while ((cur != NULL) && (cur != ilpvp)) {
1464 prev = cur;
1465 cur = cur->next;
1467 if (cur == NULL)
1468 return DDERR_INVALIDOBJECT;
1470 /* And remove it */
1471 if (prev == NULL)
1472 This->viewport_list = cur->next;
1473 else
1474 prev->next = cur->next;
1476 return DD_OK;
1481 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1482 LPDIRECT3DVIEWPORT lpvp,
1483 LPDIRECT3DVIEWPORT* lplpvp,
1484 DWORD dwFlags)
1486 ICOM_THIS(IDirect3DDeviceImpl,iface);
1487 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1488 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1489 FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1491 switch (dwFlags) {
1492 case D3DNEXT_NEXT:
1493 *ilplpvp = ilpvp->next;
1494 break;
1496 case D3DNEXT_HEAD:
1497 *ilplpvp = This->viewport_list;
1498 break;
1500 case D3DNEXT_TAIL:
1501 ilpvp = This->viewport_list;
1502 while (ilpvp->next != NULL)
1503 ilpvp = ilpvp->next;
1505 *ilplpvp = ilpvp;
1506 break;
1508 default:
1509 return DDERR_INVALIDPARAMS;
1512 return DD_OK;
1515 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1516 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1517 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1518 DWORD dwFlags,
1519 LPD3DRECT lpRect)
1521 ICOM_THIS(IDirect3DDeviceImpl,iface);
1522 TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1523 dwFlags, lpRect);
1525 return DD_OK;
1529 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1530 LPDWORD lpCount,
1531 LPD3DPICKRECORD lpD3DPickRec)
1533 ICOM_THIS(IDirect3DDeviceImpl,iface);
1534 TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1536 return DD_OK;
1540 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1541 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1542 LPVOID lpArg)
1544 ICOM_THIS(IDirect3DDeviceImpl,iface);
1545 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1547 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1551 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1552 LPD3DMATRIXHANDLE lpD3DMatHandle)
1554 ICOM_THIS(IDirect3DDeviceImpl,iface);
1555 TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
1557 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1559 return DD_OK;
1563 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1564 D3DMATRIXHANDLE d3dMatHandle,
1565 const LPD3DMATRIX lpD3DMatrix)
1567 ICOM_THIS(IDirect3DDeviceImpl,iface);
1568 TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1570 dump_mat(lpD3DMatrix);
1572 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1574 return DD_OK;
1578 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1579 D3DMATRIXHANDLE D3DMatHandle,
1580 LPD3DMATRIX lpD3DMatrix)
1582 ICOM_THIS(IDirect3DDeviceImpl,iface);
1583 TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1585 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1587 return DD_OK;
1591 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1592 D3DMATRIXHANDLE d3dMatHandle)
1594 ICOM_THIS(IDirect3DDeviceImpl,iface);
1595 TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
1597 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1599 return DD_OK;
1603 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1605 ICOM_THIS(IDirect3DDeviceImpl,iface);
1606 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1608 FIXME("(%p)->(): stub\n", This);
1610 /* We get the pointer to the surface (should be done on flip) */
1611 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1613 return DD_OK;
1617 /* This is for the moment copy-pasted from IDirect3DDevice2...
1618 Will make a common function ... */
1619 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1621 ICOM_THIS(IDirect3DDeviceImpl,iface);
1622 #ifdef USE_OSMESA
1623 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1624 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1625 DDSURFACEDESC sdesc;
1626 int x,y;
1627 unsigned char *src;
1628 unsigned short *dest;
1629 #endif
1631 FIXME("(%p)->(): stub\n", This);
1633 #ifdef USE_OSMESA
1634 /* Here we copy back the OpenGL scene to the the DDraw surface */
1635 /* First, lock the surface */
1636 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1638 /* The copy the OpenGL buffer to this surface */
1640 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1641 I am currently working on a set of patches for Mesa to have OSMesa support
1642 16 bpp surfaces => we will able to render directly onto the surface, no
1643 need to do a bpp conversion */
1644 dest = (unsigned short *) sdesc.y.lpSurface;
1645 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1646 for (y = 0; y < sdesc.dwHeight; y++) {
1647 unsigned char *lsrc = src;
1649 for (x = 0; x < sdesc.dwWidth ; x++) {
1650 unsigned char r = *lsrc++;
1651 unsigned char g = *lsrc++;
1652 unsigned char b = *lsrc++;
1653 lsrc++; /* Alpha */
1655 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1657 dest++;
1660 src -= 4 * sdesc.dwWidth;
1663 /* Unlock the surface */
1664 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1665 #else
1666 /* No need to do anything here... */
1667 #endif
1669 return DD_OK;
1673 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1674 LPDIRECT3D *lpDirect3D)
1676 ICOM_THIS(IDirect3DDeviceImpl,iface);
1677 TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
1679 return DD_OK;
1684 /*******************************************************************************
1685 * Direct3DDevice VTable
1687 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1689 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1690 IDirect3DDeviceImpl_QueryInterface,
1691 IDirect3DDeviceImpl_AddRef,
1692 IDirect3DDeviceImpl_Release,
1693 IDirect3DDeviceImpl_Initialize,
1694 IDirect3DDeviceImpl_GetCaps,
1695 IDirect3DDeviceImpl_SwapTextureHandles,
1696 IDirect3DDeviceImpl_CreateExecuteBuffer,
1697 IDirect3DDeviceImpl_GetStats,
1698 IDirect3DDeviceImpl_Execute,
1699 IDirect3DDeviceImpl_AddViewport,
1700 IDirect3DDeviceImpl_DeleteViewport,
1701 IDirect3DDeviceImpl_NextViewport,
1702 IDirect3DDeviceImpl_Pick,
1703 IDirect3DDeviceImpl_GetPickRecords,
1704 IDirect3DDeviceImpl_EnumTextureFormats,
1705 IDirect3DDeviceImpl_CreateMatrix,
1706 IDirect3DDeviceImpl_SetMatrix,
1707 IDirect3DDeviceImpl_GetMatrix,
1708 IDirect3DDeviceImpl_DeleteMatrix,
1709 IDirect3DDeviceImpl_BeginScene,
1710 IDirect3DDeviceImpl_EndScene,
1711 IDirect3DDeviceImpl_GetDirect3D,
1714 #else /* HAVE_MESAGL */
1716 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1717 return 0;
1720 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1722 return 0;
1725 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1726 return 0;
1729 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1731 return 0;
1734 #endif /* HAVE_MESAGL */