4 This files contains the MESA implementation of all the D3D devices that
11 #include "wine/obj_base.h"
15 #include "debugtools.h"
17 #include "mesa_private.h"
19 DEFAULT_DEBUG_CHANNEL(ddraw)
21 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
22 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
24 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
25 on Mesa's home page) or version 3.1b.
27 Version 3.1b2 should correct this bug */
28 #undef HAVE_BUGGY_MESAGL
30 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
31 #define DDPRIVATE(x) x11_dd_private *ddpriv=((x11_dd_private*)(x)->private)
33 /*******************************************************************************
34 * OpenGL static functions
36 static void set_context(IDirect3DDevice2Impl* This) {
38 DDPRIVATE(This->surface->s.ddraw);
41 OSMesaMakeCurrent(d3ddpriv->ctx, odev->buffer, GL_UNSIGNED_BYTE,
42 This->surface->s.surface_desc.dwWidth,
43 This->surface->s.surface_desc.dwHeight);
45 if (glXMakeCurrent(display,ddpriv->drawable, odev->ctx) == False) {
46 ERR("Error in setting current context (context %p drawable %ld)!\n",
47 odev->ctx, ddpriv->drawable);
52 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
54 pc->dwSize = sizeof(*pc);
55 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
56 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
57 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
58 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
59 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
60 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
61 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
62 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
63 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
64 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
65 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
66 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
67 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
68 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
69 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
70 pc->dwStippleWidth = 32;
71 pc->dwStippleHeight = 32;
74 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
78 d1->dwSize = sizeof(*d1);
79 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
80 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
81 d1->dcmColorModel = D3DCOLOR_RGB;
82 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
83 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
84 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
85 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
86 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
88 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
89 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
90 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
91 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
92 fill_opengl_primcaps(&(d1->dpcLineCaps));
93 fill_opengl_primcaps(&(d1->dpcTriCaps));
94 d1->dwDeviceRenderBitDepth = DDBD_16;
95 d1->dwDeviceZBufferBitDepth = DDBD_16;
96 d1->dwMaxBufferSize = 0;
97 d1->dwMaxVertexCount = 65536;
98 d1->dwMinTextureWidth = 1;
99 d1->dwMinTextureHeight = 1;
100 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
101 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
102 d1->dwMinStippleWidth = 1;
103 d1->dwMinStippleHeight = 1;
104 d1->dwMaxStippleWidth = 32;
105 d1->dwMaxStippleHeight = 32;
107 d2->dwSize = sizeof(*d2);
111 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
113 TRACE(" Enumerating OpenGL D3D device.\n");
114 fill_opengl_caps(&d1, &d2);
115 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
120 REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
121 IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
123 mesa_d3dd_private *odev = NULL;
125 if (/* Default device */
128 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
130 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
132 const float id_mat[16] = {
139 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
143 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
144 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
145 odev = (mesa_d3dd_private*)(*device)->private;
147 ICOM_VTBL(*device) = &OpenGL_vtable;
148 (*device)->d3d = d3d;
149 (*device)->surface = surface;
150 (*device)->viewport_list = NULL;
151 (*device)->current_viewport = NULL;
152 (*device)->set_context = set_context;
154 TRACE("Creating OpenGL device for surface %p\n", surface);
155 /* Create the OpenGL context */
157 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
158 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
159 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
161 /* First get the correct visual */
162 /* if (surface->s.backbuffer == NULL)
163 attributeList[3] = None; */
165 xvis = glXChooseVisual(display,
166 DefaultScreen(display),
169 ERR("No visual found !\n");
171 TRACE("Visual found\n");
172 /* Create the context */
173 odev->ctx = glXCreateContext(display,
177 if (odev->ctx == NULL)
178 ERR("Error in context creation !\n");
180 TRACE("Context created (%p)\n", odev->ctx);
182 #if 0 /* not functional currently */
183 /* Now override the surface's Flip method (if in double buffering) */
184 surface->s.d3d_device = (void *) odev;
188 struct _surface_chain *chain = surface->s.chain;
189 for (i=0;i<chain->nrofsurfaces;i++)
190 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
191 chain->surfaces[i]->s.d3d_device = (void *) odev;
196 odev->rs.src = GL_ONE;
197 odev->rs.dst = GL_ZERO;
198 odev->rs.mag = GL_NEAREST;
199 odev->rs.min = GL_NEAREST;
202 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
203 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
204 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
207 TRACE("Setting current context\n");
208 (*device)->set_context(*device);
209 TRACE("Current context set\n");
210 glClearColor(0.0, 0.0, 0.0, 0.0);
211 glColor3f(1.0, 1.0, 1.0);
213 TRACE("OpenGL device created \n");
216 FIXME("bad IID %s\n",debugstr_guid(rguid));
217 /* This is not the OpenGL UID */
221 /*******************************************************************************
222 * MESA IDirect3DDevice2
224 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
226 ICOM_THIS(IDirect3DDevice2Impl,iface);
228 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
230 if (!--(This->ref)) {
232 OSMesaDestroyContext(odev->ctx);
235 glXDestroyContext(display, odev->ctx);
238 This->private = NULL;
239 HeapFree(GetProcessHeap(),0,This);
245 /*** IDirect3DDevice2 methods ***/
246 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
247 LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
248 LPD3DDEVICEDESC lpdeschard
250 ICOM_THIS(IDirect3DDevice2Impl,iface);
251 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
252 fill_opengl_caps(lpdescsoft, lpdeschard);
256 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
259 LPDDPIXELFORMAT pformat;
261 /* Do the texture enumeration */
262 sdesc.dwSize = sizeof(DDSURFACEDESC);
263 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
264 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
265 pformat = &(sdesc.ddpfPixelFormat);
266 pformat->dwSize = sizeof(DDPIXELFORMAT);
267 pformat->dwFourCC = 0;
269 TRACE("Enumerating GL_RGBA unpacked (32)\n");
270 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
271 pformat->u.dwRGBBitCount = 32;
272 pformat->u1.dwRBitMask = 0xFF000000;
273 pformat->u2.dwGBitMask = 0x00FF0000;
274 pformat->u3.dwBBitMask = 0x0000FF00;
275 pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
276 if (cb(&sdesc, context) == 0)
279 TRACE("Enumerating GL_RGB unpacked (24)\n");
280 pformat->dwFlags = DDPF_RGB;
281 pformat->u.dwRGBBitCount = 24;
282 pformat->u1.dwRBitMask = 0x00FF0000;
283 pformat->u2.dwGBitMask = 0x0000FF00;
284 pformat->u3.dwBBitMask = 0x000000FF;
285 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
286 if (cb(&sdesc, context) == 0)
289 #ifndef HAVE_BUGGY_MESAGL
290 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
291 so that future version will work great. */
292 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
293 pformat->dwFlags = DDPF_RGB;
294 pformat->u.dwRGBBitCount = 16;
295 pformat->u1.dwRBitMask = 0x0000F800;
296 pformat->u2.dwGBitMask = 0x000007E0;
297 pformat->u3.dwBBitMask = 0x0000001F;
298 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
299 if (cb(&sdesc, context) == 0)
302 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
303 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
304 pformat->u.dwRGBBitCount = 16;
305 pformat->u1.dwRBitMask = 0x0000F800;
306 pformat->u2.dwGBitMask = 0x000007C0;
307 pformat->u3.dwBBitMask = 0x0000003E;
308 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
309 if (cb(&sdesc, context) == 0)
312 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
313 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
314 pformat->u.dwRGBBitCount = 16;
315 pformat->u1.dwRBitMask = 0x0000F000;
316 pformat->u2.dwGBitMask = 0x00000F00;
317 pformat->u3.dwBBitMask = 0x000000F0;
318 pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
319 if (cb(&sdesc, context) == 0)
322 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
323 pformat->dwFlags = DDPF_RGB;
324 pformat->u.dwRGBBitCount = 8;
325 pformat->u1.dwRBitMask = 0x0000F800;
326 pformat->u2.dwGBitMask = 0x000007C0;
327 pformat->u3.dwBBitMask = 0x0000003E;
328 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
329 if (cb(&sdesc, context) == 0)
333 #if defined(HAVE_GL_COLOR_TABLE) && defined(HAVE_GL_PALETTED_TEXTURE)
334 TRACE("Enumerating Paletted (8)\n");
335 pformat->dwFlags = DDPF_PALETTEINDEXED8;
336 pformat->u.dwRGBBitCount = 8;
337 pformat->u1.dwRBitMask = 0x00000000;
338 pformat->u2.dwGBitMask = 0x00000000;
339 pformat->u3.dwBBitMask = 0x00000000;
340 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
341 if (cb(&sdesc, context) == 0)
345 TRACE("End of enumeration\n");
350 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
351 LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
353 ICOM_THIS(IDirect3DDevice2Impl,iface);
354 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
356 return enum_texture_format_OpenGL(cb, context);
359 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
360 LPDIRECT3DDEVICE2 iface
362 ICOM_THIS(IDirect3DDevice2Impl,iface);
364 FIXME("(%p)->(): stub\n", This);
366 /* Here, we should get the DDraw surface and 'copy it' to the
367 OpenGL surface.... */
372 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
373 ICOM_THIS(IDirect3DDevice2Impl,iface);
377 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
381 unsigned short *dest;
384 FIXME("(%p)->(): stub\n", This);
387 /* Here we copy back the OpenGL scene to the the DDraw surface */
388 /* First, lock the surface */
389 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
391 /* The copy the OpenGL buffer to this surface */
393 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
394 I am currently working on a set of patches for Mesa to have OSMesa support
395 16 bpp surfaces => we will able to render directly onto the surface, no
396 need to do a bpp conversion */
397 dest = (unsigned short *) sdesc.y.lpSurface;
398 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
399 for (y = 0; y < sdesc.dwHeight; y++) {
400 unsigned char *lsrc = src;
402 for (x = 0; x < sdesc.dwWidth ; x++) {
403 unsigned char r = *lsrc++;
404 unsigned char g = *lsrc++;
405 unsigned char b = *lsrc++;
407 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
412 src -= 4 * sdesc.dwWidth;
415 /* Unlock the surface */
416 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
418 /* No need to do anything here... */
424 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
425 LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
428 ICOM_THIS(IDirect3DDevice2Impl,iface);
431 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
433 /* Call the render state functions */
434 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
439 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
440 LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
443 ICOM_THIS(IDirect3DDevice2Impl,iface);
444 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
446 switch (dwLightStateType) {
447 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
448 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
455 TRACE("Zoups !!!\n");
459 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
462 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
463 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
464 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
467 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
471 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
479 TRACE("Unexpected Light State Type\n");
480 return DDERR_INVALIDPARAMS;
486 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
487 LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
490 ICOM_THIS(IDirect3DDevice2Impl,iface);
493 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
497 /* Using a trial and failure approach, I found that the order of
498 Direct3D transformations that works best is :
500 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
502 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
503 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
505 If anyone has a good explanation of the three different matrices in
506 the SDK online documentation, feel free to point it to me. For example,
507 which matrices transform lights ? In OpenGL only the PROJECTION matrix
508 transform the lights, not the MODELVIEW. Using the matrix names, I
509 supposed that PROJECTION and VIEW (all 'camera' related names) do
510 transform lights, but WORLD do not. It may be wrong though... */
512 /* After reading through both OpenGL and Direct3D documentations, I
513 thought that D3D matrices were written in 'line major mode' transposed
514 from OpenGL's 'column major mode'. But I found out that a simple memcpy
515 works fine to transfer one matrix format to the other (it did not work
516 when transposing)....
519 1) are the documentations wrong
520 2) does the matrix work even if they are not read correctly
521 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
522 loading using glLoadMatrix ?
524 Anyway, I always use 'conv_mat' to transfer the matrices from one format
525 to the other so that if I ever find out that I need to transpose them, I
526 will able to do it quickly, only by changing the macro conv_mat. */
529 case D3DTRANSFORMSTATE_WORLD: {
530 conv_mat(lpmatrix, odev->world_mat);
531 glMatrixMode(GL_MODELVIEW);
532 glLoadMatrixf((float *) &(odev->world_mat));
535 case D3DTRANSFORMSTATE_VIEW: {
536 conv_mat(lpmatrix, odev->view_mat);
537 glMatrixMode(GL_PROJECTION);
538 glLoadMatrixf((float *) &(odev->proj_mat));
539 glMultMatrixf((float *) &(odev->view_mat));
542 case D3DTRANSFORMSTATE_PROJECTION: {
543 conv_mat(lpmatrix, odev->proj_mat);
544 glMatrixMode(GL_PROJECTION);
545 glLoadMatrixf((float *) &(odev->proj_mat));
546 glMultMatrixf((float *) &(odev->view_mat));
556 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
557 /* Puts GL in the correct lighting mode */ \
558 if (odev->vt != d3dv) { \
559 if (odev->vt == D3DVT_TLVERTEX) { \
560 /* Need to put the correct transformation again */ \
561 glMatrixMode(GL_MODELVIEW); \
562 glLoadMatrixf((float *) &(odev->world_mat)); \
563 glMatrixMode(GL_PROJECTION); \
564 glLoadMatrixf((float *) &(odev->proj_mat)); \
565 glMultMatrixf((float *) &(odev->view_mat)); \
570 TRACE("Standard Vertex\n"); \
571 glEnable(GL_LIGHTING); \
574 case D3DVT_LVERTEX: \
575 TRACE("Lighted Vertex\n"); \
576 glDisable(GL_LIGHTING); \
579 case D3DVT_TLVERTEX: { \
580 GLdouble height, width, minZ, maxZ; \
582 TRACE("Transformed - Lighted Vertex\n"); \
583 /* First, disable lighting */ \
584 glDisable(GL_LIGHTING); \
586 /* Then do not put any transformation matrixes */ \
587 glMatrixMode(GL_MODELVIEW); \
589 glMatrixMode(GL_PROJECTION); \
592 if (This->current_viewport == NULL) { \
593 ERR("No current viewport !\n"); \
594 /* Using standard values */ \
600 if (This->current_viewport->use_vp2) { \
601 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
602 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
603 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
604 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
606 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
607 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
608 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
609 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
613 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
617 ERR("Unhandled vertex type\n"); \
625 case D3DPT_POINTLIST: \
626 TRACE("Start POINTS\n"); \
627 glBegin(GL_POINTS); \
630 case D3DPT_LINELIST: \
631 TRACE("Start LINES\n"); \
635 case D3DPT_LINESTRIP: \
636 TRACE("Start LINE_STRIP\n"); \
637 glBegin(GL_LINE_STRIP); \
640 case D3DPT_TRIANGLELIST: \
641 TRACE("Start TRIANGLES\n"); \
642 glBegin(GL_TRIANGLES); \
645 case D3DPT_TRIANGLESTRIP: \
646 TRACE("Start TRIANGLE_STRIP\n"); \
647 glBegin(GL_TRIANGLE_STRIP); \
650 case D3DPT_TRIANGLEFAN: \
651 TRACE("Start TRIANGLE_FAN\n"); \
652 glBegin(GL_TRIANGLE_FAN); \
656 TRACE("Unhandled primitive\n"); \
660 /* Draw the primitives */ \
661 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
663 case D3DVT_VERTEX: { \
664 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
666 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
667 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
668 TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
671 case D3DVT_LVERTEX: { \
672 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
673 DWORD col = vx->c.color; \
675 glColor3f(((col >> 16) & 0xFF) / 255.0, \
676 ((col >> 8) & 0xFF) / 255.0, \
677 ((col >> 0) & 0xFF) / 255.0); \
678 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
679 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
680 vx->x.x, vx->y.y, vx->z.z, \
681 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
684 case D3DVT_TLVERTEX: { \
685 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
686 DWORD col = vx->c.color; \
688 glColor3f(((col >> 16) & 0xFF) / 255.0, \
689 ((col >> 8) & 0xFF) / 255.0, \
690 ((col >> 0) & 0xFF) / 255.0); \
691 glTexCoord2f(vx->u.tu, vx->v.tv); \
692 if (vx->r.rhw < 0.01) \
693 glVertex3f(vx->x.sx, \
697 glVertex4f(vx->x.sx / vx->r.rhw, \
698 vx->y.sy / vx->r.rhw, \
699 vx->z.sz / vx->r.rhw, \
701 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
702 vx->x.sx, vx->y.sy, vx->z.sz, \
703 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
704 vx->u.tu, vx->v.tv, vx->r.rhw); \
708 FIXME("Unhandled vertex type\n"); \
717 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
718 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
719 LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
721 ICOM_THIS(IDirect3DDevice2Impl,iface);
725 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
728 DRAW_PRIMITIVE(vertcount, vx_index);
734 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
735 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
736 LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
739 ICOM_THIS(IDirect3DDevice2Impl,iface);
743 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
746 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
752 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
753 LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
754 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
756 ICOM_THIS(IDirect3DDeviceImpl,iface);
757 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
758 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
763 /*******************************************************************************
764 * OpenGL-specific IDirect3DDevice2
767 /*******************************************************************************
768 * OpenGL-specific VTable
771 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
773 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
774 IDirect3DDevice2Impl_QueryInterface,
775 IDirect3DDevice2Impl_AddRef,
776 MESA_IDirect3DDevice2Impl_Release,
777 /*** IDirect3DDevice2 methods ***/
778 MESA_IDirect3DDevice2Impl_GetCaps,
779 IDirect3DDevice2Impl_SwapTextureHandles,
780 IDirect3DDevice2Impl_GetStats,
781 IDirect3DDevice2Impl_AddViewport,
782 IDirect3DDevice2Impl_DeleteViewport,
783 IDirect3DDevice2Impl_NextViewport,
784 MESA_IDirect3DDevice2Impl_EnumTextureFormats,
785 MESA_IDirect3DDevice2Impl_BeginScene,
786 MESA_IDirect3DDevice2Impl_EndScene,
787 IDirect3DDevice2Impl_GetDirect3D,
789 /*** DrawPrimitive API ***/
790 IDirect3DDevice2Impl_SetCurrentViewport,
791 IDirect3DDevice2Impl_GetCurrentViewport,
793 IDirect3DDevice2Impl_SetRenderTarget,
794 IDirect3DDevice2Impl_GetRenderTarget,
796 IDirect3DDevice2Impl_Begin,
797 IDirect3DDevice2Impl_BeginIndexed,
798 IDirect3DDevice2Impl_Vertex,
799 IDirect3DDevice2Impl_Index,
800 IDirect3DDevice2Impl_End,
802 IDirect3DDevice2Impl_GetRenderState,
803 MESA_IDirect3DDevice2Impl_SetRenderState,
804 IDirect3DDevice2Impl_GetLightState,
805 MESA_IDirect3DDevice2Impl_SetLightState,
806 MESA_IDirect3DDevice2Impl_SetTransform,
807 IDirect3DDevice2Impl_GetTransform,
808 IDirect3DDevice2Impl_MultiplyTransform,
810 MESA_IDirect3DDevice2Impl_DrawPrimitive,
811 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
813 IDirect3DDevice2Impl_SetClipStatus,
814 IDirect3DDevice2Impl_GetClipStatus,
817 /*******************************************************************************
820 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
823 TRACE(" Enumerating OpenGL D3D device.\n");
825 fill_opengl_caps(&d1, &d2);
827 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
837 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
839 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
840 mesa_d3dd_private *odev;
842 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
846 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
847 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
848 odev = (mesa_d3dd_private*)(*device)->private;
850 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
851 (*device)->d3d = NULL;
852 (*device)->surface = surface;
854 (*device)->viewport_list = NULL;
855 (*device)->current_viewport = NULL;
857 (*device)->set_context = (void*)set_context;
859 TRACE("OpenGL device created \n");
861 /* Create the OpenGL context */
863 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
864 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
865 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
867 /* First get the correct visual */
868 /* if (surface->s.backbuffer == NULL)
869 attributeList[3] = None; */
871 xvis = glXChooseVisual(display,
872 DefaultScreen(display),
875 ERR("No visual found !\n");
877 TRACE("Visual found\n");
878 /* Create the context */
879 odev->ctx = glXCreateContext(display,
883 TRACE("Context created\n");
885 #if 0 /* non working currently */
886 /* Now override the surface's Flip method (if in double buffering) */
887 surface->s.d3d_device = (void *) odev;
890 struct _surface_chain *chain = surface->s.chain;
891 for (i=0;i<chain->nrofsurfaces;i++)
892 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
893 chain->surfaces[i]->s.d3d_device = (void *) odev;
897 odev->rs.src = GL_ONE;
898 odev->rs.dst = GL_ZERO;
899 odev->rs.mag = GL_NEAREST;
900 odev->rs.min = GL_NEAREST;
902 odev->world_mat = (LPD3DMATRIX) &id_mat;
903 odev->view_mat = (LPD3DMATRIX) &id_mat;
904 odev->proj_mat = (LPD3DMATRIX) &id_mat;
907 (*device)->set_context(*device);
908 glClearColor(0.0, 0.0, 0.0, 0.0);
909 glColor3f(1.0, 1.0, 1.0);
914 /* This is not the OpenGL UID */
918 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
920 ICOM_THIS(IDirect3DDeviceImpl,iface);
921 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
923 if (!--(This->ref)) {
926 OSMesaDestroyContext(odev->ctx);
929 glXDestroyContext(display, odev->ctx);
932 This->private = NULL;
933 HeapFree(GetProcessHeap(),0,This);
939 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
940 LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
943 ICOM_THIS(IDirect3DDeviceImpl,iface);
944 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
946 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
950 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
952 ICOM_THIS(IDirect3DDeviceImpl,iface);
953 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
955 FIXME("(%p)->(): stub\n", This);
957 /* We get the pointer to the surface (should be done on flip) */
958 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
964 /* This is for the moment copy-pasted from IDirect3DDevice2...
965 Will make a common function ... */
966 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
968 ICOM_THIS(IDirect3DDeviceImpl,iface);
971 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
975 unsigned short *dest;
978 FIXME("(%p)->(): stub\n", This);
981 /* Here we copy back the OpenGL scene to the the DDraw surface */
982 /* First, lock the surface */
983 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
985 /* The copy the OpenGL buffer to this surface */
987 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
988 I am currently working on a set of patches for Mesa to have OSMesa support
989 16 bpp surfaces => we will able to render directly onto the surface, no
990 need to do a bpp conversion */
991 dest = (unsigned short *) sdesc.y.lpSurface;
992 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
993 for (y = 0; y < sdesc.dwHeight; y++) {
994 unsigned char *lsrc = src;
996 for (x = 0; x < sdesc.dwWidth ; x++) {
997 unsigned char r = *lsrc++;
998 unsigned char g = *lsrc++;
999 unsigned char b = *lsrc++;
1002 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1007 src -= 4 * sdesc.dwWidth;
1010 /* Unlock the surface */
1011 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1013 /* No need to do anything here... */
1019 /*******************************************************************************
1020 * Direct3DDevice VTable
1022 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1024 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1025 IDirect3DDeviceImpl_QueryInterface,
1026 IDirect3DDeviceImpl_AddRef,
1027 MESA_IDirect3DDeviceImpl_Release,
1028 IDirect3DDeviceImpl_Initialize,
1029 IDirect3DDeviceImpl_GetCaps,
1030 IDirect3DDeviceImpl_SwapTextureHandles,
1031 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
1032 IDirect3DDeviceImpl_GetStats,
1033 IDirect3DDeviceImpl_Execute,
1034 IDirect3DDeviceImpl_AddViewport,
1035 IDirect3DDeviceImpl_DeleteViewport,
1036 IDirect3DDeviceImpl_NextViewport,
1037 IDirect3DDeviceImpl_Pick,
1038 IDirect3DDeviceImpl_GetPickRecords,
1039 MESA_IDirect3DDeviceImpl_EnumTextureFormats,
1040 IDirect3DDeviceImpl_CreateMatrix,
1041 IDirect3DDeviceImpl_SetMatrix,
1042 IDirect3DDeviceImpl_GetMatrix,
1043 IDirect3DDeviceImpl_DeleteMatrix,
1044 MESA_IDirect3DDeviceImpl_BeginScene,
1045 MESA_IDirect3DDeviceImpl_EndScene,
1046 IDirect3DDeviceImpl_GetDirect3D,