4 This files contains the MESA implementation of all the D3D devices that
11 #include "wine/obj_base.h"
14 #include "debugtools.h"
16 #include "mesa_private.h"
18 DEFAULT_DEBUG_CHANNEL(ddraw);
20 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
21 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
23 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
24 on Mesa's home page) or version 3.1b.
26 Version 3.1b2 should correct this bug */
27 #undef HAVE_BUGGY_MESAGL
29 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
31 #ifndef HAVE_GLEXT_PROTOTYPES
32 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
33 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
34 GLsizei width, GLenum format, GLenum type,
38 static const float id_mat[16] = {
45 /*******************************************************************************
46 * OpenGL static functions
48 static void set_context(IDirect3DDevice2Impl* This) {
52 if (glXMakeCurrent(gdi_display,ddpriv->drawable, odev->ctx) == False) {
53 ERR("Error in setting current context (context %p drawable %ld)!\n",
54 odev->ctx, ddpriv->drawable);
59 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
61 pc->dwSize = sizeof(*pc);
62 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
63 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
64 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
65 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
66 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
67 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
68 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
69 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
70 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
71 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
72 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
73 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
74 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
75 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
76 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
77 pc->dwStippleWidth = 32;
78 pc->dwStippleHeight = 32;
81 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
85 d1->dwSize = sizeof(*d1);
86 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
87 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
88 d1->dcmColorModel = D3DCOLOR_RGB;
89 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
90 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
91 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
92 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
93 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
95 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
96 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
97 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
98 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
99 fill_opengl_primcaps(&(d1->dpcLineCaps));
100 fill_opengl_primcaps(&(d1->dpcTriCaps));
101 d1->dwDeviceRenderBitDepth = DDBD_16;
102 d1->dwDeviceZBufferBitDepth = DDBD_16;
103 d1->dwMaxBufferSize = 0;
104 d1->dwMaxVertexCount = 65536;
105 d1->dwMinTextureWidth = 1;
106 d1->dwMinTextureHeight = 1;
107 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
108 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
109 d1->dwMinStippleWidth = 1;
110 d1->dwMinStippleHeight = 1;
111 d1->dwMaxStippleWidth = 32;
112 d1->dwMaxStippleHeight = 32;
114 d2->dwSize = sizeof(*d2);
118 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
120 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
121 const char *ext_string;
122 Mesa_DeviceCapabilities *devcap;
124 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
125 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
128 ext_string = glGetString(GL_EXTENSIONS);
129 /* Query for the ColorTable Extension */
130 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
131 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
132 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
134 TRACE("Color table extension not found.\n");
140 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
142 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL));
143 fill_opengl_caps(&d1, &d2);
144 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context);
149 REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
150 IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
152 mesa_d3dd_private *odev = NULL;
154 if (/* Default device */
157 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
159 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
161 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
162 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
163 odev = (mesa_d3dd_private*)(*device)->private;
165 ICOM_VTBL(*device) = &OpenGL_vtable;
166 (*device)->d3d = d3d;
167 (*device)->surface = surface;
168 (*device)->viewport_list = NULL;
169 (*device)->current_viewport = NULL;
170 (*device)->set_context = set_context;
172 TRACE("Creating OpenGL device for surface %p\n", surface);
173 /* Create the OpenGL context */
175 /* First get the correct visual */
177 /* Create the context */
181 XVisualInfo template;
183 template.visualid = XVisualIDFromVisual(visual);
184 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
186 odev->ctx = glXCreateContext(gdi_display, vis,
190 if (odev->ctx == NULL)
191 ERR("Error in context creation !\n");
193 TRACE("Context created (%p)\n", odev->ctx);
195 /* Now override the surface's Flip method (if in double buffering) */
196 ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
199 struct _surface_chain *chain = surface->s.chain;
200 for (i=0;i<chain->nrofsurfaces;i++)
201 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
202 ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
206 odev->rs.src = GL_ONE;
207 odev->rs.dst = GL_ZERO;
208 odev->rs.mag = GL_NEAREST;
209 odev->rs.min = GL_NEAREST;
212 /* Allocate memory for the matrices */
213 odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
214 odev->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
215 odev->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
217 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
218 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
219 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
222 TRACE("Setting current context\n");
223 (*device)->set_context(*device);
224 TRACE("Current context set\n");
225 glClearColor(0.0, 0.0, 0.0, 0.0);
226 glColor3f(1.0, 1.0, 1.0);
229 fill_device_capabilities(d3d->ddraw);
231 TRACE("OpenGL device created \n");
234 FIXME("bad IID %s\n",debugstr_guid(rguid));
235 /* This is not the OpenGL UID */
239 /*******************************************************************************
240 * MESA IDirect3DDevice2
242 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
244 ICOM_THIS(IDirect3DDevice2Impl,iface);
245 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
247 if (!--(This->ref)) {
248 #if 0 /* broken for now */
251 glXDestroyContext(gdi_display, odev->ctx);
254 This->private = NULL;
255 HeapFree(GetProcessHeap(),0,This);
261 /*** IDirect3DDevice2 methods ***/
262 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
263 LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
264 LPD3DDEVICEDESC lpdeschard
266 ICOM_THIS(IDirect3DDevice2Impl,iface);
267 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
268 fill_opengl_caps(lpdescsoft, lpdeschard);
272 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
275 LPDDPIXELFORMAT pformat;
277 /* Do the texture enumeration */
278 sdesc.dwSize = sizeof(DDSURFACEDESC);
279 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
280 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
281 pformat = &(sdesc.ddpfPixelFormat);
282 pformat->dwSize = sizeof(DDPIXELFORMAT);
283 pformat->dwFourCC = 0;
285 TRACE("Enumerating GL_RGBA unpacked (32)\n");
286 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
287 pformat->u1.dwRGBBitCount = 32;
288 pformat->u2.dwRBitMask = 0xFF000000;
289 pformat->u3.dwGBitMask = 0x00FF0000;
290 pformat->u4.dwBBitMask = 0x0000FF00;
291 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
292 if (cb(&sdesc, context) == 0)
295 TRACE("Enumerating GL_RGB unpacked (24)\n");
296 pformat->dwFlags = DDPF_RGB;
297 pformat->u1.dwRGBBitCount = 24;
298 pformat->u2.dwRBitMask = 0x00FF0000;
299 pformat->u3.dwGBitMask = 0x0000FF00;
300 pformat->u4.dwBBitMask = 0x000000FF;
301 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
302 if (cb(&sdesc, context) == 0)
305 #ifndef HAVE_BUGGY_MESAGL
306 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
307 so that future version will work great. */
308 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
309 pformat->dwFlags = DDPF_RGB;
310 pformat->u1.dwRGBBitCount = 16;
311 pformat->u2.dwRBitMask = 0x0000F800;
312 pformat->u3.dwGBitMask = 0x000007E0;
313 pformat->u4.dwBBitMask = 0x0000001F;
314 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
315 if (cb(&sdesc, context) == 0)
318 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
319 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
320 pformat->u1.dwRGBBitCount = 16;
321 pformat->u2.dwRBitMask = 0x0000F800;
322 pformat->u3.dwGBitMask = 0x000007C0;
323 pformat->u4.dwBBitMask = 0x0000003E;
324 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
325 if (cb(&sdesc, context) == 0)
328 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
329 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
330 pformat->u1.dwRGBBitCount = 16;
331 pformat->u2.dwRBitMask = 0x0000F000;
332 pformat->u3.dwGBitMask = 0x00000F00;
333 pformat->u4.dwBBitMask = 0x000000F0;
334 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
335 if (cb(&sdesc, context) == 0)
338 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
339 pformat->dwFlags = DDPF_RGB;
340 pformat->u1.dwRGBBitCount = 8;
341 pformat->u2.dwRBitMask = 0x0000F800;
342 pformat->u3.dwGBitMask = 0x000007C0;
343 pformat->u4.dwBBitMask = 0x0000003E;
344 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
345 if (cb(&sdesc, context) == 0)
349 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
350 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
351 pformat->u1.dwRGBBitCount = 16;
352 pformat->u2.dwRBitMask = 0x00007C00;
353 pformat->u3.dwGBitMask = 0x000003E0;
354 pformat->u4.dwBBitMask = 0x0000001F;
355 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
356 if (cb(&sdesc, context) == 0)
359 TRACE("Enumerating Paletted (8)\n");
360 pformat->dwFlags = DDPF_PALETTEINDEXED8;
361 pformat->u1.dwRGBBitCount = 8;
362 pformat->u2.dwRBitMask = 0x00000000;
363 pformat->u3.dwGBitMask = 0x00000000;
364 pformat->u4.dwBBitMask = 0x00000000;
365 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
366 if (cb(&sdesc, context) == 0)
369 TRACE("End of enumeration\n");
374 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
375 LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
377 ICOM_THIS(IDirect3DDevice2Impl,iface);
378 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
380 return enum_texture_format_OpenGL(cb, context);
383 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
384 LPDIRECT3DDEVICE2 iface
386 ICOM_THIS(IDirect3DDevice2Impl,iface);
388 FIXME("(%p)->(): stub\n", This);
390 /* Here, we should get the DDraw surface and 'copy it' to the
391 OpenGL surface.... */
396 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
397 ICOM_THIS(IDirect3DDevice2Impl,iface);
399 FIXME("(%p)->(): stub\n", This);
401 /* No need to do anything here... */
406 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
407 LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
410 ICOM_THIS(IDirect3DDevice2Impl,iface);
413 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
415 /* Call the render state functions */
416 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
421 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
422 LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
425 ICOM_THIS(IDirect3DDevice2Impl,iface);
426 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
428 switch (dwLightStateType) {
429 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
430 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
437 TRACE("Zoups !!!\n");
441 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
444 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
445 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
446 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
449 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
453 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
461 TRACE("Unexpected Light State Type\n");
462 return DDERR_INVALIDPARAMS;
468 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
469 LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
472 ICOM_THIS(IDirect3DDevice2Impl,iface);
475 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
479 /* Using a trial and failure approach, I found that the order of
480 Direct3D transformations that works best is :
482 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
484 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
485 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
487 If anyone has a good explanation of the three different matrices in
488 the SDK online documentation, feel free to point it to me. For example,
489 which matrices transform lights ? In OpenGL only the PROJECTION matrix
490 transform the lights, not the MODELVIEW. Using the matrix names, I
491 supposed that PROJECTION and VIEW (all 'camera' related names) do
492 transform lights, but WORLD do not. It may be wrong though... */
494 /* After reading through both OpenGL and Direct3D documentations, I
495 thought that D3D matrices were written in 'line major mode' transposed
496 from OpenGL's 'column major mode'. But I found out that a simple memcpy
497 works fine to transfer one matrix format to the other (it did not work
498 when transposing)....
501 1) are the documentations wrong
502 2) does the matrix work even if they are not read correctly
503 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
504 loading using glLoadMatrix ?
506 Anyway, I always use 'conv_mat' to transfer the matrices from one format
507 to the other so that if I ever find out that I need to transpose them, I
508 will able to do it quickly, only by changing the macro conv_mat. */
511 case D3DTRANSFORMSTATE_WORLD: {
512 conv_mat(lpmatrix, odev->world_mat);
513 glMatrixMode(GL_MODELVIEW);
514 glLoadMatrixf((float *) odev->world_mat);
517 case D3DTRANSFORMSTATE_VIEW: {
518 conv_mat(lpmatrix, odev->view_mat);
519 glMatrixMode(GL_PROJECTION);
520 glLoadMatrixf((float *) odev->proj_mat);
521 glMultMatrixf((float *) odev->view_mat);
524 case D3DTRANSFORMSTATE_PROJECTION: {
525 conv_mat(lpmatrix, odev->proj_mat);
526 glMatrixMode(GL_PROJECTION);
527 glLoadMatrixf((float *) odev->proj_mat);
528 glMultMatrixf((float *) odev->view_mat);
538 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
539 /* Puts GL in the correct lighting mode */ \
540 if (odev->vt != d3dv) { \
541 if (odev->vt == D3DVT_TLVERTEX) { \
542 /* Need to put the correct transformation again */ \
543 glMatrixMode(GL_MODELVIEW); \
544 glLoadMatrixf((float *) odev->world_mat); \
545 glMatrixMode(GL_PROJECTION); \
546 glLoadMatrixf((float *) odev->proj_mat); \
547 glMultMatrixf((float *) odev->view_mat); \
552 TRACE("Standard Vertex\n"); \
553 glEnable(GL_LIGHTING); \
556 case D3DVT_LVERTEX: \
557 TRACE("Lighted Vertex\n"); \
558 glDisable(GL_LIGHTING); \
561 case D3DVT_TLVERTEX: { \
562 GLdouble height, width, minZ, maxZ; \
564 TRACE("Transformed - Lighted Vertex\n"); \
565 /* First, disable lighting */ \
566 glDisable(GL_LIGHTING); \
568 /* Then do not put any transformation matrixes */ \
569 glMatrixMode(GL_MODELVIEW); \
571 glMatrixMode(GL_PROJECTION); \
574 if (This->current_viewport == NULL) { \
575 ERR("No current viewport !\n"); \
576 /* Using standard values */ \
582 if (This->current_viewport->use_vp2) { \
583 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
584 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
585 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
586 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
588 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
589 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
590 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
591 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
595 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
599 ERR("Unhandled vertex type\n"); \
607 case D3DPT_POINTLIST: \
608 TRACE("Start POINTS\n"); \
609 glBegin(GL_POINTS); \
612 case D3DPT_LINELIST: \
613 TRACE("Start LINES\n"); \
617 case D3DPT_LINESTRIP: \
618 TRACE("Start LINE_STRIP\n"); \
619 glBegin(GL_LINE_STRIP); \
622 case D3DPT_TRIANGLELIST: \
623 TRACE("Start TRIANGLES\n"); \
624 glBegin(GL_TRIANGLES); \
627 case D3DPT_TRIANGLESTRIP: \
628 TRACE("Start TRIANGLE_STRIP\n"); \
629 glBegin(GL_TRIANGLE_STRIP); \
632 case D3DPT_TRIANGLEFAN: \
633 TRACE("Start TRIANGLE_FAN\n"); \
634 glBegin(GL_TRIANGLE_FAN); \
638 TRACE("Unhandled primitive\n"); \
642 /* Draw the primitives */ \
643 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
645 case D3DVT_VERTEX: { \
646 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
648 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz); \
649 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
650 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z); \
653 case D3DVT_LVERTEX: { \
654 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
655 DWORD col = vx->u4.color; \
657 glColor3f(((col >> 16) & 0xFF) / 255.0, \
658 ((col >> 8) & 0xFF) / 255.0, \
659 ((col >> 0) & 0xFF) / 255.0); \
660 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
661 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
662 vx->u1.x, vx->u2.y, vx->u3.z, \
663 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
666 case D3DVT_TLVERTEX: { \
667 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
668 DWORD col = vx->u5.color; \
670 glColor3f(((col >> 16) & 0xFF) / 255.0, \
671 ((col >> 8) & 0xFF) / 255.0, \
672 ((col >> 0) & 0xFF) / 255.0); \
673 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
674 if (vx->u4.rhw < 0.01) \
675 glVertex3f(vx->u1.sx, \
679 glVertex4f(vx->u1.sx / vx->u4.rhw, \
680 vx->u2.sy / vx->u4.rhw, \
681 vx->u3.sz / vx->u4.rhw, \
683 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
684 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
685 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
686 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
690 FIXME("Unhandled vertex type\n"); \
699 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
700 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
701 LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
703 ICOM_THIS(IDirect3DDevice2Impl,iface);
707 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
710 DRAW_PRIMITIVE(vertcount, vx_index);
716 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
717 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
718 LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
721 ICOM_THIS(IDirect3DDevice2Impl,iface);
725 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
728 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
734 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
735 LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
736 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
738 ICOM_THIS(IDirect3DDeviceImpl,iface);
739 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
740 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
745 /*******************************************************************************
746 * OpenGL-specific IDirect3DDevice2
749 /*******************************************************************************
750 * OpenGL-specific VTable
753 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
755 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
756 IDirect3DDevice2Impl_QueryInterface,
757 IDirect3DDevice2Impl_AddRef,
758 MESA_IDirect3DDevice2Impl_Release,
759 /*** IDirect3DDevice2 methods ***/
760 MESA_IDirect3DDevice2Impl_GetCaps,
761 IDirect3DDevice2Impl_SwapTextureHandles,
762 IDirect3DDevice2Impl_GetStats,
763 IDirect3DDevice2Impl_AddViewport,
764 IDirect3DDevice2Impl_DeleteViewport,
765 IDirect3DDevice2Impl_NextViewport,
766 MESA_IDirect3DDevice2Impl_EnumTextureFormats,
767 MESA_IDirect3DDevice2Impl_BeginScene,
768 MESA_IDirect3DDevice2Impl_EndScene,
769 IDirect3DDevice2Impl_GetDirect3D,
771 /*** DrawPrimitive API ***/
772 IDirect3DDevice2Impl_SetCurrentViewport,
773 IDirect3DDevice2Impl_GetCurrentViewport,
775 IDirect3DDevice2Impl_SetRenderTarget,
776 IDirect3DDevice2Impl_GetRenderTarget,
778 IDirect3DDevice2Impl_Begin,
779 IDirect3DDevice2Impl_BeginIndexed,
780 IDirect3DDevice2Impl_Vertex,
781 IDirect3DDevice2Impl_Index,
782 IDirect3DDevice2Impl_End,
784 IDirect3DDevice2Impl_GetRenderState,
785 MESA_IDirect3DDevice2Impl_SetRenderState,
786 IDirect3DDevice2Impl_GetLightState,
787 MESA_IDirect3DDevice2Impl_SetLightState,
788 MESA_IDirect3DDevice2Impl_SetTransform,
789 IDirect3DDevice2Impl_GetTransform,
790 IDirect3DDevice2Impl_MultiplyTransform,
792 MESA_IDirect3DDevice2Impl_DrawPrimitive,
793 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
795 IDirect3DDevice2Impl_SetClipStatus,
796 IDirect3DDevice2Impl_GetClipStatus,
799 /*******************************************************************************
802 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
805 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
807 fill_opengl_caps(&d1, &d2);
809 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
812 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
814 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
815 mesa_d3dd_private *odev;
816 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
819 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
820 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
821 odev = (mesa_d3dd_private*)(*device)->private;
823 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
824 (*device)->d3d = NULL;
825 (*device)->surface = surface;
827 (*device)->viewport_list = NULL;
828 (*device)->current_viewport = NULL;
830 (*device)->set_context = (void*)set_context;
832 TRACE("OpenGL device created \n");
834 /* Create the OpenGL context */
835 /* First get the correct visual */
836 /* if (surface->s.backbuffer == NULL)
837 attributeList[3] = None; */
838 #if 0 /* non working currently */
840 xvis = glXChooseVisual(gdi_display,
841 DefaultScreen(gdi_display),
844 ERR("No visual found !\n");
846 TRACE("Visual found\n");
847 /* Create the context */
848 odev->ctx = glXCreateContext(gdi_display,
852 TRACE("Context created\n");
854 /* Now override the surface's Flip method (if in double buffering) */
855 surface->s.d3d_device = (void *) odev;
858 struct _surface_chain *chain = surface->s.chain;
859 for (i=0;i<chain->nrofsurfaces;i++)
860 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
861 chain->surfaces[i]->s.d3d_device = (void *) odev;
864 odev->rs.src = GL_ONE;
865 odev->rs.dst = GL_ZERO;
866 odev->rs.mag = GL_NEAREST;
867 odev->rs.min = GL_NEAREST;
869 odev->world_mat = (LPD3DMATRIX) &id_mat;
870 odev->view_mat = (LPD3DMATRIX) &id_mat;
871 odev->proj_mat = (LPD3DMATRIX) &id_mat;
874 (*device)->set_context(*device);
875 glClearColor(0.0, 0.0, 0.0, 0.0);
876 glColor3f(1.0, 1.0, 1.0);
878 fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner);
883 /* This is not the OpenGL UID */
887 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
889 ICOM_THIS(IDirect3DDeviceImpl,iface);
890 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
892 if (!--(This->ref)) {
893 #if 0 /* broken for now */
896 glXDestroyContext(gdi_display, odev->ctx);
899 This->private = NULL;
900 HeapFree(GetProcessHeap(),0,This);
906 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
907 LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
910 ICOM_THIS(IDirect3DDeviceImpl,iface);
911 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
913 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
917 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
919 ICOM_THIS(IDirect3DDeviceImpl,iface);
920 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
922 FIXME("(%p)->(): stub\n", This);
924 /* We get the pointer to the surface (should be done on flip) */
925 /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */
931 /* This is for the moment copy-pasted from IDirect3DDevice2...
932 Will make a common function ... */
933 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
935 ICOM_THIS(IDirect3DDeviceImpl,iface);
937 FIXME("(%p)->(): stub\n", This);
939 /* No need to do anything here... */
944 /*******************************************************************************
945 * Direct3DDevice VTable
947 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
949 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
950 IDirect3DDeviceImpl_QueryInterface,
951 IDirect3DDeviceImpl_AddRef,
952 MESA_IDirect3DDeviceImpl_Release,
953 IDirect3DDeviceImpl_Initialize,
954 IDirect3DDeviceImpl_GetCaps,
955 IDirect3DDeviceImpl_SwapTextureHandles,
956 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
957 IDirect3DDeviceImpl_GetStats,
958 IDirect3DDeviceImpl_Execute,
959 IDirect3DDeviceImpl_AddViewport,
960 IDirect3DDeviceImpl_DeleteViewport,
961 IDirect3DDeviceImpl_NextViewport,
962 IDirect3DDeviceImpl_Pick,
963 IDirect3DDeviceImpl_GetPickRecords,
964 MESA_IDirect3DDeviceImpl_EnumTextureFormats,
965 IDirect3DDeviceImpl_CreateMatrix,
966 IDirect3DDeviceImpl_SetMatrix,
967 IDirect3DDeviceImpl_GetMatrix,
968 IDirect3DDeviceImpl_DeleteMatrix,
969 MESA_IDirect3DDeviceImpl_BeginScene,
970 MESA_IDirect3DDeviceImpl_EndScene,
971 IDirect3DDeviceImpl_GetDirect3D,