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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 #include "mesa_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom
);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
48 X11DRV_GET_FONT
, /* get current X font for a DC */
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL
= {
56 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
59 #ifndef HAVE_GLEXT_PROTOTYPES
60 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
61 typedef void (* PFNGLCOLORTABLEEXTPROC
) (GLenum target
, GLenum internalFormat
,
62 GLsizei width
, GLenum format
, GLenum type
,
66 const float id_mat
[16] = {
73 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
74 D3DPRIMITIVETYPE d3dptPrimitiveType
,
75 DWORD d3dvtVertexType
,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
82 /* retrieve the X display to use on a given DC */
83 inline static Display
*get_display( HDC hdc
)
86 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
88 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
89 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable
get_drawable( HDC hdc
)
99 enum x11drv_escape_codes escape
= X11DRV_GET_DRAWABLE
;
101 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
102 sizeof(drawable
), (LPSTR
)&drawable
)) drawable
= 0;
108 static BOOL
opengl_flip( LPVOID dev
, LPVOID drawable
)
110 IDirect3DDeviceImpl
*d3d_dev
= (IDirect3DDeviceImpl
*) dev
;
111 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) dev
;
113 TRACE("(%p, %ld)\n", gl_d3d_dev
->display
,(Drawable
)drawable
);
115 if (gl_d3d_dev
->state
== SURFACE_MEMORY_DIRTY
) {
116 d3d_dev
->flush_to_framebuffer(d3d_dev
, NULL
, gl_d3d_dev
->lock_surf
);
118 gl_d3d_dev
->state
= SURFACE_GL
;
119 gl_d3d_dev
->front_state
= SURFACE_GL
;
120 glXSwapBuffers(gl_d3d_dev
->display
, (Drawable
)drawable
);
127 /*******************************************************************************
128 * OpenGL static functions
130 static void set_context(IDirect3DDeviceImpl
* This
)
132 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
135 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis
->display
,glThis
->drawable
, glThis
->gl_context
);
136 if (glXMakeCurrent(glThis
->display
, glThis
->drawable
, glThis
->gl_context
) == False
) {
137 ERR("Error in setting current context (context %p drawable %ld)!\n",
138 glThis
->gl_context
, glThis
->drawable
);
143 static void fill_opengl_primcaps(D3DPRIMCAPS
*pc
)
145 pc
->dwSize
= sizeof(*pc
);
146 pc
->dwMiscCaps
= D3DPMISCCAPS_CONFORMANT
| D3DPMISCCAPS_CULLCCW
| D3DPMISCCAPS_CULLCW
|
147 D3DPMISCCAPS_LINEPATTERNREP
| D3DPMISCCAPS_MASKZ
;
148 pc
->dwRasterCaps
= D3DPRASTERCAPS_DITHER
| D3DPRASTERCAPS_FOGRANGE
| D3DPRASTERCAPS_FOGTABLE
|
149 D3DPRASTERCAPS_FOGVERTEX
| D3DPRASTERCAPS_STIPPLE
| D3DPRASTERCAPS_ZBIAS
| D3DPRASTERCAPS_ZTEST
| D3DPRASTERCAPS_SUBPIXEL
;
150 pc
->dwZCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
151 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
152 pc
->dwSrcBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_DESTCOLOR
| D3DPBLENDCAPS_INVDESTCOLOR
|
153 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
154 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
155 pc
->dwDestBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_SRCCOLOR
| D3DPBLENDCAPS_INVSRCCOLOR
|
156 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
157 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
158 pc
->dwAlphaCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
159 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
160 pc
->dwShadeCaps
= D3DPSHADECAPS_ALPHAFLATBLEND
| D3DPSHADECAPS_ALPHAGOURAUDBLEND
| D3DPSHADECAPS_COLORFLATRGB
| D3DPSHADECAPS_COLORGOURAUDRGB
|
161 D3DPSHADECAPS_FOGFLAT
| D3DPSHADECAPS_FOGGOURAUD
| D3DPSHADECAPS_SPECULARFLATRGB
| D3DPSHADECAPS_SPECULARGOURAUDRGB
;
162 pc
->dwTextureCaps
= D3DPTEXTURECAPS_ALPHA
| D3DPTEXTURECAPS_ALPHAPALETTE
| D3DPTEXTURECAPS_BORDER
| D3DPTEXTURECAPS_PERSPECTIVE
|
163 D3DPTEXTURECAPS_POW2
| D3DPTEXTURECAPS_TRANSPARENCY
;
164 pc
->dwTextureFilterCaps
= D3DPTFILTERCAPS_LINEAR
| D3DPTFILTERCAPS_LINEARMIPLINEAR
| D3DPTFILTERCAPS_LINEARMIPNEAREST
|
165 D3DPTFILTERCAPS_MIPLINEAR
| D3DPTFILTERCAPS_MIPNEAREST
| D3DPTFILTERCAPS_NEAREST
;
166 pc
->dwTextureBlendCaps
= D3DPTBLENDCAPS_ADD
| D3DPTBLENDCAPS_COPY
| D3DPTBLENDCAPS_DECAL
| D3DPTBLENDCAPS_DECALALPHA
| D3DPTBLENDCAPS_DECALMASK
|
167 D3DPTBLENDCAPS_MODULATE
| D3DPTBLENDCAPS_MODULATEALPHA
| D3DPTBLENDCAPS_MODULATEMASK
;
168 pc
->dwTextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
| D3DPTADDRESSCAPS_CLAMP
| D3DPTADDRESSCAPS_WRAP
| D3DPTADDRESSCAPS_INDEPENDENTUV
;
169 pc
->dwStippleWidth
= 32;
170 pc
->dwStippleHeight
= 32;
173 static void fill_opengl_caps(D3DDEVICEDESC
*d1
)
175 /* GLint maxlight; */
177 d1
->dwSize
= sizeof(*d1
);
178 d1
->dwFlags
= D3DDD_DEVCAPS
| D3DDD_BCLIPPING
| D3DDD_COLORMODEL
| D3DDD_DEVICERENDERBITDEPTH
| D3DDD_DEVICEZBUFFERBITDEPTH
179 | D3DDD_LIGHTINGCAPS
| D3DDD_LINECAPS
| D3DDD_MAXBUFFERSIZE
| D3DDD_MAXVERTEXCOUNT
| D3DDD_TRANSFORMCAPS
| D3DDD_TRICAPS
;
180 d1
->dcmColorModel
= D3DCOLOR_RGB
;
181 d1
->dwDevCaps
= D3DDEVCAPS_CANRENDERAFTERFLIP
| D3DDEVCAPS_DRAWPRIMTLVERTEX
| D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
182 D3DDEVCAPS_EXECUTEVIDEOMEMORY
| D3DDEVCAPS_FLOATTLVERTEX
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
| D3DDEVCAPS_TEXTURESYSTEMMEMORY
|
183 D3DDEVCAPS_TEXTUREVIDEOMEMORY
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
184 /* D3D 7 capabilities */
185 D3DDEVCAPS_DRAWPRIMITIVES2
| D3DDEVCAPS_HWTRANSFORMANDLIGHT
| D3DDEVCAPS_HWRASTERIZATION
;
186 d1
->dtcTransformCaps
.dwSize
= sizeof(D3DTRANSFORMCAPS
);
187 d1
->dtcTransformCaps
.dwCaps
= D3DTRANSFORMCAPS_CLIP
;
188 d1
->bClipping
= TRUE
;
189 d1
->dlcLightingCaps
.dwSize
= sizeof(D3DLIGHTINGCAPS
);
190 d1
->dlcLightingCaps
.dwCaps
= D3DLIGHTCAPS_DIRECTIONAL
| D3DLIGHTCAPS_PARALLELPOINT
| D3DLIGHTCAPS_POINT
| D3DLIGHTCAPS_SPOT
;
191 d1
->dlcLightingCaps
.dwLightingModel
= D3DLIGHTINGMODEL_RGB
;
192 d1
->dlcLightingCaps
.dwNumLights
= 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
193 fill_opengl_primcaps(&(d1
->dpcLineCaps
));
194 fill_opengl_primcaps(&(d1
->dpcTriCaps
));
195 d1
->dwDeviceRenderBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
;
196 d1
->dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
;
197 d1
->dwMaxBufferSize
= 0;
198 d1
->dwMaxVertexCount
= 65536;
199 d1
->dwMinTextureWidth
= 1;
200 d1
->dwMinTextureHeight
= 1;
201 d1
->dwMaxTextureWidth
= 1024;
202 d1
->dwMaxTextureHeight
= 1024;
203 d1
->dwMinStippleWidth
= 1;
204 d1
->dwMinStippleHeight
= 1;
205 d1
->dwMaxStippleWidth
= 32;
206 d1
->dwMaxStippleHeight
= 32;
207 d1
->dwMaxTextureRepeat
= 16;
208 d1
->dwMaxTextureAspectRatio
= 1024;
209 d1
->dwMaxAnisotropy
= 0;
210 d1
->dvGuardBandLeft
= 0.0;
211 d1
->dvGuardBandRight
= 0.0;
212 d1
->dvGuardBandTop
= 0.0;
213 d1
->dvGuardBandBottom
= 0.0;
214 d1
->dvExtentsAdjust
= 0.0;
215 d1
->dwStencilCaps
= D3DSTENCILCAPS_DECRSAT
| D3DSTENCILCAPS_INCRSAT
| D3DSTENCILCAPS_INVERT
| D3DSTENCILCAPS_KEEP
|
216 D3DSTENCILCAPS_REPLACE
| D3DSTENCILCAPS_ZERO
;
217 d1
->dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| 1;
218 d1
->dwTextureOpCaps
= 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1
->wMaxTextureBlendStages
= 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
220 d1
->wMaxSimultaneousTextures
= 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
223 static void fill_opengl_caps_7(D3DDEVICEDESC7
*d
)
227 /* Copy first D3D1/2/3 capabilities */
228 fill_opengl_caps(&d1
);
230 /* And fill the D3D7 one with it */
231 d
->dwDevCaps
= d1
.dwDevCaps
;
232 d
->dpcLineCaps
= d1
.dpcLineCaps
;
233 d
->dpcTriCaps
= d1
.dpcTriCaps
;
234 d
->dwDeviceRenderBitDepth
= d1
.dwDeviceRenderBitDepth
;
235 d
->dwDeviceZBufferBitDepth
= d1
.dwDeviceZBufferBitDepth
;
236 d
->dwMinTextureWidth
= d1
.dwMinTextureWidth
;
237 d
->dwMinTextureHeight
= d1
.dwMinTextureHeight
;
238 d
->dwMaxTextureWidth
= d1
.dwMaxTextureWidth
;
239 d
->dwMaxTextureHeight
= d1
.dwMaxTextureHeight
;
240 d
->dwMaxTextureRepeat
= d1
.dwMaxTextureRepeat
;
241 d
->dwMaxTextureAspectRatio
= d1
.dwMaxTextureAspectRatio
;
242 d
->dwMaxAnisotropy
= d1
.dwMaxAnisotropy
;
243 d
->dvGuardBandLeft
= d1
.dvGuardBandLeft
;
244 d
->dvGuardBandTop
= d1
.dvGuardBandTop
;
245 d
->dvGuardBandRight
= d1
.dvGuardBandRight
;
246 d
->dvGuardBandBottom
= d1
.dvGuardBandBottom
;
247 d
->dvExtentsAdjust
= d1
.dvExtentsAdjust
;
248 d
->dwStencilCaps
= d1
.dwStencilCaps
;
249 d
->dwFVFCaps
= d1
.dwFVFCaps
;
250 d
->dwTextureOpCaps
= d1
.dwTextureOpCaps
;
251 d
->wMaxTextureBlendStages
= d1
.wMaxTextureBlendStages
;
252 d
->wMaxSimultaneousTextures
= d1
.wMaxSimultaneousTextures
;
253 d
->dwMaxActiveLights
= d1
.dlcLightingCaps
.dwNumLights
;
254 d
->dvMaxVertexW
= 100000000.0; /* No idea exactly what to put here... */
255 d
->deviceGUID
= IID_IDirect3DTnLHalDevice
;
256 d
->wMaxUserClipPlanes
= 1;
257 d
->wMaxVertexBlendMatrices
= 0;
258 d
->dwVertexProcessingCaps
= D3DVTXPCAPS_TEXGEN
| D3DVTXPCAPS_MATERIALSOURCE7
| D3DVTXPCAPS_VERTEXFOG
| D3DVTXPCAPS_DIRECTIONALLIGHTS
|
259 D3DVTXPCAPS_POSITIONALLIGHTS
| D3DVTXPCAPS_LOCALVIEWER
;
266 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
267 static void fill_device_capabilities(IDirectDrawImpl
* ddraw
)
269 x11_dd_private
*private = (x11_dd_private
*) ddraw
->d
->private;
270 const char *ext_string
;
271 Mesa_DeviceCapabilities
*devcap
;
273 private->device_capabilities
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Mesa_DeviceCapabilities
));
274 devcap
= (Mesa_DeviceCapabilities
*) private->device_capabilities
;
277 ext_string
= glGetString(GL_EXTENSIONS
);
278 /* Query for the ColorTable Extension */
279 if (strstr(ext_string
, "GL_EXT_paletted_texture")) {
280 devcap
->ptr_ColorTableEXT
= (PFNGLCOLORTABLEEXTPROC
) glXGetProcAddressARB("glColorTableEXT");
281 TRACE("Color table extension supported (function at %p)\n", devcap
->ptr_ColorTableEXT
);
283 TRACE("Color table extension not found.\n");
291 HRESULT
d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb
, LPVOID context
, DWORD version
)
293 D3DDEVICEDESC dref
, d1
, d2
;
296 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
297 Let's put the string in a sufficiently sized array in writable memory. */
298 char device_name
[50];
299 strcpy(device_name
,"direct3d");
301 fill_opengl_caps(&dref
);
304 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
305 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice
));
308 ret_value
= cb((LPIID
) &IID_IDirect3DRefDevice
, "WINE Reference Direct3DX using OpenGL", device_name
, &d1
, &d2
, context
);
309 if (ret_value
!= D3DENUMRET_OK
)
313 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
316 ret_value
= cb((LPIID
) &IID_D3DDEVICE_OpenGL
, "WINE Direct3DX using OpenGL", device_name
, &d1
, &d2
, context
);
317 if (ret_value
!= D3DENUMRET_OK
)
320 return D3DENUMRET_OK
;
323 HRESULT
d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb
, LPVOID context
)
325 D3DDEVICEDESC7 ddesc
;
327 fill_opengl_caps_7(&ddesc
);
329 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
331 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc
, context
);
335 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface
)
337 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
338 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
340 TRACE("(%p/%p)->() decrementing from %lu.\n", This
, iface
, This
->ref
);
341 if (!--(This
->ref
)) {
343 IDirectDrawSurfaceImpl
*surface
= This
->surface
, *surf
;
345 /* Release texture associated with the device */
346 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
347 if (This
->current_texture
[i
] != NULL
)
348 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[i
], IDirectDrawSurface7
));
349 HeapFree(GetProcessHeap(), 0, This
->tex_mat
[i
]);
352 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
353 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
354 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
355 surf
->aux_ctx
= NULL
;
356 surf
->aux_data
= NULL
;
357 surf
->aux_flip
= NULL
;
361 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
362 IDirectDrawSurfaceImpl
*surf2
;
363 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
364 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
365 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
366 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
367 /* Override the Lock / Unlock function for all these surfaces */
368 surf2
->lock_update
= surf2
->lock_update_prev
;
369 surf2
->unlock_update
= surf2
->unlock_update_prev
;
370 /* And install also the blt / bltfast overrides */
371 surf2
->aux_blt
= NULL
;
372 surf2
->aux_bltfast
= NULL
;
374 surf2
->d3ddevice
= NULL
;
378 /* And warn the D3D object that this device is no longer active... */
379 This
->d3d
->removed_device(This
->d3d
, This
);
381 HeapFree(GetProcessHeap(), 0, This
->world_mat
);
382 HeapFree(GetProcessHeap(), 0, This
->view_mat
);
383 HeapFree(GetProcessHeap(), 0, This
->proj_mat
);
385 DeleteCriticalSection(&(This
->crit
));
388 if (glThis
->unlock_tex
)
389 glDeleteTextures(1, &(glThis
->unlock_tex
));
390 glXDestroyContext(glThis
->display
, glThis
->gl_context
);
392 HeapFree(GetProcessHeap(), 0, This
->clipping_planes
);
394 HeapFree(GetProcessHeap(), 0, This
);
401 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface
,
402 LPD3DDEVICEDESC lpD3DHWDevDesc
,
403 LPD3DDEVICEDESC lpD3DHELDevDesc
)
405 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
409 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DHWDevDesc
, lpD3DHELDevDesc
);
411 fill_opengl_caps(&desc
);
412 dwSize
= lpD3DHWDevDesc
->dwSize
;
413 memset(lpD3DHWDevDesc
, 0, dwSize
);
414 memcpy(lpD3DHWDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
416 dwSize
= lpD3DHELDevDesc
->dwSize
;
417 memset(lpD3DHELDevDesc
, 0, dwSize
);
418 memcpy(lpD3DHELDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
420 TRACE(" returning caps : (no dump function yet)\n");
425 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1
,
426 LPD3DENUMPIXELFORMATSCALLBACK cb_2
,
430 LPDDPIXELFORMAT pformat
;
432 /* Do the texture enumeration */
433 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
434 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
435 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
436 pformat
= &(sdesc
.ddpfPixelFormat
);
437 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
438 pformat
->dwFourCC
= 0;
441 /* See argument about the RGBA format for 'packed' texture formats */
442 TRACE("Enumerating GL_RGBA unpacked (32)\n");
443 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
444 pformat
->u1
.dwRGBBitCount
= 32;
445 pformat
->u2
.dwRBitMask
= 0xFF000000;
446 pformat
->u3
.dwGBitMask
= 0x00FF0000;
447 pformat
->u4
.dwBBitMask
= 0x0000FF00;
448 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
449 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
450 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
453 TRACE("Enumerating GL_RGBA unpacked (32)\n");
454 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
455 pformat
->u1
.dwRGBBitCount
= 32;
456 pformat
->u2
.dwRBitMask
= 0x00FF0000;
457 pformat
->u3
.dwGBitMask
= 0x0000FF00;
458 pformat
->u4
.dwBBitMask
= 0x000000FF;
459 pformat
->u5
.dwRGBAlphaBitMask
= 0xFF000000;
460 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
461 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
463 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
464 TRACE("Enumerating GL_RGB unpacked (32)\n");
465 pformat
->dwFlags
= DDPF_RGB
;
466 pformat
->u1
.dwRGBBitCount
= 32;
467 pformat
->u2
.dwRBitMask
= 0x00FF0000;
468 pformat
->u3
.dwGBitMask
= 0x0000FF00;
469 pformat
->u4
.dwBBitMask
= 0x000000FF;
470 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
471 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
472 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
475 TRACE("Enumerating GL_RGB unpacked (24)\n");
476 pformat
->dwFlags
= DDPF_RGB
;
477 pformat
->u1
.dwRGBBitCount
= 24;
478 pformat
->u2
.dwRBitMask
= 0x00FF0000;
479 pformat
->u3
.dwGBitMask
= 0x0000FF00;
480 pformat
->u4
.dwBBitMask
= 0x000000FF;
481 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
482 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
483 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
485 /* Note : even if this is an 'emulated' texture format, it needs to be first
486 as some dumb applications seem to rely on that. */
487 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
488 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
489 pformat
->u1
.dwRGBBitCount
= 16;
490 pformat
->u2
.dwRBitMask
= 0x00007C00;
491 pformat
->u3
.dwGBitMask
= 0x000003E0;
492 pformat
->u4
.dwBBitMask
= 0x0000001F;
493 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
494 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
495 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
497 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
498 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
499 pformat
->u1
.dwRGBBitCount
= 16;
500 pformat
->u2
.dwRBitMask
= 0x00000F00;
501 pformat
->u3
.dwGBitMask
= 0x000000F0;
502 pformat
->u4
.dwBBitMask
= 0x0000000F;
503 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000F000;
504 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
505 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
507 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
508 pformat
->dwFlags
= DDPF_RGB
;
509 pformat
->u1
.dwRGBBitCount
= 16;
510 pformat
->u2
.dwRBitMask
= 0x0000F800;
511 pformat
->u3
.dwGBitMask
= 0x000007E0;
512 pformat
->u4
.dwBBitMask
= 0x0000001F;
513 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
514 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
515 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
517 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
518 pformat
->dwFlags
= DDPF_RGB
;
519 pformat
->u1
.dwRGBBitCount
= 16;
520 pformat
->u2
.dwRBitMask
= 0x00007C00;
521 pformat
->u3
.dwGBitMask
= 0x000003E0;
522 pformat
->u4
.dwBBitMask
= 0x0000001F;
523 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
524 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
525 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
528 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
529 find enumerated, others the last one. And both want to have the ARGB one.
531 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
533 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
534 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
535 pformat
->u1
.dwRGBBitCount
= 16;
536 pformat
->u2
.dwRBitMask
= 0x0000F000;
537 pformat
->u3
.dwGBitMask
= 0x00000F00;
538 pformat
->u4
.dwBBitMask
= 0x000000F0;
539 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
540 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
541 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
543 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
544 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
545 pformat
->u1
.dwRGBBitCount
= 16;
546 pformat
->u2
.dwRBitMask
= 0x0000F800;
547 pformat
->u3
.dwGBitMask
= 0x000007C0;
548 pformat
->u4
.dwBBitMask
= 0x0000003E;
549 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
550 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
551 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
554 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
555 pformat
->dwFlags
= DDPF_RGB
;
556 pformat
->u1
.dwRGBBitCount
= 8;
557 pformat
->u2
.dwRBitMask
= 0x000000E0;
558 pformat
->u3
.dwGBitMask
= 0x0000001C;
559 pformat
->u4
.dwBBitMask
= 0x00000003;
560 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
561 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
562 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
564 TRACE("Enumerating Paletted (8)\n");
565 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
566 pformat
->u1
.dwRGBBitCount
= 8;
567 pformat
->u2
.dwRBitMask
= 0x00000000;
568 pformat
->u3
.dwGBitMask
= 0x00000000;
569 pformat
->u4
.dwBBitMask
= 0x00000000;
570 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
571 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
572 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
574 TRACE("End of enumeration\n");
580 d3ddevice_find(IDirect3DImpl
*d3d
,
581 LPD3DFINDDEVICESEARCH lpD3DDFS
,
582 LPD3DFINDDEVICERESULT lplpD3DDevice
)
586 if ((lpD3DDFS
->dwFlags
& D3DFDS_COLORMODEL
) &&
587 (lpD3DDFS
->dcmColorModel
!= D3DCOLOR_RGB
)) {
588 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
589 return DDERR_INVALIDPARAMS
; /* No real idea what to return here :-) */
591 if (lpD3DDFS
->dwFlags
& D3DFDS_GUID
) {
592 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS
->guid
)));
593 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
594 (IsEqualGUID(&IID_IDirect3DHALDevice
, &(lpD3DDFS
->guid
)) == 0) &&
595 (IsEqualGUID(&IID_IDirect3DRefDevice
, &(lpD3DDFS
->guid
)) == 0)) {
596 TRACE(" no match for this GUID.\n");
597 return DDERR_INVALIDPARAMS
;
601 /* Now return our own GUID */
602 lplpD3DDevice
->guid
= IID_D3DDEVICE_OpenGL
;
603 fill_opengl_caps(&desc
);
604 lplpD3DDevice
->ddHwDesc
= desc
;
605 lplpD3DDevice
->ddSwDesc
= desc
;
607 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
613 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface
,
614 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc
,
617 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
618 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumTextureProc
, lpArg
);
619 return enum_texture_format_OpenGL(lpD3DEnumTextureProc
, NULL
, lpArg
);
623 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface
,
624 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc
,
627 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
628 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumPixelProc
, lpArg
);
629 return enum_texture_format_OpenGL(NULL
, lpD3DEnumPixelProc
, lpArg
);
633 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface
,
634 D3DRENDERSTATETYPE dwRenderStateType
,
637 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
638 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwRenderStateType
, dwRenderState
);
640 /* Call the render state functions */
641 store_render_state(This
, dwRenderStateType
, dwRenderState
, &This
->state_block
);
642 set_render_state(This
, dwRenderStateType
, &This
->state_block
);
648 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface
,
649 D3DRENDERSTATETYPE dwRenderStateType
,
650 LPDWORD lpdwRenderState
)
652 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
653 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwRenderStateType
, lpdwRenderState
);
655 /* Call the render state functions */
656 get_render_state(This
, dwRenderStateType
, lpdwRenderState
, &This
->state_block
);
658 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType
), *lpdwRenderState
);
664 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface
,
665 D3DLIGHTSTATETYPE dwLightStateType
,
668 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
670 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwLightStateType
, dwLightState
);
672 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
))
673 TRACE("Unexpected Light State Type\n");
674 return DDERR_INVALIDPARAMS
;
676 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
677 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) dwLightState
;
684 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
686 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
687 switch (dwLightState
) {
689 ERR("DDCOLOR_MONO should not happen!\n");
692 /* We are already in this mode */
695 ERR("Unknown color model!\n");
699 D3DRENDERSTATETYPE rs
;
700 switch (dwLightStateType
) {
702 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
703 rs
= D3DRENDERSTATE_AMBIENT
;
705 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
706 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
708 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
709 rs
= D3DRENDERSTATE_FOGSTART
;
711 case D3DLIGHTSTATE_FOGEND
: /* 6 */
712 rs
= D3DRENDERSTATE_FOGEND
;
714 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
715 rs
= D3DRENDERSTATE_FOGDENSITY
;
717 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
718 rs
= D3DRENDERSTATE_COLORVERTEX
;
724 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
731 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt
)
734 case D3DPT_POINTLIST
:
735 TRACE("Start POINTS\n");
740 TRACE("Start LINES\n");
744 case D3DPT_LINESTRIP
:
745 TRACE("Start LINE_STRIP\n");
746 glBegin(GL_LINE_STRIP
);
749 case D3DPT_TRIANGLELIST
:
750 TRACE("Start TRIANGLES\n");
751 glBegin(GL_TRIANGLES
);
754 case D3DPT_TRIANGLESTRIP
:
755 TRACE("Start TRIANGLE_STRIP\n");
756 glBegin(GL_TRIANGLE_STRIP
);
759 case D3DPT_TRIANGLEFAN
:
760 TRACE("Start TRIANGLE_FAN\n");
761 glBegin(GL_TRIANGLE_FAN
);
765 FIXME("Unhandled primitive %08x\n", d3dpt
);
770 /* This function calculate the Z coordinate from Zproj */
771 static float ZfromZproj(IDirect3DDeviceImpl
*This
, D3DVALUE Zproj
)
774 /* Assume that X = Y = 0 and W = 1 */
775 a
= This
->proj_mat
->_33
;
776 b
= This
->proj_mat
->_34
;
777 c
= This
->proj_mat
->_43
;
778 d
= This
->proj_mat
->_44
;
779 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
780 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
781 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
783 return (d
*Zproj
- c
) / (a
- b
*Zproj
);
786 static void build_fog_table(BYTE
*fog_table
, DWORD fog_color
) {
789 TRACE(" rebuilding fog table (%06lx)...\n", fog_color
& 0x00FFFFFF);
791 for (i
= 0; i
< 3; i
++) {
792 BYTE fog_color_component
= (fog_color
>> (8 * i
)) & 0xFF;
794 for (elt
= 0; elt
< 0x10000; elt
++) {
795 /* We apply the fog transformation and cache the result */
796 DWORD fog_intensity
= elt
& 0xFF;
797 DWORD vertex_color
= (elt
>> 8) & 0xFF;
798 fog_table
[(i
* 0x10000) + elt
] = ((fog_intensity
* vertex_color
) + ((0xFF - fog_intensity
) * fog_color_component
)) / 0xFF;
803 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl
*This
,
804 BOOLEAN vertex_transformed
,
805 BOOLEAN vertex_lit
) {
806 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
808 /* Puts GL in the correct lighting / transformation mode */
809 if ((vertex_transformed
== FALSE
) &&
810 (glThis
->transform_state
!= GL_TRANSFORM_NORMAL
)) {
811 /* Need to put the correct transformation again if we go from Transformed
812 vertices to non-transformed ones.
814 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
815 This
->world_mat
, This
->view_mat
, This
->proj_mat
);
816 glThis
->transform_state
= GL_TRANSFORM_NORMAL
;
818 } else if ((vertex_transformed
== TRUE
) &&
819 (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
)) {
820 /* Set our orthographic projection */
821 glThis
->transform_state
= GL_TRANSFORM_ORTHO
;
822 d3ddevice_set_ortho(This
);
825 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
826 if no fogging state change occured */
827 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGENABLE
- 1] == TRUE
) {
828 if (vertex_transformed
== TRUE
) {
830 /* Now check if our fog_table still corresponds to the current vertex color.
831 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
832 if ((glThis
->fog_table
[0 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 0) & 0xFF)) ||
833 (glThis
->fog_table
[1 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 8) & 0xFF)) ||
834 (glThis
->fog_table
[2 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 16) & 0xFF))) {
835 /* We need to rebuild our fog table.... */
836 build_fog_table(glThis
->fog_table
, This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
839 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1] != D3DFOG_NONE
) {
840 switch (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1]) {
841 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); break;
842 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); break;
843 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); break;
845 if (vertex_lit
== FALSE
) {
846 glFogf(GL_FOG_START
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]);
847 glFogf(GL_FOG_END
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]);
849 /* Special case of 'pixel fog' */
850 glFogf(GL_FOG_START
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]));
851 glFogf(GL_FOG_END
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]));
862 /* Handle the 'no-normal' case */
863 if ((vertex_lit
== FALSE
) && (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
))
864 glEnable(GL_LIGHTING
);
866 glDisable(GL_LIGHTING
);
868 /* Handle the code for pre-vertex material properties */
869 if (vertex_transformed
== FALSE
) {
870 if ((This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
871 (This
->state_block
.render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
872 if ((This
->state_block
.render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
873 (This
->state_block
.render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
874 (This
->state_block
.render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
875 (This
->state_block
.render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
)) {
876 glEnable(GL_COLOR_MATERIAL
);
883 inline static void draw_primitive(IDirect3DDeviceImpl
*This
, DWORD maxvert
, WORD
*index
,
884 D3DVERTEXTYPE d3dvt
, D3DPRIMITIVETYPE d3dpt
, void *lpvertex
)
886 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
890 strided
.position
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u1
.x
;
891 strided
.position
.dwStride
= sizeof(D3DVERTEX
);
892 strided
.normal
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u4
.nx
;
893 strided
.normal
.dwStride
= sizeof(D3DVERTEX
);
894 strided
.textureCoords
[0].lpvData
= &((D3DVERTEX
*) lpvertex
)->u7
.tu
;
895 strided
.textureCoords
[0].dwStride
= sizeof(D3DVERTEX
);
896 draw_primitive_strided(This
, d3dpt
, D3DFVF_VERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
899 case D3DVT_LVERTEX
: {
900 strided
.position
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u1
.x
;
901 strided
.position
.dwStride
= sizeof(D3DLVERTEX
);
902 strided
.diffuse
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u4
.color
;
903 strided
.diffuse
.dwStride
= sizeof(D3DLVERTEX
);
904 strided
.specular
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u5
.specular
;
905 strided
.specular
.dwStride
= sizeof(D3DLVERTEX
);
906 strided
.textureCoords
[0].lpvData
= &((D3DLVERTEX
*) lpvertex
)->u6
.tu
;
907 strided
.textureCoords
[0].dwStride
= sizeof(D3DLVERTEX
);
908 draw_primitive_strided(This
, d3dpt
, D3DFVF_LVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
911 case D3DVT_TLVERTEX
: {
912 strided
.position
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u1
.sx
;
913 strided
.position
.dwStride
= sizeof(D3DTLVERTEX
);
914 strided
.diffuse
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u5
.color
;
915 strided
.diffuse
.dwStride
= sizeof(D3DTLVERTEX
);
916 strided
.specular
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u6
.specular
;
917 strided
.specular
.dwStride
= sizeof(D3DTLVERTEX
);
918 strided
.textureCoords
[0].lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u7
.tu
;
919 strided
.textureCoords
[0].dwStride
= sizeof(D3DTLVERTEX
);
920 draw_primitive_strided(This
, d3dpt
, D3DFVF_TLVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
924 FIXME("Unhandled vertex type %08x\n", d3dvt
);
930 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface
,
931 D3DPRIMITIVETYPE d3dptPrimitiveType
,
932 D3DVERTEXTYPE d3dvtVertexType
,
937 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
939 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
940 if (TRACE_ON(ddraw
)) {
941 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
944 draw_primitive(This
, dwVertexCount
, NULL
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
950 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface
,
951 D3DPRIMITIVETYPE d3dptPrimitiveType
,
952 D3DVERTEXTYPE d3dvtVertexType
,
959 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
960 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
961 if (TRACE_ON(ddraw
)) {
962 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
965 draw_primitive(This
, dwIndexCount
, dwIndices
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
971 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface
,
972 LPD3DEXECUTEBUFFERDESC lpDesc
,
973 LPDIRECT3DEXECUTEBUFFER
* lplpDirect3DExecuteBuffer
,
976 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice
, iface
);
977 IDirect3DExecuteBufferImpl
*ret
;
980 TRACE("(%p/%p)->(%p,%p,%p)\n", This
, iface
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
982 ret_value
= d3dexecutebuffer_create(&ret
, This
->d3d
, This
, lpDesc
);
983 *lplpDirect3DExecuteBuffer
= ICOM_INTERFACE(ret
, IDirect3DExecuteBuffer
);
985 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer
);
990 /* These are the various handler used in the generic path */
991 inline static void handle_xyz(D3DVALUE
*coords
) {
994 inline static void handle_xyzrhw(D3DVALUE
*coords
) {
995 if (coords
[3] < 1e-8)
998 GLfloat w
= 1.0 / coords
[3];
1000 glVertex4f(coords
[0] * w
,
1006 inline static void handle_normal(D3DVALUE
*coords
) {
1007 glNormal3fv(coords
);
1010 inline static void handle_diffuse_base(STATEBLOCK
*sb
, DWORD
*color
) {
1011 if ((sb
->render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] == TRUE
) ||
1012 (sb
->render_state
[D3DRENDERSTATE_ALPHABLENDENABLE
- 1] == TRUE
)) {
1013 glColor4ub((*color
>> 16) & 0xFF,
1014 (*color
>> 8) & 0xFF,
1015 (*color
>> 0) & 0xFF,
1016 (*color
>> 24) & 0xFF);
1018 glColor3ub((*color
>> 16) & 0xFF,
1019 (*color
>> 8) & 0xFF,
1020 (*color
>> 0) & 0xFF);
1024 inline static void handle_specular_base(STATEBLOCK
*sb
, DWORD
*color
) {
1025 glColor4ub((*color
>> 16) & 0xFF,
1026 (*color
>> 8) & 0xFF,
1027 (*color
>> 0) & 0xFF,
1028 (*color
>> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1031 inline static void handle_diffuse(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1032 if ((lighted
== FALSE
) &&
1033 (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
1034 (sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
1035 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1036 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1037 handle_diffuse_base(sb
, color
);
1039 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1040 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1041 handle_diffuse_base(sb
, color
);
1043 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) &&
1044 (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
)) {
1045 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1046 handle_diffuse_base(sb
, color
);
1048 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1049 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1050 handle_diffuse_base(sb
, color
);
1053 handle_diffuse_base(sb
, color
);
1057 inline static void handle_specular(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1058 if ((lighted
== FALSE
) &&
1059 (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
1060 (sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
1061 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1062 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1063 handle_specular_base(sb
, color
);
1065 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1066 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1067 handle_specular_base(sb
, color
);
1069 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) &&
1070 (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
)) {
1071 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1072 handle_specular_base(sb
, color
);
1074 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1075 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1076 handle_specular_base(sb
, color
);
1079 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1082 inline static void handle_diffuse_and_specular(STATEBLOCK
*sb
, BYTE
*fog_table
, DWORD
*color_d
, DWORD
*color_s
, BOOLEAN lighted
) {
1083 if (lighted
== TRUE
) {
1084 DWORD color
= *color_d
;
1085 if (sb
->render_state
[D3DRENDERSTATE_FOGENABLE
- 1] == TRUE
) {
1086 /* Special case where the specular value is used to do fogging */
1087 BYTE fog_intensity
= *color_s
>> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1088 color
&= 0xFF000000; /* Only keep the alpha component */
1089 color
|= fog_table
[((*color_d
>> 0) & 0xFF) << 8 | fog_intensity
] << 0;
1090 color
|= fog_table
[((*color_d
>> 8) & 0xFF) << 8 | fog_intensity
] << 8;
1091 color
|= fog_table
[((*color_d
>> 16) & 0xFF) << 8 | fog_intensity
] << 16;
1093 if (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
) {
1094 /* Standard specular value in transformed mode. TODO */
1096 handle_diffuse_base(sb
, &color
);
1098 if (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) {
1099 handle_diffuse(sb
, color_d
, FALSE
);
1100 handle_specular(sb
, color_s
, FALSE
);
1102 /* In that case, only put the diffuse color... */
1103 handle_diffuse_base(sb
, color_d
);
1108 inline static void handle_texture(D3DVALUE
*coords
) {
1109 glTexCoord2fv(coords
);
1111 inline static void handle_textures(D3DVALUE
*coords
, int tex_index
) {
1112 /* For the moment, draw only the first texture.. */
1113 if (tex_index
== 0) glTexCoord2fv(coords
);
1116 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
1117 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1118 DWORD d3dvtVertexType
,
1119 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1120 DWORD dwVertexCount
,
1125 BOOLEAN vertex_lighted
= FALSE
;
1126 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
1127 int num_active_stages
= 0;
1130 if (glThis
->state
== SURFACE_MEMORY_DIRTY
) {
1131 This
->flush_to_framebuffer(This
, NULL
, glThis
->lock_surf
);
1135 glThis
->state
= SURFACE_GL
;
1137 /* Compute the number of active texture stages */
1138 while (This
->current_texture
[num_active_stages
] != NULL
) num_active_stages
++;
1140 /* This is to prevent 'thread contention' between a thread locking the device and another
1141 doing 3D display on it... */
1142 EnterCriticalSection(&(This
->crit
));
1144 if (TRACE_ON(ddraw
)) {
1145 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType
);
1150 /* Just a hack for now.. Will have to find better algorithm :-/ */
1151 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) {
1152 vertex_lighted
= TRUE
;
1154 if ((d3dvtVertexType
& D3DFVF_NORMAL
) == 0) glNormal3f(0.0, 0.0, 0.0);
1157 draw_primitive_handle_GL_state(This
,
1158 (d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
,
1160 draw_primitive_start_GL(d3dptPrimitiveType
);
1162 /* Some fast paths first before the generic case.... */
1163 if ((d3dvtVertexType
== D3DFVF_VERTEX
) && (num_active_stages
<= 1)) {
1166 for (index
= 0; index
< dwIndexCount
; index
++) {
1167 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1169 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1170 D3DVALUE
*tex_coord
=
1171 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1172 D3DVALUE
*position
=
1173 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1175 handle_normal(normal
);
1176 handle_texture(tex_coord
);
1177 handle_xyz(position
);
1179 TRACE_(ddraw_geom
)(" %f %f %f / %f %f %f (%f %f)\n",
1180 position
[0], position
[1], position
[2],
1181 normal
[0], normal
[1], normal
[2],
1182 tex_coord
[0], tex_coord
[1]);
1184 } else if ((d3dvtVertexType
== D3DFVF_TLVERTEX
) && (num_active_stages
<= 1)) {
1187 for (index
= 0; index
< dwIndexCount
; index
++) {
1188 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1190 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1192 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1193 D3DVALUE
*tex_coord
=
1194 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1195 D3DVALUE
*position
=
1196 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1198 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, TRUE
);
1199 handle_texture(tex_coord
);
1200 handle_xyzrhw(position
);
1202 TRACE_(ddraw_geom
)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1203 position
[0], position
[1], position
[2], position
[3],
1204 (*color_d
>> 16) & 0xFF,
1205 (*color_d
>> 8) & 0xFF,
1206 (*color_d
>> 0) & 0xFF,
1207 (*color_d
>> 24) & 0xFF,
1208 (*color_s
>> 16) & 0xFF,
1209 (*color_s
>> 8) & 0xFF,
1210 (*color_s
>> 0) & 0xFF,
1211 (*color_s
>> 24) & 0xFF,
1212 tex_coord
[0], tex_coord
[1]);
1214 } else if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
1215 ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)) {
1216 /* This is the 'slow path' but that should support all possible vertex formats out there...
1217 Note that people should write a fast path for all vertex formats out there...
1220 int num_tex_index
= ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
);
1221 static const D3DVALUE no_index
[] = { 0.0, 0.0, 0.0, 0.0 };
1223 for (index
= 0; index
< dwIndexCount
; index
++) {
1224 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1227 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1229 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1230 handle_normal(normal
);
1232 if ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) {
1234 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1236 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1237 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, vertex_lighted
);
1239 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1241 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1242 handle_specular(&(This
->state_block
), color_s
, vertex_lighted
);
1243 } else if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1245 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1246 handle_diffuse(&(This
->state_block
), color_d
, vertex_lighted
);
1250 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1251 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0xFFFF000;
1252 if (tex_index
>= num_tex_index
) {
1253 handle_textures((D3DVALUE
*) no_index
, tex_stage
);
1255 D3DVALUE
*tex_coord
=
1256 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1257 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1258 handle_textures(tex_coord
, tex_stage
);
1262 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1263 D3DVALUE
*position
=
1264 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1265 handle_xyz(position
);
1266 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1267 D3DVALUE
*position
=
1268 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1269 handle_xyzrhw(position
);
1272 if (TRACE_ON(ddraw_geom
)) {
1275 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1276 D3DVALUE
*position
=
1277 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1278 TRACE_(ddraw_geom
)(" %f %f %f", position
[0], position
[1], position
[2]);
1279 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1280 D3DVALUE
*position
=
1281 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1282 TRACE_(ddraw_geom
)(" %f %f %f %f", position
[0], position
[1], position
[2], position
[3]);
1284 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1286 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1287 TRACE_(ddraw_geom
)(" / %f %f %f", normal
[0], normal
[1], normal
[2]);
1289 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1291 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1292 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1293 (*color_d
>> 16) & 0xFF,
1294 (*color_d
>> 8) & 0xFF,
1295 (*color_d
>> 0) & 0xFF,
1296 (*color_d
>> 24) & 0xFF);
1298 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1300 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1301 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1302 (*color_s
>> 16) & 0xFF,
1303 (*color_s
>> 8) & 0xFF,
1304 (*color_s
>> 0) & 0xFF,
1305 (*color_s
>> 24) & 0xFF);
1307 for (tex_index
= 0; tex_index
< ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
); tex_index
++) {
1308 D3DVALUE
*tex_coord
=
1309 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1310 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1311 TRACE_(ddraw_geom
)(" / %f %f", tex_coord
[0], tex_coord
[1]);
1313 TRACE_(ddraw_geom
)("\n");
1317 ERR(" matrix weighting not handled yet....\n");
1322 /* Whatever the case, disable the color material stuff */
1323 glDisable(GL_COLOR_MATERIAL
);
1328 LeaveCriticalSection(&(This
->crit
));
1332 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface
,
1333 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1334 DWORD d3dvtVertexType
,
1336 DWORD dwVertexCount
,
1339 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1340 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1342 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1343 if (TRACE_ON(ddraw
)) {
1344 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1347 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1348 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1354 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface
,
1355 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1356 DWORD d3dvtVertexType
,
1358 DWORD dwVertexCount
,
1363 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1364 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1366 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1367 if (TRACE_ON(ddraw
)) {
1368 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1371 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1372 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1378 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1379 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1381 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1382 DWORD dwVertexCount
,
1385 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1387 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, dwFlags
);
1388 if (TRACE_ON(ddraw
)) {
1389 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1391 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1397 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1398 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1400 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1401 DWORD dwVertexCount
,
1406 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1408 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1409 if (TRACE_ON(ddraw
)) {
1410 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1413 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1419 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1420 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1421 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1422 DWORD dwStartVertex
,
1423 DWORD dwNumVertices
,
1426 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1427 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1428 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1430 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, dwFlags
);
1431 if (TRACE_ON(ddraw
)) {
1432 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1435 if (vb_impl
->processed
== TRUE
) {
1436 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1437 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1439 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1440 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1441 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1443 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1444 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1447 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1448 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1455 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1456 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1457 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1458 DWORD dwStartVertex
,
1459 DWORD dwNumVertices
,
1464 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1465 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1466 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1468 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1469 if (TRACE_ON(ddraw
)) {
1470 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1473 if (vb_impl
->processed
== TRUE
) {
1474 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1475 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1477 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1478 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1479 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1481 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1482 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1485 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1486 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1493 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState
, D3DTEXTUREMIPFILTER dwMipState
)
1497 if (dwMipState
== D3DTFP_NONE
) {
1498 switch (dwMinState
) {
1499 case D3DTFN_POINT
: gl_state
= GL_NEAREST
; break;
1500 case D3DTFN_LINEAR
: gl_state
= GL_LINEAR
; break;
1501 default: gl_state
= GL_LINEAR
; break;
1503 } else if (dwMipState
== D3DTFP_POINT
) {
1504 switch (dwMinState
) {
1505 case D3DTFN_POINT
: gl_state
= GL_NEAREST_MIPMAP_NEAREST
; break;
1506 case D3DTFN_LINEAR
: gl_state
= GL_LINEAR_MIPMAP_NEAREST
; break;
1507 default: gl_state
= GL_LINEAR_MIPMAP_NEAREST
; break;
1510 switch (dwMinState
) {
1511 case D3DTFN_POINT
: gl_state
= GL_NEAREST_MIPMAP_LINEAR
; break;
1512 case D3DTFN_LINEAR
: gl_state
= GL_LINEAR_MIPMAP_LINEAR
; break;
1513 default: gl_state
= GL_LINEAR_MIPMAP_LINEAR
; break;
1520 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState
)
1526 gl_state
= GL_NEAREST
;
1529 gl_state
= GL_LINEAR
;
1532 gl_state
= GL_LINEAR
;
1538 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1540 handle_color_alpha_args(IDirect3DDeviceImpl
*This
, DWORD dwStage
, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
, DWORD dwState
, D3DTEXTUREOP tex_op
)
1542 BOOLEAN is_complement
= FALSE
;
1543 BOOLEAN is_alpha_replicate
= FALSE
;
1544 BOOLEAN handled
= TRUE
;
1546 BOOLEAN is_color
= ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
));
1550 if (d3dTexStageStateType
== D3DTSS_COLORARG1
) num
= 0;
1551 else if (d3dTexStageStateType
== D3DTSS_COLORARG2
) num
= 1;
1556 if (tex_op
== D3DTOP_SELECTARG2
) {
1560 if (d3dTexStageStateType
== D3DTSS_ALPHAARG1
) num
= 0;
1561 else if (d3dTexStageStateType
== D3DTSS_ALPHAARG2
) num
= 1;
1566 if (tex_op
== D3DTOP_SELECTARG2
) {
1571 if (dwState
& D3DTA_COMPLEMENT
) {
1572 is_complement
= TRUE
;
1574 if (dwState
& D3DTA_ALPHAREPLICATE
) {
1575 is_alpha_replicate
= TRUE
;
1577 dwState
&= D3DTA_SELECTMASK
;
1578 if ((dwStage
== 0) && (dwState
== D3DTA_CURRENT
)) {
1579 dwState
= D3DTA_DIFFUSE
;
1583 case D3DTA_CURRENT
: src
= GL_PREVIOUS_EXT
; break;
1584 case D3DTA_DIFFUSE
: src
= GL_PRIMARY_COLOR_EXT
; break;
1585 case D3DTA_TEXTURE
: src
= GL_TEXTURE
; break;
1586 case D3DTA_TFACTOR
: {
1587 /* Get the constant value from the current rendering state */
1589 DWORD col
= This
->state_block
.render_state
[D3DRENDERSTATE_TEXTUREFACTOR
- 1];
1591 color
[0] = ((col
>> 16) & 0xFF) / 255.0f
;
1592 color
[1] = ((col
>> 8) & 0xFF) / 255.0f
;
1593 color
[2] = ((col
>> 0) & 0xFF) / 255.0f
;
1594 color
[3] = ((col
>> 24) & 0xFF) / 255.0f
;
1595 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, color
);
1597 src
= GL_CONSTANT_EXT
;
1599 default: src
= GL_TEXTURE
; handled
= FALSE
; break;
1603 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
+ num
, src
);
1604 if (is_alpha_replicate
) {
1605 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1607 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_COLOR
: GL_SRC_COLOR
);
1610 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
+ num
, src
);
1611 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1618 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface
,
1620 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
,
1623 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1627 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This
, iface
, dwStage
, d3dTexStageStateType
, dwState
);
1629 if (dwStage
> 0) return DD_OK
; /* We nothing in this case for now */
1631 switch (d3dTexStageStateType
) {
1632 #define GEN_CASE(a) case a: type = #a; break
1633 GEN_CASE(D3DTSS_COLOROP
);
1634 GEN_CASE(D3DTSS_COLORARG1
);
1635 GEN_CASE(D3DTSS_COLORARG2
);
1636 GEN_CASE(D3DTSS_ALPHAOP
);
1637 GEN_CASE(D3DTSS_ALPHAARG1
);
1638 GEN_CASE(D3DTSS_ALPHAARG2
);
1639 GEN_CASE(D3DTSS_BUMPENVMAT00
);
1640 GEN_CASE(D3DTSS_BUMPENVMAT01
);
1641 GEN_CASE(D3DTSS_BUMPENVMAT10
);
1642 GEN_CASE(D3DTSS_BUMPENVMAT11
);
1643 GEN_CASE(D3DTSS_TEXCOORDINDEX
);
1644 GEN_CASE(D3DTSS_ADDRESS
);
1645 GEN_CASE(D3DTSS_ADDRESSU
);
1646 GEN_CASE(D3DTSS_ADDRESSV
);
1647 GEN_CASE(D3DTSS_BORDERCOLOR
);
1648 GEN_CASE(D3DTSS_MAGFILTER
);
1649 GEN_CASE(D3DTSS_MINFILTER
);
1650 GEN_CASE(D3DTSS_MIPFILTER
);
1651 GEN_CASE(D3DTSS_MIPMAPLODBIAS
);
1652 GEN_CASE(D3DTSS_MAXMIPLEVEL
);
1653 GEN_CASE(D3DTSS_MAXANISOTROPY
);
1654 GEN_CASE(D3DTSS_BUMPENVLSCALE
);
1655 GEN_CASE(D3DTSS_BUMPENVLOFFSET
);
1656 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS
);
1658 default: type
= "UNKNOWN";
1661 /* Store the values in the state array */
1662 prev_state
= This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1];
1663 This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1] = dwState
;
1664 /* Some special cases when one state modifies more than one... */
1665 if (d3dTexStageStateType
== D3DTSS_ADDRESS
) {
1666 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSU
- 1] = dwState
;
1667 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSV
- 1] = dwState
;
1672 switch (d3dTexStageStateType
) {
1673 case D3DTSS_MINFILTER
:
1674 case D3DTSS_MIPFILTER
:
1675 if (TRACE_ON(ddraw
)) {
1676 if (d3dTexStageStateType
== D3DTSS_MINFILTER
) {
1677 switch ((D3DTEXTUREMINFILTER
) dwState
) {
1678 case D3DTFN_POINT
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1679 case D3DTFN_LINEAR
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1680 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState
); break;
1683 switch ((D3DTEXTUREMIPFILTER
) dwState
) {
1684 case D3DTFP_NONE
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1685 case D3DTFP_POINT
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1686 case D3DTFP_LINEAR
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1687 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState
); break;
1692 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
1693 convert_min_filter_to_GL(This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_MINFILTER
- 1],
1694 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_MIPFILTER
- 1]));
1697 case D3DTSS_MAGFILTER
:
1698 if (TRACE_ON(ddraw
)) {
1699 switch ((D3DTEXTUREMAGFILTER
) dwState
) {
1700 case D3DTFG_POINT
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1701 case D3DTFG_LINEAR
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1702 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState
); break;
1705 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, convert_mag_filter_to_GL(dwState
));
1708 case D3DTSS_ADDRESS
:
1709 case D3DTSS_ADDRESSU
:
1710 case D3DTSS_ADDRESSV
: {
1711 GLenum arg
= GL_REPEAT
; /* Default value */
1712 switch ((D3DTEXTUREADDRESS
) dwState
) {
1713 case D3DTADDRESS_WRAP
: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type
); arg
= GL_REPEAT
; break;
1714 case D3DTADDRESS_CLAMP
: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type
); arg
= GL_CLAMP
; break;
1715 case D3DTADDRESS_BORDER
: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type
); arg
= GL_CLAMP_TO_EDGE
; break;
1716 #if defined(GL_VERSION_1_4)
1717 case D3DTADDRESS_MIRROR
: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type
); arg
= GL_MIRRORED_REPEAT
; break;
1718 #elif defined(GL_ARB_texture_mirrored_repeat)
1719 case D3DTADDRESS_MIRROR
: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type
); arg
= GL_MIRRORED_REPEAT_ARB
; break;
1721 default: FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
); break;
1723 if ((d3dTexStageStateType
== D3DTSS_ADDRESS
) ||
1724 (d3dTexStageStateType
== D3DTSS_ADDRESSU
))
1725 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, arg
);
1726 if ((d3dTexStageStateType
== D3DTSS_ADDRESS
) ||
1727 (d3dTexStageStateType
== D3DTSS_ADDRESSV
))
1728 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, arg
);
1731 case D3DTSS_ALPHAOP
:
1732 case D3DTSS_COLOROP
: {
1734 GLenum parm
= (d3dTexStageStateType
== D3DTSS_ALPHAOP
) ? GL_COMBINE_ALPHA_EXT
: GL_COMBINE_RGB_EXT
;
1739 #define GEN_CASE(a) case a: value = #a; break
1740 GEN_CASE(D3DTOP_DISABLE
);
1741 GEN_CASE(D3DTOP_SELECTARG1
);
1742 GEN_CASE(D3DTOP_SELECTARG2
);
1743 GEN_CASE(D3DTOP_MODULATE
);
1744 GEN_CASE(D3DTOP_MODULATE2X
);
1745 GEN_CASE(D3DTOP_MODULATE4X
);
1746 GEN_CASE(D3DTOP_ADD
);
1747 GEN_CASE(D3DTOP_ADDSIGNED
);
1748 GEN_CASE(D3DTOP_ADDSIGNED2X
);
1749 GEN_CASE(D3DTOP_SUBTRACT
);
1750 GEN_CASE(D3DTOP_ADDSMOOTH
);
1751 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA
);
1752 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA
);
1753 GEN_CASE(D3DTOP_BLENDFACTORALPHA
);
1754 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM
);
1755 GEN_CASE(D3DTOP_BLENDCURRENTALPHA
);
1756 GEN_CASE(D3DTOP_PREMODULATE
);
1757 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR
);
1758 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA
);
1759 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR
);
1760 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA
);
1761 GEN_CASE(D3DTOP_BUMPENVMAP
);
1762 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE
);
1763 GEN_CASE(D3DTOP_DOTPRODUCT3
);
1764 GEN_CASE(D3DTOP_FORCE_DWORD
);
1766 default: value
= "UNKNOWN";
1769 if ((d3dTexStageStateType
== D3DTSS_COLOROP
) && (dwState
== D3DTOP_DISABLE
) && (dwStage
== 0)) {
1770 glDisable(GL_TEXTURE_2D
);
1771 TRACE(" disabling 2D texturing.\n");
1773 /* Re-enable texturing */
1774 if ((dwStage
== 0) && (This
->current_texture
[0] != NULL
)) {
1775 glEnable(GL_TEXTURE_2D
);
1776 TRACE(" enabling 2D texturing.\n");
1779 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1780 if (dwState
!= D3DTOP_DISABLE
) {
1781 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1784 /* Now set up the operand correctly */
1786 case D3DTOP_DISABLE
:
1787 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1788 and it works, so ignore this op */
1789 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1792 case D3DTOP_SELECTARG1
:
1793 case D3DTOP_SELECTARG2
:
1794 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_REPLACE
);
1797 case D3DTOP_MODULATE4X
:
1798 scale
= scale
* 2; /* Drop through */
1799 case D3DTOP_MODULATE2X
:
1800 scale
= scale
* 2; /* Drop through */
1801 case D3DTOP_MODULATE
:
1802 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_MODULATE
);
1806 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD
);
1809 case D3DTOP_ADDSIGNED2X
:
1810 scale
= scale
* 2; /* Drop through */
1811 case D3DTOP_ADDSIGNED
:
1812 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD_SIGNED_EXT
);
1815 /* For the four blending modes, use the Arg2 parameter */
1816 case D3DTOP_BLENDDIFFUSEALPHA
:
1817 case D3DTOP_BLENDTEXTUREALPHA
:
1818 case D3DTOP_BLENDFACTORALPHA
:
1819 case D3DTOP_BLENDCURRENTALPHA
: {
1820 GLenum src
= GL_PRIMARY_COLOR_EXT
; /* Just to prevent a compiler warning.. */
1823 case D3DTOP_BLENDDIFFUSEALPHA
: src
= GL_PRIMARY_COLOR_EXT
;
1824 case D3DTOP_BLENDTEXTUREALPHA
: src
= GL_TEXTURE
;
1825 case D3DTOP_BLENDFACTORALPHA
: src
= GL_CONSTANT_EXT
;
1826 case D3DTOP_BLENDCURRENTALPHA
: src
= GL_PREVIOUS_EXT
;
1829 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_INTERPOLATE_EXT
);
1830 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, src
);
1831 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_ALPHA
);
1832 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, src
);
1833 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
1842 if (((prev_state
== D3DTOP_SELECTARG2
) && (dwState
!= D3DTOP_SELECTARG2
)) ||
1843 ((dwState
== D3DTOP_SELECTARG2
) && (prev_state
!= D3DTOP_SELECTARG2
))) {
1844 /* Switch the arguments if needed... */
1845 if (d3dTexStageStateType
== D3DTSS_COLOROP
) {
1846 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG1
,
1847 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG1
- 1],
1849 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG2
,
1850 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG2
- 1],
1853 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG1
,
1854 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG1
- 1],
1856 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG2
,
1857 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG2
- 1],
1863 if (d3dTexStageStateType
== D3DTSS_ALPHAOP
) {
1864 glTexEnvi(GL_TEXTURE_ENV
, GL_ALPHA_SCALE
, scale
);
1866 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, scale
);
1868 TRACE(" Stage type is : %s => %s\n", type
, value
);
1870 FIXME(" Unhandled stage type is : %s => %s\n", type
, value
);
1874 case D3DTSS_COLORARG1
:
1875 case D3DTSS_COLORARG2
:
1876 case D3DTSS_ALPHAARG1
:
1877 case D3DTSS_ALPHAARG2
: {
1878 const char *value
, *value_comp
= "", *value_alpha
= "";
1880 D3DTEXTUREOP tex_op
;
1882 switch (dwState
& D3DTA_SELECTMASK
) {
1883 #define GEN_CASE(a) case a: value = #a; break
1884 GEN_CASE(D3DTA_DIFFUSE
);
1885 GEN_CASE(D3DTA_CURRENT
);
1886 GEN_CASE(D3DTA_TEXTURE
);
1887 GEN_CASE(D3DTA_TFACTOR
);
1888 GEN_CASE(D3DTA_SPECULAR
);
1890 default: value
= "UNKNOWN";
1892 if (dwState
& D3DTA_COMPLEMENT
) {
1893 value_comp
= " | D3DTA_COMPLEMENT";
1895 if (dwState
& D3DTA_ALPHAREPLICATE
) {
1896 value_alpha
= " | D3DTA_ALPHAREPLICATE";
1899 if ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
)) {
1900 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1];
1902 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAOP
- 1];
1905 handled
= handle_color_alpha_args(This
, dwStage
, d3dTexStageStateType
, dwState
, tex_op
);
1908 TRACE(" Stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
1910 FIXME(" Unhandled stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
1914 case D3DTSS_MIPMAPLODBIAS
: {
1915 D3DVALUE value
= *((D3DVALUE
*) &dwState
);
1916 BOOLEAN handled
= TRUE
;
1922 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
1924 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
1928 case D3DTSS_MAXMIPLEVEL
:
1930 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1932 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState
);
1936 case D3DTSS_BORDERCOLOR
: {
1939 color
[0] = ((dwState
>> 16) & 0xFF) / 255.0;
1940 color
[1] = ((dwState
>> 8) & 0xFF) / 255.0;
1941 color
[2] = ((dwState
>> 0) & 0xFF) / 255.0;
1942 color
[3] = ((dwState
>> 24) & 0xFF) / 255.0;
1944 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, color
);
1946 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1947 ((dwState
>> 16) & 0xFF),
1948 ((dwState
>> 8) & 0xFF),
1949 ((dwState
>> 0) & 0xFF),
1950 ((dwState
>> 24) & 0xFF));
1953 case D3DTSS_TEXCOORDINDEX
: {
1954 BOOLEAN handled
= TRUE
;
1957 switch (dwState
& 0xFFFF0000) {
1958 #define GEN_CASE(a) case a: value = #a; break
1959 GEN_CASE(D3DTSS_TCI_PASSTHRU
);
1960 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL
);
1961 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION
);
1962 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
);
1964 default: value
= "UNKNOWN";
1966 if ((dwState
& 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
)
1970 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
1972 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
1976 case D3DTSS_TEXTURETRANSFORMFLAGS
: {
1977 const char *projected
= "", *value
;
1978 BOOLEAN handled
= TRUE
;
1979 switch (dwState
& 0xFF) {
1980 #define GEN_CASE(a) case a: value = #a; break
1981 GEN_CASE(D3DTTFF_DISABLE
);
1982 GEN_CASE(D3DTTFF_COUNT1
);
1983 GEN_CASE(D3DTTFF_COUNT2
);
1984 GEN_CASE(D3DTTFF_COUNT3
);
1985 GEN_CASE(D3DTTFF_COUNT4
);
1987 default: value
= "UNKNOWN";
1989 if (dwState
& D3DTTFF_PROJECTED
) {
1990 projected
= " | D3DTTFF_PROJECTED";
1994 if ((dwState
& 0xFF) != D3DTTFF_DISABLE
) {
1996 This
->matrices_updated(This
, TEXMAT0_CHANGED
<< dwStage
);
2000 if (handled
== TRUE
) {
2001 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2003 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2008 FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
);
2018 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface
,
2020 LPDIRECTDRAWSURFACE7 lpTexture2
)
2022 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2024 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwStage
, lpTexture2
);
2026 if (dwStage
> 0) return DD_OK
;
2028 if (This
->current_texture
[dwStage
] != NULL
) {
2029 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[dwStage
], IDirectDrawSurface7
));
2033 if (lpTexture2
== NULL
) {
2034 This
->current_texture
[dwStage
] = NULL
;
2036 TRACE(" disabling 2D texturing.\n");
2037 glBindTexture(GL_TEXTURE_2D
, 0);
2038 glDisable(GL_TEXTURE_2D
);
2040 IDirectDrawSurfaceImpl
*tex_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, lpTexture2
);
2041 GLint max_mip_level
;
2043 This
->current_texture
[dwStage
] = tex_impl
;
2044 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl
, IDirectDrawSurface7
)); /* Not sure about this either */
2046 if (This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
) {
2047 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2048 glEnable(GL_TEXTURE_2D
);
2049 TRACE(" enabling 2D texturing.\n");
2051 gltex_upload_texture(tex_impl
);
2053 if ((tex_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) == 0) {
2056 max_mip_level
= tex_impl
->surface_desc
.u2
.dwMipMapCount
- 1;
2059 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
,
2060 convert_mag_filter_to_GL(This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_MAGFILTER
- 1]));
2061 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
2062 convert_min_filter_to_GL(This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_MINFILTER
- 1],
2063 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_MIPFILTER
- 1]));
2064 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAX_LEVEL
, max_mip_level
);
2072 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface
,
2073 LPD3DDEVICEDESC7 lpD3DHELDevDesc
)
2075 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2076 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpD3DHELDevDesc
);
2078 fill_opengl_caps_7(lpD3DHELDevDesc
);
2080 TRACE(" returning caps : no dump function yet.\n");
2086 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface
,
2087 LPD3DMATERIAL7 lpMat
)
2089 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2090 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpMat
);
2092 if (TRACE_ON(ddraw
)) {
2093 TRACE(" material is : \n");
2094 dump_D3DMATERIAL7(lpMat
);
2097 This
->current_material
= *lpMat
;
2099 glMaterialfv(GL_FRONT_AND_BACK
,
2101 (float *) &(This
->current_material
.u
.diffuse
));
2102 glMaterialfv(GL_FRONT_AND_BACK
,
2104 (float *) &(This
->current_material
.u1
.ambient
));
2105 glMaterialfv(GL_FRONT_AND_BACK
,
2107 (float *) &(This
->current_material
.u2
.specular
));
2108 glMaterialfv(GL_FRONT_AND_BACK
,
2110 (float *) &(This
->current_material
.u3
.emissive
));
2111 glMaterialf(GL_FRONT_AND_BACK
,
2113 This
->current_material
.u4
.power
); /* Not sure about this... */
2120 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface
,
2122 LPD3DLIGHT7 lpLight
)
2124 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2125 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2126 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwLightIndex
, lpLight
);
2128 if (TRACE_ON(ddraw
)) {
2129 TRACE(" setting light : \n");
2130 dump_D3DLIGHT7(lpLight
);
2133 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2134 This
->set_lights
|= 0x00000001 << dwLightIndex
;
2135 This
->light_parameters
[dwLightIndex
] = *lpLight
;
2137 /* Some checks to print out nice warnings :-) */
2138 switch (lpLight
->dltType
) {
2139 case D3DLIGHT_DIRECTIONAL
:
2140 case D3DLIGHT_POINT
:
2141 /* These are handled properly... */
2145 if ((lpLight
->dvTheta
!= 0.0) ||
2146 (lpLight
->dvTheta
!= lpLight
->dvPhi
)) {
2147 ERR("dvTheta not fully supported yet !\n");
2152 ERR("Light type not handled yet : %08x !\n", lpLight
->dltType
);
2155 /* This will force the Light setting on next drawing of primitives */
2156 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2162 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface
,
2166 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2167 TRACE("(%p/%p)->(%08lx,%d)\n", This
, iface
, dwLightIndex
, bEnable
);
2169 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2172 if (((0x00000001 << dwLightIndex
) & This
->set_lights
) == 0) {
2173 /* Set the default parameters.. */
2174 TRACE(" setting default light parameters...\n");
2175 GL_IDirect3DDeviceImpl_7_SetLight(iface
, dwLightIndex
, &(This
->light_parameters
[dwLightIndex
]));
2177 glEnable(GL_LIGHT0
+ dwLightIndex
);
2178 if ((This
->active_lights
& (0x00000001 << dwLightIndex
)) == 0) {
2179 /* This light gets active... Need to update its parameters to GL before the next drawing */
2180 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2182 This
->active_lights
|= 0x00000001 << dwLightIndex
;
2183 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2186 glDisable(GL_LIGHT0
+ dwLightIndex
);
2187 This
->active_lights
&= ~(0x00000001 << dwLightIndex
);
2194 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface
, DWORD dwIndex
, CONST D3DVALUE
* pPlaneEquation
)
2196 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
2197 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
2199 TRACE("(%p)->(%ld,%p)\n", This
, dwIndex
, pPlaneEquation
);
2201 if (dwIndex
>= This
->max_clipping_planes
) {
2202 return DDERR_INVALIDPARAMS
;
2205 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex
, pPlaneEquation
[0], pPlaneEquation
[1], pPlaneEquation
[2], pPlaneEquation
[3] );
2207 memcpy(This
->clipping_planes
[dwIndex
].plane
, pPlaneEquation
, sizeof(D3DVALUE
[4]));
2209 /* This is to force the reset of the transformation matrices on the next drawing.
2210 * This is needed to use the correct matrices for the various clipping planes.
2212 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2218 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface
,
2219 LPD3DVIEWPORT7 lpData
)
2221 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2222 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
2224 if (TRACE_ON(ddraw
)) {
2225 TRACE(" viewport is : \n");
2226 TRACE(" - dwX = %ld dwY = %ld\n",
2227 lpData
->dwX
, lpData
->dwY
);
2228 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2229 lpData
->dwWidth
, lpData
->dwHeight
);
2230 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2231 lpData
->dvMinZ
, lpData
->dvMaxZ
);
2233 This
->active_viewport
= *lpData
;
2237 /* Set the viewport */
2238 glDepthRange(lpData
->dvMinZ
, lpData
->dvMaxZ
);
2239 glViewport(lpData
->dwX
,
2240 This
->surface
->surface_desc
.dwHeight
- (lpData
->dwHeight
+ lpData
->dwY
),
2241 lpData
->dwWidth
, lpData
->dwHeight
);
2248 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2249 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2251 # define XCAST(fun) (void*)
2254 ICOM_VTABLE(IDirect3DDevice7
) VTABLE_IDirect3DDevice7
=
2256 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2257 XCAST(QueryInterface
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface
,
2258 XCAST(AddRef
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef
,
2259 XCAST(Release
) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release
,
2260 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_7_GetCaps
,
2261 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats
,
2262 XCAST(BeginScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene
,
2263 XCAST(EndScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene
,
2264 XCAST(GetDirect3D
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D
,
2265 XCAST(SetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget
,
2266 XCAST(GetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget
,
2267 XCAST(Clear
) Main_IDirect3DDeviceImpl_7_Clear
,
2268 XCAST(SetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform
,
2269 XCAST(GetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform
,
2270 XCAST(SetViewport
) GL_IDirect3DDeviceImpl_7_SetViewport
,
2271 XCAST(MultiplyTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform
,
2272 XCAST(GetViewport
) Main_IDirect3DDeviceImpl_7_GetViewport
,
2273 XCAST(SetMaterial
) GL_IDirect3DDeviceImpl_7_SetMaterial
,
2274 XCAST(GetMaterial
) Main_IDirect3DDeviceImpl_7_GetMaterial
,
2275 XCAST(SetLight
) GL_IDirect3DDeviceImpl_7_SetLight
,
2276 XCAST(GetLight
) Main_IDirect3DDeviceImpl_7_GetLight
,
2277 XCAST(SetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState
,
2278 XCAST(GetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState
,
2279 XCAST(BeginStateBlock
) Main_IDirect3DDeviceImpl_7_BeginStateBlock
,
2280 XCAST(EndStateBlock
) Main_IDirect3DDeviceImpl_7_EndStateBlock
,
2281 XCAST(PreLoad
) Main_IDirect3DDeviceImpl_7_PreLoad
,
2282 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive
,
2283 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive
,
2284 XCAST(SetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus
,
2285 XCAST(GetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus
,
2286 XCAST(DrawPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided
,
2287 XCAST(DrawIndexedPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided
,
2288 XCAST(DrawPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB
,
2289 XCAST(DrawIndexedPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB
,
2290 XCAST(ComputeSphereVisibility
) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility
,
2291 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_7_3T_GetTexture
,
2292 XCAST(SetTexture
) GL_IDirect3DDeviceImpl_7_3T_SetTexture
,
2293 XCAST(GetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState
,
2294 XCAST(SetTextureStageState
) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState
,
2295 XCAST(ValidateDevice
) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice
,
2296 XCAST(ApplyStateBlock
) Main_IDirect3DDeviceImpl_7_ApplyStateBlock
,
2297 XCAST(CaptureStateBlock
) Main_IDirect3DDeviceImpl_7_CaptureStateBlock
,
2298 XCAST(DeleteStateBlock
) Main_IDirect3DDeviceImpl_7_DeleteStateBlock
,
2299 XCAST(CreateStateBlock
) Main_IDirect3DDeviceImpl_7_CreateStateBlock
,
2300 XCAST(Load
) Main_IDirect3DDeviceImpl_7_Load
,
2301 XCAST(LightEnable
) GL_IDirect3DDeviceImpl_7_LightEnable
,
2302 XCAST(GetLightEnable
) Main_IDirect3DDeviceImpl_7_GetLightEnable
,
2303 XCAST(SetClipPlane
) GL_IDirect3DDeviceImpl_7_SetClipPlane
,
2304 XCAST(GetClipPlane
) Main_IDirect3DDeviceImpl_7_GetClipPlane
,
2305 XCAST(GetInfo
) Main_IDirect3DDeviceImpl_7_GetInfo
,
2308 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2313 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2314 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2316 # define XCAST(fun) (void*)
2319 ICOM_VTABLE(IDirect3DDevice3
) VTABLE_IDirect3DDevice3
=
2321 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2322 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_3_QueryInterface
,
2323 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_3_AddRef
,
2324 XCAST(Release
) Thunk_IDirect3DDeviceImpl_3_Release
,
2325 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps
,
2326 XCAST(GetStats
) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats
,
2327 XCAST(AddViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport
,
2328 XCAST(DeleteViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport
,
2329 XCAST(NextViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport
,
2330 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats
,
2331 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_3_BeginScene
,
2332 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_3_EndScene
,
2333 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_3_GetDirect3D
,
2334 XCAST(SetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport
,
2335 XCAST(GetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport
,
2336 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget
,
2337 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget
,
2338 XCAST(Begin
) Main_IDirect3DDeviceImpl_3_Begin
,
2339 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_3_BeginIndexed
,
2340 XCAST(Vertex
) Main_IDirect3DDeviceImpl_3_2T_Vertex
,
2341 XCAST(Index
) Main_IDirect3DDeviceImpl_3_2T_Index
,
2342 XCAST(End
) Main_IDirect3DDeviceImpl_3_2T_End
,
2343 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_3_GetRenderState
,
2344 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_3_SetRenderState
,
2345 XCAST(GetLightState
) Main_IDirect3DDeviceImpl_3_2T_GetLightState
,
2346 XCAST(SetLightState
) GL_IDirect3DDeviceImpl_3_2T_SetLightState
,
2347 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_3_SetTransform
,
2348 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_3_GetTransform
,
2349 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform
,
2350 XCAST(DrawPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive
,
2351 XCAST(DrawIndexedPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive
,
2352 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_3_SetClipStatus
,
2353 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_3_GetClipStatus
,
2354 XCAST(DrawPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided
,
2355 XCAST(DrawIndexedPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided
,
2356 XCAST(DrawPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB
,
2357 XCAST(DrawIndexedPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB
,
2358 XCAST(ComputeSphereVisibility
) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility
,
2359 XCAST(GetTexture
) Thunk_IDirect3DDeviceImpl_3_GetTexture
,
2360 XCAST(SetTexture
) Thunk_IDirect3DDeviceImpl_3_SetTexture
,
2361 XCAST(GetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState
,
2362 XCAST(SetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState
,
2363 XCAST(ValidateDevice
) Thunk_IDirect3DDeviceImpl_3_ValidateDevice
,
2366 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2371 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2372 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2374 # define XCAST(fun) (void*)
2377 ICOM_VTABLE(IDirect3DDevice2
) VTABLE_IDirect3DDevice2
=
2379 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2380 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_2_QueryInterface
,
2381 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_2_AddRef
,
2382 XCAST(Release
) Thunk_IDirect3DDeviceImpl_2_Release
,
2383 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_2_GetCaps
,
2384 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles
,
2385 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_2_GetStats
,
2386 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_2_AddViewport
,
2387 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_2_DeleteViewport
,
2388 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_2_NextViewport
,
2389 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats
,
2390 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_2_BeginScene
,
2391 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_2_EndScene
,
2392 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_2_GetDirect3D
,
2393 XCAST(SetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport
,
2394 XCAST(GetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport
,
2395 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget
,
2396 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget
,
2397 XCAST(Begin
) Main_IDirect3DDeviceImpl_2_Begin
,
2398 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_2_BeginIndexed
,
2399 XCAST(Vertex
) Thunk_IDirect3DDeviceImpl_2_Vertex
,
2400 XCAST(Index
) Thunk_IDirect3DDeviceImpl_2_Index
,
2401 XCAST(End
) Thunk_IDirect3DDeviceImpl_2_End
,
2402 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_2_GetRenderState
,
2403 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_2_SetRenderState
,
2404 XCAST(GetLightState
) Thunk_IDirect3DDeviceImpl_2_GetLightState
,
2405 XCAST(SetLightState
) Thunk_IDirect3DDeviceImpl_2_SetLightState
,
2406 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_2_SetTransform
,
2407 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_2_GetTransform
,
2408 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform
,
2409 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_2_DrawPrimitive
,
2410 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive
,
2411 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_2_SetClipStatus
,
2412 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_2_GetClipStatus
,
2415 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2420 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2421 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2423 # define XCAST(fun) (void*)
2426 ICOM_VTABLE(IDirect3DDevice
) VTABLE_IDirect3DDevice
=
2428 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2429 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_1_QueryInterface
,
2430 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_1_AddRef
,
2431 XCAST(Release
) Thunk_IDirect3DDeviceImpl_1_Release
,
2432 XCAST(Initialize
) Main_IDirect3DDeviceImpl_1_Initialize
,
2433 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_1_GetCaps
,
2434 XCAST(SwapTextureHandles
) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles
,
2435 XCAST(CreateExecuteBuffer
) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer
,
2436 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_1_GetStats
,
2437 XCAST(Execute
) Main_IDirect3DDeviceImpl_1_Execute
,
2438 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_1_AddViewport
,
2439 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_1_DeleteViewport
,
2440 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_1_NextViewport
,
2441 XCAST(Pick
) Main_IDirect3DDeviceImpl_1_Pick
,
2442 XCAST(GetPickRecords
) Main_IDirect3DDeviceImpl_1_GetPickRecords
,
2443 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats
,
2444 XCAST(CreateMatrix
) Main_IDirect3DDeviceImpl_1_CreateMatrix
,
2445 XCAST(SetMatrix
) Main_IDirect3DDeviceImpl_1_SetMatrix
,
2446 XCAST(GetMatrix
) Main_IDirect3DDeviceImpl_1_GetMatrix
,
2447 XCAST(DeleteMatrix
) Main_IDirect3DDeviceImpl_1_DeleteMatrix
,
2448 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_1_BeginScene
,
2449 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_1_EndScene
,
2450 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_1_GetDirect3D
,
2453 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2457 static HRESULT
d3ddevice_clear(IDirect3DDeviceImpl
*This
,
2465 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2467 GLfloat old_z_clear_value
;
2468 GLbitfield bitfield
= 0;
2469 GLint old_stencil_clear_value
;
2470 GLfloat old_color_clear_value
[4];
2474 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2475 if (TRACE_ON(ddraw
)) {
2478 TRACE(" rectangles : \n");
2479 for (i
= 0; i
< dwCount
; i
++) {
2480 TRACE(" - %ld x %ld %ld x %ld\n", lpRects
[i
].u1
.x1
, lpRects
[i
].u2
.y1
, lpRects
[i
].u3
.x2
, lpRects
[i
].u4
.y2
);
2486 /* Not sure if this is really needed... */
2490 rect
.u3
.x2
= This
->surface
->surface_desc
.dwWidth
;
2491 rect
.u4
.y2
= This
->surface
->surface_desc
.dwHeight
;
2495 /* Clears the screen */
2498 if (glThis
->state
== SURFACE_MEMORY_DIRTY
) {
2499 /* TODO: optimize here the case where Clear changes all the screen... */
2500 This
->flush_to_framebuffer(This
, NULL
, glThis
->lock_surf
);
2502 glThis
->state
= SURFACE_GL
;
2504 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2505 bitfield
|= GL_DEPTH_BUFFER_BIT
;
2506 glGetBooleanv(GL_DEPTH_WRITEMASK
, &ztest
);
2507 glDepthMask(GL_TRUE
); /* Enables Z writing to be sure to delete also the Z buffer */
2508 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &old_z_clear_value
);
2510 TRACE(" depth value : %f\n", dvZ
);
2512 if (dwFlags
& D3DCLEAR_STENCIL
) {
2513 bitfield
|= GL_STENCIL_BUFFER_BIT
;
2514 glGetIntegerv(GL_STENCIL_CLEAR_VALUE
, &old_stencil_clear_value
);
2515 glClearStencil(dwStencil
);
2516 TRACE(" stencil value : %ld\n", dwStencil
);
2518 if (dwFlags
& D3DCLEAR_TARGET
) {
2519 bitfield
|= GL_COLOR_BUFFER_BIT
;
2520 glGetFloatv(GL_COLOR_CLEAR_VALUE
, old_color_clear_value
);
2521 glClearColor(((dwColor
>> 16) & 0xFF) / 255.0,
2522 ((dwColor
>> 8) & 0xFF) / 255.0,
2523 ((dwColor
>> 0) & 0xFF) / 255.0,
2524 ((dwColor
>> 24) & 0xFF) / 255.0);
2525 TRACE(" color value (ARGB) : %08lx\n", dwColor
);
2528 glEnable(GL_SCISSOR_TEST
);
2529 for (i
= 0; i
< dwCount
; i
++) {
2530 glScissor(lpRects
[i
].u1
.x1
, This
->surface
->surface_desc
.dwHeight
- lpRects
[i
].u4
.y2
,
2531 lpRects
[i
].u3
.x2
- lpRects
[i
].u1
.x1
, lpRects
[i
].u4
.y2
- lpRects
[i
].u2
.y1
);
2534 glDisable(GL_SCISSOR_TEST
);
2536 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2538 glClearDepth(old_z_clear_value
);
2540 if (dwFlags
& D3DCLEAR_STENCIL
) {
2541 bitfield
|= GL_STENCIL_BUFFER_BIT
;
2542 glClearStencil(old_stencil_clear_value
);
2544 if (dwFlags
& D3DCLEAR_TARGET
) {
2545 bitfield
|= GL_COLOR_BUFFER_BIT
;
2546 glClearColor(old_color_clear_value
[0],
2547 old_color_clear_value
[1],
2548 old_color_clear_value
[2],
2549 old_color_clear_value
[3]);
2558 d3ddevice_blt(IDirectDrawSurfaceImpl
*This
, LPRECT rdst
,
2559 LPDIRECTDRAWSURFACE7 src
, LPRECT rsrc
,
2560 DWORD dwFlags
, LPDDBLTFX lpbltfx
)
2562 if (dwFlags
& DDBLT_COLORFILL
) {
2563 /* This is easy to handle for the D3D Device... */
2564 DWORD color
= lpbltfx
->u5
.dwFillColor
;
2567 TRACE(" executing D3D Device override.\n");
2570 rect
.u1
.x1
= rdst
->left
;
2571 rect
.u2
.y1
= rdst
->top
;
2572 rect
.u3
.x2
= rdst
->right
;
2573 rect
.u4
.y2
= rdst
->bottom
;
2575 d3ddevice_clear(This
->d3ddevice
, rdst
!= NULL
? 1 : 0, &rect
, D3DCLEAR_TARGET
, color
, 0.0, 0x00000000);
2578 return DDERR_INVALIDPARAMS
;
2582 d3ddevice_bltfast(IDirectDrawSurfaceImpl
*This
, DWORD dstx
,
2583 DWORD dsty
, LPDIRECTDRAWSURFACE7 src
,
2584 LPRECT rsrc
, DWORD trans
)
2586 return DDERR_INVALIDPARAMS
;
2590 d3ddevice_set_ortho(IDirect3DDeviceImpl
*This
)
2592 GLfloat height
, width
;
2593 GLfloat trans_mat
[16];
2595 width
= This
->surface
->surface_desc
.dwWidth
;
2596 height
= This
->surface
->surface_desc
.dwHeight
;
2598 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2599 to OpenGL screen coordinates (ie the upper left corner is not the same).
2600 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2601 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2602 trans_mat
[ 0] = 2.0 / width
; trans_mat
[ 4] = 0.0; trans_mat
[ 8] = 0.0; trans_mat
[12] = -1.0;
2603 trans_mat
[ 1] = 0.0; trans_mat
[ 5] = -2.0 / height
; trans_mat
[ 9] = 0.0; trans_mat
[13] = 1.0;
2604 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 1.0; trans_mat
[14] = -1.0;
2605 trans_mat
[ 3] = 0.0; trans_mat
[ 7] = 0.0; trans_mat
[11] = 0.0; trans_mat
[15] = 1.0;
2607 glMatrixMode(GL_MODELVIEW
);
2609 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2610 Correctness Tips section).
2612 Basically, from what I understood, if the game does not filter the font texture,
2613 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2614 one and we will have strange artifacts (as the rounding and stuff may give different results
2615 for different pixels, ie sometimes take the left pixel, sometimes the right).
2617 glTranslatef(0.375, 0.375, 0);
2618 glMatrixMode(GL_PROJECTION
);
2619 glLoadMatrixf(trans_mat
);
2623 d3ddevice_set_matrices(IDirect3DDeviceImpl
*This
, DWORD matrices
,
2624 D3DMATRIX
*world_mat
, D3DMATRIX
*view_mat
, D3DMATRIX
*proj_mat
)
2626 if ((matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
)) != 0) {
2627 glMatrixMode(GL_MODELVIEW
);
2628 glLoadMatrixf((float *) view_mat
);
2630 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2631 if (This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPING
- 1] != FALSE
) {
2634 for (i
= 0, runner
= 0x00000001; i
< This
->max_clipping_planes
; i
++, runner
<<= 1) {
2635 if (runner
& This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPLANEENABLE
- 1]) {
2638 plane
[0] = This
->clipping_planes
[i
].plane
[0];
2639 plane
[1] = This
->clipping_planes
[i
].plane
[1];
2640 plane
[2] = This
->clipping_planes
[i
].plane
[2];
2641 plane
[3] = This
->clipping_planes
[i
].plane
[3];
2643 glClipPlane( GL_CLIP_PLANE0
+ i
, (const GLdouble
*) (&plane
) );
2647 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] != FALSE
) {
2651 for (i
= 0, runner
= 0x00000001; i
< MAX_LIGHTS
; i
++, runner
<<= 1) {
2652 if (runner
& This
->active_lights
) {
2653 switch (This
->light_parameters
[i
].dltType
) {
2654 case D3DLIGHT_DIRECTIONAL
: {
2656 float cut_off
= 180.0;
2658 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
2659 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
2660 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
2661 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
2663 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
2664 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
2665 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
2667 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) direction
);
2670 case D3DLIGHT_POINT
: {
2672 float cut_off
= 180.0;
2674 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
2675 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
2676 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
2677 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
2678 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
2679 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
2681 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
2682 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
2683 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
2684 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
2685 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
2688 case D3DLIGHT_SPOT
: {
2691 float cut_off
= 90.0 * (This
->light_parameters
[i
].dvPhi
/ M_PI
);
2693 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
2694 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
2695 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
2697 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
2698 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
2699 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
2701 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_DIRECTION
, (float *) direction
);
2702 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
2703 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
2704 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
2706 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
2707 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
2708 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
2709 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
2710 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
2711 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_EXPONENT
, &(This
->light_parameters
[i
].dvFalloff
));
2715 /* No warning here as it's already done at light setting */
2722 glMultMatrixf((float *) world_mat
);
2724 if ((matrices
& PROJMAT_CHANGED
) != 0) {
2725 glMatrixMode(GL_PROJECTION
);
2726 glLoadMatrixf((float *) proj_mat
);
2731 d3ddevice_matrices_updated(IDirect3DDeviceImpl
*This
, DWORD matrices
)
2733 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2734 DWORD tex_mat
, tex_stage
;
2735 if ((matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
)) != 0) {
2736 if (glThis
->transform_state
== GL_TRANSFORM_NORMAL
) {
2737 /* This will force an update of the transform state at the next drawing. */
2738 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2741 if (matrices
& (TEXMAT0_CHANGED
|TEXMAT1_CHANGED
|TEXMAT2_CHANGED
|TEXMAT3_CHANGED
|
2742 TEXMAT4_CHANGED
|TEXMAT5_CHANGED
|TEXMAT6_CHANGED
|TEXMAT7_CHANGED
))
2745 for (tex_mat
= TEXMAT0_CHANGED
, tex_stage
= 0; tex_mat
<= TEXMAT7_CHANGED
; tex_mat
<<= 1, tex_stage
++) {
2746 if (matrices
& tex_mat
) {
2747 if (This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXTURETRANSFORMFLAGS
- 1] != D3DTTFF_DISABLE
) {
2748 if (tex_stage
== 0) {
2749 /* No multi-texturing support for now ... */
2750 glMatrixMode(GL_TEXTURE
);
2751 glLoadMatrixf((float *) This
->tex_mat
[tex_stage
]);
2754 glMatrixMode(GL_TEXTURE
);
2763 /* TODO for both these functions :
2764 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2765 by other OpenGL code in D3D
2766 - handle the case where no 'Begin / EndScene' was done between two locks
2767 - handle the rectangles in the unlock too
2768 - handle pitch correctly...
2770 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
2772 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
2773 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
2776 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
2778 if ((gl_d3d_dev
->front_state
!= SURFACE_GL
) &&
2779 (gl_d3d_dev
->front_lock_surf
!= This
)) {
2780 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2782 gl_d3d_dev
->front_lock_surf
= This
;
2783 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
2785 if ((gl_d3d_dev
->state
!= SURFACE_GL
) &&
2786 (gl_d3d_dev
->lock_surf
!= This
)) {
2787 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2789 gl_d3d_dev
->lock_surf
= This
;
2791 ERR("Wrong surface type for locking !\n");
2795 /* Try to acquire the device critical section */
2796 EnterCriticalSection(&(d3d_dev
->crit
));
2798 if (((is_front
== TRUE
) && (gl_d3d_dev
->front_state
== SURFACE_GL
)) ||
2799 ((is_front
== FALSE
) && (gl_d3d_dev
->state
== SURFACE_GL
))) {
2800 /* If the surface is already in memory, no need to do anything here... */
2802 GLenum buffer_color
;
2808 TRACE(" copying frame buffer to main memory.\n");
2810 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2811 may only write to the device... But when we will blit it back to the screen, we need
2812 also to blit correctly the parts the application did not overwrite... */
2816 glGetIntegerv(GL_READ_BUFFER
, &prev_read
);
2819 if (is_front
== TRUE
)
2820 /* Application wants to lock the front buffer */
2821 glReadBuffer(GL_FRONT
);
2823 /* Application wants to lock the back buffer */
2824 glReadBuffer(GL_BACK
);
2826 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
2827 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
2828 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
2829 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F) &&
2830 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x0000)) {
2831 buffer_type
= GL_UNSIGNED_SHORT_5_6_5
;
2832 buffer_color
= GL_RGB
;
2833 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) &&
2834 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
2835 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
2836 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF) &&
2837 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000)) {
2838 buffer_type
= GL_UNSIGNED_BYTE
;
2839 buffer_color
= GL_BGRA
;
2840 glPixelStorei(GL_PACK_SWAP_BYTES
, TRUE
);
2842 ERR(" unsupported pixel format at device locking.\n");
2847 /* Just a hack while waiting for proper rectangle support */
2849 if (pRect
== NULL
) {
2852 loc_rect
.bottom
= This
->surface_desc
.dwHeight
;
2853 loc_rect
.right
= This
->surface_desc
.dwWidth
;
2858 dst
= ((char *)This
->surface_desc
.lpSurface
) +
2859 (loc_rect
.top
* This
->surface_desc
.u1
.lPitch
) + (loc_rect
.left
* GET_BPP(This
->surface_desc
));
2860 for (y
= (This
->surface_desc
.dwHeight
- loc_rect
.top
- 1);
2861 y
>= ((int) This
->surface_desc
.dwHeight
- (int) loc_rect
.bottom
);
2863 glReadPixels(loc_rect
.left
, y
,
2864 loc_rect
.right
- loc_rect
.left
, 1,
2865 buffer_color
, buffer_type
, dst
);
2866 dst
+= This
->surface_desc
.u1
.lPitch
;
2869 glReadBuffer(prev_read
);
2870 glPixelStorei(GL_PACK_SWAP_BYTES
, FALSE
);
2873 gl_d3d_dev
->front_state
= SURFACE_MEMORY
;
2875 gl_d3d_dev
->state
= SURFACE_MEMORY
;
2878 /* I keep this code here as it's very useful to debug :-) */
2880 static int flush_count
= 0;
2884 if ((++flush_count
% 50) == 0) {
2885 sprintf(buf
, "lock_%06d.pnm", flush_count
);
2886 f
= fopen(buf
, "wb");
2887 DDRAW_dump_surface_to_disk(This
, f
);
2896 #define UNLOCK_TEX_SIZE 256
2898 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
2899 GLenum buffer_type
, buffer_color
;
2901 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
2902 GLint depth_test
, alpha_test
, cull_face
, lighting
, min_tex
, max_tex
, tex_env
, blend
, stencil_test
, fog
;
2903 GLuint initial_texture
;
2907 /* This is to prevent another thread to actually lock the buffer while we flush it on screen */
2908 EnterCriticalSection(&(d3d_dev
->crit
));
2912 loc_rect
.bottom
= surf
->surface_desc
.dwHeight
;
2913 loc_rect
.right
= surf
->surface_desc
.dwWidth
;
2915 TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect
.top
, loc_rect
.left
, loc_rect
.right
, loc_rect
.bottom
);
2917 glGetIntegerv(GL_DEPTH_TEST
, &depth_test
);
2918 glGetIntegerv(GL_ALPHA_TEST
, &alpha_test
);
2919 glGetIntegerv(GL_STENCIL_TEST
, &stencil_test
);
2920 glGetIntegerv(GL_CULL_FACE
, &cull_face
);
2921 glGetIntegerv(GL_LIGHTING
, &lighting
);
2922 glGetIntegerv(GL_BLEND
, &blend
);
2923 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &initial_texture
);
2924 glGetIntegerv(GL_TEXTURE_2D
, &tex_state
);
2925 glGetIntegerv(GL_FOG
, &fog
);
2926 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, &max_tex
);
2927 glGetTexParameteriv(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, &min_tex
);
2928 glGetTexEnviv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, &tex_env
);
2929 glMatrixMode(GL_TEXTURE
);
2931 /* TODO: scissor test if ever we use it ! */
2933 if ((surf
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
2934 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
2935 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
2936 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F) &&
2937 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x0000)) {
2938 buffer_type
= GL_UNSIGNED_SHORT_5_6_5
;
2939 buffer_color
= GL_RGB
;
2940 } else if ((surf
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) &&
2941 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
2942 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
2943 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF) &&
2944 (surf
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000)) {
2945 buffer_type
= GL_UNSIGNED_BYTE
;
2946 buffer_color
= GL_BGRA
;
2947 glPixelStorei(GL_UNPACK_SWAP_BYTES
, TRUE
);
2949 ERR(" unsupported pixel format at frame buffer flush.\n");
2950 LeaveCriticalSection(&(d3d_dev
->crit
));
2954 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
2955 d3ddevice_set_ortho(d3d_dev
);
2957 glDisable(GL_DEPTH_TEST
);
2958 glEnable(GL_TEXTURE_2D
);
2959 glEnable(GL_SCISSOR_TEST
);
2960 glScissor(loc_rect
.left
, surf
->surface_desc
.dwHeight
- loc_rect
.bottom
,
2961 loc_rect
.right
- loc_rect
.left
, loc_rect
.bottom
- loc_rect
.top
);
2963 if (gl_d3d_dev
->unlock_tex
== 0) {
2964 glGenTextures(1, &gl_d3d_dev
->unlock_tex
);
2965 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
2966 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
,
2967 UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
, 0,
2968 GL_RGB
, buffer_type
, NULL
);
2970 glBindTexture(GL_TEXTURE_2D
, gl_d3d_dev
->unlock_tex
);
2972 glPixelStorei(GL_UNPACK_ROW_LENGTH
, surf
->surface_desc
.dwWidth
);
2974 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
2975 glDisable(GL_LIGHTING
);
2976 glDisable(GL_CULL_FACE
);
2977 glDisable(GL_ALPHA_TEST
);
2978 glDisable(GL_STENCIL_TEST
);
2979 glDisable(GL_BLEND
);
2981 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
2982 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
2984 for (x
= loc_rect
.left
; x
< loc_rect
.right
; x
+= UNLOCK_TEX_SIZE
) {
2985 for (y
= loc_rect
.top
; y
< loc_rect
.bottom
; y
+= UNLOCK_TEX_SIZE
) {
2986 /* First, upload the texture... */
2987 int w
= (x
+ UNLOCK_TEX_SIZE
> surf
->surface_desc
.dwWidth
) ? (surf
->surface_desc
.dwWidth
- x
) : UNLOCK_TEX_SIZE
;
2988 int h
= (y
+ UNLOCK_TEX_SIZE
> surf
->surface_desc
.dwHeight
) ? (surf
->surface_desc
.dwHeight
- y
) : UNLOCK_TEX_SIZE
;
2989 glTexSubImage2D(GL_TEXTURE_2D
,
2995 ((char *) surf
->surface_desc
.lpSurface
) + (x
* GET_BPP(surf
->surface_desc
)) + (y
* surf
->surface_desc
.u1
.lPitch
));
2997 glColor3ub(0xFF, 0xFF, 0xFF);
2998 glTexCoord2f(0.0, 0.0);
2999 glVertex3d(x
, y
, 0.5);
3000 glTexCoord2f(1.0, 0.0);
3001 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
, 0.5);
3002 glTexCoord2f(1.0, 1.0);
3003 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3004 glTexCoord2f(0.0, 1.0);
3005 glVertex3d(x
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3011 /* And restore all the various states modified by this code */
3012 if (depth_test
!= 0) glEnable(GL_DEPTH_TEST
);
3013 if (lighting
!= 0) glEnable(GL_LIGHTING
);
3014 if (alpha_test
!= 0) glEnable(GL_ALPHA_TEST
);
3015 if (stencil_test
!= 0) glEnable(GL_STENCIL_TEST
);
3016 if (cull_face
!= 0) glEnable(GL_CULL_FACE
);
3017 if (blend
!= 0) glEnable(GL_BLEND
);
3018 if (fog
!= 0) glEnable(GL_FOG
);
3019 glBindTexture(GL_TEXTURE_2D
, initial_texture
);
3020 if (tex_state
== 0) glDisable(GL_TEXTURE_2D
);
3021 glDisable(GL_SCISSOR_TEST
);
3022 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
3023 glPixelStorei(GL_UNPACK_SWAP_BYTES
, FALSE
);
3024 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, max_tex
);
3025 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, min_tex
);
3026 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, tex_env
);
3028 d3d_dev
->matrices_updated(d3d_dev
, TEXMAT0_CHANGED
);
3031 /* I keep this code here as it's very useful to debug :-) */
3033 static int flush_count
= 0;
3037 if ((++flush_count
% 50) == 0) {
3038 sprintf(buf
, "flush_%06d.pnm", flush_count
);
3039 f
= fopen(buf
, "wb");
3040 DDRAW_dump_surface_to_disk(surf
, f
);
3045 /* And leave the critical section... */
3046 LeaveCriticalSection(&(d3d_dev
->crit
));
3049 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
3052 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3053 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3055 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3057 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3060 ERR("Wrong surface type for locking !\n");
3063 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3064 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0) {
3065 if (is_front
== TRUE
) {
3068 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3069 glDrawBuffer(GL_FRONT
);
3070 d3d_dev
->flush_to_framebuffer(d3d_dev
, pRect
, gl_d3d_dev
->front_lock_surf
);
3071 glDrawBuffer(prev_draw
);
3074 gl_d3d_dev
->state
= SURFACE_MEMORY_DIRTY
;
3078 /* And 'frees' the device critical section */
3079 LeaveCriticalSection(&(d3d_dev
->crit
));
3083 apply_texture_state(IDirect3DDeviceImpl
*This
)
3087 /* Initialize texture stages states */
3088 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
3089 for (state
= 0; state
< HIGHEST_TEXTURE_STAGE_STATE
; state
+= 1) {
3090 if (This
->state_block
.set_flags
.texture_stage_state
[stage
][state
] == TRUE
) {
3091 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
3092 stage
, state
+ 1, This
->state_block
.texture_stage_state
[stage
][state
]);
3099 d3ddevice_create(IDirect3DDeviceImpl
**obj
, IDirect3DImpl
*d3d
, IDirectDrawSurfaceImpl
*surface
)
3101 IDirect3DDeviceImpl
*object
;
3102 IDirect3DDeviceGLImpl
*gl_object
;
3103 IDirectDrawSurfaceImpl
*surf
;
3108 XVisualInfo
template;
3109 GLenum buffer
= GL_FRONT
;
3111 GLint max_clipping_planes
= 0;
3113 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DDeviceGLImpl
));
3114 if (object
== NULL
) return DDERR_OUTOFMEMORY
;
3116 gl_object
= (IDirect3DDeviceGLImpl
*) object
;
3120 object
->surface
= surface
;
3121 object
->set_context
= set_context
;
3122 object
->clear
= d3ddevice_clear
;
3123 object
->set_matrices
= d3ddevice_set_matrices
;
3124 object
->matrices_updated
= d3ddevice_matrices_updated
;
3125 object
->flush_to_framebuffer
= d3ddevice_flush_to_frame_buffer
;
3127 InitializeCriticalSection(&(object
->crit
));
3129 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface
, d3d
);
3131 device_context
= GetDC(surface
->ddraw_owner
->window
);
3132 gl_object
->display
= get_display(device_context
);
3133 gl_object
->drawable
= get_drawable(device_context
);
3134 ReleaseDC(surface
->ddraw_owner
->window
,device_context
);
3137 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3138 vis
= XGetVisualInfo(gl_object
->display
, VisualIDMask
, &template, &num
);
3140 HeapFree(GetProcessHeap(), 0, object
);
3141 ERR("No visual found !\n");
3143 return DDERR_INVALIDPARAMS
;
3145 TRACE(" visual found\n");
3148 gl_object
->gl_context
= glXCreateContext(gl_object
->display
, vis
,
3151 if (gl_object
->gl_context
== NULL
) {
3152 HeapFree(GetProcessHeap(), 0, object
);
3153 ERR("Error in context creation !\n");
3155 return DDERR_INVALIDPARAMS
;
3157 TRACE(" context created (%p)\n", gl_object
->gl_context
);
3160 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3161 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3162 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
3163 surf
->aux_ctx
= (LPVOID
) object
;
3164 surf
->aux_data
= (LPVOID
) gl_object
->drawable
;
3165 surf
->aux_flip
= opengl_flip
;
3170 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3172 TRACE(" no double buffering : drawing on the front buffer\n");
3176 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3177 IDirectDrawSurfaceImpl
*surf2
;
3178 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
3179 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
3180 TRACE(" checking surface %p :", surf2
);
3181 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
3182 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
3183 /* Override the Lock / Unlock function for all these surfaces */
3184 surf2
->lock_update_prev
= surf2
->lock_update
;
3185 surf2
->lock_update
= d3ddevice_lock_update
;
3186 surf2
->unlock_update_prev
= surf2
->unlock_update
;
3187 surf2
->unlock_update
= d3ddevice_unlock_update
;
3188 /* And install also the blt / bltfast overrides */
3189 surf2
->aux_blt
= d3ddevice_blt
;
3190 surf2
->aux_bltfast
= d3ddevice_bltfast
;
3192 TRACE(" overiding direct surface access.\n");
3194 TRACE(" no overide.\n");
3196 surf2
->d3ddevice
= object
;
3200 /* Set the various light parameters */
3201 for (light
= 0; light
< MAX_LIGHTS
; light
++) {
3202 /* Only set the fields that are not zero-created */
3203 object
->light_parameters
[light
].dltType
= D3DLIGHT_DIRECTIONAL
;
3204 object
->light_parameters
[light
].dcvDiffuse
.u1
.r
= 1.0;
3205 object
->light_parameters
[light
].dcvDiffuse
.u2
.g
= 1.0;
3206 object
->light_parameters
[light
].dcvDiffuse
.u3
.b
= 1.0;
3207 object
->light_parameters
[light
].dvDirection
.u3
.z
= 1.0;
3210 /* Allocate memory for the matrices */
3211 object
->world_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3212 object
->view_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3213 object
->proj_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3214 memcpy(object
->world_mat
, id_mat
, 16 * sizeof(float));
3215 memcpy(object
->view_mat
, id_mat
, 16 * sizeof(float));
3216 memcpy(object
->proj_mat
, id_mat
, 16 * sizeof(float));
3217 for (tex_num
= 0; tex_num
< MAX_TEXTURES
; tex_num
++) {
3218 object
->tex_mat
[tex_num
] = (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3219 memcpy(object
->tex_mat
[tex_num
], id_mat
, 16 * sizeof(float));
3222 /* Initialisation */
3223 TRACE(" setting current context\n");
3225 object
->set_context(object
);
3227 TRACE(" current context set\n");
3229 /* allocate the clipping planes */
3230 glGetIntegerv(GL_MAX_CLIP_PLANES
,&max_clipping_planes
);
3231 if (max_clipping_planes
>32) {
3232 object
->max_clipping_planes
=32;
3234 object
->max_clipping_planes
= max_clipping_planes
;
3236 TRACE(" capable of %d clipping planes\n", (int)object
->max_clipping_planes
);
3237 object
->clipping_planes
= (d3d7clippingplane
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->max_clipping_planes
* sizeof(d3d7clippingplane
));
3239 glHint(GL_FOG_HINT
,GL_NICEST
);
3241 glClearColor(0.0, 0.0, 0.0, 0.0);
3242 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3243 glDrawBuffer(buffer
);
3244 glReadBuffer(buffer
);
3245 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3248 gl_object
->state
= SURFACE_GL
;
3250 /* fill_device_capabilities(d3d->ddraw); */
3252 ICOM_INIT_INTERFACE(object
, IDirect3DDevice
, VTABLE_IDirect3DDevice
);
3253 ICOM_INIT_INTERFACE(object
, IDirect3DDevice2
, VTABLE_IDirect3DDevice2
);
3254 ICOM_INIT_INTERFACE(object
, IDirect3DDevice3
, VTABLE_IDirect3DDevice3
);
3255 ICOM_INIT_INTERFACE(object
, IDirect3DDevice7
, VTABLE_IDirect3DDevice7
);
3259 TRACE(" creating implementation at %p.\n", *obj
);
3261 /* And finally warn D3D that this device is now present */
3262 object
->d3d
->added_device(object
->d3d
, object
);
3264 /* FIXME: Should handle other versions than just 7 */
3265 InitDefaultStateBlock(&object
->state_block
, 7);
3266 /* Apply default render state and texture stage state values */
3267 apply_render_state(object
, &object
->state_block
);
3268 apply_texture_state(object
);
3270 /* And fill the fog table with the default fog value */
3271 build_fog_table(gl_object
->fog_table
, object
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);