2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/obj_base.h"
31 #include "wine/debug.h"
33 #include "mesa_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
40 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
42 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
43 on Mesa's home page) or version 3.1b.
45 Version 3.1b2 should correct this bug */
46 #undef HAVE_BUGGY_MESAGL
48 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
50 #ifndef HAVE_GLEXT_PROTOTYPES
51 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
52 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
53 GLsizei width, GLenum format, GLenum type,
57 static const float id_mat[16] = {
64 /* retrieve the X display to use on a given DC */
65 inline static Display *get_display( HDC hdc )
68 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
70 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
71 sizeof(display), (LPSTR)&display )) display = NULL;
77 /* retrieve the X drawable to use on a given DC */
78 inline static Drawable get_drawable( HDC hdc )
81 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
83 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
84 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
90 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
92 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
94 glXSwapBuffers((Display*)display,(Drawable)drawable);
100 /*******************************************************************************
101 * OpenGL static functions
103 static void set_context(IDirect3DDevice2Impl* This) {
107 if (glXMakeCurrent(gdi_display,ddpriv->drawable, odev->ctx) == False) {
108 ERR("Error in setting current context (context %p drawable %ld)!\n",
109 odev->ctx, ddpriv->drawable);
115 TRACE("glxMakeCurrent %p, %ld, %p\n",odev->gdi_display,odev->drawable, odev->ctx);
116 if (glXMakeCurrent(odev->gdi_display,odev->drawable, odev->ctx) == False) {
117 ERR("Error in setting current context (context %p drawable %ld)!\n",
118 odev->ctx, odev->drawable);
123 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
125 pc->dwSize = sizeof(*pc);
126 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
127 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
128 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
129 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
130 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
131 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
132 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
133 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
134 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
135 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
136 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
137 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
138 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
139 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
140 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
141 pc->dwStippleWidth = 32;
142 pc->dwStippleHeight = 32;
145 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
147 /* GLint maxlight; */
149 d1->dwSize = sizeof(*d1);
150 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
151 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
152 d1->dcmColorModel = D3DCOLOR_RGB;
153 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
154 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
155 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
156 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
157 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
158 d1->bClipping = TRUE;
159 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
160 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
161 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
162 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
163 fill_opengl_primcaps(&(d1->dpcLineCaps));
164 fill_opengl_primcaps(&(d1->dpcTriCaps));
165 d1->dwDeviceRenderBitDepth = DDBD_16;
166 d1->dwDeviceZBufferBitDepth = DDBD_16;
167 d1->dwMaxBufferSize = 0;
168 d1->dwMaxVertexCount = 65536;
169 d1->dwMinTextureWidth = 1;
170 d1->dwMinTextureHeight = 1;
171 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
172 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
173 d1->dwMinStippleWidth = 1;
174 d1->dwMinStippleHeight = 1;
175 d1->dwMaxStippleWidth = 32;
176 d1->dwMaxStippleHeight = 32;
178 d2->dwSize = sizeof(*d2);
182 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
184 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
185 const char *ext_string;
186 Mesa_DeviceCapabilities *devcap;
188 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
189 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
192 ext_string = glGetString(GL_EXTENSIONS);
193 /* Query for the ColorTable Extension */
194 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
195 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
196 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
198 TRACE("Color table extension not found.\n");
204 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
206 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL));
207 fill_opengl_caps(&d1, &d2);
208 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context);
213 REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
214 IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
216 mesa_d3dd_private *odev = NULL;
220 XVisualInfo template;
221 IDirectDrawSurfaceImpl* surf;
223 TRACE("rguid = %s, surface = %p, &device = %p, d3d = %p\n",debugstr_guid(rguid),surface,device,d3d);
224 if (/* Default device */
227 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
229 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
231 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
232 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
233 odev = (mesa_d3dd_private*)(*device)->private;
235 ICOM_VTBL(*device) = &OpenGL_vtable;
236 (*device)->d3d = d3d;
237 (*device)->surface = surface;
238 (*device)->viewport_list = NULL;
239 (*device)->current_viewport = NULL;
240 (*device)->current_texture = NULL;
241 (*device)->set_context = set_context;
243 TRACE("Creating OpenGL device for surface %p\n", surface);
244 /* Create the OpenGL context */
245 /* First get the correct visual */
246 /* Create the context */
248 device_context = GetDC((*device)->surface->ddraw_owner->window);
249 odev->gdi_display = get_display(device_context);
250 odev->drawable = get_drawable(device_context);
251 ReleaseDC((*device)->surface->ddraw_owner->window,device_context);
254 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
255 vis = XGetVisualInfo(odev->gdi_display, VisualIDMask, &template, &num);
257 ERR("No visual found !\n");
259 TRACE("Visual found\n");
261 odev->ctx = glXCreateContext(odev->gdi_display, vis,
264 if (odev->ctx == NULL)
265 ERR("Error in context creation !\n");
267 TRACE("Context created (%p)\n", odev->ctx);
269 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
270 for (surf = surface; surf != NULL; surf = surf->surface_owner)
271 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
272 == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
274 surface->surface_owner->aux_ctx = (LPVOID)odev->gdi_display;
275 surface->surface_owner->aux_data = (LPVOID)odev->drawable;
276 surface->surface_owner->aux_flip = opengl_flip;
280 odev->rs.src = GL_ONE;
281 odev->rs.dst = GL_ZERO;
282 odev->rs.mag = GL_NEAREST;
283 odev->rs.min = GL_NEAREST;
286 /* Allocate memory for the matrices */
287 odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
288 odev->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
289 odev->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
291 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
292 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
293 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
296 TRACE("Setting current context\n");
298 (*device)->set_context(*device);
300 TRACE("Current context set\n");
301 glClearColor(0.0, 0.0, 0.0, 0.0);
302 glColor3f(1.0, 1.0, 1.0);
305 fill_device_capabilities(d3d->ddraw);
307 TRACE("OpenGL device created \n");
310 FIXME("bad IID %s\n",debugstr_guid(rguid));
311 /* This is not the OpenGL UID */
315 /*******************************************************************************
316 * MESA IDirect3DDevice2
318 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
320 ICOM_THIS(IDirect3DDevice2Impl,iface);
321 TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
323 if (!--(This->ref)) {
327 glXDestroyContext(odev->gdi_display, odev->ctx);
329 HeapFree(GetProcessHeap(),0,This->private);
330 HeapFree(GetProcessHeap(),0,This);
336 /*** IDirect3DDevice2 methods ***/
337 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
338 LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
339 LPD3DDEVICEDESC lpdeschard
341 ICOM_THIS(IDirect3DDevice2Impl,iface);
342 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
343 fill_opengl_caps(lpdescsoft, lpdeschard);
347 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
350 LPDDPIXELFORMAT pformat;
352 /* Do the texture enumeration */
353 sdesc.dwSize = sizeof(DDSURFACEDESC);
354 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
355 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
356 pformat = &(sdesc.ddpfPixelFormat);
357 pformat->dwSize = sizeof(DDPIXELFORMAT);
358 pformat->dwFourCC = 0;
360 TRACE("Enumerating GL_RGBA unpacked (32)\n");
361 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
362 pformat->u1.dwRGBBitCount = 32;
363 pformat->u2.dwRBitMask = 0xFF000000;
364 pformat->u3.dwGBitMask = 0x00FF0000;
365 pformat->u4.dwBBitMask = 0x0000FF00;
366 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
367 if (cb(&sdesc, context) == 0)
370 TRACE("Enumerating GL_RGB unpacked (24)\n");
371 pformat->dwFlags = DDPF_RGB;
372 pformat->u1.dwRGBBitCount = 24;
373 pformat->u2.dwRBitMask = 0x00FF0000;
374 pformat->u3.dwGBitMask = 0x0000FF00;
375 pformat->u4.dwBBitMask = 0x000000FF;
376 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
377 if (cb(&sdesc, context) == 0)
380 #ifndef HAVE_BUGGY_MESAGL
381 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
382 so that future version will work great. */
383 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
384 pformat->dwFlags = DDPF_RGB;
385 pformat->u1.dwRGBBitCount = 16;
386 pformat->u2.dwRBitMask = 0x0000F800;
387 pformat->u3.dwGBitMask = 0x000007E0;
388 pformat->u4.dwBBitMask = 0x0000001F;
389 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
390 if (cb(&sdesc, context) == 0)
393 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
394 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
395 pformat->u1.dwRGBBitCount = 16;
396 pformat->u2.dwRBitMask = 0x0000F800;
397 pformat->u3.dwGBitMask = 0x000007C0;
398 pformat->u4.dwBBitMask = 0x0000003E;
399 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
400 if (cb(&sdesc, context) == 0)
403 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
404 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
405 pformat->u1.dwRGBBitCount = 16;
406 pformat->u2.dwRBitMask = 0x0000F000;
407 pformat->u3.dwGBitMask = 0x00000F00;
408 pformat->u4.dwBBitMask = 0x000000F0;
409 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
410 if (cb(&sdesc, context) == 0)
413 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
414 pformat->dwFlags = DDPF_RGB;
415 pformat->u1.dwRGBBitCount = 8;
416 pformat->u2.dwRBitMask = 0x000000E0;
417 pformat->u3.dwGBitMask = 0x0000001C;
418 pformat->u4.dwBBitMask = 0x00000003;
419 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
420 if (cb(&sdesc, context) == 0)
424 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
425 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
426 pformat->u1.dwRGBBitCount = 16;
427 pformat->u2.dwRBitMask = 0x00007C00;
428 pformat->u3.dwGBitMask = 0x000003E0;
429 pformat->u4.dwBBitMask = 0x0000001F;
430 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
431 if (cb(&sdesc, context) == 0)
434 TRACE("Enumerating Paletted (8)\n");
435 pformat->dwFlags = DDPF_PALETTEINDEXED8;
436 pformat->u1.dwRGBBitCount = 8;
437 pformat->u2.dwRBitMask = 0x00000000;
438 pformat->u3.dwGBitMask = 0x00000000;
439 pformat->u4.dwBBitMask = 0x00000000;
440 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
441 if (cb(&sdesc, context) == 0)
444 TRACE("End of enumeration\n");
449 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
450 LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
452 ICOM_THIS(IDirect3DDevice2Impl,iface);
453 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
455 return enum_texture_format_OpenGL(cb, context);
458 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
459 LPDIRECT3DDEVICE2 iface
461 ICOM_THIS(IDirect3DDevice2Impl,iface);
463 FIXME("(%p)->(): stub\n", This);
465 /* Here, we should get the DDraw surface and 'copy it' to the
466 OpenGL surface.... */
471 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
472 ICOM_THIS(IDirect3DDevice2Impl,iface);
474 FIXME("(%p)->(): stub\n", This);
476 /* No need to do anything here... */
481 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
482 LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
485 ICOM_THIS(IDirect3DDevice2Impl,iface);
488 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
490 /* Call the render state functions */
491 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
496 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
497 LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
500 ICOM_THIS(IDirect3DDevice2Impl,iface);
501 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
503 switch (dwLightStateType) {
504 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
505 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
512 TRACE("Zoups !!!\n");
516 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
519 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
520 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
521 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
524 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
528 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
536 TRACE("Unexpected Light State Type\n");
537 return DDERR_INVALIDPARAMS;
543 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
544 LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
547 ICOM_THIS(IDirect3DDevice2Impl,iface);
550 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
554 /* Using a trial and failure approach, I found that the order of
555 Direct3D transformations that works best is :
557 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
559 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
560 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
562 If anyone has a good explanation of the three different matrices in
563 the SDK online documentation, feel free to point it to me. For example,
564 which matrices transform lights ? In OpenGL only the PROJECTION matrix
565 transform the lights, not the MODELVIEW. Using the matrix names, I
566 supposed that PROJECTION and VIEW (all 'camera' related names) do
567 transform lights, but WORLD do not. It may be wrong though... */
569 /* After reading through both OpenGL and Direct3D documentations, I
570 thought that D3D matrices were written in 'line major mode' transposed
571 from OpenGL's 'column major mode'. But I found out that a simple memcpy
572 works fine to transfer one matrix format to the other (it did not work
573 when transposing)....
576 1) are the documentations wrong
577 2) does the matrix work even if they are not read correctly
578 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
579 loading using glLoadMatrix ?
581 Anyway, I always use 'conv_mat' to transfer the matrices from one format
582 to the other so that if I ever find out that I need to transpose them, I
583 will able to do it quickly, only by changing the macro conv_mat. */
586 case D3DTRANSFORMSTATE_WORLD: {
587 conv_mat(lpmatrix, odev->world_mat);
588 glMatrixMode(GL_MODELVIEW);
589 glLoadMatrixf((float *) odev->world_mat);
592 case D3DTRANSFORMSTATE_VIEW: {
593 conv_mat(lpmatrix, odev->view_mat);
594 glMatrixMode(GL_PROJECTION);
595 glLoadMatrixf((float *) odev->proj_mat);
596 glMultMatrixf((float *) odev->view_mat);
599 case D3DTRANSFORMSTATE_PROJECTION: {
600 conv_mat(lpmatrix, odev->proj_mat);
601 glMatrixMode(GL_PROJECTION);
602 glLoadMatrixf((float *) odev->proj_mat);
603 glMultMatrixf((float *) odev->view_mat);
613 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
614 /* Puts GL in the correct lighting mode */ \
615 if (odev->vt != d3dv) { \
616 if (odev->vt == D3DVT_TLVERTEX) { \
617 /* Need to put the correct transformation again */ \
618 glMatrixMode(GL_MODELVIEW); \
619 glLoadMatrixf((float *) odev->world_mat); \
620 glMatrixMode(GL_PROJECTION); \
621 glLoadMatrixf((float *) odev->proj_mat); \
622 glMultMatrixf((float *) odev->view_mat); \
627 TRACE("Standard Vertex\n"); \
628 glEnable(GL_LIGHTING); \
631 case D3DVT_LVERTEX: \
632 TRACE("Lighted Vertex\n"); \
633 glDisable(GL_LIGHTING); \
636 case D3DVT_TLVERTEX: { \
637 GLdouble height, width, minZ, maxZ; \
639 TRACE("Transformed - Lighted Vertex\n"); \
640 /* First, disable lighting */ \
641 glDisable(GL_LIGHTING); \
643 /* Then do not put any transformation matrixes */ \
644 glMatrixMode(GL_MODELVIEW); \
646 glMatrixMode(GL_PROJECTION); \
649 if (This->current_viewport == NULL) { \
650 ERR("No current viewport !\n"); \
651 /* Using standard values */ \
657 if (This->current_viewport->use_vp2) { \
658 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
659 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
660 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
661 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
663 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
664 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
665 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
666 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
670 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
674 ERR("Unhandled vertex type\n"); \
682 case D3DPT_POINTLIST: \
683 TRACE("Start POINTS\n"); \
684 glBegin(GL_POINTS); \
687 case D3DPT_LINELIST: \
688 TRACE("Start LINES\n"); \
692 case D3DPT_LINESTRIP: \
693 TRACE("Start LINE_STRIP\n"); \
694 glBegin(GL_LINE_STRIP); \
697 case D3DPT_TRIANGLELIST: \
698 TRACE("Start TRIANGLES\n"); \
699 glBegin(GL_TRIANGLES); \
702 case D3DPT_TRIANGLESTRIP: \
703 TRACE("Start TRIANGLE_STRIP\n"); \
704 glBegin(GL_TRIANGLE_STRIP); \
707 case D3DPT_TRIANGLEFAN: \
708 TRACE("Start TRIANGLE_FAN\n"); \
709 glBegin(GL_TRIANGLE_FAN); \
713 TRACE("Unhandled primitive\n"); \
717 /* Draw the primitives */ \
718 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
720 case D3DVT_VERTEX: { \
721 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
723 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz); \
724 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
725 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z); \
728 case D3DVT_LVERTEX: { \
729 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
730 DWORD col = vx->u4.color; \
732 glColor3f(((col >> 16) & 0xFF) / 255.0, \
733 ((col >> 8) & 0xFF) / 255.0, \
734 ((col >> 0) & 0xFF) / 255.0); \
735 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
736 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
737 vx->u1.x, vx->u2.y, vx->u3.z, \
738 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
741 case D3DVT_TLVERTEX: { \
742 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
743 DWORD col = vx->u5.color; \
745 glColor3f(((col >> 16) & 0xFF) / 255.0, \
746 ((col >> 8) & 0xFF) / 255.0, \
747 ((col >> 0) & 0xFF) / 255.0); \
748 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
749 if (vx->u4.rhw < 0.01) \
750 glVertex3f(vx->u1.sx, \
754 glVertex4f(vx->u1.sx / vx->u4.rhw, \
755 vx->u2.sy / vx->u4.rhw, \
756 vx->u3.sz / vx->u4.rhw, \
758 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
759 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
760 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
761 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
765 FIXME("Unhandled vertex type\n"); \
774 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
775 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
776 LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
778 ICOM_THIS(IDirect3DDevice2Impl,iface);
782 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
785 DRAW_PRIMITIVE(vertcount, vx_index);
791 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
792 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
793 LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
796 ICOM_THIS(IDirect3DDevice2Impl,iface);
800 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
803 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
809 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
810 LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
811 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
813 ICOM_THIS(IDirect3DDeviceImpl,iface);
814 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
815 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
820 /*******************************************************************************
821 * OpenGL-specific IDirect3DDevice2
824 /*******************************************************************************
825 * OpenGL-specific VTable
828 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
830 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
831 IDirect3DDevice2Impl_QueryInterface,
832 IDirect3DDevice2Impl_AddRef,
833 MESA_IDirect3DDevice2Impl_Release,
834 /*** IDirect3DDevice2 methods ***/
835 MESA_IDirect3DDevice2Impl_GetCaps,
836 IDirect3DDevice2Impl_SwapTextureHandles,
837 IDirect3DDevice2Impl_GetStats,
838 IDirect3DDevice2Impl_AddViewport,
839 IDirect3DDevice2Impl_DeleteViewport,
840 IDirect3DDevice2Impl_NextViewport,
841 MESA_IDirect3DDevice2Impl_EnumTextureFormats,
842 MESA_IDirect3DDevice2Impl_BeginScene,
843 MESA_IDirect3DDevice2Impl_EndScene,
844 IDirect3DDevice2Impl_GetDirect3D,
846 /*** DrawPrimitive API ***/
847 IDirect3DDevice2Impl_SetCurrentViewport,
848 IDirect3DDevice2Impl_GetCurrentViewport,
850 IDirect3DDevice2Impl_SetRenderTarget,
851 IDirect3DDevice2Impl_GetRenderTarget,
853 IDirect3DDevice2Impl_Begin,
854 IDirect3DDevice2Impl_BeginIndexed,
855 IDirect3DDevice2Impl_Vertex,
856 IDirect3DDevice2Impl_Index,
857 IDirect3DDevice2Impl_End,
859 IDirect3DDevice2Impl_GetRenderState,
860 MESA_IDirect3DDevice2Impl_SetRenderState,
861 IDirect3DDevice2Impl_GetLightState,
862 MESA_IDirect3DDevice2Impl_SetLightState,
863 MESA_IDirect3DDevice2Impl_SetTransform,
864 IDirect3DDevice2Impl_GetTransform,
865 IDirect3DDevice2Impl_MultiplyTransform,
867 MESA_IDirect3DDevice2Impl_DrawPrimitive,
868 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
870 IDirect3DDevice2Impl_SetClipStatus,
871 IDirect3DDevice2Impl_GetClipStatus,
874 /*******************************************************************************
877 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
880 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
882 fill_opengl_caps(&d1, &d2);
884 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
887 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
889 TRACE("rguid = %s, surface = %p, &device = %p\n",debugstr_guid(rguid),surface,device);
890 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
891 mesa_d3dd_private *odev;
893 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
895 IDirectDrawSurfaceImpl* surf;
897 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
898 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
899 odev = (mesa_d3dd_private*)(*device)->private;
901 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
902 (*device)->d3d = NULL;
903 (*device)->surface = surface;
905 (*device)->viewport_list = NULL;
906 (*device)->current_viewport = NULL;
907 (*device)->current_texture = NULL;
909 (*device)->set_context = (void*)set_context;
911 TRACE("OpenGL device created \n");
913 /* Create the OpenGL context */
914 /* First get the correct visual */
915 /* if (surface->s.backbuffer == NULL)
916 attributeList[3] = None; */
917 device_context = GetDC((*device)->surface->ddraw_owner->window);
918 odev->gdi_display = get_display(device_context);
919 odev->drawable = get_drawable(device_context);
920 ReleaseDC((*device)->surface->ddraw_owner->window,device_context);
922 xvis = glXChooseVisual(odev->gdi_display,
923 DefaultScreen(odev->gdi_display),
926 ERR("No visual found !\n");
928 TRACE("Visual found\n");
930 /* Create the context */
931 odev->ctx = glXCreateContext(odev->gdi_display,
935 TRACE("Context created\n");
937 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
938 for (surf = surface; surf != NULL; surf = surf->surface_owner)
939 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
940 == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
942 surface->surface_owner->aux_ctx = (LPVOID)odev->gdi_display;
943 surface->surface_owner->aux_data = (LPVOID)odev->drawable;
944 surface->surface_owner->aux_flip = opengl_flip;
948 odev->rs.src = GL_ONE;
949 odev->rs.dst = GL_ZERO;
950 odev->rs.mag = GL_NEAREST;
951 odev->rs.min = GL_NEAREST;
953 odev->world_mat = (LPD3DMATRIX) &id_mat;
954 odev->view_mat = (LPD3DMATRIX) &id_mat;
955 odev->proj_mat = (LPD3DMATRIX) &id_mat;
959 (*device)->set_context(*device);
961 glClearColor(0.0, 0.0, 0.0, 0.0);
962 glColor3f(1.0, 1.0, 1.0);
964 fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner);
969 /* This is not the OpenGL UID */
973 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
975 ICOM_THIS(IDirect3DDeviceImpl,iface);
976 TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
978 if (!--(This->ref)) {
981 glXDestroyContext(odev->gdi_display, odev->ctx);
983 HeapFree(GetProcessHeap(),0,This->private);
984 HeapFree(GetProcessHeap(),0,This);
990 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
991 LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
994 ICOM_THIS(IDirect3DDeviceImpl,iface);
995 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
997 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
1001 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
1003 ICOM_THIS(IDirect3DDeviceImpl,iface);
1004 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
1006 FIXME("(%p)->(): stub\n", This);
1008 /* We get the pointer to the surface (should be done on flip) */
1009 /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */
1015 /* This is for the moment copy-pasted from IDirect3DDevice2...
1016 Will make a common function ... */
1017 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
1019 ICOM_THIS(IDirect3DDeviceImpl,iface);
1021 FIXME("(%p)->(): stub\n", This);
1023 /* No need to do anything here... */
1028 /*******************************************************************************
1029 * Direct3DDevice VTable
1031 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
1033 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1034 IDirect3DDeviceImpl_QueryInterface,
1035 IDirect3DDeviceImpl_AddRef,
1036 MESA_IDirect3DDeviceImpl_Release,
1037 IDirect3DDeviceImpl_Initialize,
1038 IDirect3DDeviceImpl_GetCaps,
1039 IDirect3DDeviceImpl_SwapTextureHandles,
1040 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
1041 IDirect3DDeviceImpl_GetStats,
1042 IDirect3DDeviceImpl_Execute,
1043 IDirect3DDeviceImpl_AddViewport,
1044 IDirect3DDeviceImpl_DeleteViewport,
1045 IDirect3DDeviceImpl_NextViewport,
1046 IDirect3DDeviceImpl_Pick,
1047 IDirect3DDeviceImpl_GetPickRecords,
1048 MESA_IDirect3DDeviceImpl_EnumTextureFormats,
1049 IDirect3DDeviceImpl_CreateMatrix,
1050 IDirect3DDeviceImpl_SetMatrix,
1051 IDirect3DDeviceImpl_GetMatrix,
1052 IDirect3DDeviceImpl_DeleteMatrix,
1053 MESA_IDirect3DDeviceImpl_BeginScene,
1054 MESA_IDirect3DDeviceImpl_EndScene,
1055 IDirect3DDeviceImpl_GetDirect3D,