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 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
211 static void fill_device_capabilities(IDirectDrawImpl
* ddraw
)
213 x11_dd_private
*private = (x11_dd_private
*) ddraw
->d
->private;
214 const char *ext_string
;
215 Mesa_DeviceCapabilities
*devcap
;
217 private->device_capabilities
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Mesa_DeviceCapabilities
));
218 devcap
= (Mesa_DeviceCapabilities
*) private->device_capabilities
;
221 ext_string
= glGetString(GL_EXTENSIONS
);
222 /* Query for the ColorTable Extension */
223 if (strstr(ext_string
, "GL_EXT_paletted_texture")) {
224 devcap
->ptr_ColorTableEXT
= (PFNGLCOLORTABLEEXTPROC
) glXGetProcAddressARB("glColorTableEXT");
225 TRACE("Color table extension supported (function at %p)\n", devcap
->ptr_ColorTableEXT
);
227 TRACE("Color table extension not found.\n");
235 HRESULT
d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
, DWORD interface_version
)
237 D3DDEVICEDESC d1
, d2
;
239 const void *iid
= NULL
;
241 switch (interface_version
) {
242 case 1: iid
= &IID_D3DDEVICE_OpenGL
; break;
243 case 2: iid
= &IID_D3DDEVICE2_OpenGL
; break;
244 case 3: iid
= &IID_D3DDEVICE3_OpenGL
; break;
245 case 7: iid
= &IID_D3DDEVICE7_OpenGL
; break;
247 strcpy(buf
, "WINE Direct3DX using OpenGL");
248 buf
[13] = '0' + interface_version
;
250 fill_opengl_caps(&d1
);
253 TRACE(" enumerating OpenGL D3DDevice%ld interface (IID %s).\n", interface_version
, debugstr_guid(iid
));
254 return cb((LPGUID
) iid
, buf
, "direct3d", &d1
, &d2
, context
);
258 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface
)
260 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
261 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
263 TRACE("(%p/%p)->() decrementing from %lu.\n", This
, iface
, This
->ref
);
264 if (!--(This
->ref
)) {
265 /* Release texture associated with the device */
266 if (This
->current_texture
!= NULL
)
267 IDirect3DTexture2_Release(ICOM_INTERFACE(This
->current_texture
, IDirect3DTexture2
));
270 glXDestroyContext(glThis
->display
, glThis
->gl_context
);
273 HeapFree(GetProcessHeap(), 0, This
);
280 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface
,
281 LPD3DDEVICEDESC lpD3DHWDevDesc
,
282 LPD3DDEVICEDESC lpD3DHELDevDesc
)
284 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
288 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DHWDevDesc
, lpD3DHELDevDesc
);
290 fill_opengl_caps(&desc
);
291 dwSize
= lpD3DHWDevDesc
->dwSize
;
292 memset(lpD3DHWDevDesc
, 0, dwSize
);
293 memcpy(lpD3DHWDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
295 dwSize
= lpD3DHELDevDesc
->dwSize
;
296 memset(lpD3DHELDevDesc
, 0, dwSize
);
297 memcpy(lpD3DHELDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
299 TRACE(" returning caps : (no dump function yet)\n");
304 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1
,
305 LPD3DENUMPIXELFORMATSCALLBACK cb_2
,
309 LPDDPIXELFORMAT pformat
;
311 /* Do the texture enumeration */
312 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
313 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
314 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
315 pformat
= &(sdesc
.ddpfPixelFormat
);
316 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
317 pformat
->dwFourCC
= 0;
319 TRACE("Enumerating GL_RGBA unpacked (32)\n");
320 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
321 pformat
->u1
.dwRGBBitCount
= 32;
322 pformat
->u2
.dwRBitMask
= 0xFF000000;
323 pformat
->u3
.dwGBitMask
= 0x00FF0000;
324 pformat
->u4
.dwBBitMask
= 0x0000FF00;
325 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
326 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
327 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
329 TRACE("Enumerating GL_RGB unpacked (24)\n");
330 pformat
->dwFlags
= DDPF_RGB
;
331 pformat
->u1
.dwRGBBitCount
= 24;
332 pformat
->u2
.dwRBitMask
= 0x00FF0000;
333 pformat
->u3
.dwGBitMask
= 0x0000FF00;
334 pformat
->u4
.dwBBitMask
= 0x000000FF;
335 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
336 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
337 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
339 #ifndef HAVE_BUGGY_MESAGL
340 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
341 so that future version will work great. */
342 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
343 pformat
->dwFlags
= DDPF_RGB
;
344 pformat
->u1
.dwRGBBitCount
= 16;
345 pformat
->u2
.dwRBitMask
= 0x0000F800;
346 pformat
->u3
.dwGBitMask
= 0x000007E0;
347 pformat
->u4
.dwBBitMask
= 0x0000001F;
348 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
349 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
350 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
352 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
353 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
354 pformat
->u1
.dwRGBBitCount
= 16;
355 pformat
->u2
.dwRBitMask
= 0x0000F800;
356 pformat
->u3
.dwGBitMask
= 0x000007C0;
357 pformat
->u4
.dwBBitMask
= 0x0000003E;
358 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
359 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
360 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
362 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
363 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
364 pformat
->u1
.dwRGBBitCount
= 16;
365 pformat
->u2
.dwRBitMask
= 0x0000F000;
366 pformat
->u3
.dwGBitMask
= 0x00000F00;
367 pformat
->u4
.dwBBitMask
= 0x000000F0;
368 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
369 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
370 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
372 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
373 pformat
->dwFlags
= DDPF_RGB
;
374 pformat
->u1
.dwRGBBitCount
= 8;
375 pformat
->u2
.dwRBitMask
= 0x000000E0;
376 pformat
->u3
.dwGBitMask
= 0x0000001C;
377 pformat
->u4
.dwBBitMask
= 0x00000003;
378 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
379 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
380 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
383 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
384 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
385 pformat
->u1
.dwRGBBitCount
= 16;
386 pformat
->u2
.dwRBitMask
= 0x00007C00;
387 pformat
->u3
.dwGBitMask
= 0x000003E0;
388 pformat
->u4
.dwBBitMask
= 0x0000001F;
389 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
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 TRACE("Enumerating Paletted (8)\n");
394 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
395 pformat
->u1
.dwRGBBitCount
= 8;
396 pformat
->u2
.dwRBitMask
= 0x00000000;
397 pformat
->u3
.dwGBitMask
= 0x00000000;
398 pformat
->u4
.dwBBitMask
= 0x00000000;
399 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
400 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
401 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
403 TRACE("End of enumeration\n");
409 d3ddevice_find(IDirect3DImpl
*d3d
,
410 LPD3DFINDDEVICESEARCH lpD3DDFS
,
411 LPD3DFINDDEVICERESULT lplpD3DDevice
,
412 DWORD interface_version
)
417 if ((lpD3DDFS
->dwFlags
& D3DFDS_COLORMODEL
) &&
418 (lpD3DDFS
->dcmColorModel
!= D3DCOLOR_RGB
)) {
419 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
420 return DDERR_INVALIDPARAMS
; /* No real idea what to return here :-) */
422 if (lpD3DDFS
->dwFlags
& D3DFDS_GUID
) {
423 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS
->guid
)));
424 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
425 (IsEqualGUID( &IID_D3DDEVICE2_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
426 (IsEqualGUID( &IID_D3DDEVICE3_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
427 (IsEqualGUID( &IID_D3DDEVICE7_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
428 (IsEqualGUID(&IID_IDirect3DHALDevice
, &(lpD3DDFS
->guid
)) == 0)) {
429 TRACE(" no match for this GUID.\n");
430 return DDERR_INVALIDPARAMS
;
434 /* Now return our own GUIDs according to Direct3D version */
435 if (interface_version
== 1) {
436 lplpD3DDevice
->guid
= IID_D3DDEVICE_OpenGL
;
437 } else if (interface_version
== 2) {
438 lplpD3DDevice
->guid
= IID_D3DDEVICE2_OpenGL
;
439 } else if (interface_version
== 3) {
440 lplpD3DDevice
->guid
= IID_D3DDEVICE3_OpenGL
;
442 fill_opengl_caps(&desc
);
443 dwSize
= lplpD3DDevice
->ddHwDesc
.dwSize
;
444 memset(&(lplpD3DDevice
->ddHwDesc
), 0, dwSize
);
445 memcpy(&(lplpD3DDevice
->ddHwDesc
), &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
446 dwSize
= lplpD3DDevice
->ddSwDesc
.dwSize
;
447 memset(&(lplpD3DDevice
->ddSwDesc
), 0, dwSize
);
448 memcpy(&(lplpD3DDevice
->ddSwDesc
), &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
454 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface
,
455 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc
,
458 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
459 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumTextureProc
, lpArg
);
460 return enum_texture_format_OpenGL(lpD3DEnumTextureProc
, NULL
, lpArg
);
464 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface
,
465 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc
,
468 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
469 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumPixelProc
, lpArg
);
470 return enum_texture_format_OpenGL(NULL
, lpD3DEnumPixelProc
, lpArg
);
474 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface
,
475 D3DRENDERSTATETYPE dwRenderStateType
,
478 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
479 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
480 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwRenderStateType
, dwRenderState
);
482 /* Call the render state functions */
483 set_render_state(dwRenderStateType
, dwRenderState
, &(glThis
->render_state
));
489 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface
,
490 D3DLIGHTSTATETYPE dwLightStateType
,
493 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
494 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwLightStateType
, dwLightState
);
496 switch (dwLightStateType
) {
497 case D3DLIGHTSTATE_MATERIAL
: { /* 1 */
498 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) dwLightState
;
505 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
509 case D3DLIGHTSTATE_AMBIENT
: { /* 2 */
512 light
[0] = ((dwLightState
>> 16) & 0xFF) / 255.0;
513 light
[1] = ((dwLightState
>> 8) & 0xFF) / 255.0;
514 light
[2] = ((dwLightState
>> 0) & 0xFF) / 255.0;
517 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, (float *) light
);
521 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
530 TRACE("Unexpected Light State Type\n");
531 return DDERR_INVALIDPARAMS
;
538 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface
,
539 D3DTRANSFORMSTATETYPE dtstTransformStateType
,
540 LPD3DMATRIX lpD3DMatrix
)
542 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
543 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
545 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dtstTransformStateType
, lpD3DMatrix
);
549 /* Using a trial and failure approach, I found that the order of
550 Direct3D transformations that works best is :
552 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
554 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
555 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
557 If anyone has a good explanation of the three different matrices in
558 the SDK online documentation, feel free to point it to me. For example,
559 which matrices transform lights ? In OpenGL only the PROJECTION matrix
560 transform the lights, not the MODELVIEW. Using the matrix names, I
561 supposed that PROJECTION and VIEW (all 'camera' related names) do
562 transform lights, but WORLD do not. It may be wrong though... */
564 /* After reading through both OpenGL and Direct3D documentations, I
565 thought that D3D matrices were written in 'line major mode' transposed
566 from OpenGL's 'column major mode'. But I found out that a simple memcpy
567 works fine to transfer one matrix format to the other (it did not work
568 when transposing)....
571 1) are the documentations wrong
572 2) does the matrix work even if they are not read correctly
573 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
574 loading using glLoadMatrix ?
576 Anyway, I always use 'conv_mat' to transfer the matrices from one format
577 to the other so that if I ever find out that I need to transpose them, I
578 will able to do it quickly, only by changing the macro conv_mat. */
580 switch (dtstTransformStateType
) {
581 case D3DTRANSFORMSTATE_WORLD
: {
582 conv_mat(lpD3DMatrix
, glThis
->world_mat
);
583 glMatrixMode(GL_MODELVIEW
);
584 glLoadMatrixf((float *) glThis
->world_mat
);
587 case D3DTRANSFORMSTATE_VIEW
: {
588 conv_mat(lpD3DMatrix
, glThis
->view_mat
);
589 glMatrixMode(GL_PROJECTION
);
590 glLoadMatrixf((float *) glThis
->proj_mat
);
591 glMultMatrixf((float *) glThis
->view_mat
);
594 case D3DTRANSFORMSTATE_PROJECTION
: {
595 conv_mat(lpD3DMatrix
, glThis
->proj_mat
);
596 glMatrixMode(GL_PROJECTION
);
597 glLoadMatrixf((float *) glThis
->proj_mat
);
598 glMultMatrixf((float *) glThis
->view_mat
);
602 ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType
);
610 inline static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt
)
613 case D3DPT_POINTLIST
:
614 TRACE("Start POINTS\n");
619 TRACE("Start LINES\n");
623 case D3DPT_LINESTRIP
:
624 TRACE("Start LINE_STRIP\n");
625 glBegin(GL_LINE_STRIP
);
628 case D3DPT_TRIANGLELIST
:
629 TRACE("Start TRIANGLES\n");
630 glBegin(GL_TRIANGLES
);
633 case D3DPT_TRIANGLESTRIP
:
634 TRACE("Start TRIANGLE_STRIP\n");
635 glBegin(GL_TRIANGLE_STRIP
);
638 case D3DPT_TRIANGLEFAN
:
639 TRACE("Start TRIANGLE_FAN\n");
640 glBegin(GL_TRIANGLE_FAN
);
644 TRACE("Unhandled primitive\n");
649 inline static void draw_primitive(IDirect3DDeviceGLImpl
*glThis
, DWORD maxvert
, WORD
*index
,
650 D3DVERTEXTYPE d3dvt
, D3DPRIMITIVETYPE d3dpt
, void *lpvertex
)
654 /* Puts GL in the correct lighting mode */
655 if (glThis
->vertex_type
!= d3dvt
) {
656 if ((glThis
->vertex_type
== D3DVT_TLVERTEX
) &&
657 (d3dvt
!= D3DVT_TLVERTEX
)) {
658 /* Need to put the correct transformation again if we go from Transformed / Lighted
659 vertices to non-transfromed ones.
661 glMatrixMode(GL_MODELVIEW
);
662 glLoadMatrixf((float *) glThis
->world_mat
);
663 glMatrixMode(GL_PROJECTION
);
664 glLoadMatrixf((float *) glThis
->proj_mat
);
665 glMultMatrixf((float *) glThis
->view_mat
);
670 TRACE("Standard Vertex\n");
671 glEnable(GL_LIGHTING
);
675 TRACE("Lighted Vertex\n");
676 glDisable(GL_LIGHTING
);
679 case D3DVT_TLVERTEX
: {
680 GLdouble height
, width
, minZ
, maxZ
;
682 TRACE("Transformed - Lighted Vertex\n");
683 if (glThis
->vertex_type
!= D3DVT_TLVERTEX
) {
684 /* First, disable lighting */
685 glDisable(GL_LIGHTING
);
687 /* Then do not put any transformation matrixes */
688 glMatrixMode(GL_MODELVIEW
);
690 glMatrixMode(GL_PROJECTION
);
694 if (glThis
->parent
.current_viewport
== NULL
) {
695 ERR("No current viewport !\n");
696 /* Using standard values */
702 if (glThis
->parent
.current_viewport
->use_vp2
== 1) {
703 height
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp2
.dwHeight
;
704 width
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp2
.dwWidth
;
705 minZ
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp2
.dvMinZ
;
706 maxZ
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp2
.dvMaxZ
;
708 height
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp1
.dwHeight
;
709 width
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp1
.dwWidth
;
710 minZ
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp1
.dvMinZ
;
711 maxZ
= (GLdouble
) glThis
->parent
.current_viewport
->viewports
.vp1
.dvMaxZ
;
715 glOrtho(0.0, width
, height
, 0.0, -minZ
, -maxZ
);
719 ERR("Unhandled vertex type\n");
723 glThis
->vertex_type
= d3dvt
;
726 draw_primitive_start_GL(d3dpt
);
728 /* Draw the primitives */
729 for (vx_index
= 0; vx_index
< maxvert
; vx_index
++) {
732 D3DVERTEX
*vx
= ((D3DVERTEX
*) lpvertex
) + (index
== 0 ? vx_index
: index
[vx_index
]);
734 glNormal3f(vx
->u4
.nx
, vx
->u5
.ny
, vx
->u6
.nz
);
735 glVertex3f(vx
->u1
.x
, vx
->u2
.y
, vx
->u3
.z
);
736 TRACE(" V: %f %f %f\n", vx
->u1
.x
, vx
->u2
.y
, vx
->u3
.z
);
739 case D3DVT_LVERTEX
: {
740 D3DLVERTEX
*vx
= ((D3DLVERTEX
*) lpvertex
) + (index
== 0 ? vx_index
: index
[vx_index
]);
741 DWORD col
= vx
->u4
.color
;
743 glColor3f(((col
>> 16) & 0xFF) / 255.0,
744 ((col
>> 8) & 0xFF) / 255.0,
745 ((col
>> 0) & 0xFF) / 255.0);
746 glVertex3f(vx
->u1
.x
, vx
->u2
.y
, vx
->u3
.z
);
747 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n",
748 vx
->u1
.x
, vx
->u2
.y
, vx
->u3
.z
,
749 ((col
>> 16) & 0xFF), ((col
>> 8) & 0xFF), ((col
>> 0) & 0xFF));
752 case D3DVT_TLVERTEX
: {
753 D3DTLVERTEX
*vx
= ((D3DTLVERTEX
*) lpvertex
) + (index
== 0 ? vx_index
: index
[vx_index
]);
754 DWORD col
= vx
->u5
.color
;
756 glColor4ub((col
>> 24) & 0xFF,
760 glTexCoord2f(vx
->u7
.tu
, vx
->u8
.tv
);
761 if (vx
->u4
.rhw
< 0.01)
762 glVertex3f(vx
->u1
.sx
,
766 glVertex4f(vx
->u1
.sx
/ vx
->u4
.rhw
,
767 vx
->u2
.sy
/ vx
->u4
.rhw
,
768 vx
->u3
.sz
/ vx
->u4
.rhw
,
770 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",
771 vx
->u1
.sx
, vx
->u2
.sy
, vx
->u3
.sz
,
772 ((col
>> 16) & 0xFF), ((col
>> 8) & 0xFF), ((col
>> 0) & 0xFF),
773 vx
->u7
.tu
, vx
->u8
.tv
, vx
->u4
.rhw
);
777 FIXME("Unhandled vertex type\n");
787 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface
,
788 D3DPRIMITIVETYPE d3dptPrimitiveType
,
789 D3DVERTEXTYPE d3dvtVertexType
,
794 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
795 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
798 draw_primitive((IDirect3DDeviceGLImpl
*) This
, dwVertexCount
, NULL
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
805 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface
,
806 D3DPRIMITIVETYPE d3dptPrimitiveType
,
807 D3DVERTEXTYPE d3dvtVertexType
,
814 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
815 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
818 draw_primitive((IDirect3DDeviceGLImpl
*) This
, dwIndexCount
, dwIndices
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
825 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface
,
826 LPD3DEXECUTEBUFFERDESC lpDesc
,
827 LPDIRECT3DEXECUTEBUFFER
* lplpDirect3DExecuteBuffer
,
830 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice
, iface
);
831 IDirect3DExecuteBufferImpl
*ret
;
834 TRACE("(%p/%p)->(%p,%p,%p)\n", This
, iface
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
836 ret_value
= d3dexecutebuffer_create(&ret
, This
->d3d
, This
, lpDesc
);
837 *lplpDirect3DExecuteBuffer
= ICOM_INTERFACE(ret
, IDirect3DExecuteBuffer
);
839 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer
);
844 static void dump_flexible_vertex(DWORD d3dvtVertexType
)
846 static const flag_info flags
[] = {
848 FE(D3DFVF_RESERVED1
),
852 if (d3dvtVertexType
& D3DFVF_RESERVED0
) DPRINTF("D3DFVF_RESERVED0 ");
853 switch (d3dvtVertexType
& D3DFVF_POSITION_MASK
) {
854 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
855 GEN_CASE(D3DFVF_XYZ
);
856 GEN_CASE(D3DFVF_XYZRHW
);
857 GEN_CASE(D3DFVF_XYZB1
);
858 GEN_CASE(D3DFVF_XYZB2
);
859 GEN_CASE(D3DFVF_XYZB3
);
860 GEN_CASE(D3DFVF_XYZB4
);
861 GEN_CASE(D3DFVF_XYZB5
);
863 DDRAW_dump_flags_(d3dvtVertexType
, flags
, sizeof(flags
)/sizeof(flags
[0]), FALSE
);
864 switch (d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) {
865 GEN_CASE(D3DFVF_TEX0
);
866 GEN_CASE(D3DFVF_TEX1
);
867 GEN_CASE(D3DFVF_TEX2
);
868 GEN_CASE(D3DFVF_TEX3
);
869 GEN_CASE(D3DFVF_TEX4
);
870 GEN_CASE(D3DFVF_TEX5
);
871 GEN_CASE(D3DFVF_TEX6
);
872 GEN_CASE(D3DFVF_TEX7
);
873 GEN_CASE(D3DFVF_TEX8
);
879 /* Some types used by the fast paths... */
887 static void draw_primitive_7(IDirect3DDeviceImpl
*This
,
888 D3DPRIMITIVETYPE d3dptPrimitiveType
,
889 DWORD d3dvtVertexType
,
896 if (TRACE_ON(ddraw
)) {
897 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType
);
901 draw_primitive_start_GL(d3dptPrimitiveType
);
903 /* Some fast paths first before the generic case.... */
904 if (d3dvtVertexType
== D3DFVF_VERTEX
) {
905 D3DFVF_VERTEX_1
*vertices
= (D3DFVF_VERTEX_1
*) lpvVertices
;
908 for (index
= 0; index
< dwIndexCount
; index
++) {
909 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
911 glNormal3f(vertices
[i
].nx
, vertices
[i
].ny
, vertices
[i
].nz
);
912 glTexCoord2f(vertices
[i
].tu1
, vertices
[i
].tv1
);
913 glColor4ub((vertices
[i
].dwDiffuseRGBA
>> 24) & 0xFF,
914 (vertices
[i
].dwDiffuseRGBA
>> 16) & 0xFF,
915 (vertices
[i
].dwDiffuseRGBA
>> 8) & 0xFF,
916 (vertices
[i
].dwDiffuseRGBA
>> 0) & 0xFF);
917 glVertex3f(vertices
[i
].x
, vertices
[i
].y
, vertices
[i
].z
);
918 TRACE(" %f %f %f / %f %f %f (%02lx %02lx %02lx %02lx) (%f %f)\n",
919 vertices
[i
].x
, vertices
[i
].y
, vertices
[i
].z
,
920 vertices
[i
].nx
, vertices
[i
].ny
, vertices
[i
].nz
,
921 (vertices
[i
].dwDiffuseRGBA
>> 24) & 0xFF,
922 (vertices
[i
].dwDiffuseRGBA
>> 16) & 0xFF,
923 (vertices
[i
].dwDiffuseRGBA
>> 8) & 0xFF,
924 (vertices
[i
].dwDiffuseRGBA
>> 0) & 0xFF,
925 vertices
[i
].tu1
, vertices
[i
].tv1
);
936 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface
,
937 D3DPRIMITIVETYPE d3dptPrimitiveType
,
938 DWORD d3dvtVertexType
,
943 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
944 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
946 draw_primitive_7(This
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
952 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface
,
953 D3DPRIMITIVETYPE d3dptPrimitiveType
,
954 DWORD d3dvtVertexType
,
961 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
962 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
964 draw_primitive_7(This
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
969 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
970 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
972 # define XCAST(fun) (void*)
975 ICOM_VTABLE(IDirect3DDevice7
) VTABLE_IDirect3DDevice7
=
977 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
978 XCAST(QueryInterface
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface
,
979 XCAST(AddRef
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef
,
980 XCAST(Release
) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release
,
981 XCAST(GetCaps
) Main_IDirect3DDeviceImpl_7_GetCaps
,
982 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats
,
983 XCAST(BeginScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene
,
984 XCAST(EndScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene
,
985 XCAST(GetDirect3D
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D
,
986 XCAST(SetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget
,
987 XCAST(GetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget
,
988 XCAST(Clear
) Main_IDirect3DDeviceImpl_7_Clear
,
989 XCAST(SetTransform
) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform
,
990 XCAST(GetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform
,
991 XCAST(SetViewport
) Main_IDirect3DDeviceImpl_7_SetViewport
,
992 XCAST(MultiplyTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform
,
993 XCAST(GetViewport
) Main_IDirect3DDeviceImpl_7_GetViewport
,
994 XCAST(SetMaterial
) Main_IDirect3DDeviceImpl_7_SetMaterial
,
995 XCAST(GetMaterial
) Main_IDirect3DDeviceImpl_7_GetMaterial
,
996 XCAST(SetLight
) Main_IDirect3DDeviceImpl_7_SetLight
,
997 XCAST(GetLight
) Main_IDirect3DDeviceImpl_7_GetLight
,
998 XCAST(SetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState
,
999 XCAST(GetRenderState
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState
,
1000 XCAST(BeginStateBlock
) Main_IDirect3DDeviceImpl_7_BeginStateBlock
,
1001 XCAST(EndStateBlock
) Main_IDirect3DDeviceImpl_7_EndStateBlock
,
1002 XCAST(PreLoad
) Main_IDirect3DDeviceImpl_7_PreLoad
,
1003 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive
,
1004 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive
,
1005 XCAST(SetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus
,
1006 XCAST(GetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus
,
1007 XCAST(DrawPrimitiveStrided
) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided
,
1008 XCAST(DrawIndexedPrimitiveStrided
) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided
,
1009 XCAST(DrawPrimitiveVB
) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB
,
1010 XCAST(DrawIndexedPrimitiveVB
) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB
,
1011 XCAST(ComputeSphereVisibility
) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility
,
1012 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_7_GetTexture
,
1013 XCAST(SetTexture
) Main_IDirect3DDeviceImpl_7_SetTexture
,
1014 XCAST(GetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState
,
1015 XCAST(SetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_SetTextureStageState
,
1016 XCAST(ValidateDevice
) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice
,
1017 XCAST(ApplyStateBlock
) Main_IDirect3DDeviceImpl_7_ApplyStateBlock
,
1018 XCAST(CaptureStateBlock
) Main_IDirect3DDeviceImpl_7_CaptureStateBlock
,
1019 XCAST(DeleteStateBlock
) Main_IDirect3DDeviceImpl_7_DeleteStateBlock
,
1020 XCAST(CreateStateBlock
) Main_IDirect3DDeviceImpl_7_CreateStateBlock
,
1021 XCAST(Load
) Main_IDirect3DDeviceImpl_7_Load
,
1022 XCAST(LightEnable
) Main_IDirect3DDeviceImpl_7_LightEnable
,
1023 XCAST(GetLightEnable
) Main_IDirect3DDeviceImpl_7_GetLightEnable
,
1024 XCAST(SetClipPlane
) Main_IDirect3DDeviceImpl_7_SetClipPlane
,
1025 XCAST(GetClipPlane
) Main_IDirect3DDeviceImpl_7_GetClipPlane
,
1026 XCAST(GetInfo
) Main_IDirect3DDeviceImpl_7_GetInfo
,
1029 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1034 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1035 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1037 # define XCAST(fun) (void*)
1040 ICOM_VTABLE(IDirect3DDevice3
) VTABLE_IDirect3DDevice3
=
1042 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1043 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_3_QueryInterface
,
1044 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_3_AddRef
,
1045 XCAST(Release
) Thunk_IDirect3DDeviceImpl_3_Release
,
1046 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps
,
1047 XCAST(GetStats
) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats
,
1048 XCAST(AddViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport
,
1049 XCAST(DeleteViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport
,
1050 XCAST(NextViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport
,
1051 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats
,
1052 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_3_BeginScene
,
1053 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_3_EndScene
,
1054 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_3_GetDirect3D
,
1055 XCAST(SetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport
,
1056 XCAST(GetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport
,
1057 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget
,
1058 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget
,
1059 XCAST(Begin
) Main_IDirect3DDeviceImpl_3_Begin
,
1060 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_3_BeginIndexed
,
1061 XCAST(Vertex
) Main_IDirect3DDeviceImpl_3_2T_Vertex
,
1062 XCAST(Index
) Main_IDirect3DDeviceImpl_3_2T_Index
,
1063 XCAST(End
) Main_IDirect3DDeviceImpl_3_2T_End
,
1064 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_3_GetRenderState
,
1065 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_3_SetRenderState
,
1066 XCAST(GetLightState
) Main_IDirect3DDeviceImpl_3_2T_GetLightState
,
1067 XCAST(SetLightState
) GL_IDirect3DDeviceImpl_3_2T_SetLightState
,
1068 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_3_SetTransform
,
1069 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_3_GetTransform
,
1070 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform
,
1071 XCAST(DrawPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive
,
1072 XCAST(DrawIndexedPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive
,
1073 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_3_SetClipStatus
,
1074 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_3_GetClipStatus
,
1075 XCAST(DrawPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided
,
1076 XCAST(DrawIndexedPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided
,
1077 XCAST(DrawPrimitiveVB
) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB
,
1078 XCAST(DrawIndexedPrimitiveVB
) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB
,
1079 XCAST(ComputeSphereVisibility
) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility
,
1080 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_3_GetTexture
,
1081 XCAST(SetTexture
) Main_IDirect3DDeviceImpl_3_SetTexture
,
1082 XCAST(GetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState
,
1083 XCAST(SetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState
,
1084 XCAST(ValidateDevice
) Thunk_IDirect3DDeviceImpl_3_ValidateDevice
,
1087 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1092 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1093 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1095 # define XCAST(fun) (void*)
1098 ICOM_VTABLE(IDirect3DDevice2
) VTABLE_IDirect3DDevice2
=
1100 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1101 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_2_QueryInterface
,
1102 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_2_AddRef
,
1103 XCAST(Release
) Thunk_IDirect3DDeviceImpl_2_Release
,
1104 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_2_GetCaps
,
1105 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_2_SwapTextureHandles
,
1106 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_2_GetStats
,
1107 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_2_AddViewport
,
1108 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_2_DeleteViewport
,
1109 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_2_NextViewport
,
1110 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats
,
1111 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_2_BeginScene
,
1112 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_2_EndScene
,
1113 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_2_GetDirect3D
,
1114 XCAST(SetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport
,
1115 XCAST(GetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport
,
1116 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget
,
1117 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget
,
1118 XCAST(Begin
) Main_IDirect3DDeviceImpl_2_Begin
,
1119 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_2_BeginIndexed
,
1120 XCAST(Vertex
) Thunk_IDirect3DDeviceImpl_2_Vertex
,
1121 XCAST(Index
) Thunk_IDirect3DDeviceImpl_2_Index
,
1122 XCAST(End
) Thunk_IDirect3DDeviceImpl_2_End
,
1123 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_2_GetRenderState
,
1124 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_2_SetRenderState
,
1125 XCAST(GetLightState
) Thunk_IDirect3DDeviceImpl_2_GetLightState
,
1126 XCAST(SetLightState
) Thunk_IDirect3DDeviceImpl_2_SetLightState
,
1127 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_2_SetTransform
,
1128 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_2_GetTransform
,
1129 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform
,
1130 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_2_DrawPrimitive
,
1131 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive
,
1132 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_2_SetClipStatus
,
1133 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_2_GetClipStatus
,
1136 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1141 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1142 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1144 # define XCAST(fun) (void*)
1147 ICOM_VTABLE(IDirect3DDevice
) VTABLE_IDirect3DDevice
=
1149 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1150 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_1_QueryInterface
,
1151 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_1_AddRef
,
1152 XCAST(Release
) Thunk_IDirect3DDeviceImpl_1_Release
,
1153 XCAST(Initialize
) Main_IDirect3DDeviceImpl_1_Initialize
,
1154 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_1_GetCaps
,
1155 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_1_SwapTextureHandles
,
1156 XCAST(CreateExecuteBuffer
) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer
,
1157 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_1_GetStats
,
1158 XCAST(Execute
) Main_IDirect3DDeviceImpl_1_Execute
,
1159 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_1_AddViewport
,
1160 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_1_DeleteViewport
,
1161 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_1_NextViewport
,
1162 XCAST(Pick
) Main_IDirect3DDeviceImpl_1_Pick
,
1163 XCAST(GetPickRecords
) Main_IDirect3DDeviceImpl_1_GetPickRecords
,
1164 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats
,
1165 XCAST(CreateMatrix
) Main_IDirect3DDeviceImpl_1_CreateMatrix
,
1166 XCAST(SetMatrix
) Main_IDirect3DDeviceImpl_1_SetMatrix
,
1167 XCAST(GetMatrix
) Main_IDirect3DDeviceImpl_1_GetMatrix
,
1168 XCAST(DeleteMatrix
) Main_IDirect3DDeviceImpl_1_DeleteMatrix
,
1169 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_1_BeginScene
,
1170 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_1_EndScene
,
1171 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_1_GetDirect3D
,
1174 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1178 /* TODO for both these functions :
1179 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1180 by other OpenGL code in D3D
1181 - handle the case where no 'Begin / EndScene' was done between two locks
1182 - handle the rectangles in the unlock too
1184 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
1186 /* First, check if we need to do anything */
1187 if ((This
->lastlocktype
& DDLOCK_WRITEONLY
) == 0) {
1194 glGetIntegerv(GL_READ_BUFFER
, &prev_read
);
1197 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1198 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
1199 /* Application wants to lock the front buffer */
1200 glReadBuffer(GL_FRONT
);
1201 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
1202 /* Application wants to lock the back buffer */
1203 glReadBuffer(GL_BACK
);
1205 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1208 if (This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) {
1209 buffer_type
= GL_UNSIGNED_SHORT_5_6_5
;
1211 WARN(" unsupported pixel format.\n");
1215 if (pRect
== NULL
) {
1218 loc_rect
.bottom
= This
->surface_desc
.dwHeight
;
1219 loc_rect
.right
= This
->surface_desc
.dwWidth
;
1223 glReadPixels(loc_rect
.left
, loc_rect
.top
, loc_rect
.right
, loc_rect
.bottom
,
1224 GL_RGB
, buffer_type
, ((char *)This
->surface_desc
.lpSurface
1225 + loc_rect
.top
* This
->surface_desc
.u1
.lPitch
1226 + loc_rect
.left
* GET_BPP(This
->surface_desc
)));
1227 glReadBuffer(prev_read
);
1232 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
1234 /* First, check if we need to do anything */
1235 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0) {
1241 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
1243 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1244 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
1245 /* Application wants to lock the front buffer */
1246 glDrawBuffer(GL_FRONT
);
1247 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
1248 /* Application wants to lock the back buffer */
1249 glDrawBuffer(GL_BACK
);
1251 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1254 if (This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) {
1255 buffer_type
= GL_UNSIGNED_SHORT_5_6_5
;
1257 WARN(" unsupported pixel format.\n");
1262 glDrawPixels(This
->surface_desc
.dwWidth
, This
->surface_desc
.dwHeight
,
1263 GL_RGB
, buffer_type
, This
->surface_desc
.lpSurface
);
1264 glDrawBuffer(prev_draw
);
1271 d3ddevice_create(IDirect3DDeviceImpl
**obj
, IDirect3DImpl
*d3d
, IDirectDrawSurfaceImpl
*surface
)
1273 IDirect3DDeviceImpl
*object
;
1274 IDirect3DDeviceGLImpl
*gl_object
;
1275 IDirectDrawSurfaceImpl
*surf
;
1279 XVisualInfo
template;
1282 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DDeviceGLImpl
));
1283 if (object
== NULL
) return DDERR_OUTOFMEMORY
;
1285 gl_object
= (IDirect3DDeviceGLImpl
*) object
;
1289 object
->surface
= surface
;
1290 object
->viewport_list
= NULL
;
1291 object
->current_viewport
= NULL
;
1292 object
->current_texture
= NULL
;
1293 object
->set_context
= set_context
;
1295 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface
, d3d
);
1297 device_context
= GetDC(surface
->ddraw_owner
->window
);
1298 gl_object
->display
= get_display(device_context
);
1299 gl_object
->drawable
= get_drawable(device_context
);
1300 ReleaseDC(surface
->ddraw_owner
->window
,device_context
);
1303 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1304 vis
= XGetVisualInfo(gl_object
->display
, VisualIDMask
, &template, &num
);
1306 HeapFree(GetProcessHeap(), 0, object
);
1307 ERR("No visual found !\n");
1309 return DDERR_INVALIDPARAMS
;
1311 TRACE(" visual found\n");
1314 gl_object
->gl_context
= glXCreateContext(gl_object
->display
, vis
,
1317 if (gl_object
->gl_context
== NULL
) {
1318 HeapFree(GetProcessHeap(), 0, object
);
1319 ERR("Error in context creation !\n");
1321 return DDERR_INVALIDPARAMS
;
1323 TRACE(" context created (%p)\n", gl_object
->gl_context
);
1326 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1327 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
1328 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
1329 surf
->aux_ctx
= (LPVOID
) gl_object
->display
;
1330 surf
->aux_data
= (LPVOID
) gl_object
->drawable
;
1331 surf
->aux_flip
= opengl_flip
;
1336 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1338 TRACE(" no double buffering : drawing on the front buffer\n");
1342 for (surf
= surface
; surf
->prev_attached
!= NULL
; surf
= surf
->prev_attached
) ;
1343 for (; surf
!= NULL
; surf
= surf
->next_attached
) {
1344 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
1345 ((surf
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
1346 /* Override the Lock / Unlock function for all these surfaces */
1347 surf
->lock_update
= d3ddevice_lock_update
;
1348 surf
->unlock_update
= d3ddevice_unlock_update
;
1350 surf
->d3ddevice
= object
;
1353 gl_object
->render_state
.src
= GL_ONE
;
1354 gl_object
->render_state
.dst
= GL_ZERO
;
1355 gl_object
->render_state
.mag
= GL_NEAREST
;
1356 gl_object
->render_state
.min
= GL_NEAREST
;
1357 gl_object
->vertex_type
= 0;
1359 /* Allocate memory for the matrices */
1360 gl_object
->world_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
1361 gl_object
->view_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
1362 gl_object
->proj_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
1364 memcpy(gl_object
->world_mat
, id_mat
, 16 * sizeof(float));
1365 memcpy(gl_object
->view_mat
, id_mat
, 16 * sizeof(float));
1366 memcpy(gl_object
->proj_mat
, id_mat
, 16 * sizeof(float));
1368 /* Initialisation */
1369 TRACE(" setting current context\n");
1371 object
->set_context(object
);
1373 TRACE(" current context set\n");
1374 glClearColor(0.0, 0.0, 0.0, 0.0);
1375 glColor3f(1.0, 1.0, 1.0);
1376 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1377 glDrawBuffer(buffer
);
1378 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1381 /* fill_device_capabilities(d3d->ddraw); */
1383 ICOM_INIT_INTERFACE(object
, IDirect3DDevice
, VTABLE_IDirect3DDevice
);
1384 ICOM_INIT_INTERFACE(object
, IDirect3DDevice2
, VTABLE_IDirect3DDevice2
);
1385 ICOM_INIT_INTERFACE(object
, IDirect3DDevice3
, VTABLE_IDirect3DDevice3
);
1386 ICOM_INIT_INTERFACE(object
, IDirect3DDevice7
, VTABLE_IDirect3DDevice7
);
1390 TRACE(" creating implementation at %p.\n", *obj
);