4 This files contains the MESA implementation of all the D3D devices that
13 #include "wine/obj_base.h"
16 #include "debugtools.h"
18 #include "mesa_private.h"
20 DEFAULT_DEBUG_CHANNEL(ddraw
);
22 ICOM_VTABLE(IDirect3DDevice2
) OpenGL_vtable
;
23 ICOM_VTABLE(IDirect3DDevice
) OpenGL_vtable_dx3
;
25 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
26 on Mesa's home page) or version 3.1b.
28 Version 3.1b2 should correct this bug */
29 #undef HAVE_BUGGY_MESAGL
31 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->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
) {
54 if (glXMakeCurrent(gdi_display
,ddpriv
->drawable
, odev
->ctx
) == False
) {
55 ERR("Error in setting current context (context %p drawable %ld)!\n",
56 odev
->ctx
, ddpriv
->drawable
);
61 static void fill_opengl_primcaps(D3DPRIMCAPS
*pc
)
63 pc
->dwSize
= sizeof(*pc
);
64 pc
->dwMiscCaps
= D3DPMISCCAPS_CONFORMANT
| D3DPMISCCAPS_CULLCCW
| D3DPMISCCAPS_CULLCW
|
65 D3DPMISCCAPS_LINEPATTERNREP
| D3DPMISCCAPS_MASKZ
;
66 pc
->dwRasterCaps
= D3DPRASTERCAPS_DITHER
| D3DPRASTERCAPS_FOGRANGE
| D3DPRASTERCAPS_FOGTABLE
|
67 D3DPRASTERCAPS_FOGVERTEX
| D3DPRASTERCAPS_STIPPLE
| D3DPRASTERCAPS_ZBIAS
| D3DPRASTERCAPS_ZTEST
;
68 pc
->dwZCmpCaps
= 0xFFFFFFFF; /* All Z test can be done */
69 pc
->dwSrcBlendCaps
= 0xFFFFFFFF; /* FIXME: need REAL values */
70 pc
->dwDestBlendCaps
= 0xFFFFFFFF; /* FIXME: need REAL values */
71 pc
->dwAlphaCmpCaps
= 0xFFFFFFFF; /* FIXME: need REAL values */
72 pc
->dwShadeCaps
= 0xFFFFFFFF; /* FIXME: need REAL values */
73 pc
->dwTextureCaps
= D3DPTEXTURECAPS_ALPHA
| D3DPTEXTURECAPS_BORDER
| D3DPTEXTURECAPS_PERSPECTIVE
|
74 D3DPTEXTURECAPS_POW2
| D3DPTEXTURECAPS_TRANSPARENCY
;
75 pc
->dwTextureFilterCaps
= D3DPTFILTERCAPS_LINEAR
| D3DPTFILTERCAPS_LINEARMIPLINEAR
| D3DPTFILTERCAPS_LINEARMIPNEAREST
|
76 D3DPTFILTERCAPS_MIPLINEAR
| D3DPTFILTERCAPS_MIPNEAREST
| D3DPTFILTERCAPS_NEAREST
;
77 pc
->dwTextureBlendCaps
= 0xFFFFFFFF; /* FIXME: need REAL values */
78 pc
->dwTextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
| D3DPTADDRESSCAPS_CLAMP
| D3DPTADDRESSCAPS_WRAP
;
79 pc
->dwStippleWidth
= 32;
80 pc
->dwStippleHeight
= 32;
83 static void fill_opengl_caps(D3DDEVICEDESC
*d1
, D3DDEVICEDESC
*d2
)
87 d1
->dwSize
= sizeof(*d1
);
88 d1
->dwFlags
= D3DDD_DEVCAPS
| D3DDD_BCLIPPING
| D3DDD_COLORMODEL
| D3DDD_DEVICERENDERBITDEPTH
| D3DDD_DEVICEZBUFFERBITDEPTH
89 | D3DDD_LIGHTINGCAPS
| D3DDD_LINECAPS
| D3DDD_MAXBUFFERSIZE
| D3DDD_MAXVERTEXCOUNT
| D3DDD_TRANSFORMCAPS
| D3DDD_TRICAPS
;
90 d1
->dcmColorModel
= D3DCOLOR_RGB
;
91 d1
->dwDevCaps
= D3DDEVCAPS_CANRENDERAFTERFLIP
| D3DDEVCAPS_DRAWPRIMTLVERTEX
| D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
92 D3DDEVCAPS_EXECUTEVIDEOMEMORY
| D3DDEVCAPS_FLOATTLVERTEX
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
| D3DDEVCAPS_TEXTURESYSTEMMEMORY
|
93 D3DDEVCAPS_TEXTUREVIDEOMEMORY
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
;
94 d1
->dtcTransformCaps
.dwSize
= sizeof(D3DTRANSFORMCAPS
);
95 d1
->dtcTransformCaps
.dwCaps
= D3DTRANSFORMCAPS_CLIP
;
97 d1
->dlcLightingCaps
.dwSize
= sizeof(D3DLIGHTINGCAPS
);
98 d1
->dlcLightingCaps
.dwCaps
= D3DLIGHTCAPS_DIRECTIONAL
| D3DLIGHTCAPS_PARALLELPOINT
| D3DLIGHTCAPS_POINT
| D3DLIGHTCAPS_SPOT
;
99 d1
->dlcLightingCaps
.dwLightingModel
= D3DLIGHTINGMODEL_RGB
;
100 d1
->dlcLightingCaps
.dwNumLights
= 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
101 fill_opengl_primcaps(&(d1
->dpcLineCaps
));
102 fill_opengl_primcaps(&(d1
->dpcTriCaps
));
103 d1
->dwDeviceRenderBitDepth
= DDBD_16
;
104 d1
->dwDeviceZBufferBitDepth
= DDBD_16
;
105 d1
->dwMaxBufferSize
= 0;
106 d1
->dwMaxVertexCount
= 65536;
107 d1
->dwMinTextureWidth
= 1;
108 d1
->dwMinTextureHeight
= 1;
109 d1
->dwMaxTextureWidth
= 256; /* This is for Mesa on top of Glide (in the future :-) ) */
110 d1
->dwMaxTextureHeight
= 256; /* This is for Mesa on top of Glide (in the future :-) ) */
111 d1
->dwMinStippleWidth
= 1;
112 d1
->dwMinStippleHeight
= 1;
113 d1
->dwMaxStippleWidth
= 32;
114 d1
->dwMaxStippleHeight
= 32;
116 d2
->dwSize
= sizeof(*d2
);
120 static void fill_device_capabilities(IDirectDrawImpl
* ddraw
) {
122 x11_dd_private
*private = (x11_dd_private
*) ddraw
->d
->private;
123 const char *ext_string
;
124 Mesa_DeviceCapabilities
*devcap
;
126 private->device_capabilities
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Mesa_DeviceCapabilities
));
127 devcap
= (Mesa_DeviceCapabilities
*) private->device_capabilities
;
130 ext_string
= glGetString(GL_EXTENSIONS
);
131 /* Query for the ColorTable Extension */
132 if (strstr(ext_string
, "GL_EXT_paletted_texture")) {
133 devcap
->ptr_ColorTableEXT
= (PFNGLCOLORTABLEEXTPROC
) glXGetProcAddressARB("glColorTableEXT");
134 TRACE("Color table extension supported (function at %p)\n", devcap
->ptr_ColorTableEXT
);
136 TRACE("Color table extension not found.\n");
142 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
) {
144 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL
));
145 fill_opengl_caps(&d1
, &d2
);
146 return cb((void*)&IID_D3DDEVICE2_OpenGL
,"WINE Direct3D2 using OpenGL","direct3d",&d1
,&d2
,context
);
151 REFCLSID rguid
, IDirectDrawSurfaceImpl
* surface
,
152 IDirect3DDevice2Impl
** device
, IDirect3D2Impl
* d3d
154 mesa_d3dd_private
*odev
= NULL
;
156 if (/* Default device */
159 (!memcmp(&IID_IDirect3DHALDevice
,rguid
,sizeof(IID_IDirect3DHALDevice
))) ||
161 (!memcmp(&IID_D3DDEVICE2_OpenGL
,rguid
,sizeof(IID_D3DDEVICE2_OpenGL
)))) {
163 *device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirect3DDevice2Impl
));
164 (*device
)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(mesa_d3dd_private
));
165 odev
= (mesa_d3dd_private
*)(*device
)->private;
167 ICOM_VTBL(*device
) = &OpenGL_vtable
;
168 (*device
)->d3d
= d3d
;
169 (*device
)->surface
= surface
;
170 (*device
)->viewport_list
= NULL
;
171 (*device
)->current_viewport
= NULL
;
172 (*device
)->set_context
= set_context
;
174 TRACE("Creating OpenGL device for surface %p\n", surface
);
175 /* Create the OpenGL context */
177 /* First get the correct visual */
179 /* Create the context */
183 XVisualInfo
template;
185 template.visualid
= XVisualIDFromVisual(visual
);
186 vis
= XGetVisualInfo(gdi_display
, VisualIDMask
, &template, &num
);
188 odev
->ctx
= glXCreateContext(gdi_display
, vis
,
192 if (odev
->ctx
== NULL
)
193 ERR("Error in context creation !\n");
195 TRACE("Context created (%p)\n", odev
->ctx
);
197 /* Now override the surface's Flip method (if in double buffering) */
198 ((x11_ds_private
*) surface
->private)->opengl_flip
= TRUE
;
201 struct _surface_chain
*chain
= surface
->s
.chain
;
202 for (i
=0;i
<chain
->nrofsurfaces
;i
++)
203 if (chain
->surfaces
[i
]->s
.surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_FLIP
)
204 ((x11_ds_private
*) chain
->surfaces
[i
]->private)->opengl_flip
= TRUE
;
208 odev
->rs
.src
= GL_ONE
;
209 odev
->rs
.dst
= GL_ZERO
;
210 odev
->rs
.mag
= GL_NEAREST
;
211 odev
->rs
.min
= GL_NEAREST
;
214 /* Allocate memory for the matrices */
215 odev
->world_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
216 odev
->view_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
217 odev
->proj_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
219 memcpy(odev
->world_mat
, id_mat
, 16 * sizeof(float));
220 memcpy(odev
->view_mat
, id_mat
, 16 * sizeof(float));
221 memcpy(odev
->proj_mat
, id_mat
, 16 * sizeof(float));
224 TRACE("Setting current context\n");
225 (*device
)->set_context(*device
);
226 TRACE("Current context set\n");
227 glClearColor(0.0, 0.0, 0.0, 0.0);
228 glColor3f(1.0, 1.0, 1.0);
231 fill_device_capabilities(d3d
->ddraw
);
233 TRACE("OpenGL device created \n");
236 FIXME("bad IID %s\n",debugstr_guid(rguid
));
237 /* This is not the OpenGL UID */
241 /*******************************************************************************
242 * MESA IDirect3DDevice2
244 static ULONG WINAPI
MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface
)
246 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
247 FIXME("(%p)->() decrementing from %lu.\n", This
, This
->ref
);
249 if (!--(This
->ref
)) {
250 #if 0 /* broken for now */
253 glXDestroyContext(gdi_display
, odev
->ctx
);
256 This
->private = NULL
;
257 HeapFree(GetProcessHeap(),0,This
);
263 /*** IDirect3DDevice2 methods ***/
264 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_GetCaps(
265 LPDIRECT3DDEVICE2 iface
, LPD3DDEVICEDESC lpdescsoft
,
266 LPD3DDEVICEDESC lpdeschard
268 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
269 FIXME("(%p)->(%p,%p): stub\n", This
, lpdescsoft
, lpdeschard
);
270 fill_opengl_caps(lpdescsoft
, lpdeschard
);
274 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb
,
277 LPDDPIXELFORMAT pformat
;
279 /* Do the texture enumeration */
280 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
281 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
282 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
283 pformat
= &(sdesc
.ddpfPixelFormat
);
284 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
285 pformat
->dwFourCC
= 0;
287 TRACE("Enumerating GL_RGBA unpacked (32)\n");
288 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
289 pformat
->u1
.dwRGBBitCount
= 32;
290 pformat
->u2
.dwRBitMask
= 0xFF000000;
291 pformat
->u3
.dwGBitMask
= 0x00FF0000;
292 pformat
->u4
.dwBBitMask
= 0x0000FF00;
293 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
294 if (cb(&sdesc
, context
) == 0)
297 TRACE("Enumerating GL_RGB unpacked (24)\n");
298 pformat
->dwFlags
= DDPF_RGB
;
299 pformat
->u1
.dwRGBBitCount
= 24;
300 pformat
->u2
.dwRBitMask
= 0x00FF0000;
301 pformat
->u3
.dwGBitMask
= 0x0000FF00;
302 pformat
->u4
.dwBBitMask
= 0x000000FF;
303 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
304 if (cb(&sdesc
, context
) == 0)
307 #ifndef HAVE_BUGGY_MESAGL
308 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
309 so that future version will work great. */
310 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
311 pformat
->dwFlags
= DDPF_RGB
;
312 pformat
->u1
.dwRGBBitCount
= 16;
313 pformat
->u2
.dwRBitMask
= 0x0000F800;
314 pformat
->u3
.dwGBitMask
= 0x000007E0;
315 pformat
->u4
.dwBBitMask
= 0x0000001F;
316 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
317 if (cb(&sdesc
, context
) == 0)
320 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
321 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
322 pformat
->u1
.dwRGBBitCount
= 16;
323 pformat
->u2
.dwRBitMask
= 0x0000F800;
324 pformat
->u3
.dwGBitMask
= 0x000007C0;
325 pformat
->u4
.dwBBitMask
= 0x0000003E;
326 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
327 if (cb(&sdesc
, context
) == 0)
330 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
331 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
332 pformat
->u1
.dwRGBBitCount
= 16;
333 pformat
->u2
.dwRBitMask
= 0x0000F000;
334 pformat
->u3
.dwGBitMask
= 0x00000F00;
335 pformat
->u4
.dwBBitMask
= 0x000000F0;
336 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
337 if (cb(&sdesc
, context
) == 0)
340 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
341 pformat
->dwFlags
= DDPF_RGB
;
342 pformat
->u1
.dwRGBBitCount
= 8;
343 pformat
->u2
.dwRBitMask
= 0x0000F800;
344 pformat
->u3
.dwGBitMask
= 0x000007C0;
345 pformat
->u4
.dwBBitMask
= 0x0000003E;
346 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
347 if (cb(&sdesc
, context
) == 0)
351 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
352 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
353 pformat
->u1
.dwRGBBitCount
= 16;
354 pformat
->u2
.dwRBitMask
= 0x00007C00;
355 pformat
->u3
.dwGBitMask
= 0x000003E0;
356 pformat
->u4
.dwBBitMask
= 0x0000001F;
357 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
358 if (cb(&sdesc
, context
) == 0)
361 TRACE("Enumerating Paletted (8)\n");
362 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
363 pformat
->u1
.dwRGBBitCount
= 8;
364 pformat
->u2
.dwRBitMask
= 0x00000000;
365 pformat
->u3
.dwGBitMask
= 0x00000000;
366 pformat
->u4
.dwBBitMask
= 0x00000000;
367 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
368 if (cb(&sdesc
, context
) == 0)
371 TRACE("End of enumeration\n");
376 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_EnumTextureFormats(
377 LPDIRECT3DDEVICE2 iface
, LPD3DENUMTEXTUREFORMATSCALLBACK cb
, LPVOID context
379 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
380 FIXME("(%p)->(%p,%p): stub\n", This
, cb
, context
);
382 return enum_texture_format_OpenGL(cb
, context
);
385 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_BeginScene(
386 LPDIRECT3DDEVICE2 iface
388 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
390 FIXME("(%p)->(): stub\n", This
);
392 /* Here, we should get the DDraw surface and 'copy it' to the
393 OpenGL surface.... */
398 HRESULT WINAPI
MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface
) {
399 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
401 FIXME("(%p)->(): stub\n", This
);
403 /* No need to do anything here... */
408 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetRenderState(
409 LPDIRECT3DDEVICE2 iface
, D3DRENDERSTATETYPE dwRenderStateType
,
412 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
415 TRACE("(%p)->(%d,%ld)\n", This
, dwRenderStateType
, dwRenderState
);
417 /* Call the render state functions */
418 set_render_state(dwRenderStateType
, dwRenderState
, &(odev
->rs
));
423 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetLightState(
424 LPDIRECT3DDEVICE2 iface
, D3DLIGHTSTATETYPE dwLightStateType
,
427 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
428 FIXME("(%p)->(%d,%08lx): stub\n", This
, dwLightStateType
, dwLightState
);
430 switch (dwLightStateType
) {
431 case D3DLIGHTSTATE_MATERIAL
: { /* 1 */
432 IDirect3DMaterial2Impl
* mat
= (IDirect3DMaterial2Impl
*) dwLightState
;
439 TRACE("Zoups !!!\n");
443 case D3DLIGHTSTATE_AMBIENT
: { /* 2 */
446 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
447 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
448 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.0;
451 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, (float *) light
);
455 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
463 TRACE("Unexpected Light State Type\n");
464 return DDERR_INVALIDPARAMS
;
470 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetTransform(
471 LPDIRECT3DDEVICE2 iface
, D3DTRANSFORMSTATETYPE d3dts
,
474 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
477 FIXME("(%p)->(%d,%p): stub\n", This
, d3dts
, lpmatrix
);
481 /* Using a trial and failure approach, I found that the order of
482 Direct3D transformations that works best is :
484 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
486 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
487 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
489 If anyone has a good explanation of the three different matrices in
490 the SDK online documentation, feel free to point it to me. For example,
491 which matrices transform lights ? In OpenGL only the PROJECTION matrix
492 transform the lights, not the MODELVIEW. Using the matrix names, I
493 supposed that PROJECTION and VIEW (all 'camera' related names) do
494 transform lights, but WORLD do not. It may be wrong though... */
496 /* After reading through both OpenGL and Direct3D documentations, I
497 thought that D3D matrices were written in 'line major mode' transposed
498 from OpenGL's 'column major mode'. But I found out that a simple memcpy
499 works fine to transfer one matrix format to the other (it did not work
500 when transposing)....
503 1) are the documentations wrong
504 2) does the matrix work even if they are not read correctly
505 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
506 loading using glLoadMatrix ?
508 Anyway, I always use 'conv_mat' to transfer the matrices from one format
509 to the other so that if I ever find out that I need to transpose them, I
510 will able to do it quickly, only by changing the macro conv_mat. */
513 case D3DTRANSFORMSTATE_WORLD
: {
514 conv_mat(lpmatrix
, odev
->world_mat
);
515 glMatrixMode(GL_MODELVIEW
);
516 glLoadMatrixf((float *) odev
->world_mat
);
519 case D3DTRANSFORMSTATE_VIEW
: {
520 conv_mat(lpmatrix
, odev
->view_mat
);
521 glMatrixMode(GL_PROJECTION
);
522 glLoadMatrixf((float *) odev
->proj_mat
);
523 glMultMatrixf((float *) odev
->view_mat
);
526 case D3DTRANSFORMSTATE_PROJECTION
: {
527 conv_mat(lpmatrix
, odev
->proj_mat
);
528 glMatrixMode(GL_PROJECTION
);
529 glLoadMatrixf((float *) odev
->proj_mat
);
530 glMultMatrixf((float *) odev
->view_mat
);
540 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
541 /* Puts GL in the correct lighting mode */ \
542 if (odev->vt != d3dv) { \
543 if (odev->vt == D3DVT_TLVERTEX) { \
544 /* Need to put the correct transformation again */ \
545 glMatrixMode(GL_MODELVIEW); \
546 glLoadMatrixf((float *) odev->world_mat); \
547 glMatrixMode(GL_PROJECTION); \
548 glLoadMatrixf((float *) odev->proj_mat); \
549 glMultMatrixf((float *) odev->view_mat); \
554 TRACE("Standard Vertex\n"); \
555 glEnable(GL_LIGHTING); \
558 case D3DVT_LVERTEX: \
559 TRACE("Lighted Vertex\n"); \
560 glDisable(GL_LIGHTING); \
563 case D3DVT_TLVERTEX: { \
564 GLdouble height, width, minZ, maxZ; \
566 TRACE("Transformed - Lighted Vertex\n"); \
567 /* First, disable lighting */ \
568 glDisable(GL_LIGHTING); \
570 /* Then do not put any transformation matrixes */ \
571 glMatrixMode(GL_MODELVIEW); \
573 glMatrixMode(GL_PROJECTION); \
576 if (This->current_viewport == NULL) { \
577 ERR("No current viewport !\n"); \
578 /* Using standard values */ \
584 if (This->current_viewport->use_vp2) { \
585 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
586 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
587 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
588 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
590 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
591 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
592 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
593 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
597 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
601 ERR("Unhandled vertex type\n"); \
609 case D3DPT_POINTLIST: \
610 TRACE("Start POINTS\n"); \
611 glBegin(GL_POINTS); \
614 case D3DPT_LINELIST: \
615 TRACE("Start LINES\n"); \
619 case D3DPT_LINESTRIP: \
620 TRACE("Start LINE_STRIP\n"); \
621 glBegin(GL_LINE_STRIP); \
624 case D3DPT_TRIANGLELIST: \
625 TRACE("Start TRIANGLES\n"); \
626 glBegin(GL_TRIANGLES); \
629 case D3DPT_TRIANGLESTRIP: \
630 TRACE("Start TRIANGLE_STRIP\n"); \
631 glBegin(GL_TRIANGLE_STRIP); \
634 case D3DPT_TRIANGLEFAN: \
635 TRACE("Start TRIANGLE_FAN\n"); \
636 glBegin(GL_TRIANGLE_FAN); \
640 TRACE("Unhandled primitive\n"); \
644 /* Draw the primitives */ \
645 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
647 case D3DVT_VERTEX: { \
648 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
650 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz); \
651 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
652 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z); \
655 case D3DVT_LVERTEX: { \
656 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
657 DWORD col = vx->u4.color; \
659 glColor3f(((col >> 16) & 0xFF) / 255.0, \
660 ((col >> 8) & 0xFF) / 255.0, \
661 ((col >> 0) & 0xFF) / 255.0); \
662 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
663 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
664 vx->u1.x, vx->u2.y, vx->u3.z, \
665 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
668 case D3DVT_TLVERTEX: { \
669 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
670 DWORD col = vx->u5.color; \
672 glColor3f(((col >> 16) & 0xFF) / 255.0, \
673 ((col >> 8) & 0xFF) / 255.0, \
674 ((col >> 0) & 0xFF) / 255.0); \
675 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
676 if (vx->u4.rhw < 0.01) \
677 glVertex3f(vx->u1.sx, \
681 glVertex4f(vx->u1.sx / vx->u4.rhw, \
682 vx->u2.sy / vx->u4.rhw, \
683 vx->u3.sz / vx->u4.rhw, \
685 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
686 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
687 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
688 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
692 FIXME("Unhandled vertex type\n"); \
701 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_DrawPrimitive(
702 LPDIRECT3DDEVICE2 iface
, D3DPRIMITIVETYPE d3dp
, D3DVERTEXTYPE d3dv
,
703 LPVOID lpvertex
, DWORD vertcount
, DWORD dwFlags
705 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
709 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This
, d3dp
, d3dv
, lpvertex
, vertcount
, dwFlags
);
712 DRAW_PRIMITIVE(vertcount
, vx_index
);
718 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
719 LPDIRECT3DDEVICE2 iface
, D3DPRIMITIVETYPE d3dp
, D3DVERTEXTYPE d3dv
,
720 LPVOID lpvertex
, DWORD vertcount
, LPWORD lpindexes
, DWORD indexcount
,
723 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
727 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This
, d3dp
, d3dv
, lpvertex
, vertcount
, lpindexes
, indexcount
, dwFlags
);
730 DRAW_PRIMITIVE(indexcount
, lpindexes
[vx_index
]);
736 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
737 LPDIRECT3DDEVICE iface
, LPD3DEXECUTEBUFFERDESC lpDesc
,
738 LPDIRECT3DEXECUTEBUFFER
*lplpDirect3DExecuteBuffer
, IUnknown
*pUnkOuter
740 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
741 TRACE("(%p)->(%p,%p,%p)\n", This
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
742 *lplpDirect3DExecuteBuffer
= d3dexecutebuffer_create(This
, lpDesc
);
747 /*******************************************************************************
748 * OpenGL-specific IDirect3DDevice2
751 /*******************************************************************************
752 * OpenGL-specific VTable
755 ICOM_VTABLE(IDirect3DDevice2
) OpenGL_vtable
=
757 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
758 IDirect3DDevice2Impl_QueryInterface
,
759 IDirect3DDevice2Impl_AddRef
,
760 MESA_IDirect3DDevice2Impl_Release
,
761 /*** IDirect3DDevice2 methods ***/
762 MESA_IDirect3DDevice2Impl_GetCaps
,
763 IDirect3DDevice2Impl_SwapTextureHandles
,
764 IDirect3DDevice2Impl_GetStats
,
765 IDirect3DDevice2Impl_AddViewport
,
766 IDirect3DDevice2Impl_DeleteViewport
,
767 IDirect3DDevice2Impl_NextViewport
,
768 MESA_IDirect3DDevice2Impl_EnumTextureFormats
,
769 MESA_IDirect3DDevice2Impl_BeginScene
,
770 MESA_IDirect3DDevice2Impl_EndScene
,
771 IDirect3DDevice2Impl_GetDirect3D
,
773 /*** DrawPrimitive API ***/
774 IDirect3DDevice2Impl_SetCurrentViewport
,
775 IDirect3DDevice2Impl_GetCurrentViewport
,
777 IDirect3DDevice2Impl_SetRenderTarget
,
778 IDirect3DDevice2Impl_GetRenderTarget
,
780 IDirect3DDevice2Impl_Begin
,
781 IDirect3DDevice2Impl_BeginIndexed
,
782 IDirect3DDevice2Impl_Vertex
,
783 IDirect3DDevice2Impl_Index
,
784 IDirect3DDevice2Impl_End
,
786 IDirect3DDevice2Impl_GetRenderState
,
787 MESA_IDirect3DDevice2Impl_SetRenderState
,
788 IDirect3DDevice2Impl_GetLightState
,
789 MESA_IDirect3DDevice2Impl_SetLightState
,
790 MESA_IDirect3DDevice2Impl_SetTransform
,
791 IDirect3DDevice2Impl_GetTransform
,
792 IDirect3DDevice2Impl_MultiplyTransform
,
794 MESA_IDirect3DDevice2Impl_DrawPrimitive
,
795 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive
,
797 IDirect3DDevice2Impl_SetClipStatus
,
798 IDirect3DDevice2Impl_GetClipStatus
,
801 /*******************************************************************************
804 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
) {
807 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
809 fill_opengl_caps(&d1
, &d2
);
811 return cb((void*)&IID_D3DDEVICE_OpenGL
,"WINE Direct3D using OpenGL","direct3d",&d1
,&d2
,context
);
814 int is_OpenGL_dx3(REFCLSID rguid
, IDirectDrawSurfaceImpl
* surface
, IDirect3DDeviceImpl
** device
)
816 if (!memcmp(&IID_D3DDEVICE_OpenGL
,rguid
,sizeof(IID_D3DDEVICE_OpenGL
))) {
817 mesa_d3dd_private
*odev
;
818 int attributeList
[]={ GLX_RGBA
, GLX_DEPTH_SIZE
, 16, GLX_DOUBLEBUFFER
, None
};
821 *device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirect3DDeviceImpl
));
822 (*device
)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(mesa_d3dd_private
));
823 odev
= (mesa_d3dd_private
*)(*device
)->private;
825 ICOM_VTBL(*device
) = &OpenGL_vtable_dx3
;
826 (*device
)->d3d
= NULL
;
827 (*device
)->surface
= surface
;
829 (*device
)->viewport_list
= NULL
;
830 (*device
)->current_viewport
= NULL
;
832 (*device
)->set_context
= (void*)set_context
;
834 TRACE("OpenGL device created \n");
836 /* Create the OpenGL context */
837 /* First get the correct visual */
838 /* if (surface->s.backbuffer == NULL)
839 attributeList[3] = None; */
840 #if 0 /* non working currently */
842 xvis
= glXChooseVisual(gdi_display
,
843 DefaultScreen(gdi_display
),
846 ERR("No visual found !\n");
848 TRACE("Visual found\n");
849 /* Create the context */
850 odev
->ctx
= glXCreateContext(gdi_display
,
854 TRACE("Context created\n");
856 /* Now override the surface's Flip method (if in double buffering) */
857 surface
->s
.d3d_device
= (void *) odev
;
860 struct _surface_chain
*chain
= surface
->s
.chain
;
861 for (i
=0;i
<chain
->nrofsurfaces
;i
++)
862 if (chain
->surfaces
[i
]->s
.surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_FLIP
)
863 chain
->surfaces
[i
]->s
.d3d_device
= (void *) odev
;
866 odev
->rs
.src
= GL_ONE
;
867 odev
->rs
.dst
= GL_ZERO
;
868 odev
->rs
.mag
= GL_NEAREST
;
869 odev
->rs
.min
= GL_NEAREST
;
871 odev
->world_mat
= (LPD3DMATRIX
) &id_mat
;
872 odev
->view_mat
= (LPD3DMATRIX
) &id_mat
;
873 odev
->proj_mat
= (LPD3DMATRIX
) &id_mat
;
876 (*device
)->set_context(*device
);
877 glClearColor(0.0, 0.0, 0.0, 0.0);
878 glColor3f(1.0, 1.0, 1.0);
880 fill_device_capabilities((IDirectDrawImpl
*) surface
->ddraw_owner
);
885 /* This is not the OpenGL UID */
889 static ULONG WINAPI
MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface
)
891 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
892 FIXME("(%p)->() decrementing from %lu.\n", This
, This
->ref
);
894 if (!--(This
->ref
)) {
895 #if 0 /* broken for now */
898 glXDestroyContext(gdi_display
, odev
->ctx
);
901 This
->private = NULL
;
902 HeapFree(GetProcessHeap(),0,This
);
908 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_EnumTextureFormats(
909 LPDIRECT3DDEVICE iface
,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc
,
912 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
913 TRACE("(%p)->(%p,%p): stub\n", This
, lpd3dEnumTextureProc
, lpArg
);
915 return enum_texture_format_OpenGL(lpd3dEnumTextureProc
, lpArg
);
919 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface
)
921 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
922 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
924 FIXME("(%p)->(): stub\n", This
);
926 /* We get the pointer to the surface (should be done on flip) */
927 /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */
933 /* This is for the moment copy-pasted from IDirect3DDevice2...
934 Will make a common function ... */
935 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface
)
937 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
939 FIXME("(%p)->(): stub\n", This
);
941 /* No need to do anything here... */
946 /*******************************************************************************
947 * Direct3DDevice VTable
949 ICOM_VTABLE(IDirect3DDevice
) OpenGL_vtable_dx3
=
951 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
952 IDirect3DDeviceImpl_QueryInterface
,
953 IDirect3DDeviceImpl_AddRef
,
954 MESA_IDirect3DDeviceImpl_Release
,
955 IDirect3DDeviceImpl_Initialize
,
956 IDirect3DDeviceImpl_GetCaps
,
957 IDirect3DDeviceImpl_SwapTextureHandles
,
958 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer
,
959 IDirect3DDeviceImpl_GetStats
,
960 IDirect3DDeviceImpl_Execute
,
961 IDirect3DDeviceImpl_AddViewport
,
962 IDirect3DDeviceImpl_DeleteViewport
,
963 IDirect3DDeviceImpl_NextViewport
,
964 IDirect3DDeviceImpl_Pick
,
965 IDirect3DDeviceImpl_GetPickRecords
,
966 MESA_IDirect3DDeviceImpl_EnumTextureFormats
,
967 IDirect3DDeviceImpl_CreateMatrix
,
968 IDirect3DDeviceImpl_SetMatrix
,
969 IDirect3DDeviceImpl_GetMatrix
,
970 IDirect3DDeviceImpl_DeleteMatrix
,
971 MESA_IDirect3DDeviceImpl_BeginScene
,
972 MESA_IDirect3DDeviceImpl_EndScene
,
973 IDirect3DDeviceImpl_GetDirect3D
,