2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wined3d_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
33 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
35 /* x11drv GDI escapes */
36 #define X11DRV_ESCAPE 6789
37 enum x11drv_escape_codes
39 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
40 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
41 X11DRV_GET_FONT
, /* get current X font for a DC */
44 /* retrieve the X display to use on a given DC */
45 inline static Display
*get_display( HDC hdc
)
48 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
50 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
51 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
55 /* Memory tracking and object counting */
56 static unsigned int emulated_textureram
= 64*1024*1024;
58 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
59 /* enable pbuffer support for offscreen textures */
60 BOOL pbuffer_support
= FALSE
;
61 /* allocate one pbuffer per surface */
62 BOOL pbuffer_per_surface
= FALSE
;
64 /* static function declarations */
65 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
);
67 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
);
70 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
72 #define D3DCREATEOBJECTINSTANCE(object, type) { \
73 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
74 D3DMEMCHECK(object, pp##type); \
75 object->lpVtbl = &IWineD3D##type##_Vtbl; \
76 object->wineD3DDevice = This; \
77 object->parent = parent; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
83 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
84 D3DMEMCHECK(object, pp##type); \
85 object->lpVtbl = &IWineD3D##type##_Vtbl; \
86 object->resource.wineD3DDevice = This; \
87 object->resource.parent = parent; \
88 object->resource.resourceType = d3dtype; \
89 object->resource.ref = 1; \
90 object->resource.pool = Pool; \
91 object->resource.format = Format; \
92 object->resource.usage = Usage; \
93 object->resource.size = _size; \
94 /* Check that we have enough video ram left */ \
95 if (Pool == WINED3DPOOL_DEFAULT) { \
96 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
97 WARN("Out of 'bogus' video memory\n"); \
98 HeapFree(GetProcessHeap(), 0, object); \
100 return WINED3DERR_OUTOFVIDEOMEMORY; \
102 globalChangeGlRam(_size); \
104 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
105 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
106 FIXME("Out of memory!\n"); \
107 HeapFree(GetProcessHeap(), 0, object); \
109 return WINED3DERR_OUTOFVIDEOMEMORY; \
111 *pp##type = (IWineD3D##type *) object; \
112 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
113 TRACE("(%p) : Created resource %p\n", This, object); \
116 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
117 _basetexture.levels = Levels; \
118 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
119 _basetexture.LOD = 0; \
120 _basetexture.dirty = TRUE; \
123 /**********************************************************
124 * Global variable / Constants follow
125 **********************************************************/
126 const float identity
[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
128 /**********************************************************
129 * Utility functions follow
130 **********************************************************/
131 /* Convert the D3DLIGHT properties into equivalent gl lights */
132 static void setup_light(IWineD3DDevice
*iface
, LONG Index
, PLIGHTINFOEL
*lightInfo
) {
135 float colRGBA
[] = {0.0, 0.0, 0.0, 0.0};
136 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
138 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
139 glMatrixMode(GL_MODELVIEW
);
141 glLoadMatrixf((float *)&This
->stateBlock
->transforms
[D3DTS_VIEW
].u
.m
[0][0]);
144 colRGBA
[0] = lightInfo
->OriginalParms
.Diffuse
.r
;
145 colRGBA
[1] = lightInfo
->OriginalParms
.Diffuse
.g
;
146 colRGBA
[2] = lightInfo
->OriginalParms
.Diffuse
.b
;
147 colRGBA
[3] = lightInfo
->OriginalParms
.Diffuse
.a
;
148 glLightfv(GL_LIGHT0
+Index
, GL_DIFFUSE
, colRGBA
);
149 checkGLcall("glLightfv");
152 colRGBA
[0] = lightInfo
->OriginalParms
.Specular
.r
;
153 colRGBA
[1] = lightInfo
->OriginalParms
.Specular
.g
;
154 colRGBA
[2] = lightInfo
->OriginalParms
.Specular
.b
;
155 colRGBA
[3] = lightInfo
->OriginalParms
.Specular
.a
;
156 glLightfv(GL_LIGHT0
+Index
, GL_SPECULAR
, colRGBA
);
157 checkGLcall("glLightfv");
160 colRGBA
[0] = lightInfo
->OriginalParms
.Ambient
.r
;
161 colRGBA
[1] = lightInfo
->OriginalParms
.Ambient
.g
;
162 colRGBA
[2] = lightInfo
->OriginalParms
.Ambient
.b
;
163 colRGBA
[3] = lightInfo
->OriginalParms
.Ambient
.a
;
164 glLightfv(GL_LIGHT0
+Index
, GL_AMBIENT
, colRGBA
);
165 checkGLcall("glLightfv");
167 /* Attenuation - Are these right? guessing... */
168 glLightf(GL_LIGHT0
+Index
, GL_CONSTANT_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation0
);
169 checkGLcall("glLightf");
170 glLightf(GL_LIGHT0
+Index
, GL_LINEAR_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation1
);
171 checkGLcall("glLightf");
173 if ((lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
) >= FLT_MIN
) {
174 quad_att
= 1.4/(lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
);
176 quad_att
= 0; /* 0 or MAX? (0 seems to be ok) */
179 if (quad_att
< lightInfo
->OriginalParms
.Attenuation2
) quad_att
= lightInfo
->OriginalParms
.Attenuation2
;
180 glLightf(GL_LIGHT0
+Index
, GL_QUADRATIC_ATTENUATION
, quad_att
);
181 checkGLcall("glLightf");
183 switch (lightInfo
->OriginalParms
.Type
) {
186 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
187 checkGLcall("glLightfv");
188 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
189 checkGLcall("glLightf");
195 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
196 checkGLcall("glLightfv");
198 glLightfv(GL_LIGHT0
+Index
, GL_SPOT_DIRECTION
, &lightInfo
->lightDirn
[0]);
199 checkGLcall("glLightfv");
200 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_EXPONENT
, lightInfo
->exponent
);
201 checkGLcall("glLightf");
202 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
203 checkGLcall("glLightf");
207 case D3DLIGHT_DIRECTIONAL
:
209 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]); /* Note gl uses w position of 0 for direction! */
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0
+Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
212 checkGLcall("glLightf");
213 glLightf(GL_LIGHT0
+Index
, GL_SPOT_EXPONENT
, 0.0f
);
214 checkGLcall("glLightf");
218 FIXME("Unrecognized light type %d\n", lightInfo
->OriginalParms
.Type
);
221 /* Restore the modelview matrix */
225 /* Apply the current values to the specified texture stage */
226 void WINAPI
IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice
*iface
, DWORD Sampler
, DWORD Flags
) {
227 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
235 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
236 clamping, MIPLOD, etc. This will work for up to 16 samplers.
239 if (Sampler
>= GL_LIMITS(samplers
)) {
240 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler
, GL_LIMITS(samplers
));
243 VTRACE(("Activating appropriate texture state %ld\n", Sampler
));
244 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
246 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ Sampler
));
247 checkGLcall("glActiveTextureARB");
249 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
250 } else if (Sampler
> 0) {
251 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
255 /* TODO: change this to a lookup table
256 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
257 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
258 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
259 especially when there are a number of groups of states. */
261 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler
);
263 /* The list of states not to apply is a big as the list of states to apply, so it makes sense to produce an inclusive list */
264 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
265 /* these are the only two supported states that need to be applied */
266 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX
);
267 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS
);
268 #if 0 /* not supported at the moment */
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT00
);
270 APPLY_STATE(WINED3DTSS_BUMPENVMAT01
);
271 APPLY_STATE(WINED3DTSS_BUMPENVMAT10
);
272 APPLY_STATE(WINED3DTSS_BUMPENVMAT11
);
273 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE
);
274 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET
);
275 APPLY_STATE(WINED3DTSS_RESULTARG
);
276 APPLY_STATE(WINED3DTSS_CONSTANT
);
278 /* a quick sanity check in case someone forgot to update this function */
279 if (WINED3D_HIGHEST_TEXTURE_STATE
> WINED3DTSS_CONSTANT
) {
280 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This
);
284 /* apply any sampler states that always need applying */
285 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS
)) {
286 tmpvalue
.d
= This
->stateBlock
->samplerState
[Sampler
][WINED3DSAMP_MIPMAPLODBIAS
];
287 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT
,
288 GL_TEXTURE_LOD_BIAS_EXT
,
290 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
293 /* Note the D3DRS value applies to all textures, but GL has one
294 * per texture, so apply it now ready to be used!
296 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
297 /* Set the default alpha blend color */
298 if (GL_SUPPORT(ARB_IMAGING
)) {
299 GL_EXTCALL(glBlendColor(col
[0], col
[1], col
[2], col
[3]));
300 checkGLcall("glBlendColor");
302 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
305 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
306 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
307 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
309 /* TODO: NV_POINT_SPRITE */
310 if (GL_SUPPORT(ARB_POINT_SPRITE
)) {
311 if (This
->stateBlock
->renderState
[WINED3DRS_POINTSPRITEENABLE
] != FALSE
) {
312 /* Doesn't work with GL_POINT_SMOOTH on on my ATI 9600, but then ATI drivers are buggered! */
313 glDisable(GL_POINT_SMOOTH
);
315 /* Centre the texture on the vertex */
316 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
317 glTexEnvf( GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, GL_TRUE
);
319 VTRACE(("glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)\n"));
320 glTexEnvf( GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, GL_TRUE
);
321 checkGLcall("glTexEnvf(...)");
322 VTRACE(("glEnable( GL_POINT_SPRITE_ARB )\n"));
323 glEnable( GL_POINT_SPRITE_ARB
);
324 checkGLcall("glEnable(...)");
326 VTRACE(("glDisable( GL_POINT_SPRITE_ARB )\n"));
327 glDisable( GL_POINT_SPRITE_ARB
);
328 checkGLcall("glEnable(...)");
332 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler
);
335 /**********************************************************
336 * IUnknown parts follows
337 **********************************************************/
339 HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
341 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
343 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
344 if (IsEqualGUID(riid
, &IID_IUnknown
)
345 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
346 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
347 IUnknown_AddRef(iface
);
352 return E_NOINTERFACE
;
355 ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
356 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
357 ULONG refCount
= InterlockedIncrement(&This
->ref
);
359 TRACE("(%p) : AddRef increasing from %ld\n", This
, refCount
- 1);
363 ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
364 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
365 ULONG refCount
= InterlockedDecrement(&This
->ref
);
367 TRACE("(%p) : Releasing from %ld\n", This
, refCount
+ 1);
370 /* TODO: Clean up all the surfaces and textures! */
371 /* NOTE: You must release the parent if the object was created via a callback
372 ** ***************************/
374 /* Release the update stateblock */
375 if(IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
) > 0){
376 if(This
->updateStateBlock
!= This
->stateBlock
)
377 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
379 This
->updateStateBlock
= NULL
;
380 { /* because were not doing proper internal refcounts releasing the primary state block
381 causes recursion with the extra checks in ResourceReleased, to avoid this we have
382 to set this->stateBlock = NULL; first */
383 IWineD3DStateBlock
*stateBlock
= (IWineD3DStateBlock
*)This
->stateBlock
;
384 This
->stateBlock
= NULL
;
386 /* Release the stateblock */
387 if(IWineD3DStateBlock_Release(stateBlock
) > 0){
388 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
392 if (This
->resources
!= NULL
) {
393 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
394 dumpResources(This
->resources
);
398 IWineD3D_Release(This
->wineD3D
);
399 This
->wineD3D
= NULL
;
400 HeapFree(GetProcessHeap(), 0, This
);
401 TRACE("Freed device %p\n", This
);
407 /**********************************************************
408 * IWineD3DDevice implementation follows
409 **********************************************************/
410 HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
411 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
412 *pParent
= This
->parent
;
413 IUnknown_AddRef(This
->parent
);
417 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
418 DWORD FVF
, WINED3DPOOL Pool
, IWineD3DVertexBuffer
** ppVertexBuffer
, HANDLE
*sharedHandle
,
420 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
421 IWineD3DVertexBufferImpl
*object
;
422 WINED3DFORMAT Format
= WINED3DFMT_VERTEXDATA
; /* Dummy format for now */
423 D3DCREATERESOURCEOBJECTINSTANCE(object
, VertexBuffer
, WINED3DRTYPE_VERTEXBUFFER
, Size
)
426 if (Pool
== WINED3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
427 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->resource
.size
);
431 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This
, Size
, Usage
, FVF
, Pool
, object
->resource
.allocatedMemory
, object
);
432 *ppVertexBuffer
= (IWineD3DVertexBuffer
*)object
;
437 HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
438 WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DIndexBuffer
** ppIndexBuffer
,
439 HANDLE
*sharedHandle
, IUnknown
*parent
) {
440 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
441 IWineD3DIndexBufferImpl
*object
;
442 TRACE("(%p) Creating index buffer\n", This
);
444 /* Allocate the storage for the device */
445 D3DCREATERESOURCEOBJECTINSTANCE(object
,IndexBuffer
,WINED3DRTYPE_INDEXBUFFER
, Length
)
448 if (Pool
== WINED3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
449 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,object
->resource
.size
);
452 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This
, Length
, Usage
, Format
,
453 debug_d3dformat(Format
), Pool
, object
, object
->resource
.allocatedMemory
);
454 *ppIndexBuffer
= (IWineD3DIndexBuffer
*) object
;
459 HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
* iface
, WINED3DSTATEBLOCKTYPE Type
, IWineD3DStateBlock
** ppStateBlock
, IUnknown
*parent
) {
461 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
462 IWineD3DStateBlockImpl
*object
;
465 D3DCREATEOBJECTINSTANCE(object
, StateBlock
)
466 object
->blockType
= Type
;
468 /* Special case - Used during initialization to produce a placeholder stateblock
469 so other functions called can update a state block */
470 if (Type
== WINED3DSBT_INIT
) {
471 /* Don't bother increasing the reference count otherwise a device will never
472 be freed due to circular dependencies */
476 /* Otherwise, might as well set the whole state block to the appropriate values */
477 if ( This
->stateBlock
!= NULL
) {
478 memcpy(object
, This
->stateBlock
, sizeof(IWineD3DStateBlockImpl
));
480 memset(object
->streamFreq
, 1, sizeof(object
->streamFreq
));
483 /* Reset the ref and type after kludging it */
484 object
->wineD3DDevice
= This
;
486 object
->blockType
= Type
;
488 TRACE("Updating changed flags appropriate for type %d\n", Type
);
490 if (Type
== WINED3DSBT_ALL
) {
492 TRACE("ALL => Pretend everything has changed\n");
493 memset(&object
->changed
, TRUE
, sizeof(This
->stateBlock
->changed
));
494 } else if (Type
== WINED3DSBT_PIXELSTATE
) {
496 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
497 memset(&object
->changed
, FALSE
, sizeof(This
->stateBlock
->changed
));
499 object
->changed
.pixelShader
= TRUE
;
501 /* Pixel Shader Constants */
502 for (i
= 0; i
< MAX_PSHADER_CONSTANTS
; ++i
) {
503 object
->changed
.pixelShaderConstants
[i
] = TRUE
;
505 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
506 object
->changed
.renderState
[SavedPixelStates_R
[i
]] = TRUE
;
508 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
509 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
510 object
->changed
.textureState
[j
][SavedPixelStates_T
[i
]] = TRUE
;
513 for (j
= 0 ; j
< 16; j
++) {
514 for (i
=0; i
< NUM_SAVEDPIXELSTATES_S
;i
++) {
516 object
->changed
.samplerState
[j
][SavedPixelStates_S
[i
]] = TRUE
;
520 } else if (Type
== WINED3DSBT_VERTEXSTATE
) {
522 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
523 memset(&object
->changed
, FALSE
, sizeof(This
->stateBlock
->changed
));
525 object
->changed
.vertexShader
= TRUE
;
527 /* Vertex Shader Constants */
528 for (i
= 0; i
< MAX_VSHADER_CONSTANTS
; ++i
) {
529 object
->changed
.vertexShaderConstants
[i
] = TRUE
;
531 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
532 object
->changed
.renderState
[SavedVertexStates_R
[i
]] = TRUE
;
534 for (j
= 0; j
< GL_LIMITS(textures
); j
++) {
535 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
536 object
->changed
.textureState
[j
][SavedVertexStates_T
[i
]] = TRUE
;
539 for (j
= 0 ; j
< 16; j
++){
540 for (i
=0; i
< NUM_SAVEDVERTEXSTATES_S
;i
++) {
541 object
->changed
.samplerState
[j
][SavedVertexStates_S
[i
]] = TRUE
;
545 /* Duplicate light chain */
547 PLIGHTINFOEL
*src
= NULL
;
548 PLIGHTINFOEL
*dst
= NULL
;
549 PLIGHTINFOEL
*newEl
= NULL
;
550 src
= This
->stateBlock
->lights
;
551 object
->lights
= NULL
;
555 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
556 if (newEl
== NULL
) return WINED3DERR_OUTOFVIDEOMEMORY
;
557 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
559 newEl
->changed
= TRUE
;
560 newEl
->enabledChanged
= TRUE
;
562 object
->lights
= newEl
;
573 FIXME("Unrecognized state block type %d\n", Type
);
576 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
581 /* ************************************
583 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
586 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
588 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
590 ******************************** */
592 HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, WINED3DFORMAT Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, IWineD3DSurface
**ppSurface
,WINED3DRESOURCETYPE Type
, DWORD Usage
, WINED3DPOOL Pool
, WINED3DMULTISAMPLE_TYPE MultiSample
,DWORD MultisampleQuality
, HANDLE
* pSharedHandle
, WINED3DSURFTYPE Impl
, IUnknown
*parent
) {
593 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
594 IWineD3DSurfaceImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
595 unsigned int pow2Width
, pow2Height
;
596 unsigned int Size
= 1;
597 TRACE("(%p) Create surface\n",This
);
599 /** FIXME: Check ranges on the inputs are valid
602 * [in] Quality level. The valid range is between zero and one less than the level
603 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
604 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
605 * values of paired render targets, depth stencil surfaces, and the MultiSample type
607 *******************************/
612 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
614 * If this flag is set, the contents of the depth stencil buffer will be
615 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
616 * with a different depth surface.
618 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
619 ***************************/
621 if(MultisampleQuality
< 0) {
622 FIXME("Invalid multisample level %ld\n", MultisampleQuality
);
623 return WINED3DERR_INVALIDCALL
; /* TODO: Check that this is the case! */
626 if(MultisampleQuality
> 0) {
627 FIXME("MultisampleQuality set to %ld, substituting 0\n", MultisampleQuality
);
628 MultisampleQuality
=0;
631 /** FIXME: Check that the format is supported
633 *******************************/
635 /* Non-power2 support */
637 /* Find the nearest pow2 match */
638 pow2Width
= pow2Height
= 1;
639 while (pow2Width
< Width
) pow2Width
<<= 1;
640 while (pow2Height
< Height
) pow2Height
<<= 1;
642 if (pow2Width
> Width
|| pow2Height
> Height
) {
643 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
644 if (Format
== WINED3DFMT_DXT1
|| Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
645 || Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
646 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
647 This
, Width
, Height
);
648 return WINED3DERR_NOTAVAILABLE
;
652 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
653 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
655 *********************************/
656 if (WINED3DFMT_UNKNOWN
== Format
) {
658 } else if (Format
== WINED3DFMT_DXT1
) {
659 /* DXT1 is half byte per pixel */
660 Size
= ((max(pow2Width
,4) * D3DFmtGetBpp(This
, Format
)) * max(pow2Height
,4)) >> 1;
662 } else if (Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
663 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
664 Size
= ((max(pow2Width
,4) * D3DFmtGetBpp(This
, Format
)) * max(pow2Height
,4));
666 Size
= (pow2Width
* D3DFmtGetBpp(This
, Format
)) * pow2Height
;
669 /** Create and initialise the surface resource **/
670 D3DCREATERESOURCEOBJECTINSTANCE(object
,Surface
,WINED3DRTYPE_SURFACE
, Size
)
671 /* "Standalone" surface */
672 IWineD3DSurface_SetContainer((IWineD3DSurface
*)object
, NULL
);
674 object
->currentDesc
.Width
= Width
;
675 object
->currentDesc
.Height
= Height
;
676 object
->currentDesc
.MultiSampleType
= MultiSample
;
677 object
->currentDesc
.MultiSampleQuality
= MultisampleQuality
;
679 /* Setup some glformat defaults */
680 if (WINED3DFMT_UNKNOWN
!= Format
) {
681 object
->glDescription
.glFormat
= D3DFmt2GLFmt(This
, object
->resource
.format
);
682 object
->glDescription
.glFormatInternal
= D3DFmt2GLIntFmt(This
, object
->resource
.format
);
683 object
->glDescription
.glType
= D3DFmt2GLType(This
, object
->resource
.format
);
685 object
->glDescription
.glFormat
= 0;
686 object
->glDescription
.glFormatInternal
= 0;
687 object
->glDescription
.glType
= 0;
690 object
->glDescription
.textureName
= 0;
691 object
->glDescription
.level
= Level
;
692 object
->glDescription
.target
= GL_TEXTURE_2D
;
695 object
->pow2Width
= pow2Width
;
696 object
->pow2Height
= pow2Height
;
699 object
->Flags
= 0; /* We start without flags set */
700 object
->Flags
|= (pow2Width
!= Width
|| pow2Height
!= Height
) ? SFLAG_NONPOW2
: 0;
701 object
->Flags
|= Discard
? SFLAG_DISCARD
: 0;
702 object
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== Format
) ? SFLAG_LOCKABLE
: 0;
703 object
->Flags
|= Lockable
? SFLAG_LOCKABLE
: 0;
706 if (WINED3DFMT_UNKNOWN
!= Format
) {
707 object
->bytesPerPixel
= D3DFmtGetBpp(This
, Format
);
708 object
->pow2Size
= (pow2Width
* object
->bytesPerPixel
) * pow2Height
;
710 object
->bytesPerPixel
= 0;
711 object
->pow2Size
= 0;
714 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
716 TRACE("Pool %d %d %d %d",Pool
, WINED3DPOOL_DEFAULT
, WINED3DPOOL_MANAGED
, WINED3DPOOL_SYSTEMMEM
);
718 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
719 * this function is too deap to need to care about things like this.
720 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
721 * ****************************************/
723 case WINED3DPOOL_SCRATCH
:
724 if(Lockable
== FALSE
)
725 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
726 which are mutually exclusive, setting lockable to true\n");
729 case WINED3DPOOL_SYSTEMMEM
:
730 if(Lockable
== FALSE
) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
731 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
732 case WINED3DPOOL_MANAGED
:
733 if(Usage
== WINED3DUSAGE_DYNAMIC
) FIXME("Create surface called with a pool of MANAGED and a \
734 Usage of DYNAMIC which are mutually exclusive, not doing \
735 anything just telling you.\n");
737 case WINED3DPOOL_DEFAULT
: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
738 if(!(Usage
& WINED3DUSAGE_DYNAMIC
) && !(Usage
& WINED3DUSAGE_RENDERTARGET
)
739 && !(Usage
&& WINED3DUSAGE_DEPTHSTENCIL
) && Lockable
)
740 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
743 FIXME("(%p) Unknown pool %d\n", This
, Pool
);
747 if (Usage
& WINED3DUSAGE_RENDERTARGET
&& Pool
!= WINED3DPOOL_DEFAULT
) {
748 FIXME("Trying to create a render target that isn't in the default pool\n");
751 /* mark the texture as dirty so that it get's loaded first time around*/
752 IWineD3DSurface_AddDirtyRect(*ppSurface
, NULL
);
753 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
754 This
, Width
, Height
, Format
, debug_d3dformat(Format
),
755 (WINED3DFMT_D16_LOCKABLE
== Format
), *ppSurface
, object
->resource
.allocatedMemory
, object
->resource
.size
);
757 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
758 if( (Usage
& WINED3DUSAGE_RENDERTARGET
) && (!This
->ddraw_primary
) )
759 This
->ddraw_primary
= (IWineD3DSurface
*) object
;
761 /* Look at the implementation and set the correct Vtable */
764 /* Nothing to do, it's set already */
768 object
->lpVtbl
= &IWineGDISurface_Vtbl
;
772 /* To be sure to catch this */
773 ERR("Unknown requested surface implementation %d!\n", Impl
);
774 IWineD3DSurface_Release((IWineD3DSurface
*) object
);
775 return WINED3DERR_INVALIDCALL
;
778 /* Call the private setup routine */
779 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface
*) object
);
783 HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, UINT Levels
,
784 DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
785 IWineD3DTexture
** ppTexture
, HANDLE
* pSharedHandle
, IUnknown
*parent
,
786 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
788 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
789 IWineD3DTextureImpl
*object
;
794 unsigned int pow2Width
= Width
;
795 unsigned int pow2Height
= Height
;
798 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) ....\n", This
, Width
, Height
, Levels
, Usage
);
800 /* TODO: It should only be possible to create textures for formats
801 that are reported as supported */
802 if (WINED3DFMT_UNKNOWN
>= Format
) {
803 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
804 return WINED3DERR_INVALIDCALL
;
807 D3DCREATERESOURCEOBJECTINSTANCE(object
, Texture
, WINED3DRTYPE_TEXTURE
, 0);
808 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
809 object
->width
= Width
;
810 object
->height
= Height
;
812 /** Non-power2 support **/
813 /* Find the nearest pow2 match */
814 pow2Width
= pow2Height
= 1;
815 while (pow2Width
< Width
) pow2Width
<<= 1;
816 while (pow2Height
< Height
) pow2Height
<<= 1;
818 /** FIXME: add support for real non-power-two if it's provided by the video card **/
819 /* Precalculated scaling for 'faked' non power of two texture coords */
820 object
->pow2scalingFactorX
= (((float)Width
) / ((float)pow2Width
));
821 object
->pow2scalingFactorY
= (((float)Height
) / ((float)pow2Height
));
822 TRACE(" xf(%f) yf(%f)\n", object
->pow2scalingFactorX
, object
->pow2scalingFactorY
);
824 /* Calculate levels for mip mapping */
826 TRACE("calculating levels %d\n", object
->baseTexture
.levels
);
827 object
->baseTexture
.levels
++;
830 while (tmpW
> 1 || tmpH
> 1) {
831 tmpW
= max(1, tmpW
>> 1);
832 tmpH
= max(1, tmpH
>> 1);
833 object
->baseTexture
.levels
++;
835 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
838 /* Generate all the surfaces */
841 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
843 /* use the callback to create the texture surface */
844 hr
= D3DCB_CreateSurface(This
->parent
, tmpW
, tmpH
, Format
, Usage
, Pool
, i
, &object
->surfaces
[i
],NULL
);
845 if (hr
!= WINED3D_OK
|| ( (IWineD3DSurfaceImpl
*) object
->surfaces
[i
])->Flags
& SFLAG_OVERSIZE
) {
847 FIXME("Failed to create surface %p\n", object
);
849 for (j
= 0 ; j
<= i
; j
++) {
850 if(object
->surfaces
[j
]) IWineD3DSurface_Release(object
->surfaces
[j
]);
852 /* heap free object */
853 HeapFree(GetProcessHeap(), 0, object
);
859 IWineD3DSurface_SetContainer(object
->surfaces
[i
], (IWineD3DBase
*)object
);
860 TRACE("Created surface level %d @ %p\n", i
, object
->surfaces
[i
]);
861 /* calculate the next mipmap level */
862 tmpW
= max(1, tmpW
>> 1);
863 tmpH
= max(1, tmpH
>> 1);
866 TRACE("(%p) : Created texture %p\n", This
, object
);
870 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
871 UINT Width
, UINT Height
, UINT Depth
,
872 UINT Levels
, DWORD Usage
,
873 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
874 IWineD3DVolumeTexture
**ppVolumeTexture
,
875 HANDLE
*pSharedHandle
, IUnknown
*parent
,
876 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume
) {
878 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
879 IWineD3DVolumeTextureImpl
*object
;
885 /* TODO: It should only be possible to create textures for formats
886 that are reported as supported */
887 if (WINED3DFMT_UNKNOWN
>= Format
) {
888 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
889 return WINED3DERR_INVALIDCALL
;
892 D3DCREATERESOURCEOBJECTINSTANCE(object
, VolumeTexture
, WINED3DRTYPE_VOLUMETEXTURE
, 0);
893 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
895 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
896 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
898 object
->width
= Width
;
899 object
->height
= Height
;
900 object
->depth
= Depth
;
902 /* Calculate levels for mip mapping */
904 object
->baseTexture
.levels
++;
908 while (tmpW
> 1 || tmpH
> 1 || tmpD
> 1) {
909 tmpW
= max(1, tmpW
>> 1);
910 tmpH
= max(1, tmpH
>> 1);
911 tmpD
= max(1, tmpD
>> 1);
912 object
->baseTexture
.levels
++;
914 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
917 /* Generate all the surfaces */
922 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
924 /* Create the volume */
925 D3DCB_CreateVolume(This
->parent
, Width
, Height
, Depth
, Format
, Pool
, Usage
,
926 (IWineD3DVolume
**)&object
->volumes
[i
], pSharedHandle
);
928 /* Set it's container to this object */
929 IWineD3DVolume_SetContainer(object
->volumes
[i
], (IWineD3DBase
*)object
);
931 /* calcualte the next mipmap level */
932 tmpW
= max(1, tmpW
>> 1);
933 tmpH
= max(1, tmpH
>> 1);
934 tmpD
= max(1, tmpD
>> 1);
937 *ppVolumeTexture
= (IWineD3DVolumeTexture
*) object
;
938 TRACE("(%p) : Created volume texture %p\n", This
, object
);
942 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
,
943 UINT Width
, UINT Height
, UINT Depth
,
945 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
946 IWineD3DVolume
** ppVolume
,
947 HANDLE
* pSharedHandle
, IUnknown
*parent
) {
949 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
950 IWineD3DVolumeImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
952 D3DCREATERESOURCEOBJECTINSTANCE(object
, Volume
, WINED3DRTYPE_VOLUME
, ((Width
* D3DFmtGetBpp(This
, Format
)) * Height
* Depth
))
954 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
955 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
957 object
->currentDesc
.Width
= Width
;
958 object
->currentDesc
.Height
= Height
;
959 object
->currentDesc
.Depth
= Depth
;
960 object
->bytesPerPixel
= D3DFmtGetBpp(This
, Format
);
962 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
963 object
->lockable
= TRUE
;
964 object
->locked
= FALSE
;
965 memset(&object
->lockedBox
, 0, sizeof(WINED3DBOX
));
966 object
->dirty
= TRUE
;
968 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume
*) object
, NULL
);
971 HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
,
972 UINT Levels
, DWORD Usage
,
973 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
974 IWineD3DCubeTexture
**ppCubeTexture
,
975 HANDLE
*pSharedHandle
, IUnknown
*parent
,
976 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
978 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
979 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
983 unsigned int pow2EdgeLength
= EdgeLength
;
985 /* TODO: It should only be possible to create textures for formats
986 that are reported as supported */
987 if (WINED3DFMT_UNKNOWN
>= Format
) {
988 WARN("(%p) : Texture cannot be created with a format of D3DFMT_UNKNOWN\n", This
);
989 return WINED3DERR_INVALIDCALL
;
992 D3DCREATERESOURCEOBJECTINSTANCE(object
, CubeTexture
, WINED3DRTYPE_CUBETEXTURE
, 0);
993 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
995 TRACE("(%p) Create Cube Texture\n", This
);
997 /** Non-power2 support **/
999 /* Find the nearest pow2 match */
1001 while (pow2EdgeLength
< EdgeLength
) pow2EdgeLength
<<= 1;
1003 object
->edgeLength
= EdgeLength
;
1004 /* TODO: support for native non-power 2 */
1005 /* Precalculated scaling for 'faked' non power of two texture coords */
1006 object
->pow2scalingFactor
= ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1008 /* Calculate levels for mip mapping */
1010 object
->baseTexture
.levels
++;
1013 tmpW
= max(1, tmpW
>> 1);
1014 object
->baseTexture
.levels
++;
1016 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
1019 /* Generate all the surfaces */
1021 for (i
= 0; i
< object
->baseTexture
.levels
; i
++) {
1023 /* Create the 6 faces */
1024 for (j
= 0; j
< 6; j
++) {
1026 hr
=D3DCB_CreateSurface(This
->parent
, tmpW
, tmpW
, Format
, Usage
, Pool
,
1027 i
/* Level */, &object
->surfaces
[j
][i
],pSharedHandle
);
1029 if(hr
!= WINED3D_OK
) {
1033 for (l
= 0; l
< j
; l
++) {
1034 IWineD3DSurface_Release(object
->surfaces
[j
][i
]);
1036 for (k
= 0; k
< i
; k
++) {
1037 for (l
= 0; l
< 6; l
++) {
1038 IWineD3DSurface_Release(object
->surfaces
[l
][j
]);
1042 FIXME("(%p) Failed to create surface\n",object
);
1043 HeapFree(GetProcessHeap(),0,object
);
1044 *ppCubeTexture
= NULL
;
1047 IWineD3DSurface_SetContainer(object
->surfaces
[j
][i
], (IWineD3DBase
*)object
);
1048 TRACE("Created surface level %d @ %p,\n", i
, object
->surfaces
[j
][i
]);
1050 tmpW
= max(1, tmpW
>> 1);
1053 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1054 *ppCubeTexture
= (IWineD3DCubeTexture
*) object
;
1058 HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
, WINED3DQUERYTYPE Type
, IWineD3DQuery
**ppQuery
, IUnknown
* parent
) {
1059 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1060 IWineD3DQueryImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
1062 if (NULL
== ppQuery
) {
1063 /* Just a check to see if we support this type of query */
1064 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1066 case WINED3DQUERYTYPE_OCCLUSION
:
1067 TRACE("(%p) occlusion query\n", This
);
1068 if (GL_SUPPORT(ARB_OCCLUSION_QUERY
) || GL_SUPPORT(NV_OCCLUSION_QUERY
))
1071 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1073 case WINED3DQUERYTYPE_VCACHE
:
1074 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1075 case WINED3DQUERYTYPE_VERTEXSTATS
:
1076 case WINED3DQUERYTYPE_EVENT
:
1077 case WINED3DQUERYTYPE_TIMESTAMP
:
1078 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1079 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1080 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1081 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1082 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1083 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1084 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1085 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1087 FIXME("(%p) Unhandled query type %d\n", This
, Type
);
1092 D3DCREATEOBJECTINSTANCE(object
, Query
)
1093 object
->type
= Type
;
1094 /* allocated the 'extended' data based on the type of query requested */
1096 case D3DQUERYTYPE_OCCLUSION
:
1097 if(GL_SUPPORT(ARB_OCCLUSION_QUERY
) || GL_SUPPORT(NV_OCCLUSION_QUERY
)) {
1098 TRACE("(%p) Allocating data for an occlusion query\n", This
);
1099 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryOcclusionData
));
1102 case D3DQUERYTYPE_VCACHE
:
1103 case D3DQUERYTYPE_RESOURCEMANAGER
:
1104 case D3DQUERYTYPE_VERTEXSTATS
:
1105 case D3DQUERYTYPE_EVENT
:
1106 case D3DQUERYTYPE_TIMESTAMP
:
1107 case D3DQUERYTYPE_TIMESTAMPDISJOINT
:
1108 case D3DQUERYTYPE_TIMESTAMPFREQ
:
1109 case D3DQUERYTYPE_PIPELINETIMINGS
:
1110 case D3DQUERYTYPE_INTERFACETIMINGS
:
1111 case D3DQUERYTYPE_VERTEXTIMINGS
:
1112 case D3DQUERYTYPE_PIXELTIMINGS
:
1113 case D3DQUERYTYPE_BANDWIDTHTIMINGS
:
1114 case D3DQUERYTYPE_CACHEUTILIZATION
:
1116 object
->extendedData
= 0;
1117 FIXME("(%p) Unhandled query type %d\n",This
, Type
);
1119 TRACE("(%p) : Created Query %p\n", This
, object
);
1123 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1124 HRESULT WINAPI
IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, IWineD3DSwapChain
** ppSwapChain
,
1126 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget
,
1127 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil
) {
1128 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1131 IWineD3DSwapChainImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1133 XVisualInfo
template;
1134 GLXContext oldContext
;
1135 Drawable oldDrawable
;
1136 HRESULT hr
= WINED3D_OK
;
1138 TRACE("(%p) : Created Aditional Swap Chain\n", This
);
1140 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1141 * does a device hold a reference to a swap chain giving them a lifetime of the device
1142 * or does the swap chain notify the device of its destruction.
1143 *******************************/
1145 /* Check the params */
1146 if(*pPresentationParameters
->BackBufferCount
> 1) {
1147 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters
->BackBufferCount
);
1148 return WINED3DERR_INVALIDCALL
;
1151 D3DCREATEOBJECTINSTANCE(object
, SwapChain
)
1153 /*********************
1154 * Lookup the window Handle and the relating X window handle
1155 ********************/
1157 /* Setup hwnd we are using, plus which display this equates to */
1158 object
->win_handle
= *(pPresentationParameters
->hDeviceWindow
);
1159 if (!object
->win_handle
) {
1160 object
->win_handle
= This
->createParms
.hFocusWindow
;
1163 object
->win_handle
= GetAncestor(object
->win_handle
, GA_ROOT
);
1164 if ( !( object
->win
= (Window
)GetPropA(object
->win_handle
, "__wine_x11_whole_window") ) ) {
1165 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object
->win_handle
);
1166 return WINED3DERR_NOTAVAILABLE
;
1168 hDc
= GetDC(object
->win_handle
);
1169 object
->display
= get_display(hDc
);
1170 ReleaseDC(object
->win_handle
, hDc
);
1171 TRACE("Using a display of %p %p\n", object
->display
, hDc
);
1173 if (NULL
== object
->display
|| NULL
== hDc
) {
1174 WARN("Failed to get a display and HDc for Window %p\n", object
->win_handle
);
1175 return WINED3DERR_NOTAVAILABLE
;
1178 if (object
->win
== 0) {
1179 WARN("Failed to get a valid XVisuial ID for the window %p\n", object
->win_handle
);
1180 return WINED3DERR_NOTAVAILABLE
;
1183 * Create an opengl context for the display visual
1184 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1185 * use different properties after that point in time. FIXME: How to handle when requested format
1186 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1187 * it chooses is identical to the one already being used!
1188 **********************************/
1190 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1193 /* Create a new context for this swapchain */
1194 template.visualid
= (VisualID
)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1195 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1196 (or the best possible if none is requested) */
1197 TRACE("Found x visual ID : %ld\n", template.visualid
);
1199 object
->visInfo
= XGetVisualInfo(object
->display
, VisualIDMask
, &template, &num
);
1200 if (NULL
== object
->visInfo
) {
1201 ERR("cannot really get XVisual\n");
1203 return WINED3DERR_NOTAVAILABLE
;
1206 /* Write out some debug info about the visual/s */
1207 TRACE("Using x visual ID : %ld\n", template.visualid
);
1208 TRACE(" visual info: %p\n", object
->visInfo
);
1209 TRACE(" num items : %d\n", num
);
1210 for (n
= 0;n
< num
; n
++) {
1211 TRACE("=====item=====: %d\n", n
+ 1);
1212 TRACE(" visualid : %ld\n", object
->visInfo
[n
].visualid
);
1213 TRACE(" screen : %d\n", object
->visInfo
[n
].screen
);
1214 TRACE(" depth : %u\n", object
->visInfo
[n
].depth
);
1215 TRACE(" class : %d\n", object
->visInfo
[n
].class);
1216 TRACE(" red_mask : %ld\n", object
->visInfo
[n
].red_mask
);
1217 TRACE(" green_mask : %ld\n", object
->visInfo
[n
].green_mask
);
1218 TRACE(" blue_mask : %ld\n", object
->visInfo
[n
].blue_mask
);
1219 TRACE(" colormap_size : %d\n", object
->visInfo
[n
].colormap_size
);
1220 TRACE(" bits_per_rgb : %d\n", object
->visInfo
[n
].bits_per_rgb
);
1221 /* log some extra glx info */
1222 glXGetConfig(object
->display
, object
->visInfo
, GLX_AUX_BUFFERS
, &value
);
1223 TRACE(" gl_aux_buffers : %d\n", value
);
1224 glXGetConfig(object
->display
, object
->visInfo
, GLX_BUFFER_SIZE
,&value
);
1225 TRACE(" gl_buffer_size : %d\n", value
);
1226 glXGetConfig(object
->display
, object
->visInfo
, GLX_RED_SIZE
, &value
);
1227 TRACE(" gl_red_size : %d\n", value
);
1228 glXGetConfig(object
->display
, object
->visInfo
, GLX_GREEN_SIZE
, &value
);
1229 TRACE(" gl_green_size : %d\n", value
);
1230 glXGetConfig(object
->display
, object
->visInfo
, GLX_BLUE_SIZE
, &value
);
1231 TRACE(" gl_blue_size : %d\n", value
);
1232 glXGetConfig(object
->display
, object
->visInfo
, GLX_ALPHA_SIZE
, &value
);
1233 TRACE(" gl_alpha_size : %d\n", value
);
1234 glXGetConfig(object
->display
, object
->visInfo
, GLX_DEPTH_SIZE
,&value
);
1235 TRACE(" gl_depth_size : %d\n", value
);
1236 glXGetConfig(object
->display
, object
->visInfo
, GLX_STENCIL_SIZE
, &value
);
1237 TRACE(" gl_stencil_size : %d\n", value
);
1239 /* Now choose a simila visual ID*/
1241 #ifdef USE_CONTEXT_MANAGER
1243 /** TODO: use a context mamager **/
1247 IWineD3DSwapChain
*implSwapChain
;
1248 if (WINED3D_OK
!= IWineD3DDevice_GetSwapChain(iface
, 0, &implSwapChain
)) {
1249 /* The first time around we create the context that is shared with all other swapchains and render targets */
1250 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, NULL
, GL_TRUE
);
1251 TRACE("Creating implicit context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1254 TRACE("Creating context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1255 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1256 /* and create a new context with the implicit swapchains context as the shared context */
1257 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, ((IWineD3DSwapChainImpl
*)implSwapChain
)->glCtx
, GL_TRUE
);
1258 IWineD3DSwapChain_Release(implSwapChain
);
1263 XFree(object
->visInfo
);
1264 object
->visInfo
= NULL
;
1266 if (NULL
== object
->glCtx
) {
1267 ERR("cannot create glxContext\n");
1269 return WINED3DERR_NOTAVAILABLE
;
1273 if (object
->glCtx
== NULL
) {
1274 ERR("Error in context creation !\n");
1275 return WINED3DERR_INVALIDCALL
;
1277 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1278 object
->win_handle
, object
->glCtx
, object
->win
, object
->visInfo
);
1281 /*********************
1282 * Windowed / Fullscreen
1283 *******************/
1286 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1287 * so we should really check to see if there is a fullscreen swapchain already
1288 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1289 **************************************/
1291 if (!*(pPresentationParameters
->Windowed
)) {
1297 /* Get info on the current display setup */
1298 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1299 bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
1302 /* Change the display settings */
1303 memset(&devmode
, 0, sizeof(DEVMODEW
));
1304 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1305 devmode
.dmBitsPerPel
= (bpp
>= 24) ? 32 : bpp
; /* Stupid XVidMode cannot change bpp */
1306 devmode
.dmPelsWidth
= *(pPresentationParameters
->BackBufferWidth
);
1307 devmode
.dmPelsHeight
= *(pPresentationParameters
->BackBufferHeight
);
1308 MultiByteToWideChar(CP_ACP
, 0, "Gamers CG", -1, devmode
.dmDeviceName
, CCHDEVICENAME
);
1309 ChangeDisplaySettingsExW(devmode
.dmDeviceName
, &devmode
, object
->win_handle
, CDS_FULLSCREEN
, NULL
);
1311 /* Make popup window */
1312 SetWindowLongA(object
->win_handle
, GWL_STYLE
, WS_POPUP
);
1313 SetWindowPos(object
->win_handle
, HWND_TOP
, 0, 0,
1314 *(pPresentationParameters
->BackBufferWidth
),
1315 *(pPresentationParameters
->BackBufferHeight
), SWP_SHOWWINDOW
| SWP_FRAMECHANGED
);
1317 /* For GetDisplayMode */
1318 This
->ddraw_width
= devmode
.dmPelsWidth
;
1319 This
->ddraw_height
= devmode
.dmPelsHeight
;
1320 This
->ddraw_format
= *(pPresentationParameters
->BackBufferFormat
);
1324 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1325 * then the corresponding dimension of the client area of the hDeviceWindow
1326 * (or the focus window, if hDeviceWindow is NULL) is taken.
1327 **********************/
1329 if (*(pPresentationParameters
->Windowed
) &&
1330 ((*(pPresentationParameters
->BackBufferWidth
) == 0) ||
1331 (*(pPresentationParameters
->BackBufferHeight
) == 0))) {
1334 GetClientRect(object
->win_handle
, &Rect
);
1336 if (*(pPresentationParameters
->BackBufferWidth
) == 0) {
1337 *(pPresentationParameters
->BackBufferWidth
) = Rect
.right
;
1338 TRACE("Updating width to %d\n", *(pPresentationParameters
->BackBufferWidth
));
1340 if (*(pPresentationParameters
->BackBufferHeight
) == 0) {
1341 *(pPresentationParameters
->BackBufferHeight
) = Rect
.bottom
;
1342 TRACE("Updating height to %d\n", *(pPresentationParameters
->BackBufferHeight
));
1346 /*********************
1347 * finish off parameter initialization
1348 *******************/
1350 /* Put the correct figures in the presentation parameters */
1351 TRACE("Coppying accross presentaion paraneters\n");
1352 object
->presentParms
.BackBufferWidth
= *(pPresentationParameters
->BackBufferWidth
);
1353 object
->presentParms
.BackBufferHeight
= *(pPresentationParameters
->BackBufferHeight
);
1354 object
->presentParms
.BackBufferFormat
= *(pPresentationParameters
->BackBufferFormat
);
1355 object
->presentParms
.BackBufferCount
= *(pPresentationParameters
->BackBufferCount
);
1356 object
->presentParms
.MultiSampleType
= *(pPresentationParameters
->MultiSampleType
);
1357 object
->presentParms
.MultiSampleQuality
= NULL
== pPresentationParameters
->MultiSampleQuality
? 0 : *(pPresentationParameters
->MultiSampleQuality
);
1358 object
->presentParms
.SwapEffect
= *(pPresentationParameters
->SwapEffect
);
1359 object
->presentParms
.hDeviceWindow
= *(pPresentationParameters
->hDeviceWindow
);
1360 object
->presentParms
.Windowed
= *(pPresentationParameters
->Windowed
);
1361 object
->presentParms
.EnableAutoDepthStencil
= *(pPresentationParameters
->EnableAutoDepthStencil
);
1362 object
->presentParms
.AutoDepthStencilFormat
= *(pPresentationParameters
->AutoDepthStencilFormat
);
1363 object
->presentParms
.Flags
= *(pPresentationParameters
->Flags
);
1364 object
->presentParms
.FullScreen_RefreshRateInHz
= *(pPresentationParameters
->FullScreen_RefreshRateInHz
);
1365 object
->presentParms
.PresentationInterval
= *(pPresentationParameters
->PresentationInterval
);
1368 /*********************
1369 * Create the back, front and stencil buffers
1370 *******************/
1372 TRACE("calling rendertarget CB\n");
1373 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1374 object
->presentParms
.BackBufferWidth
,
1375 object
->presentParms
.BackBufferHeight
,
1376 object
->presentParms
.BackBufferFormat
,
1377 object
->presentParms
.MultiSampleType
,
1378 object
->presentParms
.MultiSampleQuality
,
1379 TRUE
/* Lockable */,
1380 &object
->frontBuffer
,
1381 NULL
/* pShared (always null)*/);
1382 if (object
->frontBuffer
!= NULL
)
1383 IWineD3DSurface_SetContainer(object
->frontBuffer
, (IWineD3DBase
*)object
);
1384 if(object
->presentParms
.BackBufferCount
> 0) {
1385 TRACE("calling rendertarget CB\n");
1386 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1387 object
->presentParms
.BackBufferWidth
,
1388 object
->presentParms
.BackBufferHeight
,
1389 object
->presentParms
.BackBufferFormat
,
1390 object
->presentParms
.MultiSampleType
,
1391 object
->presentParms
.MultiSampleQuality
,
1392 TRUE
/* Lockable */,
1393 &object
->backBuffer
,
1394 NULL
/* pShared (always null)*/);
1396 object
->backBuffer
= NULL
;
1399 if (object
->backBuffer
!= NULL
) {
1400 IWineD3DSurface_SetContainer(object
->backBuffer
, (IWineD3DBase
*)object
);
1402 glDrawBuffer(GL_BACK
);
1403 checkGLcall("glDrawBuffer(GL_BACK)");
1406 /* Single buffering - draw to front buffer */
1408 glDrawBuffer(GL_FRONT
);
1409 checkGLcall("glDrawBuffer(GL_FRONT)");
1413 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1414 if (pPresentationParameters
->EnableAutoDepthStencil
) {
1415 TRACE("Creating depth stencil buffer\n");
1416 if (This
->depthStencilBuffer
== NULL
) {
1417 hr
= D3DCB_CreateDepthStencil((IUnknown
*) This
->parent
,
1418 object
->presentParms
.BackBufferWidth
,
1419 object
->presentParms
.BackBufferHeight
,
1420 object
->presentParms
.AutoDepthStencilFormat
,
1421 object
->presentParms
.MultiSampleType
,
1422 object
->presentParms
.MultiSampleQuality
,
1423 FALSE
/* FIXME: Discard */,
1424 &This
->depthStencilBuffer
,
1425 NULL
/* pShared (always null)*/ );
1426 if (This
->depthStencilBuffer
!= NULL
)
1427 IWineD3DSurface_SetContainer(This
->depthStencilBuffer
, 0);
1430 /** TODO: A check on width, height and multisample types
1431 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1432 ****************************/
1433 object
->wantsDepthStencilBuffer
= TRUE
;
1435 object
->wantsDepthStencilBuffer
= FALSE
;
1438 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object
->frontBuffer
, object
->backBuffer
, object
->wantsDepthStencilBuffer
);
1441 /*********************
1442 * init the default renderTarget management
1443 *******************/
1444 object
->drawable
= object
->win
;
1445 object
->render_ctx
= object
->glCtx
;
1447 if (hr
== WINED3D_OK
) {
1448 /*********************
1449 * Setup some defaults and clear down the buffers
1450 *******************/
1452 /** save current context and drawable **/
1453 oldContext
= glXGetCurrentContext();
1454 oldDrawable
= glXGetCurrentDrawable();
1456 TRACE("Activating context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1457 if (glXMakeCurrent(object
->display
, object
->win
, object
->glCtx
) == False
) {
1458 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1460 checkGLcall("glXMakeCurrent");
1462 TRACE("Setting up the screen\n");
1463 /* Clear the screen */
1464 glClearColor(1.0, 0.0, 0.0, 0.0);
1465 checkGLcall("glClearColor");
1468 glClearStencil(0xffff);
1470 checkGLcall("glClear");
1472 glColor3f(1.0, 1.0, 1.0);
1473 checkGLcall("glColor3f");
1475 glEnable(GL_LIGHTING
);
1476 checkGLcall("glEnable");
1478 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, GL_TRUE
);
1479 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1481 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1482 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1484 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL
, GL_SEPARATE_SPECULAR_COLOR
);
1485 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1487 /* switch back to the original context (if there was one)*/
1488 if (This
->swapchains
) {
1489 /** TODO: restore the context and drawable **/
1490 glXMakeCurrent(object
->display
, oldDrawable
, oldContext
);
1495 TRACE("Set swapchain to %p\n", object
);
1496 } else { /* something went wrong so clean up */
1497 IUnknown
* bufferParent
;
1498 if (object
->frontBuffer
) {
1500 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1501 IUnknown_Release(bufferParent
); /* once for the get parent */
1502 if (IUnknown_Release(bufferParent
) > 0) {
1503 FIXME("(%p) Something's still holding the front buffer\n",This
);
1506 if (object
->backBuffer
) {
1507 IWineD3DSurface_GetParent(object
->backBuffer
, &bufferParent
);
1508 IUnknown_Release(bufferParent
); /* once for the get parent */
1509 if (IUnknown_Release(bufferParent
) > 0) {
1510 FIXME("(%p) Something's still holding the back buffer\n",This
);
1513 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1514 /* Clean up the context */
1515 /* check that we are the current context first (we shouldn't be though!) */
1516 if (object
->glCtx
!= 0) {
1517 if(glXGetCurrentContext() == object
->glCtx
) {
1518 glXMakeCurrent(object
->display
, None
, NULL
);
1520 glXDestroyContext(object
->display
, object
->glCtx
);
1522 HeapFree(GetProcessHeap(), 0, object
);
1529 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1530 UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1531 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1532 TRACE("(%p)\n", This
);
1534 return This
->NumberOfSwapChains
;
1537 HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1538 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1539 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
1541 if(iSwapChain
< This
->NumberOfSwapChains
) {
1542 *pSwapChain
= This
->swapchains
[iSwapChain
];
1543 IWineD3DSwapChain_AddRef(*pSwapChain
);
1544 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1547 TRACE("Swapchain out of range\n");
1549 return WINED3DERR_INVALIDCALL
;
1554 * Vertex Declaration
1556 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
* iface
, CONST VOID
* pDeclaration
, IWineD3DVertexDeclaration
** ppVertexDeclaration
, IUnknown
*parent
) {
1557 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1558 IWineD3DVertexDeclarationImpl
*object
= NULL
;
1559 HRESULT hr
= WINED3D_OK
;
1560 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This
, ((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
, pDeclaration
, ppVertexDeclaration
);
1561 D3DCREATEOBJECTINSTANCE(object
, VertexDeclaration
)
1564 hr
= IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration
*)object
, (void *)pDeclaration
);
1569 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1570 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
, CONST DWORD
*pDeclaration
, CONST DWORD
*pFunction
, IWineD3DVertexShader
**ppVertexShader
, IUnknown
*parent
) {
1571 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1572 IWineD3DVertexShaderImpl
*object
; /* NOTE: impl usage is ok, this is a create */
1573 HRESULT hr
= WINED3D_OK
;
1574 D3DCREATEOBJECTINSTANCE(object
, VertexShader
)
1575 object
->baseShader
.shader_ins
= IWineD3DVertexShaderImpl_shader_ins
;
1577 TRACE("(%p) : Created Vertex shader %p\n", This
, *ppVertexShader
);
1579 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1580 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1581 if (pDeclaration
!= NULL
) {
1582 IWineD3DVertexDeclaration
*vertexDeclaration
;
1583 hr
= IWineD3DDevice_CreateVertexDeclaration(iface
, pDeclaration
, &vertexDeclaration
,NULL
);
1584 if (WINED3D_OK
== hr
) {
1585 TRACE("(%p) : Setting vertex declaration to %p\n", This
, vertexDeclaration
);
1586 object
->vertexDeclaration
= vertexDeclaration
;
1588 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface
);
1589 IWineD3DVertexShader_Release(*ppVertexShader
);
1590 return WINED3DERR_INVALIDCALL
;
1594 hr
= IWineD3DVertexShader_SetFunction(*ppVertexShader
, pFunction
);
1596 if (WINED3D_OK
!= hr
) {
1597 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface
);
1598 IWineD3DVertexShader_Release(*ppVertexShader
);
1599 return WINED3DERR_INVALIDCALL
;
1602 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1603 if(Usage
== WINED3DUSAGE_SOFTWAREVERTEXPROCESSING
) {
1614 HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
, CONST DWORD
*pFunction
, IWineD3DPixelShader
**ppPixelShader
, IUnknown
*parent
) {
1615 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1616 IWineD3DPixelShaderImpl
*object
; /* NOTE: impl allowed, this is a create */
1617 HRESULT hr
= WINED3D_OK
;
1619 D3DCREATEOBJECTINSTANCE(object
, PixelShader
)
1620 object
->baseShader
.shader_ins
= IWineD3DPixelShaderImpl_shader_ins
;
1621 hr
= IWineD3DPixelShader_SetFunction(*ppPixelShader
, pFunction
);
1622 if (WINED3D_OK
== hr
) {
1623 TRACE("(%p) : Created Pixel shader %p\n", This
, *ppPixelShader
);
1625 WARN("(%p) : Failed to create pixel shader\n", This
);
1631 HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD Flags
, PALETTEENTRY
*PalEnt
, IWineD3DPalette
**Palette
, IUnknown
*Parent
) {
1632 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1633 IWineD3DPaletteImpl
*object
;
1635 TRACE("(%p)->(%lx, %p, %p, %p)\n", This
, Flags
, PalEnt
, Palette
, Parent
);
1637 /* Create the new object */
1638 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DPaletteImpl
));
1640 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1641 return E_OUTOFMEMORY
;
1644 object
->lpVtbl
= &IWineD3DPalette_Vtbl
;
1646 object
->Flags
= Flags
;
1647 object
->parent
= Parent
;
1648 object
->wineD3DDevice
= This
;
1649 object
->palNumEntries
= IWineD3DPaletteImpl_Size(Flags
);
1651 object
->hpal
= CreatePalette((const LOGPALETTE
*)&(object
->palVersion
));
1654 HeapFree( GetProcessHeap(), 0, object
);
1655 return E_OUTOFMEMORY
;
1658 hr
= IWineD3DPalette_SetEntries((IWineD3DPalette
*) object
, 0, 0, IWineD3DPaletteImpl_Size(Flags
), PalEnt
);
1660 IWineD3DPalette_Release((IWineD3DPalette
*) object
);
1664 *Palette
= (IWineD3DPalette
*) object
;
1669 HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain
) {
1670 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1671 IWineD3DSwapChainImpl
*swapchain
;
1673 TRACE("(%p)->(%p,%p)\n", This
, pPresentationParameters
, D3DCB_CreateAdditionalSwapChain
);
1674 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1676 /* TODO: Test if OpenGL is compiled in and loaded */
1678 /* Setup the implicit swapchain */
1679 TRACE("Creating implicit swapchain\n");
1680 if (D3D_OK
!= D3DCB_CreateAdditionalSwapChain((IUnknown
*) This
->parent
, pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
) || swapchain
== NULL
) {
1681 WARN("Failed to create implicit swapchain\n");
1682 return WINED3DERR_INVALIDCALL
;
1685 This
->NumberOfSwapChains
= 1;
1686 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
1687 if(!This
->swapchains
) {
1688 ERR("Out of memory!\n");
1689 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
1690 return E_OUTOFMEMORY
;
1692 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
1694 if(swapchain
->backBuffer
) {
1695 TRACE("Setting rendertarget to %p\n", swapchain
->backBuffer
);
1696 This
->renderTarget
= swapchain
->backBuffer
;
1699 TRACE("Setting rendertarget to %p\n", swapchain
->frontBuffer
);
1700 This
->renderTarget
= swapchain
->frontBuffer
;
1702 IWineD3DSurface_AddRef(This
->renderTarget
);
1703 /* Depth Stencil support */
1704 This
->stencilBufferTarget
= This
->depthStencilBuffer
;
1705 if (NULL
!= This
->stencilBufferTarget
) {
1706 IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
1709 /* Set up some starting GL setup */
1712 * Initialize openGL extension related variables
1713 * with Default values
1716 ((IWineD3DImpl
*) This
->wineD3D
)->isGLInfoValid
= IWineD3DImpl_FillGLCaps( &((IWineD3DImpl
*) This
->wineD3D
)->gl_info
, swapchain
->display
);
1717 /* Setup all the devices defaults */
1718 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)This
->stateBlock
);
1720 IWineD3DImpl_CheckGraphicsMemory();
1724 { /* Set a default viewport */
1728 vp
.Width
= *(pPresentationParameters
->BackBufferWidth
);
1729 vp
.Height
= *(pPresentationParameters
->BackBufferHeight
);
1732 IWineD3DDevice_SetViewport((IWineD3DDevice
*)This
, &vp
);
1735 /* Initialize the current view state */
1736 This
->modelview_valid
= 1;
1737 This
->proj_valid
= 0;
1738 This
->view_ident
= 1;
1739 This
->last_was_rhw
= 0;
1740 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
1741 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
1743 /* Clear the screen */
1744 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
, D3DCLEAR_STENCIL
|D3DCLEAR_ZBUFFER
|D3DCLEAR_TARGET
, 0x00, 1.0, 0);
1746 This
->d3d_initialized
= TRUE
;
1750 HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
) {
1751 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1753 IUnknown
* stencilBufferParent
;
1754 IUnknown
* swapChainParent
;
1756 TRACE("(%p)\n", This
);
1758 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1760 for(texstage
= 0; texstage
< GL_LIMITS(textures
); texstage
++) {
1761 IWineD3DDevice_SetTexture(iface
, texstage
, NULL
);
1764 /* Release the buffers (with sanity checks)*/
1765 TRACE("Releasing the depth stencil buffer at %p\n", This
->stencilBufferTarget
);
1766 if(This
->stencilBufferTarget
!= NULL
&& (IWineD3DSurface_Release(This
->stencilBufferTarget
) >0)){
1767 if(This
->depthStencilBuffer
!= This
->stencilBufferTarget
)
1768 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This
);
1770 This
->stencilBufferTarget
= NULL
;
1772 TRACE("Releasing the render target at %p\n", This
->renderTarget
);
1773 if(IWineD3DSurface_Release(This
->renderTarget
) >0){
1774 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1776 TRACE("Setting rendertarget to NULL\n");
1777 This
->renderTarget
= NULL
;
1779 IWineD3DSurface_GetParent(This
->depthStencilBuffer
, &stencilBufferParent
);
1780 IUnknown_Release(stencilBufferParent
); /* once for the get parent */
1781 if(IUnknown_Release(stencilBufferParent
) >0){ /* the second time for when it was created */
1782 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This
);
1784 This
->depthStencilBuffer
= NULL
;
1786 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
1787 TRACE("Releasing the implicit swapchain %d\n", i
);
1788 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
1789 IWineD3DSwapChain_GetParent(This
->swapchains
[i
], &swapChainParent
);
1790 IUnknown_Release(swapChainParent
); /* once for the get parent */
1791 if (IUnknown_Release(swapChainParent
) > 0) { /* the second time for when it was created */
1792 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
1796 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
1797 This
->swapchains
= NULL
;
1798 This
->NumberOfSwapChains
= 0;
1800 This
->d3d_initialized
= FALSE
;
1804 HRESULT WINAPI
IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice
*iface
, DWORD Flags
, UINT Width
, UINT Height
, WINED3DFORMAT pixelformat
, LPVOID context
, D3DCB_ENUMDISPLAYMODESCALLBACK callback
) {
1805 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1810 TRACE("(%p)->(%lx,%d,%d,%d,%p,%p)\n", This
, Flags
, Width
, Height
, pixelformat
, context
, callback
);
1812 for (i
= 0; EnumDisplaySettingsExW(NULL
, i
, &DevModeW
, 0); i
++) {
1813 /* Ignore some modes if a description was passed */
1814 if ( (Width
> 0) && (Width
!= DevModeW
.dmPelsWidth
)) continue;
1815 if ( (Height
> 0) && (Height
!= DevModeW
.dmPelsHeight
)) continue;
1816 if ( (pixelformat
!= WINED3DFMT_UNKNOWN
) && ( D3DFmtGetBpp(NULL
, pixelformat
) != DevModeW
.dmBitsPerPel
) ) continue;
1818 TRACE("Enumerating %ldx%ld@%s\n", DevModeW
.dmPelsWidth
, DevModeW
.dmPelsHeight
, debug_d3dformat(pixelformat_for_depth(DevModeW
.dmBitsPerPel
)));
1820 if (callback((IUnknown
*) This
, (UINT
) DevModeW
.dmPelsWidth
, (UINT
) DevModeW
.dmPelsHeight
, pixelformat_for_depth(DevModeW
.dmBitsPerPel
), 60.0, context
) == DDENUMRET_CANCEL
)
1827 HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
1829 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1832 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1834 /* Resize the screen even without a window:
1835 * The app could have unset it with SetCooperativeLevel, but not called
1836 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1837 * but we don't have any hwnd
1840 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1841 devmode
.dmBitsPerPel
= D3DFmtGetBpp(This
, pMode
->Format
) * 8;
1842 if(devmode
.dmBitsPerPel
== 24) devmode
.dmBitsPerPel
= 32;
1843 devmode
.dmPelsWidth
= pMode
->Width
;
1844 devmode
.dmPelsHeight
= pMode
->Height
;
1846 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
1847 if (pMode
->RefreshRate
!= 0) {
1848 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
1851 /* Only change the mode if necessary */
1852 if( (This
->ddraw_width
== pMode
->Width
) &&
1853 (This
->ddraw_height
== pMode
->Height
) &&
1854 (This
->ddraw_format
== pMode
->Format
) &&
1855 (pMode
->RefreshRate
== 0) ) {
1859 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
1860 if (ret
!= DISP_CHANGE_SUCCESSFUL
) {
1861 if(devmode
.dmDisplayFrequency
!= 0) {
1862 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1863 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
1864 devmode
.dmDisplayFrequency
= 0;
1865 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
1867 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
1868 return DDERR_INVALIDMODE
;
1872 /* Store the new values */
1873 This
->ddraw_width
= pMode
->Width
;
1874 This
->ddraw_height
= pMode
->Height
;
1875 This
->ddraw_format
= pMode
->Format
;
1877 /* Only do this with a window of course */
1878 if(This
->ddraw_window
)
1879 MoveWindow(This
->ddraw_window
, 0, 0, pMode
->Width
, pMode
->Height
, TRUE
);
1884 HRESULT WINAPI
IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice
*iface
, D3DCB_ENUMPIXELFORMATS Callback
, void *Context
) {
1885 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1888 WINED3DFORMAT FormatList
[] = {
1895 WINED3DFMT_UNKNOWN
/* Terminate the list */
1898 TRACE("(%p)->(%p,%p)\n", This
, Callback
, Context
);
1900 while(FormatList
[i
] != WINED3DFMT_UNKNOWN
) {
1901 TRACE("Enumerating %s\n", debug_d3dformat(FormatList
[i
]));
1902 ret
= Callback((IUnknown
*) This
, FormatList
[i
], Context
);
1903 if(ret
!= DDENUMRET_OK
) {
1904 TRACE("Enumeration cancelled by Application\n");
1910 TRACE("End of Enumeration\n");
1915 HRESULT WINAPI
IWineD3DDeviceImpl_EnumTextureFormats(IWineD3DDevice
*iface
, D3DCB_ENUMPIXELFORMATS Callback
, void *Context
) {
1916 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1921 * WINED3DFMT_A1R5G5B5 needs to be the first 16 bit format, as some dumb apps depend on this
1923 * Do not enumerate RGBA pixel formats: "some games choose the first 16 bit texture format
1924 * with alpha they find enumerated, others the last one. And both want to have the ARGB one."
1925 * But WineD3D doesn't support RGBA formats anyway...
1928 WINED3DFORMAT FormatList
[] = {
1930 WINED3DFMT_A8R8G8B8
,
1931 WINED3DFMT_X8R8G8B8
,
1935 WINED3DFMT_A1R5G5B5
,
1936 WINED3DFMT_A4R4G4B4
,
1938 WINED3DFMT_X1R5G5B5
,
1946 /* Terminate the list */
1950 TRACE("(%p)->(%p,%p)\n", This
, Callback
, Context
);
1952 while(FormatList
[i
] != WINED3DFMT_UNKNOWN
) {
1953 TRACE("Enumerating %s\n", debug_d3dformat(FormatList
[i
]));
1954 ret
= Callback((IUnknown
*) This
, FormatList
[i
], Context
);
1955 if(ret
!= DDENUMRET_OK
) {
1956 TRACE("Enumeration cancelled by Application\n");
1962 TRACE("End of Enumeration\n");
1967 HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, IWineD3D
**ppD3D
) {
1968 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1969 *ppD3D
= This
->wineD3D
;
1970 TRACE("(%p) : wineD3D returning %p\n", This
, *ppD3D
);
1971 IWineD3D_AddRef(*ppD3D
);
1975 UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
1976 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1977 * Into the video ram as possible and seeing how many fit
1978 * you can also get the correct initial value from via X and ATI's driver
1979 *******************/
1980 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1981 static BOOL showfixmes
= TRUE
;
1983 FIXME("(%p) : stub, emulating %dMB for now, returning %dMB\n", This
, (emulated_textureram
/(1024*1024)),
1984 ((emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
1987 TRACE("(%p) : emulating %dMB for now, returning %dMB\n", This
, (emulated_textureram
/(1024*1024)),
1988 ((emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
1989 /* videomemory is simulated videomemory + AGP memory left */
1990 return (emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
);
1998 HRESULT WINAPI
IWineD3DDeviceImpl_SetFVF(IWineD3DDevice
*iface
, DWORD fvf
) {
1999 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2000 HRESULT hr
= WINED3D_OK
;
2002 /* Update the current state block */
2003 This
->updateStateBlock
->fvf
= fvf
;
2004 This
->updateStateBlock
->changed
.fvf
= TRUE
;
2005 This
->updateStateBlock
->set
.fvf
= TRUE
;
2007 TRACE("(%p) : FVF Shader FVF set to %lx\n", This
, fvf
);
2010 /* clear down the vertex declaration
2011 NOTE: Axis and Allies doesn't work properly otherwise
2012 (may be a stateblock problem though!)
2014 hr
= IWineD3DDevice_SetVertexDeclaration(iface
, NULL
);
2021 HRESULT WINAPI
IWineD3DDeviceImpl_GetFVF(IWineD3DDevice
*iface
, DWORD
*pfvf
) {
2022 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2023 TRACE("(%p) : GetFVF returning %lx\n", This
, This
->stateBlock
->fvf
);
2024 *pfvf
= This
->stateBlock
->fvf
;
2029 * Get / Set Stream Source
2031 HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
* pStreamData
, UINT OffsetInBytes
, UINT Stride
) {
2032 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2033 IWineD3DVertexBuffer
*oldSrc
;
2035 /**TODO: instance and index data, see
2036 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2038 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2041 /* D3d9 only, but shouldn't hurt d3d8 */
2044 streamFlags
= StreamNumber
&(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2046 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2047 FIXME("stream index data not supported\n");
2049 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2050 FIXME("stream instance data not supported\n");
2054 StreamNumber
&= ~(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2056 if (StreamNumber
>= MAX_STREAMS
) {
2057 WARN("Stream out of range %d\n", StreamNumber
);
2058 return WINED3DERR_INVALIDCALL
;
2061 oldSrc
= This
->stateBlock
->streamSource
[StreamNumber
];
2062 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This
, StreamNumber
, oldSrc
, pStreamData
, Stride
);
2064 This
->updateStateBlock
->changed
.streamSource
[StreamNumber
] = TRUE
;
2065 This
->updateStateBlock
->set
.streamSource
[StreamNumber
] = TRUE
;
2066 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
2067 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
2068 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
2069 This
->updateStateBlock
->streamFlags
[StreamNumber
] = streamFlags
;
2071 /* Handle recording of state blocks */
2072 if (This
->isRecordingState
) {
2073 TRACE("Recording... not performing anything\n");
2077 /* Not recording... */
2078 /* Need to do a getParent and pass the reffs up */
2079 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2080 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2081 so for now, just count internally */
2082 if (pStreamData
!= NULL
) {
2083 IWineD3DVertexBuffer_AddRef(pStreamData
);
2085 if (oldSrc
!= NULL
) {
2086 IWineD3DVertexBuffer_Release(oldSrc
);
2092 HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
** pStream
, UINT
*pOffset
, UINT
* pStride
) {
2093 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2096 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This
, StreamNumber
,
2097 This
->stateBlock
->streamSource
[StreamNumber
], This
->stateBlock
->streamStride
[StreamNumber
]);
2100 streamFlags
= StreamNumber
&(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2102 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2103 FIXME("stream index data not supported\n");
2105 if (streamFlags
& D3DSTREAMSOURCE_INDEXEDDATA
) {
2106 FIXME("stream instance data not supported\n");
2110 StreamNumber
&= ~(D3DSTREAMSOURCE_INDEXEDDATA
| D3DSTREAMSOURCE_INSTANCEDATA
);
2112 if (StreamNumber
>= MAX_STREAMS
) {
2113 WARN("Stream out of range %d\n", StreamNumber
);
2114 return WINED3DERR_INVALIDCALL
;
2116 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
2117 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
2118 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
2120 if (*pStream
== NULL
) {
2121 FIXME("Attempting to get an empty stream %d, returning WINED3DERR_INVALIDCALL\n", StreamNumber
);
2122 return WINED3DERR_INVALIDCALL
;
2125 IWineD3DVertexBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
2129 /*Should be quite easy, just an extension of vertexdata
2131 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2133 The divider is a bit odd though
2135 VertexOffset = StartVertex / Divider * StreamStride +
2136 VertexIndex / Divider * StreamStride + StreamOffset
2139 HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2140 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2142 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This
, StreamNumber
, Divider
);
2143 This
->updateStateBlock
->streamFlags
[StreamNumber
] = Divider
& (D3DSTREAMSOURCE_INSTANCEDATA
| D3DSTREAMSOURCE_INDEXEDDATA
);
2145 This
->updateStateBlock
->changed
.streamFreq
[StreamNumber
] = TRUE
;
2146 This
->updateStateBlock
->set
.streamFreq
[StreamNumber
] = TRUE
;
2147 This
->updateStateBlock
->streamFreq
[StreamNumber
] = Divider
& 0x7FFFFF;
2149 if (This
->updateStateBlock
->streamFlags
[StreamNumber
] || This
->updateStateBlock
->streamFreq
[StreamNumber
] != 1) {
2150 FIXME("Stream indexing not fully supported\n");
2156 HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2157 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2159 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This
, StreamNumber
, Divider
);
2160 *Divider
= This
->updateStateBlock
->streamFreq
[StreamNumber
] | This
->updateStateBlock
->streamFlags
[StreamNumber
];
2162 TRACE("(%p) : returning %d\n", This
, *Divider
);
2168 * Get / Set & Multiply Transform
2170 HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE d3dts
, CONST D3DMATRIX
* lpmatrix
) {
2171 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2173 /* Most of this routine, comments included copied from ddraw tree initially: */
2174 TRACE("(%p) : Transform State=%d\n", This
, d3dts
);
2176 /* Handle recording of state blocks */
2177 if (This
->isRecordingState
) {
2178 TRACE("Recording... not performing anything\n");
2179 This
->updateStateBlock
->changed
.transform
[d3dts
] = TRUE
;
2180 This
->updateStateBlock
->set
.transform
[d3dts
] = TRUE
;
2181 memcpy(&This
->updateStateBlock
->transforms
[d3dts
], lpmatrix
, sizeof(D3DMATRIX
));
2186 * If the new matrix is the same as the current one,
2187 * we cut off any further processing. this seems to be a reasonable
2188 * optimization because as was noticed, some apps (warcraft3 for example)
2189 * tend towards setting the same matrix repeatedly for some reason.
2191 * From here on we assume that the new matrix is different, wherever it matters.
2193 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(D3DMATRIX
))) {
2194 TRACE("The app is setting the same matrix over again\n");
2197 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
2201 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2202 where ViewMat = Camera space, WorldMat = world space.
2204 In OpenGL, camera and world space is combined into GL_MODELVIEW
2205 matrix. The Projection matrix stay projection matrix.
2208 /* Capture the times we can just ignore the change for now */
2209 if (d3dts
== D3DTS_WORLDMATRIX(0)) {
2210 This
->modelview_valid
= FALSE
;
2213 } else if (d3dts
== D3DTS_PROJECTION
) {
2214 This
->proj_valid
= FALSE
;
2217 } else if (d3dts
>= D3DTS_WORLDMATRIX(1) && d3dts
<= D3DTS_WORLDMATRIX(255)) {
2218 /* Indexed Vertex Blending Matrices 256 -> 511 */
2219 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
2220 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
2224 /* Now we really are going to have to change a matrix */
2227 if (d3dts
>= D3DTS_TEXTURE0
&& d3dts
<= D3DTS_TEXTURE7
) { /* handle texture matrices */
2228 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
2229 } else if (d3dts
== D3DTS_VIEW
) { /* handle the VIEW matrice */
2232 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2233 * NOTE: We have to reset the positions even if the light/plane is not currently
2234 * enabled, since the call to enable it will not reset the position.
2235 * NOTE2: Apparently texture transforms do NOT need reapplying
2238 PLIGHTINFOEL
*lightChain
= NULL
;
2239 This
->modelview_valid
= FALSE
;
2240 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2242 glMatrixMode(GL_MODELVIEW
);
2243 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2245 glLoadMatrixf((float *)lpmatrix
);
2246 checkGLcall("glLoadMatrixf(...)");
2249 lightChain
= This
->stateBlock
->lights
;
2250 while (lightChain
&& lightChain
->glIndex
!= -1) {
2251 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_POSITION
, lightChain
->lightPosn
);
2252 checkGLcall("glLightfv posn");
2253 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_SPOT_DIRECTION
, lightChain
->lightDirn
);
2254 checkGLcall("glLightfv dirn");
2255 lightChain
= lightChain
->next
;
2258 /* Reset Clipping Planes if clipping is enabled */
2259 for (k
= 0; k
< GL_LIMITS(clipplanes
); k
++) {
2260 glClipPlane(GL_CLIP_PLANE0
+ k
, This
->stateBlock
->clipplane
[k
]);
2261 checkGLcall("glClipPlane");
2265 } else { /* What was requested!?? */
2266 WARN("invalid matrix specified: %i\n", d3dts
);
2269 /* Release lock, all done */
2274 HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, D3DMATRIX
* pMatrix
) {
2275 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2276 TRACE("(%p) : for Transform State %d\n", This
, State
);
2277 memcpy(pMatrix
, &This
->stateBlock
->transforms
[State
], sizeof(D3DMATRIX
));
2281 HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, CONST D3DMATRIX
* pMatrix
) {
2282 D3DMATRIX
*mat
= NULL
;
2285 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2286 * below means it will be recorded in a state block change, but it
2287 * works regardless where it is recorded.
2288 * If this is found to be wrong, change to StateBlock.
2290 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2291 TRACE("(%p) : For state %u\n", This
, State
);
2293 if (State
< HIGHEST_TRANSFORMSTATE
)
2295 mat
= &This
->updateStateBlock
->transforms
[State
];
2297 FIXME("Unhandled transform state!!\n");
2300 multiply_matrix(&temp
, mat
, (D3DMATRIX
*) pMatrix
);
2302 /* Apply change via set transform - will reapply to eg. lights this way */
2303 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2308 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
2310 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2311 you can reference any indexes you want as long as that number max are enabled at any
2312 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2313 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2314 but when recording, just build a chain pretty much of commands to be replayed. */
2316 HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2318 PLIGHTINFOEL
*object
, *temp
;
2320 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2321 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
2323 /* If recording state block, just add to end of lights chain */
2324 if (This
->isRecordingState
) {
2325 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2326 if (NULL
== object
) {
2327 return WINED3DERR_OUTOFVIDEOMEMORY
;
2329 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
2330 object
->OriginalIndex
= Index
;
2331 object
->glIndex
= -1;
2332 object
->changed
= TRUE
;
2334 /* Add to the END of the chain of lights changes to be replayed */
2335 if (This
->updateStateBlock
->lights
== NULL
) {
2336 This
->updateStateBlock
->lights
= object
;
2338 temp
= This
->updateStateBlock
->lights
;
2339 while (temp
->next
!= NULL
) temp
=temp
->next
;
2340 temp
->next
= object
;
2342 TRACE("Recording... not performing anything more\n");
2346 /* Ok, not recording any longer so do real work */
2347 object
= This
->stateBlock
->lights
;
2348 while (object
!= NULL
&& object
->OriginalIndex
!= Index
) object
= object
->next
;
2350 /* If we didn't find it in the list of lights, time to add it */
2351 if (object
== NULL
) {
2352 PLIGHTINFOEL
*insertAt
,*prevPos
;
2354 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2355 if (NULL
== object
) {
2356 return WINED3DERR_OUTOFVIDEOMEMORY
;
2358 object
->OriginalIndex
= Index
;
2359 object
->glIndex
= -1;
2361 /* Add it to the front of list with the idea that lights will be changed as needed
2362 BUT after any lights currently assigned GL indexes */
2363 insertAt
= This
->stateBlock
->lights
;
2365 while (insertAt
!= NULL
&& insertAt
->glIndex
!= -1) {
2367 insertAt
= insertAt
->next
;
2370 if (insertAt
== NULL
&& prevPos
== NULL
) { /* Start of list */
2371 This
->stateBlock
->lights
= object
;
2372 } else if (insertAt
== NULL
) { /* End of list */
2373 prevPos
->next
= object
;
2374 object
->prev
= prevPos
;
2375 } else { /* Middle of chain */
2376 if (prevPos
== NULL
) {
2377 This
->stateBlock
->lights
= object
;
2379 prevPos
->next
= object
;
2381 object
->prev
= prevPos
;
2382 object
->next
= insertAt
;
2383 insertAt
->prev
= object
;
2387 /* Initialize the object */
2388 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index
, pLight
->Type
,
2389 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2390 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2391 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2392 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2393 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2394 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2396 /* Save away the information */
2397 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
2399 switch (pLight
->Type
) {
2400 case D3DLIGHT_POINT
:
2402 object
->lightPosn
[0] = pLight
->Position
.x
;
2403 object
->lightPosn
[1] = pLight
->Position
.y
;
2404 object
->lightPosn
[2] = pLight
->Position
.z
;
2405 object
->lightPosn
[3] = 1.0f
;
2406 object
->cutoff
= 180.0f
;
2410 case D3DLIGHT_DIRECTIONAL
:
2412 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2413 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2414 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2415 object
->lightPosn
[3] = 0.0;
2416 object
->exponent
= 0.0f
;
2417 object
->cutoff
= 180.0f
;
2422 object
->lightPosn
[0] = pLight
->Position
.x
;
2423 object
->lightPosn
[1] = pLight
->Position
.y
;
2424 object
->lightPosn
[2] = pLight
->Position
.z
;
2425 object
->lightPosn
[3] = 1.0;
2428 object
->lightDirn
[0] = pLight
->Direction
.x
;
2429 object
->lightDirn
[1] = pLight
->Direction
.y
;
2430 object
->lightDirn
[2] = pLight
->Direction
.z
;
2431 object
->lightDirn
[3] = 1.0;
2434 * opengl-ish and d3d-ish spot lights use too different models for the
2435 * light "intensity" as a function of the angle towards the main light direction,
2436 * so we only can approximate very roughly.
2437 * however spot lights are rather rarely used in games (if ever used at all).
2438 * furthermore if still used, probably nobody pays attention to such details.
2440 if (pLight
->Falloff
== 0) {
2443 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2445 if (rho
< 0.0001) rho
= 0.0001f
;
2446 object
->exponent
= -0.3/log(cos(rho
/2));
2447 object
->cutoff
= pLight
->Phi
*90/M_PI
;
2453 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2456 /* Update the live definitions if the light is currently assigned a glIndex */
2457 if (object
->glIndex
!= -1) {
2458 setup_light(iface
, object
->glIndex
, object
);
2463 HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
* pLight
) {
2464 PLIGHTINFOEL
*lightInfo
= NULL
;
2465 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2466 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
2468 /* Locate the light in the live lights */
2469 lightInfo
= This
->stateBlock
->lights
;
2470 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2472 if (lightInfo
== NULL
) {
2473 TRACE("Light information requested but light not defined\n");
2474 return WINED3DERR_INVALIDCALL
;
2477 memcpy(pLight
, &lightInfo
->OriginalParms
, sizeof(D3DLIGHT9
));
2482 * Get / Set Light Enable
2483 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2485 HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
) {
2486 PLIGHTINFOEL
*lightInfo
= NULL
;
2487 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2488 TRACE("(%p) : Idx(%ld), enable? %d\n", This
, Index
, Enable
);
2490 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2491 if (This
->isRecordingState
) {
2492 lightInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
2493 if (NULL
== lightInfo
) {
2494 return WINED3DERR_OUTOFVIDEOMEMORY
;
2496 lightInfo
->OriginalIndex
= Index
;
2497 lightInfo
->glIndex
= -1;
2498 lightInfo
->enabledChanged
= TRUE
;
2500 /* Add to the END of the chain of lights changes to be replayed */
2501 if (This
->updateStateBlock
->lights
== NULL
) {
2502 This
->updateStateBlock
->lights
= lightInfo
;
2504 PLIGHTINFOEL
*temp
= This
->updateStateBlock
->lights
;
2505 while (temp
->next
!= NULL
) temp
=temp
->next
;
2506 temp
->next
= lightInfo
;
2508 TRACE("Recording... not performing anything more\n");
2512 /* Not recording... So, locate the light in the live lights */
2513 lightInfo
= This
->stateBlock
->lights
;
2514 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2516 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2517 if (lightInfo
== NULL
) {
2518 D3DLIGHT9 lightParms
;
2519 /* Warning - untested code :-) Prob safe to change fixme to a trace but
2520 wait until someone confirms it seems to work! */
2521 TRACE("Light enabled requested but light not defined, so defining one!\n");
2522 lightParms
.Type
= D3DLIGHT_DIRECTIONAL
;
2523 lightParms
.Diffuse
.r
= 1.0;
2524 lightParms
.Diffuse
.g
= 1.0;
2525 lightParms
.Diffuse
.b
= 1.0;
2526 lightParms
.Diffuse
.a
= 0.0;
2527 lightParms
.Specular
.r
= 0.0;
2528 lightParms
.Specular
.g
= 0.0;
2529 lightParms
.Specular
.b
= 0.0;
2530 lightParms
.Specular
.a
= 0.0;
2531 lightParms
.Ambient
.r
= 0.0;
2532 lightParms
.Ambient
.g
= 0.0;
2533 lightParms
.Ambient
.b
= 0.0;
2534 lightParms
.Ambient
.a
= 0.0;
2535 lightParms
.Position
.x
= 0.0;
2536 lightParms
.Position
.y
= 0.0;
2537 lightParms
.Position
.z
= 0.0;
2538 lightParms
.Direction
.x
= 0.0;
2539 lightParms
.Direction
.y
= 0.0;
2540 lightParms
.Direction
.z
= 1.0;
2541 lightParms
.Range
= 0.0;
2542 lightParms
.Falloff
= 0.0;
2543 lightParms
.Attenuation0
= 0.0;
2544 lightParms
.Attenuation1
= 0.0;
2545 lightParms
.Attenuation2
= 0.0;
2546 lightParms
.Theta
= 0.0;
2547 lightParms
.Phi
= 0.0;
2548 IWineD3DDeviceImpl_SetLight(iface
, Index
, &lightParms
);
2550 /* Search for it again! Should be fairly quick as near head of list */
2551 lightInfo
= This
->stateBlock
->lights
;
2552 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2553 if (lightInfo
== NULL
) {
2554 FIXME("Adding default lights has failed dismally\n");
2555 return WINED3DERR_INVALIDCALL
;
2559 /* OK, we now have a light... */
2560 if (Enable
== FALSE
) {
2562 /* If we are disabling it, check it was enabled, and
2563 still only do something if it has assigned a glIndex (which it should have!) */
2564 if ((lightInfo
->lightEnabled
) && (lightInfo
->glIndex
!= -1)) {
2565 TRACE("Disabling light set up at gl idx %ld\n", lightInfo
->glIndex
);
2567 glDisable(GL_LIGHT0
+ lightInfo
->glIndex
);
2568 checkGLcall("glDisable GL_LIGHT0+Index");
2571 TRACE("Nothing to do as light was not enabled\n");
2573 lightInfo
->lightEnabled
= FALSE
;
2576 /* We are enabling it. If it is enabled, it's really simple */
2577 if (lightInfo
->lightEnabled
) {
2579 TRACE("Nothing to do as light was enabled\n");
2581 /* If it already has a glIndex, it's still simple */
2582 } else if (lightInfo
->glIndex
!= -1) {
2583 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo
->glIndex
);
2584 lightInfo
->lightEnabled
= TRUE
;
2586 glEnable(GL_LIGHT0
+ lightInfo
->glIndex
);
2587 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2590 /* Otherwise got to find space - lights are ordered gl indexes first */
2592 PLIGHTINFOEL
*bsf
= NULL
;
2593 PLIGHTINFOEL
*pos
= This
->stateBlock
->lights
;
2594 PLIGHTINFOEL
*prev
= NULL
;
2598 /* Try to minimize changes as much as possible */
2599 while (pos
!= NULL
&& pos
->glIndex
!= -1 && Index
< This
->maxConcurrentLights
) {
2601 /* Try to remember which index can be replaced if necessary */
2602 if (bsf
==NULL
&& pos
->lightEnabled
== FALSE
) {
2603 /* Found a light we can replace, save as best replacement */
2607 /* Step to next space */
2613 /* If we have too many active lights, fail the call */
2614 if ((Index
== This
->maxConcurrentLights
) && (bsf
== NULL
)) {
2615 FIXME("Program requests too many concurrent lights\n");
2616 return WINED3DERR_INVALIDCALL
;
2618 /* If we have allocated all lights, but not all are enabled,
2619 reuse one which is not enabled */
2620 } else if (Index
== This
->maxConcurrentLights
) {
2621 /* use bsf - Simply swap the new light and the BSF one */
2622 PLIGHTINFOEL
*bsfNext
= bsf
->next
;
2623 PLIGHTINFOEL
*bsfPrev
= bsf
->prev
;
2626 if (lightInfo
->next
!= NULL
) lightInfo
->next
->prev
= bsf
;
2627 if (bsf
->prev
!= NULL
) {
2628 bsf
->prev
->next
= lightInfo
;
2630 This
->stateBlock
->lights
= lightInfo
;
2633 /* If not side by side, lots of chains to update */
2634 if (bsf
->next
!= lightInfo
) {
2635 lightInfo
->prev
->next
= bsf
;
2636 bsf
->next
->prev
= lightInfo
;
2637 bsf
->next
= lightInfo
->next
;
2638 bsf
->prev
= lightInfo
->prev
;
2639 lightInfo
->next
= bsfNext
;
2640 lightInfo
->prev
= bsfPrev
;
2644 bsf
->prev
= lightInfo
;
2645 bsf
->next
= lightInfo
->next
;
2646 lightInfo
->next
= bsf
;
2647 lightInfo
->prev
= bsfPrev
;
2652 glIndex
= bsf
->glIndex
;
2654 lightInfo
->glIndex
= glIndex
;
2655 lightInfo
->lightEnabled
= TRUE
;
2657 /* Finally set up the light in gl itself */
2658 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo
->glIndex
);
2660 setup_light(iface
, glIndex
, lightInfo
);
2661 glEnable(GL_LIGHT0
+ glIndex
);
2662 checkGLcall("glEnable GL_LIGHT0 new setup");
2665 /* If we reached the end of the allocated lights, with space in the
2666 gl lights, setup a new light */
2667 } else if (pos
->glIndex
== -1) {
2669 /* We reached the end of the allocated gl lights, so already
2670 know the index of the next one! */
2672 lightInfo
->glIndex
= glIndex
;
2673 lightInfo
->lightEnabled
= TRUE
;
2675 /* In an ideal world, it's already in the right place */
2676 if (lightInfo
->prev
== NULL
|| lightInfo
->prev
->glIndex
!=-1) {
2677 /* No need to move it */
2679 /* Remove this light from the list */
2680 lightInfo
->prev
->next
= lightInfo
->next
;
2681 if (lightInfo
->next
!= NULL
) {
2682 lightInfo
->next
->prev
= lightInfo
->prev
;
2685 /* Add in at appropriate place (inbetween prev and pos) */
2686 lightInfo
->prev
= prev
;
2687 lightInfo
->next
= pos
;
2689 This
->stateBlock
->lights
= lightInfo
;
2691 prev
->next
= lightInfo
;
2694 pos
->prev
= lightInfo
;
2698 /* Finally set up the light in gl itself */
2699 TRACE("Defining new light at gl idx %ld\n", lightInfo
->glIndex
);
2701 setup_light(iface
, glIndex
, lightInfo
);
2702 glEnable(GL_LIGHT0
+ glIndex
);
2703 checkGLcall("glEnable GL_LIGHT0 new setup");
2712 HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
) {
2714 PLIGHTINFOEL
*lightInfo
= NULL
;
2715 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2716 TRACE("(%p) : for idx(%ld)\n", This
, Index
);
2718 /* Locate the light in the live lights */
2719 lightInfo
= This
->stateBlock
->lights
;
2720 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2722 if (lightInfo
== NULL
) {
2723 TRACE("Light enabled state requested but light not defined\n");
2724 return WINED3DERR_INVALIDCALL
;
2726 *pEnable
= lightInfo
->lightEnabled
;
2731 * Get / Set Clip Planes
2733 HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
2734 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2735 TRACE("(%p) : for idx %ld, %p\n", This
, Index
, pPlane
);
2737 /* Validate Index */
2738 if (Index
>= GL_LIMITS(clipplanes
)) {
2739 TRACE("Application has requested clipplane this device doesn't support\n");
2740 return WINED3DERR_INVALIDCALL
;
2743 This
->updateStateBlock
->changed
.clipplane
[Index
] = TRUE
;
2744 This
->updateStateBlock
->set
.clipplane
[Index
] = TRUE
;
2745 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
2746 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
2747 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
2748 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
2750 /* Handle recording of state blocks */
2751 if (This
->isRecordingState
) {
2752 TRACE("Recording... not performing anything\n");
2760 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2761 glMatrixMode(GL_MODELVIEW
);
2763 glLoadMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_VIEW
].u
.m
[0][0]);
2765 TRACE("Clipplane [%f,%f,%f,%f]\n",
2766 This
->updateStateBlock
->clipplane
[Index
][0],
2767 This
->updateStateBlock
->clipplane
[Index
][1],
2768 This
->updateStateBlock
->clipplane
[Index
][2],
2769 This
->updateStateBlock
->clipplane
[Index
][3]);
2770 glClipPlane(GL_CLIP_PLANE0
+ Index
, This
->updateStateBlock
->clipplane
[Index
]);
2771 checkGLcall("glClipPlane");
2779 HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
2780 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2781 TRACE("(%p) : for idx %ld\n", This
, Index
);
2783 /* Validate Index */
2784 if (Index
>= GL_LIMITS(clipplanes
)) {
2785 TRACE("Application has requested clipplane this device doesn't support\n");
2786 return WINED3DERR_INVALIDCALL
;
2789 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
2790 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
2791 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
2792 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
2797 * Get / Set Clip Plane Status
2798 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2800 HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
2801 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2802 FIXME("(%p) : stub\n", This
);
2803 if (NULL
== pClipStatus
) {
2804 return WINED3DERR_INVALIDCALL
;
2806 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
2807 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
2811 HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
2812 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2813 FIXME("(%p) : stub\n", This
);
2814 if (NULL
== pClipStatus
) {
2815 return WINED3DERR_INVALIDCALL
;
2817 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
2818 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
2823 * Get / Set Material
2824 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2826 HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
2827 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2829 This
->updateStateBlock
->changed
.material
= TRUE
;
2830 This
->updateStateBlock
->set
.material
= TRUE
;
2831 memcpy(&This
->updateStateBlock
->material
, pMaterial
, sizeof(WINED3DMATERIAL
));
2833 /* Handle recording of state blocks */
2834 if (This
->isRecordingState
) {
2835 TRACE("Recording... not performing anything\n");
2840 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
2841 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
2842 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
2843 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
2844 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
2845 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
2846 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
2847 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
2848 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
2850 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, (float*) &This
->updateStateBlock
->material
.Ambient
);
2851 checkGLcall("glMaterialfv(GL_AMBIENT)");
2852 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, (float*) &This
->updateStateBlock
->material
.Diffuse
);
2853 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2855 /* Only change material color if specular is enabled, otherwise it is set to black */
2856 if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARENABLE
]) {
2857 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
2858 checkGLcall("glMaterialfv(GL_SPECULAR");
2860 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
2861 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
2862 checkGLcall("glMaterialfv(GL_SPECULAR");
2864 glMaterialfv(GL_FRONT_AND_BACK
, GL_EMISSION
, (float*) &This
->updateStateBlock
->material
.Emissive
);
2865 checkGLcall("glMaterialfv(GL_EMISSION)");
2866 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, This
->updateStateBlock
->material
.Power
);
2867 checkGLcall("glMaterialf(GL_SHININESS");
2873 HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
2874 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2875 memcpy(pMaterial
, &This
->updateStateBlock
->material
, sizeof (WINED3DMATERIAL
));
2876 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
2877 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
2878 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
2879 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
2880 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
2881 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
2882 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
2883 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
2884 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
2892 HRESULT WINAPI
IWineD3DDeviceImpl_SetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
* pIndexData
,
2893 UINT BaseVertexIndex
) {
2894 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2895 IWineD3DIndexBuffer
*oldIdxs
;
2897 TRACE("(%p) : Setting to %p, base %d\n", This
, pIndexData
, BaseVertexIndex
);
2898 oldIdxs
= This
->updateStateBlock
->pIndexData
;
2900 This
->updateStateBlock
->changed
.indices
= TRUE
;
2901 This
->updateStateBlock
->set
.indices
= TRUE
;
2902 This
->updateStateBlock
->pIndexData
= pIndexData
;
2903 This
->updateStateBlock
->baseVertexIndex
= BaseVertexIndex
;
2905 /* Handle recording of state blocks */
2906 if (This
->isRecordingState
) {
2907 TRACE("Recording... not performing anything\n");
2911 if (NULL
!= pIndexData
) {
2912 IWineD3DIndexBuffer_AddRef(pIndexData
);
2914 if (NULL
!= oldIdxs
) {
2915 IWineD3DIndexBuffer_Release(oldIdxs
);
2920 HRESULT WINAPI
IWineD3DDeviceImpl_GetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
** ppIndexData
, UINT
* pBaseVertexIndex
) {
2921 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2923 *ppIndexData
= This
->stateBlock
->pIndexData
;
2925 /* up ref count on ppindexdata */
2927 IWineD3DIndexBuffer_AddRef(*ppIndexData
);
2928 *pBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
2929 TRACE("(%p) index data set to %p + %u\n", This
, ppIndexData
, This
->stateBlock
->baseVertexIndex
);
2931 TRACE("(%p) No index data set\n", This
);
2933 TRACE("Returning %p %d\n", *ppIndexData
, *pBaseVertexIndex
);
2939 * Get / Set Viewports
2941 HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
2942 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2944 TRACE("(%p)\n", This
);
2945 This
->updateStateBlock
->changed
.viewport
= TRUE
;
2946 This
->updateStateBlock
->set
.viewport
= TRUE
;
2947 memcpy(&This
->updateStateBlock
->viewport
, pViewport
, sizeof(WINED3DVIEWPORT
));
2949 /* Handle recording of state blocks */
2950 if (This
->isRecordingState
) {
2951 TRACE("Recording... not performing anything\n");
2954 This
->viewport_changed
= TRUE
;
2958 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This
,
2959 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
2961 glDepthRange(pViewport
->MinZ
, pViewport
->MaxZ
);
2962 checkGLcall("glDepthRange");
2963 /* Note: GL requires lower left, DirectX supplies upper left */
2964 /* TODO: replace usage of renderTarget with context management */
2965 glViewport(pViewport
->X
,
2966 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- (pViewport
->Y
+ pViewport
->Height
)),
2967 pViewport
->Width
, pViewport
->Height
);
2969 checkGLcall("glViewport");
2977 HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
2978 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2979 TRACE("(%p)\n", This
);
2980 memcpy(pViewport
, &This
->stateBlock
->viewport
, sizeof(WINED3DVIEWPORT
));
2985 * Get / Set Render States
2986 * TODO: Verify against dx9 definitions
2988 HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD Value
) {
2990 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2991 DWORD OldValue
= This
->stateBlock
->renderState
[State
];
2993 /* Simple way of referring to either a DWORD or a 4 byte float */
2999 TRACE("(%p)->state = %s(%d), value = %ld\n", This
, debug_d3drenderstate(State
), State
, Value
);
3000 This
->updateStateBlock
->changed
.renderState
[State
] = TRUE
;
3001 This
->updateStateBlock
->set
.renderState
[State
] = TRUE
;
3002 This
->updateStateBlock
->renderState
[State
] = Value
;
3004 /* Handle recording of state blocks */
3005 if (This
->isRecordingState
) {
3006 TRACE("Recording... not performing anything\n");
3013 case WINED3DRS_FILLMODE
:
3014 switch ((D3DFILLMODE
) Value
) {
3015 case D3DFILL_POINT
: glPolygonMode(GL_FRONT_AND_BACK
, GL_POINT
); break;
3016 case D3DFILL_WIREFRAME
: glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
); break;
3017 case D3DFILL_SOLID
: glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
); break;
3019 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value
);
3021 checkGLcall("glPolygonMode (fillmode)");
3024 case WINED3DRS_LIGHTING
:
3026 glEnable(GL_LIGHTING
);
3027 checkGLcall("glEnable GL_LIGHTING");
3029 glDisable(GL_LIGHTING
);
3030 checkGLcall("glDisable GL_LIGHTING");
3034 case WINED3DRS_ZENABLE
:
3035 switch ((D3DZBUFFERTYPE
) Value
) {
3037 glDisable(GL_DEPTH_TEST
);
3038 checkGLcall("glDisable GL_DEPTH_TEST");
3041 glEnable(GL_DEPTH_TEST
);
3042 checkGLcall("glEnable GL_DEPTH_TEST");
3045 glEnable(GL_DEPTH_TEST
);
3046 checkGLcall("glEnable GL_DEPTH_TEST");
3047 FIXME("W buffer is not well handled\n");
3050 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value
);
3054 case WINED3DRS_CULLMODE
:
3056 /* If we are culling "back faces with clockwise vertices" then
3057 set front faces to be counter clockwise and enable culling
3059 switch ((D3DCULL
) Value
) {
3061 glDisable(GL_CULL_FACE
);
3062 checkGLcall("glDisable GL_CULL_FACE");
3065 glEnable(GL_CULL_FACE
);
3066 checkGLcall("glEnable GL_CULL_FACE");
3067 if (This
->renderUpsideDown
) {
3069 checkGLcall("glFrontFace GL_CW");
3071 glFrontFace(GL_CCW
);
3072 checkGLcall("glFrontFace GL_CCW");
3074 glCullFace(GL_BACK
);
3077 glEnable(GL_CULL_FACE
);
3078 checkGLcall("glEnable GL_CULL_FACE");
3079 if (This
->renderUpsideDown
) {
3080 glFrontFace(GL_CCW
);
3081 checkGLcall("glFrontFace GL_CCW");
3084 checkGLcall("glFrontFace GL_CW");
3086 glCullFace(GL_BACK
);
3089 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value
);
3093 case WINED3DRS_SHADEMODE
:
3094 switch ((D3DSHADEMODE
) Value
) {
3096 glShadeModel(GL_FLAT
);
3097 checkGLcall("glShadeModel");
3099 case D3DSHADE_GOURAUD
:
3100 glShadeModel(GL_SMOOTH
);
3101 checkGLcall("glShadeModel");
3103 case D3DSHADE_PHONG
:
3104 FIXME("D3DSHADE_PHONG isn't supported?\n");
3107 return WINED3DERR_INVALIDCALL
;
3109 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value
);
3113 case WINED3DRS_DITHERENABLE
:
3115 glEnable(GL_DITHER
);
3116 checkGLcall("glEnable GL_DITHER");
3118 glDisable(GL_DITHER
);
3119 checkGLcall("glDisable GL_DITHER");
3123 case WINED3DRS_ZWRITEENABLE
:
3126 checkGLcall("glDepthMask");
3129 checkGLcall("glDepthMask");
3133 case WINED3DRS_ZFUNC
:
3135 int glParm
= GL_LESS
;
3137 switch ((D3DCMPFUNC
) Value
) {
3138 case D3DCMP_NEVER
: glParm
=GL_NEVER
; break;
3139 case D3DCMP_LESS
: glParm
=GL_LESS
; break;
3140 case D3DCMP_EQUAL
: glParm
=GL_EQUAL
; break;
3141 case D3DCMP_LESSEQUAL
: glParm
=GL_LEQUAL
; break;
3142 case D3DCMP_GREATER
: glParm
=GL_GREATER
; break;
3143 case D3DCMP_NOTEQUAL
: glParm
=GL_NOTEQUAL
; break;
3144 case D3DCMP_GREATEREQUAL
: glParm
=GL_GEQUAL
; break;
3145 case D3DCMP_ALWAYS
: glParm
=GL_ALWAYS
; break;
3147 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
3149 glDepthFunc(glParm
);
3150 checkGLcall("glDepthFunc");
3154 case WINED3DRS_AMBIENT
:
3157 D3DCOLORTOGLFLOAT4(Value
, col
);
3158 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col
[0], col
[1], col
[2], col
[3]);
3159 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, col
);
3160 checkGLcall("glLightModel for MODEL_AMBIENT");
3165 case WINED3DRS_ALPHABLENDENABLE
:
3168 checkGLcall("glEnable GL_BLEND");
3170 glDisable(GL_BLEND
);
3171 checkGLcall("glDisable GL_BLEND");
3175 case WINED3DRS_SRCBLEND
:
3176 case WINED3DRS_DESTBLEND
:
3178 int newVal
= GL_ZERO
;
3180 case D3DBLEND_ZERO
: newVal
= GL_ZERO
; break;
3181 case D3DBLEND_ONE
: newVal
= GL_ONE
; break;
3182 case D3DBLEND_SRCCOLOR
: newVal
= GL_SRC_COLOR
; break;
3183 case D3DBLEND_INVSRCCOLOR
: newVal
= GL_ONE_MINUS_SRC_COLOR
; break;
3184 case D3DBLEND_SRCALPHA
: newVal
= GL_SRC_ALPHA
; break;
3185 case D3DBLEND_INVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
; break;
3186 case D3DBLEND_DESTALPHA
: newVal
= GL_DST_ALPHA
; break;
3187 case D3DBLEND_INVDESTALPHA
: newVal
= GL_ONE_MINUS_DST_ALPHA
; break;
3188 case D3DBLEND_DESTCOLOR
: newVal
= GL_DST_COLOR
; break;
3189 case D3DBLEND_INVDESTCOLOR
: newVal
= GL_ONE_MINUS_DST_COLOR
; break;
3190 case D3DBLEND_SRCALPHASAT
: newVal
= GL_SRC_ALPHA_SATURATE
; break;
3192 case D3DBLEND_BOTHSRCALPHA
: newVal
= GL_SRC_ALPHA
;
3193 This
->srcBlend
= newVal
;
3194 This
->dstBlend
= newVal
;
3197 case D3DBLEND_BOTHINVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
;
3198 This
->srcBlend
= newVal
;
3199 This
->dstBlend
= newVal
;
3202 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value
, State
);
3205 if (State
== WINED3DRS_SRCBLEND
) This
->srcBlend
= newVal
;
3206 if (State
== WINED3DRS_DESTBLEND
) This
->dstBlend
= newVal
;
3207 TRACE("glBlendFunc src=%x, dst=%x\n", This
->srcBlend
, This
->dstBlend
);
3208 glBlendFunc(This
->srcBlend
, This
->dstBlend
);
3210 checkGLcall("glBlendFunc");
3214 case WINED3DRS_ALPHATESTENABLE
:
3215 case WINED3DRS_ALPHAFUNC
:
3216 case WINED3DRS_ALPHAREF
:
3217 case WINED3DRS_COLORKEYENABLE
:
3220 float ref
= GL_LESS
;
3221 BOOL enable_ckey
= FALSE
;
3223 IWineD3DSurfaceImpl
*surf
;
3225 /* Find out if the texture on the first stage has a ckey set */
3226 if(This
->stateBlock
->textures
[0]) {
3227 surf
= (IWineD3DSurfaceImpl
*) ((IWineD3DTextureImpl
*)This
->stateBlock
->textures
[0])->surfaces
[0];
3228 if(surf
->CKeyFlags
& DDSD_CKSRCBLT
) enable_ckey
= TRUE
;
3231 if (This
->stateBlock
->renderState
[WINED3DRS_ALPHATESTENABLE
] ||
3232 (This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
] && enable_ckey
)) {
3233 glEnable(GL_ALPHA_TEST
);
3234 checkGLcall("glEnable GL_ALPHA_TEST");
3236 glDisable(GL_ALPHA_TEST
);
3237 checkGLcall("glDisable GL_ALPHA_TEST");
3238 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
3244 if(This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
] && enable_ckey
) {
3245 glParm
= GL_NOTEQUAL
;
3248 ref
= ((float) This
->stateBlock
->renderState
[WINED3DRS_ALPHAREF
]) / 255.0f
;
3250 switch ((D3DCMPFUNC
) This
->stateBlock
->renderState
[WINED3DRS_ALPHAFUNC
]) {
3251 case D3DCMP_NEVER
: glParm
= GL_NEVER
; break;
3252 case D3DCMP_LESS
: glParm
= GL_LESS
; break;
3253 case D3DCMP_EQUAL
: glParm
= GL_EQUAL
; break;
3254 case D3DCMP_LESSEQUAL
: glParm
= GL_LEQUAL
; break;
3255 case D3DCMP_GREATER
: glParm
= GL_GREATER
; break;
3256 case D3DCMP_NOTEQUAL
: glParm
= GL_NOTEQUAL
; break;
3257 case D3DCMP_GREATEREQUAL
: glParm
= GL_GEQUAL
; break;
3258 case D3DCMP_ALWAYS
: glParm
= GL_ALWAYS
; break;
3260 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
3263 This
->alphafunc
= glParm
;
3264 glAlphaFunc(glParm
, ref
);
3265 checkGLcall("glAlphaFunc");
3269 case WINED3DRS_CLIPPLANEENABLE
:
3270 case WINED3DRS_CLIPPING
:
3272 /* Ensure we only do the changed clip planes */
3273 DWORD enable
= 0xFFFFFFFF;
3274 DWORD disable
= 0x00000000;
3276 /* If enabling / disabling all */
3277 if (State
== WINED3DRS_CLIPPING
) {
3279 enable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
3282 disable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
3286 enable
= Value
& ~OldValue
;
3287 disable
= ~Value
& OldValue
;
3290 if (enable
& D3DCLIPPLANE0
) { glEnable(GL_CLIP_PLANE0
); checkGLcall("glEnable(clip plane 0)"); }
3291 if (enable
& D3DCLIPPLANE1
) { glEnable(GL_CLIP_PLANE1
); checkGLcall("glEnable(clip plane 1)"); }
3292 if (enable
& D3DCLIPPLANE2
) { glEnable(GL_CLIP_PLANE2
); checkGLcall("glEnable(clip plane 2)"); }
3293 if (enable
& D3DCLIPPLANE3
) { glEnable(GL_CLIP_PLANE3
); checkGLcall("glEnable(clip plane 3)"); }
3294 if (enable
& D3DCLIPPLANE4
) { glEnable(GL_CLIP_PLANE4
); checkGLcall("glEnable(clip plane 4)"); }
3295 if (enable
& D3DCLIPPLANE5
) { glEnable(GL_CLIP_PLANE5
); checkGLcall("glEnable(clip plane 5)"); }
3297 if (disable
& D3DCLIPPLANE0
) { glDisable(GL_CLIP_PLANE0
); checkGLcall("glDisable(clip plane 0)"); }
3298 if (disable
& D3DCLIPPLANE1
) { glDisable(GL_CLIP_PLANE1
); checkGLcall("glDisable(clip plane 1)"); }
3299 if (disable
& D3DCLIPPLANE2
) { glDisable(GL_CLIP_PLANE2
); checkGLcall("glDisable(clip plane 2)"); }
3300 if (disable
& D3DCLIPPLANE3
) { glDisable(GL_CLIP_PLANE3
); checkGLcall("glDisable(clip plane 3)"); }
3301 if (disable
& D3DCLIPPLANE4
) { glDisable(GL_CLIP_PLANE4
); checkGLcall("glDisable(clip plane 4)"); }
3302 if (disable
& D3DCLIPPLANE5
) { glDisable(GL_CLIP_PLANE5
); checkGLcall("glDisable(clip plane 5)"); }
3304 /** update clipping status */
3306 This
->stateBlock
->clip_status
.ClipUnion
= 0;
3307 This
->stateBlock
->clip_status
.ClipIntersection
= 0xFFFFFFFF;
3309 This
->stateBlock
->clip_status
.ClipUnion
= 0;
3310 This
->stateBlock
->clip_status
.ClipIntersection
= 0;
3315 case WINED3DRS_BLENDOP
:
3317 int glParm
= GL_FUNC_ADD
;
3319 switch ((D3DBLENDOP
) Value
) {
3320 case D3DBLENDOP_ADD
: glParm
= GL_FUNC_ADD
; break;
3321 case D3DBLENDOP_SUBTRACT
: glParm
= GL_FUNC_SUBTRACT
; break;
3322 case D3DBLENDOP_REVSUBTRACT
: glParm
= GL_FUNC_REVERSE_SUBTRACT
; break;
3323 case D3DBLENDOP_MIN
: glParm
= GL_MIN
; break;
3324 case D3DBLENDOP_MAX
: glParm
= GL_MAX
; break;
3326 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value
);
3329 if(GL_SUPPORT(ARB_IMAGING
)) {
3330 TRACE("glBlendEquation(%x)\n", glParm
);
3331 GL_EXTCALL(glBlendEquation(glParm
));
3332 checkGLcall("glBlendEquation");
3334 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
3339 case WINED3DRS_TEXTUREFACTOR
:
3343 /* Note the texture color applies to all textures whereas
3344 GL_TEXTURE_ENV_COLOR applies to active only */
3346 D3DCOLORTOGLFLOAT4(Value
, col
);
3347 /* Set the default alpha blend color */
3348 if (GL_SUPPORT(ARB_IMAGING
)) {
3349 GL_EXTCALL(glBlendColor(col
[0], col
[1], col
[2], col
[3]));
3350 checkGLcall("glBlendColor");
3352 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
3355 /* And now the default texture color as well */
3356 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
3358 /* Note the D3DRS value applies to all textures, but GL has one
3359 per texture, so apply it now ready to be used! */
3360 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
3361 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
3362 checkGLcall("glActiveTextureARB");
3364 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3367 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
3368 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
3373 case WINED3DRS_SPECULARENABLE
:
3375 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
3376 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
3377 specular color. This is wrong:
3378 Separate specular color means the specular colour is maintained separately, whereas
3379 single color means it is merged in. However in both cases they are being used to
3381 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
3382 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
3386 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
3387 checkGLcall("glMaterialfv");
3388 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
3389 glEnable(GL_COLOR_SUM_EXT
);
3391 TRACE("Specular colors cannot be enabled in this version of opengl\n");
3393 checkGLcall("glEnable(GL_COLOR_SUM)");
3395 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
3397 /* for the case of enabled lighting: */
3398 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
3399 checkGLcall("glMaterialfv");
3401 /* for the case of disabled lighting: */
3402 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
3403 glDisable(GL_COLOR_SUM_EXT
);
3405 TRACE("Specular colors cannot be disabled in this version of opengl\n");
3407 checkGLcall("glDisable(GL_COLOR_SUM)");
3412 case WINED3DRS_STENCILENABLE
:
3414 glEnable(GL_STENCIL_TEST
);
3415 checkGLcall("glEnable GL_STENCIL_TEST");
3417 glDisable(GL_STENCIL_TEST
);
3418 checkGLcall("glDisable GL_STENCIL_TEST");
3422 case WINED3DRS_STENCILFUNC
:
3425 GLint ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
3426 GLuint mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
3429 switch ((D3DCMPFUNC
)Value
) {
3430 case D3DCMP_NEVER
: func
= GL_NEVER
; break;
3431 case D3DCMP_LESS
: func
= GL_LESS
; break;
3432 case D3DCMP_EQUAL
: func
= GL_EQUAL
; break;
3433 case D3DCMP_LESSEQUAL
: func
= GL_LEQUAL
; break;
3434 case D3DCMP_GREATER
: func
= GL_GREATER
; break;
3435 case D3DCMP_NOTEQUAL
: func
= GL_NOTEQUAL
; break;
3436 case D3DCMP_GREATEREQUAL
: func
= GL_GEQUAL
; break;
3437 case D3DCMP_ALWAYS
: func
= GL_ALWAYS
; break;
3439 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
3441 This
->stencilfunc
= func
;
3442 if(!This
->stateBlock
->renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
]) {
3443 #if 0 /* Don't use OpenGL 2.0 calls for now */
3444 if(GL_EXTCALL(glStencilFuncSeparate
)) {
3445 GL_EXTCALL(glStencilFuncSeparate(GL_FRONT
, func
, ref
, mask
));
3446 checkGLcall("glStencilFuncSeparate(GL_FRONT,...)");
3450 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE
)) {
3451 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
3452 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3453 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT
));
3454 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3455 glStencilFunc(func
, ref
, mask
);
3456 checkGLcall("glStencilFunc(...)");
3458 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL
)) {
3459 GL_EXTCALL(glStencilFuncSeparateATI(GL_FRONT
, func
, ref
, mask
));
3460 checkGLcall("glStencilFuncSeparateATI(GL_FRONT,...)");
3462 TRACE("Separate stencil function not supported on this version of opengl");
3463 glStencilFunc(func
, ref
, mask
);
3464 checkGLcall("glStencilFunc(...)");
3467 glStencilFunc(func
, ref
, mask
);
3468 checkGLcall("glStencilFunc(...)");
3472 case WINED3DRS_STENCILREF
:
3474 int glParm
= This
->stencilfunc
;
3476 GLuint mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
3479 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm
, ref
, mask
);
3480 glStencilFunc(glParm
, ref
, mask
);
3481 checkGLcall("glStencilFunc");
3485 case WINED3DRS_STENCILMASK
:
3487 int glParm
= This
->stencilfunc
;
3488 int ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
3489 GLuint mask
= Value
;
3491 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm
, ref
, mask
);
3492 glStencilFunc(glParm
, ref
, mask
);
3493 checkGLcall("glStencilFunc");
3497 case WINED3DRS_STENCILFAIL
:
3498 case WINED3DRS_STENCILZFAIL
:
3499 case WINED3DRS_STENCILPASS
:
3505 GLint action
= StencilOp(Value
);
3507 glGetIntegerv(GL_STENCIL_FAIL
, &stencilFail
);
3508 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &depthFail
);
3509 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &stencilPass
);
3511 if(WINED3DRS_STENCILFAIL
== State
) {
3512 stencilFail
= action
;
3514 else if(WINED3DRS_STENCILZFAIL
== State
) {
3517 else if(WINED3DRS_STENCILPASS
== State
) {
3518 stencilPass
= action
;
3521 if(!This
->stateBlock
->renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
]) {
3522 #if 0 /* Don't use OpenGL 2.0 calls for now */
3523 if(GL_EXTCALL(glStencilOpSeparate
)) {
3524 GL_EXTCALL(glStencilOpSeparate(GL_FRONT
, stencilFail
, depthFail
, stencilPass
));
3525 checkGLcall("glStencilOpSeparate(GL_FRONT,...)");
3529 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE
)) {
3530 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
3531 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
3532 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT
));
3533 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
3534 glStencilOp(stencilFail
, depthFail
, stencilPass
);
3535 checkGLcall("glStencilOp(...)");
3537 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL
)) {
3538 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT
, stencilFail
, depthFail
, stencilPass
));
3539 checkGLcall("glStencilOpSeparateATI(GL_FRONT,...)");
3541 TRACE("Separate stencil operation not supported on this version of opengl");
3542 glStencilOp(stencilFail
, depthFail
, stencilPass
);
3543 checkGLcall("glStencilOp(...)");
3546 glStencilOp(stencilFail
, depthFail
, stencilPass
);
3547 checkGLcall("glStencilOp(...)");
3551 case WINED3DRS_STENCILWRITEMASK
:
3553 glStencilMask(Value
);
3554 TRACE("glStencilMask(%lu)\n", Value
);
3555 checkGLcall("glStencilMask");
3559 case WINED3DRS_FOGENABLE
:
3561 if (Value
/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
3563 checkGLcall("glEnable GL_FOG");
3566 checkGLcall("glDisable GL_FOG");
3571 case WINED3DRS_RANGEFOGENABLE
:
3574 TRACE("Enabled RANGEFOG");
3576 TRACE("Disabled RANGEFOG");
3581 case WINED3DRS_FOGCOLOR
:
3584 D3DCOLORTOGLFLOAT4(Value
, col
);
3585 /* Set the default alpha blend color */
3586 glFogfv(GL_FOG_COLOR
, &col
[0]);
3587 checkGLcall("glFog GL_FOG_COLOR");
3591 case WINED3DRS_FOGTABLEMODE
:
3593 glHint(GL_FOG_HINT
, GL_NICEST
);
3596 if(This
->stateBlock
->renderState
[WINED3DRS_FOGVERTEXMODE
] == D3DFOG_NONE
) {
3597 glFogi(GL_FOG_MODE
, GL_LINEAR
); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
3599 /* Otherwise leave the vertex fog value */
3602 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3603 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3604 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3606 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value
);
3608 if (GL_SUPPORT(NV_FOG_DISTANCE
)) {
3609 glFogi(GL_FOG_DISTANCE_MODE_NV
, GL_EYE_PLANE_ABSOLUTE_NV
);
3614 case WINED3DRS_FOGVERTEXMODE
:
3616 glHint(GL_FOG_HINT
, GL_FASTEST
);
3617 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, the system will apply only pixel(=table) fog effects." */
3618 if(This
->stateBlock
->renderState
[WINED3DRS_FOGTABLEMODE
] == D3DFOG_NONE
) {
3620 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3621 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3623 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3625 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value
);
3627 if (GL_SUPPORT(NV_FOG_DISTANCE
)) {
3628 glFogi(GL_FOG_DISTANCE_MODE_NV
, This
->stateBlock
->renderState
[WINED3DRS_RANGEFOGENABLE
] ? GL_EYE_RADIAL_NV
: GL_EYE_PLANE_ABSOLUTE_NV
);
3634 case WINED3DRS_FOGSTART
:
3637 glFogfv(GL_FOG_START
, &tmpvalue
.f
);
3638 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3639 TRACE("Fog Start == %f\n", tmpvalue
.f
);
3643 case WINED3DRS_FOGEND
:
3646 glFogfv(GL_FOG_END
, &tmpvalue
.f
);
3647 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3648 TRACE("Fog End == %f\n", tmpvalue
.f
);
3652 case WINED3DRS_FOGDENSITY
:
3655 glFogfv(GL_FOG_DENSITY
, &tmpvalue
.f
);
3656 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3660 case WINED3DRS_VERTEXBLEND
:
3662 This
->updateStateBlock
->vertex_blend
= (D3DVERTEXBLENDFLAGS
) Value
;
3663 TRACE("Vertex Blending state to %ld\n", Value
);
3667 case WINED3DRS_TWEENFACTOR
:
3670 This
->updateStateBlock
->tween_factor
= tmpvalue
.f
;
3671 TRACE("Vertex Blending Tween Factor to %f\n", This
->updateStateBlock
->tween_factor
);
3675 case WINED3DRS_INDEXEDVERTEXBLENDENABLE
:
3677 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL
) Value
);
3681 case WINED3DRS_COLORVERTEX
:
3682 case WINED3DRS_DIFFUSEMATERIALSOURCE
:
3683 case WINED3DRS_SPECULARMATERIALSOURCE
:
3684 case WINED3DRS_AMBIENTMATERIALSOURCE
:
3685 case WINED3DRS_EMISSIVEMATERIALSOURCE
:
3687 GLenum Parm
= GL_AMBIENT_AND_DIFFUSE
;
3689 if (This
->stateBlock
->renderState
[WINED3DRS_COLORVERTEX
]) {
3690 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3691 This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
],
3692 This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
],
3693 This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
],
3694 This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
]);
3696 if (This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3697 if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3698 Parm
= GL_AMBIENT_AND_DIFFUSE
;
3702 } else if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3704 } else if (This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3706 } else if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3713 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
3715 This
->tracking_color
= NEEDS_TRACKING
;
3716 This
->tracking_parm
= Parm
;
3720 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
3725 case WINED3DRS_LINEPATTERN
:
3731 tmppattern
.d
= Value
;
3733 TRACE("Line pattern: repeat %d bits %x\n", tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
3735 if (tmppattern
.lp
.wRepeatFactor
) {
3736 glLineStipple(tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
3737 checkGLcall("glLineStipple(repeat, linepattern)");
3738 glEnable(GL_LINE_STIPPLE
);
3739 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3741 glDisable(GL_LINE_STIPPLE
);
3742 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3747 case WINED3DRS_ZBIAS
: /* D3D8 only */
3751 TRACE("ZBias value %f\n", tmpvalue
.f
);
3752 glPolygonOffset(0, -tmpvalue
.f
);
3753 checkGLcall("glPolygonOffset(0, -Value)");
3754 glEnable(GL_POLYGON_OFFSET_FILL
);
3755 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3756 glEnable(GL_POLYGON_OFFSET_LINE
);
3757 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3758 glEnable(GL_POLYGON_OFFSET_POINT
);
3759 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3761 glDisable(GL_POLYGON_OFFSET_FILL
);
3762 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3763 glDisable(GL_POLYGON_OFFSET_LINE
);
3764 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3765 glDisable(GL_POLYGON_OFFSET_POINT
);
3766 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3771 case WINED3DRS_NORMALIZENORMALS
:
3773 glEnable(GL_NORMALIZE
);
3774 checkGLcall("glEnable(GL_NORMALIZE);");
3776 glDisable(GL_NORMALIZE
);
3777 checkGLcall("glDisable(GL_NORMALIZE);");
3781 case WINED3DRS_POINTSIZE
:
3782 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
3784 TRACE("Set point size to %f\n", tmpvalue
.f
);
3785 glPointSize(tmpvalue
.f
);
3786 checkGLcall("glPointSize(...);");
3789 case WINED3DRS_POINTSIZE_MIN
:
3790 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3792 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MIN_EXT
, tmpvalue
.f
);
3793 checkGLcall("glPointParameterfEXT(...);");
3795 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3799 case WINED3DRS_POINTSIZE_MAX
:
3800 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3802 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MAX_EXT
, tmpvalue
.f
);
3803 checkGLcall("glPointParameterfEXT(...);");
3805 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3809 case WINED3DRS_POINTSCALE_A
:
3810 case WINED3DRS_POINTSCALE_B
:
3811 case WINED3DRS_POINTSCALE_C
:
3812 case WINED3DRS_POINTSCALEENABLE
:
3815 * POINTSCALEENABLE controls how point size value is treated. If set to
3816 * true, the point size is scaled with respect to height of viewport.
3817 * When set to false point size is in pixels.
3819 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
3822 /* Default values */
3823 GLfloat att
[3] = {1.0f
, 0.0f
, 0.0f
};
3826 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
3827 * This means that OpenGL will clamp really small point sizes to 1.0f.
3828 * To correct for this we need to multiply by the scale factor when sizes
3829 * are less than 1.0f. scale_factor = 1.0f / point_size.
3831 GLfloat pointSize
= *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSIZE
]);
3832 if(pointSize
> 0.0f
) {
3833 GLfloat scaleFactor
;
3835 if(pointSize
< 1.0f
) {
3836 scaleFactor
= pointSize
* pointSize
;
3841 if(This
->stateBlock
->renderState
[WINED3DRS_POINTSCALEENABLE
]) {
3842 att
[0] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_A
]) /
3843 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
3844 att
[1] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_B
]) /
3845 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
3846 att
[2] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_C
]) /
3847 (This
->stateBlock
->viewport
.Height
* This
->stateBlock
->viewport
.Height
* scaleFactor
);
3851 if(GL_SUPPORT(ARB_POINT_PARAMETERS
)) {
3852 GL_EXTCALL(glPointParameterfvARB
)(GL_POINT_DISTANCE_ATTENUATION_ARB
, att
);
3853 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
3855 else if(GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3856 GL_EXTCALL(glPointParameterfvEXT
)(GL_DISTANCE_ATTENUATION_EXT
, att
);
3857 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
3859 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
3863 case WINED3DRS_COLORWRITEENABLE
:
3865 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3866 Value
& D3DCOLORWRITEENABLE_RED
? 1 : 0,
3867 Value
& D3DCOLORWRITEENABLE_GREEN
? 1 : 0,
3868 Value
& D3DCOLORWRITEENABLE_BLUE
? 1 : 0,
3869 Value
& D3DCOLORWRITEENABLE_ALPHA
? 1 : 0);
3870 glColorMask(Value
& D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
3871 Value
& D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
3872 Value
& D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
3873 Value
& D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
3874 checkGLcall("glColorMask(...)");
3878 case WINED3DRS_LOCALVIEWER
:
3880 GLint state
= (Value
) ? 1 : 0;
3881 TRACE("Local Viewer Enable to %ul\n", (BOOL
) Value
);
3882 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, state
);
3886 case WINED3DRS_LASTPIXEL
:
3889 TRACE("Last Pixel Drawing Enabled\n");
3891 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3896 case WINED3DRS_SOFTWAREVERTEXPROCESSING
:
3899 TRACE("Software Processing Enabled\n");
3901 TRACE("Software Processing Disabled\n");
3906 /** not supported */
3907 case WINED3DRS_ZVISIBLE
:
3910 return WINED3DERR_INVALIDCALL
;
3912 case WINED3DRS_POINTSPRITEENABLE
:
3914 /* TODO: NV_POINT_SPRITE */
3915 if (!GL_SUPPORT(ARB_POINT_SPRITE
)) {
3916 TRACE("Point sprites not supported\n");
3921 * Point sprites are always enabled. Value controls texture coordinate
3922 * replacement mode. Must be set true for point sprites to use
3925 glEnable(GL_POINT_SPRITE_ARB
);
3926 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
3929 glTexEnvf(GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, TRUE
);
3930 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, TRUE)");
3932 glTexEnvf(GL_POINT_SPRITE_ARB
, GL_COORD_REPLACE_ARB
, FALSE
);
3933 checkGLcall("glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, FALSE)");
3937 case WINED3DRS_EDGEANTIALIAS
:
3940 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
3942 checkGLcall("glEnable(GL_BLEND)");
3943 glEnable(GL_LINE_SMOOTH
);
3944 checkGLcall("glEnable(GL_LINE_SMOOTH)");
3946 glDisable(GL_BLEND
);
3947 checkGLcall("glDisable(GL_BLEND)");
3948 glDisable(GL_LINE_SMOOTH
);
3949 checkGLcall("glDisable(GL_LINE_SMOOTH)");
3953 case WINED3DRS_WRAP0
:
3954 case WINED3DRS_WRAP1
:
3955 case WINED3DRS_WRAP2
:
3956 case WINED3DRS_WRAP3
:
3957 case WINED3DRS_WRAP4
:
3958 case WINED3DRS_WRAP5
:
3959 case WINED3DRS_WRAP6
:
3960 case WINED3DRS_WRAP7
:
3961 case WINED3DRS_WRAP8
:
3962 case WINED3DRS_WRAP9
:
3963 case WINED3DRS_WRAP10
:
3964 case WINED3DRS_WRAP11
:
3965 case WINED3DRS_WRAP12
:
3966 case WINED3DRS_WRAP13
:
3967 case WINED3DRS_WRAP14
:
3968 case WINED3DRS_WRAP15
:
3970 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
3971 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
3972 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
3973 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
3974 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
3976 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
3978 TRACE("(%p)->(%s,%ld) Texture wraping not yet supported\n",This
, debug_d3drenderstate(State
), Value
);
3980 case WINED3DRS_MULTISAMPLEANTIALIAS
:
3982 if (!GL_SUPPORT(ARB_MULTISAMPLE
)) {
3983 TRACE("Multisample antialiasing not supported\n");
3988 glEnable(GL_MULTISAMPLE_ARB
);
3989 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
3991 glDisable(GL_MULTISAMPLE_ARB
);
3992 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
3996 case WINED3DRS_SCISSORTESTENABLE
:
3999 glEnable(GL_SCISSOR_TEST
);
4000 checkGLcall("glEnable(GL_SCISSOR_TEST)");
4002 glDisable(GL_SCISSOR_TEST
);
4003 checkGLcall("glDisable(GL_SCISSOR_TEST)");
4007 case WINED3DRS_SLOPESCALEDEPTHBIAS
:
4011 glEnable(GL_POLYGON_OFFSET_FILL
);
4012 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4013 glPolygonOffset(tmpvalue
.f
, *((float*)&This
->stateBlock
->renderState
[WINED3DRS_DEPTHBIAS
]));
4014 checkGLcall("glPolygonOffset(...)");
4016 glDisable(GL_POLYGON_OFFSET_FILL
);
4017 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4021 case WINED3DRS_ANTIALIASEDLINEENABLE
:
4024 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
4026 checkGLcall("glEnable(GL_BLEND)");
4027 glEnable(GL_LINE_SMOOTH
);
4028 checkGLcall("glEnable(GL_LINE_SMOOTH)");
4030 glDisable(GL_BLEND
);
4031 checkGLcall("glDisable(GL_BLEND)");
4032 glDisable(GL_LINE_SMOOTH
);
4033 checkGLcall("glDisable(GL_LINE_SMOOTH)");
4037 case WINED3DRS_TWOSIDEDSTENCILMODE
:
4040 TRACE("Two-sided stencil mode enabled\n");
4042 TRACE("Two-sided stencil mode disabled\n");
4046 case WINED3DRS_CCW_STENCILFAIL
:
4047 case WINED3DRS_CCW_STENCILZFAIL
:
4048 case WINED3DRS_CCW_STENCILPASS
:
4054 GLint action
= StencilOp(Value
);
4056 glGetIntegerv(GL_STENCIL_BACK_FAIL
, &stencilFail
);
4057 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL
, &depthFail
);
4058 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS
, &stencilPass
);
4060 if(WINED3DRS_CCW_STENCILFAIL
== State
) {
4061 stencilFail
= action
;
4063 else if(WINED3DRS_CCW_STENCILZFAIL
== State
) {
4066 else if(WINED3DRS_CCW_STENCILPASS
== State
) {
4067 stencilPass
= action
;
4070 if(!This
->stateBlock
->renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
]) {
4071 #if 0 /* Don't use OpenGL 2.0 calls for now */
4072 if(GL_EXTCALL(glStencilOpSeparate
)) {
4073 GL_EXTCALL(glStencilOpSeparate(GL_BACK
, stencilFail
, depthFail
, stencilPass
));
4074 checkGLcall("glStencilOpSeparate(GL_BACK,...)");
4078 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE
)) {
4079 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
4080 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4081 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK
));
4082 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4083 glStencilOp(stencilFail
, depthFail
, stencilPass
);
4084 checkGLcall("glStencilOp(...)");
4086 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL
)) {
4087 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK
, stencilFail
, depthFail
, stencilPass
));
4088 checkGLcall("glStencilOpSeparateATI(GL_BACK,...)");
4090 TRACE("Separate stencil operation not supported on this version of opengl");
4091 glStencilOp(stencilFail
, depthFail
, stencilPass
);
4092 checkGLcall("glStencilOp(...)");
4095 glStencilOp(stencilFail
, depthFail
, stencilPass
);
4096 checkGLcall("glStencilOp(...)");
4100 case WINED3DRS_CCW_STENCILFUNC
:
4103 GLint ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
4104 GLuint mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
4107 switch ((D3DCMPFUNC
)Value
) {
4108 case D3DCMP_NEVER
: func
= GL_NEVER
; break;
4109 case D3DCMP_LESS
: func
= GL_LESS
; break;
4110 case D3DCMP_EQUAL
: func
= GL_EQUAL
; break;
4111 case D3DCMP_LESSEQUAL
: func
= GL_LEQUAL
; break;
4112 case D3DCMP_GREATER
: func
= GL_GREATER
; break;
4113 case D3DCMP_NOTEQUAL
: func
= GL_NOTEQUAL
; break;
4114 case D3DCMP_GREATEREQUAL
: func
= GL_GEQUAL
; break;
4115 case D3DCMP_ALWAYS
: func
= GL_ALWAYS
; break;
4117 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
4119 This
->stencilfunc
= func
;
4120 if(!This
->stateBlock
->renderState
[WINED3DRS_TWOSIDEDSTENCILMODE
]) {
4121 #if 0 /* Don't use OpenGL 2.0 calls for now */
4122 if(GL_EXTCALL(glStencilFuncSeparate
)) {
4123 GL_EXTCALL(glStencilFuncSeparate(GL_BACK
, func
, ref
, mask
));
4124 checkGLcall("glStencilFuncSeparate(GL_BACK,...)");
4128 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE
)) {
4129 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
4130 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
4131 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK
));
4132 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
4133 glStencilFunc(func
, ref
, mask
);
4134 checkGLcall("glStencilFunc(...)");
4136 else if(GL_SUPPORT(ATI_SEPARATE_STENCIL
)) {
4137 GL_EXTCALL(glStencilFuncSeparateATI(GL_BACK
, func
, ref
, mask
));
4138 checkGLcall("glStencilFuncSeparateATI(GL_BACK,...)");
4140 TRACE("Separate stencil function not supported on this version of opengl");
4141 glStencilFunc(func
, ref
, mask
);
4142 checkGLcall("glStencilFunc(...)");
4145 glStencilFunc(func
, ref
, mask
);
4146 checkGLcall("glStencilFunc(...)");
4150 case WINED3DRS_DEPTHBIAS
:
4154 glEnable(GL_POLYGON_OFFSET_FILL
);
4155 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
4156 glPolygonOffset(*((float*)&This
->stateBlock
->renderState
[WINED3DRS_SLOPESCALEDEPTHBIAS
]), tmpvalue
.f
);
4157 checkGLcall("glPolygonOffset(...)");
4159 glDisable(GL_POLYGON_OFFSET_FILL
);
4160 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
4165 case WINED3DRS_TEXTUREPERSPECTIVE
:
4168 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_NICEST
);
4170 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
4174 case WINED3DRS_STIPPLEDALPHA
:
4177 ERR(" Stippled Alpha not supported yet.\n");
4180 case WINED3DRS_ANTIALIAS
:
4183 ERR(" Antialias not supported yet.\n");
4187 FIXME("(%p)->(%s,%ld) not handled yet\n", This
, debug_d3drenderstate(State
), Value
);
4195 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD
*pValue
) {
4196 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4197 TRACE("(%p) for State %d = %ld\n", This
, State
, This
->stateBlock
->renderState
[State
]);
4198 *pValue
= This
->stateBlock
->renderState
[State
];
4203 * Get / Set Sampler States
4204 * TODO: Verify against dx9 definitions
4207 HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
4208 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4210 * SetSampler is designed to allow for more than the standard up to 8 textures
4211 * and Geforce has stopped supporting more than 6 standard textures in openGL.
4212 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
4214 * http://developer.nvidia.com/object/General_FAQ.html#t6
4216 * There are two new settings for GForce
4218 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
4219 * and the texture one:
4220 * GL_MAX_TEXTURE_COORDS_ARB.
4221 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
4223 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
4224 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This
, Sampler
,Type
, Value
);
4226 if(Sampler
> GL_LIMITS(samplers
) || Sampler
< 0 || Type
> WINED3D_HIGHEST_SAMPLER_STATE
|| Type
< 0) {
4227 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers
), WINED3D_HIGHEST_SAMPLER_STATE
, Sampler
, Type
);
4228 return WINED3DERR_INVALIDCALL
;
4230 TRACE("Setting sampler %ld %d to %ld\n", Sampler
, Type
, Value
);
4231 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
4232 This
->updateStateBlock
->set
.samplerState
[Sampler
][Type
] = Value
;
4233 This
->updateStateBlock
->changed
.samplerState
[Sampler
][Type
] = Value
;
4235 /* Handle recording of state blocks */
4236 if (This
->isRecordingState
) {
4237 TRACE("Recording... not performing anything\n");
4244 HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
4245 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4246 /** TODO: check that sampler is in range **/
4247 *Value
= This
->updateStateBlock
->samplerState
[Sampler
][Type
];
4248 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This
, Sampler
, Type
, *Value
);
4253 HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
4254 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4257 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4258 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
4259 glScissor(pRect
->left
, pRect
->top
, pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
);
4265 HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
4266 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4267 GLint scissorBox
[4];
4270 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
4271 glGetIntegerv(GL_SCISSOR_BOX
, scissorBox
);
4272 pRect
->left
= scissorBox
[1];
4273 pRect
->top
= scissorBox
[2];
4274 pRect
->right
= scissorBox
[1] + scissorBox
[3];
4275 pRect
->bottom
= scissorBox
[2] + scissorBox
[4];
4276 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
4281 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
4282 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4283 IWineD3DVertexDeclaration
*oldDecl
= This
->updateStateBlock
->vertexDecl
;
4285 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
4287 This
->updateStateBlock
->vertexDecl
= pDecl
;
4288 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
4289 This
->updateStateBlock
->set
.vertexDecl
= TRUE
;
4291 if (This
->isRecordingState
) {
4292 TRACE("Recording... not performing anything\n");
4295 if (NULL
!= pDecl
) {
4296 IWineD3DVertexDeclaration_AddRef(pDecl
);
4298 if (NULL
!= oldDecl
) {
4299 IWineD3DVertexDeclaration_Release(oldDecl
);
4304 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
4305 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4307 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
4309 *ppDecl
= This
->stateBlock
->vertexDecl
;
4310 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
4314 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
4315 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4316 IWineD3DVertexShader
* oldShader
= This
->updateStateBlock
->vertexShader
;
4318 This
->updateStateBlock
->vertexShader
= pShader
;
4319 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
4320 This
->updateStateBlock
->set
.vertexShader
= TRUE
;
4322 if (This
->isRecordingState
) {
4323 TRACE("Recording... not performing anything\n");
4326 if (NULL
!= pShader
) {
4327 IWineD3DVertexShader_AddRef(pShader
);
4329 if (NULL
!= oldShader
) {
4330 IWineD3DVertexShader_Release(oldShader
);
4333 if (pShader
!= NULL
&& ((IWineD3DVertexShaderImpl
*)pShader
)->vertexDeclaration
!= NULL
) {
4334 TRACE("(%p) : setting vertexDeclaration(%p)\n", This
, ((IWineD3DVertexShaderImpl
*)pShader
)->vertexDeclaration
);
4335 IWineD3DDevice_SetVertexDeclaration(iface
, ((IWineD3DVertexShaderImpl
*)pShader
)->vertexDeclaration
);
4338 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
4340 * TODO: merge HAL shaders context switching from prototype
4345 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
4346 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4348 if (NULL
== ppShader
) {
4349 return WINED3DERR_INVALIDCALL
;
4351 *ppShader
= This
->stateBlock
->vertexShader
;
4352 if( NULL
!= *ppShader
)
4353 IWineD3DVertexShader_AddRef(*ppShader
);
4355 TRACE("(%p) : returning %p\n", This
, *ppShader
);
4359 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstant(IWineD3DDevice
*iface
, void *dstData
, const void *srcData
, UINT type
, UINT start
, UINT count
, UINT registersize
) {
4360 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4363 int cnt
= min(count
, MAX_VSHADER_CONSTANTS
- (start
+ 1));
4365 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4366 iface
, dstData
, srcData
, type
, start
, count
, registersize
);
4368 if (type
!= WINESHADERCNST_NONE
) {
4369 if (srcData
== NULL
|| cnt
< 0) {
4370 return WINED3DERR_INVALIDCALL
;
4373 CopyMemory((char *)dstData
+ (start
* registersize
), srcData
, cnt
* registersize
);
4376 for (i
= start
; i
< cnt
+ start
; ++i
) {
4377 This
->updateStateBlock
->changed
.vertexShaderConstants
[i
] = TRUE
;
4378 This
->updateStateBlock
->set
.vertexShaderConstants
[i
] = TRUE
;
4379 This
->updateStateBlock
->vertexShaderConstantT
[i
] = type
;
4385 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstant(IWineD3DDevice
*iface
, void *dstData
, const void *srcData
, UINT type
, UINT start
, UINT count
, UINT registersize
) {
4386 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4389 int cnt
= min(count
, MAX_VSHADER_CONSTANTS
- (start
+ 1));
4391 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4392 iface
, dstData
, srcData
, type
, start
, count
, registersize
);
4394 /* Verify that the requested shader constant was populated with the correct type */
4395 for (i
= start
; i
< cnt
+ start
; ++i
) {
4396 if (This
->updateStateBlock
->vertexShaderConstantT
[i
] != type
) {
4397 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4398 This
, type
, This
->updateStateBlock
->vertexShaderConstantT
[i
]);
4399 return WINED3DERR_INVALIDCALL
;
4403 if (dstData
== NULL
|| cnt
< 0) {
4404 return WINED3DERR_INVALIDCALL
;
4407 CopyMemory(dstData
, (char *)srcData
+ (start
* registersize
), cnt
* registersize
);
4412 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
){
4413 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4415 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface
,
4416 This
->updateStateBlock
->vertexShaderConstantB
,
4418 WINESHADERCNST_BOOL
,
4421 sizeof(*pConstantData
));
4424 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
){
4425 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4427 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface
,
4429 This
->updateStateBlock
->vertexShaderConstantB
,
4430 WINESHADERCNST_BOOL
,
4433 sizeof(*pConstantData
));
4436 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
){
4437 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4439 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface
,
4440 This
->updateStateBlock
->vertexShaderConstantI
,
4442 WINESHADERCNST_INTEGER
,
4445 4 * sizeof(*pConstantData
));
4448 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
){
4449 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4451 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface
,
4453 This
->updateStateBlock
->vertexShaderConstantI
,
4454 WINESHADERCNST_INTEGER
,
4457 4 * sizeof(*pConstantData
));
4461 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
float *pConstantData
, UINT Vector4fCount
){
4462 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4464 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface
,
4465 This
->updateStateBlock
->vertexShaderConstantF
,
4467 WINESHADERCNST_FLOAT
,
4470 4 * sizeof(*pConstantData
));
4473 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, float *pConstantData
, UINT Vector4fCount
){
4474 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4476 return IWineD3DDeviceImpl_GetVertexShaderConstant(iface
,
4478 This
->updateStateBlock
->vertexShaderConstantF
,
4479 WINESHADERCNST_FLOAT
,
4482 4 * sizeof(*pConstantData
));
4485 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantN(IWineD3DDevice
*iface
, UINT StartRegister
, UINT VectorNCount
){
4486 return IWineD3DDeviceImpl_SetVertexShaderConstant(iface
,
4489 WINESHADERCNST_NONE
,
4495 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
4496 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4497 IWineD3DPixelShader
*oldShader
= This
->updateStateBlock
->pixelShader
;
4498 This
->updateStateBlock
->pixelShader
= pShader
;
4499 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
4500 This
->updateStateBlock
->set
.pixelShader
= TRUE
;
4502 /* Handle recording of state blocks */
4503 if (This
->isRecordingState
) {
4504 TRACE("Recording... not performing anything\n");
4507 if (NULL
!= pShader
) {
4508 IWineD3DPixelShader_AddRef(pShader
);
4510 if (NULL
!= oldShader
) {
4511 IWineD3DPixelShader_Release(oldShader
);
4514 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
4516 * TODO: merge HAL shaders context switching from prototype
4521 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
4522 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4524 if (NULL
== ppShader
) {
4525 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This
);
4526 return WINED3DERR_INVALIDCALL
;
4529 *ppShader
= This
->stateBlock
->pixelShader
;
4530 if (NULL
!= *ppShader
) {
4531 IWineD3DPixelShader_AddRef(*ppShader
);
4533 TRACE("(%p) : returning %p\n", This
, *ppShader
);
4537 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstant(IWineD3DDevice
*iface
, void *dstData
, const void *srcData
, UINT type
, UINT start
, UINT count
, UINT registersize
) {
4538 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4541 int cnt
= min(count
, MAX_PSHADER_CONSTANTS
- (start
+ 1));
4543 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4544 iface
, dstData
, srcData
, type
, start
, count
, registersize
);
4546 if (type
!= WINESHADERCNST_NONE
) {
4547 if (srcData
== NULL
|| cnt
< 0) {
4548 return WINED3DERR_INVALIDCALL
;
4551 CopyMemory((char *)dstData
+ (start
* registersize
), srcData
, cnt
* registersize
);
4554 for (i
= start
; i
< cnt
+ start
; ++i
) {
4555 This
->updateStateBlock
->changed
.pixelShaderConstants
[i
] = TRUE
;
4556 This
->updateStateBlock
->set
.pixelShaderConstants
[i
] = TRUE
;
4557 This
->updateStateBlock
->pixelShaderConstantT
[i
] = type
;
4563 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstant(IWineD3DDevice
*iface
, void *dstData
, const void *srcData
, UINT type
, UINT start
, UINT count
, UINT registersize
) {
4564 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4567 int cnt
= min(count
, MAX_PSHADER_CONSTANTS
- (start
+ 1));
4569 TRACE("(iface %p, dstData %p, srcData %p, type %d, start %d, count %d, registersize %d)\n",
4570 iface
, dstData
, srcData
, type
, start
, count
, registersize
);
4572 /* Verify that the requested shader constant was populated with the correct type */
4573 for (i
= start
; i
< cnt
+ start
; ++i
) {
4574 if (This
->updateStateBlock
->pixelShaderConstantT
[i
] != type
) {
4575 TRACE("(%p) : Caller requested 0x%x while type is 0x%x. Returning WINED3DERR_INVALIDCALL\n",
4576 This
, type
, This
->updateStateBlock
->pixelShaderConstantT
[i
]);
4577 return WINED3DERR_INVALIDCALL
;
4581 if (dstData
== NULL
|| cnt
< 0) {
4582 return WINED3DERR_INVALIDCALL
;
4585 CopyMemory(dstData
, (char *)srcData
+ (start
* registersize
), cnt
* registersize
);
4590 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
) {
4591 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4593 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface
,
4594 This
->updateStateBlock
->pixelShaderConstantB
,
4596 WINESHADERCNST_BOOL
,
4599 sizeof(*pConstantData
));
4602 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
) {
4603 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4605 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface
,
4607 This
->updateStateBlock
->pixelShaderConstantB
,
4608 WINESHADERCNST_BOOL
,
4611 sizeof(*pConstantData
));
4614 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
) {
4615 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4617 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface
,
4618 This
->updateStateBlock
->pixelShaderConstantI
,
4620 WINESHADERCNST_INTEGER
,
4623 4 * sizeof(*pConstantData
));
4626 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
) {
4627 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4629 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface
,
4631 This
->updateStateBlock
->pixelShaderConstantI
,
4632 WINESHADERCNST_INTEGER
,
4635 4 * sizeof(*pConstantData
));
4638 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
float *pConstantData
, UINT Vector4fCount
) {
4639 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4641 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface
,
4642 This
->updateStateBlock
->pixelShaderConstantF
,
4644 WINESHADERCNST_FLOAT
,
4647 4 * sizeof(*pConstantData
));
4650 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, float *pConstantData
, UINT Vector4fCount
) {
4651 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4653 return IWineD3DDeviceImpl_GetPixelShaderConstant(iface
,
4655 This
->updateStateBlock
->pixelShaderConstantF
,
4656 WINESHADERCNST_FLOAT
,
4659 4 * sizeof(*pConstantData
));
4662 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantN(IWineD3DDevice
*iface
, UINT StartRegister
, UINT VectorNCount
){
4663 return IWineD3DDeviceImpl_SetPixelShaderConstant(iface
,
4666 WINESHADERCNST_NONE
,
4672 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4674 process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
, WineDirect3DVertexStridedData
*lpStrideData
, DWORD SrcFVF
, IWineD3DVertexBufferImpl
*dest
, DWORD dwFlags
) {
4677 DWORD DestFVF
= dest
->fvf
;
4679 D3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
4683 if (SrcFVF
& D3DFVF_NORMAL
) {
4684 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4687 if ( (SrcFVF
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) {
4688 ERR("Source has no position mask\n");
4689 return WINED3DERR_INVALIDCALL
;
4692 if (dest
->resource
.allocatedMemory
== NULL
) {
4693 ERR("Destination buffer has no memory allocated\n");
4694 return WINED3DERR_INVALIDCALL
;
4698 * a) D3DRS_CLIPPING is enabled
4699 * b) WINED3DVOP_CLIP is passed
4701 if(This
->stateBlock
->renderState
[WINED3DRS_CLIPPING
]) {
4702 static BOOL warned
= FALSE
;
4704 * The clipping code is not quite correct. Some things need
4705 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4706 * so disable clipping for now.
4707 * (The graphics in Half-Life are broken, and my processvertices
4708 * test crashes with IDirect3DDevice3)
4714 FIXME("Clipping is broken and disabled for now\n");
4716 } else doClip
= FALSE
;
4717 dest_ptr
= ((char *) dest
->resource
.allocatedMemory
) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
4719 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4722 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4725 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4726 D3DTS_WORLDMATRIX(0),
4729 TRACE("View mat: \n");
4730 TRACE("%f %f %f %f\n", view_mat
.u
.s
._11
, view_mat
.u
.s
._12
, view_mat
.u
.s
._13
, view_mat
.u
.s
._14
); \
4731 TRACE("%f %f %f %f\n", view_mat
.u
.s
._21
, view_mat
.u
.s
._22
, view_mat
.u
.s
._23
, view_mat
.u
.s
._24
); \
4732 TRACE("%f %f %f %f\n", view_mat
.u
.s
._31
, view_mat
.u
.s
._32
, view_mat
.u
.s
._33
, view_mat
.u
.s
._34
); \
4733 TRACE("%f %f %f %f\n", view_mat
.u
.s
._41
, view_mat
.u
.s
._42
, view_mat
.u
.s
._43
, view_mat
.u
.s
._44
); \
4735 TRACE("Proj mat: \n");
4736 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._11
, proj_mat
.u
.s
._12
, proj_mat
.u
.s
._13
, proj_mat
.u
.s
._14
); \
4737 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._21
, proj_mat
.u
.s
._22
, proj_mat
.u
.s
._23
, proj_mat
.u
.s
._24
); \
4738 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._31
, proj_mat
.u
.s
._32
, proj_mat
.u
.s
._33
, proj_mat
.u
.s
._34
); \
4739 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._41
, proj_mat
.u
.s
._42
, proj_mat
.u
.s
._43
, proj_mat
.u
.s
._44
); \
4741 TRACE("World mat: \n");
4742 TRACE("%f %f %f %f\n", world_mat
.u
.s
._11
, world_mat
.u
.s
._12
, world_mat
.u
.s
._13
, world_mat
.u
.s
._14
); \
4743 TRACE("%f %f %f %f\n", world_mat
.u
.s
._21
, world_mat
.u
.s
._22
, world_mat
.u
.s
._23
, world_mat
.u
.s
._24
); \
4744 TRACE("%f %f %f %f\n", world_mat
.u
.s
._31
, world_mat
.u
.s
._32
, world_mat
.u
.s
._33
, world_mat
.u
.s
._34
); \
4745 TRACE("%f %f %f %f\n", world_mat
.u
.s
._41
, world_mat
.u
.s
._42
, world_mat
.u
.s
._43
, world_mat
.u
.s
._44
); \
4747 /* Get the viewport */
4748 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
4749 TRACE("Viewport: X=%ld, Y=%ld, Width=%ld, Height=%ld, MinZ=%f, MaxZ=%f\n",
4750 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
4752 multiply_matrix(&mat
,&view_mat
,&world_mat
);
4753 multiply_matrix(&mat
,&proj_mat
,&mat
);
4755 numTextures
= (DestFVF
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
;
4757 for (i
= 0; i
< dwCount
; i
+= 1) {
4758 unsigned int tex_index
;
4760 if ( ((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
4761 ((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) ) {
4762 /* The position first */
4764 (float *) (((char *) lpStrideData
->u
.s
.position
.lpData
) + i
* lpStrideData
->u
.s
.position
.dwStride
);
4766 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
4768 /* Multiplication with world, view and projection matrix */
4769 x
= (p
[0] * mat
.u
.s
._11
) + (p
[1] * mat
.u
.s
._21
) + (p
[2] * mat
.u
.s
._31
) + (1.0 * mat
.u
.s
._41
);
4770 y
= (p
[0] * mat
.u
.s
._12
) + (p
[1] * mat
.u
.s
._22
) + (p
[2] * mat
.u
.s
._32
) + (1.0 * mat
.u
.s
._42
);
4771 z
= (p
[0] * mat
.u
.s
._13
) + (p
[1] * mat
.u
.s
._23
) + (p
[2] * mat
.u
.s
._33
) + (1.0 * mat
.u
.s
._43
);
4772 rhw
= (p
[0] * mat
.u
.s
._14
) + (p
[1] * mat
.u
.s
._24
) + (p
[2] * mat
.u
.s
._34
) + (1.0 * mat
.u
.s
._44
);
4774 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
4776 /* WARNING: The following things are taken from d3d7 and were not yet checked
4777 * against d3d8 or d3d9!
4780 /* Clipping conditions: From
4781 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
4783 * A vertex is clipped if it does not match the following requirements
4787 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4789 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4790 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4794 if( doClip
== FALSE
||
4795 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
4796 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
4799 /* "Normal" viewport transformation (not clipped)
4800 * 1) The values are divided trough rhw
4801 * 2) The y axis is negative, so multiply it with -1
4802 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4803 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4804 * 4) Multiply x with Width/2 and add Width/2
4805 * 5) The same for the height
4806 * 6) Add the viewpoint X and Y to the 2D coordinates and
4807 * The minimum Z value to z
4808 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4810 * Well, basically it's simply a linear transformation into viewport
4822 z
*= vp
.MaxZ
- vp
.MinZ
;
4824 x
+= vp
.Width
/ 2 + vp
.X
;
4825 y
+= vp
.Height
/ 2 + vp
.Y
;
4830 /* That vertex got clipped
4831 * Contrary to OpenGL it is not dropped completely, it just
4832 * undergoes a different calculation.
4834 TRACE("Vertex got clipped\n");
4841 /* Msdn mentiones that Direct3D9 keeps a list of clipped vertices
4842 * outside of the main vertex buffer memory. That needs some more
4847 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
4850 ( (float *) dest_ptr
)[0] = x
;
4851 ( (float *) dest_ptr
)[1] = y
;
4852 ( (float *) dest_ptr
)[2] = z
;
4853 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
4855 dest_ptr
+= 3 * sizeof(float);
4857 if((DestFVF
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
4858 dest_ptr
+= sizeof(float);
4861 if (DestFVF
& D3DFVF_PSIZE
) {
4862 dest_ptr
+= sizeof(DWORD
);
4864 if (DestFVF
& D3DFVF_NORMAL
) {
4866 (float *) (((float *) lpStrideData
->u
.s
.normal
.lpData
) + i
* lpStrideData
->u
.s
.normal
.dwStride
);
4867 /* AFAIK this should go into the lighting information */
4868 FIXME("Didn't expect the destination to have a normal\n");
4869 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
4872 if (DestFVF
& D3DFVF_DIFFUSE
) {
4874 (DWORD
*) (((char *) lpStrideData
->u
.s
.diffuse
.lpData
) + i
* lpStrideData
->u
.s
.diffuse
.dwStride
);
4876 static BOOL warned
= FALSE
;
4878 if(warned
== FALSE
) {
4879 ERR("No diffuse color in source, but destination has one\n");
4883 *( (DWORD
*) dest_ptr
) = 0xffffffff;
4884 dest_ptr
+= sizeof(DWORD
);
4887 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
4890 if (DestFVF
& D3DFVF_SPECULAR
) {
4891 /* What's the color value in the feedback buffer? */
4893 (DWORD
*) (((char *) lpStrideData
->u
.s
.specular
.lpData
) + i
* lpStrideData
->u
.s
.specular
.dwStride
);
4895 static BOOL warned
= FALSE
;
4897 if(warned
== FALSE
) {
4898 ERR("No specular color in source, but destination has one\n");
4902 *( (DWORD
*) dest_ptr
) = 0xFF000000;
4903 dest_ptr
+= sizeof(DWORD
);
4906 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
4910 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
4912 (float *) (((char *) lpStrideData
->u
.s
.texCoords
[tex_index
].lpData
) +
4913 i
* lpStrideData
->u
.s
.texCoords
[tex_index
].dwStride
);
4915 ERR("No source texture, but destination requests one\n");
4916 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4919 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4926 #undef copy_and_next
4928 HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, IWineD3DVertexBuffer
* pDestBuffer
, IWineD3DVertexBuffer
* pVertexDecl
, DWORD Flags
) {
4929 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4930 IWineD3DVertexBufferImpl
*SrcImpl
= (IWineD3DVertexBufferImpl
*) pVertexDecl
;
4931 WineDirect3DVertexStridedData strided
;
4933 TRACE("(%p)->(%d,%d,%d,%p,%p,%ld\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, Flags
);
4935 hr
= IWineD3DDevice_SetFVF(iface
, SrcImpl
->fvf
);
4936 hr
= IWineD3DDevice_SetStreamSource(iface
, 0, pVertexDecl
, get_flexible_vertex_size(SrcImpl
->fvf
) * SrcStartIndex
, get_flexible_vertex_size(SrcImpl
->fvf
));
4938 memset(&strided
, 0, sizeof(strided
));
4939 primitiveConvertToStridedData(iface
, &strided
, 0);
4941 return process_vertices_strided(This
, DestIndex
, VertexCount
, &strided
, SrcImpl
->fvf
, (IWineD3DVertexBufferImpl
*) pDestBuffer
, Flags
);
4945 * Apply / Get / Set Texture Stage States
4946 * TODO: Verify against dx9 definitions
4949 /* NOTE: It's expected that this function is going to be called lots of times with the same stage active, so make it the callers responsibility to GLACTIVETEXTURE(Stage) for better state management. Set the correct Texture unit active before calling ApplyTextureStageState */
4950 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
) {
4951 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4952 DWORD Value
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4953 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4955 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
4957 /* Check that the stage is within limits */
4958 if (Stage
>= GL_LIMITS(textures
) || Stage
< 0) {
4959 TRACE("Attempt to access invalid texture rejected\n");
4966 case WINED3DTSS_ALPHAOP
:
4967 case WINED3DTSS_COLOROP
:
4968 /* nothing to do as moved to drawprim for now */
4970 case WINED3DTSS_ADDRESSW
:
4971 #if 0 /* I'm not sure what D3D does about ADDRESSW appearing twice */
4972 if (Value
< minLookup
[WINELOOKUP_WARPPARAM
] || Value
> maxLookup
[WINELOOKUP_WARPPARAM
]) {
4973 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value
, Type
);
4976 GLint wrapParm
= stateLookup
[WINELOOKUP_WARPPARAM
][Value
- minLookup
[WINELOOKUP_WARPPARAM
]];
4977 TRACE("Setting WRAP_R to %d for %x\n", wrapParm
, This
->stateBlock
->textureDimensions
[Stage
]);
4978 glTexParameteri(This
->stateBlock
->textureDimensions
[Stage
], GL_TEXTURE_WRAP_R
, wrapParm
);
4979 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
4982 case WINED3DTSS_TEXCOORDINDEX
:
4984 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
4986 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
4987 one flag, you can still specify an index value, which the system uses to
4988 determine the texture wrapping mode.
4989 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
4990 means use the vertex position (camera-space) as the input texture coordinates
4991 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
4992 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
4993 to the TEXCOORDINDEX value */
4996 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
4998 switch (Value
& 0xFFFF0000) {
4999 case D3DTSS_TCI_PASSTHRU
:
5000 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
5001 glDisable(GL_TEXTURE_GEN_S
);
5002 glDisable(GL_TEXTURE_GEN_T
);
5003 glDisable(GL_TEXTURE_GEN_R
);
5004 glDisable(GL_TEXTURE_GEN_Q
);
5005 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
5008 case D3DTSS_TCI_CAMERASPACEPOSITION
:
5009 /* CameraSpacePosition means use the vertex position, transformed to camera space,
5010 as the input texture coordinates for this stage's texture transformation. This
5011 equates roughly to EYE_LINEAR */
5013 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5014 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5015 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5016 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5017 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
5019 glMatrixMode(GL_MODELVIEW
);
5022 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5023 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5024 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5025 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5028 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
5029 glEnable(GL_TEXTURE_GEN_S
);
5030 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5031 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5032 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5033 glEnable(GL_TEXTURE_GEN_T
);
5034 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5035 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5036 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5037 glEnable(GL_TEXTURE_GEN_R
);
5038 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5039 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
5040 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
5044 case D3DTSS_TCI_CAMERASPACENORMAL
:
5046 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
5047 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5048 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5049 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5050 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5051 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
5053 glMatrixMode(GL_MODELVIEW
);
5056 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5057 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5058 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5059 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5062 glEnable(GL_TEXTURE_GEN_S
);
5063 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5064 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5065 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5066 glEnable(GL_TEXTURE_GEN_T
);
5067 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5068 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5069 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5070 glEnable(GL_TEXTURE_GEN_R
);
5071 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5072 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
5073 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
5078 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
:
5080 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
5081 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
5082 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
5083 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
5084 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
5085 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
5087 glMatrixMode(GL_MODELVIEW
);
5090 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
5091 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
5092 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
5093 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
5096 glEnable(GL_TEXTURE_GEN_S
);
5097 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
5098 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5099 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5100 glEnable(GL_TEXTURE_GEN_T
);
5101 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
5102 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5103 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5104 glEnable(GL_TEXTURE_GEN_R
);
5105 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
5106 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
5107 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
5112 /* Unhandled types: */
5115 /* ? disable GL_TEXTURE_GEN_n ? */
5116 glDisable(GL_TEXTURE_GEN_S
);
5117 glDisable(GL_TEXTURE_GEN_T
);
5118 glDisable(GL_TEXTURE_GEN_R
);
5119 glDisable(GL_TEXTURE_GEN_Q
);
5120 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value
);
5127 case WINED3DTSS_TEXTURETRANSFORMFLAGS
:
5128 set_texture_matrix((float *)&This
->stateBlock
->transforms
[D3DTS_TEXTURE0
+ Stage
].u
.m
[0][0], Value
, (This
->stateBlock
->textureState
[Stage
][WINED3DTSS_TEXCOORDINDEX
] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
);
5131 case WINED3DTSS_BUMPENVMAT00
:
5132 case WINED3DTSS_BUMPENVMAT01
:
5133 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT00
, Stage
, Type
, Value
);
5135 case WINED3DTSS_BUMPENVMAT10
:
5136 case WINED3DTSS_BUMPENVMAT11
:
5137 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT10
, Stage
, Type
, Value
);
5140 case WINED3DTSS_BUMPENVLSCALE
:
5141 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5144 case WINED3DTSS_BUMPENVLOFFSET
:
5145 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5148 case WINED3DTSS_RESULTARG
:
5149 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5153 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
5154 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
5163 * Get / Set Texture Stage States
5164 * TODO: Verify against dx9 definitions
5166 HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
5167 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5169 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
5171 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
5173 /* Reject invalid texture units */
5174 if (Stage
>= GL_LIMITS(textures
)) {
5175 TRACE("Attempt to access invalid texture rejected\n");
5176 return WINED3DERR_INVALIDCALL
;
5179 This
->updateStateBlock
->changed
.textureState
[Stage
][Type
] = TRUE
;
5180 This
->updateStateBlock
->set
.textureState
[Stage
][Type
] = TRUE
;
5181 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
5186 HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
5187 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5188 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
5189 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
5196 HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
* pTexture
) {
5198 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5199 IWineD3DBaseTexture
*oldTexture
;
5201 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
5202 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This
, Stage
, pTexture
);
5204 #if 0 /* TODO: check so vertex textures */
5205 if (Stage
>= D3DVERTEXTEXTURESAMPLER
&& Stage
<= D3DVERTEXTEXTURESAMPLER3
){
5206 This
->updateStateBlock
->vertexTextures
[Stage
- D3DVERTEXTEXTURESAMPLER
] = pTexture
;
5211 /* Reject invalid texture units */
5212 if (Stage
>= GL_LIMITS(textures
) || Stage
< 0) {
5213 WARN("Attempt to access invalid texture rejected\n");
5214 return WINED3DERR_INVALIDCALL
;
5217 if(pTexture
!= NULL
) {
5218 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
5220 if(((IWineD3DTextureImpl
*)pTexture
)->resource
.pool
== WINED3DPOOL_SCRATCH
) {
5221 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture
);
5222 return WINED3DERR_INVALIDCALL
;
5226 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
5227 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures
));
5228 TRACE("(%p) : oldtexture(%p)\n", This
,oldTexture
);
5230 This
->updateStateBlock
->set
.textures
[Stage
] = TRUE
;
5231 This
->updateStateBlock
->changed
.textures
[Stage
] = TRUE
;
5232 TRACE("(%p) : setting new texture to %p\n", This
, pTexture
);
5233 This
->updateStateBlock
->textures
[Stage
] = pTexture
;
5235 /* Handle recording of state blocks */
5236 if (This
->isRecordingState
) {
5237 TRACE("Recording... not performing anything\n");
5241 /** NOTE: MSDN says that setTexture increases the reference count,
5242 * and the the application nust set the texture back to null (or have a leaky application),
5243 * This means we should pass the refcount up to the parent
5244 *******************************/
5245 if (NULL
!= This
->updateStateBlock
->textures
[Stage
]) {
5246 IWineD3DBaseTexture_AddRef(This
->updateStateBlock
->textures
[Stage
]);
5249 if (NULL
!= oldTexture
) {
5250 IWineD3DBaseTexture_Release(oldTexture
);
5253 /* Reset color keying */
5254 if(Stage
== 0 && This
->stateBlock
->renderState
[WINED3DRS_COLORKEYENABLE
]) {
5255 BOOL enable_ckey
= FALSE
;
5258 IWineD3DSurfaceImpl
*surf
= (IWineD3DSurfaceImpl
*) ((IWineD3DTextureImpl
*)pTexture
)->surfaces
[0];
5259 if(surf
->CKeyFlags
& DDSD_CKSRCBLT
) enable_ckey
= TRUE
;
5263 glAlphaFunc(GL_NOTEQUAL
, 0.0);
5264 checkGLcall("glAlphaFunc");
5271 HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
5272 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5273 TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This
, Stage
, ppTexture
);
5275 /* Reject invalid texture units */
5276 if (Stage
>= GL_LIMITS(textures
)) {
5277 TRACE("Attempt to access invalid texture rejected\n");
5278 return WINED3DERR_INVALIDCALL
;
5280 *ppTexture
=This
->updateStateBlock
->textures
[Stage
];
5282 IWineD3DBaseTexture_AddRef(*ppTexture
);
5284 return WINED3DERR_INVALIDCALL
;
5291 HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT iSwapChain
, UINT BackBuffer
, WINED3DBACKBUFFER_TYPE Type
,
5292 IWineD3DSurface
**ppBackBuffer
) {
5293 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5294 IWineD3DSwapChain
*swapChain
;
5297 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This
, BackBuffer
, Type
, iSwapChain
, *ppBackBuffer
);
5299 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5300 if (hr
== WINED3D_OK
) {
5301 hr
= IWineD3DSwapChain_GetBackBuffer(swapChain
, BackBuffer
, Type
, ppBackBuffer
);
5302 IWineD3DSwapChain_Release(swapChain
);
5304 *ppBackBuffer
= NULL
;
5309 HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
5310 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5311 WARN("(%p) : stub, calling idirect3d for now\n", This
);
5312 return IWineD3D_GetDeviceCaps(This
->wineD3D
, This
->adapterNo
, This
->devType
, pCaps
);
5315 HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
5316 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5317 IWineD3DSwapChain
*swapChain
;
5320 if(iSwapChain
> 0) {
5321 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
5322 if (hr
== WINED3D_OK
) {
5323 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
5324 IWineD3DSwapChain_Release(swapChain
);
5326 FIXME("(%p) Error getting display mode\n", This
);
5329 /* Don't read the real display mode,
5330 but return the stored mode instead. X11 can't change the color
5331 depth, and some apps are pretty angry if they SetDisplayMode from
5332 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
5334 Also don't relay to the swapchain because with ddraw it's possible
5335 that there isn't a swapchain at all */
5336 pMode
->Width
= This
->ddraw_width
;
5337 pMode
->Height
= This
->ddraw_height
;
5338 pMode
->Format
= This
->ddraw_format
;
5339 pMode
->RefreshRate
= 0;
5346 HRESULT WINAPI
IWineD3DDeviceImpl_SetHWND(IWineD3DDevice
*iface
, HWND hWnd
) {
5347 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5348 TRACE("(%p)->(%p)\n", This
, hWnd
);
5350 This
->ddraw_window
= hWnd
;
5354 HRESULT WINAPI
IWineD3DDeviceImpl_GetHWND(IWineD3DDevice
*iface
, HWND
*hWnd
) {
5355 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5356 TRACE("(%p)->(%p)\n", This
, hWnd
);
5358 *hWnd
= This
->ddraw_window
;
5363 * Stateblock related functions
5366 HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
5367 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5368 IWineD3DStateBlockImpl
*object
;
5369 TRACE("(%p)", This
);
5371 if (This
->isRecordingState
) {
5372 return WINED3DERR_INVALIDCALL
;
5375 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DStateBlockImpl
));
5376 if (NULL
== object
) {
5377 FIXME("(%p)Error allocating memory for stateblock\n", This
);
5378 return E_OUTOFMEMORY
;
5380 TRACE("(%p) creted object %p\n", This
, object
);
5381 object
->wineD3DDevice
= This
;
5382 /** FIXME: object->parent = parent; **/
5383 object
->parent
= NULL
;
5384 object
->blockType
= WINED3DSBT_ALL
;
5386 object
->lpVtbl
= &IWineD3DStateBlock_Vtbl
;
5388 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
5389 This
->updateStateBlock
= object
;
5390 This
->isRecordingState
= TRUE
;
5392 TRACE("(%p) recording stateblock %p\n",This
, object
);
5396 HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
5397 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5399 if (!This
->isRecordingState
) {
5400 FIXME("(%p) not recording! returning error\n", This
);
5401 *ppStateBlock
= NULL
;
5402 return WINED3DERR_INVALIDCALL
;
5405 *ppStateBlock
= (IWineD3DStateBlock
*)This
->updateStateBlock
;
5406 This
->isRecordingState
= FALSE
;
5407 This
->updateStateBlock
= This
->stateBlock
;
5408 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
5409 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
5410 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
5415 * Scene related functions
5417 HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
5418 /* At the moment we have no need for any functionality at the beginning
5420 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5421 TRACE("(%p) : stub\n", This
);
5425 HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
) {
5426 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5427 TRACE("(%p)\n", This
);
5429 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5431 checkGLcall("glFlush");
5433 TRACE("End Scene\n");
5434 if(This
->renderTarget
!= NULL
) {
5436 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
5437 IUnknown
*targetContainer
= NULL
;
5438 if (WINED3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DBaseTexture
, (void **)&targetContainer
)
5439 || WINED3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DDevice
, (void **)&targetContainer
)) {
5440 TRACE("(%p) : Texture rendertarget %p\n", This
,This
->renderTarget
);
5441 /** always dirtify for now. we must find a better way to see that surface have been modified
5442 (Modifications should will only occur via draw-primitive, but we do need better locking
5443 switching to render-to-texture should remove the overhead though.
5445 IWineD3DSurface_SetPBufferState(This
->renderTarget
, TRUE
/* inPBuffer */, FALSE
/* inTexture */);
5446 IWineD3DSurface_AddDirtyRect(This
->renderTarget
, NULL
);
5447 IWineD3DSurface_PreLoad(This
->renderTarget
);
5448 IWineD3DSurface_SetPBufferState(This
->renderTarget
, FALSE
/* inPBuffer */, FALSE
/* inTexture */);
5449 IUnknown_Release(targetContainer
);
5452 This
->sceneEnded
= TRUE
;
5457 HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
5458 CONST RECT
* pSourceRect
, CONST RECT
* pDestRect
,
5459 HWND hDestWindowOverride
, CONST RGNDATA
* pDirtyRegion
) {
5460 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5461 IWineD3DSwapChain
*swapChain
= NULL
;
5463 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
5465 TRACE("(%p) Presenting the frame\n", This
);
5467 for(i
= 0 ; i
< swapchains
; i
++) {
5469 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, (IWineD3DSwapChain
**)&swapChain
);
5470 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
5471 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
5472 IWineD3DSwapChain_Release(swapChain
);
5478 HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST D3DRECT
* pRects
,
5479 DWORD Flags
, D3DCOLOR Color
, float Z
, DWORD Stencil
) {
5480 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5482 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
5483 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
5484 when the depth-buffer format does not contain stencil buffer information, this method fails. */
5485 GLbitfield glMask
= 0;
5486 GLboolean old_ztest
;
5487 GLfloat old_z_clear_value
;
5488 GLint old_stencil_clear_value
;
5489 GLfloat old_color_clear_value
[4];
5491 CONST D3DRECT
* curRect
;
5493 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This
,
5494 Count
, pRects
, Flags
, Z
, Stencil
);
5498 glEnable(GL_SCISSOR_TEST
);
5499 checkGLcall("glEnable GL_SCISSOR_TEST");
5501 if (Count
> 0 && pRects
) {
5507 /* Only set the values up once, as they are not changing */
5508 if (Flags
& D3DCLEAR_STENCIL
) {
5509 glGetIntegerv(GL_STENCIL_CLEAR_VALUE
, &old_stencil_clear_value
);
5510 glClearStencil(Stencil
);
5511 checkGLcall("glClearStencil");
5512 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
5513 glStencilMask(0xFFFFFFFF);
5516 if (Flags
& D3DCLEAR_ZBUFFER
) {
5517 glGetBooleanv(GL_DEPTH_WRITEMASK
, &old_ztest
);
5518 glDepthMask(GL_TRUE
);
5519 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &old_z_clear_value
);
5521 checkGLcall("glClearDepth");
5522 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
5525 if (Flags
& D3DCLEAR_TARGET
) {
5526 TRACE("Clearing screen with glClear to color %lx\n", Color
);
5527 glGetFloatv(GL_COLOR_CLEAR_VALUE
, old_color_clear_value
);
5528 glClearColor(D3DCOLOR_R(Color
),
5532 checkGLcall("glClearColor");
5534 /* Clear ALL colors! */
5535 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5536 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
5539 /* Now process each rect in turn */
5540 for (i
= 0; i
< Count
|| i
== 0; i
++) {
5543 /* Note gl uses lower left, width/height */
5544 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This
, curRect
,
5545 curRect
->x1
, curRect
->y1
, curRect
->x2
, curRect
->y2
,
5546 curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
5547 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
5548 glScissor(curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
5549 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
5550 checkGLcall("glScissor");
5552 glScissor(This
->stateBlock
->viewport
.X
,
5553 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
-
5554 (This
->stateBlock
->viewport
.Y
+ This
->stateBlock
->viewport
.Height
)),
5555 This
->stateBlock
->viewport
.Width
,
5556 This
->stateBlock
->viewport
.Height
);
5557 checkGLcall("glScissor");
5560 /* Clear the selected rectangle (or full screen) */
5562 checkGLcall("glClear");
5564 /* Step to the next rectangle */
5565 if (curRect
) curRect
= curRect
+ sizeof(D3DRECT
);
5568 /* Restore the old values (why..?) */
5569 if (Flags
& D3DCLEAR_STENCIL
) {
5570 glClearStencil(old_stencil_clear_value
);
5571 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
5573 if (Flags
& D3DCLEAR_ZBUFFER
) {
5574 glDepthMask(old_ztest
);
5575 glClearDepth(old_z_clear_value
);
5577 if (Flags
& D3DCLEAR_TARGET
) {
5578 glClearColor(old_color_clear_value
[0],
5579 old_color_clear_value
[1],
5580 old_color_clear_value
[2],
5581 old_color_clear_value
[3]);
5582 glColorMask(This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
5583 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
5584 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
5585 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
5588 glDisable(GL_SCISSOR_TEST
);
5589 checkGLcall("glDisable");
5598 HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
,
5599 UINT PrimitiveCount
) {
5601 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5602 This
->stateBlock
->streamIsUP
= FALSE
;
5604 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This
, PrimitiveType
,
5605 debug_d3dprimitivetype(PrimitiveType
),
5606 StartVertex
, PrimitiveCount
);
5607 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, StartVertex
, 0/* NumVertices */, -1 /* indxStart */,
5608 0 /* indxSize */, NULL
/* indxData */, 0 /* minIndex */, NULL
);
5614 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5615 HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
,
5616 D3DPRIMITIVETYPE PrimitiveType
,
5617 INT baseVIndex
, UINT minIndex
,
5618 UINT NumVertices
, UINT startIndex
, UINT primCount
) {
5620 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5622 IWineD3DIndexBuffer
*pIB
;
5623 WINED3DINDEXBUFFER_DESC IdxBufDsc
;
5625 pIB
= This
->stateBlock
->pIndexData
;
5626 This
->stateBlock
->streamIsUP
= FALSE
;
5628 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d\n", This
,
5629 PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5630 minIndex
, NumVertices
, startIndex
, baseVIndex
, primCount
);
5632 IWineD3DIndexBuffer_GetDesc(pIB
, &IdxBufDsc
);
5633 if (IdxBufDsc
.Format
== WINED3DFMT_INDEX16
) {
5639 drawPrimitive(iface
, PrimitiveType
, primCount
, baseVIndex
, NumVertices
, startIndex
,
5640 idxStride
, ((IWineD3DIndexBufferImpl
*) pIB
)->resource
.allocatedMemory
, minIndex
, NULL
);
5645 HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
5646 UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
,
5647 UINT VertexStreamZeroStride
) {
5648 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5650 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This
, PrimitiveType
,
5651 debug_d3dprimitivetype(PrimitiveType
),
5652 PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5654 /* release the stream source */
5655 if (This
->stateBlock
->streamSource
[0] != NULL
) {
5656 IWineD3DVertexBuffer_Release(This
->stateBlock
->streamSource
[0]);
5659 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5660 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5661 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5662 This
->stateBlock
->streamIsUP
= TRUE
;
5664 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* start vertex */, 0 /* NumVertices */,
5665 0 /* indxStart*/, 0 /* indxSize*/, NULL
/* indxData */, 0 /* indxMin */, NULL
);
5667 /* MSDN specifies stream zero settings must be set to NULL */
5668 This
->stateBlock
->streamStride
[0] = 0;
5669 This
->stateBlock
->streamSource
[0] = NULL
;
5671 /*stream zero settings set to null at end, as per the msdn */
5675 HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
5676 UINT MinVertexIndex
, UINT NumVertices
,
5677 UINT PrimitiveCount
, CONST
void* pIndexData
,
5678 WINED3DFORMAT IndexDataFormat
,CONST
void* pVertexStreamZeroData
,
5679 UINT VertexStreamZeroStride
) {
5681 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5683 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5684 This
, PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5685 MinVertexIndex
, NumVertices
, PrimitiveCount
, pIndexData
,
5686 IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5688 if (IndexDataFormat
== WINED3DFMT_INDEX16
) {
5694 /* release the stream and index data */
5695 if (This
->stateBlock
->streamSource
[0] != NULL
) {
5696 IWineD3DVertexBuffer_Release(This
->stateBlock
->streamSource
[0]);
5698 if (This
->stateBlock
->pIndexData
) {
5699 IWineD3DIndexBuffer_Release(This
->stateBlock
->pIndexData
);
5702 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5703 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5704 This
->stateBlock
->streamIsUP
= TRUE
;
5705 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5707 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* vertexStart */, NumVertices
, 0 /* indxStart */, idxStride
, pIndexData
, MinVertexIndex
, NULL
);
5709 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5710 This
->stateBlock
->streamSource
[0] = NULL
;
5711 This
->stateBlock
->streamStride
[0] = 0;
5712 This
->stateBlock
->pIndexData
= NULL
;
5717 HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, WineDirect3DVertexStridedData
*DrawPrimStrideData
) {
5719 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, 0, 0, NULL
, 0, DrawPrimStrideData
);
5722 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5723 HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice
*iface
, IWineD3DBaseTexture
*pSourceTexture
, IWineD3DBaseTexture
*pDestinationTexture
){
5724 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5725 HRESULT hr
= WINED3D_OK
;
5726 WINED3DRESOURCETYPE sourceType
;
5727 WINED3DRESOURCETYPE destinationType
;
5730 /* TODO: think about moving the code into IWineD3DBaseTexture */
5732 TRACE("(%p) Source %p Destination %p\n", This
, pSourceTexture
, pDestinationTexture
);
5734 /* verify that the source and destination textures aren't NULL */
5735 if (NULL
== pSourceTexture
|| NULL
== pDestinationTexture
) {
5736 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5737 This
, pSourceTexture
, pDestinationTexture
);
5738 hr
= WINED3DERR_INVALIDCALL
;
5741 if (pSourceTexture
== pDestinationTexture
) {
5742 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5743 This
, pSourceTexture
, pDestinationTexture
);
5744 hr
= WINED3DERR_INVALIDCALL
;
5746 /* Verify that the source and destination textures are the same type */
5747 sourceType
= IWineD3DBaseTexture_GetType(pSourceTexture
);
5748 destinationType
= IWineD3DBaseTexture_GetType(pDestinationTexture
);
5750 if (sourceType
!= destinationType
) {
5751 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5753 hr
= WINED3DERR_INVALIDCALL
;
5756 /* check that both textures have the identical numbers of levels */
5757 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture
)) {
5758 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This
, pSourceTexture
, pDestinationTexture
);
5759 hr
= WINED3DERR_INVALIDCALL
;
5762 if (WINED3D_OK
== hr
) {
5764 /* Make sure that the destination texture is loaded */
5765 IWineD3DBaseTexture_PreLoad(pDestinationTexture
);
5767 /* Update every surface level of the texture */
5768 levels
= IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
);
5770 switch (sourceType
) {
5771 case WINED3DRTYPE_TEXTURE
:
5773 IWineD3DSurface
*srcSurface
;
5774 IWineD3DSurface
*destSurface
;
5776 for (i
= 0 ; i
< levels
; ++i
) {
5777 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pSourceTexture
, i
, &srcSurface
);
5778 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pDestinationTexture
, i
, &destSurface
);
5779 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5780 IWineD3DSurface_Release(srcSurface
);
5781 IWineD3DSurface_Release(destSurface
);
5782 if (WINED3D_OK
!= hr
) {
5783 WARN("(%p) : Call to update surface failed\n", This
);
5789 case WINED3DRTYPE_CUBETEXTURE
:
5791 IWineD3DSurface
*srcSurface
;
5792 IWineD3DSurface
*destSurface
;
5793 WINED3DCUBEMAP_FACES faceType
;
5795 for (i
= 0 ; i
< levels
; ++i
) {
5796 /* Update each cube face */
5797 for (faceType
= D3DCUBEMAP_FACE_POSITIVE_X
; faceType
<= D3DCUBEMAP_FACE_NEGATIVE_Z
; ++faceType
){
5798 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pSourceTexture
, faceType
, i
, &srcSurface
);
5799 if (WINED3D_OK
!= hr
) {
5800 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5802 TRACE("Got srcSurface %p\n", srcSurface
);
5804 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pDestinationTexture
, faceType
, i
, &destSurface
);
5805 if (WINED3D_OK
!= hr
) {
5806 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5808 TRACE("Got desrSurface %p\n", destSurface
);
5810 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5811 IWineD3DSurface_Release(srcSurface
);
5812 IWineD3DSurface_Release(destSurface
);
5813 if (WINED3D_OK
!= hr
) {
5814 WARN("(%p) : Call to update surface failed\n", This
);
5821 #if 0 /* TODO: Add support for volume textures */
5822 case WINED3DRTYPE_VOLUMETEXTURE
:
5824 IWineD3DVolume srcVolume
= NULL
;
5825 IWineD3DSurface destVolume
= NULL
;
5827 for (i
= 0 ; i
< levels
; ++i
) {
5828 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture
*)pSourceTexture
, i
, &srcVolume
);
5829 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture
*)pDestinationTexture
, i
, &destVolume
);
5830 hr
= IWineD3DFoo_UpdateVolume(iface
, srcVolume
, NULL
, destVolume
, NULL
);
5831 IWineD3DVolume_Release(srcSurface
);
5832 IWineD3DVolume_Release(destSurface
);
5833 if (WINED3D_OK
!= hr
) {
5834 WARN("(%p) : Call to update volume failed\n", This
);
5842 FIXME("(%p) : Unsupported source and destination type\n", This
);
5843 hr
= WINED3DERR_INVALIDCALL
;
5850 HRESULT WINAPI
IWineD3DDeviceImpl_StretchRect(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
,
5851 CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
,
5852 CONST RECT
* pDestRect
, WINED3DTEXTUREFILTERTYPE Filter
) {
5853 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5855 TRACE("(%p) : stub\n", This
);
5858 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice
*iface
, IWineD3DSurface
*pRenderTarget
, IWineD3DSurface
*pSurface
) {
5859 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5860 /** TODO: remove remove casts to IWineD3DSurfaceImpl *
5861 * NOTE It may be best to move the code into surface to occomplish this
5862 ****************************************/
5864 WINED3DSURFACE_DESC surfaceDesc
;
5865 unsigned int surfaceWidth
, surfaceHeight
;
5866 glDescriptor
*targetGlDescription
= NULL
;
5867 glDescriptor
*surfaceGlDescription
= NULL
;
5868 IWineD3DSwapChainImpl
*container
= NULL
;
5870 IWineD3DSurface_GetGlDesc(pRenderTarget
, &targetGlDescription
);
5871 IWineD3DSurface_GetGlDesc(pSurface
, &surfaceGlDescription
);
5872 memset(&surfaceDesc
, 0, sizeof(surfaceDesc
));
5874 surfaceDesc
.Width
= &surfaceWidth
;
5875 surfaceDesc
.Height
= &surfaceHeight
;
5876 IWineD3DSurface_GetDesc(pSurface
, &surfaceDesc
);
5877 /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
5879 /* Ok, I may need to setup some kind of active swapchain reference on the device */
5880 IWineD3DSurface_GetContainer(pRenderTarget
, &IID_IWineD3DSwapChain
, (void **)&container
);
5882 /* TODO: opengl Context switching for swapchains etc... */
5883 if (NULL
!= container
|| pRenderTarget
== This
->renderTarget
|| pRenderTarget
== This
->depthStencilBuffer
) {
5884 if (NULL
!= container
&& (pRenderTarget
== container
->backBuffer
)) {
5885 glReadBuffer(GL_BACK
);
5886 vcheckGLcall("glReadBuffer(GL_BACK)");
5887 } else if ((NULL
!= container
&& (pRenderTarget
== container
->frontBuffer
)) || (pRenderTarget
== This
->renderTarget
)) {
5888 glReadBuffer(GL_FRONT
);
5889 vcheckGLcall("glReadBuffer(GL_FRONT)");
5890 } else if (pRenderTarget
== This
->depthStencilBuffer
) {
5891 FIXME("Reading of depthstencil not yet supported\n");
5894 glReadPixels(surfaceGlDescription
->target
,
5895 surfaceGlDescription
->level
,
5898 surfaceGlDescription
->glFormat
,
5899 surfaceGlDescription
->glType
,
5900 (void *)IWineD3DSurface_GetData(pSurface
));
5901 vcheckGLcall("glReadPixels(...)");
5902 if(NULL
!= container
){
5903 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) container
);
5906 IWineD3DBaseTexture
*container
;
5907 GLenum textureDimensions
= GL_TEXTURE_2D
;
5909 if (WINED3D_OK
== IWineD3DSurface_GetContainer(pSurface
, &IID_IWineD3DBaseTexture
, (void **)&container
)) {
5910 textureDimensions
= IWineD3DBaseTexture_GetTextureDimensions(container
);
5911 IWineD3DBaseTexture_Release(container
);
5913 /* TODO: 2D -> Cube surface coppies etc.. */
5914 if (surfaceGlDescription
->target
!= textureDimensions
) {
5915 FIXME("(%p) : Texture dimension mismatch\n", This
);
5917 glEnable(textureDimensions
);
5918 vcheckGLcall("glEnable(GL_TEXTURE_...)");
5919 /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
5920 glBindTexture(targetGlDescription
->target
, targetGlDescription
->textureName
);
5921 vcheckGLcall("glBindTexture");
5922 glGetTexImage(surfaceGlDescription
->target
,
5923 surfaceGlDescription
->level
,
5924 surfaceGlDescription
->glFormat
,
5925 surfaceGlDescription
->glType
,
5926 (void *)IWineD3DSurface_GetData(pSurface
));
5927 glDisable(textureDimensions
);
5928 vcheckGLcall("glDisable(GL_TEXTURE_...)");
5935 HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
5936 IWineD3DSwapChain
*swapChain
;
5938 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
5939 if(hr
== WINED3D_OK
) {
5940 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
5941 IWineD3DSwapChain_Release(swapChain
);
5946 HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
5947 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5948 /* return a sensible default */
5950 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5951 FIXME("(%p) : stub\n", This
);
5955 HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
5956 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5958 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5959 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
5960 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5961 return WINED3DERR_INVALIDCALL
;
5963 for (j
= 0; j
< 256; ++j
) {
5964 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
5965 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
5966 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
5967 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
5969 TRACE("(%p) : returning\n", This
);
5973 HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
5974 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5976 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5977 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
5978 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5979 return WINED3DERR_INVALIDCALL
;
5981 for (j
= 0; j
< 256; ++j
) {
5982 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
5983 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
5984 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
5985 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
5987 TRACE("(%p) : returning\n", This
);
5991 HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
5992 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5993 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5994 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
5995 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5996 return WINED3DERR_INVALIDCALL
;
5998 /*TODO: stateblocks */
5999 This
->currentPalette
= PaletteNumber
;
6000 TRACE("(%p) : returning\n", This
);
6004 HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
6005 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6006 if (PaletteNumber
== NULL
) {
6007 WARN("(%p) : returning Invalid Call\n", This
);
6008 return WINED3DERR_INVALIDCALL
;
6010 /*TODO: stateblocks */
6011 *PaletteNumber
= This
->currentPalette
;
6012 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
6016 HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
6017 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6018 static BOOL showFixmes
= TRUE
;
6020 FIXME("(%p) : stub\n", This
);
6024 This
->softwareVertexProcessing
= bSoftware
;
6029 BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
6030 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6031 static BOOL showFixmes
= TRUE
;
6033 FIXME("(%p) : stub\n", This
);
6036 return This
->softwareVertexProcessing
;
6040 HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DRASTER_STATUS
* pRasterStatus
) {
6041 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6042 IWineD3DSwapChain
*swapChain
;
6045 TRACE("(%p) : SwapChain %d returning %p\n", This
, iSwapChain
, pRasterStatus
);
6047 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
6048 if(hr
== WINED3D_OK
){
6049 hr
= IWineD3DSwapChain_GetRasterStatus(swapChain
, pRasterStatus
);
6050 IWineD3DSwapChain_Release(swapChain
);
6052 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This
);
6058 HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
) {
6059 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6060 static BOOL showfixmes
= TRUE
;
6061 if(nSegments
!= 0.0f
) {
6063 FIXME("(%p) : stub nSegments(%f)\n", This
, nSegments
);
6070 float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
) {
6071 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6072 static BOOL showfixmes
= TRUE
;
6074 FIXME("(%p) : stub returning(%f)\n", This
, 0.0f
);
6080 HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
6081 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6082 /** TODO: remove casts to IWineD3DSurfaceImpl
6083 * NOTE: move code to surface to accomplish this
6084 ****************************************/
6085 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
6086 int srcWidth
, srcHeight
;
6087 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
6088 WINED3DFORMAT destFormat
, srcFormat
;
6090 int destLeft
, destTop
;
6091 WINED3DPOOL srcPool
, destPool
;
6093 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
6094 glDescriptor
*glDescription
= NULL
;
6095 GLenum textureDimensions
= GL_TEXTURE_2D
;
6096 IWineD3DBaseTexture
*baseTexture
;
6098 WINED3DSURFACE_DESC winedesc
;
6100 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This
, pSourceSurface
, pSourceRect
, pDestinationSurface
, pDestPoint
);
6101 memset(&winedesc
, 0, sizeof(winedesc
));
6102 winedesc
.Width
= &srcSurfaceWidth
;
6103 winedesc
.Height
= &srcSurfaceHeight
;
6104 winedesc
.Pool
= &srcPool
;
6105 winedesc
.Format
= &srcFormat
;
6107 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
6109 winedesc
.Width
= &destSurfaceWidth
;
6110 winedesc
.Height
= &destSurfaceHeight
;
6111 winedesc
.Pool
= &destPool
;
6112 winedesc
.Format
= &destFormat
;
6113 winedesc
.Size
= &destSize
;
6115 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6117 if(srcPool
!= WINED3DPOOL_SYSTEMMEM
|| destPool
!= WINED3DPOOL_DEFAULT
){
6118 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface
, pDestinationSurface
);
6119 return WINED3DERR_INVALIDCALL
;
6122 if (destFormat
== WINED3DFMT_UNKNOWN
) {
6123 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
6124 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
6126 /* Get the update surface description */
6127 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6130 /* Make sure the surface is loaded and up to date */
6131 IWineD3DSurface_PreLoad(pDestinationSurface
);
6133 IWineD3DSurface_GetGlDesc(pDestinationSurface
, &glDescription
);
6137 /* this needs to be done in lines if the sourceRect != the sourceWidth */
6138 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
6139 srcHeight
= pSourceRect
? pSourceRect
->top
- pSourceRect
->bottom
: srcSurfaceHeight
;
6140 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
6141 destTop
= pDestPoint
? pDestPoint
->y
: 0;
6144 /* This function doesn't support compressed textures
6145 the pitch is just bytesPerPixel * width */
6146 if(srcWidth
!= srcSurfaceWidth
|| (pSourceRect
!= NULL
&& pSourceRect
->left
!= 0) ){
6147 rowoffset
= (srcSurfaceWidth
- srcWidth
) * pSrcSurface
->bytesPerPixel
;
6148 offset
+= pSourceRect
->left
* pSrcSurface
->bytesPerPixel
;
6149 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
6151 /* TODO DXT formats */
6153 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
6154 offset
+= pSourceRect
->top
* srcWidth
* pSrcSurface
->bytesPerPixel
;
6156 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
6158 ,glDescription
->level
6163 ,glDescription
->glFormat
6164 ,glDescription
->glType
6165 ,IWineD3DSurface_GetData(pSourceSurface
)
6169 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
6171 /* need to lock the surface to get the data */
6172 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
6175 /* TODO: Cube and volume support */
6177 /* not a whole row so we have to do it a line at a time */
6180 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
6181 unsigned char* data
=((unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
6183 for(j
= destTop
; j
< (srcHeight
+ destTop
) ; j
++){
6185 glTexSubImage2D(glDescription
->target
6186 ,glDescription
->level
6191 ,glDescription
->glFormat
6192 ,glDescription
->glType
6193 ,data
/* could be quicker using */
6198 } else { /* Full width, so just write out the whole texture */
6200 if (WINED3DFMT_DXT1
== destFormat
||
6201 WINED3DFMT_DXT2
== destFormat
||
6202 WINED3DFMT_DXT3
== destFormat
||
6203 WINED3DFMT_DXT4
== destFormat
||
6204 WINED3DFMT_DXT5
== destFormat
) {
6205 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
6206 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
) {
6207 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
6208 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6209 } if (destFormat
!= srcFormat
) {
6210 FIXME("Updating mixed format compressed texture is not curretly support\n");
6212 GL_EXTCALL(glCompressedTexImage2DARB
)(glDescription
->target
,
6213 glDescription
->level
,
6214 glDescription
->glFormatInternal
,
6219 IWineD3DSurface_GetData(pSourceSurface
));
6222 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6227 if (NP2_REPACK
== wined3d_settings
.nonpower2_mode
) {
6229 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
6230 to repack the data from pow2Width/Height to expected Width,Height, this makes the
6231 data returned by GetData non-power2 width/height with hardware non-power2
6232 pow2Width/height are set to surface width height, repacking isn't needed so it
6233 doesn't matter which function gets called. */
6234 glTexSubImage2D(glDescription
->target
6235 ,glDescription
->level
6240 ,glDescription
->glFormat
6241 ,glDescription
->glType
6242 ,IWineD3DSurface_GetData(pSourceSurface
)
6246 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
6247 glTexSubImage2D(glDescription
->target
6248 ,glDescription
->level
6251 ,((IWineD3DSurfaceImpl
*)pSourceSurface
)->pow2Width
6252 ,((IWineD3DSurfaceImpl
*)pSourceSurface
)->pow2Height
6253 ,glDescription
->glFormat
6254 ,glDescription
->glType
6255 ,IWineD3DSurface_GetData(pSourceSurface
)
6261 checkGLcall("glTexSubImage2D");
6263 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
6264 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
6265 * surface bigger than it needs to be hmm.. */
6266 if (WINED3D_OK
== IWineD3DSurface_GetContainer(pDestinationSurface
, &IID_IWineD3DBaseTexture
, (void **)&baseTexture
)) {
6267 textureDimensions
= IWineD3DBaseTexture_GetTextureDimensions(baseTexture
);
6268 IWineD3DBaseTexture_Release(baseTexture
);
6271 glDisable(textureDimensions
); /* This needs to be managed better.... */
6277 /* Used by DirectX 8 */
6278 HRESULT WINAPI
IWineD3DDeviceImpl_CopyRects(IWineD3DDevice
*iface
,
6279 IWineD3DSurface
* pSourceSurface
, CONST RECT
* pSourceRectsArray
, UINT cRects
,
6280 IWineD3DSurface
* pDestinationSurface
, CONST POINT
* pDestPointsArray
) {
6282 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6283 HRESULT hr
= WINED3D_OK
;
6284 WINED3DFORMAT srcFormat
, destFormat
;
6285 UINT srcWidth
, destWidth
;
6286 UINT srcHeight
, destHeight
;
6288 WINED3DSURFACE_DESC winedesc
;
6290 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This
,
6291 pSourceSurface
, pSourceRectsArray
, cRects
, pDestinationSurface
, pDestPointsArray
);
6294 /* Check that the source texture is in WINED3DPOOL_SYSTEMMEM and the destination texture is in WINED3DPOOL_DEFAULT */
6295 memset(&winedesc
, 0, sizeof(winedesc
));
6297 winedesc
.Format
= &srcFormat
;
6298 winedesc
.Width
= &srcWidth
;
6299 winedesc
.Height
= &srcHeight
;
6300 winedesc
.Size
= &srcSize
;
6301 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
6303 winedesc
.Format
= &destFormat
;
6304 winedesc
.Width
= &destWidth
;
6305 winedesc
.Height
= &destHeight
;
6306 winedesc
.Size
= NULL
;
6307 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
6309 /* Check that the source and destination formats match */
6310 if (srcFormat
!= destFormat
&& WINED3DFMT_UNKNOWN
!= destFormat
) {
6311 WARN("(%p) source %p format must match the dest %p format, returning WINED3DERR_INVALIDCALL\n", This
, pSourceSurface
, pDestinationSurface
);
6312 return WINED3DERR_INVALIDCALL
;
6313 } else if (WINED3DFMT_UNKNOWN
== destFormat
) {
6314 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
6315 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
6316 destFormat
= srcFormat
;
6319 /* Quick if complete copy ... */
6320 if (cRects
== 0 && pSourceRectsArray
== NULL
&& pDestPointsArray
== NULL
) {
6322 if (srcWidth
== destWidth
&& srcHeight
== destHeight
) {
6323 WINED3DLOCKED_RECT lrSrc
;
6324 WINED3DLOCKED_RECT lrDst
;
6325 IWineD3DSurface_LockRect(pSourceSurface
, &lrSrc
, NULL
, WINED3DLOCK_READONLY
);
6326 IWineD3DSurface_LockRect(pDestinationSurface
, &lrDst
, NULL
, 0L);
6327 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", srcWidth
, srcHeight
);
6329 memcpy(lrDst
.pBits
, lrSrc
.pBits
, srcSize
);
6331 IWineD3DSurface_UnlockRect(pSourceSurface
);
6332 IWineD3DSurface_UnlockRect(pDestinationSurface
);
6333 TRACE("Unlocked src and dst\n");
6337 FIXME("Wanted to copy all surfaces but size not compatible, returning WINED3DERR_INVALIDCALL\n");
6338 hr
= WINED3DERR_INVALIDCALL
;
6343 if (NULL
!= pSourceRectsArray
&& NULL
!= pDestPointsArray
) {
6345 int bytesPerPixel
= ((IWineD3DSurfaceImpl
*) pSourceSurface
)->bytesPerPixel
;
6348 /* Copy rect by rect */
6349 for (i
= 0; i
< cRects
; ++i
) {
6350 CONST RECT
* r
= &pSourceRectsArray
[i
];
6351 CONST POINT
* p
= &pDestPointsArray
[i
];
6354 WINED3DLOCKED_RECT lrSrc
;
6355 WINED3DLOCKED_RECT lrDst
;
6358 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i
, r
->left
, r
->top
, r
->right
, r
->bottom
, p
->x
, p
->y
);
6359 if (srcFormat
== WINED3DFMT_DXT1
) {
6360 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
) / 2; /* DXT1 is half byte per pixel */
6362 copyperline
= ((r
->right
- r
->left
) * bytesPerPixel
);
6365 IWineD3DSurface_LockRect(pSourceSurface
, &lrSrc
, r
, WINED3DLOCK_READONLY
);
6366 dest_rect
.left
= p
->x
;
6367 dest_rect
.top
= p
->y
;
6368 dest_rect
.right
= p
->x
+ (r
->right
- r
->left
);
6369 dest_rect
.bottom
= p
->y
+ (r
->bottom
- r
->top
);
6370 IWineD3DSurface_LockRect(pDestinationSurface
, &lrDst
, &dest_rect
, 0L);
6371 TRACE("Locked src and dst\n");
6373 /* Find where to start */
6374 for (j
= 0; j
< (r
->bottom
- r
->top
- 1); ++j
) {
6375 memcpy((char*) lrDst
.pBits
+ (j
* lrDst
.Pitch
), (char*) lrSrc
.pBits
+ (j
* lrSrc
.Pitch
), copyperline
);
6377 IWineD3DSurface_UnlockRect(pSourceSurface
);
6378 IWineD3DSurface_UnlockRect(pDestinationSurface
);
6379 TRACE("Unlocked src and dst\n");
6382 FIXME("Wanted to copy partial surfaces not implemented, returning WINED3DERR_INVALIDCALL\n");
6383 hr
= WINED3DERR_INVALIDCALL
;
6390 /* Implementation details at http://developer.nvidia.com/attach/6494
6392 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
6393 hmm.. no longer supported use
6394 OpenGL evaluators or tessellate surfaces within your application.
6397 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
6398 HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
6399 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6400 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
6401 FIXME("(%p) : Stub\n", This
);
6406 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
6407 HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DTRIPATCH_INFO
* pTriPatchInfo
) {
6408 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6409 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This
, Handle
, pNumSegs
, pTriPatchInfo
);
6410 FIXME("(%p) : Stub\n", This
);
6414 HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
6415 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6416 TRACE("(%p) Handle(%d)\n", This
, Handle
);
6417 FIXME("(%p) : Stub\n", This
);
6421 HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, CONST D3DRECT
* pRect
, D3DCOLOR color
) {
6422 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
6423 fill a surface with a block of color! */
6424 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6425 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
6426 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*)pSurface
;
6427 IWineD3DSwapChainImpl
*container
= NULL
;
6428 BOOL isRenderTarget
= FALSE
;
6429 unsigned int width
, height
;
6430 unsigned int top
, left
;
6433 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This
, pSurface
, pRect
, color
);
6435 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
6436 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6437 return WINED3DERR_INVALIDCALL
;
6440 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
6441 if (WINED3D_OK
== IWineD3DSurface_GetContainer(pSurface
, &IID_IWineD3DSwapChain
, (void **)&container
) || pSurface
== This
->renderTarget
) {
6442 if (WINED3DUSAGE_RENDERTARGET
& surface
->resource
.usage
) {
6443 /* TODO: make sure we set everything back to the way it was, and context management!
6444 glGetIntegerv(GL_READ_BUFFER, &prev_read);
6445 vcheckGLcall("glIntegerv");
6446 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
6447 vcheckGLcall("glIntegerv");
6449 TRACE("Color fill to render targets may cause some graphics issues\n");
6450 if (pSurface
== container
->frontBuffer
) {
6451 glDrawBuffer(GL_FRONT
);
6453 glDrawBuffer(GL_BACK
);
6456 if (WINED3DUSAGE_DEPTHSTENCIL
& surface
->resource
.usage
) {
6457 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld\n", surface
, surface
->resource
.usage
);
6459 FIXME("(%p) : Regression %ld %p %p\n", This
, surface
->resource
.usage
, pSurface
, This
->renderTarget
);
6461 if (container
!= NULL
) {
6462 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)container
);
6464 /* we can use GL_STENCIL_INDEX etc...*/
6467 if (container
!= NULL
) {
6468 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)container
);
6470 isRenderTarget
= TRUE
;
6472 /* TODO: drawing to GL_FRONT and GL_BACK */
6473 /* TODO: see if things can be speeded up by using the correct
6474 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
6475 if (pRect
== NULL
) {
6478 width
= surface
->currentDesc
.Width
;
6479 height
= surface
->currentDesc
.Height
;
6483 width
= pRect
->x2
- left
;
6484 height
= pRect
->y2
- top
;
6487 data
= HeapAlloc(GetProcessHeap(), 0, 4 * width
);
6488 /* Create a 'line' of color color, in the correct format for the surface */
6489 for (u
= 0 ; u
< width
; u
++) {
6494 if (isRenderTarget
== FALSE
) {
6495 glDescriptor
*glDesc
;
6496 IWineD3DSurface_PreLoad(pSurface
);
6498 /* draw a block of the coloured line on the sufrace */
6499 IWineD3DSurface_GetGlDesc(pSurface
, &glDesc
);
6500 for (v
= 0 ; v
< height
;v
++) {
6501 glTexSubImage2D(glDesc
->target
6502 ,glDesc
->level
/* level */
6512 checkGLcall("glTexSubImage2D");
6514 glDisable(glDesc
->target
);
6516 /** FIXME: Using GLClear may be faster **/
6517 glRasterPos2i(left
, top
);
6518 glPixelZoom((float)width
,(float)height
);
6519 glDrawPixels(1, 1, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
6520 checkGLcall("glDrawPixels");
6522 HeapFree(GetProcessHeap(), 0, data
);
6528 /* rendertarget and deptth stencil functions */
6529 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
6530 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6532 /* FIXME: Implelent RenderTargetIndex >0 */
6533 if(RenderTargetIndex
> 0)
6534 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This
, RenderTargetIndex
);
6536 *ppRenderTarget
= This
->renderTarget
;
6537 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
6538 /* Note inc ref on returned surface */
6539 if(*ppRenderTarget
!= NULL
)
6540 IWineD3DSurface_AddRef(*ppRenderTarget
);
6544 HRESULT WINAPI
IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice
*iface
, IWineD3DSurface
*Front
, IWineD3DSurface
*Back
) {
6545 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6546 IWineD3DSurfaceImpl
*FrontImpl
= (IWineD3DSurfaceImpl
*) Front
;
6547 IWineD3DSurfaceImpl
*BackImpl
= (IWineD3DSurfaceImpl
*) Back
;
6548 IWineD3DSwapChainImpl
*Swapchain
;
6551 TRACE("(%p)->(%p,%p)\n", This
, FrontImpl
, BackImpl
);
6553 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &Swapchain
);
6554 if(hr
!= WINED3D_OK
) {
6555 ERR("Can't get the swapchain\n");
6559 /* Make sure to release the swapchain */
6560 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) Swapchain
);
6562 if(FrontImpl
&& !(FrontImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) {
6563 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6564 return WINED3DERR_INVALIDCALL
;
6566 else if(BackImpl
&& !(BackImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6567 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6568 return WINED3DERR_INVALIDCALL
;
6571 if(Swapchain
->frontBuffer
!= Front
) {
6572 TRACE("Changing the front buffer from %p to %p\n", Swapchain
->frontBuffer
, Front
);
6574 if(Swapchain
->frontBuffer
)
6575 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, NULL
);
6576 Swapchain
->frontBuffer
= Front
;
6578 if(Swapchain
->frontBuffer
) {
6579 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, (IWineD3DBase
*) Swapchain
);
6582 if(Swapchain
->backBuffer
!= Back
) {
6583 TRACE("Changing the back buffer from %p to %p\n", Swapchain
->backBuffer
, Back
);
6585 if(!Swapchain
->backBuffer
) {
6586 /* GL was told to draw to the front buffer at creation,
6589 glDrawBuffer(GL_BACK
);
6590 checkGLcall("glDrawBuffer(GL_BACK)");
6592 /* That makes problems - disable for now */
6593 /* glDrawBuffer(GL_FRONT); */
6594 checkGLcall("glDrawBuffer(GL_FRONT)");
6598 if(Swapchain
->backBuffer
)
6599 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
, NULL
);
6600 Swapchain
->backBuffer
= Back
;
6602 if(Swapchain
->backBuffer
) {
6603 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
, (IWineD3DBase
*) Swapchain
);
6611 HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
6612 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6613 *ppZStencilSurface
= This
->depthStencilBuffer
;
6614 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
6616 if(*ppZStencilSurface
!= NULL
) {
6617 /* Note inc ref on returned surface */
6618 IWineD3DSurface_AddRef(*ppZStencilSurface
);
6623 /* internal static helper functions */
6624 HRESULT WINAPI
static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
6625 IWineD3DSurface
*RenderSurface
);
6627 HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
) {
6628 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6629 HRESULT hr
= WINED3D_OK
;
6630 WINED3DVIEWPORT viewport
;
6632 TRACE("(%p) Swapping rendertarget\n",This
);
6633 if (RenderTargetIndex
> 0) {
6634 FIXME("(%p) Render targets other than the first are not supported\n",This
);
6635 RenderTargetIndex
= 0;
6638 /* MSDN says that null disables the render target
6639 but a device must always be associated with a render target
6640 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6642 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
6645 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
6646 FIXME("Trying to set render target 0 to NULL\n");
6647 return WINED3DERR_INVALIDCALL
;
6649 /* TODO: replace Impl* usage with interface usage */
6650 if (!((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
6651 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This
,pRenderTarget
);
6652 return WINED3DERR_INVALIDCALL
;
6654 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
6655 * builds, but I think wine counts as a 'debug' build for now.
6656 ******************************/
6657 /* If we are trying to set what we already have, don't bother */
6658 if (pRenderTarget
== This
->renderTarget
) {
6659 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6661 /* Otherwise, set the render target up */
6663 if (FALSE
== This
->sceneEnded
) {
6664 IWineD3DDevice_EndScene(iface
);
6666 TRACE("clearing renderer\n");
6667 /* IWineD3DDeviceImpl_CleanRender(iface); */
6668 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6669 depending on the renter target implementation being used.
6670 A shared context implementation will share all buffers between all rendertargets (including swapchains),
6671 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6672 stencil buffer and incure an extra memory overhead */
6673 hr
= IWineD3DDeviceImpl_ActiveRender(iface
, pRenderTarget
);
6676 if (SUCCEEDED(hr
)) {
6677 /* Finally, reset the viewport as the MSDN states. */
6678 /* TODO: Replace impl usage */
6679 viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
;
6680 viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Width
;
6683 viewport
.MaxZ
= 1.0f
;
6684 viewport
.MinZ
= 0.0f
;
6685 IWineD3DDeviceImpl_SetViewport(iface
, &viewport
);
6687 FIXME("Unknown error setting the render target\n");
6689 This
->sceneEnded
= FALSE
;
6693 HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
6694 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6695 HRESULT hr
= WINED3D_OK
;
6696 IWineD3DSurface
*tmp
;
6698 TRACE("(%p) Swapping z-buffer\n",This
);
6700 if (pNewZStencil
== This
->stencilBufferTarget
) {
6701 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6703 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
6704 * depending on the renter target implementation being used.
6705 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6706 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6707 * stencil buffer and incure an extra memory overhead
6708 ******************************************************/
6711 tmp
= This
->stencilBufferTarget
;
6712 This
->stencilBufferTarget
= pNewZStencil
;
6713 /* should we be calling the parent or the wined3d surface? */
6714 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
6715 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
6717 /** TODO: glEnable/glDisable on depth/stencil depending on
6718 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
6719 **********************************************************/
6726 #ifdef GL_VERSION_1_3
6727 /* Internal functions not in DirectX */
6728 /** TODO: move this off to the opengl context manager
6729 *(the swapchain doesn't need to know anything about offscreen rendering!)
6730 ****************************************************/
6732 HRESULT WINAPI
IWineD3DDeviceImpl_CleanRender(IWineD3DDevice
* iface
, IWineD3DSwapChainImpl
*swapchain
)
6734 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6736 TRACE("(%p), %p\n", This
, swapchain
);
6738 if (swapchain
->win
!= swapchain
->drawable
) {
6739 /* Set everything back the way it ws */
6740 swapchain
->render_ctx
= swapchain
->glCtx
;
6741 swapchain
->drawable
= swapchain
->win
;
6746 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
6747 HRESULT WINAPI
IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, glContext
**context
) {
6748 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6751 unsigned int height
;
6752 WINED3DFORMAT format
;
6753 WINED3DSURFACE_DESC surfaceDesc
;
6754 memset(&surfaceDesc
, 0, sizeof(surfaceDesc
));
6755 surfaceDesc
.Width
= &width
;
6756 surfaceDesc
.Height
= &height
;
6757 surfaceDesc
.Format
= &format
;
6758 IWineD3DSurface_GetDesc(pSurface
, &surfaceDesc
);
6760 /* I need a get width/height function (and should do something with the format) */
6761 for (i
= 0; i
< CONTEXT_CACHE
; ++i
) {
6762 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
6763 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
6764 the pSurface can be set to 0 allowing it to be reused from cache **/
6765 if (This
->contextCache
[i
].Width
== width
&& This
->contextCache
[i
].Height
== height
6766 && (pbuffer_per_surface
== FALSE
|| This
->contextCache
[i
].pSurface
== pSurface
|| This
->contextCache
[i
].pSurface
== NULL
)) {
6767 *context
= &This
->contextCache
[i
];
6770 if (This
->contextCache
[i
].Width
== 0) {
6771 This
->contextCache
[i
].pSurface
= pSurface
;
6772 This
->contextCache
[i
].Width
= width
;
6773 This
->contextCache
[i
].Height
= height
;
6774 *context
= &This
->contextCache
[i
];
6778 if (i
== CONTEXT_CACHE
) {
6779 int minUsage
= 0x7FFFFFFF; /* MAX_INT */
6780 glContext
*dropContext
= 0;
6781 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
6782 if (This
->contextCache
[i
].usedcount
< minUsage
) {
6783 dropContext
= &This
->contextCache
[i
];
6784 minUsage
= This
->contextCache
[i
].usedcount
;
6787 /* clean up the context (this doesn't work for ATI at the moment */
6789 glXDestroyContext(swapchain
->display
, dropContext
->context
);
6790 glXDestroyPbuffer(swapchain
->display
, dropContext
->drawable
);
6793 dropContext
->Width
= 0;
6794 dropContext
->pSurface
= pSurface
;
6795 *context
= dropContext
;
6797 if (++This
->contextCache
[i
].usedcount
== 0x7FFFFFFF /* MAX_INT */ - 1 ) {
6798 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
6799 This
->contextCache
[i
].usedcount
= max(0, This
->contextCache
[i
].usedcount
- (0x7FFFFFFF /* MAX_INT */ >> 1));
6803 if (*context
!= NULL
)
6806 return E_OUTOFMEMORY
;
6810 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
6811 * the functionality needs splitting up so that we don't do more than we should do.
6812 * this only seems to impact performance a little.
6813 ******************************/
6814 HRESULT WINAPI
IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
6815 IWineD3DSurface
*RenderSurface
) {
6816 HRESULT ret
= WINED3DERR_INVALIDCALL
;
6819 * Currently only active for GLX >= 1.3
6820 * for others versions we'll have to use GLXPixmaps
6822 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
6823 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
6824 * so only check OpenGL version
6825 * ..........................
6826 * I don't believe that it is a problem with NVidia headers,
6827 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
6828 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
6830 * Your application will report GLX version 1.2 on glXQueryVersion.
6831 * However, it is safe to call the GLX 1.3 functions as described below.
6833 #if defined(GL_VERSION_1_3)
6835 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6836 IWineD3DSurface
*StencilSurface
= This
->stencilBufferTarget
;
6837 IWineD3DSurface
*tmp
;
6838 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
6839 GLXFBConfig
* cfgs
= NULL
;
6843 IWineD3DSwapChain
*currentSwapchain
;
6844 IWineD3DSwapChainImpl
*swapchain
;
6845 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
6846 * but switch them off if the StencilSurface is set to NULL
6847 ** *********************************************************/
6848 D3DFORMAT BackBufferFormat
= ((IWineD3DSurfaceImpl
*) RenderSurface
)->resource
.format
;
6849 D3DFORMAT StencilBufferFormat
= (NULL
!= StencilSurface
) ? ((IWineD3DSurfaceImpl
*) StencilSurface
)->resource
.format
: 0;
6852 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
6853 it StencilSurface != NULL && zBufferTarget == NULL switch it on
6856 #define PUSH1(att) attribs[nAttribs++] = (att);
6857 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
6859 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
6861 /** TODO: remove the reff to Impl (context manager should fix this!) **/
6862 IWineD3DSwapChainImpl
*impSwapChain
;
6863 IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**)&impSwapChain
);
6864 if (NULL
== impSwapChain
) { /* NOTE: This should NEVER fail */
6865 ERR("(%p) Failed to get a the implicit swapchain\n", iface
);
6870 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
);
6871 PUSH2(GLX_X_RENDERABLE
, TRUE
);
6872 PUSH2(GLX_DOUBLEBUFFER
, TRUE
);
6873 TRACE("calling makeglcfg\n");
6874 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, FALSE
/* alternate */);
6877 TRACE("calling chooseFGConfig\n");
6878 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
6881 if (!cfgs
) { /* OK we didn't find the exact config, so use any reasonable match */
6882 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
6883 why we failed and only show this message once! */
6884 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
6886 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
| GLX_WINDOW_BIT
);
6887 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
6888 PUSH2(GLX_RENDER_TYPE
, GLX_RGBA_BIT
);
6889 PUSH2(GLX_DOUBLEBUFFER
, FALSE
);
6890 TRACE("calling makeglcfg\n");
6891 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, TRUE
/* alternate */);
6893 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
6900 for (i
= 0; i
< nCfgs
; ++i
) {
6901 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat
,
6902 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
,
6903 debug_d3dformat(StencilBufferFormat
), i
, cfgs
[i
]);
6906 if (NULL
!= This
->renderTarget
) {
6908 vcheckGLcall("glFlush");
6909 /** This is only useful if the old render target was a swapchain,
6910 * we need to supercede this with a function that displays
6911 * the current buffer on the screen. This is easy to do in glx1.3 but
6912 * we need to do copy-write pixels in glx 1.2.
6913 ************************************************/
6914 glXSwapBuffers(impSwapChain
->display
, impSwapChain
->drawable
);
6916 printf("Hit Enter to get next frame ...\n");
6922 if (IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)¤tSwapchain
) != WINED3D_OK
) {
6923 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
6924 IWineD3DDevice_GetSwapChain(iface
, 0, ¤tSwapchain
);
6928 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6929 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
6930 **********************************************************************/
6931 if (IWineD3DSurface_GetContainer(RenderSurface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
) == WINED3D_OK
) {
6932 /* We also need to make sure that the lights &co are also in the context of the swapchains */
6933 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
6934 TRACE("making swapchain active\n");
6935 if (RenderSurface
!= This
->renderTarget
) {
6936 if (RenderSurface
== swapchain
->backBuffer
) {
6938 /* This could be flagged so that some operations work directly with the front buffer */
6939 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
6941 if (glXMakeCurrent(swapchain
->display
, swapchain
->win
, swapchain
->glCtx
)
6943 TRACE("Error in setting current context: context %p drawable %ld !\n",
6944 impSwapChain
->glCtx
, impSwapChain
->win
);
6947 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
6949 checkGLcall("glXMakeContextCurrent");
6951 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
6953 else if (pbuffer_support
&& cfgs
!= NULL
/* && some test to make sure that opengl supports pbuffers */) {
6955 /** ********************************************************************
6956 * This is a quickly hacked out implementation of offscreen textures.
6957 * It will work in most cases but there may be problems if the client
6958 * modifies the texture directly, or expects the contents of the rendertarget
6961 * There are some real speed vs compatibility issues here:
6962 * we should really use a new context for every texture, but that eats ram.
6963 * we should also be restoring the texture to the pbuffer but that eats CPU
6964 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6965 * but if this means reusing the display backbuffer then we need to make sure that
6966 * states are correctly preserved.
6967 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6968 * and gain a good performance increase at the cost of compatibility.
6969 * I would suggest that, when this is the case, a user configurable flag be made
6970 * available, allowing the user to choose the best emulated experience for them.
6971 *********************************************************************/
6973 XVisualInfo
*visinfo
;
6974 glContext
*newContext
;
6976 /* Here were using a shared context model */
6977 if (WINED3D_OK
!= IWineD3DDeviceImpl_FindGLContext(iface
, RenderSurface
, &newContext
)) {
6978 FIXME("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
6981 /* If the context doesn't exist then create a new one */
6982 /* TODO: This should really be part of findGlContext */
6983 if (NULL
== newContext
->context
) {
6985 TRACE("making new buffer\n");
6987 PUSH2(GLX_PBUFFER_WIDTH
, newContext
->Width
);
6988 PUSH2(GLX_PBUFFER_HEIGHT
, newContext
->Height
);
6991 newContext
->drawable
= glXCreatePbuffer(impSwapChain
->display
, cfgs
[0], attribs
);
6993 /** ****************************************
6994 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6996 * In future releases, we may provide the calls glXCreateNewContext,
6997 * glXQueryDrawable and glXMakeContextCurrent.
6998 * so until then we have to use glXGetVisualFromFBConfig &co..
6999 ********************************************/
7002 visinfo
= glXGetVisualFromFBConfig(impSwapChain
->display
, cfgs
[0]);
7004 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
7006 newContext
->context
= glXCreateContext(impSwapChain
->display
, visinfo
, impSwapChain
->glCtx
, GL_TRUE
);
7010 if (NULL
== newContext
|| NULL
== newContext
->context
) {
7011 ERR("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
7013 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
7014 if (glXMakeCurrent(impSwapChain
->display
, newContext
->drawable
, newContext
->context
) == False
) {
7015 TRACE("Error in setting current context: context %p drawable %ld\n", newContext
->context
, newContext
->drawable
);
7018 /* Clean up the old context */
7019 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
7020 /* Set the current context of the swapchain to the new context */
7021 impSwapChain
->drawable
= newContext
->drawable
;
7022 impSwapChain
->render_ctx
= newContext
->context
;
7026 #if 1 /* Apply the stateblock to the new context
7027 FIXME: This is a bit of a hack, each context should know it's own state,
7028 the directX current directX state should then be applied to the context */
7031 IWineD3DStateBlockImpl
*oldUpdateStateBlock
;
7032 oldUpdateStateBlock
= This
->updateStateBlock
;
7033 oldRecording
= This
->isRecordingState
;
7034 This
->isRecordingState
= FALSE
;
7035 This
->updateStateBlock
= This
->stateBlock
;
7036 IWineD3DStateBlock_Apply((IWineD3DStateBlock
*)This
->stateBlock
);
7038 This
->isRecordingState
= oldRecording
;
7039 This
->updateStateBlock
= oldUpdateStateBlock
;
7044 /* clean up the current rendertargets swapchain (if it belonged to one) */
7045 if (currentSwapchain
!= NULL
) {
7046 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)currentSwapchain
);
7049 /* Were done with the opengl context management, setup the rendertargets */
7051 tmp
= This
->renderTarget
;
7052 This
->renderTarget
= RenderSurface
;
7053 IWineD3DSurface_AddRef(This
->renderTarget
);
7054 IWineD3DSurface_Release(tmp
);
7060 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
7061 /* Check that the container is not a swapchain member */
7063 IWineD3DSwapChain
*tmpSwapChain
;
7064 if (WINED3D_OK
!= IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)&tmpSwapChain
)) {
7065 This
->renderUpsideDown
= TRUE
;
7067 This
->renderUpsideDown
= FALSE
;
7068 IWineD3DSwapChain_Release(tmpSwapChain
);
7070 /* Force updating the cull mode */
7071 TRACE("setting render state\n");
7072 IWineD3DDevice_GetRenderState(iface
, WINED3DRS_CULLMODE
, &value
);
7073 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_CULLMODE
, value
);
7075 /* Force updating projection matrix */
7076 This
->last_was_rhw
= FALSE
;
7077 This
->proj_valid
= FALSE
;
7085 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat
,
7086 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
, debug_d3dformat(StencilBufferFormat
));
7091 if ( NULL
!= impSwapChain
) {
7092 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)impSwapChain
);
7100 HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
7101 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
7102 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7103 /* TODO: the use of Impl is deprecated. */
7104 /* some basic validation checks */
7105 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
7107 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
7109 if (WINED3DFMT_A8R8G8B8
!= pSur
->resource
.format
) {
7110 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
7111 return WINED3DERR_INVALIDCALL
;
7113 if (32 != pSur
->currentDesc
.Height
|| 32 != pSur
->currentDesc
.Width
) {
7114 ERR("(%p) : surface(%p) has an invalid size\n", This
, pCursorBitmap
);
7115 return WINED3DERR_INVALIDCALL
;
7117 /* TODO: make the cursor 'real' */
7119 This
->xHotSpot
= XHotSpot
;
7120 This
->yHotSpot
= YHotSpot
;
7125 void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
7126 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7127 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
7129 This
->xScreenSpace
= XScreenSpace
;
7130 This
->yScreenSpace
= YScreenSpace
;
7136 BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
7137 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7138 TRACE("(%p) : visible(%d)\n", This
, bShow
);
7140 This
->bCursorVisible
= bShow
;
7145 HRESULT WINAPI
IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice
* iface
) {
7146 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7147 TRACE("(%p) : state (%lu)\n", This
, This
->state
);
7148 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
7149 switch (This
->state
) {
7152 case WINED3DERR_DEVICELOST
:
7154 ResourceList
*resourceList
= This
->resources
;
7155 while (NULL
!= resourceList
) {
7156 if (((IWineD3DResourceImpl
*)resourceList
->resource
)->resource
.pool
== WINED3DPOOL_DEFAULT
/* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
7157 return WINED3DERR_DEVICENOTRESET
;
7158 resourceList
= resourceList
->next
;
7160 return WINED3DERR_DEVICELOST
;
7162 case WINED3DERR_DRIVERINTERNALERROR
:
7163 return WINED3DERR_DRIVERINTERNALERROR
;
7167 return WINED3DERR_DRIVERINTERNALERROR
;
7171 HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
* iface
) {
7172 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7173 /** FIXME: Resource tracking needs to be done,
7174 * The closes we can do to this is set the priorities of all managed textures low
7175 * and then reset them.
7176 ***********************************************************/
7177 FIXME("(%p) : stub\n", This
);
7181 HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
7182 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7183 /** FIXME: Resource trascking needs to be done.
7184 * in effect this pulls all non only default
7185 * textures out of video memory and deletes all glTextures (glDeleteTextures)
7186 * and should clear down the context and set it up according to pPresentationParameters
7187 ***********************************************************/
7188 FIXME("(%p) : stub\n", This
);
7192 HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL bEnableDialogs
) {
7193 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7194 /** FIXME: always true at the moment **/
7195 if(bEnableDialogs
== FALSE
) {
7196 FIXME("(%p) Dialogs cannot be disabled yet\n", This
);
7202 HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
7203 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7204 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
7206 *pParameters
= This
->createParms
;
7210 void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST WINED3DGAMMARAMP
* pRamp
) {
7211 IWineD3DSwapChain
*swapchain
;
7212 HRESULT hrc
= WINED3D_OK
;
7214 TRACE("Relaying to swapchain\n");
7216 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == WINED3D_OK
) {
7217 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, (WINED3DGAMMARAMP
*)pRamp
);
7218 IWineD3DSwapChain_Release(swapchain
);
7223 void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
7224 IWineD3DSwapChain
*swapchain
;
7225 HRESULT hrc
= WINED3D_OK
;
7227 TRACE("Relaying to swapchain\n");
7229 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == WINED3D_OK
) {
7230 hrc
=IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
7231 IWineD3DSwapChain_Release(swapchain
);
7237 /** ********************************************************
7238 * Notification functions
7239 ** ********************************************************/
7240 /** This function must be called in the release of a resource when ref == 0,
7241 * the contents of resource must still be correct,
7242 * any handels to other resource held by the caller must be closed
7243 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7244 *****************************************************/
7245 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7246 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7247 ResourceList
* resourceList
;
7249 TRACE("(%p) : resource %p\n", This
, resource
);
7251 EnterCriticalSection(&resourceStoreCriticalSection
);
7253 /* add a new texture to the frot of the linked list */
7254 resourceList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ResourceList
));
7255 resourceList
->resource
= resource
;
7257 /* Get the old head */
7258 resourceList
->next
= This
->resources
;
7260 This
->resources
= resourceList
;
7261 TRACE("Added resource %p with element %p pointing to %p\n", resource
, resourceList
, resourceList
->next
);
7264 LeaveCriticalSection(&resourceStoreCriticalSection
);
7269 static void WINAPI
IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7270 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7271 ResourceList
* resourceList
= NULL
;
7272 ResourceList
* previousResourceList
= NULL
;
7274 TRACE("(%p) : resource %p\n", This
, resource
);
7277 EnterCriticalSection(&resourceStoreCriticalSection
);
7279 resourceList
= This
->resources
;
7281 while (resourceList
!= NULL
) {
7282 if(resourceList
->resource
== resource
) break;
7283 previousResourceList
= resourceList
;
7284 resourceList
= resourceList
->next
;
7287 if (resourceList
== NULL
) {
7288 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource
);
7290 LeaveCriticalSection(&resourceStoreCriticalSection
);
7294 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList
->resource
, resourceList
, resourceList
->next
, previousResourceList
);
7296 /* make sure we don't leave a hole in the list */
7297 if (previousResourceList
!= NULL
) {
7298 previousResourceList
->next
= resourceList
->next
;
7300 This
->resources
= resourceList
->next
;
7304 LeaveCriticalSection(&resourceStoreCriticalSection
);
7310 void WINAPI
IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7311 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7314 TRACE("(%p) : resource %p\n", This
, resource
);
7315 switch(IWineD3DResource_GetType(resource
)){
7316 case WINED3DRTYPE_SURFACE
:
7317 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7319 case WINED3DRTYPE_TEXTURE
:
7320 case WINED3DRTYPE_CUBETEXTURE
:
7321 case WINED3DRTYPE_VOLUMETEXTURE
:
7322 for (counter
= 0; counter
< GL_LIMITS(textures
); counter
++) {
7323 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7324 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7325 This
->stateBlock
->textures
[counter
] = NULL
;
7327 if (This
->updateStateBlock
!= This
->stateBlock
){
7328 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7329 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7330 This
->updateStateBlock
->textures
[counter
] = NULL
;
7335 case WINED3DRTYPE_VOLUME
:
7336 /* TODO: nothing really? */
7338 case WINED3DRTYPE_VERTEXBUFFER
:
7339 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7342 TRACE("Cleaning up stream pointers\n");
7344 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
7345 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7346 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7348 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7349 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
7350 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
7351 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
7352 /* Set changed flag? */
7355 if (This
->stateBlock
!= NULL
) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
7356 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
7357 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
7358 This
->stateBlock
->streamSource
[streamNumber
] = 0;
7361 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7362 else { /* This shouldn't happen */
7363 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7370 case WINED3DRTYPE_INDEXBUFFER
:
7371 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7372 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7373 if (This
->updateStateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7374 This
->updateStateBlock
->pIndexData
= NULL
;
7377 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7378 if (This
->stateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7379 This
->stateBlock
->pIndexData
= NULL
;
7385 FIXME("(%p) unknown resource type %p %u\n", This
, resource
, IWineD3DResource_GetType(resource
));
7390 /* Remove the resoruce from the resourceStore */
7391 IWineD3DDeviceImpl_RemoveResource(iface
, resource
);
7393 TRACE("Resource released\n");
7397 /**********************************************************
7398 * IWineD3DDevice VTbl follows
7399 **********************************************************/
7401 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
7403 /*** IUnknown methods ***/
7404 IWineD3DDeviceImpl_QueryInterface
,
7405 IWineD3DDeviceImpl_AddRef
,
7406 IWineD3DDeviceImpl_Release
,
7407 /*** IWineD3DDevice methods ***/
7408 IWineD3DDeviceImpl_GetParent
,
7409 /*** Creation methods**/
7410 IWineD3DDeviceImpl_CreateVertexBuffer
,
7411 IWineD3DDeviceImpl_CreateIndexBuffer
,
7412 IWineD3DDeviceImpl_CreateStateBlock
,
7413 IWineD3DDeviceImpl_CreateSurface
,
7414 IWineD3DDeviceImpl_CreateTexture
,
7415 IWineD3DDeviceImpl_CreateVolumeTexture
,
7416 IWineD3DDeviceImpl_CreateVolume
,
7417 IWineD3DDeviceImpl_CreateCubeTexture
,
7418 IWineD3DDeviceImpl_CreateQuery
,
7419 IWineD3DDeviceImpl_CreateAdditionalSwapChain
,
7420 IWineD3DDeviceImpl_CreateVertexDeclaration
,
7421 IWineD3DDeviceImpl_CreateVertexShader
,
7422 IWineD3DDeviceImpl_CreatePixelShader
,
7423 IWineD3DDeviceImpl_CreatePalette
,
7424 /*** Odd functions **/
7425 IWineD3DDeviceImpl_Init3D
,
7426 IWineD3DDeviceImpl_Uninit3D
,
7427 IWineD3DDeviceImpl_EnumDisplayModes
,
7428 IWineD3DDeviceImpl_EvictManagedResources
,
7429 IWineD3DDeviceImpl_GetAvailableTextureMem
,
7430 IWineD3DDeviceImpl_GetBackBuffer
,
7431 IWineD3DDeviceImpl_GetCreationParameters
,
7432 IWineD3DDeviceImpl_GetDeviceCaps
,
7433 IWineD3DDeviceImpl_GetDirect3D
,
7434 IWineD3DDeviceImpl_GetDisplayMode
,
7435 IWineD3DDeviceImpl_SetDisplayMode
,
7436 IWineD3DDeviceImpl_GetHWND
,
7437 IWineD3DDeviceImpl_SetHWND
,
7438 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
7439 IWineD3DDeviceImpl_GetRasterStatus
,
7440 IWineD3DDeviceImpl_GetSwapChain
,
7441 IWineD3DDeviceImpl_Reset
,
7442 IWineD3DDeviceImpl_SetDialogBoxMode
,
7443 IWineD3DDeviceImpl_SetCursorProperties
,
7444 IWineD3DDeviceImpl_SetCursorPosition
,
7445 IWineD3DDeviceImpl_ShowCursor
,
7446 IWineD3DDeviceImpl_TestCooperativeLevel
,
7447 IWineD3DDeviceImpl_EnumZBufferFormats
,
7448 IWineD3DDeviceImpl_EnumTextureFormats
,
7449 /*** Getters and setters **/
7450 IWineD3DDeviceImpl_SetClipPlane
,
7451 IWineD3DDeviceImpl_GetClipPlane
,
7452 IWineD3DDeviceImpl_SetClipStatus
,
7453 IWineD3DDeviceImpl_GetClipStatus
,
7454 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
7455 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
7456 IWineD3DDeviceImpl_SetDepthStencilSurface
,
7457 IWineD3DDeviceImpl_GetDepthStencilSurface
,
7458 IWineD3DDeviceImpl_SetFVF
,
7459 IWineD3DDeviceImpl_GetFVF
,
7460 IWineD3DDeviceImpl_SetGammaRamp
,
7461 IWineD3DDeviceImpl_GetGammaRamp
,
7462 IWineD3DDeviceImpl_SetIndices
,
7463 IWineD3DDeviceImpl_GetIndices
,
7464 IWineD3DDeviceImpl_SetLight
,
7465 IWineD3DDeviceImpl_GetLight
,
7466 IWineD3DDeviceImpl_SetLightEnable
,
7467 IWineD3DDeviceImpl_GetLightEnable
,
7468 IWineD3DDeviceImpl_SetMaterial
,
7469 IWineD3DDeviceImpl_GetMaterial
,
7470 IWineD3DDeviceImpl_SetNPatchMode
,
7471 IWineD3DDeviceImpl_GetNPatchMode
,
7472 IWineD3DDeviceImpl_SetPaletteEntries
,
7473 IWineD3DDeviceImpl_GetPaletteEntries
,
7474 IWineD3DDeviceImpl_SetPixelShader
,
7475 IWineD3DDeviceImpl_GetPixelShader
,
7476 IWineD3DDeviceImpl_SetPixelShaderConstant
,
7477 IWineD3DDeviceImpl_GetPixelShaderConstant
,
7478 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
7479 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
7480 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
7481 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
7482 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
7483 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
7484 IWineD3DDeviceImpl_SetPixelShaderConstantN
,
7485 IWineD3DDeviceImpl_SetRenderState
,
7486 IWineD3DDeviceImpl_GetRenderState
,
7487 IWineD3DDeviceImpl_SetRenderTarget
,
7488 IWineD3DDeviceImpl_GetRenderTarget
,
7489 IWineD3DDeviceImpl_SetFrontBackBuffers
,
7490 IWineD3DDeviceImpl_SetSamplerState
,
7491 IWineD3DDeviceImpl_GetSamplerState
,
7492 IWineD3DDeviceImpl_SetScissorRect
,
7493 IWineD3DDeviceImpl_GetScissorRect
,
7494 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
7495 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
7496 IWineD3DDeviceImpl_SetStreamSource
,
7497 IWineD3DDeviceImpl_GetStreamSource
,
7498 IWineD3DDeviceImpl_SetStreamSourceFreq
,
7499 IWineD3DDeviceImpl_GetStreamSourceFreq
,
7500 IWineD3DDeviceImpl_SetTexture
,
7501 IWineD3DDeviceImpl_GetTexture
,
7502 IWineD3DDeviceImpl_SetTextureStageState
,
7503 IWineD3DDeviceImpl_GetTextureStageState
,
7504 IWineD3DDeviceImpl_SetTransform
,
7505 IWineD3DDeviceImpl_GetTransform
,
7506 IWineD3DDeviceImpl_SetVertexDeclaration
,
7507 IWineD3DDeviceImpl_GetVertexDeclaration
,
7508 IWineD3DDeviceImpl_SetVertexShader
,
7509 IWineD3DDeviceImpl_GetVertexShader
,
7510 IWineD3DDeviceImpl_SetVertexShaderConstant
,
7511 IWineD3DDeviceImpl_GetVertexShaderConstant
,
7512 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
7513 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
7514 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
7515 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
7516 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
7517 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
7518 IWineD3DDeviceImpl_SetVertexShaderConstantN
,
7519 IWineD3DDeviceImpl_SetViewport
,
7520 IWineD3DDeviceImpl_GetViewport
,
7521 IWineD3DDeviceImpl_MultiplyTransform
,
7522 IWineD3DDeviceImpl_ValidateDevice
,
7523 IWineD3DDeviceImpl_ProcessVertices
,
7524 /*** State block ***/
7525 IWineD3DDeviceImpl_BeginStateBlock
,
7526 IWineD3DDeviceImpl_EndStateBlock
,
7527 /*** Scene management ***/
7528 IWineD3DDeviceImpl_BeginScene
,
7529 IWineD3DDeviceImpl_EndScene
,
7530 IWineD3DDeviceImpl_Present
,
7531 IWineD3DDeviceImpl_Clear
,
7533 IWineD3DDeviceImpl_DrawPrimitive
,
7534 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
7535 IWineD3DDeviceImpl_DrawPrimitiveUP
,
7536 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
7537 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
7538 IWineD3DDeviceImpl_DrawRectPatch
,
7539 IWineD3DDeviceImpl_DrawTriPatch
,
7540 IWineD3DDeviceImpl_DeletePatch
,
7541 IWineD3DDeviceImpl_ColorFill
,
7542 IWineD3DDeviceImpl_UpdateTexture
,
7543 IWineD3DDeviceImpl_UpdateSurface
,
7544 IWineD3DDeviceImpl_CopyRects
,
7545 IWineD3DDeviceImpl_StretchRect
,
7546 IWineD3DDeviceImpl_GetRenderTargetData
,
7547 IWineD3DDeviceImpl_GetFrontBufferData
,
7548 /*** Internal use IWineD3DDevice methods ***/
7549 IWineD3DDeviceImpl_SetupTextureStates
,
7550 /*** object tracking ***/
7551 IWineD3DDeviceImpl_ResourceReleased
7555 const DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
7556 WINED3DRS_ALPHABLENDENABLE
,
7557 WINED3DRS_ALPHAFUNC
,
7558 WINED3DRS_ALPHAREF
,
7559 WINED3DRS_ALPHATESTENABLE
,
7561 WINED3DRS_COLORWRITEENABLE
,
7562 WINED3DRS_DESTBLEND
,
7563 WINED3DRS_DITHERENABLE
,
7564 WINED3DRS_FILLMODE
,
7565 WINED3DRS_FOGDENSITY
,
7567 WINED3DRS_FOGSTART
,
7568 WINED3DRS_LASTPIXEL
,
7569 WINED3DRS_SHADEMODE
,
7570 WINED3DRS_SRCBLEND
,
7571 WINED3DRS_STENCILENABLE
,
7572 WINED3DRS_STENCILFAIL
,
7573 WINED3DRS_STENCILFUNC
,
7574 WINED3DRS_STENCILMASK
,
7575 WINED3DRS_STENCILPASS
,
7576 WINED3DRS_STENCILREF
,
7577 WINED3DRS_STENCILWRITEMASK
,
7578 WINED3DRS_STENCILZFAIL
,
7579 WINED3DRS_TEXTUREFACTOR
,
7590 WINED3DRS_ZWRITEENABLE
7593 const DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
7594 WINED3DTSS_ADDRESSW
,
7595 WINED3DTSS_ALPHAARG0
,
7596 WINED3DTSS_ALPHAARG1
,
7597 WINED3DTSS_ALPHAARG2
,
7598 WINED3DTSS_ALPHAOP
,
7599 WINED3DTSS_BUMPENVLOFFSET
,
7600 WINED3DTSS_BUMPENVLSCALE
,
7601 WINED3DTSS_BUMPENVMAT00
,
7602 WINED3DTSS_BUMPENVMAT01
,
7603 WINED3DTSS_BUMPENVMAT10
,
7604 WINED3DTSS_BUMPENVMAT11
,
7605 WINED3DTSS_COLORARG0
,
7606 WINED3DTSS_COLORARG1
,
7607 WINED3DTSS_COLORARG2
,
7608 WINED3DTSS_COLOROP
,
7609 WINED3DTSS_RESULTARG
,
7610 WINED3DTSS_TEXCOORDINDEX
,
7611 WINED3DTSS_TEXTURETRANSFORMFLAGS
7614 const DWORD SavedPixelStates_S
[NUM_SAVEDPIXELSTATES_S
] = {
7615 WINED3DSAMP_ADDRESSU
,
7616 WINED3DSAMP_ADDRESSV
,
7617 WINED3DSAMP_ADDRESSW
,
7618 WINED3DSAMP_BORDERCOLOR
,
7619 WINED3DSAMP_MAGFILTER
,
7620 WINED3DSAMP_MINFILTER
,
7621 WINED3DSAMP_MIPFILTER
,
7622 WINED3DSAMP_MIPMAPLODBIAS
,
7623 WINED3DSAMP_MAXMIPLEVEL
,
7624 WINED3DSAMP_MAXANISOTROPY
,
7625 WINED3DSAMP_SRGBTEXTURE
,
7626 WINED3DSAMP_ELEMENTINDEX
7629 const DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
7631 WINED3DRS_AMBIENTMATERIALSOURCE
,
7632 WINED3DRS_CLIPPING
,
7633 WINED3DRS_CLIPPLANEENABLE
,
7634 WINED3DRS_COLORVERTEX
,
7635 WINED3DRS_DIFFUSEMATERIALSOURCE
,
7636 WINED3DRS_EMISSIVEMATERIALSOURCE
,
7637 WINED3DRS_FOGDENSITY
,
7639 WINED3DRS_FOGSTART
,
7640 WINED3DRS_FOGTABLEMODE
,
7641 WINED3DRS_FOGVERTEXMODE
,
7642 WINED3DRS_INDEXEDVERTEXBLENDENABLE
,
7643 WINED3DRS_LIGHTING
,
7644 WINED3DRS_LOCALVIEWER
,
7645 WINED3DRS_MULTISAMPLEANTIALIAS
,
7646 WINED3DRS_MULTISAMPLEMASK
,
7647 WINED3DRS_NORMALIZENORMALS
,
7648 WINED3DRS_PATCHEDGESTYLE
,
7649 WINED3DRS_POINTSCALE_A
,
7650 WINED3DRS_POINTSCALE_B
,
7651 WINED3DRS_POINTSCALE_C
,
7652 WINED3DRS_POINTSCALEENABLE
,
7653 WINED3DRS_POINTSIZE
,
7654 WINED3DRS_POINTSIZE_MAX
,
7655 WINED3DRS_POINTSIZE_MIN
,
7656 WINED3DRS_POINTSPRITEENABLE
,
7657 WINED3DRS_RANGEFOGENABLE
,
7658 WINED3DRS_SPECULARMATERIALSOURCE
,
7659 WINED3DRS_TWEENFACTOR
,
7660 WINED3DRS_VERTEXBLEND
7663 const DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
7664 WINED3DTSS_TEXCOORDINDEX
,
7665 WINED3DTSS_TEXTURETRANSFORMFLAGS
7668 const DWORD SavedVertexStates_S
[NUM_SAVEDVERTEXSTATES_S
] = {
7669 WINED3DSAMP_DMAPOFFSET