Rounds to the lowest integer, not the nearest.
[wine.git] / graphics / d3ddevices.c
blobf01de0f237a78767fd6eddae6035b76157ce1dea
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 #if defined(HAVE_GL_COLOR_TABLE) && defined(HAVE_GL_PALETTED_TEXTURE)
502 TRACE("Enumerating Paletted (8)\n");
503 pformat->dwFlags = DDPF_PALETTEINDEXED8;
504 pformat->u.dwRGBBitCount = 8;
505 pformat->u1.dwRBitMask = 0x00000000;
506 pformat->u2.dwGBitMask = 0x00000000;
507 pformat->u3.dwBBitMask = 0x00000000;
508 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
509 if (cb(&sdesc, context) == 0)
510 return DD_OK;
511 #endif
513 TRACE("End of enumeration\n");
515 return DD_OK;
518 static HRESULT WINAPI IDirect3DDevice2Impl_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
519 LPD3DENUMTEXTUREFORMATSCALLBACK cb,
520 LPVOID context)
522 ICOM_THIS(IDirect3DDevice2Impl,iface);
523 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
525 return enum_texture_format_OpenGL(cb, context);
530 static HRESULT WINAPI IDirect3DDevice2Impl_BeginScene(LPDIRECT3DDEVICE2 iface)
532 ICOM_THIS(IDirect3DDevice2Impl,iface);
533 /* OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This; */
535 FIXME("(%p)->(): stub\n", This);
537 /* Here, we should get the DDraw surface and 'copy it' to the
538 OpenGL surface.... */
540 return DD_OK;
545 static HRESULT WINAPI IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface)
547 ICOM_THIS(IDirect3DDevice2Impl,iface);
548 #ifdef USE_OSMESA
549 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
550 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
551 DDSURFACEDESC sdesc;
552 int x,y;
553 unsigned char *src;
554 unsigned short *dest;
555 #endif
557 FIXME("(%p)->(): stub\n", This);
559 #ifdef USE_OSMESA
560 /* Here we copy back the OpenGL scene to the the DDraw surface */
561 /* First, lock the surface */
562 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
564 /* The copy the OpenGL buffer to this surface */
566 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
567 I am currently working on a set of patches for Mesa to have OSMesa support
568 16 bpp surfaces => we will able to render directly onto the surface, no
569 need to do a bpp conversion */
570 dest = (unsigned short *) sdesc.y.lpSurface;
571 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
572 for (y = 0; y < sdesc.dwHeight; y++) {
573 unsigned char *lsrc = src;
575 for (x = 0; x < sdesc.dwWidth ; x++) {
576 unsigned char r = *lsrc++;
577 unsigned char g = *lsrc++;
578 unsigned char b = *lsrc++;
579 lsrc++; /* Alpha */
580 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
582 dest++;
585 src -= 4 * sdesc.dwWidth;
588 /* Unlock the surface */
589 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
590 #else
591 /* No need to do anything here... */
592 #endif
594 return DD_OK;
599 static HRESULT WINAPI IDirect3DDevice2Impl_GetDirect3D(LPDIRECT3DDEVICE2 iface, LPDIRECT3D2 *lpd3d2)
601 ICOM_THIS(IDirect3DDevice2Impl,iface);
602 TRACE("(%p)->(%p): stub\n", This, lpd3d2);
604 *lpd3d2 = (LPDIRECT3D2)This->d3d;
606 return DD_OK;
611 /*** DrawPrimitive API ***/
612 static HRESULT WINAPI IDirect3DDevice2Impl_SetCurrentViewport(LPDIRECT3DDEVICE2 iface,
613 LPDIRECT3DVIEWPORT2 lpvp)
615 ICOM_THIS(IDirect3DDevice2Impl,iface);
616 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
617 FIXME("(%p)->(%p): stub\n", This, ilpvp);
619 /* Should check if the viewport was added or not */
621 /* Set this viewport as the current viewport */
622 This->current_viewport = ilpvp;
624 /* Activate this viewport */
625 ilpvp->device.active_device2 = This;
626 ilpvp->activate(ilpvp);
628 return DD_OK;
633 static HRESULT WINAPI IDirect3DDevice2Impl_GetCurrentViewport(LPDIRECT3DDEVICE2 iface,
634 LPDIRECT3DVIEWPORT2 *lplpvp)
636 ICOM_THIS(IDirect3DDevice2Impl,iface);
637 FIXME("(%p)->(%p): stub\n", This, lplpvp);
639 /* Returns the current viewport */
640 *lplpvp = (LPDIRECT3DVIEWPORT2)This->current_viewport;
642 return DD_OK;
647 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderTarget(LPDIRECT3DDEVICE2 iface,
648 LPDIRECTDRAWSURFACE lpdds,
649 DWORD dwFlags)
651 ICOM_THIS(IDirect3DDevice2Impl,iface);
652 FIXME("(%p)->(%p,%08lx): stub\n", This, lpdds, dwFlags);
654 return DD_OK;
659 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderTarget(LPDIRECT3DDEVICE2 iface,
660 LPDIRECTDRAWSURFACE *lplpdds)
662 ICOM_THIS(IDirect3DDevice2Impl,iface);
663 FIXME("(%p)->(%p): stub\n", This, lplpdds);
665 /* Returns the current rendering target (the surface on wich we render) */
666 *lplpdds = (LPDIRECTDRAWSURFACE)This->surface;
668 return DD_OK;
673 static HRESULT WINAPI IDirect3DDevice2Impl_Begin(LPDIRECT3DDEVICE2 iface,
674 D3DPRIMITIVETYPE d3dp,
675 D3DVERTEXTYPE d3dv,
676 DWORD dwFlags)
678 ICOM_THIS(IDirect3DDevice2Impl,iface);
679 FIXME("(%p)->(%d,%d,%08lx): stub\n", This, d3dp, d3dv, dwFlags);
681 return DD_OK;
686 static HRESULT WINAPI IDirect3DDevice2Impl_BeginIndexed(LPDIRECT3DDEVICE2 iface,
687 D3DPRIMITIVETYPE d3dp,
688 D3DVERTEXTYPE d3dv,
689 LPVOID lpvert,
690 DWORD numvert,
691 DWORD dwFlags)
693 ICOM_THIS(IDirect3DDevice2Impl,iface);
694 FIXME("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvert, numvert, dwFlags);
696 return DD_OK;
701 static HRESULT WINAPI IDirect3DDevice2Impl_Vertex(LPDIRECT3DDEVICE2 iface,
702 LPVOID lpvert)
704 ICOM_THIS(IDirect3DDevice2Impl,iface);
705 FIXME("(%p)->(%p): stub\n", This, lpvert);
707 return DD_OK;
712 static HRESULT WINAPI IDirect3DDevice2Impl_Index(LPDIRECT3DDEVICE2 iface,
713 WORD index)
715 ICOM_THIS(IDirect3DDevice2Impl,iface);
716 FIXME("(%p)->(%d): stub\n", This, index);
718 return DD_OK;
723 static HRESULT WINAPI IDirect3DDevice2Impl_End(LPDIRECT3DDEVICE2 iface,
724 DWORD dwFlags)
726 ICOM_THIS(IDirect3DDevice2Impl,iface);
727 FIXME("(%p)->(%08lx): stub\n", This, dwFlags);
729 return DD_OK;
735 static HRESULT WINAPI IDirect3DDevice2Impl_GetRenderState(LPDIRECT3DDEVICE2 iface,
736 D3DRENDERSTATETYPE d3drs,
737 LPDWORD lprstate)
739 ICOM_THIS(IDirect3DDevice2Impl,iface);
740 FIXME("(%p)->(%d,%p): stub\n", This, d3drs, lprstate);
742 return DD_OK;
747 static HRESULT WINAPI IDirect3DDevice2Impl_SetRenderState(LPDIRECT3DDEVICE2 iface,
748 D3DRENDERSTATETYPE dwRenderStateType,
749 DWORD dwRenderState)
751 ICOM_THIS(IDirect3DDevice2Impl,iface);
752 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
754 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
756 /* Call the render state functions */
757 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
759 return DD_OK;
764 static HRESULT WINAPI IDirect3DDevice2Impl_GetLightState(LPDIRECT3DDEVICE2 iface,
765 D3DLIGHTSTATETYPE d3dls,
766 LPDWORD lplstate)
768 ICOM_THIS(IDirect3DDevice2Impl,iface);
769 FIXME("(%p)->(%d,%p): stub\n", This, d3dls, lplstate);
771 return DD_OK;
776 static HRESULT WINAPI IDirect3DDevice2Impl_SetLightState(LPDIRECT3DDEVICE2 iface,
777 D3DLIGHTSTATETYPE dwLightStateType,
778 DWORD dwLightState)
780 ICOM_THIS(IDirect3DDevice2Impl,iface);
781 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
783 switch (dwLightStateType) {
784 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
785 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
787 if (mat != NULL) {
788 ENTER_GL();
789 mat->activate(mat);
790 LEAVE_GL();
791 } else {
792 TRACE("Zoups !!!\n");
794 } break;
796 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
797 float light[4];
799 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
800 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
801 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
802 light[3] = 1.0;
803 ENTER_GL();
804 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
805 LEAVE_GL();
806 } break;
808 case D3DLIGHTSTATE_COLORMODEL: /* 3 */
809 break;
811 case D3DLIGHTSTATE_FOGMODE: /* 4 */
812 break;
814 case D3DLIGHTSTATE_FOGSTART: /* 5 */
815 break;
817 case D3DLIGHTSTATE_FOGEND: /* 6 */
818 break;
820 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
821 break;
823 default:
824 TRACE("Unexpected Light State Type\n");
825 return DDERR_INVALIDPARAMS;
828 return DD_OK;
833 static HRESULT WINAPI IDirect3DDevice2Impl_SetTransform(LPDIRECT3DDEVICE2 iface,
834 D3DTRANSFORMSTATETYPE d3dts,
835 LPD3DMATRIX lpmatrix)
837 ICOM_THIS(IDirect3DDevice2Impl,iface);
838 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
840 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
842 ENTER_GL();
844 /* Using a trial and failure approach, I found that the order of
845 Direct3D transformations that works best is :
847 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
849 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
850 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
852 If anyone has a good explanation of the three different matrices in
853 the SDK online documentation, feel free to point it to me. For example,
854 which matrices transform lights ? In OpenGL only the PROJECTION matrix
855 transform the lights, not the MODELVIEW. Using the matrix names, I
856 supposed that PROJECTION and VIEW (all 'camera' related names) do
857 transform lights, but WORLD do not. It may be wrong though... */
859 /* After reading through both OpenGL and Direct3D documentations, I
860 thought that D3D matrices were written in 'line major mode' transposed
861 from OpenGL's 'column major mode'. But I found out that a simple memcpy
862 works fine to transfer one matrix format to the other (it did not work
863 when transposing)....
865 So :
866 1) are the documentations wrong
867 2) does the matrix work even if they are not read correctly
868 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
869 loading using glLoadMatrix ?
871 Anyway, I always use 'conv_mat' to transfer the matrices from one format
872 to the other so that if I ever find out that I need to transpose them, I
873 will able to do it quickly, only by changing the macro conv_mat. */
875 switch (d3dts) {
876 case D3DTRANSFORMSTATE_WORLD: {
877 conv_mat(lpmatrix, odev->world_mat);
878 glMatrixMode(GL_MODELVIEW);
879 glLoadMatrixf((float *) &(odev->world_mat));
880 } break;
882 case D3DTRANSFORMSTATE_VIEW: {
883 conv_mat(lpmatrix, odev->view_mat);
884 glMatrixMode(GL_PROJECTION);
885 glLoadMatrixf((float *) &(odev->proj_mat));
886 glMultMatrixf((float *) &(odev->view_mat));
887 } break;
889 case D3DTRANSFORMSTATE_PROJECTION: {
890 conv_mat(lpmatrix, odev->proj_mat);
891 glMatrixMode(GL_PROJECTION);
892 glLoadMatrixf((float *) &(odev->proj_mat));
893 glMultMatrixf((float *) &(odev->view_mat));
894 } break;
896 default:
897 break;
900 LEAVE_GL();
902 return DD_OK;
907 static HRESULT WINAPI IDirect3DDevice2Impl_GetTransform(LPDIRECT3DDEVICE2 iface,
908 D3DTRANSFORMSTATETYPE d3dts,
909 LPD3DMATRIX lpmatrix)
911 ICOM_THIS(IDirect3DDevice2Impl,iface);
912 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
914 return DD_OK;
919 static HRESULT WINAPI IDirect3DDevice2Impl_MultiplyTransform(LPDIRECT3DDEVICE2 iface,
920 D3DTRANSFORMSTATETYPE d3dts,
921 LPD3DMATRIX lpmatrix)
923 ICOM_THIS(IDirect3DDevice2Impl,iface);
924 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
926 return DD_OK;
929 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
930 /* Puts GL in the correct lighting mode */ \
931 if (odev->vt != d3dv) { \
932 if (odev->vt == D3DVT_TLVERTEX) { \
933 /* Need to put the correct transformation again */ \
934 glMatrixMode(GL_MODELVIEW); \
935 glLoadMatrixf((float *) &(odev->world_mat)); \
936 glMatrixMode(GL_PROJECTION); \
937 glLoadMatrixf((float *) &(odev->proj_mat)); \
938 glMultMatrixf((float *) &(odev->view_mat)); \
941 switch (d3dv) { \
942 case D3DVT_VERTEX: \
943 TRACE("Standard Vertex\n"); \
944 glEnable(GL_LIGHTING); \
945 break; \
947 case D3DVT_LVERTEX: \
948 TRACE("Lighted Vertex\n"); \
949 glDisable(GL_LIGHTING); \
950 break; \
952 case D3DVT_TLVERTEX: { \
953 GLdouble height, width, minZ, maxZ; \
955 TRACE("Transformed - Lighted Vertex\n"); \
956 /* First, disable lighting */ \
957 glDisable(GL_LIGHTING); \
959 /* Then do not put any transformation matrixes */ \
960 glMatrixMode(GL_MODELVIEW); \
961 glLoadIdentity(); \
962 glMatrixMode(GL_PROJECTION); \
963 glLoadIdentity(); \
965 if (This->current_viewport == NULL) { \
966 ERR("No current viewport !\n"); \
967 /* Using standard values */ \
968 height = 640.0; \
969 width = 480.0; \
970 minZ = -10.0; \
971 maxZ = 10.0; \
972 } else { \
973 if (This->current_viewport->use_vp2) { \
974 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight; \
975 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth; \
976 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ; \
977 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ; \
978 } else { \
979 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight; \
980 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth; \
981 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ; \
982 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ; \
986 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
987 } break; \
989 default: \
990 ERR("Unhandled vertex type\n"); \
991 break; \
994 odev->vt = d3dv; \
997 switch (d3dp) { \
998 case D3DPT_POINTLIST: \
999 TRACE("Start POINTS\n"); \
1000 glBegin(GL_POINTS); \
1001 break; \
1003 case D3DPT_LINELIST: \
1004 TRACE("Start LINES\n"); \
1005 glBegin(GL_LINES); \
1006 break; \
1008 case D3DPT_LINESTRIP: \
1009 TRACE("Start LINE_STRIP\n"); \
1010 glBegin(GL_LINE_STRIP); \
1011 break; \
1013 case D3DPT_TRIANGLELIST: \
1014 TRACE("Start TRIANGLES\n"); \
1015 glBegin(GL_TRIANGLES); \
1016 break; \
1018 case D3DPT_TRIANGLESTRIP: \
1019 TRACE("Start TRIANGLE_STRIP\n"); \
1020 glBegin(GL_TRIANGLE_STRIP); \
1021 break; \
1023 case D3DPT_TRIANGLEFAN: \
1024 TRACE("Start TRIANGLE_FAN\n"); \
1025 glBegin(GL_TRIANGLE_FAN); \
1026 break; \
1028 default: \
1029 TRACE("Unhandled primitive\n"); \
1030 break; \
1033 /* Draw the primitives */ \
1034 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
1035 switch (d3dv) { \
1036 case D3DVT_VERTEX: { \
1037 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
1039 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
1040 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
1041 TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
1042 } break; \
1044 case D3DVT_LVERTEX: { \
1045 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
1046 DWORD col = vx->c.color; \
1048 glColor3f(((col >> 16) & 0xFF) / 255.0, \
1049 ((col >> 8) & 0xFF) / 255.0, \
1050 ((col >> 0) & 0xFF) / 255.0); \
1051 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
1052 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
1053 vx->x.x, vx->y.y, vx->z.z, \
1054 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF)); \
1055 } break; \
1057 case D3DVT_TLVERTEX: { \
1058 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
1059 DWORD col = vx->c.color; \
1061 glColor3f(((col >> 16) & 0xFF) / 255.0, \
1062 ((col >> 8) & 0xFF) / 255.0, \
1063 ((col >> 0) & 0xFF) / 255.0); \
1064 glTexCoord2f(vx->u.tu, vx->v.tv); \
1065 if (vx->r.rhw < 0.01) \
1066 glVertex3f(vx->x.sx, \
1067 vx->y.sy, \
1068 vx->z.sz); \
1069 else \
1070 glVertex4f(vx->x.sx / vx->r.rhw, \
1071 vx->y.sy / vx->r.rhw, \
1072 vx->z.sz / vx->r.rhw, \
1073 1.0 / vx->r.rhw); \
1074 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
1075 vx->x.sx, vx->y.sy, vx->z.sz, \
1076 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), \
1077 vx->u.tu, vx->v.tv, vx->r.rhw); \
1078 } break; \
1080 default: \
1081 TRACE("Unhandled vertex type\n"); \
1082 break; \
1086 glEnd(); \
1087 TRACE("End\n");
1090 static HRESULT WINAPI IDirect3DDevice2Impl_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1091 D3DPRIMITIVETYPE d3dp,
1092 D3DVERTEXTYPE d3dv,
1093 LPVOID lpvertex,
1094 DWORD vertcount,
1095 DWORD dwFlags)
1097 ICOM_THIS(IDirect3DDevice2Impl,iface);
1098 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1099 int vx_index;
1101 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
1103 ENTER_GL();
1104 DRAW_PRIMITIVE(vertcount, vx_index);
1105 LEAVE_GL();
1107 return D3D_OK;
1112 static HRESULT WINAPI IDirect3DDevice2Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1113 D3DPRIMITIVETYPE d3dp,
1114 D3DVERTEXTYPE d3dv,
1115 LPVOID lpvertex,
1116 DWORD vertcount,
1117 LPWORD lpindexes,
1118 DWORD indexcount,
1119 DWORD dwFlags)
1121 ICOM_THIS(IDirect3DDevice2Impl,iface);
1122 OpenGL_IDirect3DDevice2 *odev = (OpenGL_IDirect3DDevice2 *) This;
1123 int vx_index;
1125 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
1127 ENTER_GL();
1128 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
1129 LEAVE_GL();
1131 return D3D_OK;
1136 static HRESULT WINAPI IDirect3DDevice2Impl_SetClipStatus(LPDIRECT3DDEVICE2 iface,
1137 LPD3DCLIPSTATUS lpcs)
1139 ICOM_THIS(IDirect3DDevice2Impl,iface);
1140 FIXME("(%p)->(%p): stub\n", This, lpcs);
1142 return DD_OK;
1147 static HRESULT WINAPI IDirect3DDevice2Impl_GetClipStatus(LPDIRECT3DDEVICE2 iface,
1148 LPD3DCLIPSTATUS lpcs)
1150 ICOM_THIS(IDirect3DDevice2Impl,iface);
1151 FIXME("(%p)->(%p): stub\n", This, lpcs);
1153 return DD_OK;
1158 /*******************************************************************************
1159 * OpenGL-specific IDirect3DDevice2
1162 /*******************************************************************************
1163 * OpenGL-specific VTable
1166 static ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
1168 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1169 IDirect3DDevice2Impl_QueryInterface,
1170 IDirect3DDevice2Impl_AddRef,
1171 IDirect3DDevice2Impl_Release,
1172 /*** IDirect3DDevice2 methods ***/
1173 IDirect3DDevice2Impl_GetCaps,
1174 IDirect3DDevice2Impl_SwapTextureHandles,
1175 IDirect3DDevice2Impl_GetStats,
1176 IDirect3DDevice2Impl_AddViewport,
1177 IDirect3DDevice2Impl_DeleteViewport,
1178 IDirect3DDevice2Impl_NextViewport,
1179 IDirect3DDevice2Impl_EnumTextureFormats,
1180 IDirect3DDevice2Impl_BeginScene,
1181 IDirect3DDevice2Impl_EndScene,
1182 IDirect3DDevice2Impl_GetDirect3D,
1184 /*** DrawPrimitive API ***/
1185 IDirect3DDevice2Impl_SetCurrentViewport,
1186 IDirect3DDevice2Impl_GetCurrentViewport,
1188 IDirect3DDevice2Impl_SetRenderTarget,
1189 IDirect3DDevice2Impl_GetRenderTarget,
1191 IDirect3DDevice2Impl_Begin,
1192 IDirect3DDevice2Impl_BeginIndexed,
1193 IDirect3DDevice2Impl_Vertex,
1194 IDirect3DDevice2Impl_Index,
1195 IDirect3DDevice2Impl_End,
1197 IDirect3DDevice2Impl_GetRenderState,
1198 IDirect3DDevice2Impl_SetRenderState,
1199 IDirect3DDevice2Impl_GetLightState,
1200 IDirect3DDevice2Impl_SetLightState,
1201 IDirect3DDevice2Impl_SetTransform,
1202 IDirect3DDevice2Impl_GetTransform,
1203 IDirect3DDevice2Impl_MultiplyTransform,
1205 IDirect3DDevice2Impl_DrawPrimitive,
1206 IDirect3DDevice2Impl_DrawIndexedPrimitive,
1208 IDirect3DDevice2Impl_SetClipStatus,
1209 IDirect3DDevice2Impl_GetClipStatus,
1212 /*******************************************************************************
1213 * Direct3DDevice
1215 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1216 D3DDEVICEDESC d1,d2;
1218 TRACE(" Enumerating OpenGL D3D device.\n");
1220 fill_opengl_caps(&d1, &d2);
1222 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
1225 float id_mat[16] = {
1226 1.0, 0.0, 0.0, 0.0,
1227 0.0, 1.0, 0.0, 0.0,
1228 0.0, 0.0, 1.0, 0.0,
1229 0.0, 0.0, 0.0, 1.0
1232 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1234 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
1235 OpenGL_IDirect3DDevice *odev;
1236 #ifndef USE_OSMESA
1237 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
1238 XVisualInfo *xvis;
1239 #endif
1241 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OpenGL_IDirect3DDevice));
1242 odev = (OpenGL_IDirect3DDevice *) (*device);
1243 (*device)->ref = 1;
1244 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
1245 (*device)->d3d = NULL;
1246 (*device)->surface = surface;
1248 (*device)->viewport_list = NULL;
1249 (*device)->current_viewport = NULL;
1251 (*device)->set_context = set_context_dx3;
1253 TRACE("OpenGL device created \n");
1255 /* Create the OpenGL context */
1256 #ifdef USE_OSMESA
1257 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
1258 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1259 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
1260 #else
1261 /* First get the correct visual */
1262 /* if (surface->s.backbuffer == NULL)
1263 attributeList[3] = None; */
1264 ENTER_GL();
1265 xvis = glXChooseVisual(display,
1266 DefaultScreen(display),
1267 attributeList);
1268 if (xvis == NULL)
1269 ERR("No visual found !\n");
1270 else
1271 TRACE("Visual found\n");
1272 /* Create the context */
1273 odev->ctx = glXCreateContext(display,
1274 xvis,
1275 NULL,
1276 GL_TRUE);
1277 TRACE("Context created\n");
1279 /* Now override the surface's Flip method (if in double buffering) */
1280 surface->s.d3d_device = (void *) odev;
1282 int i;
1283 struct _surface_chain *chain = surface->s.chain;
1284 for (i=0;i<chain->nrofsurfaces;i++)
1285 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
1286 chain->surfaces[i]->s.d3d_device = (void *) odev;
1288 #endif
1289 odev->rs.src = GL_ONE;
1290 odev->rs.dst = GL_ZERO;
1291 odev->rs.mag = GL_NEAREST;
1292 odev->rs.min = GL_NEAREST;
1294 odev->world_mat = (LPD3DMATRIX) &id_mat;
1295 odev->view_mat = (LPD3DMATRIX) &id_mat;
1296 odev->proj_mat = (LPD3DMATRIX) &id_mat;
1298 /* Initialisation */
1299 (*device)->set_context(*device);
1300 glClearColor(0.0, 0.0, 0.0, 0.0);
1301 glColor3f(1.0, 1.0, 1.0);
1303 return 1;
1306 /* This is not the OpenGL UID */
1307 return DD_OK;
1311 /*******************************************************************************
1312 * Direct3DDevice
1314 static HRESULT WINAPI IDirect3DDeviceImpl_QueryInterface(LPDIRECT3DDEVICE iface,
1315 REFIID riid,
1316 LPVOID* ppvObj)
1318 ICOM_THIS(IDirect3DDeviceImpl,iface);
1319 char xrefiid[50];
1321 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
1322 FIXME("(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
1324 return S_OK;
1329 static ULONG WINAPI IDirect3DDeviceImpl_AddRef(LPDIRECT3DDEVICE iface)
1331 ICOM_THIS(IDirect3DDeviceImpl,iface);
1332 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
1334 return ++(This->ref);
1339 static ULONG WINAPI IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
1341 ICOM_THIS(IDirect3DDeviceImpl,iface);
1342 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
1344 if (!--(This->ref)) {
1345 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1347 #ifdef USE_OSMESA
1348 OSMesaDestroyContext(odev->ctx);
1349 #else
1350 ENTER_GL();
1351 glXDestroyContext(display,
1352 odev->ctx);
1353 LEAVE_GL();
1354 #endif
1356 HeapFree(GetProcessHeap(),0,This);
1357 return 0;
1360 return This->ref;
1363 static HRESULT WINAPI IDirect3DDeviceImpl_Initialize(LPDIRECT3DDEVICE iface,
1364 LPDIRECT3D lpd3d,
1365 LPGUID lpGUID,
1366 LPD3DDEVICEDESC lpd3ddvdesc)
1368 ICOM_THIS(IDirect3DDeviceImpl,iface);
1369 TRACE("(%p)->(%p,%p,%p): stub\n", This, lpd3d,lpGUID, lpd3ddvdesc);
1371 return DDERR_ALREADYINITIALIZED;
1375 static HRESULT WINAPI IDirect3DDeviceImpl_GetCaps(LPDIRECT3DDEVICE iface,
1376 LPD3DDEVICEDESC lpD3DHWDevDesc,
1377 LPD3DDEVICEDESC lpD3DSWDevDesc)
1379 ICOM_THIS(IDirect3DDeviceImpl,iface);
1380 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DHWDevDesc, lpD3DSWDevDesc);
1382 fill_opengl_caps(lpD3DHWDevDesc, lpD3DSWDevDesc);
1384 return DD_OK;
1388 static HRESULT WINAPI IDirect3DDeviceImpl_SwapTextureHandles(LPDIRECT3DDEVICE iface,
1389 LPDIRECT3DTEXTURE lpD3DTex1,
1390 LPDIRECT3DTEXTURE lpD3DTex2)
1392 ICOM_THIS(IDirect3DDeviceImpl,iface);
1393 TRACE("(%p)->(%p,%p): stub\n", This, lpD3DTex1, lpD3DTex2);
1395 return DD_OK;
1398 static HRESULT WINAPI IDirect3DDeviceImpl_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1399 LPD3DEXECUTEBUFFERDESC lpDesc,
1400 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer,
1401 IUnknown *pUnkOuter)
1403 ICOM_THIS(IDirect3DDeviceImpl,iface);
1404 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1406 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
1408 return DD_OK;
1412 static HRESULT WINAPI IDirect3DDeviceImpl_GetStats(LPDIRECT3DDEVICE iface,
1413 LPD3DSTATS lpD3DStats)
1415 ICOM_THIS(IDirect3DDeviceImpl,iface);
1416 TRACE("(%p)->(%p): stub\n", This, lpD3DStats);
1418 return DD_OK;
1422 static HRESULT WINAPI IDirect3DDeviceImpl_Execute(LPDIRECT3DDEVICE iface,
1423 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1424 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1425 DWORD dwFlags)
1427 ICOM_THIS(IDirect3DDeviceImpl,iface);
1428 TRACE("(%p)->(%p,%p,%08ld): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport, dwFlags);
1430 /* Put this as the default context */
1432 /* Execute... */
1433 ((IDirect3DExecuteBufferImpl*)lpDirect3DExecuteBuffer)->execute(lpDirect3DExecuteBuffer, iface, lpDirect3DViewport);
1435 return DD_OK;
1438 static HRESULT WINAPI IDirect3DDeviceImpl_AddViewport(LPDIRECT3DDEVICE iface,
1439 LPDIRECT3DVIEWPORT lpvp)
1441 ICOM_THIS(IDirect3DDeviceImpl,iface);
1442 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1443 FIXME("(%p)->(%p): stub\n", This, ilpvp);
1445 /* Adds this viewport to the viewport list */
1446 ilpvp->next = This->viewport_list;
1447 This->viewport_list = ilpvp;
1449 return DD_OK;
1454 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteViewport(LPDIRECT3DDEVICE iface,
1455 LPDIRECT3DVIEWPORT lpvp)
1457 ICOM_THIS(IDirect3DDeviceImpl,iface);
1458 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1459 IDirect3DViewport2Impl *cur, *prev;
1460 FIXME("(%p)->(%p): stub\n", This, lpvp);
1462 /* Finds this viewport in the list */
1463 prev = NULL;
1464 cur = This->viewport_list;
1465 while ((cur != NULL) && (cur != ilpvp)) {
1466 prev = cur;
1467 cur = cur->next;
1469 if (cur == NULL)
1470 return DDERR_INVALIDOBJECT;
1472 /* And remove it */
1473 if (prev == NULL)
1474 This->viewport_list = cur->next;
1475 else
1476 prev->next = cur->next;
1478 return DD_OK;
1483 static HRESULT WINAPI IDirect3DDeviceImpl_NextViewport(LPDIRECT3DDEVICE iface,
1484 LPDIRECT3DVIEWPORT lpvp,
1485 LPDIRECT3DVIEWPORT* lplpvp,
1486 DWORD dwFlags)
1488 ICOM_THIS(IDirect3DDeviceImpl,iface);
1489 IDirect3DViewport2Impl* ilpvp=(IDirect3DViewport2Impl*)lpvp;
1490 IDirect3DViewport2Impl** ilplpvp=(IDirect3DViewport2Impl**)lplpvp;
1491 FIXME("(%p)->(%p,%p,%08lx): stub\n", This, ilpvp, ilplpvp, dwFlags);
1493 switch (dwFlags) {
1494 case D3DNEXT_NEXT:
1495 *ilplpvp = ilpvp->next;
1496 break;
1498 case D3DNEXT_HEAD:
1499 *ilplpvp = This->viewport_list;
1500 break;
1502 case D3DNEXT_TAIL:
1503 ilpvp = This->viewport_list;
1504 while (ilpvp->next != NULL)
1505 ilpvp = ilpvp->next;
1507 *ilplpvp = ilpvp;
1508 break;
1510 default:
1511 return DDERR_INVALIDPARAMS;
1514 return DD_OK;
1517 static HRESULT WINAPI IDirect3DDeviceImpl_Pick(LPDIRECT3DDEVICE iface,
1518 LPDIRECT3DEXECUTEBUFFER lpDirect3DExecuteBuffer,
1519 LPDIRECT3DVIEWPORT lpDirect3DViewport,
1520 DWORD dwFlags,
1521 LPD3DRECT lpRect)
1523 ICOM_THIS(IDirect3DDeviceImpl,iface);
1524 TRACE("(%p)->(%p,%p,%08lx,%p): stub\n", This, lpDirect3DExecuteBuffer, lpDirect3DViewport,
1525 dwFlags, lpRect);
1527 return DD_OK;
1531 static HRESULT WINAPI IDirect3DDeviceImpl_GetPickRecords(LPDIRECT3DDEVICE iface,
1532 LPDWORD lpCount,
1533 LPD3DPICKRECORD lpD3DPickRec)
1535 ICOM_THIS(IDirect3DDeviceImpl,iface);
1536 TRACE("(%p)->(%p,%p): stub\n", This, lpCount, lpD3DPickRec);
1538 return DD_OK;
1542 static HRESULT WINAPI IDirect3DDeviceImpl_EnumTextureFormats(LPDIRECT3DDEVICE iface,
1543 LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
1544 LPVOID lpArg)
1546 ICOM_THIS(IDirect3DDeviceImpl,iface);
1547 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
1549 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1553 static HRESULT WINAPI IDirect3DDeviceImpl_CreateMatrix(LPDIRECT3DDEVICE iface,
1554 LPD3DMATRIXHANDLE lpD3DMatHandle)
1556 ICOM_THIS(IDirect3DDeviceImpl,iface);
1557 TRACE("(%p)->(%p)\n", This, lpD3DMatHandle);
1559 *lpD3DMatHandle = (D3DMATRIXHANDLE) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(D3DMATRIX));
1561 return DD_OK;
1565 static HRESULT WINAPI IDirect3DDeviceImpl_SetMatrix(LPDIRECT3DDEVICE iface,
1566 D3DMATRIXHANDLE d3dMatHandle,
1567 const LPD3DMATRIX lpD3DMatrix)
1569 ICOM_THIS(IDirect3DDeviceImpl,iface);
1570 TRACE("(%p)->(%08lx,%p)\n", This, d3dMatHandle, lpD3DMatrix);
1572 dump_mat(lpD3DMatrix);
1574 *((D3DMATRIX *) d3dMatHandle) = *lpD3DMatrix;
1576 return DD_OK;
1580 static HRESULT WINAPI IDirect3DDeviceImpl_GetMatrix(LPDIRECT3DDEVICE iface,
1581 D3DMATRIXHANDLE D3DMatHandle,
1582 LPD3DMATRIX lpD3DMatrix)
1584 ICOM_THIS(IDirect3DDeviceImpl,iface);
1585 TRACE("(%p)->(%08lx,%p)\n", This, D3DMatHandle, lpD3DMatrix);
1587 *lpD3DMatrix = *((D3DMATRIX *) D3DMatHandle);
1589 return DD_OK;
1593 static HRESULT WINAPI IDirect3DDeviceImpl_DeleteMatrix(LPDIRECT3DDEVICE iface,
1594 D3DMATRIXHANDLE d3dMatHandle)
1596 ICOM_THIS(IDirect3DDeviceImpl,iface);
1597 TRACE("(%p)->(%08lx)\n", This, d3dMatHandle);
1599 HeapFree(GetProcessHeap(),0, (void *) d3dMatHandle);
1601 return DD_OK;
1605 static HRESULT WINAPI IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1607 ICOM_THIS(IDirect3DDeviceImpl,iface);
1608 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1610 FIXME("(%p)->(): stub\n", This);
1612 /* We get the pointer to the surface (should be done on flip) */
1613 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
1615 return DD_OK;
1619 /* This is for the moment copy-pasted from IDirect3DDevice2...
1620 Will make a common function ... */
1621 static HRESULT WINAPI IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1623 ICOM_THIS(IDirect3DDeviceImpl,iface);
1624 #ifdef USE_OSMESA
1625 OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This;
1626 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1627 DDSURFACEDESC sdesc;
1628 int x,y;
1629 unsigned char *src;
1630 unsigned short *dest;
1631 #endif
1633 FIXME("(%p)->(): stub\n", This);
1635 #ifdef USE_OSMESA
1636 /* Here we copy back the OpenGL scene to the the DDraw surface */
1637 /* First, lock the surface */
1638 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1640 /* The copy the OpenGL buffer to this surface */
1642 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1643 I am currently working on a set of patches for Mesa to have OSMesa support
1644 16 bpp surfaces => we will able to render directly onto the surface, no
1645 need to do a bpp conversion */
1646 dest = (unsigned short *) sdesc.y.lpSurface;
1647 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1648 for (y = 0; y < sdesc.dwHeight; y++) {
1649 unsigned char *lsrc = src;
1651 for (x = 0; x < sdesc.dwWidth ; x++) {
1652 unsigned char r = *lsrc++;
1653 unsigned char g = *lsrc++;
1654 unsigned char b = *lsrc++;
1655 lsrc++; /* Alpha */
1657 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1659 dest++;
1662 src -= 4 * sdesc.dwWidth;
1665 /* Unlock the surface */
1666 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1667 #else
1668 /* No need to do anything here... */
1669 #endif
1671 return DD_OK;
1675 static HRESULT WINAPI IDirect3DDeviceImpl_GetDirect3D(LPDIRECT3DDEVICE iface,
1676 LPDIRECT3D *lpDirect3D)
1678 ICOM_THIS(IDirect3DDeviceImpl,iface);
1679 TRACE("(%p)->(%p): stub\n", This, lpDirect3D);
1681 return DD_OK;
1686 /*******************************************************************************
1687 * Direct3DDevice VTable
1689 static ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1691 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1692 IDirect3DDeviceImpl_QueryInterface,
1693 IDirect3DDeviceImpl_AddRef,
1694 IDirect3DDeviceImpl_Release,
1695 IDirect3DDeviceImpl_Initialize,
1696 IDirect3DDeviceImpl_GetCaps,
1697 IDirect3DDeviceImpl_SwapTextureHandles,
1698 IDirect3DDeviceImpl_CreateExecuteBuffer,
1699 IDirect3DDeviceImpl_GetStats,
1700 IDirect3DDeviceImpl_Execute,
1701 IDirect3DDeviceImpl_AddViewport,
1702 IDirect3DDeviceImpl_DeleteViewport,
1703 IDirect3DDeviceImpl_NextViewport,
1704 IDirect3DDeviceImpl_Pick,
1705 IDirect3DDeviceImpl_GetPickRecords,
1706 IDirect3DDeviceImpl_EnumTextureFormats,
1707 IDirect3DDeviceImpl_CreateMatrix,
1708 IDirect3DDeviceImpl_SetMatrix,
1709 IDirect3DDeviceImpl_GetMatrix,
1710 IDirect3DDeviceImpl_DeleteMatrix,
1711 IDirect3DDeviceImpl_BeginScene,
1712 IDirect3DDeviceImpl_EndScene,
1713 IDirect3DDeviceImpl_GetDirect3D,
1716 #else /* HAVE_MESAGL */
1718 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1719 return 0;
1722 int is_OpenGL(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d)
1724 return 0;
1727 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
1728 return 0;
1731 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
1733 return 0;
1736 #endif /* HAVE_MESAGL */