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
31 #include "wine/debug.h"
33 #include "mesa_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 /* They are non-static as they are used by Direct3D in the creation function */
41 const GUID IID_D3DDEVICE_OpenGL = {
45 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
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 /* retrieve the X display to use on a given DC */
63 inline static Display *get_display( HDC hdc )
66 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69 sizeof(display), (LPSTR)&display )) display = NULL;
75 /* retrieve the X drawable to use on a given DC */
76 inline static Drawable get_drawable( HDC hdc )
79 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
81 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
82 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
88 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
90 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
92 glXSwapBuffers((Display*)display,(Drawable)drawable);
98 /*******************************************************************************
99 * OpenGL static functions
101 static void set_context(IDirect3DDeviceImpl* This)
103 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
106 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
107 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
108 ERR("Error in setting current context (context %p drawable %ld)!\n",
109 glThis->gl_context, glThis->drawable);
114 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
116 pc->dwSize = sizeof(*pc);
117 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
118 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
119 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
120 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
121 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
122 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
123 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
124 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
125 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
126 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
127 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
128 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
129 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
130 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
131 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
132 pc->dwStippleWidth = 32;
133 pc->dwStippleHeight = 32;
136 static void fill_opengl_caps(D3DDEVICEDESC *d1)
138 /* GLint maxlight; */
140 d1->dwSize = sizeof(*d1);
141 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
142 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
143 d1->dcmColorModel = D3DCOLOR_RGB;
144 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
145 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
146 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
147 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
148 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
149 d1->bClipping = TRUE;
150 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
151 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
152 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
153 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
154 fill_opengl_primcaps(&(d1->dpcLineCaps));
155 fill_opengl_primcaps(&(d1->dpcTriCaps));
156 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
157 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
158 d1->dwMaxBufferSize = 0;
159 d1->dwMaxVertexCount = 65536;
160 d1->dwMinTextureWidth = 1;
161 d1->dwMinTextureHeight = 1;
162 d1->dwMaxTextureWidth = 1024;
163 d1->dwMaxTextureHeight = 1024;
164 d1->dwMinStippleWidth = 1;
165 d1->dwMinStippleHeight = 1;
166 d1->dwMaxStippleWidth = 32;
167 d1->dwMaxStippleHeight = 32;
168 d1->dwMaxTextureRepeat = 16;
169 d1->dwMaxTextureAspectRatio = 1024;
170 d1->dwMaxAnisotropy = 0;
171 d1->dvGuardBandLeft = 0.0;
172 d1->dvGuardBandRight = 0.0;
173 d1->dvGuardBandTop = 0.0;
174 d1->dvGuardBandBottom = 0.0;
175 d1->dvExtentsAdjust = 0.0;
176 d1->dwStencilCaps = 0; /* TODO add proper caps according to what OpenGL can do */
177 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
178 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
179 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
180 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
183 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
187 /* Copy first D3D1/2/3 capabilities */
188 fill_opengl_caps(&d1);
190 /* And fill the D3D7 one with it */
191 d->dwDevCaps = d1.dwDevCaps;
192 d->dpcLineCaps = d1.dpcLineCaps;
193 d->dpcTriCaps = d1.dpcTriCaps;
194 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
195 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
196 d->dwMinTextureWidth = d1.dwMinTextureWidth;
197 d->dwMinTextureHeight = d1.dwMinTextureHeight;
198 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
199 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
200 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
201 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
202 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
203 d->dvGuardBandLeft = d1.dvGuardBandLeft;
204 d->dvGuardBandTop = d1.dvGuardBandTop;
205 d->dvGuardBandRight = d1.dvGuardBandRight;
206 d->dvGuardBandBottom = d1.dvGuardBandBottom;
207 d->dvExtentsAdjust = d1.dvExtentsAdjust;
208 d->dwStencilCaps = d1.dwStencilCaps;
209 d->dwFVFCaps = d1.dwFVFCaps;
210 d->dwTextureOpCaps = d1.dwTextureOpCaps;
211 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
212 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
213 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
214 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
215 d->deviceGUID = IID_IDirect3DTnLHalDevice;
216 d->wMaxUserClipPlanes = 1;
217 d->wMaxVertexBlendMatrices = 0;
218 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
219 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
226 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
227 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
229 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
230 const char *ext_string;
231 Mesa_DeviceCapabilities *devcap;
233 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
234 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
237 ext_string = glGetString(GL_EXTENSIONS);
238 /* Query for the ColorTable Extension */
239 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
240 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
241 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
243 TRACE("Color table extension not found.\n");
251 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
253 D3DDEVICEDESC d1, d2;
255 fill_opengl_caps(&d1);
258 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
259 return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
262 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
264 D3DDEVICEDESC7 ddesc;
266 fill_opengl_caps_7(&ddesc);
268 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
270 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
274 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
276 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
277 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
279 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
280 if (!--(This->ref)) {
281 /* Release texture associated with the device */
282 if (This->current_texture[0] != NULL)
283 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
285 if (glThis->handler) HeapFree(GetProcessHeap(), 0, This);
288 glXDestroyContext(glThis->display, glThis->gl_context);
291 HeapFree(GetProcessHeap(), 0, This);
298 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
299 LPD3DDEVICEDESC lpD3DHWDevDesc,
300 LPD3DDEVICEDESC lpD3DHELDevDesc)
302 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
306 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
308 fill_opengl_caps(&desc);
309 dwSize = lpD3DHWDevDesc->dwSize;
310 memset(lpD3DHWDevDesc, 0, dwSize);
311 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
313 dwSize = lpD3DHELDevDesc->dwSize;
314 memset(lpD3DHELDevDesc, 0, dwSize);
315 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
317 TRACE(" returning caps : (no dump function yet)\n");
322 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
323 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
327 LPDDPIXELFORMAT pformat;
329 /* Do the texture enumeration */
330 sdesc.dwSize = sizeof(DDSURFACEDESC);
331 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
332 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
333 pformat = &(sdesc.ddpfPixelFormat);
334 pformat->dwSize = sizeof(DDPIXELFORMAT);
335 pformat->dwFourCC = 0;
337 TRACE("Enumerating GL_RGBA unpacked (32)\n");
338 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
339 pformat->u1.dwRGBBitCount = 32;
340 pformat->u2.dwRBitMask = 0xFF000000;
341 pformat->u3.dwGBitMask = 0x00FF0000;
342 pformat->u4.dwBBitMask = 0x0000FF00;
343 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
344 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
345 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
347 TRACE("Enumerating GL_RGB unpacked (24)\n");
348 pformat->dwFlags = DDPF_RGB;
349 pformat->u1.dwRGBBitCount = 24;
350 pformat->u2.dwRBitMask = 0x00FF0000;
351 pformat->u3.dwGBitMask = 0x0000FF00;
352 pformat->u4.dwBBitMask = 0x000000FF;
353 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
354 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
355 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
357 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
358 pformat->dwFlags = DDPF_RGB;
359 pformat->u1.dwRGBBitCount = 16;
360 pformat->u2.dwRBitMask = 0x0000F800;
361 pformat->u3.dwGBitMask = 0x000007E0;
362 pformat->u4.dwBBitMask = 0x0000001F;
363 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
364 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
365 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
367 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
368 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
369 pformat->u1.dwRGBBitCount = 16;
370 pformat->u2.dwRBitMask = 0x0000F800;
371 pformat->u3.dwGBitMask = 0x000007C0;
372 pformat->u4.dwBBitMask = 0x0000003E;
373 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
374 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
375 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
377 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
378 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
379 pformat->u1.dwRGBBitCount = 16;
380 pformat->u2.dwRBitMask = 0x0000F000;
381 pformat->u3.dwGBitMask = 0x00000F00;
382 pformat->u4.dwBBitMask = 0x000000F0;
383 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
384 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
385 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
387 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (16)\n");
388 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
389 pformat->u1.dwRGBBitCount = 16;
390 pformat->u2.dwRBitMask = 0x00007C00;
391 pformat->u3.dwGBitMask = 0x000003E0;
392 pformat->u4.dwBBitMask = 0x0000001F;
393 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
394 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
395 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
397 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
398 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
399 pformat->u1.dwRGBBitCount = 16;
400 pformat->u2.dwRBitMask = 0x00000F00;
401 pformat->u3.dwGBitMask = 0x000000F0;
402 pformat->u4.dwBBitMask = 0x0000000F;
403 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
404 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
405 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
407 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
408 pformat->dwFlags = DDPF_RGB;
409 pformat->u1.dwRGBBitCount = 8;
410 pformat->u2.dwRBitMask = 0x000000E0;
411 pformat->u3.dwGBitMask = 0x0000001C;
412 pformat->u4.dwBBitMask = 0x00000003;
413 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
414 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
415 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
417 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
418 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
419 pformat->u1.dwRGBBitCount = 16;
420 pformat->u2.dwRBitMask = 0x00007C00;
421 pformat->u3.dwGBitMask = 0x000003E0;
422 pformat->u4.dwBBitMask = 0x0000001F;
423 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
424 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
425 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
427 TRACE("Enumerating Paletted (8)\n");
428 pformat->dwFlags = DDPF_PALETTEINDEXED8;
429 pformat->u1.dwRGBBitCount = 8;
430 pformat->u2.dwRBitMask = 0x00000000;
431 pformat->u3.dwGBitMask = 0x00000000;
432 pformat->u4.dwBBitMask = 0x00000000;
433 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
434 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
435 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
437 TRACE("End of enumeration\n");
443 d3ddevice_find(IDirect3DImpl *d3d,
444 LPD3DFINDDEVICESEARCH lpD3DDFS,
445 LPD3DFINDDEVICERESULT lplpD3DDevice)
450 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
451 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
452 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
453 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
455 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
456 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
457 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
458 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
459 TRACE(" no match for this GUID.\n");
460 return DDERR_INVALIDPARAMS;
464 /* Now return our own GUID */
465 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
466 fill_opengl_caps(&desc);
467 dwSize = lplpD3DDevice->ddHwDesc.dwSize;
468 memset(&(lplpD3DDevice->ddHwDesc), 0, dwSize);
469 memcpy(&(lplpD3DDevice->ddHwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
470 dwSize = lplpD3DDevice->ddSwDesc.dwSize;
471 memset(&(lplpD3DDevice->ddSwDesc), 0, dwSize);
472 memcpy(&(lplpD3DDevice->ddSwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
478 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
479 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
482 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
483 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
484 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
488 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
489 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
492 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
493 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
494 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
498 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
499 D3DRENDERSTATETYPE dwRenderStateType,
502 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
503 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
504 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
506 /* Call the render state functions */
507 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
513 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
514 D3DLIGHTSTATETYPE dwLightStateType,
517 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
518 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
520 switch (dwLightStateType) {
521 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
522 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
529 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
533 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
536 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
537 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
538 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
541 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
545 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
555 TRACE("Unexpected Light State Type\n");
556 return DDERR_INVALIDPARAMS;
563 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
564 D3DTRANSFORMSTATETYPE dtstTransformStateType,
565 LPD3DMATRIX lpD3DMatrix)
567 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
568 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
570 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
574 /* Using a trial and failure approach, I found that the order of
575 Direct3D transformations that works best is :
577 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
579 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
580 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
582 If anyone has a good explanation of the three different matrices in
583 the SDK online documentation, feel free to point it to me. For example,
584 which matrices transform lights ? In OpenGL only the PROJECTION matrix
585 transform the lights, not the MODELVIEW. Using the matrix names, I
586 supposed that PROJECTION and VIEW (all 'camera' related names) do
587 transform lights, but WORLD do not. It may be wrong though... */
589 /* After reading through both OpenGL and Direct3D documentations, I
590 thought that D3D matrices were written in 'line major mode' transposed
591 from OpenGL's 'column major mode'. But I found out that a simple memcpy
592 works fine to transfer one matrix format to the other (it did not work
593 when transposing)....
596 1) are the documentations wrong
597 2) does the matrix work even if they are not read correctly
598 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
599 loading using glLoadMatrix ?
601 Anyway, I always use 'conv_mat' to transfer the matrices from one format
602 to the other so that if I ever find out that I need to transpose them, I
603 will able to do it quickly, only by changing the macro conv_mat. */
605 switch (dtstTransformStateType) {
606 case D3DTRANSFORMSTATE_WORLD: {
607 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
608 conv_mat(lpD3DMatrix, glThis->world_mat);
609 glMatrixMode(GL_MODELVIEW);
610 glLoadMatrixf((float *) glThis->view_mat);
611 glMultMatrixf((float *) glThis->world_mat);
614 case D3DTRANSFORMSTATE_VIEW: {
615 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
616 conv_mat(lpD3DMatrix, glThis->view_mat);
617 glMatrixMode(GL_MODELVIEW);
618 glLoadMatrixf((float *) glThis->view_mat);
619 glMultMatrixf((float *) glThis->world_mat);
622 case D3DTRANSFORMSTATE_PROJECTION: {
623 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
624 conv_mat(lpD3DMatrix, glThis->proj_mat);
625 glMatrixMode(GL_PROJECTION);
626 glLoadMatrixf((float *) glThis->proj_mat);
630 ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
638 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
641 case D3DPT_POINTLIST:
642 TRACE("Start POINTS\n");
647 TRACE("Start LINES\n");
651 case D3DPT_LINESTRIP:
652 TRACE("Start LINE_STRIP\n");
653 glBegin(GL_LINE_STRIP);
656 case D3DPT_TRIANGLELIST:
657 TRACE("Start TRIANGLES\n");
658 glBegin(GL_TRIANGLES);
661 case D3DPT_TRIANGLESTRIP:
662 TRACE("Start TRIANGLE_STRIP\n");
663 glBegin(GL_TRIANGLE_STRIP);
666 case D3DPT_TRIANGLEFAN:
667 TRACE("Start TRIANGLE_FAN\n");
668 glBegin(GL_TRIANGLE_FAN);
672 TRACE("Unhandled primitive\n");
677 static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
678 BOOLEAN vertex_transformed,
679 BOOLEAN vertex_lit) {
680 /* Puts GL in the correct lighting / transformation mode */
681 if ((glThis->last_vertices_transformed == TRUE) && (vertex_transformed == FALSE)) {
682 /* Need to put the correct transformation again if we go from Transformed
683 vertices to non-transformed ones.
685 glMatrixMode(GL_MODELVIEW);
686 glLoadMatrixf((float *) glThis->view_mat);
687 glMultMatrixf((float *) glThis->world_mat);
688 glMatrixMode(GL_PROJECTION);
689 glLoadMatrixf((float *) glThis->proj_mat);
690 } else if ((glThis->last_vertices_transformed == FALSE) && (vertex_transformed == TRUE)) {
691 GLdouble height, width, minZ, maxZ;
693 glMatrixMode(GL_MODELVIEW);
695 glMatrixMode(GL_PROJECTION);
698 if (glThis->parent.current_viewport == NULL) {
699 ERR("No current viewport !\n");
700 /* Using standard values */
706 if (glThis->parent.current_viewport->use_vp2 == 1) {
707 height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
708 width = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
709 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
710 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
712 height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
713 width = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
714 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
715 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
718 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
721 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
722 glEnable(GL_LIGHTING);
723 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
724 glDisable(GL_LIGHTING);
727 /* And save the current state */
728 glThis->last_vertices_transformed = vertex_transformed;
729 glThis->last_vertices_lit = vertex_lit;
733 inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
734 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
738 draw_primitive_handle_GL_state(glThis, d3dvt == D3DVT_TLVERTEX, d3dvt != D3DVT_VERTEX);
739 draw_primitive_start_GL(d3dpt);
741 /* Draw the primitives */
742 for (vx_index = 0; vx_index < maxvert; vx_index++) {
745 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
747 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
748 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
749 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
752 case D3DVT_LVERTEX: {
753 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
754 DWORD col = vx->u4.color;
756 glColor4ub((col >> 16) & 0xFF,
760 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
761 TRACE(" LV: %f %f %f (%02lx %02lx %02lx %02lx)\n",
762 vx->u1.x, vx->u2.y, vx->u3.z,
763 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), ((col >> 24) & 0xFF));
766 case D3DVT_TLVERTEX: {
767 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
768 DWORD col = vx->u5.color;
770 glColor4ub((col >> 16) & 0xFF,
774 glTexCoord2f(vx->u7.tu, vx->u8.tv);
775 if (vx->u4.rhw < 0.01)
776 glVertex3f(vx->u1.sx,
780 glVertex4f(vx->u1.sx / vx->u4.rhw,
781 vx->u2.sy / vx->u4.rhw,
782 vx->u3.sz / vx->u4.rhw,
784 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx %02lx) (%f %f) (%f)\n",
785 vx->u1.sx, vx->u2.sy, vx->u3.sz,
786 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF), ((col >> 24) & 0xFF),
787 vx->u7.tu, vx->u8.tv, vx->u4.rhw);
791 FIXME("Unhandled vertex type\n");
801 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
802 D3DPRIMITIVETYPE d3dptPrimitiveType,
803 D3DVERTEXTYPE d3dvtVertexType,
808 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
809 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
812 draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
819 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
820 D3DPRIMITIVETYPE d3dptPrimitiveType,
821 D3DVERTEXTYPE d3dvtVertexType,
828 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
829 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
832 draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
839 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
840 LPD3DEXECUTEBUFFERDESC lpDesc,
841 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
844 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
845 IDirect3DExecuteBufferImpl *ret;
848 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
850 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
851 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
853 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
858 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements)
863 if (d3dvtVertexType & D3DFVF_NORMAL) { size += 3 * sizeof(D3DVALUE); elts += 1; }
864 if (d3dvtVertexType & D3DFVF_DIFFUSE) { size += sizeof(DWORD); elts += 1; }
865 if (d3dvtVertexType & D3DFVF_SPECULAR) { size += sizeof(DWORD); elts += 1; }
866 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
867 case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); elts += 1; break;
868 case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); elts += 1; break;
869 default: TRACE(" matrix weighting not handled yet...\n");
871 size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
872 elts += (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
874 if (elements) *elements = elts;
879 void dump_flexible_vertex(DWORD d3dvtVertexType)
881 static const flag_info flags[] = {
883 FE(D3DFVF_RESERVED1),
887 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
888 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
889 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
890 GEN_CASE(D3DFVF_XYZ);
891 GEN_CASE(D3DFVF_XYZRHW);
892 GEN_CASE(D3DFVF_XYZB1);
893 GEN_CASE(D3DFVF_XYZB2);
894 GEN_CASE(D3DFVF_XYZB3);
895 GEN_CASE(D3DFVF_XYZB4);
896 GEN_CASE(D3DFVF_XYZB5);
898 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
899 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
900 GEN_CASE(D3DFVF_TEX0);
901 GEN_CASE(D3DFVF_TEX1);
902 GEN_CASE(D3DFVF_TEX2);
903 GEN_CASE(D3DFVF_TEX3);
904 GEN_CASE(D3DFVF_TEX4);
905 GEN_CASE(D3DFVF_TEX5);
906 GEN_CASE(D3DFVF_TEX6);
907 GEN_CASE(D3DFVF_TEX7);
908 GEN_CASE(D3DFVF_TEX8);
914 /* Some types used by the fast paths... */
928 /* These are the various handler used in the generic path */
929 static void handle_xyz(char *vertex, int offset, int extra) {
930 glVertex3fv((float *) (vertex + offset));
932 static void handle_xyzrhw(char *vertex, int offset, int extra) {
933 float *coords = (float *) (vertex + offset);
934 if (coords[3] < 0.00001)
935 glVertex3f(coords[0], coords[1], coords[2]);
937 glVertex4f(coords[0] / coords[3],
938 coords[1] / coords[3],
939 coords[2] / coords[3],
942 static void handle_normal(char *vertex, int offset, int extra) {
943 glNormal3fv((float *) (vertex + offset));
945 static void handle_specular(char *vertex, int offset, int extra) {
946 /* Specular not handled yet properly... */
948 static void handle_diffuse(char *vertex, int offset, int extra) {
949 DWORD color = *((DWORD *) (vertex + offset));
950 glColor4ub((color >> 16) & 0xFF,
953 (color >> 24) & 0xFF);
955 static void handle_texture(char *vertex, int offset, int extra) {
957 /* Special case for single texture... */
958 glTexCoord2fv((float *) (vertex + offset));
960 /* Multitexturing not handled yet */
964 static void draw_primitive_7(IDirect3DDeviceImpl *This,
965 D3DPRIMITIVETYPE d3dptPrimitiveType,
966 DWORD d3dvtVertexType,
973 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
974 if (TRACE_ON(ddraw)) {
975 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
979 draw_primitive_handle_GL_state(glThis,
980 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
981 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
982 draw_primitive_start_GL(d3dptPrimitiveType);
984 /* Some fast paths first before the generic case.... */
985 if (d3dvtVertexType == D3DFVF_VERTEX) {
986 D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
989 for (index = 0; index < dwIndexCount; index++) {
990 int i = (dwIndices == NULL) ? index : dwIndices[index];
992 glNormal3fv(&(vertices[i].nx));
993 glTexCoord2fv(&(vertices[i].tu1));
994 glVertex3fv(&(vertices[i].x));
995 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
996 vertices[i].x, vertices[i].y, vertices[i].z,
997 vertices[i].nx, vertices[i].ny, vertices[i].nz,
998 vertices[i].tu1, vertices[i].tv1);
1000 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
1001 D3DFVF_TLVERTEX_1 *vertices = (D3DFVF_TLVERTEX_1 *) lpvVertices;
1004 for (index = 0; index < dwIndexCount; index++) {
1005 int i = (dwIndices == NULL) ? index : dwIndices[index];
1007 glColor4ub((vertices[i].diffuse >> 16) & 0xFF,
1008 (vertices[i].diffuse >> 8) & 0xFF,
1009 (vertices[i].diffuse >> 0) & 0xFF,
1010 (vertices[i].diffuse >> 24) & 0xFF);
1011 /* Todo : handle specular... */
1012 glTexCoord2fv(&(vertices[i].tu1));
1013 if (vertices[i].rhw < 0.00001)
1014 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
1016 glVertex4f(vertices[i].x / vertices[i].rhw,
1017 vertices[i].y / vertices[i].rhw,
1018 vertices[i].z / vertices[i].rhw,
1019 1.0 / vertices[i].rhw);
1020 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1021 vertices[i].x, vertices[i].y, vertices[i].z, vertices[i].rhw,
1022 (vertices[i].diffuse >> 16) & 0xFF,
1023 (vertices[i].diffuse >> 8) & 0xFF,
1024 (vertices[i].diffuse >> 0) & 0xFF,
1025 (vertices[i].diffuse >> 24) & 0xFF,
1026 (vertices[i].specular >> 16) & 0xFF,
1027 (vertices[i].specular >> 8) & 0xFF,
1028 (vertices[i].specular >> 0) & 0xFF,
1029 (vertices[i].specular >> 24) & 0xFF,
1030 vertices[i].tu1, vertices[i].tv1);
1032 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1033 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1034 /* This is the 'slow path' but that should support all possible vertex formats out there...
1035 Note that people should write a fast path for all vertex formats out there...
1039 char *vertices = (char *) lpvVertices;
1041 int current_offset = 0;
1042 int current_position = 0;
1043 D3DFVF_GENERIC *handler;
1045 if ((glThis->last_vertex_format != d3dvtVertexType) ||
1046 (glThis->handler == NULL)) {
1047 if (glThis->handler == NULL) HeapFree(GetProcessHeap(), 0, glThis->handler);
1048 size = get_flexible_vertex_size(d3dvtVertexType, &elements);
1050 glThis->handler = handler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, elements * sizeof(D3DFVF_GENERIC));
1051 glThis->last_vertex_format = d3dvtVertexType;
1052 glThis->last_vertex_format_size = size;
1053 glThis->last_vertex_format_elements = elements;
1055 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1056 handler[elements - 1].handler = handle_xyz;
1057 handler[elements - 1].offset = current_offset;
1058 current_offset += 3 * sizeof(D3DVALUE);
1060 handler[elements - 1].handler = handle_xyzrhw;
1061 handler[elements - 1].offset = current_offset;
1062 current_offset += 4 * sizeof(D3DVALUE);
1064 if (d3dvtVertexType & D3DFVF_NORMAL) {
1065 handler[current_position].handler = handle_normal;
1066 handler[current_position].offset = current_offset;
1067 current_position += 1;
1068 current_offset += 3 * sizeof(D3DVALUE);
1070 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1071 handler[current_position].handler = handle_diffuse;
1072 handler[current_position].offset = current_offset;
1073 current_position += 1;
1074 current_offset += sizeof(DWORD);
1076 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1077 handler[current_position].handler = handle_specular;
1078 handler[current_position].offset = current_offset;
1079 current_position += 1;
1080 current_offset += sizeof(DWORD);
1082 if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1083 handler[current_position].handler = handle_texture;
1084 handler[current_position].offset = current_offset;
1085 handler[current_position].extra = 0xFF;
1086 current_position += 1;
1087 current_offset += 2 * sizeof(D3DVALUE);
1090 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1091 handler[current_position].handler = handle_texture;
1092 handler[current_position].offset = current_offset;
1093 handler[current_position].extra = tex_index;
1094 current_position += 1;
1095 current_offset += 2 * sizeof(D3DVALUE);
1099 handler = glThis->handler;
1100 size = glThis->last_vertex_format_size;
1101 elements = glThis->last_vertex_format_elements;
1104 WARN(" using draw_primitive generic path - for better performance, add a fast path for your vertex case !\n");
1106 for (index = 0; index < dwIndexCount; index++) {
1107 int i = (dwIndices == NULL) ? index : dwIndices[index];
1109 char *vertex = vertices + (i * size);
1111 for (elt = 0; elt < elements; elt++) {
1112 handler[elt].handler(vertex, handler[elt].offset, handler[elt].extra);
1116 ERR(" matrix weighting not handled yet....\n");
1124 #define CPNT(cpnt,i,n,type) ((type*)(lpD3DDrawPrimStrideData->cpnt.lpvData+i*lpD3DDrawPrimStrideData->cpnt.dwStride))[n]
1126 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
1127 D3DPRIMITIVETYPE d3dptPrimitiveType,
1128 DWORD d3dvtVertexType,
1129 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1130 DWORD dwVertexCount,
1135 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1136 if (TRACE_ON(ddraw)) {
1137 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1141 draw_primitive_handle_GL_state(glThis,
1142 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1143 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
1144 draw_primitive_start_GL(d3dptPrimitiveType);
1146 /* Some fast paths first before the generic case.... */
1147 if (d3dvtVertexType == D3DFVF_VERTEX) {
1150 for (index = 0; index < dwIndexCount; index++) {
1151 int i = (dwIndices == NULL) ? index : dwIndices[index];
1153 glNormal3f(CPNT(normal,i,0,D3DVALUE),CPNT(normal,i,1,D3DVALUE),CPNT(normal,i,2,D3DVALUE));
1154 glTexCoord2f(CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1155 glVertex3f(CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE));
1156 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
1157 CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE),
1158 CPNT(normal,i,0,D3DVALUE),CPNT(normal,i,1,D3DVALUE),CPNT(normal,i,2,D3DVALUE),
1159 CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1162 } else if (d3dvtVertexType == D3DFVF_LVERTEX) {
1165 for (index = 0; index < dwIndexCount; index++) {
1166 int i = (dwIndices == NULL) ? index : dwIndices[index];
1168 glColor4ub((CPNT(diffuse,i,0,DWORD) >> 16) & 0xFF,
1169 (CPNT(diffuse,i,0,DWORD) >> 8) & 0xFF,
1170 (CPNT(diffuse,i,0,DWORD) >> 0) & 0xFF,
1171 (CPNT(diffuse,i,0,DWORD) >> 24) & 0xFF);
1172 /* Todo : handle specular... */
1173 glTexCoord2f(CPNT(textureCoords[1],i,0,D3DVALUE),CPNT(textureCoords[1],i,1,D3DVALUE));
1174 glVertex3f(CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE));
1175 TRACE(" %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1176 CPNT(position,i,0,D3DVALUE),CPNT(position,i,1,D3DVALUE),CPNT(position,i,2,D3DVALUE),
1177 (CPNT(diffuse,i,0,DWORD) >> 16) & 0xFF,
1178 (CPNT(diffuse,i,0,DWORD) >> 8) & 0xFF,
1179 (CPNT(diffuse,i,0,DWORD) >> 0) & 0xFF,
1180 (CPNT(diffuse,i,0,DWORD) >> 24) & 0xFF,
1181 (CPNT(specular,i,0,DWORD) >> 16) & 0xFF,
1182 (CPNT(specular,i,0,DWORD) >> 8) & 0xFF,
1183 (CPNT(specular,i,0,DWORD) >> 0) & 0xFF,
1184 (CPNT(specular,i,0,DWORD) >> 24) & 0xFF,
1185 CPNT(textureCoords[0],i,0,D3DVALUE),CPNT(textureCoords[0],i,1,D3DVALUE));
1197 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1198 D3DPRIMITIVETYPE d3dptPrimitiveType,
1199 DWORD d3dvtVertexType,
1201 DWORD dwVertexCount,
1204 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1205 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1207 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1213 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1214 D3DPRIMITIVETYPE d3dptPrimitiveType,
1215 DWORD d3dvtVertexType,
1217 DWORD dwVertexCount,
1222 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1223 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1225 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1231 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1232 D3DPRIMITIVETYPE d3dptPrimitiveType,
1234 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1235 DWORD dwVertexCount,
1238 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1239 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1240 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1245 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1246 D3DPRIMITIVETYPE d3dptPrimitiveType,
1248 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1249 DWORD dwVertexCount,
1254 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1255 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1256 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1261 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1263 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1266 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1267 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1270 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1272 if (TRACE_ON(ddraw)) {
1273 TRACE(" Stage type is : ");
1274 switch (d3dTexStageStateType) {
1275 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1276 GEN_CASE(D3DTSS_COLOROP);
1277 GEN_CASE(D3DTSS_COLORARG1);
1278 GEN_CASE(D3DTSS_COLORARG2);
1279 GEN_CASE(D3DTSS_ALPHAOP);
1280 GEN_CASE(D3DTSS_ALPHAARG1);
1281 GEN_CASE(D3DTSS_ALPHAARG2);
1282 GEN_CASE(D3DTSS_BUMPENVMAT00);
1283 GEN_CASE(D3DTSS_BUMPENVMAT01);
1284 GEN_CASE(D3DTSS_BUMPENVMAT10);
1285 GEN_CASE(D3DTSS_BUMPENVMAT11);
1286 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1287 GEN_CASE(D3DTSS_ADDRESS);
1288 GEN_CASE(D3DTSS_ADDRESSU);
1289 GEN_CASE(D3DTSS_ADDRESSV);
1290 GEN_CASE(D3DTSS_BORDERCOLOR);
1291 GEN_CASE(D3DTSS_MAGFILTER);
1292 GEN_CASE(D3DTSS_MINFILTER);
1293 GEN_CASE(D3DTSS_MIPFILTER);
1294 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1295 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1296 GEN_CASE(D3DTSS_MAXANISOTROPY);
1297 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1298 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1299 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1301 default: DPRINTF("UNKNOWN !!!");
1306 switch (d3dTexStageStateType) {
1307 case D3DTSS_MINFILTER:
1308 switch ((D3DTEXTUREMINFILTER) dwState) {
1310 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1311 gl_state = GL_NEAREST;
1314 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1315 gl_state = GL_LINEAR;
1318 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1319 gl_state = GL_LINEAR;
1322 glThis->render_state.min = gl_state;
1323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1326 case D3DTSS_MAGFILTER:
1327 switch ((D3DTEXTUREMAGFILTER) dwState) {
1329 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1330 gl_state = GL_NEAREST;
1333 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1334 gl_state = GL_LINEAR;
1337 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1338 gl_state = GL_LINEAR;
1341 glThis->render_state.mag = gl_state;
1342 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1346 if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1353 GL_IDirect3DDeviceImpl_3_SetTexture(LPDIRECT3DDEVICE3 iface,
1355 LPDIRECT3DTEXTURE2 lpTexture2)
1357 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1359 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1361 if (This->current_texture[dwStage] != NULL) {
1362 /* Seems that this is not right... Need to test in real Windows
1363 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1367 if (lpTexture2 == NULL) {
1368 TRACE(" disabling 2D texturing.\n");
1369 glBindTexture(GL_TEXTURE_2D, 0);
1370 glDisable(GL_TEXTURE_2D);
1372 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpTexture2);
1373 IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
1375 This->current_texture[dwStage] = tex_impl;
1376 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
1378 TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1380 glEnable(GL_TEXTURE_2D);
1381 glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1389 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1390 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1392 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1393 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1395 fill_opengl_caps_7(lpD3DHELDevDesc);
1397 TRACE(" returning caps : no dump function yet.\n");
1402 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1403 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1405 # define XCAST(fun) (void*)
1408 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1410 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1411 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1412 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1413 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1414 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1415 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1416 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1417 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1418 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1419 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1420 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1421 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1422 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1423 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1424 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1425 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1426 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1427 XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1428 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1429 XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1430 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1431 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1432 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1433 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1434 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1435 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1436 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1437 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1438 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1439 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1440 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1441 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1442 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1443 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1444 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1445 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1446 XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
1447 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1448 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1449 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1450 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1451 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1452 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1453 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1454 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1455 XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1456 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1457 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1458 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1459 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1462 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1467 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1468 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1470 # define XCAST(fun) (void*)
1473 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1475 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1476 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1477 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1478 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1479 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1480 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1481 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1482 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1483 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1484 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1485 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1486 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1487 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1488 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1489 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1490 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1491 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1492 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1493 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1494 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1495 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1496 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1497 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1498 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1499 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1500 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1501 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1502 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1503 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1504 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1505 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1506 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1507 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1508 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1509 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1510 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1511 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1512 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1513 XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
1514 XCAST(SetTexture) GL_IDirect3DDeviceImpl_3_SetTexture,
1515 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1516 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1517 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1520 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1525 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1526 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1528 # define XCAST(fun) (void*)
1531 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1533 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1534 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1535 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1536 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1537 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1538 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1539 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1540 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1541 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1542 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1543 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1544 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1545 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1546 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1547 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1548 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1549 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1550 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1551 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1552 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1553 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1554 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1555 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1556 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1557 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1558 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1559 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1560 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1561 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1562 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1563 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1564 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1565 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1566 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1569 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1574 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1575 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1577 # define XCAST(fun) (void*)
1580 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1582 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1583 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1584 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1585 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1586 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1587 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1588 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1589 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1590 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1591 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1592 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1593 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1594 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1595 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1596 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1597 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1598 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1599 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1600 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1601 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1602 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1603 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1604 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1607 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1611 /* TODO for both these functions :
1612 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1613 by other OpenGL code in D3D
1614 - handle the case where no 'Begin / EndScene' was done between two locks
1615 - handle the rectangles in the unlock too
1616 - handle pitch correctly...
1618 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1620 /* First, check if we need to do anything */
1621 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1628 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1631 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1632 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1633 /* Application wants to lock the front buffer */
1634 glReadBuffer(GL_FRONT);
1635 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1636 /* Application wants to lock the back buffer */
1637 glReadBuffer(GL_BACK);
1639 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1642 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1643 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1645 WARN(" unsupported pixel format.\n");
1649 if (pRect == NULL) {
1652 loc_rect.bottom = This->surface_desc.dwHeight;
1653 loc_rect.right = This->surface_desc.dwWidth;
1657 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1658 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1659 + loc_rect.top * This->surface_desc.u1.lPitch
1660 + loc_rect.left * GET_BPP(This->surface_desc)));
1661 glReadBuffer(prev_read);
1666 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1668 /* First, check if we need to do anything */
1669 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1675 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1677 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1678 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1679 /* Application wants to lock the front buffer */
1680 glDrawBuffer(GL_FRONT);
1681 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1682 /* Application wants to lock the back buffer */
1683 glDrawBuffer(GL_BACK);
1685 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1688 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1689 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1691 WARN(" unsupported pixel format.\n");
1695 glRasterPos2f(0.0, 0.0);
1696 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1697 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1698 glDrawBuffer(prev_draw);
1705 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1707 IDirect3DDeviceImpl *object;
1708 IDirect3DDeviceGLImpl *gl_object;
1709 IDirectDrawSurfaceImpl *surf;
1713 XVisualInfo template;
1716 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1717 if (object == NULL) return DDERR_OUTOFMEMORY;
1719 gl_object = (IDirect3DDeviceGLImpl *) object;
1723 object->surface = surface;
1724 object->set_context = set_context;
1726 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1728 device_context = GetDC(surface->ddraw_owner->window);
1729 gl_object->display = get_display(device_context);
1730 gl_object->drawable = get_drawable(device_context);
1731 ReleaseDC(surface->ddraw_owner->window,device_context);
1734 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1735 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1737 HeapFree(GetProcessHeap(), 0, object);
1738 ERR("No visual found !\n");
1740 return DDERR_INVALIDPARAMS;
1742 TRACE(" visual found\n");
1745 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1748 if (gl_object->gl_context == NULL) {
1749 HeapFree(GetProcessHeap(), 0, object);
1750 ERR("Error in context creation !\n");
1752 return DDERR_INVALIDPARAMS;
1754 TRACE(" context created (%p)\n", gl_object->gl_context);
1757 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1758 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1759 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1760 surf->aux_ctx = (LPVOID) gl_object->display;
1761 surf->aux_data = (LPVOID) gl_object->drawable;
1762 surf->aux_flip = opengl_flip;
1767 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1769 TRACE(" no double buffering : drawing on the front buffer\n");
1773 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1774 for (; surf != NULL; surf = surf->next_attached) {
1775 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1776 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1777 /* Override the Lock / Unlock function for all these surfaces */
1778 surf->lock_update = d3ddevice_lock_update;
1779 surf->unlock_update = d3ddevice_unlock_update;
1781 surf->d3ddevice = object;
1784 gl_object->render_state.src = GL_ONE;
1785 gl_object->render_state.dst = GL_ZERO;
1786 gl_object->render_state.mag = GL_NEAREST;
1787 gl_object->render_state.min = GL_NEAREST;
1788 gl_object->render_state.alpha_ref = 0.0; /* No actual idea about the real default value... */
1789 gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */
1791 /* Allocate memory for the matrices */
1792 gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1793 gl_object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1794 gl_object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1796 memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1797 memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1798 memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1800 /* Initialisation */
1801 TRACE(" setting current context\n");
1803 object->set_context(object);
1805 TRACE(" current context set\n");
1806 glClearColor(0.0, 0.0, 0.0, 0.0);
1807 glColor3f(1.0, 1.0, 1.0);
1808 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1809 glDrawBuffer(buffer);
1810 glReadBuffer(buffer);
1811 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1814 /* fill_device_capabilities(d3d->ddraw); */
1816 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
1817 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1818 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1819 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1823 TRACE(" creating implementation at %p.\n", *obj);