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 static const float id_mat
[16] = {
40 /*******************************************************************************
41 * OpenGL static functions
43 static void set_context(IDirect3DDevice2Impl
* This
) {
45 DDPRIVATE(This
->surface
->s
.ddraw
);
48 OSMesaMakeCurrent(d3ddpriv
->ctx
, odev
->buffer
, GL_UNSIGNED_BYTE
,
49 This
->surface
->s
.surface_desc
.dwWidth
,
50 This
->surface
->s
.surface_desc
.dwHeight
);
52 if (glXMakeCurrent(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
) {
119 x11_dd_private
*private = (x11_dd_private
*) ddraw
->private;
120 const char *ext_string
;
121 Mesa_DeviceCapabilities
*devcap
;
123 private->device_capabilities
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Mesa_DeviceCapabilities
));
124 devcap
= (Mesa_DeviceCapabilities
*) private->device_capabilities
;
127 ext_string
= glGetString(GL_EXTENSIONS
);
128 /* Query for the ColorTable Extension */
129 if (strstr(ext_string
, "GL_EXT_paletted_texture")) {
130 devcap
->ptr_ColorTableEXT
= (PFNGLCOLORTABLEEXTPROC
) glXGetProcAddressARB("glColorTableEXT");
131 TRACE("Color table extension supported (function at %p)\n", devcap
->ptr_ColorTableEXT
);
133 TRACE("Color table extension not found.\n");
138 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
) {
140 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL
));
141 fill_opengl_caps(&d1
, &d2
);
142 return cb((void*)&IID_D3DDEVICE2_OpenGL
,"WINE Direct3D2 using OpenGL","direct3d",&d1
,&d2
,context
);
147 REFCLSID rguid
, IDirectDrawSurfaceImpl
* surface
,
148 IDirect3DDevice2Impl
** device
, IDirect3D2Impl
* d3d
150 mesa_d3dd_private
*odev
= NULL
;
152 if (/* Default device */
155 (!memcmp(&IID_IDirect3DHALDevice
,rguid
,sizeof(IID_IDirect3DHALDevice
))) ||
157 (!memcmp(&IID_D3DDEVICE2_OpenGL
,rguid
,sizeof(IID_D3DDEVICE2_OpenGL
)))) {
159 *device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirect3DDevice2Impl
));
160 (*device
)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(mesa_d3dd_private
));
161 odev
= (mesa_d3dd_private
*)(*device
)->private;
163 ICOM_VTBL(*device
) = &OpenGL_vtable
;
164 (*device
)->d3d
= d3d
;
165 (*device
)->surface
= surface
;
166 (*device
)->viewport_list
= NULL
;
167 (*device
)->current_viewport
= NULL
;
168 (*device
)->set_context
= set_context
;
170 TRACE("Creating OpenGL device for surface %p\n", surface
);
171 /* Create the OpenGL context */
173 odev
->ctx
= OSMesaCreateContext(OSMESA_RGBA
, NULL
);
174 odev
->buffer
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
175 surface
->s
.surface_desc
.dwWidth
* surface
->s
.surface_desc
.dwHeight
* 4);
177 /* First get the correct visual */
179 /* Create the context */
183 XVisualInfo
template;
185 template.visualid
= XVisualIDFromVisual(visual
);
186 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
188 odev
->ctx
= glXCreateContext(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
);
248 FIXME("(%p)->() decrementing from %lu.\n", This
, This
->ref
);
250 if (!--(This
->ref
)) {
252 OSMesaDestroyContext(odev
->ctx
);
255 glXDestroyContext(display
, odev
->ctx
);
258 This
->private = NULL
;
259 HeapFree(GetProcessHeap(),0,This
);
265 /*** IDirect3DDevice2 methods ***/
266 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_GetCaps(
267 LPDIRECT3DDEVICE2 iface
, LPD3DDEVICEDESC lpdescsoft
,
268 LPD3DDEVICEDESC lpdeschard
270 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
271 FIXME("(%p)->(%p,%p): stub\n", This
, lpdescsoft
, lpdeschard
);
272 fill_opengl_caps(lpdescsoft
, lpdeschard
);
276 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb
,
279 LPDDPIXELFORMAT pformat
;
281 /* Do the texture enumeration */
282 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
283 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
284 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
285 pformat
= &(sdesc
.ddpfPixelFormat
);
286 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
287 pformat
->dwFourCC
= 0;
289 TRACE("Enumerating GL_RGBA unpacked (32)\n");
290 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
291 pformat
->u
.dwRGBBitCount
= 32;
292 pformat
->u1
.dwRBitMask
= 0xFF000000;
293 pformat
->u2
.dwGBitMask
= 0x00FF0000;
294 pformat
->u3
.dwBBitMask
= 0x0000FF00;
295 pformat
->u4
.dwRGBAlphaBitMask
= 0x000000FF;
296 if (cb(&sdesc
, context
) == 0)
299 TRACE("Enumerating GL_RGB unpacked (24)\n");
300 pformat
->dwFlags
= DDPF_RGB
;
301 pformat
->u
.dwRGBBitCount
= 24;
302 pformat
->u1
.dwRBitMask
= 0x00FF0000;
303 pformat
->u2
.dwGBitMask
= 0x0000FF00;
304 pformat
->u3
.dwBBitMask
= 0x000000FF;
305 pformat
->u4
.dwRGBAlphaBitMask
= 0x00000000;
306 if (cb(&sdesc
, context
) == 0)
309 #ifndef HAVE_BUGGY_MESAGL
310 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
311 so that future version will work great. */
312 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
313 pformat
->dwFlags
= DDPF_RGB
;
314 pformat
->u
.dwRGBBitCount
= 16;
315 pformat
->u1
.dwRBitMask
= 0x0000F800;
316 pformat
->u2
.dwGBitMask
= 0x000007E0;
317 pformat
->u3
.dwBBitMask
= 0x0000001F;
318 pformat
->u4
.dwRGBAlphaBitMask
= 0x00000000;
319 if (cb(&sdesc
, context
) == 0)
322 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
323 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
324 pformat
->u
.dwRGBBitCount
= 16;
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)
332 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
333 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
334 pformat
->u
.dwRGBBitCount
= 16;
335 pformat
->u1
.dwRBitMask
= 0x0000F000;
336 pformat
->u2
.dwGBitMask
= 0x00000F00;
337 pformat
->u3
.dwBBitMask
= 0x000000F0;
338 pformat
->u4
.dwRGBAlphaBitMask
= 0x0000000F;
339 if (cb(&sdesc
, context
) == 0)
342 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
343 pformat
->dwFlags
= DDPF_RGB
;
344 pformat
->u
.dwRGBBitCount
= 8;
345 pformat
->u1
.dwRBitMask
= 0x0000F800;
346 pformat
->u2
.dwGBitMask
= 0x000007C0;
347 pformat
->u3
.dwBBitMask
= 0x0000003E;
348 pformat
->u4
.dwRGBAlphaBitMask
= 0x00000001;
349 if (cb(&sdesc
, context
) == 0)
353 TRACE("Enumerating Paletted (8)\n");
354 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
355 pformat
->u
.dwRGBBitCount
= 8;
356 pformat
->u1
.dwRBitMask
= 0x00000000;
357 pformat
->u2
.dwGBitMask
= 0x00000000;
358 pformat
->u3
.dwBBitMask
= 0x00000000;
359 pformat
->u4
.dwRGBAlphaBitMask
= 0x00000000;
360 if (cb(&sdesc
, context
) == 0)
363 TRACE("End of enumeration\n");
368 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_EnumTextureFormats(
369 LPDIRECT3DDEVICE2 iface
, LPD3DENUMTEXTUREFORMATSCALLBACK cb
, LPVOID context
371 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
372 FIXME("(%p)->(%p,%p): stub\n", This
, cb
, context
);
374 return enum_texture_format_OpenGL(cb
, context
);
377 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_BeginScene(
378 LPDIRECT3DDEVICE2 iface
380 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
382 FIXME("(%p)->(): stub\n", This
);
384 /* Here, we should get the DDraw surface and 'copy it' to the
385 OpenGL surface.... */
390 HRESULT WINAPI
MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface
) {
391 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
395 LPDIRECTDRAWSURFACE3 surf
= (LPDIRECTDRAWSURFACE3
) This
->surface
;
399 unsigned short *dest
;
402 FIXME("(%p)->(): stub\n", This
);
405 /* Here we copy back the OpenGL scene to the the DDraw surface */
406 /* First, lock the surface */
407 IDirectDrawSurface3_Lock(surf
,NULL
,&sdesc
,DDLOCK_WRITEONLY
,0);
409 /* The copy the OpenGL buffer to this surface */
411 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
412 I am currently working on a set of patches for Mesa to have OSMesa support
413 16 bpp surfaces => we will able to render directly onto the surface, no
414 need to do a bpp conversion */
415 dest
= (unsigned short *) sdesc
.y
.lpSurface
;
416 src
= ((unsigned char *) odev
->buffer
) + 4 * (sdesc
.dwWidth
* (sdesc
.dwHeight
- 1));
417 for (y
= 0; y
< sdesc
.dwHeight
; y
++) {
418 unsigned char *lsrc
= src
;
420 for (x
= 0; x
< sdesc
.dwWidth
; x
++) {
421 unsigned char r
= *lsrc
++;
422 unsigned char g
= *lsrc
++;
423 unsigned char b
= *lsrc
++;
425 *dest
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
430 src
-= 4 * sdesc
.dwWidth
;
433 /* Unlock the surface */
434 IDirectDrawSurface3_Unlock(surf
,sdesc
.y
.lpSurface
);
436 /* No need to do anything here... */
442 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetRenderState(
443 LPDIRECT3DDEVICE2 iface
, D3DRENDERSTATETYPE dwRenderStateType
,
446 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
449 TRACE("(%p)->(%d,%ld)\n", This
, dwRenderStateType
, dwRenderState
);
451 /* Call the render state functions */
452 set_render_state(dwRenderStateType
, dwRenderState
, &(odev
->rs
));
457 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetLightState(
458 LPDIRECT3DDEVICE2 iface
, D3DLIGHTSTATETYPE dwLightStateType
,
461 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
462 FIXME("(%p)->(%d,%08lx): stub\n", This
, dwLightStateType
, dwLightState
);
464 switch (dwLightStateType
) {
465 case D3DLIGHTSTATE_MATERIAL
: { /* 1 */
466 IDirect3DMaterial2Impl
* mat
= (IDirect3DMaterial2Impl
*) dwLightState
;
473 TRACE("Zoups !!!\n");
477 case D3DLIGHTSTATE_AMBIENT
: { /* 2 */
480 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
481 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
482 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.0;
485 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, (float *) light
);
489 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
497 TRACE("Unexpected Light State Type\n");
498 return DDERR_INVALIDPARAMS
;
504 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_SetTransform(
505 LPDIRECT3DDEVICE2 iface
, D3DTRANSFORMSTATETYPE d3dts
,
508 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
511 FIXME("(%p)->(%d,%p): stub\n", This
, d3dts
, lpmatrix
);
515 /* Using a trial and failure approach, I found that the order of
516 Direct3D transformations that works best is :
518 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
520 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
521 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
523 If anyone has a good explanation of the three different matrices in
524 the SDK online documentation, feel free to point it to me. For example,
525 which matrices transform lights ? In OpenGL only the PROJECTION matrix
526 transform the lights, not the MODELVIEW. Using the matrix names, I
527 supposed that PROJECTION and VIEW (all 'camera' related names) do
528 transform lights, but WORLD do not. It may be wrong though... */
530 /* After reading through both OpenGL and Direct3D documentations, I
531 thought that D3D matrices were written in 'line major mode' transposed
532 from OpenGL's 'column major mode'. But I found out that a simple memcpy
533 works fine to transfer one matrix format to the other (it did not work
534 when transposing)....
537 1) are the documentations wrong
538 2) does the matrix work even if they are not read correctly
539 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
540 loading using glLoadMatrix ?
542 Anyway, I always use 'conv_mat' to transfer the matrices from one format
543 to the other so that if I ever find out that I need to transpose them, I
544 will able to do it quickly, only by changing the macro conv_mat. */
547 case D3DTRANSFORMSTATE_WORLD
: {
548 conv_mat(lpmatrix
, odev
->world_mat
);
549 glMatrixMode(GL_MODELVIEW
);
550 glLoadMatrixf((float *) odev
->world_mat
);
553 case D3DTRANSFORMSTATE_VIEW
: {
554 conv_mat(lpmatrix
, odev
->view_mat
);
555 glMatrixMode(GL_PROJECTION
);
556 glLoadMatrixf((float *) odev
->proj_mat
);
557 glMultMatrixf((float *) odev
->view_mat
);
560 case D3DTRANSFORMSTATE_PROJECTION
: {
561 conv_mat(lpmatrix
, odev
->proj_mat
);
562 glMatrixMode(GL_PROJECTION
);
563 glLoadMatrixf((float *) odev
->proj_mat
);
564 glMultMatrixf((float *) odev
->view_mat
);
574 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
575 /* Puts GL in the correct lighting mode */ \
576 if (odev->vt != d3dv) { \
577 if (odev->vt == D3DVT_TLVERTEX) { \
578 /* Need to put the correct transformation again */ \
579 glMatrixMode(GL_MODELVIEW); \
580 glLoadMatrixf((float *) odev->world_mat); \
581 glMatrixMode(GL_PROJECTION); \
582 glLoadMatrixf((float *) odev->proj_mat); \
583 glMultMatrixf((float *) odev->view_mat); \
588 TRACE("Standard Vertex\n"); \
589 glEnable(GL_LIGHTING); \
592 case D3DVT_LVERTEX: \
593 TRACE("Lighted Vertex\n"); \
594 glDisable(GL_LIGHTING); \
597 case D3DVT_TLVERTEX: { \
598 GLdouble height, width, minZ, maxZ; \
600 TRACE("Transformed - Lighted Vertex\n"); \
601 /* First, disable lighting */ \
602 glDisable(GL_LIGHTING); \
604 /* Then do not put any transformation matrixes */ \
605 glMatrixMode(GL_MODELVIEW); \
607 glMatrixMode(GL_PROJECTION); \
610 if (This->current_viewport == NULL) { \
611 ERR("No current viewport !\n"); \
612 /* Using standard values */ \
618 if (This->current_viewport->use_vp2) { \
619 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
620 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
621 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
622 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
624 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
625 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
626 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
627 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
631 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
635 ERR("Unhandled vertex type\n"); \
643 case D3DPT_POINTLIST: \
644 TRACE("Start POINTS\n"); \
645 glBegin(GL_POINTS); \
648 case D3DPT_LINELIST: \
649 TRACE("Start LINES\n"); \
653 case D3DPT_LINESTRIP: \
654 TRACE("Start LINE_STRIP\n"); \
655 glBegin(GL_LINE_STRIP); \
658 case D3DPT_TRIANGLELIST: \
659 TRACE("Start TRIANGLES\n"); \
660 glBegin(GL_TRIANGLES); \
663 case D3DPT_TRIANGLESTRIP: \
664 TRACE("Start TRIANGLE_STRIP\n"); \
665 glBegin(GL_TRIANGLE_STRIP); \
668 case D3DPT_TRIANGLEFAN: \
669 TRACE("Start TRIANGLE_FAN\n"); \
670 glBegin(GL_TRIANGLE_FAN); \
674 TRACE("Unhandled primitive\n"); \
678 /* Draw the primitives */ \
679 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
681 case D3DVT_VERTEX: { \
682 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
684 glNormal3f(vx->nx.nx, vx->ny.ny, vx->nz.nz); \
685 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
686 TRACE(" V: %f %f %f\n", vx->x.x, vx->y.y, vx->z.z); \
689 case D3DVT_LVERTEX: { \
690 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
691 DWORD col = vx->c.color; \
693 glColor3f(((col >> 16) & 0xFF) / 255.0, \
694 ((col >> 8) & 0xFF) / 255.0, \
695 ((col >> 0) & 0xFF) / 255.0); \
696 glVertex3f(vx->x.x, vx->y.y, vx->z.z); \
697 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
698 vx->x.x, vx->y.y, vx->z.z, \
699 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
702 case D3DVT_TLVERTEX: { \
703 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
704 DWORD col = vx->c.color; \
706 glColor3f(((col >> 16) & 0xFF) / 255.0, \
707 ((col >> 8) & 0xFF) / 255.0, \
708 ((col >> 0) & 0xFF) / 255.0); \
709 glTexCoord2f(vx->u.tu, vx->v.tv); \
710 if (vx->r.rhw < 0.01) \
711 glVertex3f(vx->x.sx, \
715 glVertex4f(vx->x.sx / vx->r.rhw, \
716 vx->y.sy / vx->r.rhw, \
717 vx->z.sz / vx->r.rhw, \
719 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
720 vx->x.sx, vx->y.sy, vx->z.sz, \
721 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
722 vx->u.tu, vx->v.tv, vx->r.rhw); \
726 FIXME("Unhandled vertex type\n"); \
735 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_DrawPrimitive(
736 LPDIRECT3DDEVICE2 iface
, D3DPRIMITIVETYPE d3dp
, D3DVERTEXTYPE d3dv
,
737 LPVOID lpvertex
, DWORD vertcount
, DWORD dwFlags
739 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
743 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This
, d3dp
, d3dv
, lpvertex
, vertcount
, dwFlags
);
746 DRAW_PRIMITIVE(vertcount
, vx_index
);
752 static HRESULT WINAPI
MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
753 LPDIRECT3DDEVICE2 iface
, D3DPRIMITIVETYPE d3dp
, D3DVERTEXTYPE d3dv
,
754 LPVOID lpvertex
, DWORD vertcount
, LPWORD lpindexes
, DWORD indexcount
,
757 ICOM_THIS(IDirect3DDevice2Impl
,iface
);
761 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This
, d3dp
, d3dv
, lpvertex
, vertcount
, lpindexes
, indexcount
, dwFlags
);
764 DRAW_PRIMITIVE(indexcount
, lpindexes
[vx_index
]);
770 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
771 LPDIRECT3DDEVICE iface
, LPD3DEXECUTEBUFFERDESC lpDesc
,
772 LPDIRECT3DEXECUTEBUFFER
*lplpDirect3DExecuteBuffer
, IUnknown
*pUnkOuter
774 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
775 TRACE("(%p)->(%p,%p,%p)\n", This
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
776 *lplpDirect3DExecuteBuffer
= d3dexecutebuffer_create(This
, lpDesc
);
781 /*******************************************************************************
782 * OpenGL-specific IDirect3DDevice2
785 /*******************************************************************************
786 * OpenGL-specific VTable
789 ICOM_VTABLE(IDirect3DDevice2
) OpenGL_vtable
=
791 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
792 IDirect3DDevice2Impl_QueryInterface
,
793 IDirect3DDevice2Impl_AddRef
,
794 MESA_IDirect3DDevice2Impl_Release
,
795 /*** IDirect3DDevice2 methods ***/
796 MESA_IDirect3DDevice2Impl_GetCaps
,
797 IDirect3DDevice2Impl_SwapTextureHandles
,
798 IDirect3DDevice2Impl_GetStats
,
799 IDirect3DDevice2Impl_AddViewport
,
800 IDirect3DDevice2Impl_DeleteViewport
,
801 IDirect3DDevice2Impl_NextViewport
,
802 MESA_IDirect3DDevice2Impl_EnumTextureFormats
,
803 MESA_IDirect3DDevice2Impl_BeginScene
,
804 MESA_IDirect3DDevice2Impl_EndScene
,
805 IDirect3DDevice2Impl_GetDirect3D
,
807 /*** DrawPrimitive API ***/
808 IDirect3DDevice2Impl_SetCurrentViewport
,
809 IDirect3DDevice2Impl_GetCurrentViewport
,
811 IDirect3DDevice2Impl_SetRenderTarget
,
812 IDirect3DDevice2Impl_GetRenderTarget
,
814 IDirect3DDevice2Impl_Begin
,
815 IDirect3DDevice2Impl_BeginIndexed
,
816 IDirect3DDevice2Impl_Vertex
,
817 IDirect3DDevice2Impl_Index
,
818 IDirect3DDevice2Impl_End
,
820 IDirect3DDevice2Impl_GetRenderState
,
821 MESA_IDirect3DDevice2Impl_SetRenderState
,
822 IDirect3DDevice2Impl_GetLightState
,
823 MESA_IDirect3DDevice2Impl_SetLightState
,
824 MESA_IDirect3DDevice2Impl_SetTransform
,
825 IDirect3DDevice2Impl_GetTransform
,
826 IDirect3DDevice2Impl_MultiplyTransform
,
828 MESA_IDirect3DDevice2Impl_DrawPrimitive
,
829 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive
,
831 IDirect3DDevice2Impl_SetClipStatus
,
832 IDirect3DDevice2Impl_GetClipStatus
,
835 /*******************************************************************************
838 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
) {
841 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
843 fill_opengl_caps(&d1
, &d2
);
845 return cb((void*)&IID_D3DDEVICE_OpenGL
,"WINE Direct3D using OpenGL","direct3d",&d1
,&d2
,context
);
848 int is_OpenGL_dx3(REFCLSID rguid
, IDirectDrawSurfaceImpl
* surface
, IDirect3DDeviceImpl
** device
)
850 if (!memcmp(&IID_D3DDEVICE_OpenGL
,rguid
,sizeof(IID_D3DDEVICE_OpenGL
))) {
851 mesa_d3dd_private
*odev
;
853 int attributeList
[]={ GLX_RGBA
, GLX_DEPTH_SIZE
, 16, GLX_DOUBLEBUFFER
, None
};
857 *device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirect3DDeviceImpl
));
858 (*device
)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(mesa_d3dd_private
));
859 odev
= (mesa_d3dd_private
*)(*device
)->private;
861 ICOM_VTBL(*device
) = &OpenGL_vtable_dx3
;
862 (*device
)->d3d
= NULL
;
863 (*device
)->surface
= surface
;
865 (*device
)->viewport_list
= NULL
;
866 (*device
)->current_viewport
= NULL
;
868 (*device
)->set_context
= (void*)set_context
;
870 TRACE("OpenGL device created \n");
872 /* Create the OpenGL context */
874 odev
->ctx
= OSMesaCreateContext(OSMESA_RGBA
, NULL
);
875 odev
->buffer
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
876 surface
->s
.surface_desc
.dwWidth
* surface
->s
.surface_desc
.dwHeight
* 4);
878 /* First get the correct visual */
879 /* if (surface->s.backbuffer == NULL)
880 attributeList[3] = None; */
882 xvis
= glXChooseVisual(display
,
883 DefaultScreen(display
),
886 ERR("No visual found !\n");
888 TRACE("Visual found\n");
889 /* Create the context */
890 odev
->ctx
= glXCreateContext(display
,
894 TRACE("Context created\n");
896 #if 0 /* non working currently */
897 /* Now override the surface's Flip method (if in double buffering) */
898 surface
->s
.d3d_device
= (void *) odev
;
901 struct _surface_chain
*chain
= surface
->s
.chain
;
902 for (i
=0;i
<chain
->nrofsurfaces
;i
++)
903 if (chain
->surfaces
[i
]->s
.surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_FLIP
)
904 chain
->surfaces
[i
]->s
.d3d_device
= (void *) odev
;
908 odev
->rs
.src
= GL_ONE
;
909 odev
->rs
.dst
= GL_ZERO
;
910 odev
->rs
.mag
= GL_NEAREST
;
911 odev
->rs
.min
= GL_NEAREST
;
913 odev
->world_mat
= (LPD3DMATRIX
) &id_mat
;
914 odev
->view_mat
= (LPD3DMATRIX
) &id_mat
;
915 odev
->proj_mat
= (LPD3DMATRIX
) &id_mat
;
918 (*device
)->set_context(*device
);
919 glClearColor(0.0, 0.0, 0.0, 0.0);
920 glColor3f(1.0, 1.0, 1.0);
922 fill_device_capabilities((IDirectDrawImpl
*) surface
->s
.ddraw
);
927 /* This is not the OpenGL UID */
931 static ULONG WINAPI
MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface
)
933 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
934 FIXME("(%p)->() decrementing from %lu.\n", This
, This
->ref
);
936 if (!--(This
->ref
)) {
939 OSMesaDestroyContext(odev
->ctx
);
942 glXDestroyContext(display
, odev
->ctx
);
945 This
->private = NULL
;
946 HeapFree(GetProcessHeap(),0,This
);
952 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_EnumTextureFormats(
953 LPDIRECT3DDEVICE iface
,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc
,
956 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
957 TRACE("(%p)->(%p,%p): stub\n", This
, lpd3dEnumTextureProc
, lpArg
);
959 return enum_texture_format_OpenGL(lpd3dEnumTextureProc
, lpArg
);
963 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface
)
965 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
966 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
968 FIXME("(%p)->(): stub\n", This
);
970 /* We get the pointer to the surface (should be done on flip) */
971 /* odev->zb->pbuf = This->surface->s.surface_desc.y.lpSurface; */
977 /* This is for the moment copy-pasted from IDirect3DDevice2...
978 Will make a common function ... */
979 static HRESULT WINAPI
MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface
)
981 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
984 LPDIRECTDRAWSURFACE3 surf
= (LPDIRECTDRAWSURFACE3
) This
->surface
;
988 unsigned short *dest
;
991 FIXME("(%p)->(): stub\n", This
);
994 /* Here we copy back the OpenGL scene to the the DDraw surface */
995 /* First, lock the surface */
996 IDirectDrawSurface3_Lock(surf
,NULL
,&sdesc
,DDLOCK_WRITEONLY
,0);
998 /* The copy the OpenGL buffer to this surface */
1000 /* NOTE : this is only for debugging purpose. I KNOW it is really unoptimal.
1001 I am currently working on a set of patches for Mesa to have OSMesa support
1002 16 bpp surfaces => we will able to render directly onto the surface, no
1003 need to do a bpp conversion */
1004 dest
= (unsigned short *) sdesc
.y
.lpSurface
;
1005 src
= ((unsigned char *) odev
->buffer
) + 4 * (sdesc
.dwWidth
* (sdesc
.dwHeight
- 1));
1006 for (y
= 0; y
< sdesc
.dwHeight
; y
++) {
1007 unsigned char *lsrc
= src
;
1009 for (x
= 0; x
< sdesc
.dwWidth
; x
++) {
1010 unsigned char r
= *lsrc
++;
1011 unsigned char g
= *lsrc
++;
1012 unsigned char b
= *lsrc
++;
1015 *dest
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
1020 src
-= 4 * sdesc
.dwWidth
;
1023 /* Unlock the surface */
1024 IDirectDrawSurface3_Unlock(surf
,sdesc
.y
.lpSurface
);
1026 /* No need to do anything here... */
1032 /*******************************************************************************
1033 * Direct3DDevice VTable
1035 ICOM_VTABLE(IDirect3DDevice
) OpenGL_vtable_dx3
=
1037 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1038 IDirect3DDeviceImpl_QueryInterface
,
1039 IDirect3DDeviceImpl_AddRef
,
1040 MESA_IDirect3DDeviceImpl_Release
,
1041 IDirect3DDeviceImpl_Initialize
,
1042 IDirect3DDeviceImpl_GetCaps
,
1043 IDirect3DDeviceImpl_SwapTextureHandles
,
1044 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer
,
1045 IDirect3DDeviceImpl_GetStats
,
1046 IDirect3DDeviceImpl_Execute
,
1047 IDirect3DDeviceImpl_AddViewport
,
1048 IDirect3DDeviceImpl_DeleteViewport
,
1049 IDirect3DDeviceImpl_NextViewport
,
1050 IDirect3DDeviceImpl_Pick
,
1051 IDirect3DDeviceImpl_GetPickRecords
,
1052 MESA_IDirect3DDeviceImpl_EnumTextureFormats
,
1053 IDirect3DDeviceImpl_CreateMatrix
,
1054 IDirect3DDeviceImpl_SetMatrix
,
1055 IDirect3DDeviceImpl_GetMatrix
,
1056 IDirect3DDeviceImpl_DeleteMatrix
,
1057 MESA_IDirect3DDeviceImpl_BeginScene
,
1058 MESA_IDirect3DDeviceImpl_EndScene
,
1059 IDirect3DDeviceImpl_GetDirect3D
,