2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps
);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps
);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader
);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
39 X11DRV_GET_FONT
, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display
*get_display( HDC hdc
)
46 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
48 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
49 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram
= 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support
= FALSE
;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface
= FALSE
;
62 /* static function declarations */
63 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
);
65 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
);
68 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
70 #define D3DCREATEOBJECTINSTANCE(object, type) { \
71 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
72 D3DMEMCHECK(object, pp##type); \
73 object->lpVtbl = &IWineD3D##type##_Vtbl; \
74 object->wineD3DDevice = This; \
75 object->parent = parent; \
77 *pp##type = (IWineD3D##type *) object; \
80 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
81 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
82 D3DMEMCHECK(object, pp##type); \
83 object->lpVtbl = &IWineD3D##type##_Vtbl; \
84 object->resource.wineD3DDevice = This; \
85 object->resource.parent = parent; \
86 object->resource.resourceType = d3dtype; \
87 object->resource.ref = 1; \
88 object->resource.pool = Pool; \
89 object->resource.format = Format; \
90 object->resource.usage = Usage; \
91 object->resource.size = _size; \
92 /* Check that we have enough video ram left */ \
93 if (Pool == D3DPOOL_DEFAULT) { \
94 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
95 WARN("Out of 'bogus' video memory\n"); \
96 HeapFree(GetProcessHeap(), 0, object); \
98 return D3DERR_OUTOFVIDEOMEMORY; \
100 globalChangeGlRam(_size); \
102 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
103 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
104 FIXME("Out of memory!\n"); \
105 HeapFree(GetProcessHeap(), 0, object); \
107 return D3DERR_OUTOFVIDEOMEMORY; \
109 *pp##type = (IWineD3D##type *) object; \
110 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
111 TRACE("(%p) : Created resource %p\n", This, object); \
114 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
115 _basetexture.levels = Levels; \
116 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
117 _basetexture.LOD = 0; \
118 _basetexture.dirty = TRUE; \
121 /**********************************************************
122 * Global variable / Constants follow
123 **********************************************************/
124 const float identity
[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
129 /* Convert the D3DLIGHT properties into equivalent gl lights */
130 static void setup_light(IWineD3DDevice
*iface
, LONG Index
, PLIGHTINFOEL
*lightInfo
) {
133 float colRGBA
[] = {0.0, 0.0, 0.0, 0.0};
134 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
136 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
137 glMatrixMode(GL_MODELVIEW
);
139 glLoadMatrixf((float *)&This
->stateBlock
->transforms
[D3DTS_VIEW
].u
.m
[0][0]);
142 colRGBA
[0] = lightInfo
->OriginalParms
.Diffuse
.r
;
143 colRGBA
[1] = lightInfo
->OriginalParms
.Diffuse
.g
;
144 colRGBA
[2] = lightInfo
->OriginalParms
.Diffuse
.b
;
145 colRGBA
[3] = lightInfo
->OriginalParms
.Diffuse
.a
;
146 glLightfv(GL_LIGHT0
+Index
, GL_DIFFUSE
, colRGBA
);
147 checkGLcall("glLightfv");
150 colRGBA
[0] = lightInfo
->OriginalParms
.Specular
.r
;
151 colRGBA
[1] = lightInfo
->OriginalParms
.Specular
.g
;
152 colRGBA
[2] = lightInfo
->OriginalParms
.Specular
.b
;
153 colRGBA
[3] = lightInfo
->OriginalParms
.Specular
.a
;
154 glLightfv(GL_LIGHT0
+Index
, GL_SPECULAR
, colRGBA
);
155 checkGLcall("glLightfv");
158 colRGBA
[0] = lightInfo
->OriginalParms
.Ambient
.r
;
159 colRGBA
[1] = lightInfo
->OriginalParms
.Ambient
.g
;
160 colRGBA
[2] = lightInfo
->OriginalParms
.Ambient
.b
;
161 colRGBA
[3] = lightInfo
->OriginalParms
.Ambient
.a
;
162 glLightfv(GL_LIGHT0
+Index
, GL_AMBIENT
, colRGBA
);
163 checkGLcall("glLightfv");
165 /* Attenuation - Are these right? guessing... */
166 glLightf(GL_LIGHT0
+Index
, GL_CONSTANT_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation0
);
167 checkGLcall("glLightf");
168 glLightf(GL_LIGHT0
+Index
, GL_LINEAR_ATTENUATION
, lightInfo
->OriginalParms
.Attenuation1
);
169 checkGLcall("glLightf");
171 if ((lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
) != 0) {
172 quad_att
= 1.4/(lightInfo
->OriginalParms
.Range
*lightInfo
->OriginalParms
.Range
);
174 quad_att
= 0; /* 0 or MAX? (0 seems to be ok) */
177 if (quad_att
< lightInfo
->OriginalParms
.Attenuation2
) quad_att
= lightInfo
->OriginalParms
.Attenuation2
;
178 glLightf(GL_LIGHT0
+Index
, GL_QUADRATIC_ATTENUATION
, quad_att
);
179 checkGLcall("glLightf");
181 switch (lightInfo
->OriginalParms
.Type
) {
184 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
187 checkGLcall("glLightf");
193 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]);
194 checkGLcall("glLightfv");
196 glLightfv(GL_LIGHT0
+Index
, GL_SPOT_DIRECTION
, &lightInfo
->lightDirn
[0]);
197 checkGLcall("glLightfv");
198 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_EXPONENT
, lightInfo
->exponent
);
199 checkGLcall("glLightf");
200 glLightf(GL_LIGHT0
+ Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
201 checkGLcall("glLightf");
205 case D3DLIGHT_DIRECTIONAL
:
207 glLightfv(GL_LIGHT0
+Index
, GL_POSITION
, &lightInfo
->lightPosn
[0]); /* Note gl uses w position of 0 for direction! */
208 checkGLcall("glLightfv");
209 glLightf(GL_LIGHT0
+Index
, GL_SPOT_CUTOFF
, lightInfo
->cutoff
);
210 checkGLcall("glLightf");
211 glLightf(GL_LIGHT0
+Index
, GL_SPOT_EXPONENT
, 0.0f
);
212 checkGLcall("glLightf");
216 FIXME("Unrecognized light type %d\n", lightInfo
->OriginalParms
.Type
);
219 /* Restore the modelview matrix */
223 /* Apply the current values to the specified texture stage */
224 void WINAPI
IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice
*iface
, DWORD Sampler
, DWORD Flags
) {
225 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
233 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
234 clamping, MIPLOD, etc. This will work for up to 16 samplers.
237 if (Sampler
>= GL_LIMITS(samplers
)) {
238 FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler
, GL_LIMITS(samplers
));
241 VTRACE(("Activating appropriate texture state %ld\n", Sampler
));
242 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
244 GLACTIVETEXTURE(Sampler
);
246 /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
247 } else if (Sampler
> 0) {
248 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
252 /* TODO: change this to a lookup table
253 LOOKUP_TEXTURE_STATES lists all texture states that should be applied.
254 LOOKUP_CONTEXT_SATES list all context applicable states that can be applied
255 etc.... it's a lot cleaner, quicker and possibly easier to maintain than running a switch and setting a skip flag...
256 especially when there are a number of groups of states. */
258 TRACE("-----------------------> Updating the texture at Sampler %ld to have new texture state information\n", Sampler
);
260 /* 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 */
261 #define APPLY_STATE(_state) IWineD3DDeviceImpl_ApplyTextureUnitState(iface, Sampler, _state)
262 /* these are the only two supported states that need to be applied */
263 APPLY_STATE(WINED3DTSS_TEXCOORDINDEX
);
264 APPLY_STATE(WINED3DTSS_TEXTURETRANSFORMFLAGS
);
265 #if 0 /* not supported at the moment */
266 APPLY_STATE(WINED3DTSS_BUMPENVMAT00
);
267 APPLY_STATE(WINED3DTSS_BUMPENVMAT01
);
268 APPLY_STATE(WINED3DTSS_BUMPENVMAT10
);
269 APPLY_STATE(WINED3DTSS_BUMPENVMAT11
);
270 APPLY_STATE(WINED3DTSS_BUMPENVLSCALE
);
271 APPLY_STATE(WINED3DTSS_BUMPENVLOFFSET
);
272 APPLY_STATE(WINED3DTSS_RESULTARG
);
273 APPLY_STATE(WINED3DTSS_CONSTANT
);
275 /* a quick sanity check in case someone forgot to update this function */
276 if (WINED3D_HIGHEST_TEXTURE_STATE
> WINED3DTSS_CONSTANT
) {
277 FIXME("(%p) : There are more texture states than expected, update device.c to match\n", This
);
281 /* apply any sampler states that always need applying */
282 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS
)) {
283 tmpvalue
.d
= This
->stateBlock
->samplerState
[Sampler
][WINED3DSAMP_MIPMAPLODBIAS
];
284 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT
,
285 GL_TEXTURE_LOD_BIAS_EXT
,
287 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
294 /* Set the default alpha blend color */
295 glBlendColor(col
[0], col
[1], col
[2], col
[3]);
296 checkGLcall("glBlendColor");
298 D3DCOLORTOGLFLOAT4(This
->stateBlock
->renderState
[WINED3DRS_TEXTUREFACTOR
], col
);
299 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
300 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
302 TRACE("-----------------------> Updated the texture at Sampler %ld to have new texture state information\n", Sampler
);
305 /**********************************************************
306 * IUnknown parts follows
307 **********************************************************/
309 HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
311 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
312 /* FIXME: This needs to extend an IWineD3DBaseObject */
314 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
315 if (IsEqualGUID(riid
, &IID_IUnknown
)
316 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
317 IUnknown_AddRef(iface
);
322 return E_NOINTERFACE
;
325 ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
326 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
327 ULONG refCount
= InterlockedIncrement(&This
->ref
);
329 TRACE("(%p) : AddRef increasing from %ld\n", This
, refCount
- 1);
333 ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
334 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
335 ULONG refCount
= InterlockedDecrement(&This
->ref
);
337 TRACE("(%p) : Releasing from %ld\n", This
, refCount
+ 1);
340 /* TODO: Clean up all the surfaces and textures! */
341 /* FIXME: Create targets and state blocks in d3d8 */
342 if (((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
> 8) { /*We don't create a state block in d3d8 yet*/
343 /* NOTE: You must release the parent if the object was created via a callback
344 ** ***************************/
345 IUnknown
* swapChainParent
;
347 /* NOTE: Don't release swapchain 0 here, it's 'special' */
348 SwapChainList
*nextSwapchain
= This
->swapchains
;
349 if (nextSwapchain
!= NULL
) {
350 nextSwapchain
= nextSwapchain
->next
;
352 WARN("Expected to find the implicit swapchain\n");
355 /* release all the other swapchains */
356 while (nextSwapchain
!= NULL
) {
357 SwapChainList
*prevSwapchain
= nextSwapchain
;
358 nextSwapchain
= nextSwapchain
->next
;
359 IWineD3DSwapChain_Release(prevSwapchain
->swapchain
);
360 /* NOTE: no need to free the list element, it will be done by the release callback
361 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
364 if (This
->stateBlock
!= NULL
) {
365 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->stateBlock
);
368 if (This
->swapchains
!= NULL
) {
369 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
370 IWineD3DSwapChain_GetParent(This
->swapchains
->swapchain
, &swapChainParent
);
371 IUnknown_Release(swapChainParent
); /* once for the get parent */
372 if (IUnknown_Release(swapChainParent
) > 0) { /* the second time for when it was created */
373 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
378 IWineD3D_Release(This
->wineD3D
);
379 HeapFree(GetProcessHeap(), 0, This
);
384 /**********************************************************
385 * IWineD3DDevice implementation follows
386 **********************************************************/
387 HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
388 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
389 *pParent
= This
->parent
;
390 IUnknown_AddRef(This
->parent
);
394 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
395 DWORD FVF
, D3DPOOL Pool
, IWineD3DVertexBuffer
** ppVertexBuffer
, HANDLE
*sharedHandle
,
397 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
398 IWineD3DVertexBufferImpl
*object
;
399 WINED3DFORMAT Format
= WINED3DFMT_VERTEXDATA
; /* Dummy format for now */
400 D3DCREATERESOURCEOBJECTINSTANCE(object
, VertexBuffer
, D3DRTYPE_VERTEXBUFFER
, Size
)
403 if (Pool
== D3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
404 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->resource
.size
);
408 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This
, Size
, Usage
, FVF
, Pool
, object
->resource
.allocatedMemory
, object
);
409 *ppVertexBuffer
= (IWineD3DVertexBuffer
*)object
;
414 HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
415 WINED3DFORMAT Format
, D3DPOOL Pool
, IWineD3DIndexBuffer
** ppIndexBuffer
,
416 HANDLE
*sharedHandle
, IUnknown
*parent
) {
417 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
418 IWineD3DIndexBufferImpl
*object
;
419 TRACE("(%p) Creating index buffer\n", This
);
421 /* Allocate the storage for the device */
422 D3DCREATERESOURCEOBJECTINSTANCE(object
,IndexBuffer
,D3DRTYPE_INDEXBUFFER
, Length
)
425 if (Pool
== D3DPOOL_DEFAULT
) { /* Allocate some system memory for now */
426 object
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,object
->resource
.size
);
429 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This
, Length
, Usage
, Format
,
430 debug_d3dformat(Format
), Pool
, object
, object
->resource
.allocatedMemory
);
431 *ppIndexBuffer
= (IWineD3DIndexBuffer
*) object
;
436 HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
* iface
, WINED3DSTATEBLOCKTYPE Type
, IWineD3DStateBlock
** ppStateBlock
, IUnknown
*parent
) {
438 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
439 IWineD3DStateBlockImpl
*object
;
442 D3DCREATEOBJECTINSTANCE(object
, StateBlock
)
443 object
->blockType
= Type
;
445 /* Special case - Used during initialization to produce a placeholder stateblock
446 so other functions called can update a state block */
447 if (Type
== WINED3DSBT_INIT
) {
448 /* Don't bother increasing the reference count otherwise a device will never
449 be freed due to circular dependencies */
453 /* Otherwise, might as well set the whole state block to the appropriate values */
454 IWineD3DDevice_AddRef(iface
);
455 /* Otherwise, might as well set the whole state block to the appropriate values */
456 if ( This
->stateBlock
!= NULL
) {
457 memcpy(object
, This
->stateBlock
, sizeof(IWineD3DStateBlockImpl
));
459 memset(object
->streamFreq
, 1, sizeof(object
->streamFreq
));
462 /* Reset the ref and type after kludging it */
463 object
->wineD3DDevice
= This
;
465 object
->blockType
= Type
;
467 TRACE("Updating changed flags appropriate for type %d\n", Type
);
469 if (Type
== WINED3DSBT_ALL
) {
470 TRACE("ALL => Pretend everything has changed\n");
471 memset(&object
->changed
, TRUE
, sizeof(This
->stateBlock
->changed
));
472 } else if (Type
== WINED3DSBT_PIXELSTATE
) {
474 memset(&object
->changed
, FALSE
, sizeof(This
->stateBlock
->changed
));
475 /* TODO: Pixel Shader Constants */
476 object
->changed
.pixelShader
= TRUE
;
477 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
478 object
->changed
.renderState
[SavedPixelStates_R
[i
]] = TRUE
;
481 } else if (Type
== WINED3DSBT_VERTEXSTATE
) {
483 memset(&object
->changed
, FALSE
, sizeof(This
->stateBlock
->changed
));
484 /* TODO: Vertex Shader Constants */
485 object
->changed
.vertexShader
= TRUE
;
486 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
487 object
->changed
.renderState
[SavedVertexStates_R
[i
]] = TRUE
;
490 /* Duplicate light chain */
492 PLIGHTINFOEL
*src
= NULL
;
493 PLIGHTINFOEL
*dst
= NULL
;
494 PLIGHTINFOEL
*newEl
= NULL
;
495 src
= This
->stateBlock
->lights
;
496 object
->lights
= NULL
;
500 newEl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
501 if (newEl
== NULL
) return D3DERR_OUTOFVIDEOMEMORY
;
502 memcpy(newEl
, src
, sizeof(PLIGHTINFOEL
));
504 newEl
->changed
= TRUE
;
505 newEl
->enabledChanged
= TRUE
;
507 object
->lights
= newEl
;
518 FIXME("Unrecognized state block type %d\n", Type
);
521 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
526 /* ************************************
528 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
531 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
533 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.
535 ******************************** */
537 HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, WINED3DFORMAT Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, IWineD3DSurface
**ppSurface
,D3DRESOURCETYPE Type
, DWORD Usage
, D3DPOOL Pool
, D3DMULTISAMPLE_TYPE MultiSample
,DWORD MultisampleQuality
, HANDLE
* pSharedHandle
, IUnknown
*parent
) {
538 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
539 IWineD3DSurfaceImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
540 unsigned int pow2Width
, pow2Height
;
541 unsigned int Size
= 1;
542 TRACE("(%p) Create surface\n",This
);
544 /** FIXME: Check ranges on the inputs are valid
547 * [in] Quality level. The valid range is between zero and one less than the level
548 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
549 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
550 * values of paired render targets, depth stencil surfaces, and the MultiSample type
552 *******************************/
557 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
559 * If this flag is set, the contents of the depth stencil buffer will be
560 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
561 * with a different depth surface.
563 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
564 ***************************/
566 if(MultisampleQuality
< 0) {
567 FIXME("Invalid multisample level %ld \n", MultisampleQuality
);
568 return D3DERR_INVALIDCALL
; /* TODO: Check that this is the case! */
571 if(MultisampleQuality
> 0) {
572 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality
);
573 MultisampleQuality
=0;
576 /** FIXME: Check that the format is supported
578 *******************************/
579 /* TODO: add support for dxt2 and dxt4 formats */
580 if (Format
== D3DFMT_DXT2
|| Format
== D3DFMT_DXT4
) return D3DERR_NOTAVAILABLE
;
582 /* Non-power2 support */
584 /* Find the nearest pow2 match */
585 pow2Width
= pow2Height
= 1;
586 while (pow2Width
< Width
) pow2Width
<<= 1;
587 while (pow2Height
< Height
) pow2Height
<<= 1;
589 if (pow2Width
> Width
|| pow2Height
> Height
) {
590 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
591 if (Format
== WINED3DFMT_DXT1
|| Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
592 || Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
593 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
594 This
, Width
, Height
);
595 return D3DERR_NOTAVAILABLE
;
599 /** Check against the maximum texture sizes supported by the video card **/
600 if (pow2Width
> GL_LIMITS(texture_size
) || pow2Height
> GL_LIMITS(texture_size
)) {
601 /* one of three options
602 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
603 2: Set the texture to the maxium size (bad idea)
604 3: WARN and return D3DERR_NOTAVAILABLE;
606 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This
, Width
, Height
, GL_LIMITS(texture_size
));
607 return D3DERR_NOTAVAILABLE
;
612 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
613 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
615 *********************************/
616 if (Format
== WINED3DFMT_DXT1
) {
617 /* DXT1 is half byte per pixel */
618 Size
= ((max(pow2Width
,4) * D3DFmtGetBpp(This
, Format
)) * max(pow2Height
,4)) >> 1;
620 } else if (Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
621 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
622 Size
= ((max(pow2Width
,4) * D3DFmtGetBpp(This
, Format
)) * max(pow2Height
,4));
624 Size
= (pow2Width
* D3DFmtGetBpp(This
, Format
)) * pow2Height
;
627 /** Create the and initilise surface resource **/
628 D3DCREATERESOURCEOBJECTINSTANCE(object
,Surface
,D3DRTYPE_SURFACE
, Size
)
629 object
->container
= (IUnknown
*) This
;
631 object
->currentDesc
.Width
= Width
;
632 object
->currentDesc
.Height
= Height
;
633 object
->currentDesc
.MultiSampleType
= MultiSample
;
634 object
->currentDesc
.MultiSampleQuality
= MultisampleQuality
;
636 /* Setup some glformat defaults */
637 object
->glDescription
.glFormat
= D3DFmt2GLFmt(This
, object
->resource
.format
);
638 object
->glDescription
.glFormatInternal
= D3DFmt2GLIntFmt(This
, object
->resource
.format
);
639 object
->glDescription
.glType
= D3DFmt2GLType(This
, object
->resource
.format
);
640 object
->glDescription
.textureName
= 0;
641 object
->glDescription
.level
= Level
;
642 object
->glDescription
.target
= GL_TEXTURE_2D
;
645 object
->pow2Width
= pow2Width
;
646 object
->pow2Height
= pow2Height
;
647 object
->nonpow2
= (pow2Width
!= Width
|| pow2Height
!= Height
) ? TRUE
: FALSE
;
648 object
->discard
= Discard
;
649 object
->activeLock
= FALSE
;
650 object
->bytesPerPixel
= D3DFmtGetBpp(This
, Format
);
651 object
->pow2Size
= (pow2Width
* object
->bytesPerPixel
) * pow2Height
;
653 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
655 TRACE("Pool %d %d %d %d",Pool
, D3DPOOL_DEFAULT
, D3DPOOL_MANAGED
, D3DPOOL_SYSTEMMEM
);
657 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
658 * this function is too deap to need to care about things like this.
659 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
660 * ****************************************/
662 case D3DPOOL_SCRATCH
:
663 if(Lockable
== FALSE
)
664 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
665 which are mutually exclusive, setting lockable to true\n");
668 case D3DPOOL_SYSTEMMEM
:
669 if(Lockable
== FALSE
) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
670 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
671 case D3DPOOL_MANAGED
:
672 if(Usage
== D3DUSAGE_DYNAMIC
) FIXME("Create surface called with a pool of MANAGED and a \
673 Usage of DYNAMIC which are mutually exclusive, not doing \
674 anything just telling you.\n");
676 case D3DPOOL_DEFAULT
: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
677 if(!(Usage
& D3DUSAGE_DYNAMIC
) && !(Usage
& D3DUSAGE_RENDERTARGET
)
678 && !(Usage
&& D3DUSAGE_DEPTHSTENCIL
) && Lockable
== TRUE
)
679 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
682 FIXME("(%p) Unknown pool %d\n", This
, Pool
);
686 if (Usage
& D3DUSAGE_RENDERTARGET
&& Pool
!= D3DPOOL_DEFAULT
) {
687 FIXME("Trying to create a render target that isn't in the default pool\n");
691 object
->locked
= FALSE
;
692 object
->lockable
= (WINED3DFMT_D16_LOCKABLE
== Format
) ? TRUE
: Lockable
;
694 /* mark the texture as dirty so that it get's loaded first time around*/
695 IWineD3DSurface_AddDirtyRect(*ppSurface
, NULL
);
696 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
697 This
, Width
, Height
, Format
, debug_d3dformat(Format
),
698 (WINED3DFMT_D16_LOCKABLE
== Format
), *ppSurface
, object
->resource
.allocatedMemory
, object
->resource
.size
);
703 HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, UINT Levels
,
704 DWORD Usage
, WINED3DFORMAT Format
, D3DPOOL Pool
,
705 IWineD3DTexture
** ppTexture
, HANDLE
* pSharedHandle
, IUnknown
*parent
,
706 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
708 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
709 IWineD3DTextureImpl
*object
;
714 unsigned int pow2Width
= Width
;
715 unsigned int pow2Height
= Height
;
718 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This
, Width
, Height
, Levels
, Usage
);
720 D3DCREATERESOURCEOBJECTINSTANCE(object
, Texture
, D3DRTYPE_TEXTURE
, 0);
721 D3DINITILIZEBASETEXTURE(object
->baseTexture
);
722 object
->width
= Width
;
723 object
->height
= Height
;
725 /** Non-power2 support **/
726 /* Find the nearest pow2 match */
727 pow2Width
= pow2Height
= 1;
728 while (pow2Width
< Width
) pow2Width
<<= 1;
729 while (pow2Height
< Height
) pow2Height
<<= 1;
731 /** FIXME: add support for real non-power-two if it's provided by the video card **/
732 /* Precalculated scaling for 'faked' non power of two texture coords */
733 object
->pow2scalingFactorX
= (((float)Width
) / ((float)pow2Width
));
734 object
->pow2scalingFactorY
= (((float)Height
) / ((float)pow2Height
));
735 TRACE(" xf(%f) yf(%f) \n", object
->pow2scalingFactorX
, object
->pow2scalingFactorY
);
737 /* Calculate levels for mip mapping */
739 TRACE("calculating levels %d\n", object
->baseTexture
.levels
);
740 object
->baseTexture
.levels
++;
743 while (tmpW
> 1 && tmpH
> 1) {
744 tmpW
= max(1, tmpW
>> 1);
745 tmpH
= max(1, tmpH
>> 1);
746 object
->baseTexture
.levels
++;
748 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
751 /* Generate all the surfaces */
754 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
756 /* use the callback to create the texture surface */
757 hr
= D3DCB_CreateSurface(This
->parent
, tmpW
, tmpH
, Format
, Usage
, Pool
, i
, &object
->surfaces
[i
],NULL
);
760 FIXME("Failed to create surface %p \n",object
);
762 for(j
= 0 ; j
< i
; j
++) {
763 IWineD3DSurface_Release(object
->surfaces
[j
]);
765 /* heap free object */
766 HeapFree(GetProcessHeap(),0,object
);
772 IWineD3DSurface_SetContainer(object
->surfaces
[i
], (IUnknown
*)object
);
773 TRACE("Created surface level %d @ %p\n", i
, object
->surfaces
[i
]);
774 /* calculate the next mipmap level */
775 tmpW
= max(1, tmpW
>> 1);
776 tmpH
= max(1, tmpH
>> 1);
779 TRACE("(%p) : Created texture %p\n", This
, object
);
783 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
784 UINT Width
, UINT Height
, UINT Depth
,
785 UINT Levels
, DWORD Usage
,
786 WINED3DFORMAT Format
, D3DPOOL Pool
,
787 IWineD3DVolumeTexture
** ppVolumeTexture
,
788 HANDLE
* pSharedHandle
, IUnknown
*parent
,
789 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume
) {
791 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
792 IWineD3DVolumeTextureImpl
*object
;
798 D3DCREATERESOURCEOBJECTINSTANCE(object
, VolumeTexture
, D3DRTYPE_VOLUMETEXTURE
, 0);
799 D3DINITILIZEBASETEXTURE(object
->baseTexture
);
801 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
802 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
804 object
->width
= Width
;
805 object
->height
= Height
;
806 object
->depth
= Depth
;
808 /* Calculate levels for mip mapping */
810 object
->baseTexture
.levels
++;
814 while (tmpW
> 1 && tmpH
> 1 && tmpD
> 1) {
815 tmpW
= max(1, tmpW
>> 1);
816 tmpH
= max(1, tmpH
>> 1);
817 tmpD
= max(1, tmpD
>> 1);
818 object
->baseTexture
.levels
++;
820 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
823 /* Generate all the surfaces */
828 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
830 /* Create the volume */
831 D3DCB_CreateVolume(This
->parent
, Width
, Height
, Depth
, Format
, Pool
, Usage
,
832 (IWineD3DVolume
**)&object
->volumes
[i
], pSharedHandle
);
834 /* Set it's container to this object */
835 IWineD3DVolume_SetContainer(object
->volumes
[i
], (IUnknown
*)object
);
837 /* calcualte the next mipmap level */
838 tmpW
= max(1, tmpW
>> 1);
839 tmpH
= max(1, tmpH
>> 1);
840 tmpD
= max(1, tmpD
>> 1);
843 *ppVolumeTexture
= (IWineD3DVolumeTexture
*) object
;
844 TRACE("(%p) : Created volume texture %p\n", This
, object
);
848 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
,
849 UINT Width
, UINT Height
, UINT Depth
,
851 WINED3DFORMAT Format
, D3DPOOL Pool
,
852 IWineD3DVolume
** ppVolume
,
853 HANDLE
* pSharedHandle
, IUnknown
*parent
) {
855 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
856 IWineD3DVolumeImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
858 D3DCREATERESOURCEOBJECTINSTANCE(object
, Volume
, D3DRTYPE_VOLUME
, ((Width
* D3DFmtGetBpp(This
, Format
)) * Height
* Depth
))
860 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
861 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
863 object
->currentDesc
.Width
= Width
;
864 object
->currentDesc
.Height
= Height
;
865 object
->currentDesc
.Depth
= Depth
;
866 object
->bytesPerPixel
= D3DFmtGetBpp(This
, Format
);
868 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
869 object
->lockable
= TRUE
;
870 object
->locked
= FALSE
;
871 memset(&object
->lockedBox
, 0, sizeof(D3DBOX
));
872 object
->dirty
= TRUE
;
874 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume
*) object
, NULL
);
877 HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
,
878 UINT Levels
, DWORD Usage
,
879 WINED3DFORMAT Format
, D3DPOOL Pool
,
880 IWineD3DCubeTexture
** ppCubeTexture
,
881 HANDLE
* pSharedHandle
, IUnknown
*parent
,
882 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
884 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
885 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
889 unsigned int pow2EdgeLength
= EdgeLength
;
891 D3DCREATERESOURCEOBJECTINSTANCE(object
, CubeTexture
, D3DRTYPE_CUBETEXTURE
, 0);
892 D3DINITILIZEBASETEXTURE(object
->baseTexture
);
894 TRACE("(%p) Create Cube Texture \n", This
);
896 object
->edgeLength
= EdgeLength
;
898 /** Non-power2 support **/
900 /* Find the nearest pow2 match */
902 while (pow2EdgeLength
< EdgeLength
) pow2EdgeLength
<<= 1;
904 /* TODO: support for native non-power 2 */
905 /* Precalculated scaling for 'faked' non power of two texture coords */
906 object
->pow2scalingFactor
= ((float)EdgeLength
) / ((float)pow2EdgeLength
);
908 /* Calculate levels for mip mapping */
910 object
->baseTexture
.levels
++;
913 tmpW
= max(1, tmpW
/ 2);
914 object
->baseTexture
.levels
++;
916 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
919 /* Generate all the surfaces */
921 for (i
= 0; i
< object
->baseTexture
.levels
; i
++) {
923 /* Create the 6 faces */
924 for (j
= 0; j
< 6; j
++) {
926 hr
=D3DCB_CreateSurface(This
->parent
, tmpW
, tmpW
, Format
, Usage
, Pool
,
927 i
/* Level */, &object
->surfaces
[j
][i
],pSharedHandle
);
934 IWineD3DSurface_Release(object
->surfaces
[j
][i
]);
938 IWineD3DSurface_Release(object
->surfaces
[l
][j
]);
942 FIXME("(%p) Failed to create surface\n",object
);
943 HeapFree(GetProcessHeap(),0,object
);
944 *ppCubeTexture
= NULL
;
947 IWineD3DSurface_SetContainer(object
->surfaces
[j
][i
], (IUnknown
*)object
);
948 TRACE("Created surface level %d @ %p, \n", i
, object
->surfaces
[j
][i
]);
950 tmpW
= max(1, tmpW
>> 1);
953 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
954 *ppCubeTexture
= (IWineD3DCubeTexture
*) object
;
958 HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
, WINED3DQUERYTYPE Type
, IWineD3DQuery
**ppQuery
, IUnknown
* parent
) {
959 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
960 IWineD3DQueryImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
962 if(NULL
== ppQuery
) {
963 /* Just a check to see if we support this type of query */
964 HRESULT hr
= D3DERR_NOTAVAILABLE
;
965 /* Lie and say everything is good (we can return ok fake data from a stub) */
967 case WINED3DQUERYTYPE_VCACHE
:
968 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
969 case WINED3DQUERYTYPE_VERTEXSTATS
:
970 case WINED3DQUERYTYPE_EVENT
:
971 case WINED3DQUERYTYPE_OCCLUSION
:
972 case WINED3DQUERYTYPE_TIMESTAMP
:
973 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
974 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
975 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
976 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
977 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
978 case WINED3DQUERYTYPE_PIXELTIMINGS
:
979 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
980 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
984 FIXME("(%p) Unhandled query type %d\n",This
, Type
);
986 FIXME("(%p) : Stub request for query type %d returned %ld\n", This
, Type
, hr
);
990 D3DCREATEOBJECTINSTANCE(object
, Query
)
992 object
->extendedData
= 0;
993 TRACE("(%p) : Created Query %p\n", This
, object
);
997 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
998 HRESULT WINAPI
IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, IWineD3DSwapChain
** ppSwapChain
,
1000 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget
,
1001 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil
) {
1002 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1005 IWineD3DSwapChainImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1007 XVisualInfo
template;
1008 GLXContext oldContext
;
1009 Drawable oldDrawable
;
1010 HRESULT hr
= D3D_OK
;
1012 TRACE("(%p) : Created Aditional Swap Chain\n", This
);
1014 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1015 * does a device hold a reference to a swap chain giving them a lifetime of the device
1016 * or does the swap chain notify the device of it'd destruction.
1017 *******************************/
1019 D3DCREATEOBJECTINSTANCE(object
, SwapChain
)
1021 /* Initialize other useful values */
1022 object
->presentParms
.BackBufferCount
= 1; /* TODO:? support for gl_aux buffers */
1024 /*********************
1025 * Lookup the window Handle and the relating X window handle
1026 ********************/
1028 /* Setup hwnd we are using, plus which display this equates to */
1029 object
->win_handle
= *(pPresentationParameters
->hDeviceWindow
);
1030 if (!object
->win_handle
) {
1031 object
->win_handle
= This
->createParms
.hFocusWindow
;
1034 object
->win
= (Window
)GetPropA(object
->win_handle
, "__wine_x11_whole_window" );
1035 hDc
= GetDC(object
->win_handle
);
1036 object
->display
= get_display(hDc
);
1037 ReleaseDC(object
->win_handle
, hDc
);
1038 TRACE("Using a display of %p %p \n", object
->display
, hDc
);
1040 if (NULL
== object
->display
|| NULL
== hDc
) {
1041 WARN("Failed to get a display and HDc for Window %p\n", object
->win_handle
);
1042 return D3DERR_NOTAVAILABLE
;
1045 if (object
->win
== 0) {
1046 WARN("Failed to get a valid XVisuial ID for the window %p\n", object
->win_handle
);
1047 return D3DERR_NOTAVAILABLE
;
1050 * Create an opengl context for the display visual
1051 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1052 * use different properties after that point in time. FIXME: How to handle when requested format
1053 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1054 * it chooses is identical to the one already being used!
1055 **********************************/
1057 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1060 /* Create a new context for this swapchain */
1061 template.visualid
= (VisualID
)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1062 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1063 (or the best possible if none is requested) */
1064 TRACE("Found x visual ID : %ld\n", template.visualid
);
1066 object
->visInfo
= XGetVisualInfo(object
->display
, VisualIDMask
, &template, &num
);
1067 if (NULL
== object
->visInfo
) {
1068 ERR("cannot really get XVisual\n");
1070 return D3DERR_NOTAVAILABLE
;
1073 /* Write out some debug info about the visual/s */
1074 TRACE("Using x visual ID : %ld\n", template.visualid
);
1075 TRACE(" visual info: %p\n", object
->visInfo
);
1076 TRACE(" num items : %d\n", num
);
1077 for(n
= 0;n
< num
; n
++) {
1078 TRACE("=====item=====: %d\n", n
+ 1);
1079 TRACE(" visualid : %ld\n", object
->visInfo
[n
].visualid
);
1080 TRACE(" screen : %d\n", object
->visInfo
[n
].screen
);
1081 TRACE(" depth : %u\n", object
->visInfo
[n
].depth
);
1082 TRACE(" class : %d\n", object
->visInfo
[n
].class);
1083 TRACE(" red_mask : %ld\n", object
->visInfo
[n
].red_mask
);
1084 TRACE(" green_mask : %ld\n", object
->visInfo
[n
].green_mask
);
1085 TRACE(" blue_mask : %ld\n", object
->visInfo
[n
].blue_mask
);
1086 TRACE(" colormap_size : %d\n", object
->visInfo
[n
].colormap_size
);
1087 TRACE(" bits_per_rgb : %d\n", object
->visInfo
[n
].bits_per_rgb
);
1088 /* log some extra glx info */
1089 glXGetConfig(object
->display
, object
->visInfo
, GLX_AUX_BUFFERS
, &value
);
1090 TRACE(" gl_aux_buffers : %d\n", value
);
1091 glXGetConfig(object
->display
, object
->visInfo
, GLX_BUFFER_SIZE
,&value
);
1092 TRACE(" gl_buffer_size : %d\n", value
);
1093 glXGetConfig(object
->display
, object
->visInfo
, GLX_RED_SIZE
, &value
);
1094 TRACE(" gl_red_size : %d\n", value
);
1095 glXGetConfig(object
->display
, object
->visInfo
, GLX_GREEN_SIZE
, &value
);
1096 TRACE(" gl_green_size : %d\n", value
);
1097 glXGetConfig(object
->display
, object
->visInfo
, GLX_BLUE_SIZE
, &value
);
1098 TRACE(" gl_blue_size : %d\n", value
);
1099 glXGetConfig(object
->display
, object
->visInfo
, GLX_ALPHA_SIZE
, &value
);
1100 TRACE(" gl_alpha_size : %d\n", value
);
1101 glXGetConfig(object
->display
, object
->visInfo
, GLX_DEPTH_SIZE
,&value
);
1102 TRACE(" gl_depth_size : %d\n", value
);
1103 glXGetConfig(object
->display
, object
->visInfo
, GLX_STENCIL_SIZE
, &value
);
1104 TRACE(" gl_stencil_size : %d\n", value
);
1106 /* Now choose a simila visual ID*/
1108 #ifdef USE_CONTEXT_MANAGER
1110 /** TODO: use a context mamager **/
1114 IWineD3DSwapChain
*implSwapChain
;
1115 if (D3D_OK
!= IWineD3DDevice_GetSwapChain(iface
, 0, &implSwapChain
)) {
1116 /* The first time around we create the context that is shared with all other swapchains and render targets */
1117 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, NULL
, GL_TRUE
);
1118 TRACE("Creating implicit context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1121 TRACE("Creating context for vis %p, hwnd %p\n", object
->display
, object
->visInfo
);
1122 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1123 /* and create a new context with the implicit swapchains context as the shared context */
1124 object
->glCtx
= glXCreateContext(object
->display
, object
->visInfo
, ((IWineD3DSwapChainImpl
*)implSwapChain
)->glCtx
, GL_TRUE
);
1125 IWineD3DSwapChain_Release(implSwapChain
);
1130 XFree(object
->visInfo
);
1131 object
->visInfo
= NULL
;
1133 if (NULL
== object
->glCtx
) {
1134 ERR("cannot create glxContext\n");
1136 return D3DERR_NOTAVAILABLE
;
1140 if (object
->glCtx
== NULL
) {
1141 ERR("Error in context creation !\n");
1142 return D3DERR_INVALIDCALL
;
1144 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1145 object
->win_handle
, object
->glCtx
, object
->win
, object
->visInfo
);
1148 /*********************
1149 * Windowed / Fullscreen
1150 *******************/
1153 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1154 * so we should really check to see if their is a fullscreen swapchain already
1155 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1156 **************************************/
1158 if (!*(pPresentationParameters
->Windowed
)) {
1164 /* Get info on the current display setup */
1165 hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1166 bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
1169 /* Change the display settings */
1170 memset(&devmode
, 0, sizeof(DEVMODEW
));
1171 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1172 devmode
.dmBitsPerPel
= (bpp
>= 24) ? 32 : bpp
; /* Stupid XVidMode cannot change bpp */
1173 devmode
.dmPelsWidth
= *(pPresentationParameters
->BackBufferWidth
);
1174 devmode
.dmPelsHeight
= *(pPresentationParameters
->BackBufferHeight
);
1175 MultiByteToWideChar(CP_ACP
, 0, "Gamers CG", -1, devmode
.dmDeviceName
, CCHDEVICENAME
);
1176 ChangeDisplaySettingsExW(devmode
.dmDeviceName
, &devmode
, object
->win_handle
, CDS_FULLSCREEN
, NULL
);
1178 /* Make popup window */
1179 SetWindowLongA(object
->win_handle
, GWL_STYLE
, WS_POPUP
);
1180 SetWindowPos(object
->win_handle
, HWND_TOP
, 0, 0,
1181 *(pPresentationParameters
->BackBufferWidth
),
1182 *(pPresentationParameters
->BackBufferHeight
), SWP_SHOWWINDOW
| SWP_FRAMECHANGED
);
1188 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1189 * then the corresponding dimension of the client area of the hDeviceWindow
1190 * (or the focus window, if hDeviceWindow is NULL) is taken.
1191 **********************/
1193 if (*(pPresentationParameters
->Windowed
) &&
1194 ((*(pPresentationParameters
->BackBufferWidth
) == 0) ||
1195 (*(pPresentationParameters
->BackBufferHeight
) == 0))) {
1198 GetClientRect(object
->win_handle
, &Rect
);
1200 if (*(pPresentationParameters
->BackBufferWidth
) == 0) {
1201 *(pPresentationParameters
->BackBufferWidth
) = Rect
.right
;
1202 TRACE("Updating width to %d\n", *(pPresentationParameters
->BackBufferWidth
));
1204 if (*(pPresentationParameters
->BackBufferHeight
) == 0) {
1205 *(pPresentationParameters
->BackBufferHeight
) = Rect
.bottom
;
1206 TRACE("Updating height to %d\n", *(pPresentationParameters
->BackBufferHeight
));
1210 /*********************
1211 * finish off parameter initialization
1212 *******************/
1214 /* Put the correct figures in the presentation parameters */
1215 TRACE("Coppying accross presentaion paraneters\n");
1216 object
->presentParms
.BackBufferWidth
= *(pPresentationParameters
->BackBufferWidth
);
1217 object
->presentParms
.BackBufferHeight
= *(pPresentationParameters
->BackBufferHeight
);
1218 object
->presentParms
.BackBufferFormat
= *(pPresentationParameters
->BackBufferFormat
);
1219 object
->presentParms
.BackBufferCount
= *(pPresentationParameters
->BackBufferCount
);
1220 object
->presentParms
.MultiSampleType
= *(pPresentationParameters
->MultiSampleType
);
1221 object
->presentParms
.MultiSampleQuality
= *(pPresentationParameters
->MultiSampleQuality
);
1222 object
->presentParms
.SwapEffect
= *(pPresentationParameters
->SwapEffect
);
1223 object
->presentParms
.hDeviceWindow
= *(pPresentationParameters
->hDeviceWindow
);
1224 object
->presentParms
.Windowed
= *(pPresentationParameters
->Windowed
);
1225 object
->presentParms
.EnableAutoDepthStencil
= *(pPresentationParameters
->EnableAutoDepthStencil
);
1226 object
->presentParms
.AutoDepthStencilFormat
= *(pPresentationParameters
->AutoDepthStencilFormat
);
1227 object
->presentParms
.Flags
= *(pPresentationParameters
->Flags
);
1228 object
->presentParms
.FullScreen_RefreshRateInHz
= *(pPresentationParameters
->FullScreen_RefreshRateInHz
);
1229 object
->presentParms
.PresentationInterval
= *(pPresentationParameters
->PresentationInterval
);
1232 /*********************
1233 * Create the back, front and stencil buffers
1234 *******************/
1235 TRACE("calling rendertarget CB\n");
1236 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1237 object
->presentParms
.BackBufferWidth
,
1238 object
->presentParms
.BackBufferHeight
,
1239 object
->presentParms
.BackBufferFormat
,
1240 object
->presentParms
.MultiSampleType
,
1241 object
->presentParms
.MultiSampleQuality
,
1242 TRUE
/* Lockable */,
1243 &object
->frontBuffer
,
1244 NULL
/* pShared (always null)*/);
1245 if (object
->frontBuffer
!= NULL
)
1246 IWineD3DSurface_SetContainer(object
->frontBuffer
, (IUnknown
*)object
);
1247 TRACE("calling rendertarget CB\n");
1248 hr
= D3DCB_CreateRenderTarget((IUnknown
*) This
->parent
,
1249 object
->presentParms
.BackBufferWidth
,
1250 object
->presentParms
.BackBufferHeight
,
1251 object
->presentParms
.BackBufferFormat
,
1252 object
->presentParms
.MultiSampleType
,
1253 object
->presentParms
.MultiSampleQuality
,
1254 TRUE
/* Lockable */,
1255 &object
->backBuffer
,
1256 NULL
/* pShared (always null)*/);
1257 if (object
->backBuffer
!= NULL
)
1258 IWineD3DSurface_SetContainer(object
->backBuffer
, (IUnknown
*)object
);
1260 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1261 if (pPresentationParameters
->EnableAutoDepthStencil
) {
1262 TRACE("Creating depth stencil buffer\n");
1263 if (This
->depthStencilBuffer
== NULL
) {
1264 hr
= D3DCB_CreateDepthStencil((IUnknown
*) This
->parent
,
1265 object
->presentParms
.BackBufferWidth
,
1266 object
->presentParms
.BackBufferHeight
,
1267 object
->presentParms
.AutoDepthStencilFormat
,
1268 object
->presentParms
.MultiSampleType
,
1269 object
->presentParms
.MultiSampleQuality
,
1270 FALSE
/* FIXME: Discard */,
1271 &This
->depthStencilBuffer
,
1272 NULL
/* pShared (always null)*/ );
1273 if (This
->depthStencilBuffer
!= NULL
)
1274 IWineD3DSurface_SetContainer(This
->depthStencilBuffer
, (IUnknown
*)iface
);
1277 /** TODO: A check on width, height and multisample types
1278 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1279 ****************************/
1280 object
->wantsDepthStencilBuffer
= TRUE
;
1282 object
->wantsDepthStencilBuffer
= FALSE
;
1285 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object
->frontBuffer
, object
->backBuffer
, object
->wantsDepthStencilBuffer
);
1288 /*********************
1289 * init the default renderTarget management
1290 *******************/
1291 object
->drawable
= object
->win
;
1292 object
->render_ctx
= object
->glCtx
;
1295 /*********************
1296 * Setup some defaults and clear down the buffers
1297 *******************/
1299 /** save current context and drawable **/
1300 oldContext
= glXGetCurrentContext();
1301 oldDrawable
= glXGetCurrentDrawable();
1303 TRACE("Activating context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1304 if (glXMakeCurrent(object
->display
, object
->win
, object
->glCtx
) == False
) {
1305 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object
->display
, object
->glCtx
, object
->win
);
1307 checkGLcall("glXMakeCurrent");
1309 TRACE("Setting up the screen\n");
1310 /* Clear the screen */
1311 glClearColor(0.0, 0.0, 0.0, 0.0);
1312 checkGLcall("glClearColor");
1315 glClearStencil(0xffff);
1317 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_ACCUM_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
1318 checkGLcall("glClear");
1320 glColor3f(1.0, 1.0, 1.0);
1321 checkGLcall("glColor3f");
1323 glEnable(GL_LIGHTING
);
1324 checkGLcall("glEnable");
1326 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, GL_TRUE
);
1327 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1329 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1330 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1332 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL
, GL_SEPARATE_SPECULAR_COLOR
);
1333 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1335 /* switch back to the original context (unless it was zero)*/
1336 if (This
->swapchains
!= NULL
) {
1337 /** TODO: restore the context and drawable **/
1338 glXMakeCurrent(object
->display
, oldDrawable
, oldContext
);
1343 { /* Finally add the swapchain to the end of the devices' swapchain list */
1344 SwapChainList
**nextSwapchain
;
1345 nextSwapchain
= &This
->swapchains
;
1346 while(*nextSwapchain
!= NULL
) {
1347 nextSwapchain
= &((*nextSwapchain
)->next
);
1349 (*nextSwapchain
) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
->swapchains
));
1350 (*nextSwapchain
)->swapchain
= (IWineD3DSwapChain
*)object
;
1352 TRACE("Set swapchain to %p\n", object
);
1353 } else { /* something went wrong so clean up */
1354 IUnknown
* bufferParent
;
1355 if (object
->frontBuffer
) {
1356 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1357 IUnknown_Release(bufferParent
); /* once for the get parent */
1358 if(IUnknown_Release(bufferParent
) > 0) {
1359 FIXME("(%p) Something's still holding the front buffer\n",This
);
1362 if (object
->backBuffer
) {
1363 IWineD3DSurface_GetParent(object
->backBuffer
, &bufferParent
);
1364 IUnknown_Release(bufferParent
); /* once for the get parent */
1365 if(IUnknown_Release(bufferParent
) > 0) {
1366 FIXME("(%p) Something's still holding the back buffer\n",This
);
1369 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1370 /* Clean up the context */
1371 /* check that we are the current context first (we shouldn't be though!) */
1372 if (object
->glCtx
!= 0) {
1373 if(glXGetCurrentContext() == object
->glCtx
) {
1374 glXMakeCurrent(object
->display
, None
, NULL
);
1376 glXDestroyContext(object
->display
, object
->glCtx
);
1378 HeapFree(GetProcessHeap(), 0, object
);
1384 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1385 UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1386 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1387 unsigned int numberOfSwapChains
= 0;
1388 SwapChainList
*swapchain
;
1390 swapchain
= This
->swapchains
;
1391 /* itterate through the list to get a count */
1392 while (swapchain
!= NULL
) {
1393 swapchain
= swapchain
->next
;
1394 numberOfSwapChains
++;
1397 TRACE("(%p) returning %d\n", This
, numberOfSwapChains
);
1398 return numberOfSwapChains
;
1401 HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1402 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1403 SwapChainList
*swapchain
;
1404 HRESULT hr
= D3DERR_INVALIDCALL
;
1405 swapchain
= This
->swapchains
;
1406 TRACE("(%p) : swapchain %d \n", This
, iSwapChain
);
1409 TRACE("(%p) Finding swapchain %d\n", This
, iSwapChain
);
1410 while (iSwapChain
> 0 && swapchain
!= NULL
) {
1411 swapchain
= swapchain
->next
;
1415 if (iSwapChain
> 0 || swapchain
== NULL
) {
1416 FIXME("(%p) Unable to find swapchain %d\n", This
, iSwapChain
);
1419 /** TODO: move off to a linkesList implementation **/
1420 *pSwapChain
= swapchain
->swapchain
;
1421 IWineD3DSwapChain_AddRef(*pSwapChain
);
1425 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1429 HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
1430 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1432 FIXME("(%p) : Stub\n",This
);
1438 * Vertex Declaration
1440 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
* iface
, CONST VOID
* pDeclaration
, IWineD3DVertexDeclaration
** ppVertexDeclaration
, IUnknown
*parent
) {
1441 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1442 IWineD3DVertexDeclarationImpl
*object
= NULL
;
1443 HRESULT hr
= D3D_OK
;
1444 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This
, ((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
, pDeclaration
, ppVertexDeclaration
);
1445 D3DCREATEOBJECTINSTANCE(object
, VertexDeclaration
)
1448 hr
= IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration
*)object
, (void *)pDeclaration
);
1453 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1454 HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
* iface
, CONST DWORD
* pFunction
, IWineD3DVertexShader
** ppVertexShader
, IUnknown
*parent
) {
1455 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1456 IWineD3DVertexShaderImpl
*object
; /* NOTE: impl usage is ok, this is a create */
1457 D3DCREATEOBJECTINSTANCE(object
, VertexShader
)
1458 object
->function
= pFunction
;
1459 FIXME("(%p) : STUB: Created Vertex shader %p\n", This
, ppVertexShader
);
1464 HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
* iface
, CONST DWORD
* pFunction
, IWineD3DPixelShader
** ppPixelShader
, IUnknown
*parent
) {
1465 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1466 FIXME("(%p) : Stub\n", This
);
1470 HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
* iface
, IWineD3D
** ppD3D
) {
1471 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1472 *ppD3D
= This
->wineD3D
;
1473 TRACE("(%p) : wineD3D returning %p\n", This
, *ppD3D
);
1474 IWineD3D_AddRef(*ppD3D
);
1479 UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
1480 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1481 * Into the video ram as possible and seeing how many fit
1482 * you can also get the correct initial value from via X and ATI's driver
1483 *******************/
1484 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1485 static BOOL showfixmes
= TRUE
;
1487 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This
, (emulated_textureram
/(1024*1024)),
1488 ((emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
1491 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This
, (emulated_textureram
/(1024*1024)),
1492 ((emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
) / (1024*1024)));
1493 /* videomemory is simulated videomemory + AGP memory left */
1494 return (emulated_textureram
- wineD3DGlobalStatistics
->glsurfaceram
);
1502 HRESULT WINAPI
IWineD3DDeviceImpl_SetFVF(IWineD3DDevice
*iface
, DWORD fvf
) {
1503 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1505 /* Update the current state block */
1506 This
->updateStateBlock
->fvf
= fvf
;
1507 This
->updateStateBlock
->changed
.fvf
= TRUE
;
1508 This
->updateStateBlock
->set
.fvf
= TRUE
;
1510 TRACE("(%p) : FVF Shader FVF set to %lx\n", This
, fvf
);
1511 /* clear down the vertex declaration
1512 NOTE: Axis and Allies doesn't work properly otherwise
1513 (may be a stateblock problem though!)
1515 /* No difference if recording or not */
1516 return IWineD3DDevice_SetVertexDeclaration(iface
, NULL
);
1521 HRESULT WINAPI
IWineD3DDeviceImpl_GetFVF(IWineD3DDevice
*iface
, DWORD
*pfvf
) {
1522 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1523 TRACE("(%p) : GetFVF returning %lx\n", This
, This
->stateBlock
->fvf
);
1524 *pfvf
= This
->stateBlock
->fvf
;
1529 * Get / Set Stream Source
1531 HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
* pStreamData
, UINT OffsetInBytes
, UINT Stride
) {
1532 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1533 IWineD3DVertexBuffer
*oldSrc
;
1535 oldSrc
= This
->stateBlock
->streamSource
[StreamNumber
];
1536 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This
, StreamNumber
, oldSrc
, pStreamData
, Stride
);
1538 This
->updateStateBlock
->changed
.streamSource
[StreamNumber
] = TRUE
;
1539 This
->updateStateBlock
->set
.streamSource
[StreamNumber
] = TRUE
;
1540 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
1541 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
1542 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
1544 /* Handle recording of state blocks */
1545 if (This
->isRecordingState
) {
1546 TRACE("Recording... not performing anything\n");
1550 /* Not recording... */
1551 if (pStreamData
!= NULL
) {
1552 IUnknown
*newVertexBufferParent
;
1553 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1554 IWineD3DVertexBuffer_GetParent(pStreamData
, &newVertexBufferParent
);
1556 if (oldSrc
!= NULL
) {
1557 IUnknown
*oldVertexBufferParent
;
1558 IWineD3DVertexBuffer_GetParent(oldSrc
, &oldVertexBufferParent
);
1559 IUnknown_Release(oldVertexBufferParent
);
1560 IUnknown_Release(oldVertexBufferParent
);
1566 HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
** pStream
, UINT
*pOffset
, UINT
* pStride
) {
1567 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1569 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This
, StreamNumber
, This
->stateBlock
->streamSource
[StreamNumber
], This
->stateBlock
->streamStride
[StreamNumber
]);
1570 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
1571 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
1572 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
1573 if (*pStream
!= NULL
) IWineD3DVertexBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
1577 /*Should be quite easy, just an extension of vertexdata
1579 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1581 The divider is a bit odd though
1583 VertexOffset = StartVertex / Divider * StreamStride +
1584 VertexIndex / Divider * StreamStride + StreamOffset
1587 HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
1588 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1590 FIXME("(%p) : stub\n", This
);
1594 HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
1595 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1597 FIXME("(%p) : stub\n", This
);
1602 * Get / Set & Multiply Transform
1604 HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE d3dts
, CONST D3DMATRIX
* lpmatrix
) {
1605 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1607 /* Most of this routine, comments included copied from ddraw tree initially: */
1608 TRACE("(%p) : Transform State=%d\n", This
, d3dts
);
1610 /* Handle recording of state blocks */
1611 if (This
->isRecordingState
) {
1612 TRACE("Recording... not performing anything\n");
1613 This
->updateStateBlock
->changed
.transform
[d3dts
] = TRUE
;
1614 This
->updateStateBlock
->set
.transform
[d3dts
] = TRUE
;
1615 memcpy(&This
->updateStateBlock
->transforms
[d3dts
], lpmatrix
, sizeof(D3DMATRIX
));
1620 * If the new matrix is the same as the current one,
1621 * we cut off any further processing. this seems to be a reasonable
1622 * optimization because as was noticed, some apps (warcraft3 for example)
1623 * tend towards setting the same matrix repeatedly for some reason.
1625 * From here on we assume that the new matrix is different, wherever it matters.
1627 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(D3DMATRIX
))) {
1628 TRACE("The app is setting the same matrix over again\n");
1631 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
1635 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1636 where ViewMat = Camera space, WorldMat = world space.
1638 In OpenGL, camera and world space is combined into GL_MODELVIEW
1639 matrix. The Projection matrix stay projection matrix.
1642 /* Capture the times we can just ignore the change for now */
1643 if (d3dts
== D3DTS_WORLDMATRIX(0)) {
1644 This
->modelview_valid
= FALSE
;
1647 } else if (d3dts
== D3DTS_PROJECTION
) {
1648 This
->proj_valid
= FALSE
;
1651 } else if (d3dts
>= D3DTS_WORLDMATRIX(1) && d3dts
<= D3DTS_WORLDMATRIX(255)) {
1652 /* Indexed Vertex Blending Matrices 256 -> 511 */
1653 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1654 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1658 /* Now we really are going to have to change a matrix */
1661 if (d3dts
>= D3DTS_TEXTURE0
&& d3dts
<= D3DTS_TEXTURE7
) { /* handle texture matrices */
1662 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
1663 } else if (d3dts
== D3DTS_VIEW
) { /* handle the VIEW matrice */
1666 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1667 * NOTE: We have to reset the positions even if the light/plane is not currently
1668 * enabled, since the call to enable it will not reset the position.
1669 * NOTE2: Apparently texture transforms do NOT need reapplying
1672 PLIGHTINFOEL
*lightChain
= NULL
;
1673 This
->modelview_valid
= FALSE
;
1674 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
1676 glMatrixMode(GL_MODELVIEW
);
1677 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1679 glLoadMatrixf((float *)lpmatrix
);
1680 checkGLcall("glLoadMatrixf(...)");
1683 lightChain
= This
->stateBlock
->lights
;
1684 while (lightChain
&& lightChain
->glIndex
!= -1) {
1685 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_POSITION
, lightChain
->lightPosn
);
1686 checkGLcall("glLightfv posn");
1687 glLightfv(GL_LIGHT0
+ lightChain
->glIndex
, GL_SPOT_DIRECTION
, lightChain
->lightDirn
);
1688 checkGLcall("glLightfv dirn");
1689 lightChain
= lightChain
->next
;
1692 /* Reset Clipping Planes if clipping is enabled */
1693 for (k
= 0; k
< GL_LIMITS(clipplanes
); k
++) {
1694 glClipPlane(GL_CLIP_PLANE0
+ k
, This
->stateBlock
->clipplane
[k
]);
1695 checkGLcall("glClipPlane");
1699 } else { /* What was requested!?? */
1700 WARN("invalid matrix specified: %i\n", d3dts
);
1703 /* Release lock, all done */
1708 HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, D3DMATRIX
* pMatrix
) {
1709 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1710 TRACE("(%p) : for Transform State %d\n", This
, State
);
1711 memcpy(pMatrix
, &This
->stateBlock
->transforms
[State
], sizeof(D3DMATRIX
));
1715 HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, D3DTRANSFORMSTATETYPE State
, CONST D3DMATRIX
* pMatrix
) {
1716 D3DMATRIX
*mat
= NULL
;
1719 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1720 * below means it will be recorded in a state block change, but it
1721 * works regardless where it is recorded.
1722 * If this is found to be wrong, change to StateBlock.
1724 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1725 TRACE("(%p) : For state %u\n", This
, State
);
1727 if (State
< HIGHEST_TRANSFORMSTATE
)
1729 mat
= &This
->updateStateBlock
->transforms
[State
];
1731 FIXME("Unhandled transform state!!\n");
1734 /* Copied from ddraw code: */
1735 temp
.u
.s
._11
= (mat
->u
.s
._11
* pMatrix
->u
.s
._11
) + (mat
->u
.s
._21
* pMatrix
->u
.s
._12
) + (mat
->u
.s
._31
* pMatrix
->u
.s
._13
) + (mat
->u
.s
._41
* pMatrix
->u
.s
._14
);
1736 temp
.u
.s
._21
= (mat
->u
.s
._11
* pMatrix
->u
.s
._21
) + (mat
->u
.s
._21
* pMatrix
->u
.s
._22
) + (mat
->u
.s
._31
* pMatrix
->u
.s
._23
) + (mat
->u
.s
._41
* pMatrix
->u
.s
._24
);
1737 temp
.u
.s
._31
= (mat
->u
.s
._11
* pMatrix
->u
.s
._31
) + (mat
->u
.s
._21
* pMatrix
->u
.s
._32
) + (mat
->u
.s
._31
* pMatrix
->u
.s
._33
) + (mat
->u
.s
._41
* pMatrix
->u
.s
._34
);
1738 temp
.u
.s
._41
= (mat
->u
.s
._11
* pMatrix
->u
.s
._41
) + (mat
->u
.s
._21
* pMatrix
->u
.s
._42
) + (mat
->u
.s
._31
* pMatrix
->u
.s
._43
) + (mat
->u
.s
._41
* pMatrix
->u
.s
._44
);
1740 temp
.u
.s
._12
= (mat
->u
.s
._12
* pMatrix
->u
.s
._11
) + (mat
->u
.s
._22
* pMatrix
->u
.s
._12
) + (mat
->u
.s
._32
* pMatrix
->u
.s
._13
) + (mat
->u
.s
._42
* pMatrix
->u
.s
._14
);
1741 temp
.u
.s
._22
= (mat
->u
.s
._12
* pMatrix
->u
.s
._21
) + (mat
->u
.s
._22
* pMatrix
->u
.s
._22
) + (mat
->u
.s
._32
* pMatrix
->u
.s
._23
) + (mat
->u
.s
._42
* pMatrix
->u
.s
._24
);
1742 temp
.u
.s
._32
= (mat
->u
.s
._12
* pMatrix
->u
.s
._31
) + (mat
->u
.s
._22
* pMatrix
->u
.s
._32
) + (mat
->u
.s
._32
* pMatrix
->u
.s
._33
) + (mat
->u
.s
._42
* pMatrix
->u
.s
._34
);
1743 temp
.u
.s
._42
= (mat
->u
.s
._12
* pMatrix
->u
.s
._41
) + (mat
->u
.s
._22
* pMatrix
->u
.s
._42
) + (mat
->u
.s
._32
* pMatrix
->u
.s
._43
) + (mat
->u
.s
._42
* pMatrix
->u
.s
._44
);
1745 temp
.u
.s
._13
= (mat
->u
.s
._13
* pMatrix
->u
.s
._11
) + (mat
->u
.s
._23
* pMatrix
->u
.s
._12
) + (mat
->u
.s
._33
* pMatrix
->u
.s
._13
) + (mat
->u
.s
._43
* pMatrix
->u
.s
._14
);
1746 temp
.u
.s
._23
= (mat
->u
.s
._13
* pMatrix
->u
.s
._21
) + (mat
->u
.s
._23
* pMatrix
->u
.s
._22
) + (mat
->u
.s
._33
* pMatrix
->u
.s
._23
) + (mat
->u
.s
._43
* pMatrix
->u
.s
._24
);
1747 temp
.u
.s
._33
= (mat
->u
.s
._13
* pMatrix
->u
.s
._31
) + (mat
->u
.s
._23
* pMatrix
->u
.s
._32
) + (mat
->u
.s
._33
* pMatrix
->u
.s
._33
) + (mat
->u
.s
._43
* pMatrix
->u
.s
._34
);
1748 temp
.u
.s
._43
= (mat
->u
.s
._13
* pMatrix
->u
.s
._41
) + (mat
->u
.s
._23
* pMatrix
->u
.s
._42
) + (mat
->u
.s
._33
* pMatrix
->u
.s
._43
) + (mat
->u
.s
._43
* pMatrix
->u
.s
._44
);
1750 temp
.u
.s
._14
= (mat
->u
.s
._14
* pMatrix
->u
.s
._11
) + (mat
->u
.s
._24
* pMatrix
->u
.s
._12
) + (mat
->u
.s
._34
* pMatrix
->u
.s
._13
) + (mat
->u
.s
._44
* pMatrix
->u
.s
._14
);
1751 temp
.u
.s
._24
= (mat
->u
.s
._14
* pMatrix
->u
.s
._21
) + (mat
->u
.s
._24
* pMatrix
->u
.s
._22
) + (mat
->u
.s
._34
* pMatrix
->u
.s
._23
) + (mat
->u
.s
._44
* pMatrix
->u
.s
._24
);
1752 temp
.u
.s
._34
= (mat
->u
.s
._14
* pMatrix
->u
.s
._31
) + (mat
->u
.s
._24
* pMatrix
->u
.s
._32
) + (mat
->u
.s
._34
* pMatrix
->u
.s
._33
) + (mat
->u
.s
._44
* pMatrix
->u
.s
._34
);
1753 temp
.u
.s
._44
= (mat
->u
.s
._14
* pMatrix
->u
.s
._41
) + (mat
->u
.s
._24
* pMatrix
->u
.s
._42
) + (mat
->u
.s
._34
* pMatrix
->u
.s
._43
) + (mat
->u
.s
._44
* pMatrix
->u
.s
._44
);
1755 /* Apply change via set transform - will reapply to eg. lights this way */
1756 IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
1762 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1764 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1765 you can reference any indexes you want as long as that number max are enabled at any
1766 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1767 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1768 but when recording, just build a chain pretty much of commands to be replayed. */
1770 HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
1772 PLIGHTINFOEL
*object
, *temp
;
1774 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1775 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
1777 /* If recording state block, just add to end of lights chain */
1778 if (This
->isRecordingState
) {
1779 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
1780 if (NULL
== object
) {
1781 return D3DERR_OUTOFVIDEOMEMORY
;
1783 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
1784 object
->OriginalIndex
= Index
;
1785 object
->glIndex
= -1;
1786 object
->changed
= TRUE
;
1788 /* Add to the END of the chain of lights changes to be replayed */
1789 if (This
->updateStateBlock
->lights
== NULL
) {
1790 This
->updateStateBlock
->lights
= object
;
1792 temp
= This
->updateStateBlock
->lights
;
1793 while (temp
->next
!= NULL
) temp
=temp
->next
;
1794 temp
->next
= object
;
1796 TRACE("Recording... not performing anything more\n");
1800 /* Ok, not recording any longer so do real work */
1801 object
= This
->stateBlock
->lights
;
1802 while (object
!= NULL
&& object
->OriginalIndex
!= Index
) object
= object
->next
;
1804 /* If we didn't find it in the list of lights, time to add it */
1805 if (object
== NULL
) {
1806 PLIGHTINFOEL
*insertAt
,*prevPos
;
1808 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
1809 if (NULL
== object
) {
1810 return D3DERR_OUTOFVIDEOMEMORY
;
1812 object
->OriginalIndex
= Index
;
1813 object
->glIndex
= -1;
1815 /* Add it to the front of list with the idea that lights will be changed as needed
1816 BUT after any lights currently assigned GL indexes */
1817 insertAt
= This
->stateBlock
->lights
;
1819 while (insertAt
!= NULL
&& insertAt
->glIndex
!= -1) {
1821 insertAt
= insertAt
->next
;
1824 if (insertAt
== NULL
&& prevPos
== NULL
) { /* Start of list */
1825 This
->stateBlock
->lights
= object
;
1826 } else if (insertAt
== NULL
) { /* End of list */
1827 prevPos
->next
= object
;
1828 object
->prev
= prevPos
;
1829 } else { /* Middle of chain */
1830 if (prevPos
== NULL
) {
1831 This
->stateBlock
->lights
= object
;
1833 prevPos
->next
= object
;
1835 object
->prev
= prevPos
;
1836 object
->next
= insertAt
;
1837 insertAt
->prev
= object
;
1841 /* Initialze the object */
1842 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
,
1843 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
1844 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
1845 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
1846 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
1847 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
1848 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
1850 /* Save away the information */
1851 memcpy(&object
->OriginalParms
, pLight
, sizeof(D3DLIGHT9
));
1853 switch (pLight
->Type
) {
1854 case D3DLIGHT_POINT
:
1856 object
->lightPosn
[0] = pLight
->Position
.x
;
1857 object
->lightPosn
[1] = pLight
->Position
.y
;
1858 object
->lightPosn
[2] = pLight
->Position
.z
;
1859 object
->lightPosn
[3] = 1.0f
;
1860 object
->cutoff
= 180.0f
;
1864 case D3DLIGHT_DIRECTIONAL
:
1866 object
->lightPosn
[0] = -pLight
->Direction
.x
;
1867 object
->lightPosn
[1] = -pLight
->Direction
.y
;
1868 object
->lightPosn
[2] = -pLight
->Direction
.z
;
1869 object
->lightPosn
[3] = 0.0;
1870 object
->exponent
= 0.0f
;
1871 object
->cutoff
= 180.0f
;
1876 object
->lightPosn
[0] = pLight
->Position
.x
;
1877 object
->lightPosn
[1] = pLight
->Position
.y
;
1878 object
->lightPosn
[2] = pLight
->Position
.z
;
1879 object
->lightPosn
[3] = 1.0;
1882 object
->lightDirn
[0] = pLight
->Direction
.x
;
1883 object
->lightDirn
[1] = pLight
->Direction
.y
;
1884 object
->lightDirn
[2] = pLight
->Direction
.z
;
1885 object
->lightDirn
[3] = 1.0;
1888 * opengl-ish and d3d-ish spot lights use too different models for the
1889 * light "intensity" as a function of the angle towards the main light direction,
1890 * so we only can approximate very roughly.
1891 * however spot lights are rather rarely used in games (if ever used at all).
1892 * furthermore if still used, probably nobody pays attention to such details.
1894 if (pLight
->Falloff
== 0) {
1897 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
1899 if (rho
< 0.0001) rho
= 0.0001f
;
1900 object
->exponent
= -0.3/log(cos(rho
/2));
1901 object
->cutoff
= pLight
->Phi
*90/M_PI
;
1907 FIXME("Unrecognized light type %d\n", pLight
->Type
);
1910 /* Update the live definitions if the light is currently assigned a glIndex */
1911 if (object
->glIndex
!= -1) {
1912 setup_light(iface
, object
->glIndex
, object
);
1917 HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
* pLight
) {
1918 PLIGHTINFOEL
*lightInfo
= NULL
;
1919 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1920 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This
, Index
, pLight
);
1922 /* Locate the light in the live lights */
1923 lightInfo
= This
->stateBlock
->lights
;
1924 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
1926 if (lightInfo
== NULL
) {
1927 TRACE("Light information requested but light not defined\n");
1928 return D3DERR_INVALIDCALL
;
1931 memcpy(pLight
, &lightInfo
->OriginalParms
, sizeof(D3DLIGHT9
));
1936 * Get / Set Light Enable
1937 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1939 HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
) {
1940 PLIGHTINFOEL
*lightInfo
= NULL
;
1941 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1942 TRACE("(%p) : Idx(%ld), enable? %d\n", This
, Index
, Enable
);
1944 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1945 if (This
->isRecordingState
) {
1946 lightInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PLIGHTINFOEL
));
1947 if (NULL
== lightInfo
) {
1948 return D3DERR_OUTOFVIDEOMEMORY
;
1950 lightInfo
->OriginalIndex
= Index
;
1951 lightInfo
->glIndex
= -1;
1952 lightInfo
->enabledChanged
= TRUE
;
1954 /* Add to the END of the chain of lights changes to be replayed */
1955 if (This
->updateStateBlock
->lights
== NULL
) {
1956 This
->updateStateBlock
->lights
= lightInfo
;
1958 PLIGHTINFOEL
*temp
= This
->updateStateBlock
->lights
;
1959 while (temp
->next
!= NULL
) temp
=temp
->next
;
1960 temp
->next
= lightInfo
;
1962 TRACE("Recording... not performing anything more\n");
1966 /* Not recording... So, locate the light in the live lights */
1967 lightInfo
= This
->stateBlock
->lights
;
1968 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
1970 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1971 if (lightInfo
== NULL
) {
1972 D3DLIGHT9 lightParms
;
1973 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1974 wait until someone confirms it seems to work! */
1975 TRACE("Light enabled requested but light not defined, so defining one!\n");
1976 lightParms
.Type
= D3DLIGHT_DIRECTIONAL
;
1977 lightParms
.Diffuse
.r
= 1.0;
1978 lightParms
.Diffuse
.g
= 1.0;
1979 lightParms
.Diffuse
.b
= 1.0;
1980 lightParms
.Diffuse
.a
= 0.0;
1981 lightParms
.Specular
.r
= 0.0;
1982 lightParms
.Specular
.g
= 0.0;
1983 lightParms
.Specular
.b
= 0.0;
1984 lightParms
.Specular
.a
= 0.0;
1985 lightParms
.Ambient
.r
= 0.0;
1986 lightParms
.Ambient
.g
= 0.0;
1987 lightParms
.Ambient
.b
= 0.0;
1988 lightParms
.Ambient
.a
= 0.0;
1989 lightParms
.Position
.x
= 0.0;
1990 lightParms
.Position
.y
= 0.0;
1991 lightParms
.Position
.z
= 0.0;
1992 lightParms
.Direction
.x
= 0.0;
1993 lightParms
.Direction
.y
= 0.0;
1994 lightParms
.Direction
.z
= 1.0;
1995 lightParms
.Range
= 0.0;
1996 lightParms
.Falloff
= 0.0;
1997 lightParms
.Attenuation0
= 0.0;
1998 lightParms
.Attenuation1
= 0.0;
1999 lightParms
.Attenuation2
= 0.0;
2000 lightParms
.Theta
= 0.0;
2001 lightParms
.Phi
= 0.0;
2002 IWineD3DDeviceImpl_SetLight(iface
, Index
, &lightParms
);
2004 /* Search for it again! Should be fairly quick as near head of list */
2005 lightInfo
= This
->stateBlock
->lights
;
2006 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2007 if (lightInfo
== NULL
) {
2008 FIXME("Adding default lights has failed dismally\n");
2009 return D3DERR_INVALIDCALL
;
2013 /* OK, we now have a light... */
2014 if (Enable
== FALSE
) {
2016 /* If we are disabling it, check it was enabled, and
2017 still only do something if it has assigned a glIndex (which it should have!) */
2018 if ((lightInfo
->lightEnabled
) && (lightInfo
->glIndex
!= -1)) {
2019 TRACE("Disabling light set up at gl idx %ld\n", lightInfo
->glIndex
);
2021 glDisable(GL_LIGHT0
+ lightInfo
->glIndex
);
2022 checkGLcall("glDisable GL_LIGHT0+Index");
2025 TRACE("Nothing to do as light was not enabled\n");
2027 lightInfo
->lightEnabled
= FALSE
;
2030 /* We are enabling it. If it is enabled, it's really simple */
2031 if (lightInfo
->lightEnabled
) {
2033 TRACE("Nothing to do as light was enabled\n");
2035 /* If it already has a glIndex, it's still simple */
2036 } else if (lightInfo
->glIndex
!= -1) {
2037 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo
->glIndex
);
2038 lightInfo
->lightEnabled
= TRUE
;
2040 glEnable(GL_LIGHT0
+ lightInfo
->glIndex
);
2041 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2044 /* Otherwise got to find space - lights are ordered gl indexes first */
2046 PLIGHTINFOEL
*bsf
= NULL
;
2047 PLIGHTINFOEL
*pos
= This
->stateBlock
->lights
;
2048 PLIGHTINFOEL
*prev
= NULL
;
2052 /* Try to minimize changes as much as possible */
2053 while (pos
!= NULL
&& pos
->glIndex
!= -1 && Index
< This
->maxConcurrentLights
) {
2055 /* Try to remember which index can be replaced if necessary */
2056 if (bsf
==NULL
&& pos
->lightEnabled
== FALSE
) {
2057 /* Found a light we can replace, save as best replacement */
2061 /* Step to next space */
2067 /* If we have too many active lights, fail the call */
2068 if ((Index
== This
->maxConcurrentLights
) && (bsf
== NULL
)) {
2069 FIXME("Program requests too many concurrent lights\n");
2070 return D3DERR_INVALIDCALL
;
2072 /* If we have allocated all lights, but not all are enabled,
2073 reuse one which is not enabled */
2074 } else if (Index
== This
->maxConcurrentLights
) {
2075 /* use bsf - Simply swap the new light and the BSF one */
2076 PLIGHTINFOEL
*bsfNext
= bsf
->next
;
2077 PLIGHTINFOEL
*bsfPrev
= bsf
->prev
;
2080 if (lightInfo
->next
!= NULL
) lightInfo
->next
->prev
= bsf
;
2081 if (bsf
->prev
!= NULL
) {
2082 bsf
->prev
->next
= lightInfo
;
2084 This
->stateBlock
->lights
= lightInfo
;
2087 /* If not side by side, lots of chains to update */
2088 if (bsf
->next
!= lightInfo
) {
2089 lightInfo
->prev
->next
= bsf
;
2090 bsf
->next
->prev
= lightInfo
;
2091 bsf
->next
= lightInfo
->next
;
2092 bsf
->prev
= lightInfo
->prev
;
2093 lightInfo
->next
= bsfNext
;
2094 lightInfo
->prev
= bsfPrev
;
2098 bsf
->prev
= lightInfo
;
2099 bsf
->next
= lightInfo
->next
;
2100 lightInfo
->next
= bsf
;
2101 lightInfo
->prev
= bsfPrev
;
2106 glIndex
= bsf
->glIndex
;
2108 lightInfo
->glIndex
= glIndex
;
2109 lightInfo
->lightEnabled
= TRUE
;
2111 /* Finally set up the light in gl itself */
2112 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo
->glIndex
);
2114 setup_light(iface
, glIndex
, lightInfo
);
2115 glEnable(GL_LIGHT0
+ glIndex
);
2116 checkGLcall("glEnable GL_LIGHT0 new setup");
2119 /* If we reached the end of the allocated lights, with space in the
2120 gl lights, setup a new light */
2121 } else if (pos
->glIndex
== -1) {
2123 /* We reached the end of the allocated gl lights, so already
2124 know the index of the next one! */
2126 lightInfo
->glIndex
= glIndex
;
2127 lightInfo
->lightEnabled
= TRUE
;
2129 /* In an ideal world, it's already in the right place */
2130 if (lightInfo
->prev
== NULL
|| lightInfo
->prev
->glIndex
!=-1) {
2131 /* No need to move it */
2133 /* Remove this light from the list */
2134 lightInfo
->prev
->next
= lightInfo
->next
;
2135 if (lightInfo
->next
!= NULL
) {
2136 lightInfo
->next
->prev
= lightInfo
->prev
;
2139 /* Add in at appropriate place (inbetween prev and pos) */
2140 lightInfo
->prev
= prev
;
2141 lightInfo
->next
= pos
;
2143 This
->stateBlock
->lights
= lightInfo
;
2145 prev
->next
= lightInfo
;
2148 pos
->prev
= lightInfo
;
2152 /* Finally set up the light in gl itself */
2153 TRACE("Defining new light at gl idx %ld\n", lightInfo
->glIndex
);
2155 setup_light(iface
, glIndex
, lightInfo
);
2156 glEnable(GL_LIGHT0
+ glIndex
);
2157 checkGLcall("glEnable GL_LIGHT0 new setup");
2166 HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
) {
2168 PLIGHTINFOEL
*lightInfo
= NULL
;
2169 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2170 TRACE("(%p) : for idx(%ld)\n", This
, Index
);
2172 /* Locate the light in the live lights */
2173 lightInfo
= This
->stateBlock
->lights
;
2174 while (lightInfo
!= NULL
&& lightInfo
->OriginalIndex
!= Index
) lightInfo
= lightInfo
->next
;
2176 if (lightInfo
== NULL
) {
2177 TRACE("Light enabled state requested but light not defined\n");
2178 return D3DERR_INVALIDCALL
;
2180 *pEnable
= lightInfo
->lightEnabled
;
2185 * Get / Set Clip Planes
2187 HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
2188 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2189 TRACE("(%p) : for idx %ld, %p\n", This
, Index
, pPlane
);
2191 /* Validate Index */
2192 if (Index
>= GL_LIMITS(clipplanes
)) {
2193 TRACE("Application has requested clipplane this device doesn't support\n");
2194 return D3DERR_INVALIDCALL
;
2197 This
->updateStateBlock
->changed
.clipplane
[Index
] = TRUE
;
2198 This
->updateStateBlock
->set
.clipplane
[Index
] = TRUE
;
2199 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
2200 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
2201 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
2202 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
2204 /* Handle recording of state blocks */
2205 if (This
->isRecordingState
) {
2206 TRACE("Recording... not performing anything\n");
2214 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2215 glMatrixMode(GL_MODELVIEW
);
2217 glLoadMatrixf((float *) &This
->stateBlock
->transforms
[D3DTS_VIEW
].u
.m
[0][0]);
2219 TRACE("Clipplane [%f,%f,%f,%f]\n",
2220 This
->updateStateBlock
->clipplane
[Index
][0],
2221 This
->updateStateBlock
->clipplane
[Index
][1],
2222 This
->updateStateBlock
->clipplane
[Index
][2],
2223 This
->updateStateBlock
->clipplane
[Index
][3]);
2224 glClipPlane(GL_CLIP_PLANE0
+ Index
, This
->updateStateBlock
->clipplane
[Index
]);
2225 checkGLcall("glClipPlane");
2233 HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
2234 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2235 TRACE("(%p) : for idx %ld\n", This
, Index
);
2237 /* Validate Index */
2238 if (Index
>= GL_LIMITS(clipplanes
)) {
2239 TRACE("Application has requested clipplane this device doesn't support\n");
2240 return D3DERR_INVALIDCALL
;
2243 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
2244 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
2245 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
2246 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
2251 * Get / Set Clip Plane Status
2252 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2254 HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
2255 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2256 FIXME("(%p) : stub\n", This
);
2257 if (NULL
== pClipStatus
) {
2258 return D3DERR_INVALIDCALL
;
2260 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
2261 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
2265 HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
2266 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2267 FIXME("(%p) : stub\n", This
);
2268 if (NULL
== pClipStatus
) {
2269 return D3DERR_INVALIDCALL
;
2271 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
2272 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
2277 * Get / Set Material
2278 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2280 HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
2281 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2283 This
->updateStateBlock
->changed
.material
= TRUE
;
2284 This
->updateStateBlock
->set
.material
= TRUE
;
2285 memcpy(&This
->updateStateBlock
->material
, pMaterial
, sizeof(WINED3DMATERIAL
));
2287 /* Handle recording of state blocks */
2288 if (This
->isRecordingState
) {
2289 TRACE("Recording... not performing anything\n");
2294 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
, pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
2295 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
, pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
2296 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
, pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
2297 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
, pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
2298 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
2300 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, (float*) &This
->updateStateBlock
->material
.Ambient
);
2301 checkGLcall("glMaterialfv");
2302 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, (float*) &This
->updateStateBlock
->material
.Diffuse
);
2303 checkGLcall("glMaterialfv");
2305 /* Only change material color if specular is enabled, otherwise it is set to black */
2306 if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARENABLE
]) {
2307 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
2308 checkGLcall("glMaterialfv");
2310 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
2311 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
2312 checkGLcall("glMaterialfv");
2314 glMaterialfv(GL_FRONT_AND_BACK
, GL_EMISSION
, (float*) &This
->updateStateBlock
->material
.Emissive
);
2315 checkGLcall("glMaterialfv");
2316 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, This
->updateStateBlock
->material
.Power
);
2317 checkGLcall("glMaterialf");
2323 HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
2324 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2325 memcpy(pMaterial
, &This
->updateStateBlock
->material
, sizeof (WINED3DMATERIAL
));
2326 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
, pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
2327 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
, pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
2328 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
, pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
2329 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
, pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
2330 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
2337 HRESULT WINAPI
IWineD3DDeviceImpl_SetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
* pIndexData
,
2338 UINT BaseVertexIndex
) {
2339 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2340 IWineD3DIndexBuffer
*oldIdxs
;
2342 TRACE("(%p) : Setting to %p, base %d\n", This
, pIndexData
, BaseVertexIndex
);
2343 oldIdxs
= This
->updateStateBlock
->pIndexData
;
2345 This
->updateStateBlock
->changed
.indices
= TRUE
;
2346 This
->updateStateBlock
->set
.indices
= TRUE
;
2347 This
->updateStateBlock
->pIndexData
= pIndexData
;
2348 This
->updateStateBlock
->baseVertexIndex
= BaseVertexIndex
;
2350 /* Handle recording of state blocks */
2351 if (This
->isRecordingState
) {
2352 TRACE("Recording... not performing anything\n");
2357 IUnknown
*indexBufferParent
;
2358 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2359 IWineD3DIndexBuffer_GetParent(pIndexData
, &indexBufferParent
);
2362 IUnknown
*indexBufferParent
;
2363 IWineD3DIndexBuffer_GetParent(oldIdxs
, &indexBufferParent
);
2364 IUnknown_Release(indexBufferParent
);
2365 IUnknown_Release(indexBufferParent
);
2370 HRESULT WINAPI
IWineD3DDeviceImpl_GetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
** ppIndexData
, UINT
* pBaseVertexIndex
) {
2371 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2373 *ppIndexData
= This
->stateBlock
->pIndexData
;
2375 /* up ref count on ppindexdata */
2376 if (*ppIndexData
) IWineD3DIndexBuffer_AddRef(*ppIndexData
);
2377 *pBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
2383 * Get / Set Viewports
2385 HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
2386 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2388 TRACE("(%p)\n", This
);
2389 This
->updateStateBlock
->changed
.viewport
= TRUE
;
2390 This
->updateStateBlock
->set
.viewport
= TRUE
;
2391 memcpy(&This
->updateStateBlock
->viewport
, pViewport
, sizeof(WINED3DVIEWPORT
));
2393 /* Handle recording of state blocks */
2394 if (This
->isRecordingState
) {
2395 TRACE("Recording... not performing anything\n");
2401 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This
,
2402 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
2404 glDepthRange(pViewport
->MinZ
, pViewport
->MaxZ
);
2405 checkGLcall("glDepthRange");
2406 /* Note: GL requires lower left, DirectX supplies upper left */
2407 /* TODO: replace usage of renderTarget with context management */
2408 glViewport(pViewport
->X
,
2409 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- (pViewport
->Y
+ pViewport
->Height
)),
2410 pViewport
->Width
, pViewport
->Height
);
2412 checkGLcall("glViewport");
2420 HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
2421 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2422 TRACE("(%p)\n", This
);
2423 memcpy(pViewport
, &This
->stateBlock
->viewport
, sizeof(WINED3DVIEWPORT
));
2428 * Get / Set Render States
2429 * TODO: Verify against dx9 definitions
2431 HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD Value
) {
2433 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2434 DWORD OldValue
= This
->stateBlock
->renderState
[State
];
2436 /* Simple way of referring to either a DWORD or a 4 byte float */
2442 TRACE("(%p)->state = %s(%d), value = %ld\n", This
, debug_d3drenderstate(State
), State
, Value
);
2443 This
->updateStateBlock
->changed
.renderState
[State
] = TRUE
;
2444 This
->updateStateBlock
->set
.renderState
[State
] = TRUE
;
2445 This
->updateStateBlock
->renderState
[State
] = Value
;
2447 /* Handle recording of state blocks */
2448 if (This
->isRecordingState
) {
2449 TRACE("Recording... not performing anything\n");
2456 case WINED3DRS_FILLMODE
:
2457 switch ((D3DFILLMODE
) Value
) {
2458 case D3DFILL_POINT
: glPolygonMode(GL_FRONT_AND_BACK
, GL_POINT
); break;
2459 case D3DFILL_WIREFRAME
: glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
); break;
2460 case D3DFILL_SOLID
: glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
); break;
2462 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value
);
2464 checkGLcall("glPolygonMode (fillmode)");
2467 case WINED3DRS_LIGHTING
:
2469 glEnable(GL_LIGHTING
);
2470 checkGLcall("glEnable GL_LIGHTING");
2472 glDisable(GL_LIGHTING
);
2473 checkGLcall("glDisable GL_LIGHTING");
2477 case WINED3DRS_ZENABLE
:
2478 switch ((D3DZBUFFERTYPE
) Value
) {
2480 glDisable(GL_DEPTH_TEST
);
2481 checkGLcall("glDisable GL_DEPTH_TEST");
2484 glEnable(GL_DEPTH_TEST
);
2485 checkGLcall("glEnable GL_DEPTH_TEST");
2488 glEnable(GL_DEPTH_TEST
);
2489 checkGLcall("glEnable GL_DEPTH_TEST");
2490 FIXME("W buffer is not well handled\n");
2493 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value
);
2497 case WINED3DRS_CULLMODE
:
2499 /* If we are culling "back faces with clockwise vertices" then
2500 set front faces to be counter clockwise and enable culling
2502 switch ((D3DCULL
) Value
) {
2504 glDisable(GL_CULL_FACE
);
2505 checkGLcall("glDisable GL_CULL_FACE");
2508 glEnable(GL_CULL_FACE
);
2509 checkGLcall("glEnable GL_CULL_FACE");
2510 if (This
->renderUpsideDown
) {
2512 checkGLcall("glFrontFace GL_CW");
2514 glFrontFace(GL_CCW
);
2515 checkGLcall("glFrontFace GL_CCW");
2517 glCullFace(GL_BACK
);
2520 glEnable(GL_CULL_FACE
);
2521 checkGLcall("glEnable GL_CULL_FACE");
2522 if (This
->renderUpsideDown
) {
2523 glFrontFace(GL_CCW
);
2524 checkGLcall("glFrontFace GL_CCW");
2527 checkGLcall("glFrontFace GL_CW");
2529 glCullFace(GL_BACK
);
2532 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value
);
2536 case WINED3DRS_SHADEMODE
:
2537 switch ((D3DSHADEMODE
) Value
) {
2539 glShadeModel(GL_FLAT
);
2540 checkGLcall("glShadeModel");
2542 case D3DSHADE_GOURAUD
:
2543 glShadeModel(GL_SMOOTH
);
2544 checkGLcall("glShadeModel");
2546 case D3DSHADE_PHONG
:
2547 FIXME("D3DSHADE_PHONG isn't supported?\n");
2550 return D3DERR_INVALIDCALL
;
2552 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value
);
2556 case WINED3DRS_DITHERENABLE
:
2558 glEnable(GL_DITHER
);
2559 checkGLcall("glEnable GL_DITHER");
2561 glDisable(GL_DITHER
);
2562 checkGLcall("glDisable GL_DITHER");
2566 case WINED3DRS_ZWRITEENABLE
:
2569 checkGLcall("glDepthMask");
2572 checkGLcall("glDepthMask");
2576 case WINED3DRS_ZFUNC
:
2578 int glParm
= GL_LESS
;
2580 switch ((D3DCMPFUNC
) Value
) {
2581 case D3DCMP_NEVER
: glParm
=GL_NEVER
; break;
2582 case D3DCMP_LESS
: glParm
=GL_LESS
; break;
2583 case D3DCMP_EQUAL
: glParm
=GL_EQUAL
; break;
2584 case D3DCMP_LESSEQUAL
: glParm
=GL_LEQUAL
; break;
2585 case D3DCMP_GREATER
: glParm
=GL_GREATER
; break;
2586 case D3DCMP_NOTEQUAL
: glParm
=GL_NOTEQUAL
; break;
2587 case D3DCMP_GREATEREQUAL
: glParm
=GL_GEQUAL
; break;
2588 case D3DCMP_ALWAYS
: glParm
=GL_ALWAYS
; break;
2590 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
2592 glDepthFunc(glParm
);
2593 checkGLcall("glDepthFunc");
2597 case WINED3DRS_AMBIENT
:
2600 D3DCOLORTOGLFLOAT4(Value
, col
);
2601 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col
[0], col
[1], col
[2], col
[3]);
2602 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, col
);
2603 checkGLcall("glLightModel for MODEL_AMBIENT");
2608 case WINED3DRS_ALPHABLENDENABLE
:
2611 checkGLcall("glEnable GL_BLEND");
2613 glDisable(GL_BLEND
);
2614 checkGLcall("glDisable GL_BLEND");
2618 case WINED3DRS_SRCBLEND
:
2619 case WINED3DRS_DESTBLEND
:
2621 int newVal
= GL_ZERO
;
2623 case D3DBLEND_ZERO
: newVal
= GL_ZERO
; break;
2624 case D3DBLEND_ONE
: newVal
= GL_ONE
; break;
2625 case D3DBLEND_SRCCOLOR
: newVal
= GL_SRC_COLOR
; break;
2626 case D3DBLEND_INVSRCCOLOR
: newVal
= GL_ONE_MINUS_SRC_COLOR
; break;
2627 case D3DBLEND_SRCALPHA
: newVal
= GL_SRC_ALPHA
; break;
2628 case D3DBLEND_INVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
; break;
2629 case D3DBLEND_DESTALPHA
: newVal
= GL_DST_ALPHA
; break;
2630 case D3DBLEND_INVDESTALPHA
: newVal
= GL_ONE_MINUS_DST_ALPHA
; break;
2631 case D3DBLEND_DESTCOLOR
: newVal
= GL_DST_COLOR
; break;
2632 case D3DBLEND_INVDESTCOLOR
: newVal
= GL_ONE_MINUS_DST_COLOR
; break;
2633 case D3DBLEND_SRCALPHASAT
: newVal
= GL_SRC_ALPHA_SATURATE
; break;
2635 case D3DBLEND_BOTHSRCALPHA
: newVal
= GL_SRC_ALPHA
;
2636 This
->srcBlend
= newVal
;
2637 This
->dstBlend
= newVal
;
2640 case D3DBLEND_BOTHINVSRCALPHA
: newVal
= GL_ONE_MINUS_SRC_ALPHA
;
2641 This
->srcBlend
= newVal
;
2642 This
->dstBlend
= newVal
;
2645 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value
, State
);
2648 if (State
== WINED3DRS_SRCBLEND
) This
->srcBlend
= newVal
;
2649 if (State
== WINED3DRS_DESTBLEND
) This
->dstBlend
= newVal
;
2650 TRACE("glBlendFunc src=%x, dst=%x\n", This
->srcBlend
, This
->dstBlend
);
2651 glBlendFunc(This
->srcBlend
, This
->dstBlend
);
2653 checkGLcall("glBlendFunc");
2657 case WINED3DRS_ALPHATESTENABLE
:
2659 glEnable(GL_ALPHA_TEST
);
2660 checkGLcall("glEnable GL_ALPHA_TEST");
2662 glDisable(GL_ALPHA_TEST
);
2663 checkGLcall("glDisable GL_ALPHA_TEST");
2667 case WINED3DRS_ALPHAFUNC
:
2669 int glParm
= GL_LESS
;
2670 float ref
= ((float) This
->stateBlock
->renderState
[WINED3DRS_ALPHAREF
]) / 255.0f
;
2672 switch ((D3DCMPFUNC
) Value
) {
2673 case D3DCMP_NEVER
: glParm
= GL_NEVER
; break;
2674 case D3DCMP_LESS
: glParm
= GL_LESS
; break;
2675 case D3DCMP_EQUAL
: glParm
= GL_EQUAL
; break;
2676 case D3DCMP_LESSEQUAL
: glParm
= GL_LEQUAL
; break;
2677 case D3DCMP_GREATER
: glParm
= GL_GREATER
; break;
2678 case D3DCMP_NOTEQUAL
: glParm
= GL_NOTEQUAL
; break;
2679 case D3DCMP_GREATEREQUAL
: glParm
= GL_GEQUAL
; break;
2680 case D3DCMP_ALWAYS
: glParm
= GL_ALWAYS
; break;
2682 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
2684 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm
, ref
);
2685 glAlphaFunc(glParm
, ref
);
2686 This
->alphafunc
= glParm
;
2687 checkGLcall("glAlphaFunc");
2691 case WINED3DRS_ALPHAREF
:
2693 int glParm
= This
->alphafunc
;
2696 ref
= ((float) Value
) / 255.0f
;
2697 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm
, ref
);
2698 glAlphaFunc(glParm
, ref
);
2699 checkGLcall("glAlphaFunc");
2703 case WINED3DRS_CLIPPLANEENABLE
:
2704 case WINED3DRS_CLIPPING
:
2706 /* Ensure we only do the changed clip planes */
2707 DWORD enable
= 0xFFFFFFFF;
2708 DWORD disable
= 0x00000000;
2710 /* If enabling / disabling all */
2711 if (State
== WINED3DRS_CLIPPING
) {
2713 enable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
2716 disable
= This
->stateBlock
->renderState
[WINED3DRS_CLIPPLANEENABLE
];
2720 enable
= Value
& ~OldValue
;
2721 disable
= ~Value
& OldValue
;
2724 if (enable
& D3DCLIPPLANE0
) { glEnable(GL_CLIP_PLANE0
); checkGLcall("glEnable(clip plane 0)"); }
2725 if (enable
& D3DCLIPPLANE1
) { glEnable(GL_CLIP_PLANE1
); checkGLcall("glEnable(clip plane 1)"); }
2726 if (enable
& D3DCLIPPLANE2
) { glEnable(GL_CLIP_PLANE2
); checkGLcall("glEnable(clip plane 2)"); }
2727 if (enable
& D3DCLIPPLANE3
) { glEnable(GL_CLIP_PLANE3
); checkGLcall("glEnable(clip plane 3)"); }
2728 if (enable
& D3DCLIPPLANE4
) { glEnable(GL_CLIP_PLANE4
); checkGLcall("glEnable(clip plane 4)"); }
2729 if (enable
& D3DCLIPPLANE5
) { glEnable(GL_CLIP_PLANE5
); checkGLcall("glEnable(clip plane 5)"); }
2731 if (disable
& D3DCLIPPLANE0
) { glDisable(GL_CLIP_PLANE0
); checkGLcall("glDisable(clip plane 0)"); }
2732 if (disable
& D3DCLIPPLANE1
) { glDisable(GL_CLIP_PLANE1
); checkGLcall("glDisable(clip plane 1)"); }
2733 if (disable
& D3DCLIPPLANE2
) { glDisable(GL_CLIP_PLANE2
); checkGLcall("glDisable(clip plane 2)"); }
2734 if (disable
& D3DCLIPPLANE3
) { glDisable(GL_CLIP_PLANE3
); checkGLcall("glDisable(clip plane 3)"); }
2735 if (disable
& D3DCLIPPLANE4
) { glDisable(GL_CLIP_PLANE4
); checkGLcall("glDisable(clip plane 4)"); }
2736 if (disable
& D3DCLIPPLANE5
) { glDisable(GL_CLIP_PLANE5
); checkGLcall("glDisable(clip plane 5)"); }
2738 /** update clipping status */
2740 This
->stateBlock
->clip_status
.ClipUnion
= 0;
2741 This
->stateBlock
->clip_status
.ClipIntersection
= 0xFFFFFFFF;
2743 This
->stateBlock
->clip_status
.ClipUnion
= 0;
2744 This
->stateBlock
->clip_status
.ClipIntersection
= 0;
2749 case WINED3DRS_BLENDOP
:
2751 int glParm
= GL_FUNC_ADD
;
2753 switch ((D3DBLENDOP
) Value
) {
2754 case D3DBLENDOP_ADD
: glParm
= GL_FUNC_ADD
; break;
2755 case D3DBLENDOP_SUBTRACT
: glParm
= GL_FUNC_SUBTRACT
; break;
2756 case D3DBLENDOP_REVSUBTRACT
: glParm
= GL_FUNC_REVERSE_SUBTRACT
; break;
2757 case D3DBLENDOP_MIN
: glParm
= GL_MIN
; break;
2758 case D3DBLENDOP_MAX
: glParm
= GL_MAX
; break;
2760 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value
);
2762 TRACE("glBlendEquation(%x)\n", glParm
);
2763 glBlendEquation(glParm
);
2764 checkGLcall("glBlendEquation");
2768 case WINED3DRS_TEXTUREFACTOR
:
2772 /* Note the texture color applies to all textures whereas
2773 GL_TEXTURE_ENV_COLOR applies to active only */
2775 D3DCOLORTOGLFLOAT4(Value
, col
);
2776 /* Set the default alpha blend color */
2777 glBlendColor(col
[0], col
[1], col
[2], col
[3]);
2778 checkGLcall("glBlendColor");
2780 /* And now the default texture color as well */
2781 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
2783 /* Note the D3DRS value applies to all textures, but GL has one
2784 per texture, so apply it now ready to be used! */
2785 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
2788 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2791 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, &col
[0]);
2792 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2797 case WINED3DRS_SPECULARENABLE
:
2799 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2800 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2801 specular color. This is wrong:
2802 Separate specular color means the specular colour is maintained separately, whereas
2803 single color means it is merged in. However in both cases they are being used to
2805 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2806 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2810 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, (float*) &This
->updateStateBlock
->material
.Specular
);
2811 checkGLcall("glMaterialfv");
2812 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
2813 glEnable(GL_COLOR_SUM_EXT
);
2815 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2817 checkGLcall("glEnable(GL_COLOR_SUM)");
2819 float black
[4] = {0.0f
, 0.0f
, 0.0f
, 0.0f
};
2821 /* for the case of enabled lighting: */
2822 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, &black
[0]);
2823 checkGLcall("glMaterialfv");
2825 /* for the case of disabled lighting: */
2826 if (GL_SUPPORT(EXT_SECONDARY_COLOR
)) {
2827 glDisable(GL_COLOR_SUM_EXT
);
2829 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2831 checkGLcall("glDisable(GL_COLOR_SUM)");
2836 case WINED3DRS_STENCILENABLE
:
2838 glEnable(GL_STENCIL_TEST
);
2839 checkGLcall("glEnable GL_STENCIL_TEST");
2841 glDisable(GL_STENCIL_TEST
);
2842 checkGLcall("glDisable GL_STENCIL_TEST");
2846 case WINED3DRS_STENCILFUNC
:
2848 int glParm
= GL_ALWAYS
;
2849 int ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
2850 GLuint mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
2852 switch ((D3DCMPFUNC
) Value
) {
2853 case D3DCMP_NEVER
: glParm
=GL_NEVER
; break;
2854 case D3DCMP_LESS
: glParm
=GL_LESS
; break;
2855 case D3DCMP_EQUAL
: glParm
=GL_EQUAL
; break;
2856 case D3DCMP_LESSEQUAL
: glParm
=GL_LEQUAL
; break;
2857 case D3DCMP_GREATER
: glParm
=GL_GREATER
; break;
2858 case D3DCMP_NOTEQUAL
: glParm
=GL_NOTEQUAL
; break;
2859 case D3DCMP_GREATEREQUAL
: glParm
=GL_GEQUAL
; break;
2860 case D3DCMP_ALWAYS
: glParm
=GL_ALWAYS
; break;
2862 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value
);
2864 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm
, ref
, mask
);
2865 This
->stencilfunc
= glParm
;
2866 glStencilFunc(glParm
, ref
, mask
);
2867 checkGLcall("glStencilFunc");
2871 case WINED3DRS_STENCILREF
:
2873 int glParm
= This
->stencilfunc
;
2875 GLuint mask
= This
->stateBlock
->renderState
[WINED3DRS_STENCILMASK
];
2878 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm
, ref
, mask
);
2879 glStencilFunc(glParm
, ref
, mask
);
2880 checkGLcall("glStencilFunc");
2884 case WINED3DRS_STENCILMASK
:
2886 int glParm
= This
->stencilfunc
;
2887 int ref
= This
->stateBlock
->renderState
[WINED3DRS_STENCILREF
];
2888 GLuint mask
= Value
;
2890 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm
, ref
, mask
);
2891 glStencilFunc(glParm
, ref
, mask
);
2892 checkGLcall("glStencilFunc");
2896 case WINED3DRS_STENCILFAIL
:
2902 fail
= StencilOp(Value
);
2903 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &zpass
);
2904 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2905 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &zfail
);
2906 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2908 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail
, zfail
, zpass
);
2909 glStencilOp(fail
, zfail
, zpass
);
2910 checkGLcall("glStencilOp(fail, zfail, zpass);");
2913 case WINED3DRS_STENCILZFAIL
:
2919 glGetIntegerv(GL_STENCIL_FAIL
, &fail
);
2920 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2921 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS
, &zpass
);
2922 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2923 zfail
= StencilOp(Value
);
2925 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail
, zfail
, zpass
);
2926 glStencilOp(fail
, zfail
, zpass
);
2927 checkGLcall("glStencilOp(fail, zfail, zpass);");
2930 case WINED3DRS_STENCILPASS
:
2936 glGetIntegerv(GL_STENCIL_FAIL
, &fail
);
2937 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2938 zpass
= StencilOp(Value
);
2939 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL
, &zfail
);
2940 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2942 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail
, zfail
, zpass
);
2943 glStencilOp(fail
, zfail
, zpass
);
2944 checkGLcall("glStencilOp(fail, zfail, zpass);");
2948 case WINED3DRS_STENCILWRITEMASK
:
2950 glStencilMask(Value
);
2951 TRACE("glStencilMask(%lu)\n", Value
);
2952 checkGLcall("glStencilMask");
2956 case WINED3DRS_FOGENABLE
:
2958 if (Value
/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2960 checkGLcall("glEnable GL_FOG");
2963 checkGLcall("glDisable GL_FOG");
2968 case WINED3DRS_RANGEFOGENABLE
:
2971 TRACE("Enabled RANGEFOG");
2973 TRACE("Disabled RANGEFOG");
2978 case WINED3DRS_FOGCOLOR
:
2981 D3DCOLORTOGLFLOAT4(Value
, col
);
2982 /* Set the default alpha blend color */
2983 glFogfv(GL_FOG_COLOR
, &col
[0]);
2984 checkGLcall("glFog GL_FOG_COLOR");
2988 case WINED3DRS_FOGTABLEMODE
:
2990 glHint(GL_FOG_HINT
, GL_NICEST
);
2992 case D3DFOG_NONE
: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2993 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2994 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2995 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2997 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value
);
2999 if (GL_SUPPORT(NV_FOG_DISTANCE
)) {
3000 glFogi(GL_FOG_DISTANCE_MODE_NV
, GL_EYE_PLANE_ABSOLUTE_NV
);
3005 case WINED3DRS_FOGVERTEXMODE
:
3007 glHint(GL_FOG_HINT
, GL_FASTEST
);
3009 case D3DFOG_NONE
: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3010 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3011 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3012 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3014 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value
);
3016 if (GL_SUPPORT(NV_FOG_DISTANCE
)) {
3017 glFogi(GL_FOG_DISTANCE_MODE_NV
, This
->stateBlock
->renderState
[WINED3DRS_RANGEFOGENABLE
] ? GL_EYE_RADIAL_NV
: GL_EYE_PLANE_ABSOLUTE_NV
);
3022 case WINED3DRS_FOGSTART
:
3025 glFogfv(GL_FOG_START
, &tmpvalue
.f
);
3026 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3027 TRACE("Fog Start == %f\n", tmpvalue
.f
);
3031 case WINED3DRS_FOGEND
:
3034 glFogfv(GL_FOG_END
, &tmpvalue
.f
);
3035 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3036 TRACE("Fog End == %f\n", tmpvalue
.f
);
3040 case WINED3DRS_FOGDENSITY
:
3043 glFogfv(GL_FOG_DENSITY
, &tmpvalue
.f
);
3044 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3048 case WINED3DRS_VERTEXBLEND
:
3050 This
->updateStateBlock
->vertex_blend
= (D3DVERTEXBLENDFLAGS
) Value
;
3051 TRACE("Vertex Blending state to %ld\n", Value
);
3055 case WINED3DRS_TWEENFACTOR
:
3058 This
->updateStateBlock
->tween_factor
= tmpvalue
.f
;
3059 TRACE("Vertex Blending Tween Factor to %f\n", This
->updateStateBlock
->tween_factor
);
3063 case WINED3DRS_INDEXEDVERTEXBLENDENABLE
:
3065 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL
) Value
);
3069 case WINED3DRS_COLORVERTEX
:
3070 case WINED3DRS_DIFFUSEMATERIALSOURCE
:
3071 case WINED3DRS_SPECULARMATERIALSOURCE
:
3072 case WINED3DRS_AMBIENTMATERIALSOURCE
:
3073 case WINED3DRS_EMISSIVEMATERIALSOURCE
:
3075 GLenum Parm
= GL_AMBIENT_AND_DIFFUSE
;
3077 if (This
->stateBlock
->renderState
[WINED3DRS_COLORVERTEX
]) {
3078 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3079 This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
],
3080 This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
],
3081 This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
],
3082 This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
]);
3084 if (This
->stateBlock
->renderState
[WINED3DRS_DIFFUSEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3085 if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3086 Parm
= GL_AMBIENT_AND_DIFFUSE
;
3090 } else if (This
->stateBlock
->renderState
[WINED3DRS_AMBIENTMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3092 } else if (This
->stateBlock
->renderState
[WINED3DRS_EMISSIVEMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3094 } else if (This
->stateBlock
->renderState
[WINED3DRS_SPECULARMATERIALSOURCE
] == D3DMCS_COLOR1
) {
3101 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
3103 This
->tracking_color
= NEEDS_TRACKING
;
3104 This
->tracking_parm
= Parm
;
3108 if (This
->tracking_color
!= DISABLED_TRACKING
) This
->tracking_color
= NEEDS_DISABLE
;
3113 case WINED3DRS_LINEPATTERN
:
3119 tmppattern
.d
= Value
;
3121 TRACE("Line pattern: repeat %d bits %x\n", tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
3123 if (tmppattern
.lp
.wRepeatFactor
) {
3124 glLineStipple(tmppattern
.lp
.wRepeatFactor
, tmppattern
.lp
.wLinePattern
);
3125 checkGLcall("glLineStipple(repeat, linepattern)");
3126 glEnable(GL_LINE_STIPPLE
);
3127 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3129 glDisable(GL_LINE_STIPPLE
);
3130 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3135 case WINED3DRS_ZBIAS
:
3139 TRACE("ZBias value %f\n", tmpvalue
.f
);
3140 glPolygonOffset(0, -tmpvalue
.f
);
3141 checkGLcall("glPolygonOffset(0, -Value)");
3142 glEnable(GL_POLYGON_OFFSET_FILL
);
3143 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3144 glEnable(GL_POLYGON_OFFSET_LINE
);
3145 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3146 glEnable(GL_POLYGON_OFFSET_POINT
);
3147 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3149 glDisable(GL_POLYGON_OFFSET_FILL
);
3150 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3151 glDisable(GL_POLYGON_OFFSET_LINE
);
3152 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3153 glDisable(GL_POLYGON_OFFSET_POINT
);
3154 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3159 case WINED3DRS_NORMALIZENORMALS
:
3161 glEnable(GL_NORMALIZE
);
3162 checkGLcall("glEnable(GL_NORMALIZE);");
3164 glDisable(GL_NORMALIZE
);
3165 checkGLcall("glDisable(GL_NORMALIZE);");
3169 case WINED3DRS_POINTSIZE
:
3171 TRACE("Set point size to %f\n", tmpvalue
.f
);
3172 glPointSize(tmpvalue
.f
);
3173 checkGLcall("glPointSize(...);");
3176 case WINED3DRS_POINTSIZE_MIN
:
3177 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3179 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MIN_EXT
, tmpvalue
.f
);
3180 checkGLcall("glPointParameterfEXT(...);");
3182 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3186 case WINED3DRS_POINTSIZE_MAX
:
3187 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3189 GL_EXTCALL(glPointParameterfEXT
)(GL_POINT_SIZE_MAX_EXT
, tmpvalue
.f
);
3190 checkGLcall("glPointParameterfEXT(...);");
3192 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3196 case WINED3DRS_POINTSCALE_A
:
3197 case WINED3DRS_POINTSCALE_B
:
3198 case WINED3DRS_POINTSCALE_C
:
3199 case WINED3DRS_POINTSCALEENABLE
:
3201 /* If enabled, supply the parameters, otherwise fall back to defaults */
3202 if (This
->stateBlock
->renderState
[WINED3DRS_POINTSCALEENABLE
]) {
3203 GLfloat att
[3] = {1.0f
, 0.0f
, 0.0f
};
3204 att
[0] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_A
]);
3205 att
[1] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_B
]);
3206 att
[2] = *((float*)&This
->stateBlock
->renderState
[WINED3DRS_POINTSCALE_C
]);
3208 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3209 GL_EXTCALL(glPointParameterfvEXT
)(GL_DISTANCE_ATTENUATION_EXT
, att
);
3210 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3212 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3215 GLfloat att
[3] = {1.0f
, 0.0f
, 0.0f
};
3216 if (GL_SUPPORT(EXT_POINT_PARAMETERS
)) {
3217 GL_EXTCALL(glPointParameterfvEXT
)(GL_DISTANCE_ATTENUATION_EXT
, att
);
3218 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3220 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3226 case WINED3DRS_COLORWRITEENABLE
:
3228 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3229 Value
& D3DCOLORWRITEENABLE_RED
? 1 : 0,
3230 Value
& D3DCOLORWRITEENABLE_GREEN
? 1 : 0,
3231 Value
& D3DCOLORWRITEENABLE_BLUE
? 1 : 0,
3232 Value
& D3DCOLORWRITEENABLE_ALPHA
? 1 : 0);
3233 glColorMask(Value
& D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
3234 Value
& D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
3235 Value
& D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
3236 Value
& D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
3237 checkGLcall("glColorMask(...)");
3241 case WINED3DRS_LOCALVIEWER
:
3243 GLint state
= (Value
) ? 1 : 0;
3244 TRACE("Local Viewer Enable to %ul\n", (BOOL
) Value
);
3245 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER
, state
);
3249 case WINED3DRS_LASTPIXEL
:
3252 TRACE("Last Pixel Drawing Enabled\n");
3254 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3259 case WINED3DRS_SOFTWAREVERTEXPROCESSING
:
3262 TRACE("Software Processing Enabled\n");
3264 TRACE("Software Processing Disabled\n");
3269 /** not supported */
3270 case WINED3DRS_ZVISIBLE
:
3273 return D3DERR_INVALIDCALL
;
3276 /* Unhandled yet...! */
3277 case WINED3DRS_EDGEANTIALIAS
:
3278 case WINED3DRS_WRAP0
:
3279 case WINED3DRS_WRAP1
:
3280 case WINED3DRS_WRAP2
:
3281 case WINED3DRS_WRAP3
:
3282 case WINED3DRS_WRAP4
:
3283 case WINED3DRS_WRAP5
:
3284 case WINED3DRS_WRAP6
:
3285 case WINED3DRS_WRAP7
:
3286 case WINED3DRS_POINTSPRITEENABLE
:
3287 case WINED3DRS_MULTISAMPLEANTIALIAS
:
3288 case WINED3DRS_MULTISAMPLEMASK
:
3289 case WINED3DRS_PATCHEDGESTYLE
:
3290 case WINED3DRS_PATCHSEGMENTS
:
3291 case WINED3DRS_DEBUGMONITORTOKEN
:
3292 case WINED3DRS_POSITIONORDER
:
3293 case WINED3DRS_NORMALORDER
:
3294 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3295 FIXME("(%p)->(%d,%ld) not handled yet\n", This
, State
, Value
);
3298 FIXME("(%p)->(%d,%ld) unrecognized\n", This
, State
, Value
);
3306 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, D3DRENDERSTATETYPE State
, DWORD
*pValue
) {
3307 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3308 TRACE("(%p) for State %d = %ld\n", This
, State
, This
->stateBlock
->renderState
[State
]);
3309 *pValue
= This
->stateBlock
->renderState
[State
];
3314 * Get / Set Sampler States
3315 * TODO: Verify against dx9 definitions
3318 HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
3319 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3321 * SetSampler is designed to allow for more than the standard up to 8 textures
3322 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3323 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3325 * http://developer.nvidia.com/object/General_FAQ.html#t6
3327 * There are two new settings for GForce
3329 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3330 * and the texture one:
3331 * GL_MAX_TEXTURE_COORDS_ARB.
3332 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3334 /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
3335 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This
, Sampler
,Type
, Value
);
3337 if(Sampler
> GL_LIMITS(samplers
) || Sampler
< 0 || Type
> WINED3D_HIGHEST_SAMPLER_STATE
|| Type
< 0) {
3338 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers
), WINED3D_HIGHEST_SAMPLER_STATE
, Sampler
, Type
);
3339 return D3DERR_INVALIDCALL
;
3341 TRACE("Setting sampler %ld %d to %ld \n", Sampler
, Type
, Value
);
3342 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
3344 /* Handle recording of state blocks */
3345 if (This
->isRecordingState
) {
3346 TRACE("Recording... not performing anything\n");
3353 HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
3354 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3355 /** TODO: check that sampler is in range **/
3356 *Value
= This
->updateStateBlock
->samplerState
[Sampler
][Type
];
3357 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This
, Sampler
, Type
, *Value
);
3362 HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
3363 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3366 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3367 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3368 glScissor(pRect
->left
, pRect
->top
, pRect
->right
- pRect
->left
, pRect
->bottom
- pRect
->top
);
3374 HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
3375 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3376 GLint scissorBox
[4];
3379 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3380 glGetIntegerv(GL_SCISSOR_BOX
, scissorBox
);
3381 pRect
->left
= scissorBox
[1];
3382 pRect
->top
= scissorBox
[2];
3383 pRect
->right
= scissorBox
[1] + scissorBox
[3];
3384 pRect
->bottom
= scissorBox
[2] + scissorBox
[4];
3385 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3390 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
3391 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
3393 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
3395 /* TODO: what about recording stateblocks? */
3396 if (NULL
!= pDecl
) {
3397 IWineD3DVertexDeclaration_AddRef(pDecl
);
3399 if (NULL
!= This
->updateStateBlock
->vertexDecl
) {
3400 IWineD3DVertexDeclaration_Release(This
->updateStateBlock
->vertexDecl
);
3402 This
->updateStateBlock
->vertexDecl
= pDecl
;
3403 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
3404 This
->updateStateBlock
->set
.vertexDecl
= TRUE
;
3408 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
3409 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3411 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
3413 *ppDecl
= This
->updateStateBlock
->vertexDecl
;
3414 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
3418 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
3419 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3421 static BOOL showFixmes
= TRUE
;
3423 This
->updateStateBlock
->vertexShader
= pShader
;
3424 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3425 This
->updateStateBlock
->set
.vertexShader
= TRUE
;
3427 if(pShader
== NULL
) {
3428 /* clear down the shader */
3429 TRACE("Clear down the shader\n");
3432 FIXME("(%p) : stub pShader(%p)\n", This
, pShader
);
3439 /** FIXME: refernece counting? **/
3440 if (pShader
== NULL
) { /* only valid with non FVF shaders */
3441 TRACE_(d3d_shader
)("(%p) : FVF Shader, pShader=%p\n", This
, pShader
);
3442 This
->updateStateBlock
->vertexShader
= NULL
;
3444 TRACE_(d3d_shader
)("(%p) : Created shader, pShader=%p\n", This
, pShader
);
3445 This
->updateStateBlock
->vertexShader
= pShader
;
3448 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3449 This
->updateStateBlock
->set
.vertexShader
= TRUE
;
3451 /* Handle recording of state blocks */
3452 if (This
->isRecordingState
) {
3453 TRACE("Recording... not performing anything\n");
3457 * TODO: merge HAL shaders context switching from prototype
3462 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
3463 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3464 *ppShader
= This
->stateBlock
->vertexShader
;
3465 if(*ppShader
!= NULL
)
3466 IWineD3DVertexShader_AddRef(*ppShader
);
3467 TRACE("(%p) : returning %p\n", This
, *ppShader
);
3471 #define GET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3472 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3473 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3474 return D3DERR_INVALIDCALL; \
3475 memcpy(pConstantData, This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), count * (sizeof(*pConstantData) * _sizecount));
3477 #define SET_SHADER_CONSTANT(_vertexshaderconstant, _count, _sizecount) \
3478 int count = min(_count, MAX_VSHADER_CONSTANTS - (StartRegister + 1)); \
3479 if (NULL == pConstantData || count < 0 /* || _count != count */ ) \
3480 return D3DERR_INVALIDCALL; \
3481 memcpy(This->updateStateBlock->_vertexshaderconstant + (StartRegister * _sizecount), pConstantData, count * (sizeof(*pConstantData) * _sizecount)); \
3482 This->updateStateBlock->changed.vertexShader = TRUE; \
3483 This->updateStateBlock->set.vertexShader = TRUE;
3485 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
){
3486 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3487 static BOOL showFixmes
= TRUE
;
3488 SET_SHADER_CONSTANT(vertexShaderConstantB
, BoolCount
, 1);
3489 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3490 memset(This
->updateStateBlock
->vsibfBitmap
+ StartRegister
, WINESHADER_CONSTANTB
, BoolCount
);
3492 /* clean out the other constants? */
3493 if(showFixmes
|| TRUE
) {
3494 FIXME("(%p) : stub\n", This
);
3500 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
){
3501 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3502 static BOOL showFixmes
= TRUE
;
3503 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3504 for (i
= 0; i
< BoolCount
; i
++ ) {
3505 if (This
->updateStateBlock
->vsibfBitmap
[StartRegister
+ i
] != WINESHADER_CONSTANTB
) {
3506 /* the constant for this register isn't a boolean */
3507 return D3DERR_INVALIDCALL
;
3511 GET_SHADER_CONSTANT(vertexShaderConstantB
, BoolCount
, 1);
3512 if(showFixmes
|| TRUE
) {
3513 FIXME("(%p) : stub\n", This
);
3519 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
){
3520 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3521 static BOOL showFixmes
= TRUE
;
3522 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3523 memset(This
->updateStateBlock
->vsibfBitmap
+ StartRegister
, WINESHADER_CONSTANTI
, Vector4iCount
);
3525 SET_SHADER_CONSTANT(vertexShaderConstantI
, Vector4iCount
, 4);
3526 /* clean out the other constants? */
3527 if(showFixmes
|| TRUE
) {
3528 FIXME("(%p) : stub\n", This
);
3534 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
){
3535 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3536 static BOOL showFixmes
= TRUE
;
3537 #if 0 /* TODO: a bitmap to say which constant type we should load */
3538 for (i
= 0; i
< Vector4iCount
; i
++ ) {
3539 if (This
->updateStateBlock
->vsibfBitmap
[StartRegister
+ i
] != WINESHADER_CONSTANTI
) {
3540 /* the constant for this register isn't a boolean */
3541 return D3DERR_INVALIDCALL
;
3545 GET_SHADER_CONSTANT(vertexShaderConstantI
, Vector4iCount
, 4);
3546 if(showFixmes
|| TRUE
) {
3547 FIXME("(%p) : stub\n", This
);
3553 HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
float *pConstantData
, UINT Vector4fCount
){
3554 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3555 static BOOL showFixmes
= TRUE
;
3556 #if 0 /* TODO: a bitmasp to say which constant type we should load */
3557 memset(This
->updateStateBlock
->vsibfBitmap
+ StartRegister
, WINESHADER_CONSTANTF
, Vector4fCount
);
3559 SET_SHADER_CONSTANT(vertexShaderConstantF
, Vector4fCount
, 4);
3560 /* clean out the other constants? */
3562 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This
);
3568 HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, float *pConstantData
, UINT Vector4fCount
){
3569 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3570 static BOOL showFixmes
= TRUE
;
3571 #if 0 /* TODO: a bitmap to say which constant type we should load */
3572 for (i
= 0; i
< Vector4fCount
; i
++ ) {
3573 if (This
->updateStateBlock
->vsibfBitmap
[StartRegister
+ i
] != WINESHADER_CONSTANTF
) {
3574 /* the constant for this register isn't a boolean */
3575 return D3DERR_INVALIDCALL
;
3579 GET_SHADER_CONSTANT(vertexShaderConstantF
, Vector4fCount
, 4);
3581 TRACE("(%p) : ConstantF isn't intergrated properly with the other constants.\n", This
);
3587 #undef SET_SHADER_CONSTANT
3588 #undef GET_SHADER_CONSTANT
3591 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
3592 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3593 TRACE("(%p) : stub\n", This
);
3597 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
3598 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3599 TRACE("(%p) : stub\n", This
);
3604 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, CONST BOOL
*pConstantData
, UINT BoolCount
) {
3605 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3606 TRACE("(%p) : stub\n", This
);
3610 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice
*iface
, UINT StartRegister
, BOOL
*pConstantData
, UINT BoolCount
) {
3611 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3612 TRACE("(%p) : stub\n", This
);
3616 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
int *pConstantData
, UINT Vector4iCount
) {
3617 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3618 TRACE("(%p) : stub\n", This
);
3622 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice
*iface
, UINT StartRegister
, int *pConstantData
, UINT Vector4iCount
) {
3623 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3624 TRACE("(%p) : stub\n", This
);
3628 HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, CONST
float *pConstantData
, UINT Vector4fCount
) {
3629 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3630 TRACE("(%p) : stub\n", This
);
3634 HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice
*iface
, UINT StartRegister
, float *pConstantData
, UINT Vector4fCount
) {
3635 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3636 TRACE("(%p) : stub\n", This
);
3640 HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, IWineD3DVertexBuffer
* pDestBuffer
, IWineD3DVertexBuffer
* pVertexDecl
, DWORD Flags
) {
3641 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3642 FIXME("(%p) : stub\n", This
);
3647 * Apply / Get / Set Texture Stage States
3648 * TODO: Verify against dx9 definitions
3651 /* 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 callnig ApplyTextureStageState */
3652 static void WINAPI
IWineD3DDeviceImpl_ApplyTextureUnitState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
) {
3653 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3654 DWORD Value
= This
->updateStateBlock
->textureState
[Stage
][Type
];
3655 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3657 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
3659 /* Check that the stage is within limits */
3660 if (Stage
>= GL_LIMITS(textures
) || Stage
< 0) {
3661 TRACE("Attempt to access invalid texture rejected\n");
3668 case WINED3DTSS_ALPHAOP
:
3669 case WINED3DTSS_COLOROP
:
3672 if ((Value
== D3DTOP_DISABLE
) && (Type
== WINED3DTSS_COLOROP
)) {
3673 /* TODO: Disable by making this and all later levels disabled */
3674 glDisable(GL_TEXTURE_1D
);
3675 checkGLcall("Disable GL_TEXTURE_1D");
3676 glDisable(GL_TEXTURE_2D
);
3677 checkGLcall("Disable GL_TEXTURE_2D");
3678 glDisable(GL_TEXTURE_3D
);
3679 checkGLcall("Disable GL_TEXTURE_3D");
3680 break; /* Don't bother setting the texture operations */
3682 /* Enable only the appropriate texture dimension */
3683 if (Type
== WINED3DTSS_COLOROP
) {
3684 if (This
->stateBlock
->textureDimensions
[Stage
] == GL_TEXTURE_1D
) {
3685 glEnable(GL_TEXTURE_1D
);
3686 checkGLcall("Enable GL_TEXTURE_1D");
3688 glDisable(GL_TEXTURE_1D
);
3689 checkGLcall("Disable GL_TEXTURE_1D");
3691 if (This
->stateBlock
->textureDimensions
[Stage
] == GL_TEXTURE_2D
) {
3692 if (GL_SUPPORT(NV_TEXTURE_SHADER
) && This
->texture_shader_active
) {
3693 glTexEnvi(GL_TEXTURE_SHADER_NV
, GL_SHADER_OPERATION_NV
, GL_TEXTURE_2D
);
3694 checkGLcall("Enable GL_TEXTURE_2D");
3696 glEnable(GL_TEXTURE_2D
);
3697 checkGLcall("Enable GL_TEXTURE_2D");
3700 glDisable(GL_TEXTURE_2D
);
3701 checkGLcall("Disable GL_TEXTURE_2D");
3703 if (This
->stateBlock
->textureDimensions
[Stage
] == GL_TEXTURE_3D
) {
3704 glEnable(GL_TEXTURE_3D
);
3705 checkGLcall("Enable GL_TEXTURE_3D");
3707 glDisable(GL_TEXTURE_3D
);
3708 checkGLcall("Disable GL_TEXTURE_3D");
3710 if (This
->stateBlock
->textureDimensions
[Stage
] == GL_TEXTURE_CUBE_MAP_ARB
) {
3711 glEnable(GL_TEXTURE_CUBE_MAP_ARB
);
3712 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3714 glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
3715 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3719 /* Drop through... (Except disable case) */
3720 case WINED3DTSS_COLORARG0
:
3721 case WINED3DTSS_COLORARG1
:
3722 case WINED3DTSS_COLORARG2
:
3723 case WINED3DTSS_ALPHAARG0
:
3724 case WINED3DTSS_ALPHAARG1
:
3725 case WINED3DTSS_ALPHAARG2
:
3727 BOOL isAlphaArg
= (Type
== WINED3DTSS_ALPHAOP
|| Type
== WINED3DTSS_ALPHAARG1
||
3728 Type
== WINED3DTSS_ALPHAARG2
|| Type
== WINED3DTSS_ALPHAARG0
);
3730 set_tex_op(iface
, TRUE
, Stage
, This
->stateBlock
->textureState
[Stage
][WINED3DTSS_ALPHAOP
],
3731 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_ALPHAARG1
],
3732 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_ALPHAARG2
],
3733 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_ALPHAARG0
]);
3735 set_tex_op(iface
, FALSE
, Stage
, This
->stateBlock
->textureState
[Stage
][WINED3DTSS_COLOROP
],
3736 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_COLORARG1
],
3737 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_COLORARG2
],
3738 This
->stateBlock
->textureState
[Stage
][WINED3DTSS_COLORARG0
]);
3744 case WINED3DTSS_ADDRESSW
:
3746 GLint wrapParm
= GL_REPEAT
;
3749 case D3DTADDRESS_WRAP
: wrapParm
= GL_REPEAT
; break;
3750 case D3DTADDRESS_CLAMP
: wrapParm
= GL_CLAMP_TO_EDGE
; break;
3751 case D3DTADDRESS_BORDER
:
3753 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
3754 wrapParm
= GL_CLAMP_TO_BORDER_ARB
;
3756 /* FIXME: Not right, but better */
3757 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value
, Type
);
3758 wrapParm
= GL_REPEAT
;
3762 case D3DTADDRESS_MIRROR
:
3764 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
3765 wrapParm
= GL_MIRRORED_REPEAT_ARB
;
3767 /* Unsupported in OpenGL pre-1.4 */
3768 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type
);
3769 wrapParm
= GL_REPEAT
;
3773 case D3DTADDRESS_MIRRORONCE
:
3775 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
3776 wrapParm
= GL_MIRROR_CLAMP_TO_EDGE_ATI
;
3778 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type
);
3779 wrapParm
= GL_REPEAT
;
3785 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value
, Type
);
3786 wrapParm
= GL_REPEAT
;
3789 TRACE("Setting WRAP_R to %d for %x\n", wrapParm
, This
->stateBlock
->textureDimensions
[Stage
]);
3790 glTexParameteri(This
->stateBlock
->textureDimensions
[Stage
], GL_TEXTURE_WRAP_R
, wrapParm
);
3791 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3795 case WINED3DTSS_TEXCOORDINDEX
:
3797 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3799 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3800 one flag, you can still specify an index value, which the system uses to
3801 determine the texture wrapping mode.
3802 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3803 means use the vertex position (camera-space) as the input texture coordinates
3804 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3805 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3806 to the TEXCOORDINDEX value */
3809 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3811 switch (Value
& 0xFFFF0000) {
3812 case D3DTSS_TCI_PASSTHRU
:
3813 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3814 glDisable(GL_TEXTURE_GEN_S
);
3815 glDisable(GL_TEXTURE_GEN_T
);
3816 glDisable(GL_TEXTURE_GEN_R
);
3817 glDisable(GL_TEXTURE_GEN_Q
);
3818 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3821 case D3DTSS_TCI_CAMERASPACEPOSITION
:
3822 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3823 as the input texture coordinates for this stage's texture transformation. This
3824 equates roughly to EYE_LINEAR */
3826 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
3827 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
3828 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
3829 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
3830 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3832 glMatrixMode(GL_MODELVIEW
);
3835 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
3836 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
3837 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
3838 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
3841 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3842 glEnable(GL_TEXTURE_GEN_S
);
3843 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3844 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
3845 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3846 glEnable(GL_TEXTURE_GEN_T
);
3847 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3848 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
3849 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3850 glEnable(GL_TEXTURE_GEN_R
);
3851 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3852 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_EYE_LINEAR
);
3853 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3857 case D3DTSS_TCI_CAMERASPACENORMAL
:
3859 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
3860 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
3861 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
3862 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
3863 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
3864 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3866 glMatrixMode(GL_MODELVIEW
);
3869 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
3870 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
3871 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
3872 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
3875 glEnable(GL_TEXTURE_GEN_S
);
3876 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3877 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
3878 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3879 glEnable(GL_TEXTURE_GEN_T
);
3880 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3881 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
3882 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3883 glEnable(GL_TEXTURE_GEN_R
);
3884 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3885 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_NORMAL_MAP_NV
);
3886 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3891 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
:
3893 if (GL_SUPPORT(NV_TEXGEN_REFLECTION
)) {
3894 float s_plane
[] = { 1.0, 0.0, 0.0, 0.0 };
3895 float t_plane
[] = { 0.0, 1.0, 0.0, 0.0 };
3896 float r_plane
[] = { 0.0, 0.0, 1.0, 0.0 };
3897 float q_plane
[] = { 0.0, 0.0, 0.0, 1.0 };
3898 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3900 glMatrixMode(GL_MODELVIEW
);
3903 glTexGenfv(GL_S
, GL_EYE_PLANE
, s_plane
);
3904 glTexGenfv(GL_T
, GL_EYE_PLANE
, t_plane
);
3905 glTexGenfv(GL_R
, GL_EYE_PLANE
, r_plane
);
3906 glTexGenfv(GL_Q
, GL_EYE_PLANE
, q_plane
);
3909 glEnable(GL_TEXTURE_GEN_S
);
3910 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3911 glTexGeni(GL_S
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
3912 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3913 glEnable(GL_TEXTURE_GEN_T
);
3914 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3915 glTexGeni(GL_T
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
3916 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3917 glEnable(GL_TEXTURE_GEN_R
);
3918 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3919 glTexGeni(GL_R
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_NV
);
3920 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3925 /* Unhandled types: */
3928 /* ? disable GL_TEXTURE_GEN_n ? */
3929 glDisable(GL_TEXTURE_GEN_S
);
3930 glDisable(GL_TEXTURE_GEN_T
);
3931 glDisable(GL_TEXTURE_GEN_R
);
3932 glDisable(GL_TEXTURE_GEN_Q
);
3933 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value
);
3940 case WINED3DTSS_TEXTURETRANSFORMFLAGS
:
3941 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
);
3944 case WINED3DTSS_BUMPENVMAT00
:
3945 case WINED3DTSS_BUMPENVMAT01
:
3946 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT00
, Stage
, Type
, Value
);
3948 case WINED3DTSS_BUMPENVMAT10
:
3949 case WINED3DTSS_BUMPENVMAT11
:
3950 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type
- WINED3DTSS_BUMPENVMAT10
, Stage
, Type
, Value
);
3953 case WINED3DTSS_BUMPENVLSCALE
:
3954 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
3957 case WINED3DTSS_BUMPENVLOFFSET
:
3958 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
3961 case WINED3DTSS_RESULTARG
:
3962 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
3966 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3967 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage
, Type
, Value
);
3975 HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
3976 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3978 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3980 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
3982 /* Reject invalid texture units */
3983 if (Stage
>= GL_LIMITS(textures
)) {
3984 TRACE("Attempt to access invalid texture rejected\n");
3985 return D3DERR_INVALIDCALL
;
3988 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
3993 HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
3994 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3995 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
3996 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4003 HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
* pTexture
) {
4005 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4006 IWineD3DBaseTexture
*oldTexture
;
4008 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
4009 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This
, Stage
, pTexture
);
4011 #if 0 /* TODO: check so vertex textures */
4012 if (Stage
>= D3DVERTEXTEXTURESAMPLER
&& Stage
<= D3DVERTEXTEXTURESAMPLER3
){
4013 This
->updateStateBlock
->vertexTextures
[Stage
- D3DVERTEXTEXTURESAMPLER
] = pTexture
;
4018 if (Stage
>= GL_LIMITS(textures
) || Stage
< 0) {
4019 WARN("Attempt to access invalid texture rejected\n");
4020 return D3DERR_INVALIDCALL
;
4023 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
4024 TRACE("GL_LIMITS %d\n",GL_LIMITS(textures
));
4025 TRACE("(%p) : oldtexture(%p)\n", This
,oldTexture
);
4027 This
->updateStateBlock
->set
.textures
[Stage
] = TRUE
;
4028 This
->updateStateBlock
->changed
.textures
[Stage
] = TRUE
;
4029 TRACE("(%p) : setting new texture to %p\n", This
, pTexture
);
4030 This
->updateStateBlock
->textures
[Stage
] = pTexture
;
4032 /* Handle recording of state blocks */
4033 if (This
->isRecordingState
) {
4034 TRACE("Recording... not performing anything\n");
4038 /** NOTE: MSDN says that setTexture increases the reference count,
4039 * and the the application nust set the texture back to null (or have a leaky application),
4040 * This means we should pass the refcount upto the parent
4041 *******************************/
4042 if (NULL
!= This
->updateStateBlock
->textures
[Stage
]) {
4043 IUnknown
*textureParent
;
4044 IWineD3DBaseTexture_GetParent(This
->updateStateBlock
->textures
[Stage
], (IUnknown
**)&textureParent
);
4045 /** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
4048 if (NULL
!= oldTexture
) {
4049 IUnknown
*textureParent
;
4050 IWineD3DBaseTexture_GetParent(oldTexture
, (IUnknown
**)&textureParent
);
4051 IUnknown_Release(textureParent
);
4052 IUnknown_Release(textureParent
); /** NOTE: Twice because GetParent adds a ref **/
4059 HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
4060 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4061 TRACE("(%p) : returning %p for stage %ld\n", This
, This
->updateStateBlock
->textures
[Stage
], Stage
);
4062 *ppTexture
= (IWineD3DBaseTexture
*) This
->updateStateBlock
->textures
[Stage
];
4064 IWineD3DBaseTexture_AddRef(*ppTexture
);
4071 HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT iSwapChain
, UINT BackBuffer
, D3DBACKBUFFER_TYPE Type
,
4072 IWineD3DSurface
** ppBackBuffer
) {
4073 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4074 IWineD3DSwapChain
*swapChain
;
4077 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This
, BackBuffer
, Type
, iSwapChain
, *ppBackBuffer
);
4079 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4081 hr
= IWineD3DSwapChain_GetBackBuffer(swapChain
, BackBuffer
, Type
, ppBackBuffer
);
4082 IWineD3DSwapChain_Release(swapChain
);
4084 *ppBackBuffer
= NULL
;
4089 HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
4090 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4091 WARN("(%p) : stub, calling idirect3d for now\n", This
);
4092 return IWineD3D_GetDeviceCaps(This
->wineD3D
, This
->adapterNo
, This
->devType
, pCaps
);
4095 HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, D3DDISPLAYMODE
* pMode
) {
4096 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4097 IWineD3DSwapChain
*swapChain
;
4100 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
4102 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
4103 IWineD3DSwapChain_Release(swapChain
);
4105 FIXME("(%p) Error getting display mode\n", This
);
4110 * Stateblock related functions
4113 HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
4114 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4115 IWineD3DStateBlockImpl
*object
;
4116 TRACE("(%p)", This
);
4117 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DStateBlockImpl
));
4118 if(NULL
== object
) {
4119 FIXME("(%p)Error allocating memory for stateblock\n", This
);
4120 return E_OUTOFMEMORY
;
4122 TRACE("(%p) creted object %p\n", This
, object
);
4123 object
->wineD3DDevice
= This
;
4124 /** FIXME: object->parent = parent; **/
4125 object
->parent
= NULL
;
4126 object
->blockType
= WINED3DSBT_ALL
;
4128 object
->lpVtbl
= &IWineD3DStateBlock_Vtbl
;
4130 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
4131 This
->updateStateBlock
= object
;
4132 This
->isRecordingState
= TRUE
;
4134 TRACE("(%p) recording stateblock %p\n",This
, object
);
4138 HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
4139 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4141 if (!This
->isRecordingState
) {
4142 FIXME("(%p) not recording! returning error\n", This
);
4143 *ppStateBlock
= NULL
;
4144 return D3DERR_INVALIDCALL
;
4147 *ppStateBlock
= (IWineD3DStateBlock
*)This
->updateStateBlock
;
4148 This
->isRecordingState
= FALSE
;
4149 This
->updateStateBlock
= This
->stateBlock
;
4150 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
4151 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4152 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
4157 * Scene related functions
4159 HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4160 /* At the moment we have no need for any functionality at the beginning
4162 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4163 TRACE("(%p) : stub\n", This
);
4167 HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
) {
4168 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4169 TRACE("(%p)\n", This
);
4171 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4173 checkGLcall("glFlush");
4175 TRACE("End Scene\n");
4176 if(This
->renderTarget
!= NULL
) {
4178 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4179 IUnknown
*targetContainer
= NULL
;
4180 if (D3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DBaseTexture
, (void **)&targetContainer
)
4181 || D3D_OK
== IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DDevice
, (void **)&targetContainer
)) {
4182 TRACE("(%p) : Texture rendertarget %p\n", This
,This
->renderTarget
);
4183 /** always dirtify for now. we must find a better way to see that surface have been modified
4184 (Modifications should will only occur via draw-primitive, but we do need better locking
4185 switching to render-to-texture should remove the overhead though.
4187 IWineD3DSurface_SetPBufferState(This
->renderTarget
, TRUE
/* inPBuffer */, FALSE
/* inTexture */);
4188 IWineD3DSurface_AddDirtyRect(This
->renderTarget
, NULL
);
4189 IWineD3DSurface_PreLoad(This
->renderTarget
);
4190 IWineD3DSurface_SetPBufferState(This
->renderTarget
, FALSE
/* inPBuffer */, FALSE
/* inTexture */);
4191 IUnknown_Release(targetContainer
);
4194 This
->sceneEnded
= TRUE
;
4199 HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
4200 CONST RECT
* pSourceRect
, CONST RECT
* pDestRect
,
4201 HWND hDestWindowOverride
, CONST RGNDATA
* pDirtyRegion
) {
4202 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4203 IWineD3DSwapChain
*swapChain
= NULL
;
4205 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
4207 TRACE("(%p) Presenting the frame\n", This
);
4209 for(i
= 0 ; i
< swapchains
; i
++) {
4211 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, (IWineD3DSwapChain
**)&swapChain
);
4212 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
4213 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
4214 IWineD3DSwapChain_Release(swapChain
);
4220 HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST D3DRECT
* pRects
,
4221 DWORD Flags
, D3DCOLOR Color
, float Z
, DWORD Stencil
) {
4222 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4224 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4225 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4226 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4227 GLbitfield glMask
= 0;
4228 GLboolean old_ztest
;
4229 GLfloat old_z_clear_value
;
4230 GLint old_stencil_clear_value
;
4231 GLfloat old_color_clear_value
[4];
4233 CONST D3DRECT
* curRect
;
4235 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This
,
4236 Count
, pRects
, Flags
, Z
, Stencil
);
4240 glEnable(GL_SCISSOR_TEST
);
4241 checkGLcall("glEnable GL_SCISSOR_TEST");
4243 if (Count
> 0 && pRects
) {
4249 /* Only set the values up once, as they are not changing */
4250 if (Flags
& D3DCLEAR_STENCIL
) {
4251 glGetIntegerv(GL_STENCIL_CLEAR_VALUE
, &old_stencil_clear_value
);
4252 glClearStencil(Stencil
);
4253 checkGLcall("glClearStencil");
4254 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
4255 glStencilMask(0xFFFFFFFF);
4258 if (Flags
& D3DCLEAR_ZBUFFER
) {
4259 glGetBooleanv(GL_DEPTH_WRITEMASK
, &old_ztest
);
4260 glDepthMask(GL_TRUE
);
4261 glGetFloatv(GL_DEPTH_CLEAR_VALUE
, &old_z_clear_value
);
4263 checkGLcall("glClearDepth");
4264 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
4267 if (Flags
& D3DCLEAR_TARGET
) {
4268 TRACE("Clearing screen with glClear to color %lx\n", Color
);
4269 glGetFloatv(GL_COLOR_CLEAR_VALUE
, old_color_clear_value
);
4270 glClearColor(((Color
>> 16) & 0xFF) / 255.0f
,
4271 ((Color
>> 8) & 0xFF) / 255.0f
,
4272 ((Color
>> 0) & 0xFF) / 255.0f
,
4273 ((Color
>> 24) & 0xFF) / 255.0f
);
4274 checkGLcall("glClearColor");
4276 /* Clear ALL colors! */
4277 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4278 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
4281 /* Now process each rect in turn */
4282 for (i
= 0; i
< Count
|| i
== 0; i
++) {
4285 /* Note gl uses lower left, width/height */
4286 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This
, curRect
,
4287 curRect
->x1
, curRect
->y1
, curRect
->x2
, curRect
->y2
,
4288 curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
4289 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
4290 glScissor(curRect
->x1
, (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- curRect
->y2
),
4291 curRect
->x2
- curRect
->x1
, curRect
->y2
- curRect
->y1
);
4292 checkGLcall("glScissor");
4294 glScissor(This
->stateBlock
->viewport
.X
,
4295 (((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
- (This
->stateBlock
->viewport
.Y
+ This
->stateBlock
->viewport
.Height
)),
4296 This
->stateBlock
->viewport
.Width
,
4297 This
->stateBlock
->viewport
.Height
);
4298 checkGLcall("glScissor");
4301 /* Clear the selected rectangle (or full screen) */
4303 checkGLcall("glClear");
4305 /* Step to the next rectangle */
4306 if (curRect
) curRect
= curRect
+ sizeof(D3DRECT
);
4309 /* Restore the old values (why..?) */
4310 if (Flags
& D3DCLEAR_STENCIL
) {
4311 glClearStencil(old_stencil_clear_value
);
4312 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
4314 if (Flags
& D3DCLEAR_ZBUFFER
) {
4315 glDepthMask(old_ztest
);
4316 glClearDepth(old_z_clear_value
);
4318 if (Flags
& D3DCLEAR_TARGET
) {
4319 glClearColor(old_color_clear_value
[0],
4320 old_color_clear_value
[1],
4321 old_color_clear_value
[2],
4322 old_color_clear_value
[3]);
4323 glColorMask(This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
4324 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
4325 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
4326 This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
] & D3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
4329 glDisable(GL_SCISSOR_TEST
);
4330 checkGLcall("glDisable");
4339 HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
,
4340 UINT PrimitiveCount
) {
4342 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4343 This
->stateBlock
->streamIsUP
= FALSE
;
4345 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This
, PrimitiveType
,
4346 debug_d3dprimitivetype(PrimitiveType
),
4347 StartVertex
, PrimitiveCount
);
4348 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, StartVertex
, -1, 0, NULL
, 0);
4353 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4354 HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
,
4355 D3DPRIMITIVETYPE PrimitiveType
,
4356 INT baseVIndex
, UINT minIndex
,
4357 UINT NumVertices
,UINT startIndex
,UINT primCount
) {
4359 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4361 IWineD3DIndexBuffer
*pIB
;
4362 D3DINDEXBUFFER_DESC IdxBufDsc
;
4364 pIB
= This
->stateBlock
->pIndexData
;
4365 This
->stateBlock
->streamIsUP
= FALSE
;
4367 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This
,
4368 PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
4369 minIndex
, NumVertices
, startIndex
, baseVIndex
, primCount
);
4371 IWineD3DIndexBuffer_GetDesc(pIB
, &IdxBufDsc
);
4372 if (IdxBufDsc
.Format
== WINED3DFMT_INDEX16
) {
4378 drawPrimitive(iface
, PrimitiveType
, primCount
, baseVIndex
,
4379 startIndex
, idxStride
,
4380 ((IWineD3DIndexBufferImpl
*) pIB
)->resource
.allocatedMemory
,
4386 HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4387 UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
,
4388 UINT VertexStreamZeroStride
) {
4389 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4391 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This
, PrimitiveType
,
4392 debug_d3dprimitivetype(PrimitiveType
),
4393 PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4395 if (This
->stateBlock
->streamSource
[0] != NULL
) {
4396 IUnknown
*vertexBufferParent
;
4397 IWineD3DVertexBuffer_GetParent(This
->stateBlock
->streamSource
[0], &vertexBufferParent
);
4398 IUnknown_Release(vertexBufferParent
);
4399 IUnknown_Release(vertexBufferParent
);
4402 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4403 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
4404 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
4405 This
->stateBlock
->streamIsUP
= TRUE
;
4406 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, 0, NULL
, 0);
4407 This
->stateBlock
->streamStride
[0] = 0;
4408 This
->stateBlock
->streamSource
[0] = NULL
;
4410 /*stream zero settings set to null at end, as per the msdn */
4414 HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
, D3DPRIMITIVETYPE PrimitiveType
,
4415 UINT MinVertexIndex
,
4416 UINT NumVertexIndices
,UINT PrimitiveCount
,CONST
void* pIndexData
,
4417 WINED3DFORMAT IndexDataFormat
, CONST
void* pVertexStreamZeroData
,
4418 UINT VertexStreamZeroStride
) {
4420 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4422 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4423 This
, PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
4424 MinVertexIndex
, NumVertexIndices
, PrimitiveCount
, pIndexData
,
4425 IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4427 if (IndexDataFormat
== WINED3DFMT_INDEX16
) {
4433 if (This
->stateBlock
->streamSource
[0] != NULL
) {
4434 IUnknown
*vertexBufferParent
;
4435 IWineD3DVertexBuffer_GetParent(This
->stateBlock
->streamSource
[0], &vertexBufferParent
);
4436 This
->stateBlock
->streamSource
[0] = NULL
;
4437 IUnknown_Release(vertexBufferParent
);
4438 IUnknown_Release(vertexBufferParent
);
4441 if (This
->stateBlock
->pIndexData
) {
4442 IUnknown
*indexBufferParent
;
4443 IWineD3DIndexBuffer_GetParent(This
->stateBlock
->pIndexData
, &indexBufferParent
);
4444 This
->stateBlock
->pIndexData
= NULL
;
4445 IUnknown_Release(indexBufferParent
);
4446 IUnknown_Release(indexBufferParent
);
4449 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4450 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
4451 This
->stateBlock
->streamIsUP
= TRUE
;
4452 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
4454 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, idxStride
, pIndexData
, MinVertexIndex
);
4456 /* stream zero settings set to null at end as per the msdn */
4457 This
->stateBlock
->streamSource
[0] = NULL
;
4458 This
->stateBlock
->streamStride
[0] = 0;
4463 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4464 HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice
*iface
, IWineD3DBaseTexture
*pSourceTexture
, IWineD3DBaseTexture
*pDestinationTexture
){
4465 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4466 D3DRESOURCETYPE sourceType
;
4467 D3DRESOURCETYPE destinationType
;
4468 IWineD3DTextureImpl
*pDestTexture
= (IWineD3DTextureImpl
*)pDestinationTexture
;
4469 IWineD3DTextureImpl
*pSrcTexture
= (IWineD3DTextureImpl
*)pSourceTexture
;
4472 sourceType
= IWineD3DBaseTexture_GetType(pSourceTexture
);
4473 destinationType
= IWineD3DBaseTexture_GetType(pDestinationTexture
);
4474 if(sourceType
!= D3DRTYPE_TEXTURE
&& destinationType
!= D3DRTYPE_TEXTURE
){
4475 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This
);
4476 return D3DERR_INVALIDCALL
;
4478 TRACE("(%p) Source %p Destination %p\n", This
, pSourceTexture
, pDestinationTexture
);
4480 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4481 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4482 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4484 /* Make sure that the destination texture is loaded */
4485 IWineD3DBaseTexture_PreLoad(pDestinationTexture
);
4486 TRACE("Loading source texture\n");
4488 if(pSrcTexture
->surfaces
[0] == NULL
|| pDestTexture
->surfaces
[0] == NULL
){
4489 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This
, pSrcTexture
, pDestTexture
,
4490 pSrcTexture
->surfaces
[0], pDestTexture
->surfaces
[0]);
4493 if(((IWineD3DSurfaceImpl
*)pSrcTexture
->surfaces
[0])->resource
.pool
!= D3DPOOL_SYSTEMMEM
||
4494 ((IWineD3DSurfaceImpl
*)pDestTexture
->surfaces
[0])->resource
.pool
!= D3DPOOL_DEFAULT
){
4496 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This
, pSrcTexture
, pDestTexture
);
4497 return D3DERR_INVALIDCALL
;
4499 /** TODO: check that both textures have the same number of levels **/
4501 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture
))
4502 return D3DERR_INVALIDCALL
;
4504 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4505 for(i
= 0 ; i
< IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) ; i
++){
4506 IWineD3DDevice_UpdateSurface(iface
, pSrcTexture
->surfaces
[i
], NULL
, pDestTexture
->surfaces
[i
], NULL
);
4512 HRESULT WINAPI
IWineD3DDeviceImpl_StretchRect(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
,
4513 CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
,
4514 CONST RECT
* pDestRect
, D3DTEXTUREFILTERTYPE Filter
) {
4515 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4517 TRACE("(%p) : stub\n", This
);
4520 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice
*iface
, IWineD3DSurface
*pRenderTarget
, IWineD3DSurface
*pSurface
) {
4521 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4523 TRACE("(%p) : stub\n", This
);
4527 HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
4528 IWineD3DSwapChain
*swapChain
;
4530 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, (IWineD3DSwapChain
**)&swapChain
);
4532 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
4533 IWineD3DSwapChain_Release(swapChain
);
4538 HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
4539 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4540 /* return a sensible default */
4542 FIXME("(%p) : stub\n", This
);
4546 HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
4547 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4549 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4550 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
4551 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
4552 return D3DERR_INVALIDCALL
;
4554 for (j
= 0; j
< 256; ++j
) {
4555 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
4556 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
4557 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
4558 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
4560 TRACE("(%p) : returning\n", This
);
4564 HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
4565 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4567 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4568 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
4569 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
4570 return D3DERR_INVALIDCALL
;
4572 for (j
= 0; j
< 256; ++j
) {
4573 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
4574 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
4575 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
4576 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
4578 TRACE("(%p) : returning\n", This
);
4582 HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
4583 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4584 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4585 if ( PaletteNumber
< 0 || PaletteNumber
>= MAX_PALETTES
) {
4586 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
4587 return D3DERR_INVALIDCALL
;
4589 /*TODO: stateblocks */
4590 This
->currentPalette
= PaletteNumber
;
4591 TRACE("(%p) : returning\n", This
);
4595 HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
4596 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4597 if (PaletteNumber
== NULL
) {
4598 WARN("(%p) : returning Invalid Call\n", This
);
4599 return D3DERR_INVALIDCALL
;
4601 /*TODO: stateblocks */
4602 *PaletteNumber
= This
->currentPalette
;
4603 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
4607 HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
4608 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4609 static BOOL showFixmes
= TRUE
;
4611 FIXME("(%p) : stub\n", This
);
4615 This
->updateStateBlock
->softwareVertexProcessing
= bSoftware
;
4620 BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
4621 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4622 static BOOL showFixmes
= TRUE
;
4624 FIXME("(%p) : stub\n", This
);
4627 return This
->updateStateBlock
->softwareVertexProcessing
;
4631 HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
, UINT iSwapChain
, D3DRASTER_STATUS
* pRasterStatus
) {
4632 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4634 pRasterStatus
->InVBlank
= TRUE
;
4635 pRasterStatus
->ScanLine
= 0;
4636 FIXME("(%p) : stub\n", This
);
4641 HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
) {
4642 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4643 static BOOL showfixmes
= TRUE
;
4644 if(nSegments
!= 0.0f
) {
4646 FIXME("(%p) : stub nSegments(%f)\n", This
, nSegments
);
4653 float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
) {
4654 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4655 static BOOL showfixmes
= TRUE
;
4657 FIXME("(%p) : stub returning(%f)\n", This
, 0.0f
);
4664 HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
4665 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4666 /** TODO: remove casts to IWineD3DSurfaceImpl
4667 * NOTE: move code to surface to accomplish this
4668 ****************************************/
4669 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
4670 int srcWidth
, srcHeight
;
4671 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
4672 WINED3DFORMAT destFormat
, srcFormat
;
4674 int destLeft
, destTop
;
4675 D3DPOOL srcPool
, destPool
;
4677 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4678 glDescriptor
*glDescription
= NULL
;
4679 GLenum textureDimensions
= GL_TEXTURE_2D
;
4680 IWineD3DBaseTexture
*baseTexture
;
4682 WINED3DSURFACE_DESC winedesc
;
4684 memset(&winedesc
, 0, sizeof(winedesc
));
4685 winedesc
.Width
= &srcSurfaceWidth
;
4686 winedesc
.Height
= &srcSurfaceHeight
;
4687 winedesc
.Pool
= &srcPool
;
4688 winedesc
.Format
= &srcFormat
;
4690 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
4692 winedesc
.Width
= &destSurfaceWidth
;
4693 winedesc
.Height
= &destSurfaceHeight
;
4694 winedesc
.Pool
= &destPool
;
4695 winedesc
.Format
= &destFormat
;
4696 winedesc
.Size
= &destSize
;
4698 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
4700 if(srcPool
!= D3DPOOL_SYSTEMMEM
|| destPool
!= D3DPOOL_DEFAULT
){
4701 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface
, pDestinationSurface
);
4702 return D3DERR_INVALIDCALL
;
4704 /* TODO: change this to use bindTexture */
4705 /* Make sure the surface is loaded and upto date */
4706 IWineD3DSurface_PreLoad(pDestinationSurface
);
4708 IWineD3DSurface_GetGlDesc(pDestinationSurface
, &glDescription
);
4712 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4713 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
4714 srcHeight
= pSourceRect
? pSourceRect
->top
- pSourceRect
->bottom
: srcSurfaceHeight
;
4715 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
4716 destTop
= pDestPoint
? pDestPoint
->y
: 0;
4719 /* This function doesn't support compressed textures
4720 the pitch is just bytesPerPixel * width */
4722 if(srcWidth
!= srcSurfaceWidth
|| (pSourceRect
!= NULL
&& pSourceRect
->left
!= 0) ){
4723 rowoffset
= (srcSurfaceWidth
- srcWidth
) * pSrcSurface
->bytesPerPixel
;
4724 offset
+= pSourceRect
->left
* pSrcSurface
->bytesPerPixel
;
4725 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4727 /* TODO DXT formats */
4729 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
4730 offset
+= pSourceRect
->top
* srcWidth
* pSrcSurface
->bytesPerPixel
;
4732 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4734 ,glDescription
->level
4739 ,glDescription
->glFormat
4740 ,glDescription
->glType
4741 ,IWineD3DSurface_GetData(pSourceSurface
)
4745 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
4746 /* need to lock the surface to get the data */
4747 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4749 /* TODO: Cube and volume support */
4751 /* not a whole row so we have to do it a line at a time */
4753 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4754 unsigned char* data
=((unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
4756 for(j
= destTop
; j
< (srcHeight
+ destTop
) ; j
++){
4758 glTexSubImage2D(glDescription
->target
4759 ,glDescription
->level
4764 ,glDescription
->glFormat
4765 ,glDescription
->glType
4766 ,data
/* could be quicker using */
4771 } else { /* Full width, so just write out the whole texture */
4773 if (WINED3DFMT_DXT1
== destFormat
||
4774 WINED3DFMT_DXT3
== destFormat
||
4775 WINED3DFMT_DXT5
== destFormat
) {
4776 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
4777 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
) {
4778 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4779 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4780 } if (destFormat
!= srcFormat
) {
4781 FIXME("Updating mixed format compressed texture is not curretly support\n");
4783 GL_EXTCALL(glCompressedTexImage2DARB
)(glDescription
->target
,
4784 glDescription
->level
,
4785 glDescription
->glFormatInternal
,
4790 IWineD3DSurface_GetData(pSourceSurface
));
4793 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4798 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
4799 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4800 data returned by GetData non-power2 width/height with hardware non-power2
4801 pow2Width/height are set to surface width height, repacking isn't needed so it
4802 doesn't matter which function gets called. */
4803 glTexSubImage2D(glDescription
->target
4804 ,glDescription
->level
4809 ,glDescription
->glFormat
4810 ,glDescription
->glType
4811 ,IWineD3DSurface_GetData(pSourceSurface
)
4816 checkGLcall("glTexSubImage2D");
4817 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4818 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4819 * surface bigger than it needs to be hmm.. */
4820 if (D3D_OK
== IWineD3DSurface_GetContainer(pDestinationSurface
, &IID_IWineD3DBaseTexture
, (void **)&baseTexture
)) {
4821 textureDimensions
= IWineD3DBaseTexture_GetTextureDimensions(baseTexture
);
4822 IWineD3DBaseTexture_Release(baseTexture
);
4825 glDisable(textureDimensions
); /* This needs to be managed better.... */
4831 /* Implementation details at http://developer.nvidia.com/attach/6494
4833 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4834 hmm.. no longer supported use
4835 OpenGL evaluators or tessellate surfaces within your application.
4838 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4839 HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST D3DRECTPATCH_INFO
* pRectPatchInfo
) {
4840 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4841 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
4842 FIXME("(%p) : Stub\n", This
);
4847 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4848 HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST D3DTRIPATCH_INFO
* pTriPatchInfo
) {
4849 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4850 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This
, Handle
, pNumSegs
, pTriPatchInfo
);
4851 FIXME("(%p) : Stub\n", This
);
4855 HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
4856 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4857 TRACE("(%p) Handle(%d)\n", This
, Handle
);
4858 FIXME("(%p) : Stub\n", This
);
4862 HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, CONST D3DRECT
* pRect
, D3DCOLOR color
) {
4863 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
4864 fill a surface with a block of color! */
4865 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4866 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
4867 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*)pSurface
;
4868 IWineD3DSwapChainImpl
*container
= NULL
;
4869 BOOL isRenderTarget
= FALSE
;
4870 unsigned int width
, height
;
4871 unsigned int top
, left
;
4874 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This
, pSurface
, pRect
, color
);
4875 if (surface
->resource
.pool
!= D3DPOOL_DEFAULT
) {
4876 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
4877 return D3DERR_INVALIDCALL
;
4880 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
4881 if (D3D_OK
== IWineD3DSurface_GetContainer(pSurface
, &IID_IWineD3DSwapChain
, (void **)&container
) || pSurface
== This
->renderTarget
) {
4882 if (D3DUSAGE_RENDERTARGET
& surface
->resource
.usage
) {
4883 /* TODO: make sure we set everything back to the way it was, and context management!
4884 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4885 vcheckGLcall("glIntegerv");
4886 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
4887 vcheckGLcall("glIntegerv");
4889 TRACE("Color fill to render targets may cause some graphics issues\n");
4890 if (pSurface
== container
->frontBuffer
) {
4891 glDrawBuffer(GL_FRONT
);
4893 glDrawBuffer(GL_BACK
);
4896 if (D3DUSAGE_DEPTHSTENCIL
& surface
->resource
.usage
) {
4897 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface
, surface
->resource
.usage
);
4899 FIXME("(%p) : Regression %ld %p %p\n", This
, surface
->resource
.usage
, pSurface
, This
->renderTarget
);
4901 if (container
!= NULL
) {
4902 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)container
);
4904 /* we can use GL_STENCIL_INDEX etc...*/
4907 if (container
!= NULL
) {
4908 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)container
);
4910 isRenderTarget
= TRUE
;
4912 /* TODO: drawing to GL_FRONT and GL_BACK */
4913 /* TODO: see if things can be speeded up by using the correct
4914 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
4915 if (pRect
== NULL
) {
4918 width
= surface
->currentDesc
.Width
;
4919 height
= surface
->currentDesc
.Height
;
4923 width
= pRect
->x2
- left
;
4924 height
= pRect
->y2
- top
;
4927 data
= HeapAlloc(GetProcessHeap(), 0, 4 * width
);
4928 /* Create a 'line' of color color, in the correct format for the surface */
4929 for (u
= 0 ; u
< width
; u
++) {
4934 if (isRenderTarget
== FALSE
) {
4935 glDescriptor
*glDesc
;
4936 IWineD3DSurface_PreLoad(pSurface
);
4938 /* draw a block of the coloured line on the sufrace */
4939 IWineD3DSurface_GetGlDesc(pSurface
, &glDesc
);
4940 for (v
= 0 ; v
< height
;v
++) {
4941 glTexSubImage2D(glDesc
->target
4942 ,glDesc
->level
/* level */
4952 checkGLcall("glTexSubImage2D");
4954 glDisable(glDesc
->target
);
4956 /** FIXME: Using GLClear may be faster **/
4957 glRasterPos2i(left
, top
);
4958 glPixelZoom((float)width
,(float)height
);
4959 glDrawPixels(1, 1, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
4960 checkGLcall("glDrawPixels");
4962 HeapFree(GetProcessHeap(), 0, data
);
4968 /* rendertarget and deptth stencil functions */
4969 HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
4970 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4972 /* FIXME: Implelent RenderTargetIndex >0 */
4973 if(RenderTargetIndex
> 0)
4974 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This
, RenderTargetIndex
);
4976 *ppRenderTarget
= This
->renderTarget
;
4977 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
4978 /* Note inc ref on returned surface */
4979 if(*ppRenderTarget
!= NULL
)
4980 IWineD3DSurface_AddRef(*ppRenderTarget
);
4984 HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
4985 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4986 *ppZStencilSurface
= This
->depthStencilBuffer
;
4987 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
4989 if(*ppZStencilSurface
!= NULL
) {
4990 /* Note inc ref on returned surface */
4991 IWineD3DSurface_AddRef(*ppZStencilSurface
);
4996 /* internal static helper functions */
4997 HRESULT WINAPI
static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
4998 IWineD3DSurface
*RenderSurface
);
5000 HRESULT WINAPI
static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice
* iface
, IWineD3DSwapChainImpl
*swapchain
);
5002 HRESULT WINAPI
static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, glContext
**context
);
5004 HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
) {
5005 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5006 HRESULT hr
= D3D_OK
;
5007 WINED3DVIEWPORT viewport
;
5009 TRACE("(%p) Swapping rendertarget\n",This
);
5010 if (RenderTargetIndex
> 0) {
5011 FIXME("(%p) Render targets other than the first are not supported\n",This
);
5012 RenderTargetIndex
= 0;
5015 /* MSDN says that null disables the render target
5016 but a device must always be associated with a render target
5017 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5019 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5022 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
5023 FIXME("Trying to set render target 0 to NULL\n");
5024 return D3DERR_INVALIDCALL
;
5026 /* TODO: replace Impl* usage with interface usage */
5027 if (!((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& D3DUSAGE_RENDERTARGET
) {
5028 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This
,pRenderTarget
);
5029 return D3DERR_INVALIDCALL
;
5031 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5032 * builds, but I think wine counts as a 'debug' build for now.
5033 ******************************/
5034 /* If we are trying to set what we already have, don't bother */
5035 if (pRenderTarget
== This
->renderTarget
) {
5036 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5038 /* Otherwise, set the render target up */
5040 if (FALSE
== This
->sceneEnded
) {
5041 IWineD3DDevice_EndScene(iface
);
5043 TRACE("clearing renderer\n");
5044 /* IWineD3DDeviceImpl_CleanRender(iface); */
5045 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5046 depending on the renter target implementation being used.
5047 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5048 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5049 stencil buffer and incure an extra memory overhead */
5050 hr
= IWineD3DDeviceImpl_ActiveRender(iface
, pRenderTarget
);
5053 if (SUCCEEDED(hr
)) {
5054 /* Finally, reset the viewport as the MSDN states. */
5055 /* TODO: Replace impl usage */
5056 viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Height
;
5057 viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->renderTarget
)->currentDesc
.Width
;
5060 viewport
.MaxZ
= 1.0f
;
5061 viewport
.MinZ
= 0.0f
;
5062 IWineD3DDeviceImpl_SetViewport(iface
, &viewport
);
5064 FIXME("Unknown error setting the render target\n");
5066 This
->sceneEnded
= FALSE
;
5070 HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
5071 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5072 HRESULT hr
= D3D_OK
;
5073 IWineD3DSurface
*tmp
;
5075 TRACE("(%p) Swapping z-buffer\n",This
);
5077 if (pNewZStencil
== This
->stencilBufferTarget
) {
5078 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5080 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5081 * depending on the renter target implementation being used.
5082 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5083 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5084 * stencil buffer and incure an extra memory overhead
5085 ******************************************************/
5088 tmp
= This
->stencilBufferTarget
;
5089 This
->stencilBufferTarget
= pNewZStencil
;
5090 /* should we be calling the parent or the wined3d surface? */
5091 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
5092 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
5094 /** TODO: glEnable/glDisable on depth/stencil depending on
5095 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5096 **********************************************************/
5103 /* Internal functions not in DirectX */
5104 /** TODO: move this off to the opengl context manager
5105 *(the swapchain doesn't need to know anything about offscreen rendering!)
5106 ****************************************************/
5108 HRESULT WINAPI
IWineD3DDeviceImpl_CleanRender(IWineD3DDevice
* iface
, IWineD3DSwapChainImpl
*swapchain
)
5110 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5112 TRACE("(%p), %p\n", This
, swapchain
);
5114 if (swapchain
->win
!= swapchain
->drawable
) {
5115 /* Set everything back the way it ws */
5116 swapchain
->render_ctx
= swapchain
->glCtx
;
5117 swapchain
->drawable
= swapchain
->win
;
5121 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5122 HRESULT WINAPI
IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, glContext
**context
) {
5123 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5126 unsigned int height
;
5127 WINED3DFORMAT format
;
5128 WINED3DSURFACE_DESC surfaceDesc
;
5129 memset(&surfaceDesc
, 0, sizeof(surfaceDesc
));
5130 surfaceDesc
.Width
= &width
;
5131 surfaceDesc
.Height
= &height
;
5132 surfaceDesc
.Format
= &format
;
5133 IWineD3DSurface_GetDesc(pSurface
, &surfaceDesc
);
5135 /* I need a get width/height function (and should do something with the format) */
5136 for (i
= 0; i
< CONTEXT_CACHE
; ++i
) {
5137 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5138 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5139 the pSurface can be set to 0 allowing it to be reused from cache **/
5140 if (This
->contextCache
[i
].Width
== width
&& This
->contextCache
[i
].Height
== height
5141 && (pbuffer_per_surface
== FALSE
|| This
->contextCache
[i
].pSurface
== pSurface
|| This
->contextCache
[i
].pSurface
== NULL
)) {
5142 *context
= &This
->contextCache
[i
];
5145 if (This
->contextCache
[i
].Width
== 0) {
5146 This
->contextCache
[i
].pSurface
= pSurface
;
5147 This
->contextCache
[i
].Width
= width
;
5148 This
->contextCache
[i
].Height
= height
;
5149 *context
= &This
->contextCache
[i
];
5153 if (i
== CONTEXT_CACHE
) {
5154 int minUsage
= 0x7FFFFFFF; /* MAX_INT */
5155 glContext
*dropContext
= 0;
5156 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
5157 if (This
->contextCache
[i
].usedcount
< minUsage
) {
5158 dropContext
= &This
->contextCache
[i
];
5159 minUsage
= This
->contextCache
[i
].usedcount
;
5162 /* clean up the context (this doesn't work for ATI at the moment */
5164 glXDestroyContext(swapchain
->display
, dropContext
->context
);
5165 glXDestroyPbuffer(swapchain
->display
, dropContext
->drawable
);
5168 dropContext
->Width
= 0;
5169 dropContext
->pSurface
= pSurface
;
5170 *context
= dropContext
;
5172 if (++This
->contextCache
[i
].usedcount
== 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5173 for (i
= 0; i
< CONTEXT_CACHE
; i
++) {
5174 This
->contextCache
[i
].usedcount
= max(0, This
->contextCache
[i
].usedcount
- (0x7FFFFFFF /* MAX_INT */ >> 1));
5178 if (*context
!= NULL
)
5181 return E_OUTOFMEMORY
;
5184 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5185 * the functionality needs splitting up so that we don't do more than we should do.
5186 * this only seems to impact performance a little.
5187 ******************************/
5188 HRESULT WINAPI
IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice
* iface
,
5189 IWineD3DSurface
*RenderSurface
) {
5190 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5192 IWineD3DSurface
*StencilSurface
= This
->stencilBufferTarget
;
5193 HRESULT ret
= D3DERR_INVALIDCALL
;
5194 IWineD3DSurface
*tmp
;
5196 * Currently only active for GLX >= 1.3
5197 * for others versions we'll have to use GLXPixmaps
5199 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5200 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5201 * so only check OpenGL version
5202 * ..........................
5203 * I don't believe that it is a problem with NVidia headers,
5204 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5205 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5207 * Your application will report GLX version 1.2 on glXQueryVersion.
5208 * However, it is safe to call the GLX 1.3 functions as described below.
5210 #if defined(GL_VERSION_1_3)
5212 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5213 GLXFBConfig
* cfgs
= NULL
;
5217 IWineD3DSwapChain
*currentSwapchain
;
5218 IWineD3DSwapChainImpl
*swapchain
;
5219 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5220 * but switch them off if the StencilSurface is set to NULL
5221 ** *********************************************************/
5222 D3DFORMAT BackBufferFormat
= ((IWineD3DSurfaceImpl
*) RenderSurface
)->resource
.format
;
5223 D3DFORMAT StencilBufferFormat
= (NULL
!= StencilSurface
) ? ((IWineD3DSurfaceImpl
*) StencilSurface
)->resource
.format
: 0;
5226 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5227 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5230 #define PUSH1(att) attribs[nAttribs++] = (att);
5231 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5233 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5235 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5236 IWineD3DSwapChainImpl
*impSwapChain
;
5237 IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**)&impSwapChain
);
5238 if (NULL
== impSwapChain
) { /* NOTE: This should NEVER fail */
5239 ERR("(%p) Failed to get a the implicit swapchain\n", iface
);
5244 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
);
5245 PUSH2(GLX_X_RENDERABLE
, TRUE
);
5246 PUSH2(GLX_DOUBLEBUFFER
, TRUE
);
5247 TRACE("calling makeglcfg\n");
5248 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, FALSE
/* alternate */);
5251 TRACE("calling chooseFGConfig\n");
5252 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
5255 if (!cfgs
) { /* OK we didn't find the exact config, so use any reasonable match */
5256 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5257 why we failed and only show this message once! */
5258 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"); /**/
5260 PUSH2(GLX_DRAWABLE_TYPE
, GLX_PBUFFER_BIT
| GLX_WINDOW_BIT
);
5261 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5262 PUSH2(GLX_RENDER_TYPE
, GLX_RGBA_BIT
);
5263 PUSH2(GLX_DOUBLEBUFFER
, FALSE
);
5264 TRACE("calling makeglcfg\n");
5265 D3DFmtMakeGlCfg(BackBufferFormat
, StencilBufferFormat
, attribs
, &nAttribs
, TRUE
/* alternate */);
5267 cfgs
= glXChooseFBConfig(impSwapChain
->display
, DefaultScreen(impSwapChain
->display
),
5274 for (i
= 0; i
< nCfgs
; ++i
) {
5275 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat
,
5276 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
,
5277 debug_d3dformat(StencilBufferFormat
), i
, cfgs
[i
]);
5280 if (NULL
!= This
->renderTarget
) {
5282 vcheckGLcall("glFlush");
5283 /** This is only useful if the old render target was a swapchain,
5284 * we need to supercede this with a function that displays
5285 * the current buffer on the screen. This is easy to do in glx1.3 but
5286 * we need to do copy-write pixels in glx 1.2.
5287 ************************************************/
5288 glXSwapBuffers(impSwapChain
->display
, impSwapChain
->drawable
);
5290 printf("Hit Enter to get next frame ...\n");
5296 if (IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)¤tSwapchain
) != D3D_OK
) {
5297 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5298 IWineD3DDevice_GetSwapChain(iface
, 0, ¤tSwapchain
);
5302 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5303 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5304 **********************************************************************/
5305 if (IWineD3DSurface_GetContainer(RenderSurface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
) == D3D_OK
) {
5306 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5307 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5308 TRACE("making swapchain active\n");
5309 if (RenderSurface
!= This
->renderTarget
) {
5310 if (RenderSurface
== swapchain
->backBuffer
) {
5312 /* This could be flagged so that some operations work directly with the front buffer */
5313 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5315 if (glXMakeCurrent(swapchain
->display
, swapchain
->win
, swapchain
->glCtx
)
5317 TRACE("Error in setting current context: context %p drawable %ld !\n",
5318 impSwapChain
->glCtx
, impSwapChain
->win
);
5321 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
5323 checkGLcall("glXMakeContextCurrent");
5325 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
5327 else if (pbuffer_support
== TRUE
&& cfgs
!= NULL
/* && some test to make sure that opengl supports pbuffers */) {
5329 /** ********************************************************************
5330 * This is a quickly hacked out implementation of offscreen textures.
5331 * It will work in most cases but there may be problems if the client
5332 * modifies the texture directly, or expects the contents of the rendertarget
5335 * There are some real speed vs compatibility issues here:
5336 * we should really use a new context for every texture, but that eats ram.
5337 * we should also be restoring the texture to the pbuffer but that eats CPU
5338 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5339 * but if this means reusing the display backbuffer then we need to make sure that
5340 * states are correctly preserved.
5341 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5342 * and gain a good performance increase at the cost of compatibility.
5343 * I would suggest that, when this is the case, a user configurable flag be made
5344 * available, allowing the user to choose the best emmulated experience for them.
5345 *********************************************************************/
5347 XVisualInfo
*visinfo
;
5348 glContext
*newContext
;
5350 /* Here were using a shared context model */
5351 if (D3D_OK
!= IWineD3DDeviceImpl_FindGLContext(iface
, RenderSurface
, &newContext
)) {
5352 FIXME("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
5355 /* If the context doesn't exist then create a new one */
5356 /* TODO: This should really be part of findGlContext */
5357 if (NULL
== newContext
->context
) {
5359 TRACE("making new buffer\n");
5361 PUSH2(GLX_PBUFFER_WIDTH
, newContext
->Width
);
5362 PUSH2(GLX_PBUFFER_HEIGHT
, newContext
->Height
);
5365 newContext
->drawable
= glXCreatePbuffer(impSwapChain
->display
, cfgs
[0], attribs
);
5367 /** ****************************************
5368 *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
5370 * In future releases, we may provide the calls glXCreateNewContext,
5371 * glXQueryDrawable and glXMakeContextCurrent.
5372 * so until then we have to use glXGetVisualFromFBConfig &co..
5373 ********************************************/
5376 visinfo
= glXGetVisualFromFBConfig(impSwapChain
->display
, cfgs
[0]);
5378 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5380 newContext
->context
= glXCreateContext(impSwapChain
->display
, visinfo
, impSwapChain
->glCtx
, GL_TRUE
);
5384 if (NULL
== newContext
|| NULL
== newContext
->context
) {
5385 ERR("(%p) : Failed to find a context for surface %p\n", iface
, RenderSurface
);
5387 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5388 if (glXMakeCurrent(impSwapChain
->display
, newContext
->drawable
, newContext
->context
) == False
) {
5389 TRACE("Error in setting current context: context %p drawable %ld\n", newContext
->context
, newContext
->drawable
);
5392 /* Clean up the old context */
5393 IWineD3DDeviceImpl_CleanRender(iface
, (IWineD3DSwapChainImpl
*)currentSwapchain
);
5394 /* Set the current context of the swapchain to the new context */
5395 impSwapChain
->drawable
= newContext
->drawable
;
5396 impSwapChain
->render_ctx
= newContext
->context
;
5400 #if 1 /* Apply the stateblock to the new context
5401 FIXME: This is a bit of a hack, each context should know it's own state,
5402 the directX current directX state should then be applied to the context */
5405 IWineD3DStateBlockImpl
*oldUpdateStateBlock
;
5406 oldUpdateStateBlock
= This
->updateStateBlock
;
5407 oldRecording
= This
->isRecordingState
;
5408 This
->isRecordingState
= FALSE
;
5409 This
->updateStateBlock
= This
->stateBlock
;
5410 IWineD3DStateBlock_Apply((IWineD3DStateBlock
*)This
->stateBlock
);
5412 This
->isRecordingState
= oldRecording
;
5413 This
->updateStateBlock
= oldUpdateStateBlock
;
5418 /* clean up the current rendertargets swapchain (if it belonged to one) */
5419 if (currentSwapchain
!= NULL
) {
5420 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)currentSwapchain
);
5423 /* Were done with the opengl context management, setup the rendertargets */
5425 tmp
= This
->renderTarget
;
5426 This
->renderTarget
= RenderSurface
;
5427 IWineD3DSurface_AddRef(This
->renderTarget
);
5428 IWineD3DSurface_Release(tmp
);
5434 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5435 /* Check that the container is not a swapchain member */
5437 IWineD3DSwapChain
*tmpSwapChain
;
5438 if (D3D_OK
!= IWineD3DSurface_GetContainer(This
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)&tmpSwapChain
)) {
5439 This
->renderUpsideDown
= TRUE
;
5441 This
->renderUpsideDown
= FALSE
;
5442 IWineD3DSwapChain_Release(tmpSwapChain
);
5444 /* Force updating the cull mode */
5445 TRACE("setting render state\n");
5446 IWineD3DDevice_GetRenderState(iface
, WINED3DRS_CULLMODE
, &value
);
5447 IWineD3DDevice_SetRenderState(iface
, WINED3DRS_CULLMODE
, value
);
5449 /* Force updating projection matrix */
5450 This
->last_was_rhw
= FALSE
;
5451 This
->proj_valid
= FALSE
;
5459 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat
,
5460 debug_d3dformat(BackBufferFormat
), StencilBufferFormat
, debug_d3dformat(StencilBufferFormat
));
5465 if ( NULL
!= impSwapChain
) {
5466 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)impSwapChain
);
5474 HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
5475 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
5476 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5477 /* TODO: the use of Impl is deprecated. */
5478 /* some basic validation checks */
5479 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
5481 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
5483 if (WINED3DFMT_A8R8G8B8
!= pSur
->resource
.format
) {
5484 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
5485 return D3DERR_INVALIDCALL
;
5487 if (32 != pSur
->currentDesc
.Height
|| 32 != pSur
->currentDesc
.Width
) {
5488 ERR("(%p) : surface(%p) has an invalid size\n", This
, pCursorBitmap
);
5489 return D3DERR_INVALIDCALL
;
5491 /* TODO: make the cursor 'real' */
5493 This
->xHotSpot
= XHotSpot
;
5494 This
->yHotSpot
= YHotSpot
;
5499 void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
5500 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5501 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
5503 This
->xScreenSpace
= XScreenSpace
;
5504 This
->yScreenSpace
= YScreenSpace
;
5510 BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
5511 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5512 TRACE("(%p) : visible(%d)\n", This
, bShow
);
5514 This
->bCursorVisible
= bShow
;
5519 HRESULT WINAPI
IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice
* iface
) {
5520 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5521 FIXME("(%p) : stub\n", This
); /* No way of notifying yet! */
5526 HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
* iface
) {
5527 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5528 /** FIXME: Resource tracking needs to be done,
5529 * The closes we can do to this is set the priorities of all managed textures low
5530 * and then reset them.
5531 ***********************************************************/
5532 FIXME("(%p) : stub\n", This
);
5536 HRESULT WINAPI
IWineD3DDeviceImpl_Rest(IWineD3DDevice
* iface
, D3DPRESENT_PARAMETERS
* pPresentationParameters
) {
5537 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5538 /** FIXME: Resource trascking needs to be done.
5539 * in effect this pulls all non only default
5540 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5541 * and should clear down the context and set it up according to pPresentationParameters
5542 ***********************************************************/
5543 FIXME("(%p) : stub\n", This
);
5547 HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL bEnableDialogs
) {
5548 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5549 /** FIXME: always true at the moment **/
5550 if(bEnableDialogs
== FALSE
) {
5551 FIXME("(%p) Dialogs cannot be disabled yet\n", This
);
5557 HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, D3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
5558 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5560 FIXME("(%p) : stub\n", This
);
5561 /* Setup some reasonable defaults */
5562 pParameters
->AdapterOrdinal
= 0; /* always for now */
5563 pParameters
->DeviceType
= D3DDEVTYPE_HAL
; /* always for now */
5564 pParameters
->hFocusWindow
= 0;
5565 pParameters
->BehaviorFlags
=0;
5569 void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST D3DGAMMARAMP
* pRamp
) {
5570 IWineD3DSwapChain
*swapchain
;
5571 HRESULT hrc
= D3D_OK
;
5573 TRACE("Relaying to swapchain\n");
5575 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == D3D_OK
) {
5576 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, (D3DGAMMARAMP
*)pRamp
);
5577 IWineD3DSwapChain_Release(swapchain
);
5582 void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, D3DGAMMARAMP
* pRamp
) {
5583 IWineD3DSwapChain
*swapchain
;
5584 HRESULT hrc
= D3D_OK
;
5586 TRACE("Relaying to swapchain\n");
5588 if ((hrc
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)) == D3D_OK
) {
5589 hrc
=IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
5590 IWineD3DSwapChain_Release(swapchain
);
5596 /** ********************************************************
5597 * Notification functions
5598 ** ********************************************************/
5599 /** This function must be called in the release of a resource when ref == 0,
5600 * the contents of resource must still be correct,
5601 * any handels to other resource held by the caller must be closed
5602 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5603 *****************************************************/
5604 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
5605 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5606 ResourceList
* resourceList
;
5608 TRACE("(%p) : resource %p\n", This
, resource
);
5610 EnterCriticalSection(&resourceStoreCriticalSection
);
5612 /* add a new texture to the frot of the linked list */
5613 resourceList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ResourceList
));
5614 resourceList
->resource
= resource
;
5616 /* Get the old head */
5617 resourceList
->next
= This
->resources
;
5619 This
->resources
= resourceList
;
5620 TRACE("Added resource %p with element %p pointing to %p\n", resource
, resourceList
, resourceList
->next
);
5623 LeaveCriticalSection(&resourceStoreCriticalSection
);
5628 static void WINAPI
IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
5629 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5630 ResourceList
* resourceList
= NULL
;
5631 ResourceList
* previousResourceList
= NULL
;
5633 TRACE("(%p) : resource %p\n", This
, resource
);
5636 EnterCriticalSection(&resourceStoreCriticalSection
);
5638 resourceList
= This
->resources
;
5640 while (resourceList
!= NULL
) {
5641 if(resourceList
->resource
== resource
) break;
5642 previousResourceList
= resourceList
;
5643 resourceList
= resourceList
->next
;
5646 if (resourceList
== NULL
) {
5647 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource
);
5649 LeaveCriticalSection(&resourceStoreCriticalSection
);
5653 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList
->resource
, resourceList
, resourceList
->next
, previousResourceList
);
5655 /* make sure we don't leave a hole in the list */
5656 if (previousResourceList
!= NULL
) {
5657 previousResourceList
->next
= resourceList
->next
;
5659 This
->resources
= resourceList
->next
;
5663 LeaveCriticalSection(&resourceStoreCriticalSection
);
5669 void WINAPI
IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
5670 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5673 TRACE("(%p) : resource %p\n", This
, resource
);
5674 switch(IWineD3DResource_GetType(resource
)){
5675 case D3DRTYPE_SURFACE
:
5676 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5678 case D3DRTYPE_TEXTURE
:
5679 case D3DRTYPE_CUBETEXTURE
:
5680 case D3DRTYPE_VOLUMETEXTURE
:
5681 for (counter
= 0; counter
< GL_LIMITS(textures
); counter
++) {
5682 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
5683 IUnknown
*textureParent
;
5684 IWineD3DBaseTexture_GetParent(This
->stateBlock
->textures
[counter
], &textureParent
);
5685 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5686 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter
, resource
, textureParent
);
5687 IUnknown_Release(textureParent
);
5688 This
->stateBlock
->textures
[counter
] = NULL
;
5690 if (This
->updateStateBlock
!= This
->stateBlock
){
5691 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
5692 IUnknown
*textureParent
;
5693 IWineD3DBaseTexture_GetParent(This
->updateStateBlock
->textures
[counter
], &textureParent
);
5694 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5695 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter
, resource
, textureParent
);
5696 IUnknown_Release(textureParent
);
5697 This
->updateStateBlock
->textures
[counter
] = NULL
;
5702 case D3DRTYPE_VOLUME
:
5703 /* TODO: nothing really? */
5705 case D3DRTYPE_VERTEXBUFFER
:
5706 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5709 TRACE("Cleaning up stream pointers\n");
5711 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
5712 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5713 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5715 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
5716 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
5717 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
5718 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
5719 /* Set changed flag? */
5722 if (This
->stateBlock
!= NULL
) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
5723 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
5724 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber
);
5725 This
->stateBlock
->streamSource
[streamNumber
] = 0;
5728 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5729 else { /* This shouldn't happen */
5730 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5737 case D3DRTYPE_INDEXBUFFER
:
5738 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5739 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
5740 if (This
->updateStateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
5741 This
->updateStateBlock
->pIndexData
= NULL
;
5744 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
5745 if (This
->stateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
5746 This
->stateBlock
->pIndexData
= NULL
;
5752 FIXME("(%p) unknown resource type %p %u \n", This
, resource
, IWineD3DResource_GetType(resource
));
5757 /* Remove the resoruce from the resourceStore */
5758 IWineD3DDeviceImpl_RemoveResource(iface
, resource
);
5760 TRACE("Resource released\n");
5765 /** This function is to be called by the swapchain when it is released and it's ref = 0
5766 *****************************************************/
5767 void WINAPI
IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice
*iface
, IWineD3DSwapChain
*swapChain
){
5768 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5769 SwapChainList
**nextSwapchain
;
5770 nextSwapchain
= &This
->swapchains
;
5772 /* Check to see if the swapchian is being used as the render target */
5773 if (This
->renderTarget
!= NULL
) {
5774 IWineD3DSurface
*swapchainBackBuffer
;
5776 IWineD3DSwapChain_GetBackBuffer(swapChain
, 0 ,( D3DBACKBUFFER_TYPE
) 0, &swapchainBackBuffer
);
5777 if (This
->renderTarget
== swapchainBackBuffer
) {
5778 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5779 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5783 /* Go through the swapchain list and try to find the swapchain being released */
5784 while(*nextSwapchain
!= NULL
&& (*nextSwapchain
)->swapchain
!= swapChain
) {
5785 nextSwapchain
= &(*nextSwapchain
)->next
;
5788 /* Check to see if we found the swapchain */
5789 if (NULL
!= *nextSwapchain
) {
5790 /* We found the swapchain so remove it from the list */
5791 TRACE("(%p) releasing swapchain(%p)\n", iface
, swapChain
);
5792 HeapFree(GetProcessHeap(), 0 , *nextSwapchain
);
5793 *nextSwapchain
= (*nextSwapchain
)->next
;
5795 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5796 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface
, swapChain
);
5799 TRACE("swapchain (%p) released\n", swapChain
);
5803 /**********************************************************
5804 * IWineD3DDevice VTbl follows
5805 **********************************************************/
5807 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
5809 /*** IUnknown methods ***/
5810 IWineD3DDeviceImpl_QueryInterface
,
5811 IWineD3DDeviceImpl_AddRef
,
5812 IWineD3DDeviceImpl_Release
,
5813 /*** IWineD3DDevice methods ***/
5814 IWineD3DDeviceImpl_GetParent
,
5815 /*** Creation methods**/
5816 IWineD3DDeviceImpl_CreateVertexBuffer
,
5817 IWineD3DDeviceImpl_CreateIndexBuffer
,
5818 IWineD3DDeviceImpl_CreateStateBlock
,
5819 IWineD3DDeviceImpl_CreateSurface
,
5820 IWineD3DDeviceImpl_CreateTexture
,
5821 IWineD3DDeviceImpl_CreateVolumeTexture
,
5822 IWineD3DDeviceImpl_CreateVolume
,
5823 IWineD3DDeviceImpl_CreateCubeTexture
,
5824 IWineD3DDeviceImpl_CreateQuery
,
5825 IWineD3DDeviceImpl_CreateAdditionalSwapChain
,
5826 IWineD3DDeviceImpl_CreateVertexDeclaration
,
5827 IWineD3DDeviceImpl_CreateVertexShader
,
5828 IWineD3DDeviceImpl_CreatePixelShader
,
5830 /*** Odd functions **/
5831 IWineD3DDeviceImpl_EvictManagedResources
,
5832 IWineD3DDeviceImpl_GetAvailableTextureMem
,
5833 IWineD3DDeviceImpl_GetBackBuffer
,
5834 IWineD3DDeviceImpl_GetCreationParameters
,
5835 IWineD3DDeviceImpl_GetDeviceCaps
,
5836 IWineD3DDeviceImpl_GetDirect3D
,
5837 IWineD3DDeviceImpl_GetDisplayMode
,
5838 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
5839 IWineD3DDeviceImpl_GetRasterStatus
,
5840 IWineD3DDeviceImpl_GetSwapChain
,
5841 IWineD3DDeviceImpl_Reset
,
5842 IWineD3DDeviceImpl_SetDialogBoxMode
,
5843 IWineD3DDeviceImpl_SetCursorProperties
,
5844 IWineD3DDeviceImpl_SetCursorPosition
,
5845 IWineD3DDeviceImpl_ShowCursor
,
5846 IWineD3DDeviceImpl_TestCooperativeLevel
,
5847 /*** Getters and setters **/
5848 IWineD3DDeviceImpl_SetClipPlane
,
5849 IWineD3DDeviceImpl_GetClipPlane
,
5850 IWineD3DDeviceImpl_SetClipStatus
,
5851 IWineD3DDeviceImpl_GetClipStatus
,
5852 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
5853 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
5854 IWineD3DDeviceImpl_SetDepthStencilSurface
,
5855 IWineD3DDeviceImpl_GetDepthStencilSurface
,
5856 IWineD3DDeviceImpl_SetFVF
,
5857 IWineD3DDeviceImpl_GetFVF
,
5858 IWineD3DDeviceImpl_SetGammaRamp
,
5859 IWineD3DDeviceImpl_GetGammaRamp
,
5860 IWineD3DDeviceImpl_SetIndices
,
5861 IWineD3DDeviceImpl_GetIndices
,
5862 IWineD3DDeviceImpl_SetLight
,
5863 IWineD3DDeviceImpl_GetLight
,
5864 IWineD3DDeviceImpl_SetLightEnable
,
5865 IWineD3DDeviceImpl_GetLightEnable
,
5866 IWineD3DDeviceImpl_SetMaterial
,
5867 IWineD3DDeviceImpl_GetMaterial
,
5868 IWineD3DDeviceImpl_SetNPatchMode
,
5869 IWineD3DDeviceImpl_GetNPatchMode
,
5870 IWineD3DDeviceImpl_SetPaletteEntries
,
5871 IWineD3DDeviceImpl_GetPaletteEntries
,
5872 IWineD3DDeviceImpl_SetPixelShader
,
5873 IWineD3DDeviceImpl_GetPixelShader
,
5874 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
5875 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
5876 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
5877 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
5878 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
5879 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
5880 IWineD3DDeviceImpl_SetRenderState
,
5881 IWineD3DDeviceImpl_GetRenderState
,
5882 IWineD3DDeviceImpl_SetRenderTarget
,
5883 IWineD3DDeviceImpl_GetRenderTarget
,
5884 IWineD3DDeviceImpl_SetSamplerState
,
5885 IWineD3DDeviceImpl_GetSamplerState
,
5886 IWineD3DDeviceImpl_SetScissorRect
,
5887 IWineD3DDeviceImpl_GetScissorRect
,
5888 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
5889 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
5890 IWineD3DDeviceImpl_SetStreamSource
,
5891 IWineD3DDeviceImpl_GetStreamSource
,
5892 IWineD3DDeviceImpl_SetStreamSourceFreq
,
5893 IWineD3DDeviceImpl_GetStreamSourceFreq
,
5894 IWineD3DDeviceImpl_SetTexture
,
5895 IWineD3DDeviceImpl_GetTexture
,
5896 IWineD3DDeviceImpl_SetTextureStageState
,
5897 IWineD3DDeviceImpl_GetTextureStageState
,
5898 IWineD3DDeviceImpl_SetTransform
,
5899 IWineD3DDeviceImpl_GetTransform
,
5900 IWineD3DDeviceImpl_SetVertexDeclaration
,
5901 IWineD3DDeviceImpl_GetVertexDeclaration
,
5902 IWineD3DDeviceImpl_SetVertexShader
,
5903 IWineD3DDeviceImpl_GetVertexShader
,
5904 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
5905 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
5906 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
5907 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
5908 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
5909 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
5910 IWineD3DDeviceImpl_SetViewport
,
5911 IWineD3DDeviceImpl_GetViewport
,
5912 IWineD3DDeviceImpl_MultiplyTransform
,
5913 IWineD3DDeviceImpl_ValidateDevice
,
5914 IWineD3DDeviceImpl_ProcessVertices
,
5915 /*** State block ***/
5916 IWineD3DDeviceImpl_BeginStateBlock
,
5917 IWineD3DDeviceImpl_EndStateBlock
,
5918 /*** Scene management ***/
5919 IWineD3DDeviceImpl_BeginScene
,
5920 IWineD3DDeviceImpl_EndScene
,
5921 IWineD3DDeviceImpl_Present
,
5922 IWineD3DDeviceImpl_Clear
,
5924 IWineD3DDeviceImpl_DrawPrimitive
,
5925 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
5926 IWineD3DDeviceImpl_DrawPrimitiveUP
,
5927 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
5928 IWineD3DDeviceImpl_DrawRectPatch
,
5929 IWineD3DDeviceImpl_DrawTriPatch
,
5930 IWineD3DDeviceImpl_DeletePatch
,
5931 IWineD3DDeviceImpl_ColorFill
,
5932 IWineD3DDeviceImpl_UpdateTexture
,
5933 IWineD3DDeviceImpl_UpdateSurface
,
5934 IWineD3DDeviceImpl_StretchRect
,
5935 IWineD3DDeviceImpl_GetRenderTargetData
,
5936 IWineD3DDeviceImpl_GetFrontBufferData
,
5937 /*** Internal use IWineD3DDevice methods ***/
5938 IWineD3DDeviceImpl_SetupTextureStates
,
5939 IWineD3DDeviceImpl_SwapChainReleased
,
5940 /*** object tracking ***/
5941 IWineD3DDeviceImpl_ResourceReleased
5945 const DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
5946 WINED3DRS_ALPHABLENDENABLE
,
5947 WINED3DRS_ALPHAFUNC
,
5948 WINED3DRS_ALPHAREF
,
5949 WINED3DRS_ALPHATESTENABLE
,
5951 WINED3DRS_COLORWRITEENABLE
,
5952 WINED3DRS_DESTBLEND
,
5953 WINED3DRS_DITHERENABLE
,
5954 WINED3DRS_FILLMODE
,
5955 WINED3DRS_FOGDENSITY
,
5957 WINED3DRS_FOGSTART
,
5958 WINED3DRS_LASTPIXEL
,
5959 WINED3DRS_SHADEMODE
,
5960 WINED3DRS_SRCBLEND
,
5961 WINED3DRS_STENCILENABLE
,
5962 WINED3DRS_STENCILFAIL
,
5963 WINED3DRS_STENCILFUNC
,
5964 WINED3DRS_STENCILMASK
,
5965 WINED3DRS_STENCILPASS
,
5966 WINED3DRS_STENCILREF
,
5967 WINED3DRS_STENCILWRITEMASK
,
5968 WINED3DRS_STENCILZFAIL
,
5969 WINED3DRS_TEXTUREFACTOR
,
5980 WINED3DRS_ZWRITEENABLE
5983 const DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
5984 WINED3DTSS_ADDRESSW
,
5985 WINED3DTSS_ALPHAARG0
,
5986 WINED3DTSS_ALPHAARG1
,
5987 WINED3DTSS_ALPHAARG2
,
5988 WINED3DTSS_ALPHAOP
,
5989 WINED3DTSS_BUMPENVLOFFSET
,
5990 WINED3DTSS_BUMPENVLSCALE
,
5991 WINED3DTSS_BUMPENVMAT00
,
5992 WINED3DTSS_BUMPENVMAT01
,
5993 WINED3DTSS_BUMPENVMAT10
,
5994 WINED3DTSS_BUMPENVMAT11
,
5995 WINED3DTSS_COLORARG0
,
5996 WINED3DTSS_COLORARG1
,
5997 WINED3DTSS_COLORARG2
,
5998 WINED3DTSS_COLOROP
,
5999 WINED3DTSS_RESULTARG
,
6000 WINED3DTSS_TEXCOORDINDEX
,
6001 WINED3DTSS_TEXTURETRANSFORMFLAGS
6004 const DWORD SavedPixelStates_S
[NUM_SAVEDPIXELSTATES_S
] = {
6005 WINED3DSAMP_ADDRESSU
,
6006 WINED3DSAMP_ADDRESSV
,
6007 WINED3DSAMP_ADDRESSW
,
6008 WINED3DSAMP_BORDERCOLOR
,
6009 WINED3DSAMP_MAGFILTER
,
6010 WINED3DSAMP_MINFILTER
,
6011 WINED3DSAMP_MIPFILTER
,
6012 WINED3DSAMP_MIPMAPLODBIAS
,
6013 WINED3DSAMP_MAXMIPLEVEL
,
6014 WINED3DSAMP_MAXANISOTROPY
,
6015 WINED3DSAMP_SRGBTEXTURE
,
6016 WINED3DSAMP_ELEMENTINDEX
6019 const DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
6021 WINED3DRS_AMBIENTMATERIALSOURCE
,
6022 WINED3DRS_CLIPPING
,
6023 WINED3DRS_CLIPPLANEENABLE
,
6024 WINED3DRS_COLORVERTEX
,
6025 WINED3DRS_DIFFUSEMATERIALSOURCE
,
6026 WINED3DRS_EMISSIVEMATERIALSOURCE
,
6027 WINED3DRS_FOGDENSITY
,
6029 WINED3DRS_FOGSTART
,
6030 WINED3DRS_FOGTABLEMODE
,
6031 WINED3DRS_FOGVERTEXMODE
,
6032 WINED3DRS_INDEXEDVERTEXBLENDENABLE
,
6033 WINED3DRS_LIGHTING
,
6034 WINED3DRS_LOCALVIEWER
,
6035 WINED3DRS_MULTISAMPLEANTIALIAS
,
6036 WINED3DRS_MULTISAMPLEMASK
,
6037 WINED3DRS_NORMALIZENORMALS
,
6038 WINED3DRS_PATCHEDGESTYLE
,
6039 WINED3DRS_POINTSCALE_A
,
6040 WINED3DRS_POINTSCALE_B
,
6041 WINED3DRS_POINTSCALE_C
,
6042 WINED3DRS_POINTSCALEENABLE
,
6043 WINED3DRS_POINTSIZE
,
6044 WINED3DRS_POINTSIZE_MAX
,
6045 WINED3DRS_POINTSIZE_MIN
,
6046 WINED3DRS_POINTSPRITEENABLE
,
6047 WINED3DRS_RANGEFOGENABLE
,
6048 WINED3DRS_SPECULARMATERIALSOURCE
,
6049 WINED3DRS_TWEENFACTOR
,
6050 WINED3DRS_VERTEXBLEND
6053 const DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
6054 WINED3DTSS_TEXCOORDINDEX
,
6055 WINED3DTSS_TEXTURETRANSFORMFLAGS
6058 const DWORD SavedVertexStates_S
[NUM_SAVEDVERTEXSTATES_S
] = {
6059 WINED3DSAMP_DMAPOFFSET