Make sure that no files except unknwn.h include wine/obj_base.h
[wine/hacks.git] / dlls / ddraw / d3ddevice / mesa.c
blob967c88f6366b155350943c41adddef4c03460702
1 /* Direct3D Device
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
5 * Wine supports.
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
22 #include "config.h"
24 #include <string.h>
26 #include "windef.h"
27 #include "winerror.h"
28 #include "objbase.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
33 #include "mesa_private.h"
34 #include "main.h"
36 #include "x11drv.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 = {
42 0x31416d44,
43 0x86ae,
44 0x11d2,
45 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
48 /* Define this variable if you have an unpatched Mesa 3.0 (patches are available
49 on Mesa's home page) or version 3.1b.
51 Version 3.1b2 should correct this bug */
52 #undef HAVE_BUGGY_MESAGL
54 #ifndef HAVE_GLEXT_PROTOTYPES
55 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
56 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
57 GLsizei width, GLenum format, GLenum type,
58 const GLvoid *table);
59 #endif
61 static const float id_mat[16] = {
62 1.0, 0.0, 0.0, 0.0,
63 0.0, 1.0, 0.0, 0.0,
64 0.0, 0.0, 1.0, 0.0,
65 0.0, 0.0, 0.0, 1.0
68 /* retrieve the X display to use on a given DC */
69 inline static Display *get_display( HDC hdc )
71 Display *display;
72 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
74 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
75 sizeof(display), (LPSTR)&display )) display = NULL;
77 return display;
81 /* retrieve the X drawable to use on a given DC */
82 inline static Drawable get_drawable( HDC hdc )
84 Drawable drawable;
85 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
87 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
88 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
90 return drawable;
94 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
96 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
97 ENTER_GL();
98 glXSwapBuffers((Display*)display,(Drawable)drawable);
99 LEAVE_GL();
100 return TRUE;
104 /*******************************************************************************
105 * OpenGL static functions
107 static void set_context(IDirect3DDeviceImpl* This)
109 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
111 ENTER_GL();
112 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
113 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
114 ERR("Error in setting current context (context %p drawable %ld)!\n",
115 glThis->gl_context, glThis->drawable);
117 LEAVE_GL();
120 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
122 pc->dwSize = sizeof(*pc);
123 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
124 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
125 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
126 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
127 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
128 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
129 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
130 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
131 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
132 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
133 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
134 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
135 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
136 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
137 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
138 pc->dwStippleWidth = 32;
139 pc->dwStippleHeight = 32;
142 static void fill_opengl_caps(D3DDEVICEDESC *d1)
144 /* GLint maxlight; */
146 d1->dwSize = sizeof(*d1);
147 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
148 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
149 d1->dcmColorModel = D3DCOLOR_RGB;
150 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
151 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
152 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
153 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
154 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
155 d1->bClipping = TRUE;
156 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
157 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
158 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
159 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
160 fill_opengl_primcaps(&(d1->dpcLineCaps));
161 fill_opengl_primcaps(&(d1->dpcTriCaps));
162 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
163 d1->dwDeviceZBufferBitDepth = DDBD_16;
164 d1->dwMaxBufferSize = 0;
165 d1->dwMaxVertexCount = 65536;
166 d1->dwMinTextureWidth = 1;
167 d1->dwMinTextureHeight = 1;
168 d1->dwMaxTextureWidth = 1024;
169 d1->dwMaxTextureHeight = 1024;
170 d1->dwMinStippleWidth = 1;
171 d1->dwMinStippleHeight = 1;
172 d1->dwMaxStippleWidth = 32;
173 d1->dwMaxStippleHeight = 32;
174 d1->dwMaxTextureRepeat = 16;
175 d1->dwMaxTextureAspectRatio = 1024;
176 d1->dwMaxAnisotropy = 0;
177 d1->dvGuardBandLeft = 0.0;
178 d1->dvGuardBandRight = 0.0;
179 d1->dvGuardBandTop = 0.0;
180 d1->dvGuardBandBottom = 0.0;
181 d1->dvExtentsAdjust = 0.0;
182 d1->dwStencilCaps = 0; /* TODO add proper caps according to what OpenGL can do */
183 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
184 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
185 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
186 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
189 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
191 D3DDEVICEDESC d1;
193 /* Copy first D3D1/2/3 capabilities */
194 fill_opengl_caps(&d1);
196 /* And fill the D3D7 one with it */
197 d->dwDevCaps = d1.dwDevCaps;
198 d->dpcLineCaps = d1.dpcLineCaps;
199 d->dpcTriCaps = d1.dpcTriCaps;
200 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
201 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
202 d->dwMinTextureWidth = d1.dwMinTextureWidth;
203 d->dwMinTextureHeight = d1.dwMinTextureHeight;
204 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
205 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
206 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
207 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
208 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
209 d->dvGuardBandLeft = d1.dvGuardBandLeft;
210 d->dvGuardBandTop = d1.dvGuardBandTop;
211 d->dvGuardBandRight = d1.dvGuardBandRight;
212 d->dvGuardBandBottom = d1.dvGuardBandBottom;
213 d->dvExtentsAdjust = d1.dvExtentsAdjust;
214 d->dwStencilCaps = d1.dwStencilCaps;
215 d->dwFVFCaps = d1.dwFVFCaps;
216 d->dwTextureOpCaps = d1.dwTextureOpCaps;
217 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
218 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
219 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
220 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
221 d->deviceGUID = IID_IDirect3DTnLHalDevice;
222 d->wMaxUserClipPlanes = 1;
223 d->wMaxVertexBlendMatrices = 0;
224 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
225 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
226 d->dwReserved1 = 0;
227 d->dwReserved2 = 0;
228 d->dwReserved3 = 0;
229 d->dwReserved4 = 0;
232 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
233 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
235 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
236 const char *ext_string;
237 Mesa_DeviceCapabilities *devcap;
239 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
240 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
242 ENTER_GL();
243 ext_string = glGetString(GL_EXTENSIONS);
244 /* Query for the ColorTable Extension */
245 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
246 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
247 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
248 } else {
249 TRACE("Color table extension not found.\n");
251 LEAVE_GL();
253 #endif
257 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
259 D3DDEVICEDESC d1, d2;
261 fill_opengl_caps(&d1);
262 d2 = d1;
264 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
265 return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
268 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
270 D3DDEVICEDESC7 ddesc;
272 fill_opengl_caps_7(&ddesc);
274 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
276 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
279 ULONG WINAPI
280 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
282 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
283 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
285 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
286 if (!--(This->ref)) {
287 /* Release texture associated with the device */
288 if (This->current_texture[0] != NULL)
289 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
291 ENTER_GL();
292 glXDestroyContext(glThis->display, glThis->gl_context);
293 LEAVE_GL();
295 HeapFree(GetProcessHeap(), 0, This);
296 return 0;
298 return This->ref;
301 HRESULT WINAPI
302 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
303 LPD3DDEVICEDESC lpD3DHWDevDesc,
304 LPD3DDEVICEDESC lpD3DHELDevDesc)
306 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
307 D3DDEVICEDESC desc;
308 DWORD dwSize;
310 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
312 fill_opengl_caps(&desc);
313 dwSize = lpD3DHWDevDesc->dwSize;
314 memset(lpD3DHWDevDesc, 0, dwSize);
315 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
317 dwSize = lpD3DHELDevDesc->dwSize;
318 memset(lpD3DHELDevDesc, 0, dwSize);
319 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
321 TRACE(" returning caps : (no dump function yet)\n");
323 return DD_OK;
326 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
327 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
328 LPVOID context)
330 DDSURFACEDESC sdesc;
331 LPDDPIXELFORMAT pformat;
333 /* Do the texture enumeration */
334 sdesc.dwSize = sizeof(DDSURFACEDESC);
335 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
336 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
337 pformat = &(sdesc.ddpfPixelFormat);
338 pformat->dwSize = sizeof(DDPIXELFORMAT);
339 pformat->dwFourCC = 0;
341 TRACE("Enumerating GL_RGBA unpacked (32)\n");
342 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
343 pformat->u1.dwRGBBitCount = 32;
344 pformat->u2.dwRBitMask = 0xFF000000;
345 pformat->u3.dwGBitMask = 0x00FF0000;
346 pformat->u4.dwBBitMask = 0x0000FF00;
347 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
348 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
349 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
351 TRACE("Enumerating GL_RGB unpacked (24)\n");
352 pformat->dwFlags = DDPF_RGB;
353 pformat->u1.dwRGBBitCount = 24;
354 pformat->u2.dwRBitMask = 0x00FF0000;
355 pformat->u3.dwGBitMask = 0x0000FF00;
356 pformat->u4.dwBBitMask = 0x000000FF;
357 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
358 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
359 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
361 #ifndef HAVE_BUGGY_MESAGL
362 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
363 so that future version will work great. */
364 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
365 pformat->dwFlags = DDPF_RGB;
366 pformat->u1.dwRGBBitCount = 16;
367 pformat->u2.dwRBitMask = 0x0000F800;
368 pformat->u3.dwGBitMask = 0x000007E0;
369 pformat->u4.dwBBitMask = 0x0000001F;
370 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
371 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
372 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
374 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
375 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
376 pformat->u1.dwRGBBitCount = 16;
377 pformat->u2.dwRBitMask = 0x0000F800;
378 pformat->u3.dwGBitMask = 0x000007C0;
379 pformat->u4.dwBBitMask = 0x0000003E;
380 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
381 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
382 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
384 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
385 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
386 pformat->u1.dwRGBBitCount = 16;
387 pformat->u2.dwRBitMask = 0x0000F000;
388 pformat->u3.dwGBitMask = 0x00000F00;
389 pformat->u4.dwBBitMask = 0x000000F0;
390 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
391 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
392 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
394 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
395 pformat->dwFlags = DDPF_RGB;
396 pformat->u1.dwRGBBitCount = 8;
397 pformat->u2.dwRBitMask = 0x000000E0;
398 pformat->u3.dwGBitMask = 0x0000001C;
399 pformat->u4.dwBBitMask = 0x00000003;
400 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
401 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
402 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
403 #endif
405 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
406 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
407 pformat->u1.dwRGBBitCount = 16;
408 pformat->u2.dwRBitMask = 0x00007C00;
409 pformat->u3.dwGBitMask = 0x000003E0;
410 pformat->u4.dwBBitMask = 0x0000001F;
411 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
412 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
413 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
415 TRACE("Enumerating Paletted (8)\n");
416 pformat->dwFlags = DDPF_PALETTEINDEXED8;
417 pformat->u1.dwRGBBitCount = 8;
418 pformat->u2.dwRBitMask = 0x00000000;
419 pformat->u3.dwGBitMask = 0x00000000;
420 pformat->u4.dwBBitMask = 0x00000000;
421 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
422 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
423 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
425 TRACE("End of enumeration\n");
426 return DD_OK;
430 HRESULT
431 d3ddevice_find(IDirect3DImpl *d3d,
432 LPD3DFINDDEVICESEARCH lpD3DDFS,
433 LPD3DFINDDEVICERESULT lplpD3DDevice)
435 DWORD dwSize;
436 D3DDEVICEDESC desc;
438 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
439 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
440 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
441 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
443 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
444 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
445 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
446 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
447 TRACE(" no match for this GUID.\n");
448 return DDERR_INVALIDPARAMS;
452 /* Now return our own GUID */
453 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
454 fill_opengl_caps(&desc);
455 dwSize = lplpD3DDevice->ddHwDesc.dwSize;
456 memset(&(lplpD3DDevice->ddHwDesc), 0, dwSize);
457 memcpy(&(lplpD3DDevice->ddHwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
458 dwSize = lplpD3DDevice->ddSwDesc.dwSize;
459 memset(&(lplpD3DDevice->ddSwDesc), 0, dwSize);
460 memcpy(&(lplpD3DDevice->ddSwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
462 return D3D_OK;
465 HRESULT WINAPI
466 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
467 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
468 LPVOID lpArg)
470 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
471 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
472 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
475 HRESULT WINAPI
476 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
477 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
478 LPVOID lpArg)
480 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
481 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
482 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
485 HRESULT WINAPI
486 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
487 D3DRENDERSTATETYPE dwRenderStateType,
488 DWORD dwRenderState)
490 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
491 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
492 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
494 /* Call the render state functions */
495 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
497 return DD_OK;
500 HRESULT WINAPI
501 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
502 D3DLIGHTSTATETYPE dwLightStateType,
503 DWORD dwLightState)
505 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
506 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
508 switch (dwLightStateType) {
509 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
510 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
512 if (mat != NULL) {
513 ENTER_GL();
514 mat->activate(mat);
515 LEAVE_GL();
516 } else {
517 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
519 } break;
521 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
522 float light[4];
524 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
525 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
526 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
527 light[3] = 1.0;
528 ENTER_GL();
529 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
530 LEAVE_GL();
531 } break;
533 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
534 UNSUP(COLORMODEL);
535 UNSUP(FOGMODE);
536 UNSUP(FOGSTART);
537 UNSUP(FOGEND);
538 UNSUP(FOGDENSITY);
539 UNSUP(COLORVERTEX);
540 #undef UNSUP
542 default:
543 TRACE("Unexpected Light State Type\n");
544 return DDERR_INVALIDPARAMS;
547 return DD_OK;
550 HRESULT WINAPI
551 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
552 D3DTRANSFORMSTATETYPE dtstTransformStateType,
553 LPD3DMATRIX lpD3DMatrix)
555 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
556 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
558 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
560 ENTER_GL();
562 /* Using a trial and failure approach, I found that the order of
563 Direct3D transformations that works best is :
565 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
567 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
568 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
570 If anyone has a good explanation of the three different matrices in
571 the SDK online documentation, feel free to point it to me. For example,
572 which matrices transform lights ? In OpenGL only the PROJECTION matrix
573 transform the lights, not the MODELVIEW. Using the matrix names, I
574 supposed that PROJECTION and VIEW (all 'camera' related names) do
575 transform lights, but WORLD do not. It may be wrong though... */
577 /* After reading through both OpenGL and Direct3D documentations, I
578 thought that D3D matrices were written in 'line major mode' transposed
579 from OpenGL's 'column major mode'. But I found out that a simple memcpy
580 works fine to transfer one matrix format to the other (it did not work
581 when transposing)....
583 So :
584 1) are the documentations wrong
585 2) does the matrix work even if they are not read correctly
586 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
587 loading using glLoadMatrix ?
589 Anyway, I always use 'conv_mat' to transfer the matrices from one format
590 to the other so that if I ever find out that I need to transpose them, I
591 will able to do it quickly, only by changing the macro conv_mat. */
593 switch (dtstTransformStateType) {
594 case D3DTRANSFORMSTATE_WORLD: {
595 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
596 conv_mat(lpD3DMatrix, glThis->world_mat);
597 glMatrixMode(GL_MODELVIEW);
598 glLoadMatrixf((float *) glThis->view_mat);
599 glMultMatrixf((float *) glThis->world_mat);
600 } break;
602 case D3DTRANSFORMSTATE_VIEW: {
603 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
604 conv_mat(lpD3DMatrix, glThis->view_mat);
605 glMatrixMode(GL_MODELVIEW);
606 glLoadMatrixf((float *) glThis->view_mat);
607 glMultMatrixf((float *) glThis->world_mat);
608 } break;
610 case D3DTRANSFORMSTATE_PROJECTION: {
611 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
612 conv_mat(lpD3DMatrix, glThis->proj_mat);
613 glMatrixMode(GL_PROJECTION);
614 glLoadMatrixf((float *) glThis->proj_mat);
615 } break;
617 default:
618 ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
619 break;
621 LEAVE_GL();
623 return DD_OK;
626 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
628 switch (d3dpt) {
629 case D3DPT_POINTLIST:
630 TRACE("Start POINTS\n");
631 glBegin(GL_POINTS);
632 break;
634 case D3DPT_LINELIST:
635 TRACE("Start LINES\n");
636 glBegin(GL_LINES);
637 break;
639 case D3DPT_LINESTRIP:
640 TRACE("Start LINE_STRIP\n");
641 glBegin(GL_LINE_STRIP);
642 break;
644 case D3DPT_TRIANGLELIST:
645 TRACE("Start TRIANGLES\n");
646 glBegin(GL_TRIANGLES);
647 break;
649 case D3DPT_TRIANGLESTRIP:
650 TRACE("Start TRIANGLE_STRIP\n");
651 glBegin(GL_TRIANGLE_STRIP);
652 break;
654 case D3DPT_TRIANGLEFAN:
655 TRACE("Start TRIANGLE_FAN\n");
656 glBegin(GL_TRIANGLE_FAN);
657 break;
659 default:
660 TRACE("Unhandled primitive\n");
661 break;
665 static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
666 BOOLEAN vertex_transformed,
667 BOOLEAN vertex_lit) {
668 /* Puts GL in the correct lighting / transformation mode */
669 if ((glThis->last_vertices_transformed == TRUE) && (vertex_transformed == FALSE)) {
670 /* Need to put the correct transformation again if we go from Transformed
671 vertices to non-transformed ones.
673 glMatrixMode(GL_MODELVIEW);
674 glLoadMatrixf((float *) glThis->view_mat);
675 glMultMatrixf((float *) glThis->world_mat);
676 glMatrixMode(GL_PROJECTION);
677 glLoadMatrixf((float *) glThis->proj_mat);
678 } else if ((glThis->last_vertices_transformed == FALSE) && (vertex_transformed == TRUE)) {
679 GLdouble height, width, minZ, maxZ;
681 glMatrixMode(GL_MODELVIEW);
682 glLoadIdentity();
683 glMatrixMode(GL_PROJECTION);
684 glLoadIdentity();
686 if (glThis->parent.current_viewport == NULL) {
687 ERR("No current viewport !\n");
688 /* Using standard values */
689 height = 640.0;
690 width = 480.0;
691 minZ = -10.0;
692 maxZ = 10.0;
693 } else {
694 if (glThis->parent.current_viewport->use_vp2 == 1) {
695 height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
696 width = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
697 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
698 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
699 } else {
700 height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
701 width = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
702 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
703 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
706 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
709 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
710 glEnable(GL_LIGHTING);
711 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
712 glDisable(GL_LIGHTING);
715 /* And save the current state */
716 glThis->last_vertices_transformed = vertex_transformed;
717 glThis->last_vertices_lit = vertex_lit;
721 inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
722 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
724 DWORD vx_index;
726 draw_primitive_handle_GL_state(glThis, d3dvt == D3DVT_TLVERTEX, d3dvt != D3DVT_VERTEX);
727 draw_primitive_start_GL(d3dpt);
729 /* Draw the primitives */
730 for (vx_index = 0; vx_index < maxvert; vx_index++) {
731 switch (d3dvt) {
732 case D3DVT_VERTEX: {
733 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
735 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
736 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
737 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
738 } break;
740 case D3DVT_LVERTEX: {
741 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
742 DWORD col = vx->u4.color;
744 glColor3f(((col >> 16) & 0xFF) / 255.0,
745 ((col >> 8) & 0xFF) / 255.0,
746 ((col >> 0) & 0xFF) / 255.0);
747 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
748 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n",
749 vx->u1.x, vx->u2.y, vx->u3.z,
750 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));
751 } break;
753 case D3DVT_TLVERTEX: {
754 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
755 DWORD col = vx->u5.color;
757 glColor4ub((col >> 24) & 0xFF,
758 (col >> 16) & 0xFF,
759 (col >> 8) & 0xFF,
760 (col >> 0) & 0xFF);
761 glTexCoord2f(vx->u7.tu, vx->u8.tv);
762 if (vx->u4.rhw < 0.01)
763 glVertex3f(vx->u1.sx,
764 vx->u2.sy,
765 vx->u3.sz);
766 else
767 glVertex4f(vx->u1.sx / vx->u4.rhw,
768 vx->u2.sy / vx->u4.rhw,
769 vx->u3.sz / vx->u4.rhw,
770 1.0 / vx->u4.rhw);
771 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",
772 vx->u1.sx, vx->u2.sy, vx->u3.sz,
773 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),
774 vx->u7.tu, vx->u8.tv, vx->u4.rhw);
775 } break;
777 default:
778 FIXME("Unhandled vertex type\n");
779 break;
783 glEnd();
784 TRACE("End\n");
787 HRESULT WINAPI
788 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
789 D3DPRIMITIVETYPE d3dptPrimitiveType,
790 D3DVERTEXTYPE d3dvtVertexType,
791 LPVOID lpvVertices,
792 DWORD dwVertexCount,
793 DWORD dwFlags)
795 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
796 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
798 ENTER_GL();
799 draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
800 LEAVE_GL();
802 return DD_OK;
805 HRESULT WINAPI
806 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
807 D3DPRIMITIVETYPE d3dptPrimitiveType,
808 D3DVERTEXTYPE d3dvtVertexType,
809 LPVOID lpvVertices,
810 DWORD dwVertexCount,
811 LPWORD dwIndices,
812 DWORD dwIndexCount,
813 DWORD dwFlags)
815 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
816 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
818 ENTER_GL();
819 draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
820 LEAVE_GL();
822 return DD_OK;
825 HRESULT WINAPI
826 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
827 LPD3DEXECUTEBUFFERDESC lpDesc,
828 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
829 IUnknown* pUnkOuter)
831 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
832 IDirect3DExecuteBufferImpl *ret;
833 HRESULT ret_value;
835 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
837 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
838 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
840 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
842 return ret_value;
845 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType)
847 DWORD size = 0;
849 if (d3dvtVertexType & D3DFVF_NORMAL) size += 3 * sizeof(D3DVALUE);
850 if (d3dvtVertexType & D3DFVF_DIFFUSE) size += sizeof(DWORD);
851 if (d3dvtVertexType & D3DFVF_SPECULAR) size += sizeof(DWORD);
852 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
853 case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); break;
854 case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); break;
855 default: TRACE(" matrix weighting not handled yet...\n");
857 size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
859 return size;
862 void dump_flexible_vertex(DWORD d3dvtVertexType)
864 static const flag_info flags[] = {
865 FE(D3DFVF_NORMAL),
866 FE(D3DFVF_RESERVED1),
867 FE(D3DFVF_DIFFUSE),
868 FE(D3DFVF_SPECULAR)
870 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
871 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
872 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
873 GEN_CASE(D3DFVF_XYZ);
874 GEN_CASE(D3DFVF_XYZRHW);
875 GEN_CASE(D3DFVF_XYZB1);
876 GEN_CASE(D3DFVF_XYZB2);
877 GEN_CASE(D3DFVF_XYZB3);
878 GEN_CASE(D3DFVF_XYZB4);
879 GEN_CASE(D3DFVF_XYZB5);
881 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
882 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
883 GEN_CASE(D3DFVF_TEX0);
884 GEN_CASE(D3DFVF_TEX1);
885 GEN_CASE(D3DFVF_TEX2);
886 GEN_CASE(D3DFVF_TEX3);
887 GEN_CASE(D3DFVF_TEX4);
888 GEN_CASE(D3DFVF_TEX5);
889 GEN_CASE(D3DFVF_TEX6);
890 GEN_CASE(D3DFVF_TEX7);
891 GEN_CASE(D3DFVF_TEX8);
893 #undef GEN_CASE
894 DPRINTF("\n");
897 /* Some types used by the fast paths... */
898 typedef struct {
899 float x, y, z;
900 float nx, ny, nz;
901 float tu1, tv1;
902 } D3DFVF_VERTEX_1;
904 typedef struct {
905 float x, y, z, rhw;
906 DWORD diffuse;
907 DWORD specular;
908 float tu1, tv1;
909 } D3DFVF_TLVERTEX_1;
911 static void draw_primitive_7(IDirect3DDeviceImpl *This,
912 D3DPRIMITIVETYPE d3dptPrimitiveType,
913 DWORD d3dvtVertexType,
914 LPVOID lpvVertices,
915 DWORD dwVertexCount,
916 LPWORD dwIndices,
917 DWORD dwIndexCount,
918 DWORD dwFlags)
920 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
921 if (TRACE_ON(ddraw)) {
922 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
925 ENTER_GL();
926 draw_primitive_handle_GL_state(glThis,
927 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
928 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
929 draw_primitive_start_GL(d3dptPrimitiveType);
931 /* Some fast paths first before the generic case.... */
932 if (d3dvtVertexType == D3DFVF_VERTEX) {
933 D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
934 int index;
936 for (index = 0; index < dwIndexCount; index++) {
937 int i = (dwIndices == NULL) ? index : dwIndices[index];
939 glNormal3f(vertices[i].nx, vertices[i].ny, vertices[i].nz);
940 glTexCoord2f(vertices[i].tu1, vertices[i].tv1);
941 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
942 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
943 vertices[i].x, vertices[i].y, vertices[i].z,
944 vertices[i].nx, vertices[i].ny, vertices[i].nz,
945 vertices[i].tu1, vertices[i].tv1);
947 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
948 D3DFVF_TLVERTEX_1 *vertices = (D3DFVF_TLVERTEX_1 *) lpvVertices;
949 int index;
951 for (index = 0; index < dwIndexCount; index++) {
952 int i = (dwIndices == NULL) ? index : dwIndices[index];
954 glColor4ub((vertices[i].diffuse >> 24) & 0xFF,
955 (vertices[i].diffuse >> 16) & 0xFF,
956 (vertices[i].diffuse >> 8) & 0xFF,
957 (vertices[i].diffuse >> 0) & 0xFF);
958 /* Todo : handle specular... */
959 glTexCoord2f(vertices[i].tu1, vertices[i].tv1);
960 if (vertices[i].rhw < 0.00001)
961 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
962 else
963 glVertex4f(vertices[i].x / vertices[i].rhw,
964 vertices[i].y / vertices[i].rhw,
965 vertices[i].z / vertices[i].rhw,
966 1.0 / vertices[i].rhw);
967 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
968 vertices[i].x, vertices[i].y, vertices[i].z, vertices[i].rhw,
969 (vertices[i].diffuse >> 24) & 0xFF,
970 (vertices[i].diffuse >> 16) & 0xFF,
971 (vertices[i].diffuse >> 8) & 0xFF,
972 (vertices[i].diffuse >> 0) & 0xFF,
973 (vertices[i].specular >> 24) & 0xFF,
974 (vertices[i].specular >> 16) & 0xFF,
975 (vertices[i].specular >> 8) & 0xFF,
976 (vertices[i].specular >> 0) & 0xFF,
977 vertices[i].tu1, vertices[i].tv1);
981 glEnd();
982 LEAVE_GL();
983 TRACE("End\n");
987 HRESULT WINAPI
988 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
989 D3DPRIMITIVETYPE d3dptPrimitiveType,
990 DWORD d3dvtVertexType,
991 LPVOID lpvVertices,
992 DWORD dwVertexCount,
993 DWORD dwFlags)
995 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
996 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
998 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1000 return DD_OK;
1003 HRESULT WINAPI
1004 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1005 D3DPRIMITIVETYPE d3dptPrimitiveType,
1006 DWORD d3dvtVertexType,
1007 LPVOID lpvVertices,
1008 DWORD dwVertexCount,
1009 LPWORD dwIndices,
1010 DWORD dwIndexCount,
1011 DWORD dwFlags)
1013 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1014 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1016 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1018 return DD_OK;
1021 HRESULT WINAPI
1022 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1023 DWORD dwStage,
1024 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1025 DWORD dwState)
1027 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1028 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1029 GLenum gl_state;
1031 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1033 if (TRACE_ON(ddraw)) {
1034 TRACE(" Stage type is : ");
1035 switch (d3dTexStageStateType) {
1036 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1037 GEN_CASE(D3DTSS_COLOROP);
1038 GEN_CASE(D3DTSS_COLORARG1);
1039 GEN_CASE(D3DTSS_COLORARG2);
1040 GEN_CASE(D3DTSS_ALPHAOP);
1041 GEN_CASE(D3DTSS_ALPHAARG1);
1042 GEN_CASE(D3DTSS_ALPHAARG2);
1043 GEN_CASE(D3DTSS_BUMPENVMAT00);
1044 GEN_CASE(D3DTSS_BUMPENVMAT01);
1045 GEN_CASE(D3DTSS_BUMPENVMAT10);
1046 GEN_CASE(D3DTSS_BUMPENVMAT11);
1047 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1048 GEN_CASE(D3DTSS_ADDRESS);
1049 GEN_CASE(D3DTSS_ADDRESSU);
1050 GEN_CASE(D3DTSS_ADDRESSV);
1051 GEN_CASE(D3DTSS_BORDERCOLOR);
1052 GEN_CASE(D3DTSS_MAGFILTER);
1053 GEN_CASE(D3DTSS_MINFILTER);
1054 GEN_CASE(D3DTSS_MIPFILTER);
1055 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1056 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1057 GEN_CASE(D3DTSS_MAXANISOTROPY);
1058 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1059 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1060 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1061 #undef GEN_CASE
1062 default: DPRINTF("UNKNOWN !!!");
1064 DPRINTF(" => ");
1067 switch (d3dTexStageStateType) {
1068 case D3DTSS_MINFILTER:
1069 switch ((D3DTEXTUREMINFILTER) dwState) {
1070 case D3DTFN_POINT:
1071 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1072 gl_state = GL_NEAREST;
1073 break;
1074 case D3DTFN_LINEAR:
1075 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1076 gl_state = GL_LINEAR;
1077 break;
1078 default:
1079 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1080 gl_state = GL_LINEAR;
1081 break;
1083 glThis->render_state.min = gl_state;
1084 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1085 break;
1087 case D3DTSS_MAGFILTER:
1088 switch ((D3DTEXTUREMAGFILTER) dwState) {
1089 case D3DTFG_POINT:
1090 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1091 gl_state = GL_NEAREST;
1092 break;
1093 case D3DTFG_LINEAR:
1094 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1095 gl_state = GL_LINEAR;
1096 break;
1097 default:
1098 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1099 gl_state = GL_LINEAR;
1100 break;
1102 glThis->render_state.mag = gl_state;
1103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1104 break;
1106 default:
1107 if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1110 return DD_OK;
1113 HRESULT WINAPI
1114 GL_IDirect3DDeviceImpl_3_SetTexture(LPDIRECT3DDEVICE3 iface,
1115 DWORD dwStage,
1116 LPDIRECT3DTEXTURE2 lpTexture2)
1118 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1120 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1122 if (This->current_texture[dwStage] != NULL) {
1123 /* Seems that this is not right... Need to test in real Windows
1124 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1127 ENTER_GL();
1128 if (lpTexture2 == NULL) {
1129 TRACE(" disabling 2D texturing.\n");
1130 glBindTexture(GL_TEXTURE_2D, 0);
1131 glDisable(GL_TEXTURE_2D);
1132 } else {
1133 IDirect3DTextureImpl *tex_impl = ICOM_OBJECT(IDirect3DTextureImpl, IDirect3DTexture2, lpTexture2);
1134 IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl;
1136 This->current_texture[dwStage] = tex_impl;
1137 IDirect3DTexture2_AddRef(lpTexture2);
1139 TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1141 glEnable(GL_TEXTURE_2D);
1142 glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1144 LEAVE_GL();
1146 return DD_OK;
1149 HRESULT WINAPI
1150 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1151 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1153 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1154 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1156 fill_opengl_caps_7(lpD3DHELDevDesc);
1158 TRACE(" returning caps : no dump function yet.\n");
1160 return DD_OK;
1163 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1164 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1165 #else
1166 # define XCAST(fun) (void*)
1167 #endif
1169 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1171 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1172 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1173 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1174 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1175 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1176 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1177 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1178 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1179 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1180 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1181 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1182 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1183 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1184 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1185 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1186 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1187 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1188 XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1189 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1190 XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1191 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1192 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1193 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1194 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1195 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1196 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1197 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1198 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1199 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1200 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1201 XCAST(DrawPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1202 XCAST(DrawIndexedPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1203 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1204 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1205 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1206 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1207 XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
1208 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1209 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1210 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1211 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1212 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1213 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1214 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1215 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1216 XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1217 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1218 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1219 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1220 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1223 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1224 #undef XCAST
1225 #endif
1228 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1229 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1230 #else
1231 # define XCAST(fun) (void*)
1232 #endif
1234 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1236 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1237 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1238 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1239 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1240 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1241 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1242 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1243 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1244 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1245 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1246 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1247 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1248 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1249 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1250 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1251 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1252 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1253 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1254 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1255 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1256 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1257 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1258 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1259 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1260 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1261 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1262 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1263 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1264 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1265 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1266 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1267 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1268 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1269 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1270 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1271 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1272 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1273 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1274 XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
1275 XCAST(SetTexture) GL_IDirect3DDeviceImpl_3_SetTexture,
1276 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1277 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1278 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1281 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1282 #undef XCAST
1283 #endif
1286 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1287 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1288 #else
1289 # define XCAST(fun) (void*)
1290 #endif
1292 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1294 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1295 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1296 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1297 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1298 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1299 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1300 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1301 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1302 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1303 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1304 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1305 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1306 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1307 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1308 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1309 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1310 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1311 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1312 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1313 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1314 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1315 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1316 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1317 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1318 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1319 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1320 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1321 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1322 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1323 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1324 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1325 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1326 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1327 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1330 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1331 #undef XCAST
1332 #endif
1335 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1336 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1337 #else
1338 # define XCAST(fun) (void*)
1339 #endif
1341 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1343 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1344 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1345 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1346 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1347 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1348 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1349 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1350 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1351 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1352 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1353 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1354 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1355 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1356 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1357 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1358 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1359 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1360 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1361 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1362 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1363 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1364 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1365 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1368 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1369 #undef XCAST
1370 #endif
1372 /* TODO for both these functions :
1373 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1374 by other OpenGL code in D3D
1375 - handle the case where no 'Begin / EndScene' was done between two locks
1376 - handle the rectangles in the unlock too
1377 - handle pitch correctly...
1379 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1381 /* First, check if we need to do anything */
1382 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1383 GLenum buffer_type;
1384 GLenum prev_read;
1385 RECT loc_rect;
1387 ENTER_GL();
1389 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1390 glFlush();
1392 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1393 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1394 /* Application wants to lock the front buffer */
1395 glReadBuffer(GL_FRONT);
1396 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1397 /* Application wants to lock the back buffer */
1398 glReadBuffer(GL_BACK);
1399 } else {
1400 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1403 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1404 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1405 } else {
1406 WARN(" unsupported pixel format.\n");
1407 LEAVE_GL();
1408 return;
1410 if (pRect == NULL) {
1411 loc_rect.top = 0;
1412 loc_rect.left = 0;
1413 loc_rect.bottom = This->surface_desc.dwHeight;
1414 loc_rect.right = This->surface_desc.dwWidth;
1415 } else {
1416 loc_rect = *pRect;
1418 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1419 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1420 + loc_rect.top * This->surface_desc.u1.lPitch
1421 + loc_rect.left * GET_BPP(This->surface_desc)));
1422 glReadBuffer(prev_read);
1423 LEAVE_GL();
1427 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1429 /* First, check if we need to do anything */
1430 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1431 GLenum buffer_type;
1432 GLenum prev_draw;
1434 ENTER_GL();
1436 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1438 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1439 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1440 /* Application wants to lock the front buffer */
1441 glDrawBuffer(GL_FRONT);
1442 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1443 /* Application wants to lock the back buffer */
1444 glDrawBuffer(GL_BACK);
1445 } else {
1446 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1449 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1450 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1451 } else {
1452 WARN(" unsupported pixel format.\n");
1453 LEAVE_GL();
1454 return;
1457 glRasterPos2f(0.0, 0.0);
1458 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1459 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1460 glDrawBuffer(prev_draw);
1462 LEAVE_GL();
1466 HRESULT
1467 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1469 IDirect3DDeviceImpl *object;
1470 IDirect3DDeviceGLImpl *gl_object;
1471 IDirectDrawSurfaceImpl *surf;
1472 HDC device_context;
1473 XVisualInfo *vis;
1474 int num;
1475 XVisualInfo template;
1476 GLenum buffer;
1478 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1479 if (object == NULL) return DDERR_OUTOFMEMORY;
1481 gl_object = (IDirect3DDeviceGLImpl *) object;
1483 object->ref = 1;
1484 object->d3d = d3d;
1485 object->surface = surface;
1486 object->set_context = set_context;
1488 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1490 device_context = GetDC(surface->ddraw_owner->window);
1491 gl_object->display = get_display(device_context);
1492 gl_object->drawable = get_drawable(device_context);
1493 ReleaseDC(surface->ddraw_owner->window,device_context);
1495 ENTER_GL();
1496 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1497 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1498 if (vis == NULL) {
1499 HeapFree(GetProcessHeap(), 0, object);
1500 ERR("No visual found !\n");
1501 LEAVE_GL();
1502 return DDERR_INVALIDPARAMS;
1503 } else {
1504 TRACE(" visual found\n");
1507 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1508 NULL, GL_TRUE);
1510 if (gl_object->gl_context == NULL) {
1511 HeapFree(GetProcessHeap(), 0, object);
1512 ERR("Error in context creation !\n");
1513 LEAVE_GL();
1514 return DDERR_INVALIDPARAMS;
1515 } else {
1516 TRACE(" context created (%p)\n", gl_object->gl_context);
1519 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1520 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1521 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1522 surf->aux_ctx = (LPVOID) gl_object->display;
1523 surf->aux_data = (LPVOID) gl_object->drawable;
1524 surf->aux_flip = opengl_flip;
1525 buffer = GL_BACK;
1526 break;
1529 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1530 if (surf == NULL) {
1531 TRACE(" no double buffering : drawing on the front buffer\n");
1532 buffer = GL_FRONT;
1535 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1536 for (; surf != NULL; surf = surf->next_attached) {
1537 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1538 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1539 /* Override the Lock / Unlock function for all these surfaces */
1540 surf->lock_update = d3ddevice_lock_update;
1541 surf->unlock_update = d3ddevice_unlock_update;
1543 surf->d3ddevice = object;
1546 gl_object->render_state.src = GL_ONE;
1547 gl_object->render_state.dst = GL_ZERO;
1548 gl_object->render_state.mag = GL_NEAREST;
1549 gl_object->render_state.min = GL_NEAREST;
1551 /* Allocate memory for the matrices */
1552 gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1553 gl_object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1554 gl_object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1556 memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1557 memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1558 memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1560 /* Initialisation */
1561 TRACE(" setting current context\n");
1562 LEAVE_GL();
1563 object->set_context(object);
1564 ENTER_GL();
1565 TRACE(" current context set\n");
1566 glClearColor(0.0, 0.0, 0.0, 0.0);
1567 glColor3f(1.0, 1.0, 1.0);
1568 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1569 glDrawBuffer(buffer);
1570 glReadBuffer(buffer);
1571 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1572 LEAVE_GL();
1574 /* fill_device_capabilities(d3d->ddraw); */
1576 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
1577 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1578 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1579 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1581 *obj = object;
1583 TRACE(" creating implementation at %p.\n", *obj);
1585 return DD_OK;