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)->d->private)
33 #ifndef HAVE_GLEXT_PROTOTYPES
34 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
35 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
36 GLsizei width, GLenum format, GLenum type,
40 static const float id_mat[16] = {
47 /*******************************************************************************
48 * OpenGL static functions
50 static void set_context(IDirect3DDevice2Impl* This) {
52 DDPRIVATE(This->surface->s.ddraw);
55 OSMesaMakeCurrent(d3ddpriv->ctx, odev->buffer, GL_UNSIGNED_BYTE,
56 This->surface->s.surface_desc.dwWidth,
57 This->surface->s.surface_desc.dwHeight);
59 if (glXMakeCurrent(display,ddpriv->drawable, odev->ctx) == False) {
60 ERR("Error in setting current context (context %p drawable %ld)!\n",
61 odev->ctx, ddpriv->drawable);
66 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
68 pc->dwSize = sizeof(*pc);
69 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
70 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
71 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
72 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
73 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
74 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
75 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
76 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
77 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
78 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
79 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
80 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
81 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
82 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
83 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
84 pc->dwStippleWidth = 32;
85 pc->dwStippleHeight = 32;
88 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
92 d1->dwSize = sizeof(*d1);
93 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
94 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
95 d1->dcmColorModel = D3DCOLOR_RGB;
96 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
97 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
98 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
99 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
100 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
101 d1->bClipping = TRUE;
102 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
103 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
104 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
105 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
106 fill_opengl_primcaps(&(d1->dpcLineCaps));
107 fill_opengl_primcaps(&(d1->dpcTriCaps));
108 d1->dwDeviceRenderBitDepth = DDBD_16;
109 d1->dwDeviceZBufferBitDepth = DDBD_16;
110 d1->dwMaxBufferSize = 0;
111 d1->dwMaxVertexCount = 65536;
112 d1->dwMinTextureWidth = 1;
113 d1->dwMinTextureHeight = 1;
114 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
115 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
116 d1->dwMinStippleWidth = 1;
117 d1->dwMinStippleHeight = 1;
118 d1->dwMaxStippleWidth = 32;
119 d1->dwMaxStippleHeight = 32;
121 d2->dwSize = sizeof(*d2);
125 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
126 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
127 const char *ext_string;
128 Mesa_DeviceCapabilities *devcap;
130 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
131 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
134 ext_string = glGetString(GL_EXTENSIONS);
135 /* Query for the ColorTable Extension */
136 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
137 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
138 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
140 TRACE("Color table extension not found.\n");
145 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
147 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL));
148 fill_opengl_caps(&d1, &d2);
149 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context);
154 REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
155 IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
157 mesa_d3dd_private *odev = NULL;
159 if (/* Default device */
162 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
164 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
166 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
167 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
168 odev = (mesa_d3dd_private*)(*device)->private;
170 ICOM_VTBL(*device) = &OpenGL_vtable;
171 (*device)->d3d = d3d;
172 (*device)->surface = surface;
173 (*device)->viewport_list = NULL;
174 (*device)->current_viewport = NULL;
175 (*device)->set_context = set_context;
177 TRACE("Creating OpenGL device for surface %p\n", surface);
178 /* Create the OpenGL context */
180 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
181 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
182 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
184 /* First get the correct visual */
186 /* Create the context */
190 XVisualInfo template;
192 template.visualid = XVisualIDFromVisual(visual);
193 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
195 odev->ctx = glXCreateContext(display, vis,
199 if (odev->ctx == NULL)
200 ERR("Error in context creation !\n");
202 TRACE("Context created (%p)\n", odev->ctx);
204 /* Now override the surface's Flip method (if in double buffering) */
205 ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
208 struct _surface_chain *chain = surface->s.chain;
209 for (i=0;i<chain->nrofsurfaces;i++)
210 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
211 ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
215 odev->rs.src = GL_ONE;
216 odev->rs.dst = GL_ZERO;
217 odev->rs.mag = GL_NEAREST;
218 odev->rs.min = GL_NEAREST;
221 /* Allocate memory for the matrices */
222 odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
223 odev->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
224 odev->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
226 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
227 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
228 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
231 TRACE("Setting current context\n");
232 (*device)->set_context(*device);
233 TRACE("Current context set\n");
234 glClearColor(0.0, 0.0, 0.0, 0.0);
235 glColor3f(1.0, 1.0, 1.0);
238 fill_device_capabilities(d3d->ddraw);
240 TRACE("OpenGL device created \n");
243 FIXME("bad IID %s\n",debugstr_guid(rguid));
244 /* This is not the OpenGL UID */
248 /*******************************************************************************
249 * MESA IDirect3DDevice2
251 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
253 ICOM_THIS(IDirect3DDevice2Impl,iface);
255 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
257 if (!--(This->ref)) {
259 OSMesaDestroyContext(odev->ctx);
262 glXDestroyContext(display, odev->ctx);
265 This->private = NULL;
266 HeapFree(GetProcessHeap(),0,This);
272 /*** IDirect3DDevice2 methods ***/
273 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
274 LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
275 LPD3DDEVICEDESC lpdeschard
277 ICOM_THIS(IDirect3DDevice2Impl,iface);
278 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
279 fill_opengl_caps(lpdescsoft, lpdeschard);
283 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
286 LPDDPIXELFORMAT pformat;
288 /* Do the texture enumeration */
289 sdesc.dwSize = sizeof(DDSURFACEDESC);
290 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
291 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
292 pformat = &(sdesc.ddpfPixelFormat);
293 pformat->dwSize = sizeof(DDPIXELFORMAT);
294 pformat->dwFourCC = 0;
296 TRACE("Enumerating GL_RGBA unpacked (32)\n");
297 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
298 pformat->u.dwRGBBitCount = 32;
299 pformat->u1.dwRBitMask = 0xFF000000;
300 pformat->u2.dwGBitMask = 0x00FF0000;
301 pformat->u3.dwBBitMask = 0x0000FF00;
302 pformat->u4.dwRGBAlphaBitMask = 0x000000FF;
303 if (cb(&sdesc, context) == 0)
306 TRACE("Enumerating GL_RGB unpacked (24)\n");
307 pformat->dwFlags = DDPF_RGB;
308 pformat->u.dwRGBBitCount = 24;
309 pformat->u1.dwRBitMask = 0x00FF0000;
310 pformat->u2.dwGBitMask = 0x0000FF00;
311 pformat->u3.dwBBitMask = 0x000000FF;
312 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
313 if (cb(&sdesc, context) == 0)
316 #ifndef HAVE_BUGGY_MESAGL
317 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
318 so that future version will work great. */
319 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
320 pformat->dwFlags = DDPF_RGB;
321 pformat->u.dwRGBBitCount = 16;
322 pformat->u1.dwRBitMask = 0x0000F800;
323 pformat->u2.dwGBitMask = 0x000007E0;
324 pformat->u3.dwBBitMask = 0x0000001F;
325 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
326 if (cb(&sdesc, context) == 0)
329 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
330 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
331 pformat->u.dwRGBBitCount = 16;
332 pformat->u1.dwRBitMask = 0x0000F800;
333 pformat->u2.dwGBitMask = 0x000007C0;
334 pformat->u3.dwBBitMask = 0x0000003E;
335 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
336 if (cb(&sdesc, context) == 0)
339 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
340 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
341 pformat->u.dwRGBBitCount = 16;
342 pformat->u1.dwRBitMask = 0x0000F000;
343 pformat->u2.dwGBitMask = 0x00000F00;
344 pformat->u3.dwBBitMask = 0x000000F0;
345 pformat->u4.dwRGBAlphaBitMask = 0x0000000F;
346 if (cb(&sdesc, context) == 0)
349 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
350 pformat->dwFlags = DDPF_RGB;
351 pformat->u.dwRGBBitCount = 8;
352 pformat->u1.dwRBitMask = 0x0000F800;
353 pformat->u2.dwGBitMask = 0x000007C0;
354 pformat->u3.dwBBitMask = 0x0000003E;
355 pformat->u4.dwRGBAlphaBitMask = 0x00000001;
356 if (cb(&sdesc, context) == 0)
360 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
361 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
362 pformat->u.dwRGBBitCount = 16;
363 pformat->u1.dwRBitMask = 0x00007C00;
364 pformat->u2.dwGBitMask = 0x000003E0;
365 pformat->u3.dwBBitMask = 0x0000001F;
366 pformat->u4.dwRGBAlphaBitMask = 0x00008000;
367 if (cb(&sdesc, context) == 0)
370 TRACE("Enumerating Paletted (8)\n");
371 pformat->dwFlags = DDPF_PALETTEINDEXED8;
372 pformat->u.dwRGBBitCount = 8;
373 pformat->u1.dwRBitMask = 0x00000000;
374 pformat->u2.dwGBitMask = 0x00000000;
375 pformat->u3.dwBBitMask = 0x00000000;
376 pformat->u4.dwRGBAlphaBitMask = 0x00000000;
377 if (cb(&sdesc, context) == 0)
380 TRACE("End of enumeration\n");
385 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
386 LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
388 ICOM_THIS(IDirect3DDevice2Impl,iface);
389 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
391 return enum_texture_format_OpenGL(cb, context);
394 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
395 LPDIRECT3DDEVICE2 iface
397 ICOM_THIS(IDirect3DDevice2Impl,iface);
399 FIXME("(%p)->(): stub\n", This);
401 /* Here, we should get the DDraw surface and 'copy it' to the
402 OpenGL surface.... */
407 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
408 ICOM_THIS(IDirect3DDevice2Impl,iface);
412 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
416 unsigned short *dest;
419 FIXME("(%p)->(): stub\n", This);
422 /* Here we copy back the OpenGL scene to the the DDraw surface */
423 /* First, lock the surface */
424 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
426 /* The copy the OpenGL buffer to this surface */
428 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
429 I am currently working on a set of patches for Mesa to have OSMesa support
430 16 bpp surfaces => we will able to render directly onto the surface, no
431 need to do a bpp conversion */
432 dest = (unsigned short *) sdesc.y.lpSurface;
433 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
434 for (y = 0; y < sdesc.dwHeight; y++) {
435 unsigned char *lsrc = src;
437 for (x = 0; x < sdesc.dwWidth ; x++) {
438 unsigned char r = *lsrc++;
439 unsigned char g = *lsrc++;
440 unsigned char b = *lsrc++;
442 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
447 src -= 4 * sdesc.dwWidth;
450 /* Unlock the surface */
451 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
453 /* No need to do anything here... */
459 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
460 LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
463 ICOM_THIS(IDirect3DDevice2Impl,iface);
466 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
468 /* Call the render state functions */
469 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
474 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
475 LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
478 ICOM_THIS(IDirect3DDevice2Impl,iface);
479 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
481 switch (dwLightStateType) {
482 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
483 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
490 TRACE("Zoups !!!\n");
494 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
497 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
498 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
499 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
502 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
506 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
514 TRACE("Unexpected Light State Type\n");
515 return DDERR_INVALIDPARAMS;
521 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
522 LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
525 ICOM_THIS(IDirect3DDevice2Impl,iface);
528 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
532 /* Using a trial and failure approach, I found that the order of
533 Direct3D transformations that works best is :
535 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
537 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
538 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
540 If anyone has a good explanation of the three different matrices in
541 the SDK online documentation, feel free to point it to me. For example,
542 which matrices transform lights ? In OpenGL only the PROJECTION matrix
543 transform the lights, not the MODELVIEW. Using the matrix names, I
544 supposed that PROJECTION and VIEW (all 'camera' related names) do
545 transform lights, but WORLD do not. It may be wrong though... */
547 /* After reading through both OpenGL and Direct3D documentations, I
548 thought that D3D matrices were written in 'line major mode' transposed
549 from OpenGL's 'column major mode'. But I found out that a simple memcpy
550 works fine to transfer one matrix format to the other (it did not work
551 when transposing)....
554 1) are the documentations wrong
555 2) does the matrix work even if they are not read correctly
556 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
557 loading using glLoadMatrix ?
559 Anyway, I always use 'conv_mat' to transfer the matrices from one format
560 to the other so that if I ever find out that I need to transpose them, I
561 will able to do it quickly, only by changing the macro conv_mat. */
564 case D3DTRANSFORMSTATE_WORLD: {
565 conv_mat(lpmatrix, odev->world_mat);
566 glMatrixMode(GL_MODELVIEW);
567 glLoadMatrixf((float *) odev->world_mat);
570 case D3DTRANSFORMSTATE_VIEW: {
571 conv_mat(lpmatrix, odev->view_mat);
572 glMatrixMode(GL_PROJECTION);
573 glLoadMatrixf((float *) odev->proj_mat);
574 glMultMatrixf((float *) odev->view_mat);
577 case D3DTRANSFORMSTATE_PROJECTION: {
578 conv_mat(lpmatrix, odev->proj_mat);
579 glMatrixMode(GL_PROJECTION);
580 glLoadMatrixf((float *) odev->proj_mat);
581 glMultMatrixf((float *) odev->view_mat);
591 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
592 /* Puts GL in the correct lighting mode */ \
593 if (odev->vt != d3dv) { \
594 if (odev->vt == D3DVT_TLVERTEX) { \
595 /* Need to put the correct transformation again */ \
596 glMatrixMode(GL_MODELVIEW); \
597 glLoadMatrixf((float *) odev->world_mat); \
598 glMatrixMode(GL_PROJECTION); \
599 glLoadMatrixf((float *) odev->proj_mat); \
600 glMultMatrixf((float *) odev->view_mat); \
605 TRACE("Standard Vertex\n"); \
606 glEnable(GL_LIGHTING); \
609 case D3DVT_LVERTEX: \
610 TRACE("Lighted Vertex\n"); \
611 glDisable(GL_LIGHTING); \
614 case D3DVT_TLVERTEX: { \
615 GLdouble height, width, minZ, maxZ; \
617 TRACE("Transformed - Lighted Vertex\n"); \
618 /* First, disable lighting */ \
619 glDisable(GL_LIGHTING); \
621 /* Then do not put any transformation matrixes */ \
622 glMatrixMode(GL_MODELVIEW); \
624 glMatrixMode(GL_PROJECTION); \
627 if (This->current_viewport == NULL) { \
628 ERR("No current viewport !\n"); \
629 /* Using standard values */ \
635 if (This->current_viewport->use_vp2) { \
636 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
637 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
638 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
639 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
641 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
642 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
643 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
644 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
648 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
652 ERR("Unhandled vertex type\n"); \
660 case D3DPT_POINTLIST: \
661 TRACE("Start POINTS\n"); \
662 glBegin(GL_POINTS); \
665 case D3DPT_LINELIST: \
666 TRACE("Start LINES\n"); \
670 case D3DPT_LINESTRIP: \
671 TRACE("Start LINE_STRIP\n"); \
672 glBegin(GL_LINE_STRIP); \
675 case D3DPT_TRIANGLELIST: \
676 TRACE("Start TRIANGLES\n"); \
677 glBegin(GL_TRIANGLES); \
680 case D3DPT_TRIANGLESTRIP: \
681 TRACE("Start TRIANGLE_STRIP\n"); \
682 glBegin(GL_TRIANGLE_STRIP); \
685 case D3DPT_TRIANGLEFAN: \
686 TRACE("Start TRIANGLE_FAN\n"); \
687 glBegin(GL_TRIANGLE_FAN); \
691 TRACE("Unhandled primitive\n"); \
695 /* Draw the primitives */ \
696 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
698 case D3DVT_VERTEX: { \
699 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
701 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
702 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
703 TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
706 case D3DVT_LVERTEX: { \
707 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
708 DWORD col = vx->c.color; \
710 glColor3f(((col >> 16) & 0xFF) / 255.0, \
711 ((col >> 8) & 0xFF) / 255.0, \
712 ((col >> 0) & 0xFF) / 255.0); \
713 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
714 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
715 vx->x.x, vx->y.y, vx->z.z, \
716 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
719 case D3DVT_TLVERTEX: { \
720 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
721 DWORD col = vx->c.color; \
723 glColor3f(((col >> 16) & 0xFF) / 255.0, \
724 ((col >> 8) & 0xFF) / 255.0, \
725 ((col >> 0) & 0xFF) / 255.0); \
726 glTexCoord2f(vx->u.tu, vx->v.tv); \
727 if (vx->r.rhw < 0.01) \
728 glVertex3f(vx->x.sx, \
732 glVertex4f(vx->x.sx / vx->r.rhw, \
733 vx->y.sy / vx->r.rhw, \
734 vx->z.sz / vx->r.rhw, \
736 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
737 vx->x.sx, vx->y.sy, vx->z.sz, \
738 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
739 vx->u.tu, vx->v.tv, vx->r.rhw); \
743 FIXME("Unhandled vertex type\n"); \
752 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
753 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
754 LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
756 ICOM_THIS(IDirect3DDevice2Impl,iface);
760 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
763 DRAW_PRIMITIVE(vertcount, vx_index);
769 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
770 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
771 LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
774 ICOM_THIS(IDirect3DDevice2Impl,iface);
778 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
781 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
787 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
788 LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
789 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
791 ICOM_THIS(IDirect3DDeviceImpl,iface);
792 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
793 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
798 /*******************************************************************************
799 * OpenGL-specific IDirect3DDevice2
802 /*******************************************************************************
803 * OpenGL-specific VTable
806 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
808 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
809 IDirect3DDevice2Impl_QueryInterface,
810 IDirect3DDevice2Impl_AddRef,
811 MESA_IDirect3DDevice2Impl_Release,
812 /*** IDirect3DDevice2 methods ***/
813 MESA_IDirect3DDevice2Impl_GetCaps,
814 IDirect3DDevice2Impl_SwapTextureHandles,
815 IDirect3DDevice2Impl_GetStats,
816 IDirect3DDevice2Impl_AddViewport,
817 IDirect3DDevice2Impl_DeleteViewport,
818 IDirect3DDevice2Impl_NextViewport,
819 MESA_IDirect3DDevice2Impl_EnumTextureFormats,
820 MESA_IDirect3DDevice2Impl_BeginScene,
821 MESA_IDirect3DDevice2Impl_EndScene,
822 IDirect3DDevice2Impl_GetDirect3D,
824 /*** DrawPrimitive API ***/
825 IDirect3DDevice2Impl_SetCurrentViewport,
826 IDirect3DDevice2Impl_GetCurrentViewport,
828 IDirect3DDevice2Impl_SetRenderTarget,
829 IDirect3DDevice2Impl_GetRenderTarget,
831 IDirect3DDevice2Impl_Begin,
832 IDirect3DDevice2Impl_BeginIndexed,
833 IDirect3DDevice2Impl_Vertex,
834 IDirect3DDevice2Impl_Index,
835 IDirect3DDevice2Impl_End,
837 IDirect3DDevice2Impl_GetRenderState,
838 MESA_IDirect3DDevice2Impl_SetRenderState,
839 IDirect3DDevice2Impl_GetLightState,
840 MESA_IDirect3DDevice2Impl_SetLightState,
841 MESA_IDirect3DDevice2Impl_SetTransform,
842 IDirect3DDevice2Impl_GetTransform,
843 IDirect3DDevice2Impl_MultiplyTransform,
845 MESA_IDirect3DDevice2Impl_DrawPrimitive,
846 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
848 IDirect3DDevice2Impl_SetClipStatus,
849 IDirect3DDevice2Impl_GetClipStatus,
852 /*******************************************************************************
855 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
858 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
860 fill_opengl_caps(&d1, &d2);
862 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
865 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
867 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
868 mesa_d3dd_private *odev;
870 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
874 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
875 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
876 odev = (mesa_d3dd_private*)(*device)->private;
878 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
879 (*device)->d3d = NULL;
880 (*device)->surface = surface;
882 (*device)->viewport_list = NULL;
883 (*device)->current_viewport = NULL;
885 (*device)->set_context = (void*)set_context;
887 TRACE("OpenGL device created \n");
889 /* Create the OpenGL context */
891 odev->ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
892 odev->buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
893 surface->s.surface_desc.dwWidth * surface->s.surface_desc.dwHeight * 4);
895 /* First get the correct visual */
896 /* if (surface->s.backbuffer == NULL)
897 attributeList[3] = None; */
899 xvis = glXChooseVisual(display,
900 DefaultScreen(display),
903 ERR("No visual found !\n");
905 TRACE("Visual found\n");
906 /* Create the context */
907 odev->ctx = glXCreateContext(display,
911 TRACE("Context created\n");
913 #if 0 /* non working currently */
914 /* Now override the surface's Flip method (if in double buffering) */
915 surface->s.d3d_device = (void *) odev;
918 struct _surface_chain *chain = surface->s.chain;
919 for (i=0;i<chain->nrofsurfaces;i++)
920 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
921 chain->surfaces[i]->s.d3d_device = (void *) odev;
925 odev->rs.src = GL_ONE;
926 odev->rs.dst = GL_ZERO;
927 odev->rs.mag = GL_NEAREST;
928 odev->rs.min = GL_NEAREST;
930 odev->world_mat = (LPD3DMATRIX) &id_mat;
931 odev->view_mat = (LPD3DMATRIX) &id_mat;
932 odev->proj_mat = (LPD3DMATRIX) &id_mat;
935 (*device)->set_context(*device);
936 glClearColor(0.0, 0.0, 0.0, 0.0);
937 glColor3f(1.0, 1.0, 1.0);
939 fill_device_capabilities((IDirectDrawImpl *) surface->s.ddraw);
944 /* This is not the OpenGL UID */
948 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
950 ICOM_THIS(IDirect3DDeviceImpl,iface);
951 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
953 if (!--(This->ref)) {
956 OSMesaDestroyContext(odev->ctx);
959 glXDestroyContext(display, odev->ctx);
962 This->private = NULL;
963 HeapFree(GetProcessHeap(),0,This);
969 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
970 LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
973 ICOM_THIS(IDirect3DDeviceImpl,iface);
974 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
976 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
980 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
982 ICOM_THIS(IDirect3DDeviceImpl,iface);
983 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
985 FIXME("(%p)->(): stub\n", This);
987 /* We get the pointer to the surface (should be done on flip) */
988 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
994 /* This is for the moment copy-pasted from IDirect3DDevice2...
995 Will make a common function ... */
996 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
998 ICOM_THIS(IDirect3DDeviceImpl,iface);
1001 LPDIRECTDRAWSURFACE3 surf = (LPDIRECTDRAWSURFACE3) This->surface;
1002 DDSURFACEDESC sdesc;
1005 unsigned short *dest;
1008 FIXME("(%p)->(): stub\n", This);
1011 /* Here we copy back the OpenGL scene to the the DDraw surface */
1012 /* First, lock the surface */
1013 IDirectDrawSurface3_Lock(surf,NULL,&sdesc,DDLOCK_WRITEONLY,0);
1015 /* The copy the OpenGL buffer to this surface */
1017 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1018 I am currently working on a set of patches for Mesa to have OSMesa support
1019 16 bpp surfaces => we will able to render directly onto the surface, no
1020 need to do a bpp conversion */
1021 dest = (unsigned short *) sdesc.y.lpSurface;
1022 src = ((unsigned char *) odev->buffer) + 4 * (sdesc.dwWidth * (sdesc.dwHeight - 1));
1023 for (y = 0; y < sdesc.dwHeight; y++) {
1024 unsigned char *lsrc = src;
1026 for (x = 0; x < sdesc.dwWidth ; x++) {
1027 unsigned char r = *lsrc++;
1028 unsigned char g = *lsrc++;
1029 unsigned char b = *lsrc++;
1032 *dest = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
1037 src -= 4 * sdesc.dwWidth;
1040 /* Unlock the surface */
1041 IDirectDrawSurface3_Unlock(surf,sdesc.y.lpSurface);
1043 /* No need to do anything here... */
1049 /*******************************************************************************
1050 * Direct3DDevice VTable
1052 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1054 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1055 IDirect3DDeviceImpl_QueryInterface,
1056 IDirect3DDeviceImpl_AddRef,
1057 MESA_IDirect3DDeviceImpl_Release,
1058 IDirect3DDeviceImpl_Initialize,
1059 IDirect3DDeviceImpl_GetCaps,
1060 IDirect3DDeviceImpl_SwapTextureHandles,
1061 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
1062 IDirect3DDeviceImpl_GetStats,
1063 IDirect3DDeviceImpl_Execute,
1064 IDirect3DDeviceImpl_AddViewport,
1065 IDirect3DDeviceImpl_DeleteViewport,
1066 IDirect3DDeviceImpl_NextViewport,
1067 IDirect3DDeviceImpl_Pick,
1068 IDirect3DDeviceImpl_GetPickRecords,
1069 MESA_IDirect3DDeviceImpl_EnumTextureFormats,
1070 IDirect3DDeviceImpl_CreateMatrix,
1071 IDirect3DDeviceImpl_SetMatrix,
1072 IDirect3DDeviceImpl_GetMatrix,
1073 IDirect3DDeviceImpl_DeleteMatrix,
1074 MESA_IDirect3DDeviceImpl_BeginScene,
1075 MESA_IDirect3DDeviceImpl_EndScene,
1076 IDirect3DDeviceImpl_GetDirect3D,