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"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable;
38 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3;
40 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
41 on Mesa's home page) or version 3.1b.
43 Version 3.1b2 should correct this bug */
44 #undef HAVE_BUGGY_MESAGL
46 #define D3DDPRIVATE(x) mesa_d3dd_private *odev=((mesa_d3dd_private*)x->private)
48 #ifndef HAVE_GLEXT_PROTOTYPES
49 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
50 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
51 GLsizei width, GLenum format, GLenum type,
55 static const float id_mat[16] = {
62 /*******************************************************************************
63 * OpenGL static functions
65 static void set_context(IDirect3DDevice2Impl* This) {
69 if (glXMakeCurrent(gdi_display,ddpriv->drawable, odev->ctx) == False) {
70 ERR("Error in setting current context (context %p drawable %ld)!\n",
71 odev->ctx, ddpriv->drawable);
76 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
78 pc->dwSize = sizeof(*pc);
79 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
80 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
81 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
82 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
83 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
84 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
85 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
86 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
87 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
88 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
89 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
90 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
91 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
92 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
93 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
94 pc->dwStippleWidth = 32;
95 pc->dwStippleHeight = 32;
98 static void fill_opengl_caps(D3DDEVICEDESC *d1, D3DDEVICEDESC *d2)
100 /* GLint maxlight; */
102 d1->dwSize = sizeof(*d1);
103 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
104 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
105 d1->dcmColorModel = D3DCOLOR_RGB;
106 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
107 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
108 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
109 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
110 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
111 d1->bClipping = TRUE;
112 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
113 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
114 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
115 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
116 fill_opengl_primcaps(&(d1->dpcLineCaps));
117 fill_opengl_primcaps(&(d1->dpcTriCaps));
118 d1->dwDeviceRenderBitDepth = DDBD_16;
119 d1->dwDeviceZBufferBitDepth = DDBD_16;
120 d1->dwMaxBufferSize = 0;
121 d1->dwMaxVertexCount = 65536;
122 d1->dwMinTextureWidth = 1;
123 d1->dwMinTextureHeight = 1;
124 d1->dwMaxTextureWidth = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
125 d1->dwMaxTextureHeight = 256; /* This is for Mesa on top of Glide (in the future :-) ) */
126 d1->dwMinStippleWidth = 1;
127 d1->dwMinStippleHeight = 1;
128 d1->dwMaxStippleWidth = 32;
129 d1->dwMaxStippleHeight = 32;
131 d2->dwSize = sizeof(*d2);
135 static void fill_device_capabilities(IDirectDrawImpl* ddraw) {
137 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
138 const char *ext_string;
139 Mesa_DeviceCapabilities *devcap;
141 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
142 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
145 ext_string = glGetString(GL_EXTENSIONS);
146 /* Query for the ColorTable Extension */
147 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
148 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
149 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
151 TRACE("Color table extension not found.\n");
157 int d3d_OpenGL(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
159 TRACE(" Enumerating OpenGL D3D2 device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE2_OpenGL));
160 fill_opengl_caps(&d1, &d2);
161 return cb((void*)&IID_D3DDEVICE2_OpenGL,"WINE Direct3D2 using OpenGL","direct3d",&d1,&d2,context);
166 REFCLSID rguid, IDirectDrawSurfaceImpl* surface,
167 IDirect3DDevice2Impl** device, IDirect3D2Impl* d3d
169 mesa_d3dd_private *odev = NULL;
171 if (/* Default device */
174 (!memcmp(&IID_IDirect3DHALDevice,rguid,sizeof(IID_IDirect3DHALDevice))) ||
176 (!memcmp(&IID_D3DDEVICE2_OpenGL,rguid,sizeof(IID_D3DDEVICE2_OpenGL)))) {
178 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDevice2Impl));
179 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
180 odev = (mesa_d3dd_private*)(*device)->private;
182 ICOM_VTBL(*device) = &OpenGL_vtable;
183 (*device)->d3d = d3d;
184 (*device)->surface = surface;
185 (*device)->viewport_list = NULL;
186 (*device)->current_viewport = NULL;
187 (*device)->set_context = set_context;
189 TRACE("Creating OpenGL device for surface %p\n", surface);
190 /* Create the OpenGL context */
192 /* First get the correct visual */
194 /* Create the context */
198 XVisualInfo template;
200 template.visualid = XVisualIDFromVisual(visual);
201 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
203 odev->ctx = glXCreateContext(gdi_display, vis,
207 if (odev->ctx == NULL)
208 ERR("Error in context creation !\n");
210 TRACE("Context created (%p)\n", odev->ctx);
212 /* Now override the surface's Flip method (if in double buffering) */
213 ((x11_ds_private *) surface->private)->opengl_flip = TRUE;
216 struct _surface_chain *chain = surface->s.chain;
217 for (i=0;i<chain->nrofsurfaces;i++)
218 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
219 ((x11_ds_private *) chain->surfaces[i]->private)->opengl_flip = TRUE;
223 odev->rs.src = GL_ONE;
224 odev->rs.dst = GL_ZERO;
225 odev->rs.mag = GL_NEAREST;
226 odev->rs.min = GL_NEAREST;
229 /* Allocate memory for the matrices */
230 odev->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
231 odev->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
232 odev->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
234 memcpy(odev->world_mat, id_mat, 16 * sizeof(float));
235 memcpy(odev->view_mat , id_mat, 16 * sizeof(float));
236 memcpy(odev->proj_mat , id_mat, 16 * sizeof(float));
239 TRACE("Setting current context\n");
240 (*device)->set_context(*device);
241 TRACE("Current context set\n");
242 glClearColor(0.0, 0.0, 0.0, 0.0);
243 glColor3f(1.0, 1.0, 1.0);
246 fill_device_capabilities(d3d->ddraw);
248 TRACE("OpenGL device created \n");
251 FIXME("bad IID %s\n",debugstr_guid(rguid));
252 /* This is not the OpenGL UID */
256 /*******************************************************************************
257 * MESA IDirect3DDevice2
259 static ULONG WINAPI MESA_IDirect3DDevice2Impl_Release(LPDIRECT3DDEVICE2 iface)
261 ICOM_THIS(IDirect3DDevice2Impl,iface);
262 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
264 if (!--(This->ref)) {
265 #if 0 /* broken for now */
268 glXDestroyContext(gdi_display, odev->ctx);
271 This->private = NULL;
272 HeapFree(GetProcessHeap(),0,This);
278 /*** IDirect3DDevice2 methods ***/
279 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_GetCaps(
280 LPDIRECT3DDEVICE2 iface, LPD3DDEVICEDESC lpdescsoft,
281 LPD3DDEVICEDESC lpdeschard
283 ICOM_THIS(IDirect3DDevice2Impl,iface);
284 FIXME("(%p)->(%p,%p): stub\n", This, lpdescsoft, lpdeschard);
285 fill_opengl_caps(lpdescsoft, lpdeschard);
289 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb,
292 LPDDPIXELFORMAT pformat;
294 /* Do the texture enumeration */
295 sdesc.dwSize = sizeof(DDSURFACEDESC);
296 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
297 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
298 pformat = &(sdesc.ddpfPixelFormat);
299 pformat->dwSize = sizeof(DDPIXELFORMAT);
300 pformat->dwFourCC = 0;
302 TRACE("Enumerating GL_RGBA unpacked (32)\n");
303 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
304 pformat->u1.dwRGBBitCount = 32;
305 pformat->u2.dwRBitMask = 0xFF000000;
306 pformat->u3.dwGBitMask = 0x00FF0000;
307 pformat->u4.dwBBitMask = 0x0000FF00;
308 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
309 if (cb(&sdesc, context) == 0)
312 TRACE("Enumerating GL_RGB unpacked (24)\n");
313 pformat->dwFlags = DDPF_RGB;
314 pformat->u1.dwRGBBitCount = 24;
315 pformat->u2.dwRBitMask = 0x00FF0000;
316 pformat->u3.dwGBitMask = 0x0000FF00;
317 pformat->u4.dwBBitMask = 0x000000FF;
318 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
319 if (cb(&sdesc, context) == 0)
322 #ifndef HAVE_BUGGY_MESAGL
323 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
324 so that future version will work great. */
325 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
326 pformat->dwFlags = DDPF_RGB;
327 pformat->u1.dwRGBBitCount = 16;
328 pformat->u2.dwRBitMask = 0x0000F800;
329 pformat->u3.dwGBitMask = 0x000007E0;
330 pformat->u4.dwBBitMask = 0x0000001F;
331 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
332 if (cb(&sdesc, context) == 0)
335 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
336 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
337 pformat->u1.dwRGBBitCount = 16;
338 pformat->u2.dwRBitMask = 0x0000F800;
339 pformat->u3.dwGBitMask = 0x000007C0;
340 pformat->u4.dwBBitMask = 0x0000003E;
341 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
342 if (cb(&sdesc, context) == 0)
345 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
346 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
347 pformat->u1.dwRGBBitCount = 16;
348 pformat->u2.dwRBitMask = 0x0000F000;
349 pformat->u3.dwGBitMask = 0x00000F00;
350 pformat->u4.dwBBitMask = 0x000000F0;
351 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
352 if (cb(&sdesc, context) == 0)
355 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
356 pformat->dwFlags = DDPF_RGB;
357 pformat->u1.dwRGBBitCount = 8;
358 pformat->u2.dwRBitMask = 0x0000F800;
359 pformat->u3.dwGBitMask = 0x000007C0;
360 pformat->u4.dwBBitMask = 0x0000003E;
361 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
362 if (cb(&sdesc, context) == 0)
366 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
367 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
368 pformat->u1.dwRGBBitCount = 16;
369 pformat->u2.dwRBitMask = 0x00007C00;
370 pformat->u3.dwGBitMask = 0x000003E0;
371 pformat->u4.dwBBitMask = 0x0000001F;
372 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
373 if (cb(&sdesc, context) == 0)
376 TRACE("Enumerating Paletted (8)\n");
377 pformat->dwFlags = DDPF_PALETTEINDEXED8;
378 pformat->u1.dwRGBBitCount = 8;
379 pformat->u2.dwRBitMask = 0x00000000;
380 pformat->u3.dwGBitMask = 0x00000000;
381 pformat->u4.dwBBitMask = 0x00000000;
382 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
383 if (cb(&sdesc, context) == 0)
386 TRACE("End of enumeration\n");
391 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_EnumTextureFormats(
392 LPDIRECT3DDEVICE2 iface, LPD3DENUMTEXTUREFORMATSCALLBACK cb, LPVOID context
394 ICOM_THIS(IDirect3DDevice2Impl,iface);
395 FIXME("(%p)->(%p,%p): stub\n", This, cb, context);
397 return enum_texture_format_OpenGL(cb, context);
400 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_BeginScene(
401 LPDIRECT3DDEVICE2 iface
403 ICOM_THIS(IDirect3DDevice2Impl,iface);
405 FIXME("(%p)->(): stub\n", This);
407 /* Here, we should get the DDraw surface and 'copy it' to the
408 OpenGL surface.... */
413 HRESULT WINAPI MESA_IDirect3DDevice2Impl_EndScene(LPDIRECT3DDEVICE2 iface) {
414 ICOM_THIS(IDirect3DDevice2Impl,iface);
416 FIXME("(%p)->(): stub\n", This);
418 /* No need to do anything here... */
423 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetRenderState(
424 LPDIRECT3DDEVICE2 iface, D3DRENDERSTATETYPE dwRenderStateType,
427 ICOM_THIS(IDirect3DDevice2Impl,iface);
430 TRACE("(%p)->(%d,%ld)\n", This, dwRenderStateType, dwRenderState);
432 /* Call the render state functions */
433 set_render_state(dwRenderStateType, dwRenderState, &(odev->rs));
438 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetLightState(
439 LPDIRECT3DDEVICE2 iface, D3DLIGHTSTATETYPE dwLightStateType,
442 ICOM_THIS(IDirect3DDevice2Impl,iface);
443 FIXME("(%p)->(%d,%08lx): stub\n", This, dwLightStateType, dwLightState);
445 switch (dwLightStateType) {
446 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
447 IDirect3DMaterial2Impl* mat = (IDirect3DMaterial2Impl*) dwLightState;
454 TRACE("Zoups !!!\n");
458 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
461 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
462 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
463 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
466 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
470 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
478 TRACE("Unexpected Light State Type\n");
479 return DDERR_INVALIDPARAMS;
485 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_SetTransform(
486 LPDIRECT3DDEVICE2 iface, D3DTRANSFORMSTATETYPE d3dts,
489 ICOM_THIS(IDirect3DDevice2Impl,iface);
492 FIXME("(%p)->(%d,%p): stub\n", This, d3dts, lpmatrix);
496 /* Using a trial and failure approach, I found that the order of
497 Direct3D transformations that works best is :
499 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
501 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
502 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
504 If anyone has a good explanation of the three different matrices in
505 the SDK online documentation, feel free to point it to me. For example,
506 which matrices transform lights ? In OpenGL only the PROJECTION matrix
507 transform the lights, not the MODELVIEW. Using the matrix names, I
508 supposed that PROJECTION and VIEW (all 'camera' related names) do
509 transform lights, but WORLD do not. It may be wrong though... */
511 /* After reading through both OpenGL and Direct3D documentations, I
512 thought that D3D matrices were written in 'line major mode' transposed
513 from OpenGL's 'column major mode'. But I found out that a simple memcpy
514 works fine to transfer one matrix format to the other (it did not work
515 when transposing)....
518 1) are the documentations wrong
519 2) does the matrix work even if they are not read correctly
520 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
521 loading using glLoadMatrix ?
523 Anyway, I always use 'conv_mat' to transfer the matrices from one format
524 to the other so that if I ever find out that I need to transpose them, I
525 will able to do it quickly, only by changing the macro conv_mat. */
528 case D3DTRANSFORMSTATE_WORLD: {
529 conv_mat(lpmatrix, odev->world_mat);
530 glMatrixMode(GL_MODELVIEW);
531 glLoadMatrixf((float *) odev->world_mat);
534 case D3DTRANSFORMSTATE_VIEW: {
535 conv_mat(lpmatrix, odev->view_mat);
536 glMatrixMode(GL_PROJECTION);
537 glLoadMatrixf((float *) odev->proj_mat);
538 glMultMatrixf((float *) odev->view_mat);
541 case D3DTRANSFORMSTATE_PROJECTION: {
542 conv_mat(lpmatrix, odev->proj_mat);
543 glMatrixMode(GL_PROJECTION);
544 glLoadMatrixf((float *) odev->proj_mat);
545 glMultMatrixf((float *) odev->view_mat);
555 #define DRAW_PRIMITIVE(MAXVERT,INDEX) \
556 /* Puts GL in the correct lighting mode */ \
557 if (odev->vt != d3dv) { \
558 if (odev->vt == D3DVT_TLVERTEX) { \
559 /* Need to put the correct transformation again */ \
560 glMatrixMode(GL_MODELVIEW); \
561 glLoadMatrixf((float *) odev->world_mat); \
562 glMatrixMode(GL_PROJECTION); \
563 glLoadMatrixf((float *) odev->proj_mat); \
564 glMultMatrixf((float *) odev->view_mat); \
569 TRACE("Standard Vertex\n"); \
570 glEnable(GL_LIGHTING); \
573 case D3DVT_LVERTEX: \
574 TRACE("Lighted Vertex\n"); \
575 glDisable(GL_LIGHTING); \
578 case D3DVT_TLVERTEX: { \
579 GLdouble height, width, minZ, maxZ; \
581 TRACE("Transformed - Lighted Vertex\n"); \
582 /* First, disable lighting */ \
583 glDisable(GL_LIGHTING); \
585 /* Then do not put any transformation matrixes */ \
586 glMatrixMode(GL_MODELVIEW); \
588 glMatrixMode(GL_PROJECTION); \
591 if (This->current_viewport == NULL) { \
592 ERR("No current viewport !\n"); \
593 /* Using standard values */ \
599 if (This->current_viewport->use_vp2) { \
600 height = (GLdouble) This->current_viewport->viewport.vp2.dwHeight;\
601 width = (GLdouble) This->current_viewport->viewport.vp2.dwWidth;\
602 minZ = (GLdouble) This->current_viewport->viewport.vp2.dvMinZ;\
603 maxZ = (GLdouble) This->current_viewport->viewport.vp2.dvMaxZ;\
605 height = (GLdouble) This->current_viewport->viewport.vp1.dwHeight;\
606 width = (GLdouble) This->current_viewport->viewport.vp1.dwWidth;\
607 minZ = (GLdouble) This->current_viewport->viewport.vp1.dvMinZ;\
608 maxZ = (GLdouble) This->current_viewport->viewport.vp1.dvMaxZ;\
612 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ); \
616 ERR("Unhandled vertex type\n"); \
624 case D3DPT_POINTLIST: \
625 TRACE("Start POINTS\n"); \
626 glBegin(GL_POINTS); \
629 case D3DPT_LINELIST: \
630 TRACE("Start LINES\n"); \
634 case D3DPT_LINESTRIP: \
635 TRACE("Start LINE_STRIP\n"); \
636 glBegin(GL_LINE_STRIP); \
639 case D3DPT_TRIANGLELIST: \
640 TRACE("Start TRIANGLES\n"); \
641 glBegin(GL_TRIANGLES); \
644 case D3DPT_TRIANGLESTRIP: \
645 TRACE("Start TRIANGLE_STRIP\n"); \
646 glBegin(GL_TRIANGLE_STRIP); \
649 case D3DPT_TRIANGLEFAN: \
650 TRACE("Start TRIANGLE_FAN\n"); \
651 glBegin(GL_TRIANGLE_FAN); \
655 TRACE("Unhandled primitive\n"); \
659 /* Draw the primitives */ \
660 for (vx_index = 0; vx_index < MAXVERT; vx_index++) { \
662 case D3DVT_VERTEX: { \
663 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + INDEX; \
665 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz); \
666 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
667 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z); \
670 case D3DVT_LVERTEX: { \
671 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + INDEX; \
672 DWORD col = vx->u4.color; \
674 glColor3f(((col >> 16) & 0xFF) / 255.0, \
675 ((col >> 8) & 0xFF) / 255.0, \
676 ((col >> 0) & 0xFF) / 255.0); \
677 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z); \
678 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n", \
679 vx->u1.x, vx->u2.y, vx->u3.z, \
680 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));\
683 case D3DVT_TLVERTEX: { \
684 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + INDEX; \
685 DWORD col = vx->u5.color; \
687 glColor3f(((col >> 16) & 0xFF) / 255.0, \
688 ((col >> 8) & 0xFF) / 255.0, \
689 ((col >> 0) & 0xFF) / 255.0); \
690 glTexCoord2f(vx->u7.tu, vx->u8.tv); \
691 if (vx->u4.rhw < 0.01) \
692 glVertex3f(vx->u1.sx, \
696 glVertex4f(vx->u1.sx / vx->u4.rhw, \
697 vx->u2.sy / vx->u4.rhw, \
698 vx->u3.sz / vx->u4.rhw, \
700 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n", \
701 vx->u1.sx, vx->u2.sy, vx->u3.sz, \
702 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),\
703 vx->u7.tu, vx->u8.tv, vx->u4.rhw); \
707 FIXME("Unhandled vertex type\n"); \
716 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawPrimitive(
717 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
718 LPVOID lpvertex, DWORD vertcount, DWORD dwFlags
720 ICOM_THIS(IDirect3DDevice2Impl,iface);
724 TRACE("(%p)->(%d,%d,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, dwFlags);
727 DRAW_PRIMITIVE(vertcount, vx_index);
733 static HRESULT WINAPI MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive(
734 LPDIRECT3DDEVICE2 iface, D3DPRIMITIVETYPE d3dp, D3DVERTEXTYPE d3dv,
735 LPVOID lpvertex, DWORD vertcount, LPWORD lpindexes, DWORD indexcount,
738 ICOM_THIS(IDirect3DDevice2Impl,iface);
742 TRACE("(%p)->(%d,%d,%p,%ld,%p,%ld,%08lx): stub\n", This, d3dp, d3dv, lpvertex, vertcount, lpindexes, indexcount, dwFlags);
745 DRAW_PRIMITIVE(indexcount, lpindexes[vx_index]);
751 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_CreateExecuteBuffer(
752 LPDIRECT3DDEVICE iface, LPD3DEXECUTEBUFFERDESC lpDesc,
753 LPDIRECT3DEXECUTEBUFFER *lplpDirect3DExecuteBuffer, IUnknown *pUnkOuter
755 ICOM_THIS(IDirect3DDeviceImpl,iface);
756 TRACE("(%p)->(%p,%p,%p)\n", This, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
757 *lplpDirect3DExecuteBuffer = d3dexecutebuffer_create(This, lpDesc);
762 /*******************************************************************************
763 * OpenGL-specific IDirect3DDevice2
766 /*******************************************************************************
767 * OpenGL-specific VTable
770 ICOM_VTABLE(IDirect3DDevice2) OpenGL_vtable =
772 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
773 IDirect3DDevice2Impl_QueryInterface,
774 IDirect3DDevice2Impl_AddRef,
775 MESA_IDirect3DDevice2Impl_Release,
776 /*** IDirect3DDevice2 methods ***/
777 MESA_IDirect3DDevice2Impl_GetCaps,
778 IDirect3DDevice2Impl_SwapTextureHandles,
779 IDirect3DDevice2Impl_GetStats,
780 IDirect3DDevice2Impl_AddViewport,
781 IDirect3DDevice2Impl_DeleteViewport,
782 IDirect3DDevice2Impl_NextViewport,
783 MESA_IDirect3DDevice2Impl_EnumTextureFormats,
784 MESA_IDirect3DDevice2Impl_BeginScene,
785 MESA_IDirect3DDevice2Impl_EndScene,
786 IDirect3DDevice2Impl_GetDirect3D,
788 /*** DrawPrimitive API ***/
789 IDirect3DDevice2Impl_SetCurrentViewport,
790 IDirect3DDevice2Impl_GetCurrentViewport,
792 IDirect3DDevice2Impl_SetRenderTarget,
793 IDirect3DDevice2Impl_GetRenderTarget,
795 IDirect3DDevice2Impl_Begin,
796 IDirect3DDevice2Impl_BeginIndexed,
797 IDirect3DDevice2Impl_Vertex,
798 IDirect3DDevice2Impl_Index,
799 IDirect3DDevice2Impl_End,
801 IDirect3DDevice2Impl_GetRenderState,
802 MESA_IDirect3DDevice2Impl_SetRenderState,
803 IDirect3DDevice2Impl_GetLightState,
804 MESA_IDirect3DDevice2Impl_SetLightState,
805 MESA_IDirect3DDevice2Impl_SetTransform,
806 IDirect3DDevice2Impl_GetTransform,
807 IDirect3DDevice2Impl_MultiplyTransform,
809 MESA_IDirect3DDevice2Impl_DrawPrimitive,
810 MESA_IDirect3DDevice2Impl_DrawIndexedPrimitive,
812 IDirect3DDevice2Impl_SetClipStatus,
813 IDirect3DDevice2Impl_GetClipStatus,
816 /*******************************************************************************
819 int d3d_OpenGL_dx3(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) {
822 TRACE(" Enumerating OpenGL D3D device (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
824 fill_opengl_caps(&d1, &d2);
826 return cb((void*)&IID_D3DDEVICE_OpenGL,"WINE Direct3D using OpenGL","direct3d",&d1,&d2,context);
829 int is_OpenGL_dx3(REFCLSID rguid, IDirectDrawSurfaceImpl* surface, IDirect3DDeviceImpl** device)
831 if (!memcmp(&IID_D3DDEVICE_OpenGL,rguid,sizeof(IID_D3DDEVICE_OpenGL))) {
832 mesa_d3dd_private *odev;
833 #if 0 /* See below */
834 int attributeList[]={ GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None };
838 *device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DDeviceImpl));
839 (*device)->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dd_private));
840 odev = (mesa_d3dd_private*)(*device)->private;
842 ICOM_VTBL(*device) = &OpenGL_vtable_dx3;
843 (*device)->d3d = NULL;
844 (*device)->surface = surface;
846 (*device)->viewport_list = NULL;
847 (*device)->current_viewport = NULL;
849 (*device)->set_context = (void*)set_context;
851 TRACE("OpenGL device created \n");
853 /* Create the OpenGL context */
854 /* First get the correct visual */
855 /* if (surface->s.backbuffer == NULL)
856 attributeList[3] = None; */
857 #if 0 /* non working currently */
859 xvis = glXChooseVisual(gdi_display,
860 DefaultScreen(gdi_display),
863 ERR("No visual found !\n");
865 TRACE("Visual found\n");
866 /* Create the context */
867 odev->ctx = glXCreateContext(gdi_display,
871 TRACE("Context created\n");
873 /* Now override the surface's Flip method (if in double buffering) */
874 surface->s.d3d_device = (void *) odev;
877 struct _surface_chain *chain = surface->s.chain;
878 for (i=0;i<chain->nrofsurfaces;i++)
879 if (chain->surfaces[i]->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_FLIP)
880 chain->surfaces[i]->s.d3d_device = (void *) odev;
883 odev->rs.src = GL_ONE;
884 odev->rs.dst = GL_ZERO;
885 odev->rs.mag = GL_NEAREST;
886 odev->rs.min = GL_NEAREST;
888 odev->world_mat = (LPD3DMATRIX) &id_mat;
889 odev->view_mat = (LPD3DMATRIX) &id_mat;
890 odev->proj_mat = (LPD3DMATRIX) &id_mat;
893 (*device)->set_context(*device);
894 glClearColor(0.0, 0.0, 0.0, 0.0);
895 glColor3f(1.0, 1.0, 1.0);
897 fill_device_capabilities((IDirectDrawImpl *) surface->ddraw_owner);
902 /* This is not the OpenGL UID */
906 static ULONG WINAPI MESA_IDirect3DDeviceImpl_Release(LPDIRECT3DDEVICE iface)
908 ICOM_THIS(IDirect3DDeviceImpl,iface);
909 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
911 if (!--(This->ref)) {
912 #if 0 /* broken for now */
915 glXDestroyContext(gdi_display, odev->ctx);
918 This->private = NULL;
919 HeapFree(GetProcessHeap(),0,This);
925 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EnumTextureFormats(
926 LPDIRECT3DDEVICE iface,LPD3DENUMTEXTUREFORMATSCALLBACK lpd3dEnumTextureProc,
929 ICOM_THIS(IDirect3DDeviceImpl,iface);
930 TRACE("(%p)->(%p,%p): stub\n", This, lpd3dEnumTextureProc, lpArg);
932 return enum_texture_format_OpenGL(lpd3dEnumTextureProc, lpArg);
936 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_BeginScene(LPDIRECT3DDEVICE iface)
938 ICOM_THIS(IDirect3DDeviceImpl,iface);
939 /* OpenGL_IDirect3DDevice *odev = (OpenGL_IDirect3DDevice *) This; */
941 FIXME("(%p)->(): stub\n", This);
943 /* We get the pointer to the surface (should be done on flip) */
944 /* odev->zb->pbuf = This->surface->s.surface_desc.u2.lpSurface; */
950 /* This is for the moment copy-pasted from IDirect3DDevice2...
951 Will make a common function ... */
952 static HRESULT WINAPI MESA_IDirect3DDeviceImpl_EndScene(LPDIRECT3DDEVICE iface)
954 ICOM_THIS(IDirect3DDeviceImpl,iface);
956 FIXME("(%p)->(): stub\n", This);
958 /* No need to do anything here... */
963 /*******************************************************************************
964 * Direct3DDevice VTable
966 ICOM_VTABLE(IDirect3DDevice) OpenGL_vtable_dx3 =
968 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
969 IDirect3DDeviceImpl_QueryInterface,
970 IDirect3DDeviceImpl_AddRef,
971 MESA_IDirect3DDeviceImpl_Release,
972 IDirect3DDeviceImpl_Initialize,
973 IDirect3DDeviceImpl_GetCaps,
974 IDirect3DDeviceImpl_SwapTextureHandles,
975 MESA_IDirect3DDeviceImpl_CreateExecuteBuffer,
976 IDirect3DDeviceImpl_GetStats,
977 IDirect3DDeviceImpl_Execute,
978 IDirect3DDeviceImpl_AddViewport,
979 IDirect3DDeviceImpl_DeleteViewport,
980 IDirect3DDeviceImpl_NextViewport,
981 IDirect3DDeviceImpl_Pick,
982 IDirect3DDeviceImpl_GetPickRecords,
983 MESA_IDirect3DDeviceImpl_EnumTextureFormats,
984 IDirect3DDeviceImpl_CreateMatrix,
985 IDirect3DDeviceImpl_SetMatrix,
986 IDirect3DDeviceImpl_GetMatrix,
987 IDirect3DDeviceImpl_DeleteMatrix,
988 MESA_IDirect3DDeviceImpl_BeginScene,
989 MESA_IDirect3DDeviceImpl_EndScene,
990 IDirect3DDeviceImpl_GetDirect3D,