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"
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 const GUID IID_D3DDEVICE2_OpenGL = {
52 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfb }
55 const GUID IID_D3DDEVICE3_OpenGL = {
59 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfc }
62 const GUID IID_D3DDEVICE7_OpenGL = {
66 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfd }
69 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
70 on Mesa's home page) or version 3.1b.
72 Version 3.1b2 should correct this bug */
73 #undef HAVE_BUGGY_MESAGL
75 #ifndef HAVE_GLEXT_PROTOTYPES
76 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
77 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
78 GLsizei width, GLenum format, GLenum type,
82 static const float id_mat[16] = {
89 /* retrieve the X display to use on a given DC */
90 inline static Display *get_display( HDC hdc )
93 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
95 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
96 sizeof(display), (LPSTR)&display )) display = NULL;
102 /* retrieve the X drawable to use on a given DC */
103 inline static Drawable get_drawable( HDC hdc )
106 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
108 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
109 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
115 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
117 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
119 glXSwapBuffers((Display*)display,(Drawable)drawable);
125 /*******************************************************************************
126 * OpenGL static functions
128 static void set_context(IDirect3DDeviceImpl* This)
130 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
133 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
134 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
135 ERR("Error in setting current context (context %p drawable %ld)!\n",
136 glThis->gl_context, glThis->drawable);
141 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
143 pc->dwSize = sizeof(*pc);
144 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
145 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
146 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
147 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
148 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
149 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
150 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
151 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
152 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
153 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
154 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
155 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
156 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
157 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
158 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
159 pc->dwStippleWidth = 32;
160 pc->dwStippleHeight = 32;
163 static void fill_opengl_caps(D3DDEVICEDESC *d1)
165 /* GLint maxlight; */
167 d1->dwSize = sizeof(*d1);
168 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
169 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
170 d1->dcmColorModel = D3DCOLOR_RGB;
171 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
172 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
173 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
174 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
175 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
176 d1->bClipping = TRUE;
177 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
178 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
179 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
180 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
181 fill_opengl_primcaps(&(d1->dpcLineCaps));
182 fill_opengl_primcaps(&(d1->dpcTriCaps));
183 d1->dwDeviceRenderBitDepth = DDBD_16;
184 d1->dwDeviceZBufferBitDepth = DDBD_16;
185 d1->dwMaxBufferSize = 0;
186 d1->dwMaxVertexCount = 65536;
187 d1->dwMinTextureWidth = 1;
188 d1->dwMinTextureHeight = 1;
189 d1->dwMaxTextureWidth = 1024;
190 d1->dwMaxTextureHeight = 1024;
191 d1->dwMinStippleWidth = 1;
192 d1->dwMinStippleHeight = 1;
193 d1->dwMaxStippleWidth = 32;
194 d1->dwMaxStippleHeight = 32;
195 d1->dwMaxTextureRepeat = 16;
196 d1->dwMaxTextureAspectRatio = 1024;
197 d1->dwMaxAnisotropy = 0;
198 d1->dvGuardBandLeft = 0.0;
199 d1->dvGuardBandRight = 0.0;
200 d1->dvGuardBandTop = 0.0;
201 d1->dvGuardBandBottom = 0.0;
202 d1->dvExtentsAdjust = 0.0;
203 d1->dwStencilCaps = 0; /* TODO add proper caps according to what OpenGL can do */
204 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
205 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
206 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
207 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
210 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
214 /* Copy first D3D1/2/3 capabilities */
215 fill_opengl_caps(&d1);
217 /* And fill the D3D7 one with it */
218 d->dwDevCaps = d1.dwDevCaps;
219 d->dpcLineCaps = d1.dpcLineCaps;
220 d->dpcTriCaps = d1.dpcTriCaps;
221 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
222 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
223 d->dwMinTextureWidth = d1.dwMinTextureWidth;
224 d->dwMinTextureHeight = d1.dwMinTextureHeight;
225 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
226 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
227 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
228 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
229 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
230 d->dvGuardBandLeft = d1.dvGuardBandLeft;
231 d->dvGuardBandTop = d1.dvGuardBandTop;
232 d->dvGuardBandRight = d1.dvGuardBandRight;
233 d->dvGuardBandBottom = d1.dvGuardBandBottom;
234 d->dvExtentsAdjust = d1.dvExtentsAdjust;
235 d->dwStencilCaps = d1.dwStencilCaps;
236 d->dwFVFCaps = d1.dwFVFCaps;
237 d->dwTextureOpCaps = d1.dwTextureOpCaps;
238 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
239 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
240 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
241 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
242 d->deviceGUID = IID_IDirect3DTnLHalDevice;
243 d->wMaxUserClipPlanes = 1;
244 d->wMaxVertexBlendMatrices = 1;
245 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
246 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
253 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
254 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
256 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
257 const char *ext_string;
258 Mesa_DeviceCapabilities *devcap;
260 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
261 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
264 ext_string = glGetString(GL_EXTENSIONS);
265 /* Query for the ColorTable Extension */
266 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
267 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
268 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
270 TRACE("Color table extension not found.\n");
278 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD interface_version)
280 D3DDEVICEDESC d1, d2;
282 const void *iid = NULL;
284 switch (interface_version) {
285 case 1: iid = &IID_D3DDEVICE_OpenGL; break;
286 case 2: iid = &IID_D3DDEVICE2_OpenGL; break;
287 case 3: iid = &IID_D3DDEVICE3_OpenGL; break;
288 case 7: iid = &IID_D3DDEVICE7_OpenGL; break;
290 strcpy(buf, "WINE Direct3DX using OpenGL");
291 buf[13] = '0' + interface_version;
293 fill_opengl_caps(&d1);
296 TRACE(" enumerating OpenGL D3DDevice%ld interface (IID %s).\n", interface_version, debugstr_guid(iid));
297 return cb((LPGUID) iid, buf, "direct3d", &d1, &d2, context);
300 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
302 D3DDEVICEDESC7 ddesc;
304 fill_opengl_caps_7(&ddesc);
306 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
308 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
312 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
314 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
315 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
317 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
318 if (!--(This->ref)) {
319 /* Release texture associated with the device */
320 if (This->current_texture != NULL)
321 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture, IDirect3DTexture2));
324 glXDestroyContext(glThis->display, glThis->gl_context);
327 HeapFree(GetProcessHeap(), 0, This);
334 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
335 LPD3DDEVICEDESC lpD3DHWDevDesc,
336 LPD3DDEVICEDESC lpD3DHELDevDesc)
338 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
342 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
344 fill_opengl_caps(&desc);
345 dwSize = lpD3DHWDevDesc->dwSize;
346 memset(lpD3DHWDevDesc, 0, dwSize);
347 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
349 dwSize = lpD3DHELDevDesc->dwSize;
350 memset(lpD3DHELDevDesc, 0, dwSize);
351 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
353 TRACE(" returning caps : (no dump function yet)\n");
358 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
359 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
363 LPDDPIXELFORMAT pformat;
365 /* Do the texture enumeration */
366 sdesc.dwSize = sizeof(DDSURFACEDESC);
367 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
368 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
369 pformat = &(sdesc.ddpfPixelFormat);
370 pformat->dwSize = sizeof(DDPIXELFORMAT);
371 pformat->dwFourCC = 0;
373 TRACE("Enumerating GL_RGBA unpacked (32)\n");
374 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
375 pformat->u1.dwRGBBitCount = 32;
376 pformat->u2.dwRBitMask = 0xFF000000;
377 pformat->u3.dwGBitMask = 0x00FF0000;
378 pformat->u4.dwBBitMask = 0x0000FF00;
379 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
380 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
381 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
383 TRACE("Enumerating GL_RGB unpacked (24)\n");
384 pformat->dwFlags = DDPF_RGB;
385 pformat->u1.dwRGBBitCount = 24;
386 pformat->u2.dwRBitMask = 0x00FF0000;
387 pformat->u3.dwGBitMask = 0x0000FF00;
388 pformat->u4.dwBBitMask = 0x000000FF;
389 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
390 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
391 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
393 #ifndef HAVE_BUGGY_MESAGL
394 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
395 so that future version will work great. */
396 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
397 pformat->dwFlags = DDPF_RGB;
398 pformat->u1.dwRGBBitCount = 16;
399 pformat->u2.dwRBitMask = 0x0000F800;
400 pformat->u3.dwGBitMask = 0x000007E0;
401 pformat->u4.dwBBitMask = 0x0000001F;
402 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
403 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
404 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
406 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
407 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
408 pformat->u1.dwRGBBitCount = 16;
409 pformat->u2.dwRBitMask = 0x0000F800;
410 pformat->u3.dwGBitMask = 0x000007C0;
411 pformat->u4.dwBBitMask = 0x0000003E;
412 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
413 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
414 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
416 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
417 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
418 pformat->u1.dwRGBBitCount = 16;
419 pformat->u2.dwRBitMask = 0x0000F000;
420 pformat->u3.dwGBitMask = 0x00000F00;
421 pformat->u4.dwBBitMask = 0x000000F0;
422 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
423 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
424 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
426 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
427 pformat->dwFlags = DDPF_RGB;
428 pformat->u1.dwRGBBitCount = 8;
429 pformat->u2.dwRBitMask = 0x000000E0;
430 pformat->u3.dwGBitMask = 0x0000001C;
431 pformat->u4.dwBBitMask = 0x00000003;
432 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
433 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
434 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
437 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
438 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
439 pformat->u1.dwRGBBitCount = 16;
440 pformat->u2.dwRBitMask = 0x00007C00;
441 pformat->u3.dwGBitMask = 0x000003E0;
442 pformat->u4.dwBBitMask = 0x0000001F;
443 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
444 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
445 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
447 TRACE("Enumerating Paletted (8)\n");
448 pformat->dwFlags = DDPF_PALETTEINDEXED8;
449 pformat->u1.dwRGBBitCount = 8;
450 pformat->u2.dwRBitMask = 0x00000000;
451 pformat->u3.dwGBitMask = 0x00000000;
452 pformat->u4.dwBBitMask = 0x00000000;
453 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
454 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
455 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
457 TRACE("End of enumeration\n");
463 d3ddevice_find(IDirect3DImpl *d3d,
464 LPD3DFINDDEVICESEARCH lpD3DDFS,
465 LPD3DFINDDEVICERESULT lplpD3DDevice,
466 DWORD interface_version)
471 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
472 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
473 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
474 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
476 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
477 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
478 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
479 (IsEqualGUID( &IID_D3DDEVICE2_OpenGL, &(lpD3DDFS->guid)) == 0) &&
480 (IsEqualGUID( &IID_D3DDEVICE3_OpenGL, &(lpD3DDFS->guid)) == 0) &&
481 (IsEqualGUID( &IID_D3DDEVICE7_OpenGL, &(lpD3DDFS->guid)) == 0) &&
482 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
483 TRACE(" no match for this GUID.\n");
484 return DDERR_INVALIDPARAMS;
488 /* Now return our own GUIDs according to Direct3D version */
489 if (interface_version == 1) {
490 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
491 } else if (interface_version == 2) {
492 lplpD3DDevice->guid = IID_D3DDEVICE2_OpenGL;
493 } else if (interface_version == 3) {
494 lplpD3DDevice->guid = IID_D3DDEVICE3_OpenGL;
496 fill_opengl_caps(&desc);
497 dwSize = lplpD3DDevice->ddHwDesc.dwSize;
498 memset(&(lplpD3DDevice->ddHwDesc), 0, dwSize);
499 memcpy(&(lplpD3DDevice->ddHwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
500 dwSize = lplpD3DDevice->ddSwDesc.dwSize;
501 memset(&(lplpD3DDevice->ddSwDesc), 0, dwSize);
502 memcpy(&(lplpD3DDevice->ddSwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
508 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
509 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
512 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
513 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
514 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
518 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
519 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
522 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
523 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
524 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
528 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
529 D3DRENDERSTATETYPE dwRenderStateType,
532 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
533 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
534 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
536 /* Call the render state functions */
537 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
543 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
544 D3DLIGHTSTATETYPE dwLightStateType,
547 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
548 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
550 switch (dwLightStateType) {
551 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
552 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
559 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
563 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
566 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
567 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
568 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
571 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
575 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
584 TRACE("Unexpected Light State Type\n");
585 return DDERR_INVALIDPARAMS;
592 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
593 D3DTRANSFORMSTATETYPE dtstTransformStateType,
594 LPD3DMATRIX lpD3DMatrix)
596 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
597 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
599 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
603 /* Using a trial and failure approach, I found that the order of
604 Direct3D transformations that works best is :
606 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
608 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
609 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
611 If anyone has a good explanation of the three different matrices in
612 the SDK online documentation, feel free to point it to me. For example,
613 which matrices transform lights ? In OpenGL only the PROJECTION matrix
614 transform the lights, not the MODELVIEW. Using the matrix names, I
615 supposed that PROJECTION and VIEW (all 'camera' related names) do
616 transform lights, but WORLD do not. It may be wrong though... */
618 /* After reading through both OpenGL and Direct3D documentations, I
619 thought that D3D matrices were written in 'line major mode' transposed
620 from OpenGL's 'column major mode'. But I found out that a simple memcpy
621 works fine to transfer one matrix format to the other (it did not work
622 when transposing)....
625 1) are the documentations wrong
626 2) does the matrix work even if they are not read correctly
627 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
628 loading using glLoadMatrix ?
630 Anyway, I always use 'conv_mat' to transfer the matrices from one format
631 to the other so that if I ever find out that I need to transpose them, I
632 will able to do it quickly, only by changing the macro conv_mat. */
634 switch (dtstTransformStateType) {
635 case D3DTRANSFORMSTATE_WORLD: {
636 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
637 conv_mat(lpD3DMatrix, glThis->world_mat);
638 glMatrixMode(GL_MODELVIEW);
639 glLoadMatrixf((float *) glThis->view_mat);
640 glMultMatrixf((float *) glThis->world_mat);
643 case D3DTRANSFORMSTATE_VIEW: {
644 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
645 conv_mat(lpD3DMatrix, glThis->view_mat);
646 glMatrixMode(GL_MODELVIEW);
647 glLoadMatrixf((float *) glThis->view_mat);
648 glMultMatrixf((float *) glThis->world_mat);
651 case D3DTRANSFORMSTATE_PROJECTION: {
652 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
653 conv_mat(lpD3DMatrix, glThis->proj_mat);
654 glMatrixMode(GL_PROJECTION);
655 glLoadMatrixf((float *) glThis->proj_mat);
659 ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
667 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
670 case D3DPT_POINTLIST:
671 TRACE("Start POINTS\n");
676 TRACE("Start LINES\n");
680 case D3DPT_LINESTRIP:
681 TRACE("Start LINE_STRIP\n");
682 glBegin(GL_LINE_STRIP);
685 case D3DPT_TRIANGLELIST:
686 TRACE("Start TRIANGLES\n");
687 glBegin(GL_TRIANGLES);
690 case D3DPT_TRIANGLESTRIP:
691 TRACE("Start TRIANGLE_STRIP\n");
692 glBegin(GL_TRIANGLE_STRIP);
695 case D3DPT_TRIANGLEFAN:
696 TRACE("Start TRIANGLE_FAN\n");
697 glBegin(GL_TRIANGLE_FAN);
701 TRACE("Unhandled primitive\n");
706 static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
707 BOOLEAN vertex_transformed,
708 BOOLEAN vertex_lit) {
709 /* Puts GL in the correct lighting / transformation mode */
710 if ((glThis->last_vertices_transformed == TRUE) && (vertex_transformed == FALSE)) {
711 /* Need to put the correct transformation again if we go from Transformed
712 vertices to non-transformed ones.
714 glMatrixMode(GL_MODELVIEW);
715 glLoadMatrixf((float *) glThis->view_mat);
716 glMultMatrixf((float *) glThis->world_mat);
717 glMatrixMode(GL_PROJECTION);
718 glLoadMatrixf((float *) glThis->proj_mat);
719 } else if ((glThis->last_vertices_transformed == FALSE) && (vertex_transformed == TRUE)) {
720 GLdouble height, width, minZ, maxZ;
722 glMatrixMode(GL_MODELVIEW);
724 glMatrixMode(GL_PROJECTION);
727 if (glThis->parent.current_viewport == NULL) {
728 ERR("No current viewport !\n");
729 /* Using standard values */
735 if (glThis->parent.current_viewport->use_vp2 == 1) {
736 height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
737 width = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
738 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
739 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
741 height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
742 width = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
743 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
744 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
747 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
750 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
751 glEnable(GL_LIGHTING);
752 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
753 glDisable(GL_LIGHTING);
756 /* And save the current state */
757 glThis->last_vertices_transformed = vertex_transformed;
758 glThis->last_vertices_lit = vertex_lit;
762 inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
763 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
767 draw_primitive_handle_GL_state(glThis, d3dvt == D3DVT_TLVERTEX, d3dvt != D3DVT_VERTEX);
768 draw_primitive_start_GL(d3dpt);
770 /* Draw the primitives */
771 for (vx_index = 0; vx_index < maxvert; vx_index++) {
774 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
776 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
777 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
778 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
781 case D3DVT_LVERTEX: {
782 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
783 DWORD col = vx->u4.color;
785 glColor3f(((col >> 16) & 0xFF) / 255.0,
786 ((col >> 8) & 0xFF) / 255.0,
787 ((col >> 0) & 0xFF) / 255.0);
788 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
789 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n",
790 vx->u1.x, vx->u2.y, vx->u3.z,
791 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));
794 case D3DVT_TLVERTEX: {
795 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
796 DWORD col = vx->u5.color;
798 glColor4ub((col >> 24) & 0xFF,
802 glTexCoord2f(vx->u7.tu, vx->u8.tv);
803 if (vx->u4.rhw < 0.01)
804 glVertex3f(vx->u1.sx,
808 glVertex4f(vx->u1.sx / vx->u4.rhw,
809 vx->u2.sy / vx->u4.rhw,
810 vx->u3.sz / vx->u4.rhw,
812 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",
813 vx->u1.sx, vx->u2.sy, vx->u3.sz,
814 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),
815 vx->u7.tu, vx->u8.tv, vx->u4.rhw);
819 FIXME("Unhandled vertex type\n");
829 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
830 D3DPRIMITIVETYPE d3dptPrimitiveType,
831 D3DVERTEXTYPE d3dvtVertexType,
836 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
837 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
840 draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
847 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
848 D3DPRIMITIVETYPE d3dptPrimitiveType,
849 D3DVERTEXTYPE d3dvtVertexType,
856 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
857 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
860 draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
867 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
868 LPD3DEXECUTEBUFFERDESC lpDesc,
869 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
872 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
873 IDirect3DExecuteBufferImpl *ret;
876 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
878 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
879 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
881 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
886 static void dump_flexible_vertex(DWORD d3dvtVertexType)
888 static const flag_info flags[] = {
890 FE(D3DFVF_RESERVED1),
894 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
895 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
896 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
897 GEN_CASE(D3DFVF_XYZ);
898 GEN_CASE(D3DFVF_XYZRHW);
899 GEN_CASE(D3DFVF_XYZB1);
900 GEN_CASE(D3DFVF_XYZB2);
901 GEN_CASE(D3DFVF_XYZB3);
902 GEN_CASE(D3DFVF_XYZB4);
903 GEN_CASE(D3DFVF_XYZB5);
905 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
906 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
907 GEN_CASE(D3DFVF_TEX0);
908 GEN_CASE(D3DFVF_TEX1);
909 GEN_CASE(D3DFVF_TEX2);
910 GEN_CASE(D3DFVF_TEX3);
911 GEN_CASE(D3DFVF_TEX4);
912 GEN_CASE(D3DFVF_TEX5);
913 GEN_CASE(D3DFVF_TEX6);
914 GEN_CASE(D3DFVF_TEX7);
915 GEN_CASE(D3DFVF_TEX8);
921 /* Some types used by the fast paths... */
935 static void draw_primitive_7(IDirect3DDeviceImpl *This,
936 D3DPRIMITIVETYPE d3dptPrimitiveType,
937 DWORD d3dvtVertexType,
944 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
945 if (TRACE_ON(ddraw)) {
946 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
950 draw_primitive_handle_GL_state(glThis,
951 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
952 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
953 draw_primitive_start_GL(d3dptPrimitiveType);
955 /* Some fast paths first before the generic case.... */
956 if (d3dvtVertexType == D3DFVF_VERTEX) {
957 D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
960 for (index = 0; index < dwIndexCount; index++) {
961 int i = (dwIndices == NULL) ? index : dwIndices[index];
963 glNormal3f(vertices[i].nx, vertices[i].ny, vertices[i].nz);
964 glTexCoord2f(vertices[i].tu1, vertices[i].tv1);
965 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
966 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
967 vertices[i].x, vertices[i].y, vertices[i].z,
968 vertices[i].nx, vertices[i].ny, vertices[i].nz,
969 vertices[i].tu1, vertices[i].tv1);
971 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
972 D3DFVF_TLVERTEX_1 *vertices = (D3DFVF_TLVERTEX_1 *) lpvVertices;
975 for (index = 0; index < dwIndexCount; index++) {
976 int i = (dwIndices == NULL) ? index : dwIndices[index];
978 glColor4ub((vertices[i].diffuse >> 24) & 0xFF,
979 (vertices[i].diffuse >> 16) & 0xFF,
980 (vertices[i].diffuse >> 8) & 0xFF,
981 (vertices[i].diffuse >> 0) & 0xFF);
982 /* Todo : handle specular... */
983 glTexCoord2f(vertices[i].tu1, vertices[i].tv1);
984 if (vertices[i].rhw < 0.00001)
985 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
987 glVertex4f(vertices[i].x / vertices[i].rhw,
988 vertices[i].y / vertices[i].rhw,
989 vertices[i].z / vertices[i].rhw,
990 1.0 / vertices[i].rhw);
991 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
992 vertices[i].x, vertices[i].y, vertices[i].z, vertices[i].rhw,
993 (vertices[i].diffuse >> 24) & 0xFF,
994 (vertices[i].diffuse >> 16) & 0xFF,
995 (vertices[i].diffuse >> 8) & 0xFF,
996 (vertices[i].diffuse >> 0) & 0xFF,
997 (vertices[i].specular >> 24) & 0xFF,
998 (vertices[i].specular >> 16) & 0xFF,
999 (vertices[i].specular >> 8) & 0xFF,
1000 (vertices[i].specular >> 0) & 0xFF,
1001 vertices[i].tu1, vertices[i].tv1);
1012 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1013 D3DPRIMITIVETYPE d3dptPrimitiveType,
1014 DWORD d3dvtVertexType,
1016 DWORD dwVertexCount,
1019 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1020 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1022 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1028 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1029 D3DPRIMITIVETYPE d3dptPrimitiveType,
1030 DWORD d3dvtVertexType,
1032 DWORD dwVertexCount,
1037 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1038 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1040 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1045 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1046 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1048 # define XCAST(fun) (void*)
1051 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1053 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1054 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1055 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1056 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1057 XCAST(GetCaps) Main_IDirect3DDeviceImpl_7_GetCaps,
1058 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1059 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1060 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1061 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1062 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1063 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1064 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1065 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1066 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1067 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1068 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1069 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1070 XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1071 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1072 XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1073 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1074 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1075 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1076 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1077 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1078 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1079 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1080 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1081 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1082 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1083 XCAST(DrawPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1084 XCAST(DrawIndexedPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1085 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1086 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1087 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1088 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1089 XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
1090 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1091 XCAST(SetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1092 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1093 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1094 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1095 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1096 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1097 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1098 XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1099 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1100 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1101 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1102 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1105 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1110 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1111 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1113 # define XCAST(fun) (void*)
1116 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1118 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1119 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1120 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1121 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1122 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1123 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1124 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1125 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1126 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1127 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1128 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1129 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1130 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1131 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1132 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1133 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1134 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1135 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1136 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1137 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1138 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1139 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1140 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1141 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1142 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1143 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1144 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1145 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1146 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1147 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1148 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1149 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1150 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1151 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1152 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1153 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1154 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1155 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1156 XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
1157 XCAST(SetTexture) Main_IDirect3DDeviceImpl_3_SetTexture,
1158 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1159 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1160 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1163 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1168 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1169 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1171 # define XCAST(fun) (void*)
1174 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1176 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1177 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1178 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1179 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1180 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1181 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1182 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1183 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1184 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1185 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1186 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1187 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1188 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1189 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1190 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1191 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1192 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1193 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1194 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1195 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1196 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1197 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1198 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1199 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1200 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1201 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1202 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1203 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1204 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1205 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1206 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1207 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1208 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1209 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1212 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1217 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1218 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1220 # define XCAST(fun) (void*)
1223 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1225 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1226 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1227 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1228 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1229 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1230 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1231 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1232 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1233 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1234 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1235 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1236 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1237 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1238 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1239 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1240 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1241 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1242 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1243 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1244 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1245 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1246 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1247 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1250 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1254 /* TODO for both these functions :
1255 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1256 by other OpenGL code in D3D
1257 - handle the case where no 'Begin / EndScene' was done between two locks
1258 - handle the rectangles in the unlock too
1259 - handle pitch correctly...
1261 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1263 /* First, check if we need to do anything */
1264 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1271 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1274 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1275 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1276 /* Application wants to lock the front buffer */
1277 glReadBuffer(GL_FRONT);
1278 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1279 /* Application wants to lock the back buffer */
1280 glReadBuffer(GL_BACK);
1282 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1285 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1286 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1288 WARN(" unsupported pixel format.\n");
1292 if (pRect == NULL) {
1295 loc_rect.bottom = This->surface_desc.dwHeight;
1296 loc_rect.right = This->surface_desc.dwWidth;
1300 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1301 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1302 + loc_rect.top * This->surface_desc.u1.lPitch
1303 + loc_rect.left * GET_BPP(This->surface_desc)));
1304 glReadBuffer(prev_read);
1309 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1311 /* First, check if we need to do anything */
1312 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1318 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1320 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1321 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1322 /* Application wants to lock the front buffer */
1323 glDrawBuffer(GL_FRONT);
1324 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1325 /* Application wants to lock the back buffer */
1326 glDrawBuffer(GL_BACK);
1328 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1331 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1332 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1334 WARN(" unsupported pixel format.\n");
1339 glRasterPos2f(0.0, 0.0);
1340 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1341 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1342 glDrawBuffer(prev_draw);
1349 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1351 IDirect3DDeviceImpl *object;
1352 IDirect3DDeviceGLImpl *gl_object;
1353 IDirectDrawSurfaceImpl *surf;
1357 XVisualInfo template;
1360 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1361 if (object == NULL) return DDERR_OUTOFMEMORY;
1363 gl_object = (IDirect3DDeviceGLImpl *) object;
1367 object->surface = surface;
1368 object->viewport_list = NULL;
1369 object->current_viewport = NULL;
1370 object->current_texture = NULL;
1371 object->set_context = set_context;
1373 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1375 device_context = GetDC(surface->ddraw_owner->window);
1376 gl_object->display = get_display(device_context);
1377 gl_object->drawable = get_drawable(device_context);
1378 ReleaseDC(surface->ddraw_owner->window,device_context);
1381 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1382 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1384 HeapFree(GetProcessHeap(), 0, object);
1385 ERR("No visual found !\n");
1387 return DDERR_INVALIDPARAMS;
1389 TRACE(" visual found\n");
1392 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1395 if (gl_object->gl_context == NULL) {
1396 HeapFree(GetProcessHeap(), 0, object);
1397 ERR("Error in context creation !\n");
1399 return DDERR_INVALIDPARAMS;
1401 TRACE(" context created (%p)\n", gl_object->gl_context);
1404 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1405 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1406 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1407 surf->aux_ctx = (LPVOID) gl_object->display;
1408 surf->aux_data = (LPVOID) gl_object->drawable;
1409 surf->aux_flip = opengl_flip;
1414 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1416 TRACE(" no double buffering : drawing on the front buffer\n");
1420 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1421 for (; surf != NULL; surf = surf->next_attached) {
1422 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1423 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1424 /* Override the Lock / Unlock function for all these surfaces */
1425 surf->lock_update = d3ddevice_lock_update;
1426 surf->unlock_update = d3ddevice_unlock_update;
1428 surf->d3ddevice = object;
1431 gl_object->render_state.src = GL_ONE;
1432 gl_object->render_state.dst = GL_ZERO;
1433 gl_object->render_state.mag = GL_NEAREST;
1434 gl_object->render_state.min = GL_NEAREST;
1436 /* Allocate memory for the matrices */
1437 gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1438 gl_object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1439 gl_object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1441 memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1442 memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1443 memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1445 /* Initialisation */
1446 TRACE(" setting current context\n");
1448 object->set_context(object);
1450 TRACE(" current context set\n");
1451 glClearColor(0.0, 0.0, 0.0, 0.0);
1452 glColor3f(1.0, 1.0, 1.0);
1453 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1454 glDrawBuffer(buffer);
1455 glReadBuffer(buffer);
1456 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1459 /* fill_device_capabilities(d3d->ddraw); */
1461 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
1462 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1463 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1464 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1468 TRACE(" creating implementation at %p.\n", *obj);