2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
10 * Copyright 2006-2007 Henri Verbeet
11 * Copyright 2007 Andrew Riedi
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wined3d_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
36 #define GLINFO_LOCATION This->adapter->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light
= {
41 WINED3DLIGHT_DIRECTIONAL
, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* static function declarations */
55 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
);
58 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
60 #define D3DCREATEOBJECTINSTANCE(object, type) { \
61 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
62 D3DMEMCHECK(object, pp##type); \
63 object->lpVtbl = &IWineD3D##type##_Vtbl; \
64 object->wineD3DDevice = This; \
65 object->parent = parent; \
67 *pp##type = (IWineD3D##type *) object; \
70 #define D3DCREATESHADEROBJECTINSTANCE(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->parent = parent; \
75 object->baseShader.ref = 1; \
76 object->baseShader.device = (IWineD3DDevice*) This; \
77 list_init(&object->baseShader.linked_programs); \
78 *pp##type = (IWineD3D##type *) object; \
81 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
82 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
83 D3DMEMCHECK(object, pp##type); \
84 object->lpVtbl = &IWineD3D##type##_Vtbl; \
85 object->resource.wineD3DDevice = This; \
86 object->resource.parent = parent; \
87 object->resource.resourceType = d3dtype; \
88 object->resource.ref = 1; \
89 object->resource.pool = Pool; \
90 object->resource.format = Format; \
91 object->resource.usage = Usage; \
92 object->resource.size = _size; \
93 list_init(&object->resource.privateData); \
94 /* Check that we have enough video ram left */ \
95 if (Pool == WINED3DPOOL_DEFAULT) { \
96 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
97 WARN("Out of 'bogus' video memory\n"); \
98 HeapFree(GetProcessHeap(), 0, object); \
100 return WINED3DERR_OUTOFVIDEOMEMORY; \
102 WineD3DAdapterChangeGLRam(This, _size); \
104 object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \
105 if (object->resource.heapMemory == NULL && _size != 0) { \
106 FIXME("Out of memory!\n"); \
107 HeapFree(GetProcessHeap(), 0, object); \
109 return WINED3DERR_OUTOFVIDEOMEMORY; \
111 object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \
112 *pp##type = (IWineD3D##type *) object; \
113 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
114 TRACE("(%p) : Created resource %p\n", This, object); \
117 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
118 _basetexture.levels = Levels; \
119 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
120 _basetexture.LOD = 0; \
121 _basetexture.dirty = TRUE; \
122 _basetexture.is_srgb = FALSE; \
123 _basetexture.srgb_mode_change_count = 0; \
126 /**********************************************************
127 * Global variable / Constants follow
128 **********************************************************/
129 const float identity
[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
131 /**********************************************************
132 * IUnknown parts follows
133 **********************************************************/
135 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
137 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
139 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
140 if (IsEqualGUID(riid
, &IID_IUnknown
)
141 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
142 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
143 IUnknown_AddRef(iface
);
148 return E_NOINTERFACE
;
151 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
152 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
153 ULONG refCount
= InterlockedIncrement(&This
->ref
);
155 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
159 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
160 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
161 ULONG refCount
= InterlockedDecrement(&This
->ref
);
163 TRACE("(%p) : Releasing from %d\n", This
, refCount
+ 1);
167 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->fbo
));
170 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->src_fbo
));
173 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->dst_fbo
));
176 /* TODO: Clean up all the surfaces and textures! */
177 /* NOTE: You must release the parent if the object was created via a callback
178 ** ***************************/
180 if (!list_empty(&This
->resources
)) {
181 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
182 dumpResources(&This
->resources
);
185 if(This
->contexts
) ERR("Context array not freed!\n");
186 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
187 This
->haveHardwareCursor
= FALSE
;
189 IWineD3D_Release(This
->wineD3D
);
190 This
->wineD3D
= NULL
;
191 HeapFree(GetProcessHeap(), 0, This
);
192 TRACE("Freed device %p\n", This
);
198 /**********************************************************
199 * IWineD3DDevice implementation follows
200 **********************************************************/
201 static HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
202 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
203 *pParent
= This
->parent
;
204 IUnknown_AddRef(This
->parent
);
208 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
209 DWORD FVF
, WINED3DPOOL Pool
, IWineD3DVertexBuffer
** ppVertexBuffer
, HANDLE
*sharedHandle
,
211 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
212 IWineD3DVertexBufferImpl
*object
;
213 WINED3DFORMAT Format
= WINED3DFMT_VERTEXDATA
; /* Dummy format for now */
214 int dxVersion
= ( (IWineD3DImpl
*) This
->wineD3D
)->dxVersion
;
218 WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
219 *ppVertexBuffer
= NULL
;
220 return WINED3DERR_INVALIDCALL
;
221 } else if(Pool
== WINED3DPOOL_SCRATCH
) {
222 /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
223 * anyway, SCRATCH vertex buffers aren't usable anywhere
225 WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
226 *ppVertexBuffer
= NULL
;
227 return WINED3DERR_INVALIDCALL
;
230 D3DCREATERESOURCEOBJECTINSTANCE(object
, VertexBuffer
, WINED3DRTYPE_VERTEXBUFFER
, Size
)
232 TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This
, Size
, Usage
, FVF
, Pool
, object
->resource
.allocatedMemory
, object
);
233 *ppVertexBuffer
= (IWineD3DVertexBuffer
*)object
;
237 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
238 * drawStridedFast (half-life 2).
240 * Basically converting the vertices in the buffer is quite expensive, and observations
241 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
242 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
244 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
245 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
246 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
247 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
249 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
250 * more. In this call we can convert dx7 buffers too.
252 conv
= ((FVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) || (FVF
& (WINED3DFVF_DIFFUSE
| WINED3DFVF_SPECULAR
));
253 if(!GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
254 TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n");
255 } else if(Pool
== WINED3DPOOL_SYSTEMMEM
) {
256 TRACE("Not creating a vbo because the vertex buffer is in system memory\n");
257 } else if(Usage
& WINED3DUSAGE_DYNAMIC
) {
258 TRACE("Not creating a vbo because the buffer has dynamic usage\n");
259 } else if(dxVersion
<= 7 && conv
) {
260 TRACE("Not creating a vbo because dxVersion is 7 and the fvf needs conversion\n");
262 object
->Flags
|= VBFLAG_CREATEVBO
;
267 static void CreateIndexBufferVBO(IWineD3DDeviceImpl
*This
, IWineD3DIndexBufferImpl
*object
) {
268 GLenum error
, glUsage
;
269 TRACE("Creating VBO for Index Buffer %p\n", object
);
271 /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
272 * restored on the next draw
274 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
276 /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
277 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
282 GL_EXTCALL(glGenBuffersARB(1, &object
->vbo
));
283 error
= glGetError();
284 if(error
!= GL_NO_ERROR
|| object
->vbo
== 0) {
285 ERR("Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error
), error
);
289 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, object
->vbo
));
290 error
= glGetError();
291 if(error
!= GL_NO_ERROR
) {
292 ERR("Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error
), error
);
296 /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
297 * copy no readback will be needed
299 glUsage
= GL_STATIC_DRAW_ARB
;
300 GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, object
->resource
.size
, NULL
, glUsage
));
301 error
= glGetError();
302 if(error
!= GL_NO_ERROR
) {
303 ERR("Failed to initialize the index buffer with error %s (%#x)\n", debug_glerror(error
), error
);
307 TRACE("Successfully created vbo %d for index buffer %p\n", object
->vbo
, object
);
311 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0));
312 GL_EXTCALL(glDeleteBuffersARB(1, &object
->vbo
));
317 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
318 WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DIndexBuffer
** ppIndexBuffer
,
319 HANDLE
*sharedHandle
, IUnknown
*parent
) {
320 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
321 IWineD3DIndexBufferImpl
*object
;
322 TRACE("(%p) Creating index buffer\n", This
);
324 /* Allocate the storage for the device */
325 D3DCREATERESOURCEOBJECTINSTANCE(object
,IndexBuffer
,WINED3DRTYPE_INDEXBUFFER
, Length
)
327 if(Pool
!= WINED3DPOOL_SYSTEMMEM
&& !(Usage
& WINED3DUSAGE_DYNAMIC
) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
328 CreateIndexBufferVBO(This
, object
);
331 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This
, Length
, Usage
, Format
,
332 debug_d3dformat(Format
), Pool
, object
, object
->resource
.allocatedMemory
);
333 *ppIndexBuffer
= (IWineD3DIndexBuffer
*) object
;
338 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
* iface
, WINED3DSTATEBLOCKTYPE Type
, IWineD3DStateBlock
** ppStateBlock
, IUnknown
*parent
) {
340 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
341 IWineD3DStateBlockImpl
*object
;
345 D3DCREATEOBJECTINSTANCE(object
, StateBlock
)
346 object
->blockType
= Type
;
348 for(i
= 0; i
< LIGHTMAP_SIZE
; i
++) {
349 list_init(&object
->lightMap
[i
]);
352 /* Special case - Used during initialization to produce a placeholder stateblock
353 so other functions called can update a state block */
354 if (Type
== WINED3DSBT_INIT
) {
355 /* Don't bother increasing the reference count otherwise a device will never
356 be freed due to circular dependencies */
360 temp_result
= allocate_shader_constants(object
);
361 if (WINED3D_OK
!= temp_result
)
364 /* Otherwise, might as well set the whole state block to the appropriate values */
365 if (This
->stateBlock
!= NULL
)
366 stateblock_copy((IWineD3DStateBlock
*) object
, (IWineD3DStateBlock
*) This
->stateBlock
);
368 memset(object
->streamFreq
, 1, sizeof(object
->streamFreq
));
370 /* Reset the ref and type after kludging it */
371 object
->wineD3DDevice
= This
;
373 object
->blockType
= Type
;
375 TRACE("Updating changed flags appropriate for type %d\n", Type
);
377 if (Type
== WINED3DSBT_ALL
) {
379 TRACE("ALL => Pretend everything has changed\n");
380 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, TRUE
);
382 /* Lights are not part of the changed / set structure */
383 for(j
= 0; j
< LIGHTMAP_SIZE
; j
++) {
385 LIST_FOR_EACH(e
, &object
->lightMap
[j
]) {
386 PLIGHTINFOEL
*light
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
387 light
->changed
= TRUE
;
388 light
->enabledChanged
= TRUE
;
391 for(j
= 1; j
<= WINEHIGHEST_RENDER_STATE
; j
++) {
392 object
->contained_render_states
[j
- 1] = j
;
394 object
->num_contained_render_states
= WINEHIGHEST_RENDER_STATE
;
395 /* TODO: Filter unused transforms between TEXTURE8 and WORLD0? */
396 for(j
= 1; j
<= HIGHEST_TRANSFORMSTATE
; j
++) {
397 object
->contained_transform_states
[j
- 1] = j
;
399 object
->num_contained_transform_states
= HIGHEST_TRANSFORMSTATE
;
400 for(j
= 0; j
< GL_LIMITS(vshader_constantsF
); j
++) {
401 object
->contained_vs_consts_f
[j
] = j
;
403 object
->num_contained_vs_consts_f
= GL_LIMITS(vshader_constantsF
);
404 for(j
= 0; j
< MAX_CONST_I
; j
++) {
405 object
->contained_vs_consts_i
[j
] = j
;
407 object
->num_contained_vs_consts_i
= MAX_CONST_I
;
408 for(j
= 0; j
< MAX_CONST_B
; j
++) {
409 object
->contained_vs_consts_b
[j
] = j
;
411 object
->num_contained_vs_consts_b
= MAX_CONST_B
;
412 for(j
= 0; j
< GL_LIMITS(pshader_constantsF
); j
++) {
413 object
->contained_ps_consts_f
[j
] = j
;
415 object
->num_contained_ps_consts_f
= GL_LIMITS(pshader_constantsF
);
416 for(j
= 0; j
< MAX_CONST_I
; j
++) {
417 object
->contained_ps_consts_i
[j
] = j
;
419 object
->num_contained_ps_consts_i
= MAX_CONST_I
;
420 for(j
= 0; j
< MAX_CONST_B
; j
++) {
421 object
->contained_ps_consts_b
[j
] = j
;
423 object
->num_contained_ps_consts_b
= MAX_CONST_B
;
424 for(i
= 0; i
< MAX_TEXTURES
; i
++) {
425 for(j
= 1; j
<= WINED3D_HIGHEST_TEXTURE_STATE
; j
++) {
426 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= i
;
427 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= j
;
428 object
->num_contained_tss_states
++;
431 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
432 for(j
= 1; j
<= WINED3D_HIGHEST_SAMPLER_STATE
; j
++) {
433 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= i
;
434 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= j
;
435 object
->num_contained_sampler_states
++;
439 for(i
= 0; i
< MAX_STREAMS
; i
++) {
440 if(object
->streamSource
[i
]) {
441 IWineD3DVertexBuffer_AddRef(object
->streamSource
[i
]);
444 if(object
->pIndexData
) {
445 IWineD3DIndexBuffer_AddRef(object
->pIndexData
);
447 if(object
->vertexShader
) {
448 IWineD3DVertexShader_AddRef(object
->vertexShader
);
450 if(object
->pixelShader
) {
451 IWineD3DPixelShader_AddRef(object
->pixelShader
);
454 } else if (Type
== WINED3DSBT_PIXELSTATE
) {
456 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
457 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
459 object
->changed
.pixelShader
= TRUE
;
461 /* Pixel Shader Constants */
462 for (i
= 0; i
< GL_LIMITS(vshader_constantsF
); ++i
) {
463 object
->contained_ps_consts_f
[i
] = i
;
464 object
->changed
.pixelShaderConstantsF
[i
] = TRUE
;
466 object
->num_contained_ps_consts_f
= GL_LIMITS(vshader_constantsF
);
467 for (i
= 0; i
< MAX_CONST_B
; ++i
) {
468 object
->contained_ps_consts_b
[i
] = i
;
469 object
->changed
.pixelShaderConstantsB
[i
] = TRUE
;
471 object
->num_contained_ps_consts_b
= MAX_CONST_B
;
472 for (i
= 0; i
< MAX_CONST_I
; ++i
) {
473 object
->contained_ps_consts_i
[i
] = i
;
474 object
->changed
.pixelShaderConstantsI
[i
] = TRUE
;
476 object
->num_contained_ps_consts_i
= MAX_CONST_I
;
478 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
479 object
->changed
.renderState
[SavedPixelStates_R
[i
]] = TRUE
;
480 object
->contained_render_states
[i
] = SavedPixelStates_R
[i
];
482 object
->num_contained_render_states
= NUM_SAVEDPIXELSTATES_R
;
483 for (j
= 0; j
< MAX_TEXTURES
; j
++) {
484 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
485 object
->changed
.textureState
[j
][SavedPixelStates_T
[i
]] = TRUE
;
486 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= j
;
487 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= SavedPixelStates_T
[i
];
488 object
->num_contained_tss_states
++;
491 for (j
= 0 ; j
< MAX_COMBINED_SAMPLERS
; j
++) {
492 for (i
=0; i
< NUM_SAVEDPIXELSTATES_S
;i
++) {
493 object
->changed
.samplerState
[j
][SavedPixelStates_S
[i
]] = TRUE
;
494 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= j
;
495 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= SavedPixelStates_S
[i
];
496 object
->num_contained_sampler_states
++;
499 if(object
->pixelShader
) {
500 IWineD3DPixelShader_AddRef(object
->pixelShader
);
503 /* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
504 * on them. This makes releasing the buffer easier
506 for(i
= 0; i
< MAX_STREAMS
; i
++) {
507 object
->streamSource
[i
] = NULL
;
509 object
->pIndexData
= NULL
;
510 object
->vertexShader
= NULL
;
512 } else if (Type
== WINED3DSBT_VERTEXSTATE
) {
514 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
515 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
517 object
->changed
.vertexShader
= TRUE
;
519 /* Vertex Shader Constants */
520 for (i
= 0; i
< GL_LIMITS(vshader_constantsF
); ++i
) {
521 object
->changed
.vertexShaderConstantsF
[i
] = TRUE
;
522 object
->contained_vs_consts_f
[i
] = i
;
524 object
->num_contained_vs_consts_f
= GL_LIMITS(vshader_constantsF
);
525 for (i
= 0; i
< MAX_CONST_B
; ++i
) {
526 object
->changed
.vertexShaderConstantsB
[i
] = TRUE
;
527 object
->contained_vs_consts_b
[i
] = i
;
529 object
->num_contained_vs_consts_b
= MAX_CONST_B
;
530 for (i
= 0; i
< MAX_CONST_I
; ++i
) {
531 object
->changed
.vertexShaderConstantsI
[i
] = TRUE
;
532 object
->contained_vs_consts_i
[i
] = i
;
534 object
->num_contained_vs_consts_i
= MAX_CONST_I
;
535 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
536 object
->changed
.renderState
[SavedVertexStates_R
[i
]] = TRUE
;
537 object
->contained_render_states
[i
] = SavedVertexStates_R
[i
];
539 object
->num_contained_render_states
= NUM_SAVEDVERTEXSTATES_R
;
540 for (j
= 0; j
< MAX_TEXTURES
; j
++) {
541 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
542 object
->changed
.textureState
[j
][SavedVertexStates_T
[i
]] = TRUE
;
543 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= j
;
544 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= SavedVertexStates_T
[i
];
545 object
->num_contained_tss_states
++;
548 for (j
= 0 ; j
< MAX_COMBINED_SAMPLERS
; j
++){
549 for (i
=0; i
< NUM_SAVEDVERTEXSTATES_S
;i
++) {
550 object
->changed
.samplerState
[j
][SavedVertexStates_S
[i
]] = TRUE
;
551 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= j
;
552 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= SavedVertexStates_S
[i
];
553 object
->num_contained_sampler_states
++;
557 for(j
= 0; j
< LIGHTMAP_SIZE
; j
++) {
559 LIST_FOR_EACH(e
, &object
->lightMap
[j
]) {
560 PLIGHTINFOEL
*light
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
561 light
->changed
= TRUE
;
562 light
->enabledChanged
= TRUE
;
566 for(i
= 0; i
< MAX_STREAMS
; i
++) {
567 if(object
->streamSource
[i
]) {
568 IWineD3DVertexBuffer_AddRef(object
->streamSource
[i
]);
571 if(object
->vertexShader
) {
572 IWineD3DVertexShader_AddRef(object
->vertexShader
);
574 object
->pIndexData
= NULL
;
575 object
->pixelShader
= NULL
;
577 FIXME("Unrecognized state block type %d\n", Type
);
580 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
584 /* ************************************
586 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
589 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
591 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.
593 ******************************** */
595 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, WINED3DFORMAT Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, IWineD3DSurface
**ppSurface
,WINED3DRESOURCETYPE Type
, DWORD Usage
, WINED3DPOOL Pool
, WINED3DMULTISAMPLE_TYPE MultiSample
,DWORD MultisampleQuality
, HANDLE
* pSharedHandle
, WINED3DSURFTYPE Impl
, IUnknown
*parent
) {
596 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
597 IWineD3DSurfaceImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
598 unsigned int Size
= 1;
599 const StaticPixelFormatDesc
*tableEntry
= getFormatDescEntry(Format
, NULL
, NULL
);
600 TRACE("(%p) Create surface\n",This
);
602 /** FIXME: Check ranges on the inputs are valid
605 * [in] Quality level. The valid range is between zero and one less than the level
606 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
607 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
608 * values of paired render targets, depth stencil surfaces, and the MultiSample type
610 *******************************/
615 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
617 * If this flag is set, the contents of the depth stencil buffer will be
618 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
619 * with a different depth surface.
621 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
622 ***************************/
624 if(MultisampleQuality
> 0) {
625 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality
);
626 MultisampleQuality
=0;
629 /** FIXME: Check that the format is supported
631 *******************************/
633 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
634 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
636 *********************************/
637 if (WINED3DFMT_UNKNOWN
== Format
) {
639 } else if (Format
== WINED3DFMT_DXT1
) {
640 /* DXT1 is half byte per pixel */
641 Size
= ((max(Width
,4) * tableEntry
->bpp
) * max(Height
,4)) >> 1;
643 } else if (Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
644 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
) {
645 Size
= ((max(Width
,4) * tableEntry
->bpp
) * max(Height
,4));
647 /* The pitch is a multiple of 4 bytes */
648 Size
= ((Width
* tableEntry
->bpp
) + This
->surface_alignment
- 1) & ~(This
->surface_alignment
- 1);
652 /** Create and initialise the surface resource **/
653 D3DCREATERESOURCEOBJECTINSTANCE(object
,Surface
,WINED3DRTYPE_SURFACE
, Size
)
654 /* "Standalone" surface */
655 IWineD3DSurface_SetContainer((IWineD3DSurface
*)object
, NULL
);
657 object
->currentDesc
.Width
= Width
;
658 object
->currentDesc
.Height
= Height
;
659 object
->currentDesc
.MultiSampleType
= MultiSample
;
660 object
->currentDesc
.MultiSampleQuality
= MultisampleQuality
;
661 object
->glDescription
.level
= Level
;
664 object
->Flags
= SFLAG_NORMCOORD
; /* Default to normalized coords */
665 object
->Flags
|= Discard
? SFLAG_DISCARD
: 0;
666 object
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== Format
) ? SFLAG_LOCKABLE
: 0;
667 object
->Flags
|= Lockable
? SFLAG_LOCKABLE
: 0;
670 if (WINED3DFMT_UNKNOWN
!= Format
) {
671 object
->bytesPerPixel
= tableEntry
->bpp
;
673 object
->bytesPerPixel
= 0;
676 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
678 TRACE("Pool %d %d %d %d\n",Pool
, WINED3DPOOL_DEFAULT
, WINED3DPOOL_MANAGED
, WINED3DPOOL_SYSTEMMEM
);
680 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
681 * this function is too deep to need to care about things like this.
682 * Levels need to be checked too, and possibly Type since they all affect what can be done.
683 * ****************************************/
685 case WINED3DPOOL_SCRATCH
:
687 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
688 "which are mutually exclusive, setting lockable to TRUE\n");
691 case WINED3DPOOL_SYSTEMMEM
:
692 if(!Lockable
) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
693 "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
694 case WINED3DPOOL_MANAGED
:
695 if(Usage
== WINED3DUSAGE_DYNAMIC
) FIXME("Create surface called with a pool of MANAGED and a "
696 "Usage of DYNAMIC which are mutually exclusive, not doing "
697 "anything just telling you.\n");
699 case WINED3DPOOL_DEFAULT
: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
700 if(!(Usage
& WINED3DUSAGE_DYNAMIC
) && !(Usage
& WINED3DUSAGE_RENDERTARGET
)
701 && !(Usage
&& WINED3DUSAGE_DEPTHSTENCIL
) && Lockable
)
702 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
705 FIXME("(%p) Unknown pool %d\n", This
, Pool
);
709 if (Usage
& WINED3DUSAGE_RENDERTARGET
&& Pool
!= WINED3DPOOL_DEFAULT
) {
710 FIXME("Trying to create a render target that isn't in the default pool\n");
713 /* mark the texture as dirty so that it gets loaded first time around*/
714 IWineD3DSurface_AddDirtyRect(*ppSurface
, NULL
);
715 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
716 This
, Width
, Height
, Format
, debug_d3dformat(Format
),
717 (WINED3DFMT_D16_LOCKABLE
== Format
), *ppSurface
, object
->resource
.allocatedMemory
, object
->resource
.size
);
719 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
720 if( (Usage
& WINED3DUSAGE_RENDERTARGET
) && (!This
->ddraw_primary
) )
721 This
->ddraw_primary
= (IWineD3DSurface
*) object
;
723 /* Look at the implementation and set the correct Vtable */
726 /* Check if a 3D adapter is available when creating gl surfaces */
728 ERR("OpenGL surfaces are not available without opengl\n");
729 HeapFree(GetProcessHeap(), 0, object
->resource
.allocatedMemory
);
730 HeapFree(GetProcessHeap(), 0, object
);
731 return WINED3DERR_NOTAVAILABLE
;
736 object
->lpVtbl
= &IWineGDISurface_Vtbl
;
740 /* To be sure to catch this */
741 ERR("Unknown requested surface implementation %d!\n", Impl
);
742 IWineD3DSurface_Release((IWineD3DSurface
*) object
);
743 return WINED3DERR_INVALIDCALL
;
746 list_init(&object
->renderbuffers
);
748 /* Call the private setup routine */
749 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface
*) object
);
753 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
, UINT Width
, UINT Height
, UINT Levels
,
754 DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
755 IWineD3DTexture
** ppTexture
, HANDLE
* pSharedHandle
, IUnknown
*parent
,
756 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
758 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
759 IWineD3DTextureImpl
*object
;
764 unsigned int pow2Width
;
765 unsigned int pow2Height
;
766 const GlPixelFormatDesc
*glDesc
;
767 getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
769 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This
, Width
, Height
, Levels
, Usage
);
770 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
771 Format
, debug_d3dformat(Format
), Pool
, ppTexture
, pSharedHandle
, parent
);
773 /* TODO: It should only be possible to create textures for formats
774 that are reported as supported */
775 if (WINED3DFMT_UNKNOWN
>= Format
) {
776 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This
);
777 return WINED3DERR_INVALIDCALL
;
780 D3DCREATERESOURCEOBJECTINSTANCE(object
, Texture
, WINED3DRTYPE_TEXTURE
, 0);
781 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
782 object
->width
= Width
;
783 object
->height
= Height
;
785 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
786 object
->baseTexture
.minMipLookup
= &minMipLookup
;
787 object
->baseTexture
.magLookup
= &magLookup
;
789 object
->baseTexture
.minMipLookup
= &minMipLookup_noFilter
;
790 object
->baseTexture
.magLookup
= &magLookup_noFilter
;
793 /** Non-power2 support **/
794 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
)) {
798 /* Find the nearest pow2 match */
799 pow2Width
= pow2Height
= 1;
800 while (pow2Width
< Width
) pow2Width
<<= 1;
801 while (pow2Height
< Height
) pow2Height
<<= 1;
803 if(pow2Width
!= Width
|| pow2Height
!= Height
) {
805 WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n");
806 HeapFree(GetProcessHeap(), 0, object
);
808 return WINED3DERR_INVALIDCALL
;
815 /** FIXME: add support for real non-power-two if it's provided by the video card **/
816 /* Precalculated scaling for 'faked' non power of two texture coords.
817 Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
818 is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
819 doesn't work in combination with ARB_TEXTURE_RECTANGLE.
821 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE
) &&
822 (Width
!= pow2Width
|| Height
!= pow2Height
) &&
823 !((Format
== WINED3DFMT_P8
) && GL_SUPPORT(EXT_PALETTED_TEXTURE
) && (wined3d_settings
.rendertargetlock_mode
== RTL_READTEX
|| wined3d_settings
.rendertargetlock_mode
== RTL_TEXTEX
)))
825 object
->baseTexture
.pow2Matrix
[0] = (float)Width
;
826 object
->baseTexture
.pow2Matrix
[5] = (float)Height
;
827 object
->baseTexture
.pow2Matrix
[10] = 1.0;
828 object
->baseTexture
.pow2Matrix
[15] = 1.0;
829 object
->target
= GL_TEXTURE_RECTANGLE_ARB
;
831 object
->baseTexture
.pow2Matrix
[0] = (((float)Width
) / ((float)pow2Width
));
832 object
->baseTexture
.pow2Matrix
[5] = (((float)Height
) / ((float)pow2Height
));
833 object
->baseTexture
.pow2Matrix
[10] = 1.0;
834 object
->baseTexture
.pow2Matrix
[15] = 1.0;
835 object
->target
= GL_TEXTURE_2D
;
837 TRACE(" xf(%f) yf(%f)\n", object
->baseTexture
.pow2Matrix
[0], object
->baseTexture
.pow2Matrix
[5]);
839 /* Calculate levels for mip mapping */
840 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
) {
841 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
842 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
843 return WINED3DERR_INVALIDCALL
;
846 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
847 return WINED3DERR_INVALIDCALL
;
849 object
->baseTexture
.levels
= 1;
850 } else if (Levels
== 0) {
851 TRACE("calculating levels %d\n", object
->baseTexture
.levels
);
852 object
->baseTexture
.levels
++;
855 while (tmpW
> 1 || tmpH
> 1) {
856 tmpW
= max(1, tmpW
>> 1);
857 tmpH
= max(1, tmpH
>> 1);
858 object
->baseTexture
.levels
++;
860 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
863 /* Generate all the surfaces */
866 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
868 /* use the callback to create the texture surface */
869 hr
= D3DCB_CreateSurface(This
->parent
, parent
, tmpW
, tmpH
, Format
, Usage
, Pool
, i
, WINED3DCUBEMAP_FACE_POSITIVE_X
, &object
->surfaces
[i
],NULL
);
870 if (hr
!= WINED3D_OK
|| ( (IWineD3DSurfaceImpl
*) object
->surfaces
[i
])->Flags
& SFLAG_OVERSIZE
) {
871 FIXME("Failed to create surface %p\n", object
);
873 object
->surfaces
[i
] = NULL
;
874 IWineD3DTexture_Release((IWineD3DTexture
*)object
);
880 IWineD3DSurface_SetContainer(object
->surfaces
[i
], (IWineD3DBase
*)object
);
881 TRACE("Created surface level %d @ %p\n", i
, object
->surfaces
[i
]);
882 /* calculate the next mipmap level */
883 tmpW
= max(1, tmpW
>> 1);
884 tmpH
= max(1, tmpH
>> 1);
886 object
->baseTexture
.shader_conversion_group
= glDesc
->conversion_group
;
888 TRACE("(%p) : Created texture %p\n", This
, object
);
892 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
893 UINT Width
, UINT Height
, UINT Depth
,
894 UINT Levels
, DWORD Usage
,
895 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
896 IWineD3DVolumeTexture
**ppVolumeTexture
,
897 HANDLE
*pSharedHandle
, IUnknown
*parent
,
898 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume
) {
900 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
901 IWineD3DVolumeTextureImpl
*object
;
906 const GlPixelFormatDesc
*glDesc
;
908 getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
910 /* TODO: It should only be possible to create textures for formats
911 that are reported as supported */
912 if (WINED3DFMT_UNKNOWN
>= Format
) {
913 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This
);
914 return WINED3DERR_INVALIDCALL
;
916 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
917 WARN("(%p) : Texture cannot be created - no volume texture support\n", This
);
918 return WINED3DERR_INVALIDCALL
;
921 D3DCREATERESOURCEOBJECTINSTANCE(object
, VolumeTexture
, WINED3DRTYPE_VOLUMETEXTURE
, 0);
922 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
924 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
925 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
927 object
->width
= Width
;
928 object
->height
= Height
;
929 object
->depth
= Depth
;
931 /* Is NP2 support for volumes needed? */
932 object
->baseTexture
.pow2Matrix
[ 0] = 1.0;
933 object
->baseTexture
.pow2Matrix
[ 5] = 1.0;
934 object
->baseTexture
.pow2Matrix
[10] = 1.0;
935 object
->baseTexture
.pow2Matrix
[15] = 1.0;
937 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
938 object
->baseTexture
.minMipLookup
= &minMipLookup
;
939 object
->baseTexture
.magLookup
= &magLookup
;
941 object
->baseTexture
.minMipLookup
= &minMipLookup_noFilter
;
942 object
->baseTexture
.magLookup
= &magLookup_noFilter
;
945 /* Calculate levels for mip mapping */
946 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
) {
947 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
948 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
949 return WINED3DERR_INVALIDCALL
;
952 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
953 return WINED3DERR_INVALIDCALL
;
956 } else if (Levels
== 0) {
957 object
->baseTexture
.levels
++;
961 while (tmpW
> 1 || tmpH
> 1 || tmpD
> 1) {
962 tmpW
= max(1, tmpW
>> 1);
963 tmpH
= max(1, tmpH
>> 1);
964 tmpD
= max(1, tmpD
>> 1);
965 object
->baseTexture
.levels
++;
967 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
970 /* Generate all the surfaces */
975 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
978 /* Create the volume */
979 hr
= D3DCB_CreateVolume(This
->parent
, parent
, tmpW
, tmpH
, tmpD
, Format
, Pool
, Usage
,
980 &object
->volumes
[i
], pSharedHandle
);
983 ERR("Creating a volume for the volume texture failed(%08x)\n", hr
);
984 IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture
*) object
);
985 *ppVolumeTexture
= NULL
;
989 /* Set its container to this object */
990 IWineD3DVolume_SetContainer(object
->volumes
[i
], (IWineD3DBase
*)object
);
992 /* calculate the next mipmap level */
993 tmpW
= max(1, tmpW
>> 1);
994 tmpH
= max(1, tmpH
>> 1);
995 tmpD
= max(1, tmpD
>> 1);
997 object
->baseTexture
.shader_conversion_group
= glDesc
->conversion_group
;
999 *ppVolumeTexture
= (IWineD3DVolumeTexture
*) object
;
1000 TRACE("(%p) : Created volume texture %p\n", This
, object
);
1004 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
,
1005 UINT Width
, UINT Height
, UINT Depth
,
1007 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1008 IWineD3DVolume
** ppVolume
,
1009 HANDLE
* pSharedHandle
, IUnknown
*parent
) {
1011 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1012 IWineD3DVolumeImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1013 const StaticPixelFormatDesc
*formatDesc
= getFormatDescEntry(Format
, NULL
, NULL
);
1015 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
1016 WARN("(%p) : Volume cannot be created - no volume texture support\n", This
);
1017 return WINED3DERR_INVALIDCALL
;
1020 D3DCREATERESOURCEOBJECTINSTANCE(object
, Volume
, WINED3DRTYPE_VOLUME
, ((Width
* formatDesc
->bpp
) * Height
* Depth
))
1022 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1023 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1025 object
->currentDesc
.Width
= Width
;
1026 object
->currentDesc
.Height
= Height
;
1027 object
->currentDesc
.Depth
= Depth
;
1028 object
->bytesPerPixel
= formatDesc
->bpp
;
1030 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1031 object
->lockable
= TRUE
;
1032 object
->locked
= FALSE
;
1033 memset(&object
->lockedBox
, 0, sizeof(WINED3DBOX
));
1034 object
->dirty
= TRUE
;
1036 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume
*) object
, NULL
);
1039 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
,
1040 UINT Levels
, DWORD Usage
,
1041 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1042 IWineD3DCubeTexture
**ppCubeTexture
,
1043 HANDLE
*pSharedHandle
, IUnknown
*parent
,
1044 D3DCB_CREATESURFACEFN D3DCB_CreateSurface
) {
1046 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1047 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1051 unsigned int pow2EdgeLength
= EdgeLength
;
1052 const GlPixelFormatDesc
*glDesc
;
1053 getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
1055 /* TODO: It should only be possible to create textures for formats
1056 that are reported as supported */
1057 if (WINED3DFMT_UNKNOWN
>= Format
) {
1058 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This
);
1059 return WINED3DERR_INVALIDCALL
;
1062 if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
) && Pool
!= WINED3DPOOL_SCRATCH
) {
1063 WARN("(%p) : Tried to create not supported cube texture\n", This
);
1064 return WINED3DERR_INVALIDCALL
;
1067 D3DCREATERESOURCEOBJECTINSTANCE(object
, CubeTexture
, WINED3DRTYPE_CUBETEXTURE
, 0);
1068 D3DINITIALIZEBASETEXTURE(object
->baseTexture
);
1070 TRACE("(%p) Create Cube Texture\n", This
);
1072 /** Non-power2 support **/
1074 /* Find the nearest pow2 match */
1076 while (pow2EdgeLength
< EdgeLength
) pow2EdgeLength
<<= 1;
1078 object
->edgeLength
= EdgeLength
;
1079 /* TODO: support for native non-power 2 */
1080 /* Precalculated scaling for 'faked' non power of two texture coords */
1081 object
->baseTexture
.pow2Matrix
[ 0] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1082 object
->baseTexture
.pow2Matrix
[ 5] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1083 object
->baseTexture
.pow2Matrix
[10] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1084 object
->baseTexture
.pow2Matrix
[15] = 1.0;
1086 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
1087 object
->baseTexture
.minMipLookup
= &minMipLookup
;
1088 object
->baseTexture
.magLookup
= &magLookup
;
1090 object
->baseTexture
.minMipLookup
= &minMipLookup_noFilter
;
1091 object
->baseTexture
.magLookup
= &magLookup_noFilter
;
1094 /* Calculate levels for mip mapping */
1095 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
) {
1096 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP
)) {
1097 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
1098 HeapFree(GetProcessHeap(), 0, object
);
1099 *ppCubeTexture
= NULL
;
1101 return WINED3DERR_INVALIDCALL
;
1104 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
1105 HeapFree(GetProcessHeap(), 0, object
);
1106 *ppCubeTexture
= NULL
;
1108 return WINED3DERR_INVALIDCALL
;
1111 } else if (Levels
== 0) {
1112 object
->baseTexture
.levels
++;
1115 tmpW
= max(1, tmpW
>> 1);
1116 object
->baseTexture
.levels
++;
1118 TRACE("Calculated levels = %d\n", object
->baseTexture
.levels
);
1121 /* Generate all the surfaces */
1123 for (i
= 0; i
< object
->baseTexture
.levels
; i
++) {
1125 /* Create the 6 faces */
1126 for (j
= 0; j
< 6; j
++) {
1128 hr
=D3DCB_CreateSurface(This
->parent
, parent
, tmpW
, tmpW
, Format
, Usage
, Pool
,
1129 i
/* Level */, j
, &object
->surfaces
[j
][i
],pSharedHandle
);
1131 if(hr
!= WINED3D_OK
) {
1135 for (l
= 0; l
< j
; l
++) {
1136 IWineD3DSurface_Release(object
->surfaces
[l
][i
]);
1138 for (k
= 0; k
< i
; k
++) {
1139 for (l
= 0; l
< 6; l
++) {
1140 IWineD3DSurface_Release(object
->surfaces
[l
][k
]);
1144 FIXME("(%p) Failed to create surface\n",object
);
1145 HeapFree(GetProcessHeap(),0,object
);
1146 *ppCubeTexture
= NULL
;
1149 IWineD3DSurface_SetContainer(object
->surfaces
[j
][i
], (IWineD3DBase
*)object
);
1150 TRACE("Created surface level %d @ %p,\n", i
, object
->surfaces
[j
][i
]);
1152 tmpW
= max(1, tmpW
>> 1);
1154 object
->baseTexture
.shader_conversion_group
= glDesc
->conversion_group
;
1156 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1157 *ppCubeTexture
= (IWineD3DCubeTexture
*) object
;
1161 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
, WINED3DQUERYTYPE Type
, IWineD3DQuery
**ppQuery
, IUnknown
* parent
) {
1162 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1163 IWineD3DQueryImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
1164 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1165 const IWineD3DQueryVtbl
*vtable
;
1167 /* Just a check to see if we support this type of query */
1169 case WINED3DQUERYTYPE_OCCLUSION
:
1170 TRACE("(%p) occlusion query\n", This
);
1171 if (GL_SUPPORT(ARB_OCCLUSION_QUERY
))
1174 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1176 vtable
= &IWineD3DOcclusionQuery_Vtbl
;
1179 case WINED3DQUERYTYPE_EVENT
:
1180 if(!(GL_SUPPORT(NV_FENCE
) || GL_SUPPORT(APPLE_FENCE
) )) {
1181 /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1182 * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1184 FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This
);
1186 vtable
= &IWineD3DEventQuery_Vtbl
;
1190 case WINED3DQUERYTYPE_VCACHE
:
1191 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1192 case WINED3DQUERYTYPE_VERTEXSTATS
:
1193 case WINED3DQUERYTYPE_TIMESTAMP
:
1194 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1195 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1196 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1197 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1198 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1199 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1200 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1201 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1203 /* Use the base Query vtable until we have a special one for each query */
1204 vtable
= &IWineD3DQuery_Vtbl
;
1205 FIXME("(%p) Unhandled query type %d\n", This
, Type
);
1207 if(NULL
== ppQuery
|| hr
!= WINED3D_OK
) {
1211 D3DCREATEOBJECTINSTANCE(object
, Query
)
1212 object
->lpVtbl
= vtable
;
1213 object
->type
= Type
;
1214 object
->state
= QUERY_CREATED
;
1215 /* allocated the 'extended' data based on the type of query requested */
1217 case WINED3DQUERYTYPE_OCCLUSION
:
1218 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryOcclusionData
));
1219 ((WineQueryOcclusionData
*)(object
->extendedData
))->ctx
= This
->activeContext
;
1221 if(GL_SUPPORT(ARB_OCCLUSION_QUERY
)) {
1222 TRACE("(%p) Allocating data for an occlusion query\n", This
);
1223 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData
*)(object
->extendedData
))->queryId
));
1226 case WINED3DQUERYTYPE_EVENT
:
1227 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryEventData
));
1228 ((WineQueryEventData
*)(object
->extendedData
))->ctx
= This
->activeContext
;
1230 if(GL_SUPPORT(APPLE_FENCE
)) {
1231 GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData
*)(object
->extendedData
))->fenceId
));
1232 checkGLcall("glGenFencesAPPLE");
1233 } else if(GL_SUPPORT(NV_FENCE
)) {
1234 GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData
*)(object
->extendedData
))->fenceId
));
1235 checkGLcall("glGenFencesNV");
1239 case WINED3DQUERYTYPE_VCACHE
:
1240 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1241 case WINED3DQUERYTYPE_VERTEXSTATS
:
1242 case WINED3DQUERYTYPE_TIMESTAMP
:
1243 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1244 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1245 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1246 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1247 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1248 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1249 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1250 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1252 object
->extendedData
= 0;
1253 FIXME("(%p) Unhandled query type %d\n",This
, Type
);
1255 TRACE("(%p) : Created Query %p\n", This
, object
);
1259 /*****************************************************************************
1260 * IWineD3DDeviceImpl_SetupFullscreenWindow
1262 * Helper function that modifies a HWND's Style and ExStyle for proper
1266 * iface: Pointer to the IWineD3DDevice interface
1267 * window: Window to setup
1269 *****************************************************************************/
1270 static LONG
fullscreen_style(LONG orig_style
) {
1271 LONG style
= orig_style
;
1272 style
&= ~WS_CAPTION
;
1273 style
&= ~WS_THICKFRAME
;
1275 /* Make sure the window is managed, otherwise we won't get keyboard input */
1276 style
|= WS_POPUP
| WS_SYSMENU
;
1281 static LONG
fullscreen_exStyle(LONG orig_exStyle
) {
1282 LONG exStyle
= orig_exStyle
;
1284 /* Filter out window decorations */
1285 exStyle
&= ~WS_EX_WINDOWEDGE
;
1286 exStyle
&= ~WS_EX_CLIENTEDGE
;
1291 static void WINAPI
IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice
*iface
, HWND window
) {
1292 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1294 LONG style
, exStyle
;
1295 /* Don't do anything if an original style is stored.
1296 * That shouldn't happen
1298 TRACE("(%p): Setting up window %p for exclusive mode\n", This
, window
);
1299 if (This
->style
|| This
->exStyle
) {
1300 ERR("(%p): Want to change the window parameters of HWND %p, but "
1301 "another style is stored for restoration afterwards\n", This
, window
);
1304 /* Get the parameters and save them */
1305 style
= GetWindowLongW(window
, GWL_STYLE
);
1306 exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1307 This
->style
= style
;
1308 This
->exStyle
= exStyle
;
1310 style
= fullscreen_style(style
);
1311 exStyle
= fullscreen_exStyle(exStyle
);
1313 TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1314 This
->style
, This
->exStyle
, style
, exStyle
);
1316 SetWindowLongW(window
, GWL_STYLE
, style
);
1317 SetWindowLongW(window
, GWL_EXSTYLE
, exStyle
);
1319 /* Inform the window about the update. */
1320 SetWindowPos(window
, HWND_TOP
, 0, 0,
1321 This
->ddraw_width
, This
->ddraw_height
, SWP_FRAMECHANGED
);
1322 ShowWindow(window
, SW_NORMAL
);
1325 /*****************************************************************************
1326 * IWineD3DDeviceImpl_RestoreWindow
1328 * Helper function that restores a windows' properties when taking it out
1329 * of fullscreen mode
1332 * iface: Pointer to the IWineD3DDevice interface
1333 * window: Window to setup
1335 *****************************************************************************/
1336 static void WINAPI
IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice
*iface
, HWND window
) {
1337 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1338 LONG style
, exStyle
;
1340 /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1341 * switch, do nothing
1343 if (!This
->style
&& !This
->exStyle
) return;
1345 TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1346 This
, window
, This
->style
, This
->exStyle
);
1348 style
= GetWindowLongW(window
, GWL_STYLE
);
1349 exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1351 /* Only restore the style if the application didn't modify it during the fullscreen phase.
1352 * Some applications change it before calling Reset() when switching between windowed and
1353 * fullscreen modes(HL2), some depend on the original style(Eve Online)
1355 if(style
== fullscreen_style(This
->style
) &&
1356 exStyle
== fullscreen_style(This
->exStyle
)) {
1357 SetWindowLongW(window
, GWL_STYLE
, This
->style
);
1358 SetWindowLongW(window
, GWL_EXSTYLE
, This
->exStyle
);
1361 /* Delete the old values */
1365 /* Inform the window about the update */
1366 SetWindowPos(window
, 0 /* InsertAfter, ignored */,
1367 0, 0, 0, 0, /* Pos, Size, ignored */
1368 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
);
1371 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1372 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, IWineD3DSwapChain
** ppSwapChain
,
1374 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget
,
1375 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil
) {
1376 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1379 IWineD3DSwapChainImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1380 HRESULT hr
= WINED3D_OK
;
1381 IUnknown
*bufferParent
;
1382 BOOL displaymode_set
= FALSE
;
1383 WINED3DDISPLAYMODE Mode
;
1384 const StaticPixelFormatDesc
*formatDesc
;
1386 TRACE("(%p) : Created Additional Swap Chain\n", This
);
1388 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1389 * does a device hold a reference to a swap chain giving them a lifetime of the device
1390 * or does the swap chain notify the device of its destruction.
1391 *******************************/
1393 /* Check the params */
1394 if(pPresentationParameters
->BackBufferCount
> WINED3DPRESENT_BACK_BUFFER_MAX
) {
1395 ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters
->BackBufferCount
);
1396 return WINED3DERR_INVALIDCALL
;
1397 } else if (pPresentationParameters
->BackBufferCount
> 1) {
1398 FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1401 D3DCREATEOBJECTINSTANCE(object
, SwapChain
)
1403 /*********************
1404 * Lookup the window Handle and the relating X window handle
1405 ********************/
1407 /* Setup hwnd we are using, plus which display this equates to */
1408 object
->win_handle
= pPresentationParameters
->hDeviceWindow
;
1409 if (!object
->win_handle
) {
1410 object
->win_handle
= This
->createParms
.hFocusWindow
;
1412 if(!This
->ddraw_window
) IWineD3DDevice_SetHWND(iface
, object
->win_handle
);
1414 hDc
= GetDC(object
->win_handle
);
1415 TRACE("Using hDc %p\n", hDc
);
1418 WARN("Failed to get a HDc for Window %p\n", object
->win_handle
);
1419 return WINED3DERR_NOTAVAILABLE
;
1422 /* Get info on the current display setup */
1423 IWineD3D_GetAdapterDisplayMode(This
->wineD3D
, This
->adapter
->num
, &Mode
);
1424 object
->orig_width
= Mode
.Width
;
1425 object
->orig_height
= Mode
.Height
;
1426 object
->orig_fmt
= Mode
.Format
;
1427 formatDesc
= getFormatDescEntry(Mode
.Format
, NULL
, NULL
);
1429 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1430 * then the corresponding dimension of the client area of the hDeviceWindow
1431 * (or the focus window, if hDeviceWindow is NULL) is taken.
1432 **********************/
1434 if (pPresentationParameters
->Windowed
&&
1435 ((pPresentationParameters
->BackBufferWidth
== 0) ||
1436 (pPresentationParameters
->BackBufferHeight
== 0) ||
1437 (pPresentationParameters
->BackBufferFormat
== WINED3DFMT_UNKNOWN
))) {
1440 GetClientRect(object
->win_handle
, &Rect
);
1442 if (pPresentationParameters
->BackBufferWidth
== 0) {
1443 pPresentationParameters
->BackBufferWidth
= Rect
.right
;
1444 TRACE("Updating width to %d\n", pPresentationParameters
->BackBufferWidth
);
1446 if (pPresentationParameters
->BackBufferHeight
== 0) {
1447 pPresentationParameters
->BackBufferHeight
= Rect
.bottom
;
1448 TRACE("Updating height to %d\n", pPresentationParameters
->BackBufferHeight
);
1450 if (pPresentationParameters
->BackBufferFormat
== WINED3DFMT_UNKNOWN
) {
1451 pPresentationParameters
->BackBufferFormat
= object
->orig_fmt
;
1452 TRACE("Updating format to %s\n", debug_d3dformat(object
->orig_fmt
));
1456 /* Put the correct figures in the presentation parameters */
1457 TRACE("Copying across presentation parameters\n");
1458 object
->presentParms
= *pPresentationParameters
;
1460 TRACE("calling rendertarget CB\n");
1461 hr
= D3DCB_CreateRenderTarget(This
->parent
,
1463 object
->presentParms
.BackBufferWidth
,
1464 object
->presentParms
.BackBufferHeight
,
1465 object
->presentParms
.BackBufferFormat
,
1466 object
->presentParms
.MultiSampleType
,
1467 object
->presentParms
.MultiSampleQuality
,
1468 TRUE
/* Lockable */,
1469 &object
->frontBuffer
,
1470 NULL
/* pShared (always null)*/);
1471 if (object
->frontBuffer
!= NULL
) {
1472 IWineD3DSurface_SetContainer(object
->frontBuffer
, (IWineD3DBase
*)object
);
1473 IWineD3DSurface_ModifyLocation(object
->frontBuffer
, SFLAG_INDRAWABLE
, TRUE
);
1475 ERR("Failed to create the front buffer\n");
1479 /*********************
1480 * Windowed / Fullscreen
1481 *******************/
1484 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1485 * so we should really check to see if there is a fullscreen swapchain already
1486 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1487 **************************************/
1489 if (!pPresentationParameters
->Windowed
) {
1490 WINED3DDISPLAYMODE mode
;
1493 /* Change the display settings */
1494 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
1495 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
1496 mode
.Format
= pPresentationParameters
->BackBufferFormat
;
1497 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
1499 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
1500 displaymode_set
= TRUE
;
1501 IWineD3DDevice_SetFullscreen(iface
, TRUE
);
1505 * Create an opengl context for the display visual
1506 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1507 * use different properties after that point in time. FIXME: How to handle when requested format
1508 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1509 * it chooses is identical to the one already being used!
1510 **********************************/
1511 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1513 object
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(object
->context
));
1514 if(!object
->context
)
1515 return E_OUTOFMEMORY
;
1516 object
->num_contexts
= 1;
1518 object
->context
[0] = CreateContext(This
, (IWineD3DSurfaceImpl
*) object
->frontBuffer
, object
->win_handle
, FALSE
/* pbuffer */, pPresentationParameters
);
1519 if (!object
->context
[0]) {
1520 ERR("Failed to create a new context\n");
1521 hr
= WINED3DERR_NOTAVAILABLE
;
1524 TRACE("Context created (HWND=%p, glContext=%p)\n",
1525 object
->win_handle
, object
->context
[0]->glCtx
);
1528 /*********************
1529 * Create the back, front and stencil buffers
1530 *******************/
1531 if(object
->presentParms
.BackBufferCount
> 0) {
1534 object
->backBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface
*) * object
->presentParms
.BackBufferCount
);
1535 if(!object
->backBuffer
) {
1536 ERR("Out of memory\n");
1541 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1542 TRACE("calling rendertarget CB\n");
1543 hr
= D3DCB_CreateRenderTarget(This
->parent
,
1545 object
->presentParms
.BackBufferWidth
,
1546 object
->presentParms
.BackBufferHeight
,
1547 object
->presentParms
.BackBufferFormat
,
1548 object
->presentParms
.MultiSampleType
,
1549 object
->presentParms
.MultiSampleQuality
,
1550 TRUE
/* Lockable */,
1551 &object
->backBuffer
[i
],
1552 NULL
/* pShared (always null)*/);
1553 if(hr
== WINED3D_OK
&& object
->backBuffer
[i
]) {
1554 IWineD3DSurface_SetContainer(object
->backBuffer
[i
], (IWineD3DBase
*)object
);
1556 ERR("Cannot create new back buffer\n");
1560 glDrawBuffer(GL_BACK
);
1561 checkGLcall("glDrawBuffer(GL_BACK)");
1565 object
->backBuffer
= NULL
;
1567 /* Single buffering - draw to front buffer */
1569 glDrawBuffer(GL_FRONT
);
1570 checkGLcall("glDrawBuffer(GL_FRONT)");
1574 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1575 if (pPresentationParameters
->EnableAutoDepthStencil
&& hr
== WINED3D_OK
) {
1576 TRACE("Creating depth stencil buffer\n");
1577 if (This
->auto_depth_stencil_buffer
== NULL
) {
1578 hr
= D3DCB_CreateDepthStencil(This
->parent
,
1580 object
->presentParms
.BackBufferWidth
,
1581 object
->presentParms
.BackBufferHeight
,
1582 object
->presentParms
.AutoDepthStencilFormat
,
1583 object
->presentParms
.MultiSampleType
,
1584 object
->presentParms
.MultiSampleQuality
,
1585 FALSE
/* FIXME: Discard */,
1586 &This
->auto_depth_stencil_buffer
,
1587 NULL
/* pShared (always null)*/ );
1588 if (This
->auto_depth_stencil_buffer
!= NULL
)
1589 IWineD3DSurface_SetContainer(This
->auto_depth_stencil_buffer
, 0);
1592 /** TODO: A check on width, height and multisample types
1593 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1594 ****************************/
1595 object
->wantsDepthStencilBuffer
= TRUE
;
1597 object
->wantsDepthStencilBuffer
= FALSE
;
1600 IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain
*) object
, &object
->orig_gamma
);
1602 TRACE("Created swapchain %p\n", object
);
1603 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object
->frontBuffer
, object
->backBuffer
? object
->backBuffer
[0] : NULL
, object
->wantsDepthStencilBuffer
);
1607 if (displaymode_set
) {
1611 SetRect(&clip_rc
, 0, 0, object
->orig_width
, object
->orig_height
);
1614 /* Change the display settings */
1615 memset(&devmode
, 0, sizeof(devmode
));
1616 devmode
.dmSize
= sizeof(devmode
);
1617 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1618 devmode
.dmBitsPerPel
= formatDesc
->bpp
* 8;
1619 devmode
.dmPelsWidth
= object
->orig_width
;
1620 devmode
.dmPelsHeight
= object
->orig_height
;
1621 ChangeDisplaySettingsExW(This
->adapter
->DeviceName
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
1624 if (object
->backBuffer
) {
1626 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1627 if(object
->backBuffer
[i
]) {
1628 IWineD3DSurface_GetParent(object
->backBuffer
[i
], &bufferParent
);
1629 IUnknown_Release(bufferParent
); /* once for the get parent */
1630 if (IUnknown_Release(bufferParent
) > 0) {
1631 FIXME("(%p) Something's still holding the back buffer\n",This
);
1635 HeapFree(GetProcessHeap(), 0, object
->backBuffer
);
1636 object
->backBuffer
= NULL
;
1638 if(object
->context
[0])
1639 DestroyContext(This
, object
->context
[0]);
1640 if(object
->frontBuffer
) {
1641 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1642 IUnknown_Release(bufferParent
); /* once for the get parent */
1643 if (IUnknown_Release(bufferParent
) > 0) {
1644 FIXME("(%p) Something's still holding the front buffer\n",This
);
1647 HeapFree(GetProcessHeap(), 0, object
);
1651 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1652 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1653 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1654 TRACE("(%p)\n", This
);
1656 return This
->NumberOfSwapChains
;
1659 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1660 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1661 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
1663 if(iSwapChain
< This
->NumberOfSwapChains
) {
1664 *pSwapChain
= This
->swapchains
[iSwapChain
];
1665 IWineD3DSwapChain_AddRef(*pSwapChain
);
1666 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1669 TRACE("Swapchain out of range\n");
1671 return WINED3DERR_INVALIDCALL
;
1676 * Vertex Declaration
1678 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppVertexDeclaration
,
1679 IUnknown
*parent
, const WINED3DVERTEXELEMENT
*elements
, UINT element_count
) {
1680 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1681 IWineD3DVertexDeclarationImpl
*object
= NULL
;
1682 HRESULT hr
= WINED3D_OK
;
1684 TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1685 This
, ((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
, elements
, element_count
, ppVertexDeclaration
);
1687 D3DCREATEOBJECTINSTANCE(object
, VertexDeclaration
)
1689 hr
= IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration
*)object
, elements
, element_count
);
1691 *ppVertexDeclaration
= NULL
;
1692 HeapFree(GetProcessHeap(), 0, object
);
1698 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl
*This
, /* For the GL info, which has the type table */
1699 DWORD fvf
, WINED3DVERTEXELEMENT
** ppVertexElements
) {
1701 unsigned int idx
, idx2
;
1702 unsigned int offset
;
1703 BOOL has_pos
= (fvf
& WINED3DFVF_POSITION_MASK
) != 0;
1704 BOOL has_blend
= (fvf
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
;
1705 BOOL has_blend_idx
= has_blend
&&
1706 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB5
) ||
1707 (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
) ||
1708 (fvf
& WINED3DFVF_LASTBETA_UBYTE4
));
1709 BOOL has_normal
= (fvf
& WINED3DFVF_NORMAL
) != 0;
1710 BOOL has_psize
= (fvf
& WINED3DFVF_PSIZE
) != 0;
1711 BOOL has_diffuse
= (fvf
& WINED3DFVF_DIFFUSE
) != 0;
1712 BOOL has_specular
= (fvf
& WINED3DFVF_SPECULAR
) !=0;
1714 DWORD num_textures
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
1715 DWORD texcoords
= (fvf
& 0x00FF0000) >> 16;
1717 WINED3DVERTEXELEMENT end_element
= WINED3DDECL_END();
1718 WINED3DVERTEXELEMENT
*elements
= NULL
;
1721 DWORD num_blends
= 1 + (((fvf
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
1722 if (has_blend_idx
) num_blends
--;
1724 /* Compute declaration size */
1725 size
= has_pos
+ (has_blend
&& num_blends
> 0) + has_blend_idx
+ has_normal
+
1726 has_psize
+ has_diffuse
+ has_specular
+ num_textures
+ 1;
1728 /* convert the declaration */
1729 elements
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WINED3DVERTEXELEMENT
));
1733 elements
[size
-1] = end_element
;
1736 if (!has_blend
&& (fvf
& WINED3DFVF_XYZRHW
)) {
1737 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
;
1738 elements
[idx
].Usage
= WINED3DDECLUSAGE_POSITIONT
;
1741 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1742 elements
[idx
].Usage
= WINED3DDECLUSAGE_POSITION
;
1744 elements
[idx
].UsageIndex
= 0;
1747 if (has_blend
&& (num_blends
> 0)) {
1748 if (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
))
1749 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1751 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
+ num_blends
- 1;
1752 elements
[idx
].Usage
= WINED3DDECLUSAGE_BLENDWEIGHT
;
1753 elements
[idx
].UsageIndex
= 0;
1756 if (has_blend_idx
) {
1757 if (fvf
& WINED3DFVF_LASTBETA_UBYTE4
||
1758 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)))
1759 elements
[idx
].Type
= WINED3DDECLTYPE_UBYTE4
;
1760 else if (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)
1761 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1763 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1764 elements
[idx
].Usage
= WINED3DDECLUSAGE_BLENDINDICES
;
1765 elements
[idx
].UsageIndex
= 0;
1769 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1770 elements
[idx
].Usage
= WINED3DDECLUSAGE_NORMAL
;
1771 elements
[idx
].UsageIndex
= 0;
1775 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1776 elements
[idx
].Usage
= WINED3DDECLUSAGE_PSIZE
;
1777 elements
[idx
].UsageIndex
= 0;
1781 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1782 elements
[idx
].Usage
= WINED3DDECLUSAGE_COLOR
;
1783 elements
[idx
].UsageIndex
= 0;
1787 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1788 elements
[idx
].Usage
= WINED3DDECLUSAGE_COLOR
;
1789 elements
[idx
].UsageIndex
= 1;
1792 for (idx2
= 0; idx2
< num_textures
; idx2
++) {
1793 unsigned int numcoords
= (texcoords
>> (idx2
*2)) & 0x03;
1794 switch (numcoords
) {
1795 case WINED3DFVF_TEXTUREFORMAT1
:
1796 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1798 case WINED3DFVF_TEXTUREFORMAT2
:
1799 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT2
;
1801 case WINED3DFVF_TEXTUREFORMAT3
:
1802 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1804 case WINED3DFVF_TEXTUREFORMAT4
:
1805 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
;
1808 elements
[idx
].Usage
= WINED3DDECLUSAGE_TEXCOORD
;
1809 elements
[idx
].UsageIndex
= idx2
;
1813 /* Now compute offsets, and initialize the rest of the fields */
1814 for (idx
= 0, offset
= 0; idx
< size
-1; idx
++) {
1815 elements
[idx
].Stream
= 0;
1816 elements
[idx
].Method
= WINED3DDECLMETHOD_DEFAULT
;
1817 elements
[idx
].Offset
= offset
;
1818 offset
+= WINED3D_ATR_SIZE(elements
[idx
].Type
) * WINED3D_ATR_TYPESIZE(elements
[idx
].Type
);
1821 *ppVertexElements
= elements
;
1825 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppVertexDeclaration
, IUnknown
*Parent
, DWORD Fvf
) {
1826 WINED3DVERTEXELEMENT
* elements
= NULL
;
1827 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1831 size
= ConvertFvfToDeclaration(This
, Fvf
, &elements
);
1832 if (size
== 0) return WINED3DERR_OUTOFVIDEOMEMORY
;
1834 hr
= IWineD3DDevice_CreateVertexDeclaration(iface
, ppVertexDeclaration
, Parent
, elements
, size
);
1835 HeapFree(GetProcessHeap(), 0, elements
);
1836 if (hr
!= S_OK
) return hr
;
1841 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexDeclaration
*vertex_declaration
, CONST DWORD
*pFunction
, IWineD3DVertexShader
**ppVertexShader
, IUnknown
*parent
) {
1842 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1843 IWineD3DVertexShaderImpl
*object
; /* NOTE: impl usage is ok, this is a create */
1844 HRESULT hr
= WINED3D_OK
;
1845 D3DCREATESHADEROBJECTINSTANCE(object
, VertexShader
)
1846 object
->baseShader
.shader_ins
= IWineD3DVertexShaderImpl_shader_ins
;
1848 TRACE("(%p) : Created Vertex shader %p\n", This
, *ppVertexShader
);
1850 if (vertex_declaration
) {
1851 IWineD3DVertexShader_FakeSemantics(*ppVertexShader
, vertex_declaration
);
1854 hr
= IWineD3DVertexShader_SetFunction(*ppVertexShader
, pFunction
);
1856 if (WINED3D_OK
!= hr
) {
1857 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface
);
1858 IWineD3DVertexShader_Release(*ppVertexShader
);
1859 return WINED3DERR_INVALIDCALL
;
1861 list_add_head(&This
->shaders
, &object
->baseShader
.shader_list_entry
);
1866 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
, CONST DWORD
*pFunction
, IWineD3DPixelShader
**ppPixelShader
, IUnknown
*parent
) {
1867 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1868 IWineD3DPixelShaderImpl
*object
; /* NOTE: impl allowed, this is a create */
1869 HRESULT hr
= WINED3D_OK
;
1871 D3DCREATESHADEROBJECTINSTANCE(object
, PixelShader
)
1872 object
->baseShader
.shader_ins
= IWineD3DPixelShaderImpl_shader_ins
;
1873 hr
= IWineD3DPixelShader_SetFunction(*ppPixelShader
, pFunction
);
1874 if (WINED3D_OK
== hr
) {
1875 TRACE("(%p) : Created Pixel shader %p\n", This
, *ppPixelShader
);
1876 list_add_head(&This
->shaders
, &object
->baseShader
.shader_list_entry
);
1878 WARN("(%p) : Failed to create pixel shader\n", This
);
1884 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD Flags
, PALETTEENTRY
*PalEnt
, IWineD3DPalette
**Palette
, IUnknown
*Parent
) {
1885 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1886 IWineD3DPaletteImpl
*object
;
1888 TRACE("(%p)->(%x, %p, %p, %p)\n", This
, Flags
, PalEnt
, Palette
, Parent
);
1890 /* Create the new object */
1891 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DPaletteImpl
));
1893 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1894 return E_OUTOFMEMORY
;
1897 object
->lpVtbl
= &IWineD3DPalette_Vtbl
;
1899 object
->Flags
= Flags
;
1900 object
->parent
= Parent
;
1901 object
->wineD3DDevice
= This
;
1902 object
->palNumEntries
= IWineD3DPaletteImpl_Size(Flags
);
1904 object
->hpal
= CreatePalette((const LOGPALETTE
*)&(object
->palVersion
));
1907 HeapFree( GetProcessHeap(), 0, object
);
1908 return E_OUTOFMEMORY
;
1911 hr
= IWineD3DPalette_SetEntries((IWineD3DPalette
*) object
, 0, 0, IWineD3DPaletteImpl_Size(Flags
), PalEnt
);
1913 IWineD3DPalette_Release((IWineD3DPalette
*) object
);
1917 *Palette
= (IWineD3DPalette
*) object
;
1922 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl
*This
, const char *filename
) {
1926 HDC dcb
= NULL
, dcs
= NULL
;
1927 WINEDDCOLORKEY colorkey
;
1929 hbm
= (HBITMAP
) LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
);
1932 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
1933 dcb
= CreateCompatibleDC(NULL
);
1935 SelectObject(dcb
, hbm
);
1939 /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
1940 * couldn't be loaded
1942 memset(&bm
, 0, sizeof(bm
));
1947 hr
= IWineD3DDevice_CreateSurface((IWineD3DDevice
*) This
, bm
.bmWidth
, bm
.bmHeight
, WINED3DFMT_R5G6B5
,
1948 TRUE
, FALSE
, 0, &This
->logo_surface
, WINED3DRTYPE_SURFACE
, 0,
1949 WINED3DPOOL_DEFAULT
, WINED3DMULTISAMPLE_NONE
, 0, NULL
, SURFACE_OPENGL
, NULL
);
1951 ERR("Wine logo requested, but failed to create surface\n");
1956 hr
= IWineD3DSurface_GetDC(This
->logo_surface
, &dcs
);
1957 if(FAILED(hr
)) goto out
;
1958 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
1959 IWineD3DSurface_ReleaseDC(This
->logo_surface
, dcs
);
1961 colorkey
.dwColorSpaceLowValue
= 0;
1962 colorkey
.dwColorSpaceHighValue
= 0;
1963 IWineD3DSurface_SetColorKey(This
->logo_surface
, WINEDDCKEY_SRCBLT
, &colorkey
);
1965 /* Fill the surface with a white color to show that wined3d is there */
1966 IWineD3DDevice_ColorFill((IWineD3DDevice
*) This
, This
->logo_surface
, NULL
, 0xffffffff);
1979 static void create_dummy_textures(IWineD3DDeviceImpl
*This
) {
1981 /* Under DirectX you can have texture stage operations even if no texture is
1982 bound, whereas opengl will only do texture operations when a valid texture is
1983 bound. We emulate this by creating dummy textures and binding them to each
1984 texture stage, but disable all stages by default. Hence if a stage is enabled
1985 then the default texture will kick in until replaced by a SetTexture call */
1988 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
1989 /* The dummy texture does not have client storage backing */
1990 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
1991 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
1993 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
1994 GLubyte white
= 255;
1996 /* Make appropriate texture active */
1997 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1998 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
1999 checkGLcall("glActiveTextureARB");
2001 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2004 /* Generate an opengl texture name */
2005 glGenTextures(1, &This
->dummyTextureName
[i
]);
2006 checkGLcall("glGenTextures");
2007 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
2009 /* Generate a dummy 2d texture (not using 1d because they cause many
2010 * DRI drivers fall back to sw) */
2011 This
->stateBlock
->textureDimensions
[i
] = GL_TEXTURE_2D
;
2012 glBindTexture(GL_TEXTURE_2D
, This
->dummyTextureName
[i
]);
2013 checkGLcall("glBindTexture");
2015 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
, 1, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
2016 checkGLcall("glTexImage2D");
2018 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
2019 /* Reenable because if supported it is enabled by default */
2020 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
2021 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
2027 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain
) {
2028 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2029 IWineD3DSwapChainImpl
*swapchain
= NULL
;
2034 TRACE("(%p)->(%p,%p)\n", This
, pPresentationParameters
, D3DCB_CreateAdditionalSwapChain
);
2035 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2036 if(!This
->adapter
->opengl
) return WINED3DERR_INVALIDCALL
;
2038 /* TODO: Test if OpenGL is compiled in and loaded */
2040 TRACE("(%p) : Creating stateblock\n", This
);
2041 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2042 hr
= IWineD3DDevice_CreateStateBlock(iface
,
2044 (IWineD3DStateBlock
**)&This
->stateBlock
,
2046 if (WINED3D_OK
!= hr
) { /* Note: No parent needed for initial internal stateblock */
2047 WARN("Failed to create stateblock\n");
2050 TRACE("(%p) : Created stateblock (%p)\n", This
, This
->stateBlock
);
2051 This
->updateStateBlock
= This
->stateBlock
;
2052 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
2054 hr
= allocate_shader_constants(This
->updateStateBlock
);
2055 if (WINED3D_OK
!= hr
) {
2059 This
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*) * GL_LIMITS(buffers
));
2060 This
->fbo_color_attachments
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*) * GL_LIMITS(buffers
));
2061 This
->draw_buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLenum
) * GL_LIMITS(buffers
));
2063 This
->NumberOfPalettes
= 1;
2064 This
->palettes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PALETTEENTRY
*));
2065 if(!This
->palettes
|| !This
->render_targets
|| !This
->fbo_color_attachments
|| !This
->draw_buffers
) {
2066 ERR("Out of memory!\n");
2069 This
->palettes
[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
2070 if(!This
->palettes
[0]) {
2071 ERR("Out of memory!\n");
2074 for (i
= 0; i
< 256; ++i
) {
2075 This
->palettes
[0][i
].peRed
= 0xFF;
2076 This
->palettes
[0][i
].peGreen
= 0xFF;
2077 This
->palettes
[0][i
].peBlue
= 0xFF;
2078 This
->palettes
[0][i
].peFlags
= 0xFF;
2080 This
->currentPalette
= 0;
2082 /* Initialize the texture unit mapping to a 1:1 mapping */
2083 for (state
= 0; state
< MAX_COMBINED_SAMPLERS
; ++state
) {
2084 if (state
< GL_LIMITS(fragment_samplers
)) {
2085 This
->texUnitMap
[state
] = state
;
2086 This
->rev_tex_unit_map
[state
] = state
;
2088 This
->texUnitMap
[state
] = -1;
2089 This
->rev_tex_unit_map
[state
] = -1;
2093 /* Setup the implicit swapchain */
2094 TRACE("Creating implicit swapchain\n");
2095 hr
=D3DCB_CreateAdditionalSwapChain(This
->parent
, pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
2096 if (FAILED(hr
) || !swapchain
) {
2097 WARN("Failed to create implicit swapchain\n");
2101 This
->NumberOfSwapChains
= 1;
2102 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
2103 if(!This
->swapchains
) {
2104 ERR("Out of memory!\n");
2107 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
2109 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0]) {
2110 TRACE("Setting rendertarget to %p\n", swapchain
->backBuffer
);
2111 This
->render_targets
[0] = swapchain
->backBuffer
[0];
2112 This
->lastActiveRenderTarget
= swapchain
->backBuffer
[0];
2115 TRACE("Setting rendertarget to %p\n", swapchain
->frontBuffer
);
2116 This
->render_targets
[0] = swapchain
->frontBuffer
;
2117 This
->lastActiveRenderTarget
= swapchain
->frontBuffer
;
2119 IWineD3DSurface_AddRef(This
->render_targets
[0]);
2120 This
->activeContext
= swapchain
->context
[0];
2121 This
->lastThread
= GetCurrentThreadId();
2123 /* Depth Stencil support */
2124 This
->stencilBufferTarget
= This
->auto_depth_stencil_buffer
;
2125 if (NULL
!= This
->stencilBufferTarget
) {
2126 IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
2129 hr
= This
->shader_backend
->shader_alloc_private(iface
);
2131 TRACE("Shader private data couldn't be allocated\n");
2134 hr
= This
->frag_pipe
->alloc_private(iface
);
2136 TRACE("Fragment pipeline private data couldn't be allocated\n");
2140 /* Set up some starting GL setup */
2142 /* Setup all the devices defaults */
2143 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)This
->stateBlock
);
2144 create_dummy_textures(This
);
2149 IWineD3DImpl_CheckGraphicsMemory();
2152 { /* Set a default viewport */
2156 vp
.Width
= pPresentationParameters
->BackBufferWidth
;
2157 vp
.Height
= pPresentationParameters
->BackBufferHeight
;
2160 IWineD3DDevice_SetViewport((IWineD3DDevice
*)This
, &vp
);
2163 /* Initialize the current view state */
2164 This
->view_ident
= 1;
2165 This
->contexts
[0]->last_was_rhw
= 0;
2166 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
2167 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
2169 switch(wined3d_settings
.offscreen_rendering_mode
) {
2172 This
->offscreenBuffer
= GL_BACK
;
2175 case ORM_BACKBUFFER
:
2177 if(This
->activeContext
->aux_buffers
> 0) {
2178 TRACE("Using auxilliary buffer for offscreen rendering\n");
2179 This
->offscreenBuffer
= GL_AUX0
;
2181 TRACE("Using back buffer for offscreen rendering\n");
2182 This
->offscreenBuffer
= GL_BACK
;
2187 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
2190 /* Clear the screen */
2191 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
,
2192 WINED3DCLEAR_TARGET
| pPresentationParameters
->EnableAutoDepthStencil
? WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
: 0,
2195 This
->d3d_initialized
= TRUE
;
2197 if(wined3d_settings
.logo
) {
2198 IWineD3DDeviceImpl_LoadLogo(This
, wined3d_settings
.logo
);
2200 This
->highest_dirty_ps_const
= 0;
2201 This
->highest_dirty_vs_const
= 0;
2205 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2206 HeapFree(GetProcessHeap(), 0, This
->fbo_color_attachments
);
2207 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
2208 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2209 This
->NumberOfSwapChains
= 0;
2210 if(This
->palettes
) {
2211 HeapFree(GetProcessHeap(), 0, This
->palettes
[0]);
2212 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2214 This
->NumberOfPalettes
= 0;
2216 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
2218 This
->draw_buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLenum
) * GL_LIMITS(buffers
));
2219 if(This
->stateBlock
) {
2220 IWineD3DStateBlock_Release((IWineD3DStateBlock
*) This
->stateBlock
);
2221 This
->stateBlock
= NULL
;
2223 This
->shader_backend
->shader_free_private(iface
);
2224 This
->frag_pipe
->free_private(iface
);
2228 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface
, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
) {
2229 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2232 TRACE("(%p)\n", This
);
2234 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2236 /* I don't think that the interface guarantees that the device is destroyed from the same thread
2237 * it was created. Thus make sure a context is active for the glDelete* calls
2239 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
2241 if(This
->logo_surface
) IWineD3DSurface_Release(This
->logo_surface
);
2243 TRACE("Deleting high order patches\n");
2244 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2245 struct list
*e1
, *e2
;
2246 struct WineD3DRectPatch
*patch
;
2247 LIST_FOR_EACH_SAFE(e1
, e2
, &This
->patches
[i
]) {
2248 patch
= LIST_ENTRY(e1
, struct WineD3DRectPatch
, entry
);
2249 IWineD3DDevice_DeletePatch(iface
, patch
->Handle
);
2253 /* Delete the palette conversion shader if it is around */
2254 if(This
->paletteConversionShader
) {
2256 GL_EXTCALL(glDeleteProgramsARB(1, &This
->paletteConversionShader
));
2258 This
->paletteConversionShader
= 0;
2261 /* Delete the pbuffer context if there is any */
2262 if(This
->pbufferContext
) DestroyContext(This
, This
->pbufferContext
);
2264 /* Delete the mouse cursor texture */
2265 if(This
->cursorTexture
) {
2267 glDeleteTextures(1, &This
->cursorTexture
);
2269 This
->cursorTexture
= 0;
2272 for (sampler
= 0; sampler
< MAX_FRAGMENT_SAMPLERS
; ++sampler
) {
2273 IWineD3DDevice_SetTexture(iface
, sampler
, NULL
);
2275 for (sampler
= 0; sampler
< MAX_VERTEX_SAMPLERS
; ++sampler
) {
2276 IWineD3DDevice_SetTexture(iface
, WINED3DVERTEXTEXTURESAMPLER0
+ sampler
, NULL
);
2279 /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2280 * private data, it might contain opengl pointers
2282 if(This
->depth_blt_texture
) {
2283 glDeleteTextures(1, &This
->depth_blt_texture
);
2284 This
->depth_blt_texture
= 0;
2286 if (This
->depth_blt_rb
) {
2287 GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This
->depth_blt_rb
));
2288 This
->depth_blt_rb
= 0;
2289 This
->depth_blt_rb_w
= 0;
2290 This
->depth_blt_rb_h
= 0;
2293 /* Release the update stateblock */
2294 if(IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
) > 0){
2295 if(This
->updateStateBlock
!= This
->stateBlock
)
2296 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
2298 This
->updateStateBlock
= NULL
;
2300 { /* because were not doing proper internal refcounts releasing the primary state block
2301 causes recursion with the extra checks in ResourceReleased, to avoid this we have
2302 to set this->stateBlock = NULL; first */
2303 IWineD3DStateBlock
*stateBlock
= (IWineD3DStateBlock
*)This
->stateBlock
;
2304 This
->stateBlock
= NULL
;
2306 /* Release the stateblock */
2307 if(IWineD3DStateBlock_Release(stateBlock
) > 0){
2308 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
2312 /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2313 This
->shader_backend
->shader_free_private(iface
);
2314 This
->frag_pipe
->free_private(iface
);
2316 /* Release the buffers (with sanity checks)*/
2317 TRACE("Releasing the depth stencil buffer at %p\n", This
->stencilBufferTarget
);
2318 if(This
->stencilBufferTarget
!= NULL
&& (IWineD3DSurface_Release(This
->stencilBufferTarget
) >0)){
2319 if(This
->auto_depth_stencil_buffer
!= This
->stencilBufferTarget
)
2320 FIXME("(%p) Something's still holding the stencilBufferTarget\n",This
);
2322 This
->stencilBufferTarget
= NULL
;
2324 TRACE("Releasing the render target at %p\n", This
->render_targets
[0]);
2325 if(IWineD3DSurface_Release(This
->render_targets
[0]) >0){
2326 /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2328 TRACE("Setting rendertarget to NULL\n");
2329 This
->render_targets
[0] = NULL
;
2331 if (This
->auto_depth_stencil_buffer
) {
2332 if(D3DCB_DestroyDepthStencilSurface(This
->auto_depth_stencil_buffer
) > 0) {
2333 FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This
);
2335 This
->auto_depth_stencil_buffer
= NULL
;
2338 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
2339 TRACE("Releasing the implicit swapchain %d\n", i
);
2340 if (D3DCB_DestroySwapChain(This
->swapchains
[i
]) > 0) {
2341 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2345 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2346 This
->swapchains
= NULL
;
2347 This
->NumberOfSwapChains
= 0;
2349 for (i
= 0; i
< This
->NumberOfPalettes
; i
++) HeapFree(GetProcessHeap(), 0, This
->palettes
[i
]);
2350 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2351 This
->palettes
= NULL
;
2352 This
->NumberOfPalettes
= 0;
2354 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2355 HeapFree(GetProcessHeap(), 0, This
->fbo_color_attachments
);
2356 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
2357 This
->render_targets
= NULL
;
2358 This
->fbo_color_attachments
= NULL
;
2359 This
->draw_buffers
= NULL
;
2361 This
->d3d_initialized
= FALSE
;
2365 static void WINAPI
IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice
*iface
, BOOL fullscreen
) {
2366 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2367 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This
, fullscreen
? "true" : "false");
2369 /* Setup the window for fullscreen mode */
2370 if(fullscreen
&& !This
->ddraw_fullscreen
) {
2371 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, This
->ddraw_window
);
2372 } else if(!fullscreen
&& This
->ddraw_fullscreen
) {
2373 IWineD3DDeviceImpl_RestoreWindow(iface
, This
->ddraw_window
);
2376 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
2377 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
2378 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
2381 This
->ddraw_fullscreen
= fullscreen
;
2384 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2385 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2386 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2388 * There is no way to deactivate thread safety once it is enabled.
2390 static void WINAPI
IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice
*iface
) {
2391 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2393 /*For now just store the flag(needed in case of ddraw) */
2394 This
->createParms
.BehaviorFlags
|= WINED3DCREATE_MULTITHREADED
;
2399 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
2401 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2403 const StaticPixelFormatDesc
*formatDesc
= getFormatDescEntry(pMode
->Format
, NULL
, NULL
);
2406 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
2408 /* Resize the screen even without a window:
2409 * The app could have unset it with SetCooperativeLevel, but not called
2410 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2411 * but we don't have any hwnd
2414 memset(&devmode
, 0, sizeof(devmode
));
2415 devmode
.dmSize
= sizeof(devmode
);
2416 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
2417 devmode
.dmBitsPerPel
= formatDesc
->bpp
* 8;
2418 devmode
.dmPelsWidth
= pMode
->Width
;
2419 devmode
.dmPelsHeight
= pMode
->Height
;
2421 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
2422 if (pMode
->RefreshRate
!= 0) {
2423 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
2426 /* Only change the mode if necessary */
2427 if( (This
->ddraw_width
== pMode
->Width
) &&
2428 (This
->ddraw_height
== pMode
->Height
) &&
2429 (This
->ddraw_format
== pMode
->Format
) &&
2430 (pMode
->RefreshRate
== 0) ) {
2434 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
2435 if (ret
!= DISP_CHANGE_SUCCESSFUL
) {
2436 if(devmode
.dmDisplayFrequency
!= 0) {
2437 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2438 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
2439 devmode
.dmDisplayFrequency
= 0;
2440 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
2442 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
2443 return WINED3DERR_NOTAVAILABLE
;
2447 /* Store the new values */
2448 This
->ddraw_width
= pMode
->Width
;
2449 This
->ddraw_height
= pMode
->Height
;
2450 This
->ddraw_format
= pMode
->Format
;
2452 /* Only do this with a window of course, and only if we're fullscreened */
2453 if(This
->ddraw_window
&& This
->ddraw_fullscreen
)
2454 MoveWindow(This
->ddraw_window
, 0, 0, pMode
->Width
, pMode
->Height
, TRUE
);
2456 /* And finally clip mouse to our screen */
2457 SetRect(&clip_rc
, 0, 0, pMode
->Width
, pMode
->Height
);
2458 ClipCursor(&clip_rc
);
2463 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, IWineD3D
**ppD3D
) {
2464 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2465 *ppD3D
= This
->wineD3D
;
2466 TRACE("(%p) : wineD3D returning %p\n", This
, *ppD3D
);
2467 IWineD3D_AddRef(*ppD3D
);
2471 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
2472 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2474 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
2475 (This
->adapter
->TextureRam
/(1024*1024)),
2476 ((This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
) / (1024*1024)));
2477 /* return simulated texture memory left */
2478 return (This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
);
2486 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFVF(IWineD3DDevice
*iface
, DWORD fvf
) {
2487 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2489 /* Update the current state block */
2490 This
->updateStateBlock
->changed
.fvf
= TRUE
;
2492 if(This
->updateStateBlock
->fvf
== fvf
) {
2493 TRACE("Application is setting the old fvf over, nothing to do\n");
2497 This
->updateStateBlock
->fvf
= fvf
;
2498 TRACE("(%p) : FVF Shader FVF set to %x\n", This
, fvf
);
2499 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
2504 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFVF(IWineD3DDevice
*iface
, DWORD
*pfvf
) {
2505 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2506 TRACE("(%p) : GetFVF returning %x\n", This
, This
->stateBlock
->fvf
);
2507 *pfvf
= This
->stateBlock
->fvf
;
2512 * Get / Set Stream Source
2514 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
* pStreamData
, UINT OffsetInBytes
, UINT Stride
) {
2515 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2516 IWineD3DVertexBuffer
*oldSrc
;
2518 if (StreamNumber
>= MAX_STREAMS
) {
2519 WARN("Stream out of range %d\n", StreamNumber
);
2520 return WINED3DERR_INVALIDCALL
;
2521 } else if(OffsetInBytes
& 0x3) {
2522 WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes
);
2523 return WINED3DERR_INVALIDCALL
;
2526 oldSrc
= This
->updateStateBlock
->streamSource
[StreamNumber
];
2527 TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This
, StreamNumber
, oldSrc
, pStreamData
, OffsetInBytes
, Stride
);
2529 This
->updateStateBlock
->changed
.streamSource
[StreamNumber
] = TRUE
;
2531 if(oldSrc
== pStreamData
&&
2532 This
->updateStateBlock
->streamStride
[StreamNumber
] == Stride
&&
2533 This
->updateStateBlock
->streamOffset
[StreamNumber
] == OffsetInBytes
) {
2534 TRACE("Application is setting the old values over, nothing to do\n");
2538 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
2540 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
2541 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
2544 /* Handle recording of state blocks */
2545 if (This
->isRecordingState
) {
2546 TRACE("Recording... not performing anything\n");
2547 if(pStreamData
) IWineD3DVertexBuffer_AddRef(pStreamData
);
2548 if(oldSrc
) IWineD3DVertexBuffer_Release(oldSrc
);
2552 /* Need to do a getParent and pass the references up */
2553 /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed.
2554 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2555 so for now, just count internally */
2556 if (pStreamData
!= NULL
) {
2557 IWineD3DVertexBufferImpl
*vbImpl
= (IWineD3DVertexBufferImpl
*) pStreamData
;
2558 InterlockedIncrement(&vbImpl
->bindCount
);
2559 IWineD3DVertexBuffer_AddRef(pStreamData
);
2561 if (oldSrc
!= NULL
) {
2562 InterlockedDecrement(&((IWineD3DVertexBufferImpl
*) oldSrc
)->bindCount
);
2563 IWineD3DVertexBuffer_Release(oldSrc
);
2566 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2571 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
** pStream
, UINT
*pOffset
, UINT
* pStride
) {
2572 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2574 TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This
, StreamNumber
,
2575 This
->stateBlock
->streamSource
[StreamNumber
],
2576 This
->stateBlock
->streamOffset
[StreamNumber
],
2577 This
->stateBlock
->streamStride
[StreamNumber
]);
2579 if (StreamNumber
>= MAX_STREAMS
) {
2580 WARN("Stream out of range %d\n", StreamNumber
);
2581 return WINED3DERR_INVALIDCALL
;
2583 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
2584 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
2586 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
2589 if (*pStream
!= NULL
) {
2590 IWineD3DVertexBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
2595 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2596 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2597 UINT oldFlags
= This
->updateStateBlock
->streamFlags
[StreamNumber
];
2598 UINT oldFreq
= This
->updateStateBlock
->streamFreq
[StreamNumber
];
2600 /* Verify input at least in d3d9 this is invalid*/
2601 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && (Divider
& WINED3DSTREAMSOURCE_INDEXEDDATA
)){
2602 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2603 return WINED3DERR_INVALIDCALL
;
2605 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && StreamNumber
== 0 ){
2606 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2607 return WINED3DERR_INVALIDCALL
;
2610 WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2611 return WINED3DERR_INVALIDCALL
;
2614 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This
, StreamNumber
, Divider
);
2615 This
->updateStateBlock
->streamFlags
[StreamNumber
] = Divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
2617 This
->updateStateBlock
->changed
.streamFreq
[StreamNumber
] = TRUE
;
2618 This
->updateStateBlock
->streamFreq
[StreamNumber
] = Divider
& 0x7FFFFF;
2620 if(This
->updateStateBlock
->streamFreq
[StreamNumber
] != oldFreq
||
2621 This
->updateStateBlock
->streamFlags
[StreamNumber
] != oldFlags
) {
2622 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2628 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2629 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2631 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This
, StreamNumber
, Divider
);
2632 *Divider
= This
->updateStateBlock
->streamFreq
[StreamNumber
] | This
->updateStateBlock
->streamFlags
[StreamNumber
];
2634 TRACE("(%p) : returning %d\n", This
, *Divider
);
2640 * Get / Set & Multiply Transform
2642 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE d3dts
, CONST WINED3DMATRIX
* lpmatrix
) {
2643 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2645 /* Most of this routine, comments included copied from ddraw tree initially: */
2646 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
2648 /* Handle recording of state blocks */
2649 if (This
->isRecordingState
) {
2650 TRACE("Recording... not performing anything\n");
2651 This
->updateStateBlock
->changed
.transform
[d3dts
] = TRUE
;
2652 This
->updateStateBlock
->transforms
[d3dts
] = *lpmatrix
;
2657 * If the new matrix is the same as the current one,
2658 * we cut off any further processing. this seems to be a reasonable
2659 * optimization because as was noticed, some apps (warcraft3 for example)
2660 * tend towards setting the same matrix repeatedly for some reason.
2662 * From here on we assume that the new matrix is different, wherever it matters.
2664 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(WINED3DMATRIX
))) {
2665 TRACE("The app is setting the same matrix over again\n");
2668 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
2672 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2673 where ViewMat = Camera space, WorldMat = world space.
2675 In OpenGL, camera and world space is combined into GL_MODELVIEW
2676 matrix. The Projection matrix stay projection matrix.
2679 /* Capture the times we can just ignore the change for now */
2680 if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrix */
2681 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2682 /* Handled by the state manager */
2685 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TRANSFORM(d3dts
));
2689 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, WINED3DMATRIX
* pMatrix
) {
2690 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2691 TRACE("(%p) : for Transform State %s\n", This
, debug_d3dtstype(State
));
2692 *pMatrix
= This
->stateBlock
->transforms
[State
];
2696 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, CONST WINED3DMATRIX
* pMatrix
) {
2697 WINED3DMATRIX
*mat
= NULL
;
2700 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2701 * below means it will be recorded in a state block change, but it
2702 * works regardless where it is recorded.
2703 * If this is found to be wrong, change to StateBlock.
2705 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2706 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2708 if (State
< HIGHEST_TRANSFORMSTATE
)
2710 mat
= &This
->updateStateBlock
->transforms
[State
];
2712 FIXME("Unhandled transform state!!\n");
2715 multiply_matrix(&temp
, mat
, pMatrix
);
2717 /* Apply change via set transform - will reapply to eg. lights this way */
2718 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2724 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2725 you can reference any indexes you want as long as that number max are enabled at any
2726 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2727 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2728 but when recording, just build a chain pretty much of commands to be replayed. */
2730 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2732 PLIGHTINFOEL
*object
= NULL
;
2733 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2736 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2737 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This
, Index
, pLight
, Hi
);
2739 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2743 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2744 return WINED3DERR_INVALIDCALL
;
2747 switch(pLight
->Type
) {
2748 case WINED3DLIGHT_POINT
:
2749 case WINED3DLIGHT_SPOT
:
2750 case WINED3DLIGHT_PARALLELPOINT
:
2751 case WINED3DLIGHT_GLSPOT
:
2752 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2755 if(pLight
->Attenuation0
< 0.0 || pLight
->Attenuation1
< 0.0 || pLight
->Attenuation2
< 0.0) {
2756 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2757 return WINED3DERR_INVALIDCALL
;
2761 case WINED3DLIGHT_DIRECTIONAL
:
2762 /* Ignores attenuation */
2766 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2767 return WINED3DERR_INVALIDCALL
;
2770 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
2771 object
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2772 if(object
->OriginalIndex
== Index
) break;
2777 TRACE("Adding new light\n");
2778 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2780 ERR("Out of memory error when allocating a light\n");
2781 return E_OUTOFMEMORY
;
2783 list_add_head(&This
->updateStateBlock
->lightMap
[Hi
], &object
->entry
);
2784 object
->glIndex
= -1;
2785 object
->OriginalIndex
= Index
;
2786 object
->changed
= TRUE
;
2789 /* Initialize the object */
2790 TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index
, pLight
->Type
,
2791 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2792 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2793 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2794 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2795 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2796 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2798 /* Save away the information */
2799 object
->OriginalParms
= *pLight
;
2801 switch (pLight
->Type
) {
2802 case WINED3DLIGHT_POINT
:
2804 object
->lightPosn
[0] = pLight
->Position
.x
;
2805 object
->lightPosn
[1] = pLight
->Position
.y
;
2806 object
->lightPosn
[2] = pLight
->Position
.z
;
2807 object
->lightPosn
[3] = 1.0f
;
2808 object
->cutoff
= 180.0f
;
2812 case WINED3DLIGHT_DIRECTIONAL
:
2814 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2815 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2816 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2817 object
->lightPosn
[3] = 0.0;
2818 object
->exponent
= 0.0f
;
2819 object
->cutoff
= 180.0f
;
2822 case WINED3DLIGHT_SPOT
:
2824 object
->lightPosn
[0] = pLight
->Position
.x
;
2825 object
->lightPosn
[1] = pLight
->Position
.y
;
2826 object
->lightPosn
[2] = pLight
->Position
.z
;
2827 object
->lightPosn
[3] = 1.0;
2830 object
->lightDirn
[0] = pLight
->Direction
.x
;
2831 object
->lightDirn
[1] = pLight
->Direction
.y
;
2832 object
->lightDirn
[2] = pLight
->Direction
.z
;
2833 object
->lightDirn
[3] = 1.0;
2836 * opengl-ish and d3d-ish spot lights use too different models for the
2837 * light "intensity" as a function of the angle towards the main light direction,
2838 * so we only can approximate very roughly.
2839 * however spot lights are rather rarely used in games (if ever used at all).
2840 * furthermore if still used, probably nobody pays attention to such details.
2842 if (pLight
->Falloff
== 0) {
2843 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2844 * falloff resp. exponent parameter as an exponent, so the spot light lighting
2845 * will always be 1.0 for both of them, and we don't have to care for the
2846 * rest of the rather complex calculation
2848 object
->exponent
= 0;
2850 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2851 if (rho
< 0.0001) rho
= 0.0001f
;
2852 object
->exponent
= -0.3/log(cos(rho
/2));
2854 if (object
->exponent
> 128.0) {
2855 object
->exponent
= 128.0;
2857 object
->cutoff
= pLight
->Phi
*90/M_PI
;
2863 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2866 /* Update the live definitions if the light is currently assigned a glIndex */
2867 if (object
->glIndex
!= -1 && !This
->isRecordingState
) {
2868 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(object
->glIndex
));
2873 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
* pLight
) {
2874 PLIGHTINFOEL
*lightInfo
= NULL
;
2875 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2876 DWORD Hi
= LIGHTMAP_HASHFUNC(Index
);
2878 TRACE("(%p) : Idx(%d), pLight(%p)\n", This
, Index
, pLight
);
2880 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
]) {
2881 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2882 if(lightInfo
->OriginalIndex
== Index
) break;
2886 if (lightInfo
== NULL
) {
2887 TRACE("Light information requested but light not defined\n");
2888 return WINED3DERR_INVALIDCALL
;
2891 *pLight
= lightInfo
->OriginalParms
;
2896 * Get / Set Light Enable
2897 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2899 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
) {
2900 PLIGHTINFOEL
*lightInfo
= NULL
;
2901 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2902 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2904 TRACE("(%p) : Idx(%d), enable? %d\n", This
, Index
, Enable
);
2906 /* Tests show true = 128...not clear why */
2907 Enable
= Enable
? 128: 0;
2909 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
2910 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2911 if(lightInfo
->OriginalIndex
== Index
) break;
2914 TRACE("Found light: %p\n", lightInfo
);
2916 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2917 if (lightInfo
== NULL
) {
2919 TRACE("Light enabled requested but light not defined, so defining one!\n");
2920 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
2922 /* Search for it again! Should be fairly quick as near head of list */
2923 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
2924 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2925 if(lightInfo
->OriginalIndex
== Index
) break;
2928 if (lightInfo
== NULL
) {
2929 FIXME("Adding default lights has failed dismally\n");
2930 return WINED3DERR_INVALIDCALL
;
2934 lightInfo
->enabledChanged
= TRUE
;
2936 if(lightInfo
->glIndex
!= -1) {
2937 if(!This
->isRecordingState
) {
2938 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(lightInfo
->glIndex
));
2941 This
->stateBlock
->activeLights
[lightInfo
->glIndex
] = NULL
;
2942 lightInfo
->glIndex
= -1;
2944 TRACE("Light already disabled, nothing to do\n");
2946 lightInfo
->enabled
= FALSE
;
2948 lightInfo
->enabled
= TRUE
;
2949 if (lightInfo
->glIndex
!= -1) {
2951 TRACE("Nothing to do as light was enabled\n");
2954 /* Find a free gl light */
2955 for(i
= 0; i
< This
->maxConcurrentLights
; i
++) {
2956 if(This
->stateBlock
->activeLights
[i
] == NULL
) {
2957 This
->stateBlock
->activeLights
[i
] = lightInfo
;
2958 lightInfo
->glIndex
= i
;
2962 if(lightInfo
->glIndex
== -1) {
2963 /* Our tests show that Windows returns D3D_OK in this situation, even with
2964 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2965 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2966 * as well for those lights.
2968 * TODO: Test how this affects rendering
2970 FIXME("Too many concurrently active lights\n");
2974 /* i == lightInfo->glIndex */
2975 if(!This
->isRecordingState
) {
2976 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(i
));
2984 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
) {
2986 PLIGHTINFOEL
*lightInfo
= NULL
;
2987 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2989 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2990 TRACE("(%p) : for idx(%d)\n", This
, Index
);
2992 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
]) {
2993 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2994 if(lightInfo
->OriginalIndex
== Index
) break;
2998 if (lightInfo
== NULL
) {
2999 TRACE("Light enabled state requested but light not defined\n");
3000 return WINED3DERR_INVALIDCALL
;
3002 /* true is 128 according to SetLightEnable */
3003 *pEnable
= lightInfo
->enabled
? 128 : 0;
3008 * Get / Set Clip Planes
3010 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
3011 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3012 TRACE("(%p) : for idx %d, %p\n", This
, Index
, pPlane
);
3014 /* Validate Index */
3015 if (Index
>= GL_LIMITS(clipplanes
)) {
3016 TRACE("Application has requested clipplane this device doesn't support\n");
3017 return WINED3DERR_INVALIDCALL
;
3020 This
->updateStateBlock
->changed
.clipplane
[Index
] = TRUE
;
3022 if(This
->updateStateBlock
->clipplane
[Index
][0] == pPlane
[0] &&
3023 This
->updateStateBlock
->clipplane
[Index
][1] == pPlane
[1] &&
3024 This
->updateStateBlock
->clipplane
[Index
][2] == pPlane
[2] &&
3025 This
->updateStateBlock
->clipplane
[Index
][3] == pPlane
[3]) {
3026 TRACE("Application is setting old values over, nothing to do\n");
3030 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
3031 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
3032 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
3033 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
3035 /* Handle recording of state blocks */
3036 if (This
->isRecordingState
) {
3037 TRACE("Recording... not performing anything\n");
3041 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_CLIPPLANE(Index
));
3046 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
3047 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3048 TRACE("(%p) : for idx %d\n", This
, Index
);
3050 /* Validate Index */
3051 if (Index
>= GL_LIMITS(clipplanes
)) {
3052 TRACE("Application has requested clipplane this device doesn't support\n");
3053 return WINED3DERR_INVALIDCALL
;
3056 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
3057 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
3058 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
3059 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
3064 * Get / Set Clip Plane Status
3065 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3067 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
3068 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3069 FIXME("(%p) : stub\n", This
);
3070 if (NULL
== pClipStatus
) {
3071 return WINED3DERR_INVALIDCALL
;
3073 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
3074 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
3078 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
3079 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3080 FIXME("(%p) : stub\n", This
);
3081 if (NULL
== pClipStatus
) {
3082 return WINED3DERR_INVALIDCALL
;
3084 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
3085 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
3090 * Get / Set Material
3092 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
3093 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3095 if (!pMaterial
) return WINED3DERR_INVALIDCALL
;
3097 This
->updateStateBlock
->changed
.material
= TRUE
;
3098 This
->updateStateBlock
->material
= *pMaterial
;
3100 /* Handle recording of state blocks */
3101 if (This
->isRecordingState
) {
3102 TRACE("Recording... not performing anything\n");
3106 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_MATERIAL
);
3110 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
3111 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3112 *pMaterial
= This
->updateStateBlock
->material
;
3113 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3114 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3115 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3116 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3117 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3118 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3119 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3120 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3121 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3129 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
* pIndexData
) {
3130 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3131 IWineD3DIndexBuffer
*oldIdxs
;
3133 TRACE("(%p) : Setting to %p\n", This
, pIndexData
);
3134 oldIdxs
= This
->updateStateBlock
->pIndexData
;
3136 This
->updateStateBlock
->changed
.indices
= TRUE
;
3137 This
->updateStateBlock
->pIndexData
= pIndexData
;
3139 /* Handle recording of state blocks */
3140 if (This
->isRecordingState
) {
3141 TRACE("Recording... not performing anything\n");
3142 if(pIndexData
) IWineD3DIndexBuffer_AddRef(pIndexData
);
3143 if(oldIdxs
) IWineD3DIndexBuffer_Release(oldIdxs
);
3147 if(oldIdxs
!= pIndexData
) {
3148 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
3149 if(pIndexData
) IWineD3DIndexBuffer_AddRef(pIndexData
);
3150 if(oldIdxs
) IWineD3DIndexBuffer_Release(oldIdxs
);
3155 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
** ppIndexData
) {
3156 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3158 *ppIndexData
= This
->stateBlock
->pIndexData
;
3160 /* up ref count on ppindexdata */
3162 IWineD3DIndexBuffer_AddRef(*ppIndexData
);
3163 TRACE("(%p) index data set to %p\n", This
, ppIndexData
);
3165 TRACE("(%p) No index data set\n", This
);
3167 TRACE("Returning %p\n", *ppIndexData
);
3172 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3173 static HRESULT WINAPI
IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice
*iface
, INT BaseIndex
) {
3174 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3175 TRACE("(%p)->(%d)\n", This
, BaseIndex
);
3177 if(This
->updateStateBlock
->baseVertexIndex
== BaseIndex
) {
3178 TRACE("Application is setting the old value over, nothing to do\n");
3182 This
->updateStateBlock
->baseVertexIndex
= BaseIndex
;
3184 if (This
->isRecordingState
) {
3185 TRACE("Recording... not performing anything\n");
3188 /* The base vertex index affects the stream sources */
3189 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
3193 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice
*iface
, INT
* base_index
) {
3194 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3195 TRACE("(%p) : base_index %p\n", This
, base_index
);
3197 *base_index
= This
->stateBlock
->baseVertexIndex
;
3199 TRACE("Returning %u\n", *base_index
);
3205 * Get / Set Viewports
3207 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
3208 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3210 TRACE("(%p)\n", This
);
3211 This
->updateStateBlock
->changed
.viewport
= TRUE
;
3212 This
->updateStateBlock
->viewport
= *pViewport
;
3214 /* Handle recording of state blocks */
3215 if (This
->isRecordingState
) {
3216 TRACE("Recording... not performing anything\n");
3220 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This
,
3221 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
3223 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
3228 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
3229 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3230 TRACE("(%p)\n", This
);
3231 *pViewport
= This
->stateBlock
->viewport
;
3236 * Get / Set Render States
3237 * TODO: Verify against dx9 definitions
3239 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD Value
) {
3241 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3242 DWORD oldValue
= This
->stateBlock
->renderState
[State
];
3244 TRACE("(%p)->state = %s(%d), value = %d\n", This
, debug_d3drenderstate(State
), State
, Value
);
3246 This
->updateStateBlock
->changed
.renderState
[State
] = TRUE
;
3247 This
->updateStateBlock
->renderState
[State
] = Value
;
3249 /* Handle recording of state blocks */
3250 if (This
->isRecordingState
) {
3251 TRACE("Recording... not performing anything\n");
3255 /* Compared here and not before the assignment to allow proper stateblock recording */
3256 if(Value
== oldValue
) {
3257 TRACE("Application is setting the old value over, nothing to do\n");
3259 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(State
));
3265 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD
*pValue
) {
3266 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3267 TRACE("(%p) for State %d = %d\n", This
, State
, This
->stateBlock
->renderState
[State
]);
3268 *pValue
= This
->stateBlock
->renderState
[State
];
3273 * Get / Set Sampler States
3274 * TODO: Verify against dx9 definitions
3277 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
3278 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3281 TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3282 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
, Value
);
3284 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3285 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3288 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
3289 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3290 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3293 * SetSampler is designed to allow for more than the standard up to 8 textures
3294 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3295 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3297 * http://developer.nvidia.com/object/General_FAQ.html#t6
3299 * There are two new settings for GForce
3301 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3302 * and the texture one:
3303 * GL_MAX_TEXTURE_COORDS_ARB.
3304 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3307 oldValue
= This
->stateBlock
->samplerState
[Sampler
][Type
];
3308 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
3309 This
->updateStateBlock
->changed
.samplerState
[Sampler
][Type
] = Value
;
3311 /* Handle recording of state blocks */
3312 if (This
->isRecordingState
) {
3313 TRACE("Recording... not performing anything\n");
3317 if(oldValue
== Value
) {
3318 TRACE("Application is setting the old value over, nothing to do\n");
3322 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Sampler
));
3327 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
3328 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3330 TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3331 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
);
3333 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3334 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3337 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
3338 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3339 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3341 *Value
= This
->stateBlock
->samplerState
[Sampler
][Type
];
3342 TRACE("(%p) : Returning %#x\n", This
, *Value
);
3347 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
3348 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3350 This
->updateStateBlock
->changed
.scissorRect
= TRUE
;
3351 if(EqualRect(&This
->updateStateBlock
->scissorRect
, pRect
)) {
3352 TRACE("App is setting the old scissor rectangle over, nothing to do\n");
3355 CopyRect(&This
->updateStateBlock
->scissorRect
, pRect
);
3357 if(This
->isRecordingState
) {
3358 TRACE("Recording... not performing anything\n");
3362 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
3367 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
3368 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3370 *pRect
= This
->updateStateBlock
->scissorRect
;
3371 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3375 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
3376 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
3377 IWineD3DVertexDeclaration
*oldDecl
= This
->updateStateBlock
->vertexDecl
;
3379 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
3381 This
->updateStateBlock
->vertexDecl
= pDecl
;
3382 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
3384 if (This
->isRecordingState
) {
3385 TRACE("Recording... not performing anything\n");
3387 } else if(pDecl
== oldDecl
) {
3388 /* Checked after the assignment to allow proper stateblock recording */
3389 TRACE("Application is setting the old declaration over, nothing to do\n");
3393 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
3397 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
3398 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3400 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
3402 *ppDecl
= This
->stateBlock
->vertexDecl
;
3403 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
3407 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
3408 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3409 IWineD3DVertexShader
* oldShader
= This
->updateStateBlock
->vertexShader
;
3411 This
->updateStateBlock
->vertexShader
= pShader
;
3412 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3414 if (This
->isRecordingState
) {
3415 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3416 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3417 TRACE("Recording... not performing anything\n");
3419 } else if(oldShader
== pShader
) {
3420 /* Checked here to allow proper stateblock recording */
3421 TRACE("App is setting the old shader over, nothing to do\n");
3425 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3426 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3427 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3429 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VSHADER
);
3434 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
3435 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3437 if (NULL
== ppShader
) {
3438 return WINED3DERR_INVALIDCALL
;
3440 *ppShader
= This
->stateBlock
->vertexShader
;
3441 if( NULL
!= *ppShader
)
3442 IWineD3DVertexShader_AddRef(*ppShader
);
3444 TRACE("(%p) : returning %p\n", This
, *ppShader
);
3448 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
3449 IWineD3DDevice
*iface
,
3451 CONST BOOL
*srcData
,
3454 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3455 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3457 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3458 iface
, srcData
, start
, count
);
3460 if (srcData
== NULL
|| cnt
< 0)
3461 return WINED3DERR_INVALIDCALL
;
3463 memcpy(&This
->updateStateBlock
->vertexShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
3464 for (i
= 0; i
< cnt
; i
++)
3465 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3467 for (i
= start
; i
< cnt
+ start
; ++i
) {
3468 This
->updateStateBlock
->changed
.vertexShaderConstantsB
[i
] = TRUE
;
3471 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3476 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
3477 IWineD3DDevice
*iface
,
3482 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3483 int cnt
= min(count
, MAX_CONST_B
- start
);
3485 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3486 iface
, dstData
, start
, count
);
3488 if (dstData
== NULL
|| cnt
< 0)
3489 return WINED3DERR_INVALIDCALL
;
3491 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantB
[start
], cnt
* sizeof(BOOL
));
3495 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
3496 IWineD3DDevice
*iface
,
3501 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3502 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3504 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3505 iface
, srcData
, start
, count
);
3507 if (srcData
== NULL
|| cnt
< 0)
3508 return WINED3DERR_INVALIDCALL
;
3510 memcpy(&This
->updateStateBlock
->vertexShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3511 for (i
= 0; i
< cnt
; i
++)
3512 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3513 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3515 for (i
= start
; i
< cnt
+ start
; ++i
) {
3516 This
->updateStateBlock
->changed
.vertexShaderConstantsI
[i
] = TRUE
;
3519 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3524 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
3525 IWineD3DDevice
*iface
,
3530 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3531 int cnt
= min(count
, MAX_CONST_I
- start
);
3533 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3534 iface
, dstData
, start
, count
);
3536 if (dstData
== NULL
|| ((signed int) MAX_CONST_I
- (signed int) start
) <= (signed int) 0)
3537 return WINED3DERR_INVALIDCALL
;
3539 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
3543 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
3544 IWineD3DDevice
*iface
,
3546 CONST
float *srcData
,
3549 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3552 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3553 iface
, srcData
, start
, count
);
3555 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3556 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(vshader_constantsF
) || start
> GL_LIMITS(vshader_constantsF
))
3557 return WINED3DERR_INVALIDCALL
;
3559 memcpy(&This
->updateStateBlock
->vertexShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
3561 for (i
= 0; i
< count
; i
++)
3562 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3563 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3566 for (i
= start
; i
< count
+ start
; ++i
) {
3567 if (!This
->updateStateBlock
->changed
.vertexShaderConstantsF
[i
]) {
3568 constants_entry
*ptr
= LIST_ENTRY(list_head(&This
->updateStateBlock
->set_vconstantsF
), constants_entry
, entry
);
3569 if (!ptr
|| ptr
->count
>= sizeof(ptr
->idx
) / sizeof(*ptr
->idx
)) {
3570 ptr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(constants_entry
));
3571 list_add_head(&This
->updateStateBlock
->set_vconstantsF
, &ptr
->entry
);
3573 ptr
->idx
[ptr
->count
++] = i
;
3574 This
->updateStateBlock
->changed
.vertexShaderConstantsF
[i
] = TRUE
;
3578 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3583 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst(
3584 IWineD3DDevice
*iface
,
3586 CONST
float *srcData
,
3589 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3592 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3593 iface
, srcData
, start
, count
);
3595 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3596 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(vshader_constantsF
) || start
> GL_LIMITS(vshader_constantsF
))
3597 return WINED3DERR_INVALIDCALL
;
3599 memcpy(&This
->updateStateBlock
->vertexShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
3601 for (i
= 0; i
< count
; i
++)
3602 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3603 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3606 /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
3607 * context. On a context switch the old context will be fully dirtified
3609 memset(This
->activeContext
->vshader_const_dirty
+ start
, 1,
3610 sizeof(*This
->activeContext
->vshader_const_dirty
) * count
);
3611 This
->highest_dirty_vs_const
= max(This
->highest_dirty_vs_const
, start
+count
+1);
3613 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3618 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
3619 IWineD3DDevice
*iface
,
3624 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3625 int cnt
= min(count
, GL_LIMITS(vshader_constantsF
) - start
);
3627 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3628 iface
, dstData
, start
, count
);
3630 if (dstData
== NULL
|| cnt
< 0)
3631 return WINED3DERR_INVALIDCALL
;
3633 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
3637 static inline void markTextureStagesDirty(IWineD3DDeviceImpl
*This
, DWORD stage
) {
3639 for(i
= 0; i
< WINED3D_HIGHEST_TEXTURE_STATE
; i
++) {
3640 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, i
));
3644 static void device_map_stage(IWineD3DDeviceImpl
*This
, int stage
, int unit
) {
3645 int i
= This
->rev_tex_unit_map
[unit
];
3646 int j
= This
->texUnitMap
[stage
];
3648 This
->texUnitMap
[stage
] = unit
;
3649 if (i
!= -1 && i
!= stage
) {
3650 This
->texUnitMap
[i
] = -1;
3653 This
->rev_tex_unit_map
[unit
] = stage
;
3654 if (j
!= -1 && j
!= unit
) {
3655 This
->rev_tex_unit_map
[j
] = -1;
3659 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl
*This
) {
3662 for (i
= 0; i
< MAX_TEXTURES
; ++i
) {
3663 WINED3DTEXTUREOP color_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLOROP
];
3664 WINED3DTEXTUREOP alpha_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAOP
];
3665 DWORD color_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG1
] & WINED3DTA_SELECTMASK
;
3666 DWORD color_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG2
] & WINED3DTA_SELECTMASK
;
3667 DWORD color_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG0
] & WINED3DTA_SELECTMASK
;
3668 DWORD alpha_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG1
] & WINED3DTA_SELECTMASK
;
3669 DWORD alpha_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG2
] & WINED3DTA_SELECTMASK
;
3670 DWORD alpha_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG0
] & WINED3DTA_SELECTMASK
;
3672 if (color_op
== WINED3DTOP_DISABLE
) {
3673 /* Not used, and disable higher stages */
3674 while (i
< MAX_TEXTURES
) {
3675 This
->fixed_function_usage_map
[i
] = FALSE
;
3681 if (((color_arg1
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG2
)
3682 || ((color_arg2
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG1
)
3683 || ((color_arg3
== WINED3DTA_TEXTURE
) && (color_op
== WINED3DTOP_MULTIPLYADD
|| color_op
== WINED3DTOP_LERP
))
3684 || ((alpha_arg1
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG2
)
3685 || ((alpha_arg2
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG1
)
3686 || ((alpha_arg3
== WINED3DTA_TEXTURE
) && (alpha_op
== WINED3DTOP_MULTIPLYADD
|| alpha_op
== WINED3DTOP_LERP
))) {
3687 This
->fixed_function_usage_map
[i
] = TRUE
;
3689 This
->fixed_function_usage_map
[i
] = FALSE
;
3692 if ((color_op
== WINED3DTOP_BUMPENVMAP
|| color_op
== WINED3DTOP_BUMPENVMAPLUMINANCE
) && i
< MAX_TEXTURES
- 1) {
3693 This
->fixed_function_usage_map
[i
+1] = TRUE
;
3698 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl
*This
) {
3701 device_update_fixed_function_usage_map(This
);
3703 if (!GL_SUPPORT(NV_REGISTER_COMBINERS
) || This
->stateBlock
->lowest_disabled_stage
<= GL_LIMITS(textures
)) {
3704 for (i
= 0; i
< This
->stateBlock
->lowest_disabled_stage
; ++i
) {
3705 if (!This
->fixed_function_usage_map
[i
]) continue;
3707 if (This
->texUnitMap
[i
] != i
) {
3708 device_map_stage(This
, i
, i
);
3709 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3710 markTextureStagesDirty(This
, i
);
3716 /* Now work out the mapping */
3718 for (i
= 0; i
< This
->stateBlock
->lowest_disabled_stage
; ++i
) {
3719 if (!This
->fixed_function_usage_map
[i
]) continue;
3721 if (This
->texUnitMap
[i
] != tex
) {
3722 device_map_stage(This
, i
, tex
);
3723 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3724 markTextureStagesDirty(This
, i
);
3731 static void device_map_psamplers(IWineD3DDeviceImpl
*This
) {
3732 DWORD
*sampler_tokens
= ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.reg_maps
.samplers
;
3735 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
) {
3736 if (sampler_tokens
[i
] && This
->texUnitMap
[i
] != i
) {
3737 device_map_stage(This
, i
, i
);
3738 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3739 if (i
< MAX_TEXTURES
) {
3740 markTextureStagesDirty(This
, i
);
3746 static BOOL
device_unit_free_for_vs(IWineD3DDeviceImpl
*This
, DWORD
*pshader_sampler_tokens
, DWORD
*vshader_sampler_tokens
, int unit
) {
3747 int current_mapping
= This
->rev_tex_unit_map
[unit
];
3749 if (current_mapping
== -1) {
3750 /* Not currently used */
3754 if (current_mapping
< MAX_FRAGMENT_SAMPLERS
) {
3755 /* Used by a fragment sampler */
3757 if (!pshader_sampler_tokens
) {
3758 /* No pixel shader, check fixed function */
3759 return current_mapping
>= MAX_TEXTURES
|| !This
->fixed_function_usage_map
[current_mapping
];
3762 /* Pixel shader, check the shader's sampler map */
3763 return !pshader_sampler_tokens
[current_mapping
];
3766 /* Used by a vertex sampler */
3767 return !vshader_sampler_tokens
[current_mapping
];
3770 static void device_map_vsamplers(IWineD3DDeviceImpl
*This
, BOOL ps
) {
3771 DWORD
*vshader_sampler_tokens
= ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.reg_maps
.samplers
;
3772 DWORD
*pshader_sampler_tokens
= NULL
;
3773 int start
= GL_LIMITS(combined_samplers
) - 1;
3777 IWineD3DPixelShaderImpl
*pshader
= (IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
;
3779 /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
3780 IWineD3DPixelShader_CompileShader((IWineD3DPixelShader
*)pshader
);
3781 pshader_sampler_tokens
= pshader
->baseShader
.reg_maps
.samplers
;
3784 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
) {
3785 int vsampler_idx
= i
+ MAX_FRAGMENT_SAMPLERS
;
3786 if (vshader_sampler_tokens
[i
]) {
3787 if (This
->texUnitMap
[vsampler_idx
] != -1) {
3788 /* Already mapped somewhere */
3792 while (start
>= 0) {
3793 if (device_unit_free_for_vs(This
, pshader_sampler_tokens
, vshader_sampler_tokens
, start
)) {
3794 device_map_stage(This
, vsampler_idx
, start
);
3795 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(vsampler_idx
));
3807 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl
*This
) {
3808 BOOL vs
= use_vs(This
);
3809 BOOL ps
= use_ps(This
);
3812 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3813 * that would be really messy and require shader recompilation
3814 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3815 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3818 device_map_psamplers(This
);
3820 device_map_fixed_function_samplers(This
);
3824 device_map_vsamplers(This
, ps
);
3828 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
3829 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3830 IWineD3DPixelShader
*oldShader
= This
->updateStateBlock
->pixelShader
;
3831 This
->updateStateBlock
->pixelShader
= pShader
;
3832 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
3834 /* Handle recording of state blocks */
3835 if (This
->isRecordingState
) {
3836 TRACE("Recording... not performing anything\n");
3839 if (This
->isRecordingState
) {
3840 TRACE("Recording... not performing anything\n");
3841 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3842 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3846 if(pShader
== oldShader
) {
3847 TRACE("App is setting the old pixel shader over, nothing to do\n");
3851 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3852 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3854 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3855 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
3860 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
3861 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3863 if (NULL
== ppShader
) {
3864 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This
);
3865 return WINED3DERR_INVALIDCALL
;
3868 *ppShader
= This
->stateBlock
->pixelShader
;
3869 if (NULL
!= *ppShader
) {
3870 IWineD3DPixelShader_AddRef(*ppShader
);
3872 TRACE("(%p) : returning %p\n", This
, *ppShader
);
3876 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
3877 IWineD3DDevice
*iface
,
3879 CONST BOOL
*srcData
,
3882 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3883 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3885 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3886 iface
, srcData
, start
, count
);
3888 if (srcData
== NULL
|| cnt
< 0)
3889 return WINED3DERR_INVALIDCALL
;
3891 memcpy(&This
->updateStateBlock
->pixelShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
3892 for (i
= 0; i
< cnt
; i
++)
3893 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3895 for (i
= start
; i
< cnt
+ start
; ++i
) {
3896 This
->updateStateBlock
->changed
.pixelShaderConstantsB
[i
] = TRUE
;
3899 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3904 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
3905 IWineD3DDevice
*iface
,
3910 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3911 int cnt
= min(count
, MAX_CONST_B
- start
);
3913 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3914 iface
, dstData
, start
, count
);
3916 if (dstData
== NULL
|| cnt
< 0)
3917 return WINED3DERR_INVALIDCALL
;
3919 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantB
[start
], cnt
* sizeof(BOOL
));
3923 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
3924 IWineD3DDevice
*iface
,
3929 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3930 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3932 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3933 iface
, srcData
, start
, count
);
3935 if (srcData
== NULL
|| cnt
< 0)
3936 return WINED3DERR_INVALIDCALL
;
3938 memcpy(&This
->updateStateBlock
->pixelShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3939 for (i
= 0; i
< cnt
; i
++)
3940 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3941 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3943 for (i
= start
; i
< cnt
+ start
; ++i
) {
3944 This
->updateStateBlock
->changed
.pixelShaderConstantsI
[i
] = TRUE
;
3947 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3952 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
3953 IWineD3DDevice
*iface
,
3958 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3959 int cnt
= min(count
, MAX_CONST_I
- start
);
3961 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3962 iface
, dstData
, start
, count
);
3964 if (dstData
== NULL
|| cnt
< 0)
3965 return WINED3DERR_INVALIDCALL
;
3967 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
3971 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
3972 IWineD3DDevice
*iface
,
3974 CONST
float *srcData
,
3977 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3980 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3981 iface
, srcData
, start
, count
);
3983 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3984 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(pshader_constantsF
) || start
> GL_LIMITS(pshader_constantsF
))
3985 return WINED3DERR_INVALIDCALL
;
3987 memcpy(&This
->updateStateBlock
->pixelShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
3989 for (i
= 0; i
< count
; i
++)
3990 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3991 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3994 for (i
= start
; i
< count
+ start
; ++i
) {
3995 if (!This
->updateStateBlock
->changed
.pixelShaderConstantsF
[i
]) {
3996 constants_entry
*ptr
= LIST_ENTRY(list_head(&This
->updateStateBlock
->set_pconstantsF
), constants_entry
, entry
);
3997 if (!ptr
|| ptr
->count
>= sizeof(ptr
->idx
) / sizeof(*ptr
->idx
)) {
3998 ptr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(constants_entry
));
3999 list_add_head(&This
->updateStateBlock
->set_pconstantsF
, &ptr
->entry
);
4001 ptr
->idx
[ptr
->count
++] = i
;
4002 This
->updateStateBlock
->changed
.pixelShaderConstantsF
[i
] = TRUE
;
4006 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
4011 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst(
4012 IWineD3DDevice
*iface
,
4014 CONST
float *srcData
,
4017 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4020 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4021 iface
, srcData
, start
, count
);
4023 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
4024 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(pshader_constantsF
) || start
> GL_LIMITS(pshader_constantsF
))
4025 return WINED3DERR_INVALIDCALL
;
4027 memcpy(&This
->updateStateBlock
->pixelShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
4029 for (i
= 0; i
< count
; i
++)
4030 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
4031 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4034 /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
4035 * context. On a context switch the old context will be fully dirtified
4037 memset(This
->activeContext
->pshader_const_dirty
+ start
, 1,
4038 sizeof(*This
->activeContext
->pshader_const_dirty
) * count
);
4039 This
->highest_dirty_ps_const
= max(This
->highest_dirty_ps_const
, start
+count
+1);
4041 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
4046 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
4047 IWineD3DDevice
*iface
,
4052 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4053 int cnt
= min(count
, GL_LIMITS(pshader_constantsF
) - start
);
4055 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4056 iface
, dstData
, start
, count
);
4058 if (dstData
== NULL
|| cnt
< 0)
4059 return WINED3DERR_INVALIDCALL
;
4061 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
4065 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4067 process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
, WineDirect3DVertexStridedData
*lpStrideData
, IWineD3DVertexBufferImpl
*dest
, DWORD dwFlags
) {
4068 char *dest_ptr
, *dest_conv
= NULL
, *dest_conv_addr
= NULL
;
4070 DWORD DestFVF
= dest
->fvf
;
4072 WINED3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
4076 if (lpStrideData
->u
.s
.normal
.lpData
) {
4077 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4080 if (lpStrideData
->u
.s
.position
.lpData
== NULL
) {
4081 ERR("Source has no position mask\n");
4082 return WINED3DERR_INVALIDCALL
;
4085 /* We might access VBOs from this code, so hold the lock */
4088 if (dest
->resource
.allocatedMemory
== NULL
) {
4089 /* This may happen if we do direct locking into a vbo. Unlikely,
4090 * but theoretically possible(ddraw processvertices test)
4092 dest
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), 0, dest
->resource
.size
);
4093 if(!dest
->resource
.allocatedMemory
) {
4095 ERR("Out of memory\n");
4096 return E_OUTOFMEMORY
;
4100 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
4101 checkGLcall("glBindBufferARB");
4102 src
= GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_READ_ONLY_ARB
));
4104 memcpy(dest
->resource
.allocatedMemory
, src
, dest
->resource
.size
);
4106 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
));
4107 checkGLcall("glUnmapBufferARB");
4111 /* Get a pointer into the destination vbo(create one if none exists) and
4112 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4114 if(!dest
->vbo
&& GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
4115 dest
->Flags
|= VBFLAG_CREATEVBO
;
4116 IWineD3DVertexBuffer_PreLoad((IWineD3DVertexBuffer
*) dest
);
4120 unsigned char extrabytes
= 0;
4121 /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4122 * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4123 * this may write 4 extra bytes beyond the area that should be written
4125 if(DestFVF
== WINED3DFVF_XYZ
) extrabytes
= 4;
4126 dest_conv_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwCount
* get_flexible_vertex_size(DestFVF
) + extrabytes
);
4127 if(!dest_conv_addr
) {
4128 ERR("Out of memory\n");
4129 /* Continue without storing converted vertices */
4131 dest_conv
= dest_conv_addr
;
4135 * a) WINED3DRS_CLIPPING is enabled
4136 * b) WINED3DVOP_CLIP is passed
4138 if(This
->stateBlock
->renderState
[WINED3DRS_CLIPPING
]) {
4139 static BOOL warned
= FALSE
;
4141 * The clipping code is not quite correct. Some things need
4142 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4143 * so disable clipping for now.
4144 * (The graphics in Half-Life are broken, and my processvertices
4145 * test crashes with IDirect3DDevice3)
4151 FIXME("Clipping is broken and disabled for now\n");
4153 } else doClip
= FALSE
;
4154 dest_ptr
= ((char *) dest
->resource
.allocatedMemory
) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
4156 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4159 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4160 WINED3DTS_PROJECTION
,
4162 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4163 WINED3DTS_WORLDMATRIX(0),
4166 TRACE("View mat:\n");
4167 TRACE("%f %f %f %f\n", view_mat
.u
.s
._11
, view_mat
.u
.s
._12
, view_mat
.u
.s
._13
, view_mat
.u
.s
._14
);
4168 TRACE("%f %f %f %f\n", view_mat
.u
.s
._21
, view_mat
.u
.s
._22
, view_mat
.u
.s
._23
, view_mat
.u
.s
._24
);
4169 TRACE("%f %f %f %f\n", view_mat
.u
.s
._31
, view_mat
.u
.s
._32
, view_mat
.u
.s
._33
, view_mat
.u
.s
._34
);
4170 TRACE("%f %f %f %f\n", view_mat
.u
.s
._41
, view_mat
.u
.s
._42
, view_mat
.u
.s
._43
, view_mat
.u
.s
._44
);
4172 TRACE("Proj mat:\n");
4173 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._11
, proj_mat
.u
.s
._12
, proj_mat
.u
.s
._13
, proj_mat
.u
.s
._14
);
4174 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._21
, proj_mat
.u
.s
._22
, proj_mat
.u
.s
._23
, proj_mat
.u
.s
._24
);
4175 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._31
, proj_mat
.u
.s
._32
, proj_mat
.u
.s
._33
, proj_mat
.u
.s
._34
);
4176 TRACE("%f %f %f %f\n", proj_mat
.u
.s
._41
, proj_mat
.u
.s
._42
, proj_mat
.u
.s
._43
, proj_mat
.u
.s
._44
);
4178 TRACE("World mat:\n");
4179 TRACE("%f %f %f %f\n", world_mat
.u
.s
._11
, world_mat
.u
.s
._12
, world_mat
.u
.s
._13
, world_mat
.u
.s
._14
);
4180 TRACE("%f %f %f %f\n", world_mat
.u
.s
._21
, world_mat
.u
.s
._22
, world_mat
.u
.s
._23
, world_mat
.u
.s
._24
);
4181 TRACE("%f %f %f %f\n", world_mat
.u
.s
._31
, world_mat
.u
.s
._32
, world_mat
.u
.s
._33
, world_mat
.u
.s
._34
);
4182 TRACE("%f %f %f %f\n", world_mat
.u
.s
._41
, world_mat
.u
.s
._42
, world_mat
.u
.s
._43
, world_mat
.u
.s
._44
);
4184 /* Get the viewport */
4185 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
4186 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4187 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
4189 multiply_matrix(&mat
,&view_mat
,&world_mat
);
4190 multiply_matrix(&mat
,&proj_mat
,&mat
);
4192 numTextures
= (DestFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
4194 for (i
= 0; i
< dwCount
; i
+= 1) {
4195 unsigned int tex_index
;
4197 if ( ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
4198 ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
4199 /* The position first */
4201 (float *) (((char *) lpStrideData
->u
.s
.position
.lpData
) + i
* lpStrideData
->u
.s
.position
.dwStride
);
4203 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
4205 /* Multiplication with world, view and projection matrix */
4206 x
= (p
[0] * mat
.u
.s
._11
) + (p
[1] * mat
.u
.s
._21
) + (p
[2] * mat
.u
.s
._31
) + (1.0 * mat
.u
.s
._41
);
4207 y
= (p
[0] * mat
.u
.s
._12
) + (p
[1] * mat
.u
.s
._22
) + (p
[2] * mat
.u
.s
._32
) + (1.0 * mat
.u
.s
._42
);
4208 z
= (p
[0] * mat
.u
.s
._13
) + (p
[1] * mat
.u
.s
._23
) + (p
[2] * mat
.u
.s
._33
) + (1.0 * mat
.u
.s
._43
);
4209 rhw
= (p
[0] * mat
.u
.s
._14
) + (p
[1] * mat
.u
.s
._24
) + (p
[2] * mat
.u
.s
._34
) + (1.0 * mat
.u
.s
._44
);
4211 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
4213 /* WARNING: The following things are taken from d3d7 and were not yet checked
4214 * against d3d8 or d3d9!
4217 /* Clipping conditions: From msdn
4219 * A vertex is clipped if it does not match the following requirements
4223 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4225 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4226 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4231 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
4232 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
4235 /* "Normal" viewport transformation (not clipped)
4236 * 1) The values are divided by rhw
4237 * 2) The y axis is negative, so multiply it with -1
4238 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4239 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4240 * 4) Multiply x with Width/2 and add Width/2
4241 * 5) The same for the height
4242 * 6) Add the viewpoint X and Y to the 2D coordinates and
4243 * The minimum Z value to z
4244 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4246 * Well, basically it's simply a linear transformation into viewport
4258 z
*= vp
.MaxZ
- vp
.MinZ
;
4260 x
+= vp
.Width
/ 2 + vp
.X
;
4261 y
+= vp
.Height
/ 2 + vp
.Y
;
4266 /* That vertex got clipped
4267 * Contrary to OpenGL it is not dropped completely, it just
4268 * undergoes a different calculation.
4270 TRACE("Vertex got clipped\n");
4277 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4278 * outside of the main vertex buffer memory. That needs some more
4283 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
4286 ( (float *) dest_ptr
)[0] = x
;
4287 ( (float *) dest_ptr
)[1] = y
;
4288 ( (float *) dest_ptr
)[2] = z
;
4289 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
4291 dest_ptr
+= 3 * sizeof(float);
4293 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4294 dest_ptr
+= sizeof(float);
4299 ( (float *) dest_conv
)[0] = x
* w
;
4300 ( (float *) dest_conv
)[1] = y
* w
;
4301 ( (float *) dest_conv
)[2] = z
* w
;
4302 ( (float *) dest_conv
)[3] = w
;
4304 dest_conv
+= 3 * sizeof(float);
4306 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4307 dest_conv
+= sizeof(float);
4311 if (DestFVF
& WINED3DFVF_PSIZE
) {
4312 dest_ptr
+= sizeof(DWORD
);
4313 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
4315 if (DestFVF
& WINED3DFVF_NORMAL
) {
4317 (float *) (((float *) lpStrideData
->u
.s
.normal
.lpData
) + i
* lpStrideData
->u
.s
.normal
.dwStride
);
4318 /* AFAIK this should go into the lighting information */
4319 FIXME("Didn't expect the destination to have a normal\n");
4320 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
4322 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
4326 if (DestFVF
& WINED3DFVF_DIFFUSE
) {
4328 (DWORD
*) (((char *) lpStrideData
->u
.s
.diffuse
.lpData
) + i
* lpStrideData
->u
.s
.diffuse
.dwStride
);
4330 static BOOL warned
= FALSE
;
4333 ERR("No diffuse color in source, but destination has one\n");
4337 *( (DWORD
*) dest_ptr
) = 0xffffffff;
4338 dest_ptr
+= sizeof(DWORD
);
4341 *( (DWORD
*) dest_conv
) = 0xffffffff;
4342 dest_conv
+= sizeof(DWORD
);
4346 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
4348 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
4349 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
4350 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
4351 dest_conv
+= sizeof(DWORD
);
4356 if (DestFVF
& WINED3DFVF_SPECULAR
) {
4357 /* What's the color value in the feedback buffer? */
4359 (DWORD
*) (((char *) lpStrideData
->u
.s
.specular
.lpData
) + i
* lpStrideData
->u
.s
.specular
.dwStride
);
4361 static BOOL warned
= FALSE
;
4364 ERR("No specular color in source, but destination has one\n");
4368 *( (DWORD
*) dest_ptr
) = 0xFF000000;
4369 dest_ptr
+= sizeof(DWORD
);
4372 *( (DWORD
*) dest_conv
) = 0xFF000000;
4373 dest_conv
+= sizeof(DWORD
);
4377 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
4379 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
4380 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
4381 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
4382 dest_conv
+= sizeof(DWORD
);
4387 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
4389 (float *) (((char *) lpStrideData
->u
.s
.texCoords
[tex_index
].lpData
) +
4390 i
* lpStrideData
->u
.s
.texCoords
[tex_index
].dwStride
);
4392 ERR("No source texture, but destination requests one\n");
4393 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4394 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4397 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4399 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4406 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
4407 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4408 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, dwDestIndex
* get_flexible_vertex_size(DestFVF
),
4409 dwCount
* get_flexible_vertex_size(DestFVF
),
4411 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4412 HeapFree(GetProcessHeap(), 0, dest_conv_addr
);
4419 #undef copy_and_next
4421 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, IWineD3DVertexBuffer
* pDestBuffer
, IWineD3DVertexDeclaration
* pVertexDecl
, DWORD Flags
) {
4422 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4423 WineDirect3DVertexStridedData strided
;
4424 BOOL vbo
= FALSE
, streamWasUP
= This
->stateBlock
->streamIsUP
;
4425 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, Flags
);
4428 ERR("Output vertex declaration not implemented yet\n");
4431 /* Need any context to write to the vbo. */
4432 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
4434 /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4435 * control the streamIsUP flag, thus restore it afterwards.
4437 This
->stateBlock
->streamIsUP
= FALSE
;
4438 memset(&strided
, 0, sizeof(strided
));
4439 primitiveDeclarationConvertToStridedData(iface
, FALSE
, &strided
, &vbo
);
4440 This
->stateBlock
->streamIsUP
= streamWasUP
;
4442 if(vbo
|| SrcStartIndex
) {
4444 /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4445 * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
4447 * Also get the start index in, but only loop over all elements if there's something to add at all.
4449 #define FIXSRC(type) \
4450 if(strided.u.s.type.VBO) { \
4451 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
4452 strided.u.s.type.VBO = 0; \
4453 strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
4455 GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); \
4459 if(strided.u.s.type.lpData) { \
4460 strided.u.s.type.lpData += strided.u.s.type.dwStride * SrcStartIndex; \
4463 FIXSRC(blendWeights
);
4464 FIXSRC(blendMatrixIndices
);
4469 for(i
= 0; i
< WINED3DDP_MAXTEXCOORD
; i
++) {
4470 FIXSRC(texCoords
[i
]);
4483 return process_vertices_strided(This
, DestIndex
, VertexCount
, &strided
, (IWineD3DVertexBufferImpl
*) pDestBuffer
, Flags
);
4487 * Get / Set Texture Stage States
4488 * TODO: Verify against dx9 definitions
4490 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
4491 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4492 DWORD oldValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4494 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
4496 if (Stage
>= MAX_TEXTURES
) {
4497 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage
, MAX_TEXTURES
- 1);
4501 This
->updateStateBlock
->changed
.textureState
[Stage
][Type
] = TRUE
;
4502 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
4504 if (This
->isRecordingState
) {
4505 TRACE("Recording... not performing anything\n");
4509 /* Checked after the assignments to allow proper stateblock recording */
4510 if(oldValue
== Value
) {
4511 TRACE("App is setting the old value over, nothing to do\n");
4515 if(Stage
> This
->stateBlock
->lowest_disabled_stage
&&
4516 This
->StateTable
[STATE_TEXTURESTAGE(0, Type
)].representative
== STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP
)) {
4517 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4518 * Changes in other states are important on disabled stages too
4523 if(Type
== WINED3DTSS_COLOROP
) {
4526 if(Value
== WINED3DTOP_DISABLE
&& oldValue
!= WINED3DTOP_DISABLE
) {
4527 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4528 * they have to be disabled
4530 * The current stage is dirtified below.
4532 for(i
= Stage
+ 1; i
< This
->stateBlock
->lowest_disabled_stage
; i
++) {
4533 TRACE("Additionally dirtifying stage %d\n", i
);
4534 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4536 This
->stateBlock
->lowest_disabled_stage
= Stage
;
4537 TRACE("New lowest disabled: %d\n", Stage
);
4538 } else if(Value
!= WINED3DTOP_DISABLE
&& oldValue
== WINED3DTOP_DISABLE
) {
4539 /* Previously disabled stage enabled. Stages above it may need enabling
4540 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4541 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4543 * Again stage Stage doesn't need to be dirtified here, it is handled below.
4546 for(i
= Stage
+ 1; i
< GL_LIMITS(texture_stages
); i
++) {
4547 if(This
->updateStateBlock
->textureState
[i
][WINED3DTSS_COLOROP
] == WINED3DTOP_DISABLE
) {
4550 TRACE("Additionally dirtifying stage %d due to enable\n", i
);
4551 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4553 This
->stateBlock
->lowest_disabled_stage
= i
;
4554 TRACE("New lowest disabled: %d\n", i
);
4556 if(GL_SUPPORT(NV_REGISTER_COMBINERS
) && !This
->stateBlock
->pixelShader
) {
4557 /* TODO: Built a stage -> texture unit mapping for register combiners */
4561 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, Type
));
4566 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
4567 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4568 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
4569 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4576 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
* pTexture
) {
4577 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4578 IWineD3DBaseTexture
*oldTexture
;
4580 TRACE("(%p) : Stage %#x, Texture %p\n", This
, Stage
, pTexture
);
4582 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
4583 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4586 if (Stage
>= sizeof(This
->stateBlock
->textures
)/sizeof(This
->stateBlock
->textures
[0])) {
4587 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
4588 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4591 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
4593 if(pTexture
!= NULL
) {
4594 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
4596 if(((IWineD3DTextureImpl
*)pTexture
)->resource
.pool
== WINED3DPOOL_SCRATCH
) {
4597 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture
);
4598 return WINED3DERR_INVALIDCALL
;
4600 This
->stateBlock
->textureDimensions
[Stage
] = IWineD3DBaseTexture_GetTextureDimensions(pTexture
);
4603 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages
));
4604 TRACE("(%p) : oldtexture(%p)\n", This
,oldTexture
);
4606 This
->updateStateBlock
->changed
.textures
[Stage
] = TRUE
;
4607 TRACE("(%p) : setting new texture to %p\n", This
, pTexture
);
4608 This
->updateStateBlock
->textures
[Stage
] = pTexture
;
4610 /* Handle recording of state blocks */
4611 if (This
->isRecordingState
) {
4612 TRACE("Recording... not performing anything\n");
4616 if(oldTexture
== pTexture
) {
4617 TRACE("App is setting the same texture again, nothing to do\n");
4621 /** NOTE: MSDN says that setTexture increases the reference count,
4622 * and that the application must set the texture back to null (or have a leaky application),
4623 * This means we should pass the refcount up to the parent
4624 *******************************/
4625 if (NULL
!= This
->updateStateBlock
->textures
[Stage
]) {
4626 IWineD3DBaseTextureImpl
*new = (IWineD3DBaseTextureImpl
*) This
->updateStateBlock
->textures
[Stage
];
4627 ULONG bindCount
= InterlockedIncrement(&new->baseTexture
.bindCount
);
4629 IWineD3DBaseTexture_AddRef(This
->updateStateBlock
->textures
[Stage
]);
4630 if(oldTexture
== NULL
&& Stage
< MAX_TEXTURES
) {
4631 /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4632 * so the COLOROP and ALPHAOP have to be dirtified.
4634 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_COLOROP
));
4635 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_ALPHAOP
));
4637 if(bindCount
== 1) {
4638 new->baseTexture
.sampler
= Stage
;
4640 /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4644 if (NULL
!= oldTexture
) {
4645 IWineD3DBaseTextureImpl
*old
= (IWineD3DBaseTextureImpl
*) oldTexture
;
4646 LONG bindCount
= InterlockedDecrement(&old
->baseTexture
.bindCount
);
4648 IWineD3DBaseTexture_Release(oldTexture
);
4649 if(pTexture
== NULL
&& Stage
< MAX_TEXTURES
) {
4650 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_COLOROP
));
4651 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_ALPHAOP
));
4654 if(bindCount
&& old
->baseTexture
.sampler
== Stage
) {
4656 /* Have to do a search for the other sampler(s) where the texture is bound to
4657 * Shouldn't happen as long as apps bind a texture only to one stage
4659 TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4660 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
4661 if(This
->updateStateBlock
->textures
[i
] == oldTexture
) {
4662 old
->baseTexture
.sampler
= i
;
4669 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Stage
));
4674 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
4675 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4677 TRACE("(%p) : Stage %#x, ppTexture %p\n", This
, Stage
, ppTexture
);
4679 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
4680 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4683 if (Stage
>= sizeof(This
->stateBlock
->textures
)/sizeof(This
->stateBlock
->textures
[0])) {
4684 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
4685 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4688 *ppTexture
=This
->stateBlock
->textures
[Stage
];
4690 IWineD3DBaseTexture_AddRef(*ppTexture
);
4692 TRACE("(%p) : Returning %p\n", This
, *ppTexture
);
4700 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT iSwapChain
, UINT BackBuffer
, WINED3DBACKBUFFER_TYPE Type
,
4701 IWineD3DSurface
**ppBackBuffer
) {
4702 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4703 IWineD3DSwapChain
*swapChain
;
4706 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This
, BackBuffer
, Type
, iSwapChain
, *ppBackBuffer
);
4708 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4709 if (hr
== WINED3D_OK
) {
4710 hr
= IWineD3DSwapChain_GetBackBuffer(swapChain
, BackBuffer
, Type
, ppBackBuffer
);
4711 IWineD3DSwapChain_Release(swapChain
);
4713 *ppBackBuffer
= NULL
;
4718 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
4719 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4720 WARN("(%p) : stub, calling idirect3d for now\n", This
);
4721 return IWineD3D_GetDeviceCaps(This
->wineD3D
, This
->adapterNo
, This
->devType
, pCaps
);
4724 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
4725 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4726 IWineD3DSwapChain
*swapChain
;
4729 if(iSwapChain
> 0) {
4730 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4731 if (hr
== WINED3D_OK
) {
4732 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
4733 IWineD3DSwapChain_Release(swapChain
);
4735 FIXME("(%p) Error getting display mode\n", This
);
4738 /* Don't read the real display mode,
4739 but return the stored mode instead. X11 can't change the color
4740 depth, and some apps are pretty angry if they SetDisplayMode from
4741 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4743 Also don't relay to the swapchain because with ddraw it's possible
4744 that there isn't a swapchain at all */
4745 pMode
->Width
= This
->ddraw_width
;
4746 pMode
->Height
= This
->ddraw_height
;
4747 pMode
->Format
= This
->ddraw_format
;
4748 pMode
->RefreshRate
= 0;
4755 static HRESULT WINAPI
IWineD3DDeviceImpl_SetHWND(IWineD3DDevice
*iface
, HWND hWnd
) {
4756 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4757 TRACE("(%p)->(%p)\n", This
, hWnd
);
4759 if(This
->ddraw_fullscreen
) {
4760 if(This
->ddraw_window
&& This
->ddraw_window
!= hWnd
) {
4761 IWineD3DDeviceImpl_RestoreWindow(iface
, This
->ddraw_window
);
4763 if(hWnd
&& This
->ddraw_window
!= hWnd
) {
4764 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, hWnd
);
4768 This
->ddraw_window
= hWnd
;
4772 static HRESULT WINAPI
IWineD3DDeviceImpl_GetHWND(IWineD3DDevice
*iface
, HWND
*hWnd
) {
4773 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4774 TRACE("(%p)->(%p)\n", This
, hWnd
);
4776 *hWnd
= This
->ddraw_window
;
4781 * Stateblock related functions
4784 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
4785 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4786 IWineD3DStateBlockImpl
*object
;
4787 HRESULT temp_result
;
4790 TRACE("(%p)\n", This
);
4792 if (This
->isRecordingState
) {
4793 return WINED3DERR_INVALIDCALL
;
4796 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DStateBlockImpl
));
4797 if (NULL
== object
) {
4798 FIXME("(%p)Error allocating memory for stateblock\n", This
);
4799 return E_OUTOFMEMORY
;
4801 TRACE("(%p) created object %p\n", This
, object
);
4802 object
->wineD3DDevice
= This
;
4803 /** FIXME: object->parent = parent; **/
4804 object
->parent
= NULL
;
4805 object
->blockType
= WINED3DSBT_RECORDED
;
4807 object
->lpVtbl
= &IWineD3DStateBlock_Vtbl
;
4809 for(i
= 0; i
< LIGHTMAP_SIZE
; i
++) {
4810 list_init(&object
->lightMap
[i
]);
4813 temp_result
= allocate_shader_constants(object
);
4814 if (WINED3D_OK
!= temp_result
)
4817 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
4818 This
->updateStateBlock
= object
;
4819 This
->isRecordingState
= TRUE
;
4821 TRACE("(%p) recording stateblock %p\n",This
, object
);
4825 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
4826 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4828 IWineD3DStateBlockImpl
*object
= This
->updateStateBlock
;
4830 if (!This
->isRecordingState
) {
4831 FIXME("(%p) not recording! returning error\n", This
);
4832 *ppStateBlock
= NULL
;
4833 return WINED3DERR_INVALIDCALL
;
4836 for(i
= 1; i
<= WINEHIGHEST_RENDER_STATE
; i
++) {
4837 if(object
->changed
.renderState
[i
]) {
4838 object
->contained_render_states
[object
->num_contained_render_states
] = i
;
4839 object
->num_contained_render_states
++;
4842 for(i
= 1; i
<= HIGHEST_TRANSFORMSTATE
; i
++) {
4843 if(object
->changed
.transform
[i
]) {
4844 object
->contained_transform_states
[object
->num_contained_transform_states
] = i
;
4845 object
->num_contained_transform_states
++;
4848 for(i
= 0; i
< GL_LIMITS(vshader_constantsF
); i
++) {
4849 if(object
->changed
.vertexShaderConstantsF
[i
]) {
4850 object
->contained_vs_consts_f
[object
->num_contained_vs_consts_f
] = i
;
4851 object
->num_contained_vs_consts_f
++;
4854 for(i
= 0; i
< MAX_CONST_I
; i
++) {
4855 if(object
->changed
.vertexShaderConstantsI
[i
]) {
4856 object
->contained_vs_consts_i
[object
->num_contained_vs_consts_i
] = i
;
4857 object
->num_contained_vs_consts_i
++;
4860 for(i
= 0; i
< MAX_CONST_B
; i
++) {
4861 if(object
->changed
.vertexShaderConstantsB
[i
]) {
4862 object
->contained_vs_consts_b
[object
->num_contained_vs_consts_b
] = i
;
4863 object
->num_contained_vs_consts_b
++;
4866 for(i
= 0; i
< MAX_CONST_I
; i
++) {
4867 if(object
->changed
.pixelShaderConstantsI
[i
]) {
4868 object
->contained_ps_consts_i
[object
->num_contained_ps_consts_i
] = i
;
4869 object
->num_contained_ps_consts_i
++;
4872 for(i
= 0; i
< MAX_CONST_B
; i
++) {
4873 if(object
->changed
.pixelShaderConstantsB
[i
]) {
4874 object
->contained_ps_consts_b
[object
->num_contained_ps_consts_b
] = i
;
4875 object
->num_contained_ps_consts_b
++;
4878 for(i
= 0; i
< MAX_TEXTURES
; i
++) {
4879 for(j
= 1; j
<= WINED3D_HIGHEST_TEXTURE_STATE
; j
++) {
4880 if(object
->changed
.textureState
[i
][j
]) {
4881 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= i
;
4882 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= j
;
4883 object
->num_contained_tss_states
++;
4887 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++){
4888 for (j
= 1; j
< WINED3D_HIGHEST_SAMPLER_STATE
; j
++) {
4889 if(object
->changed
.samplerState
[i
][j
]) {
4890 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= i
;
4891 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= j
;
4892 object
->num_contained_sampler_states
++;
4897 *ppStateBlock
= (IWineD3DStateBlock
*) object
;
4898 This
->isRecordingState
= FALSE
;
4899 This
->updateStateBlock
= This
->stateBlock
;
4900 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
4901 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4902 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
4907 * Scene related functions
4909 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4910 /* At the moment we have no need for any functionality at the beginning
4912 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4913 TRACE("(%p)\n", This
);
4916 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4917 return WINED3DERR_INVALIDCALL
;
4919 This
->inScene
= TRUE
;
4923 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
) {
4924 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4925 TRACE("(%p)\n", This
);
4927 if(!This
->inScene
) {
4928 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4929 return WINED3DERR_INVALIDCALL
;
4932 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
4933 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4936 checkGLcall("glFlush");
4939 This
->inScene
= FALSE
;
4943 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
4944 CONST RECT
* pSourceRect
, CONST RECT
* pDestRect
,
4945 HWND hDestWindowOverride
, CONST RGNDATA
* pDirtyRegion
) {
4946 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4947 IWineD3DSwapChain
*swapChain
= NULL
;
4949 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
4951 TRACE("(%p) Presenting the frame\n", This
);
4953 for(i
= 0 ; i
< swapchains
; i
++) {
4955 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, &swapChain
);
4956 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
4957 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
4958 IWineD3DSwapChain_Release(swapChain
);
4964 /* Not called from the VTable (internal subroutine) */
4965 HRESULT
IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl
*This
, IWineD3DSurfaceImpl
*target
, DWORD Count
,
4966 CONST WINED3DRECT
* pRects
, DWORD Flags
, WINED3DCOLOR Color
,
4967 float Z
, DWORD Stencil
) {
4968 GLbitfield glMask
= 0;
4970 WINED3DRECT curRect
;
4972 WINED3DVIEWPORT
*vp
= &This
->stateBlock
->viewport
;
4973 UINT drawable_width
, drawable_height
;
4974 IWineD3DSurfaceImpl
*depth_stencil
= (IWineD3DSurfaceImpl
*) This
->stencilBufferTarget
;
4976 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4977 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4978 * for the cleared parts, and the untouched parts.
4980 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4981 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4982 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4983 * checking all this if the dest surface is in the drawable anyway.
4985 if((Flags
& WINED3DCLEAR_TARGET
) && !(target
->Flags
& SFLAG_INDRAWABLE
)) {
4987 if(vp
->X
!= 0 || vp
->Y
!= 0 ||
4988 vp
->Width
< target
->currentDesc
.Width
|| vp
->Height
< target
->currentDesc
.Height
) {
4989 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
4992 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
4993 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
4994 This
->stateBlock
->scissorRect
.right
< target
->currentDesc
.Width
||
4995 This
->stateBlock
->scissorRect
.bottom
< target
->currentDesc
.Height
)) {
4996 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
4999 if(Count
> 0 && pRects
&& (
5000 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
5001 pRects
[0].x2
< target
->currentDesc
.Width
||
5002 pRects
[0].y2
< target
->currentDesc
.Height
)) {
5003 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
5010 target
->get_drawable_size(target
, &drawable_width
, &drawable_height
);
5012 ActivateContext(This
, (IWineD3DSurface
*) target
, CTXUSAGE_CLEAR
);
5015 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
5016 apply_fbo_state((IWineD3DDevice
*) This
);
5019 /* Only set the values up once, as they are not changing */
5020 if (Flags
& WINED3DCLEAR_STENCIL
) {
5021 glClearStencil(Stencil
);
5022 checkGLcall("glClearStencil");
5023 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
5024 glStencilMask(0xFFFFFFFF);
5027 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
5028 DWORD location
= This
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
5029 glDepthMask(GL_TRUE
);
5031 checkGLcall("glClearDepth");
5032 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
5033 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZWRITEENABLE
));
5035 if (vp
->X
!= 0 || vp
->Y
!= 0 ||
5036 vp
->Width
< depth_stencil
->currentDesc
.Width
|| vp
->Height
< depth_stencil
->currentDesc
.Height
) {
5037 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5039 else if (This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
5040 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
5041 This
->stateBlock
->scissorRect
.right
< depth_stencil
->currentDesc
.Width
||
5042 This
->stateBlock
->scissorRect
.bottom
< depth_stencil
->currentDesc
.Height
)) {
5043 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5045 else if (Count
> 0 && pRects
&& (
5046 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
5047 pRects
[0].x2
< depth_stencil
->currentDesc
.Width
||
5048 pRects
[0].y2
< depth_stencil
->currentDesc
.Height
)) {
5049 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5053 if (Flags
& WINED3DCLEAR_TARGET
) {
5054 TRACE("Clearing screen with glClear to color %x\n", Color
);
5055 glClearColor(D3DCOLOR_R(Color
),
5059 checkGLcall("glClearColor");
5061 /* Clear ALL colors! */
5062 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5063 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
5066 vp_rect
.left
= vp
->X
;
5067 vp_rect
.top
= vp
->Y
;
5068 vp_rect
.right
= vp
->X
+ vp
->Width
;
5069 vp_rect
.bottom
= vp
->Y
+ vp
->Height
;
5070 if (!(Count
> 0 && pRects
)) {
5071 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
5072 IntersectRect(&vp_rect
, &vp_rect
, &This
->stateBlock
->scissorRect
);
5074 if(This
->render_offscreen
) {
5075 glScissor(vp_rect
.left
, vp_rect
.top
,
5076 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
5078 glScissor(vp_rect
.left
, drawable_height
- vp_rect
.bottom
,
5079 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
5081 checkGLcall("glScissor");
5083 checkGLcall("glClear");
5085 /* Now process each rect in turn */
5086 for (i
= 0; i
< Count
; i
++) {
5087 /* Note gl uses lower left, width/height */
5088 IntersectRect((RECT
*) &curRect
, &vp_rect
, (RECT
*) &pRects
[i
]);
5089 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
5090 IntersectRect((RECT
*) &curRect
, (RECT
*) &curRect
, &This
->stateBlock
->scissorRect
);
5092 TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This
,
5093 pRects
[i
].x1
, pRects
[i
].y1
, pRects
[i
].x2
, pRects
[i
].y2
,
5094 curRect
.x1
, (target
->currentDesc
.Height
- curRect
.y2
),
5095 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5097 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5098 * The rectangle is not cleared, no error is returned, but further rectanlges are
5099 * still cleared if they are valid
5101 if(curRect
.x1
> curRect
.x2
|| curRect
.y1
> curRect
.y2
) {
5102 TRACE("Rectangle with negative dimensions, ignoring\n");
5106 if(This
->render_offscreen
) {
5107 glScissor(curRect
.x1
, curRect
.y1
,
5108 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5110 glScissor(curRect
.x1
, drawable_height
- curRect
.y2
,
5111 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5113 checkGLcall("glScissor");
5116 checkGLcall("glClear");
5120 /* Restore the old values (why..?) */
5121 if (Flags
& WINED3DCLEAR_STENCIL
) {
5122 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
5124 if (Flags
& WINED3DCLEAR_TARGET
) {
5125 DWORD mask
= This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
];
5126 glColorMask(mask
& WINED3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
5127 mask
& WINED3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
5128 mask
& WINED3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
5129 mask
& WINED3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
5131 /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5132 * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5134 IWineD3DSurface_ModifyLocation(This
->lastActiveRenderTarget
, SFLAG_INDRAWABLE
, TRUE
);
5135 /* TODO: Move the fbo logic into ModifyLocation() */
5136 if(This
->render_offscreen
&& wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
5137 target
->Flags
|= SFLAG_INTEXTURE
;
5140 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
5141 /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
5142 DWORD location
= This
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
5143 surface_modify_ds_location(This
->stencilBufferTarget
, location
);
5151 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST WINED3DRECT
* pRects
,
5152 DWORD Flags
, WINED3DCOLOR Color
, float Z
, DWORD Stencil
) {
5153 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5154 IWineD3DSurfaceImpl
*target
= (IWineD3DSurfaceImpl
*)This
->render_targets
[0];
5156 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This
,
5157 Count
, pRects
, Flags
, Color
, Z
, Stencil
);
5159 if(Flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && This
->stencilBufferTarget
== NULL
) {
5160 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5161 /* TODO: What about depth stencil buffers without stencil bits? */
5162 return WINED3DERR_INVALIDCALL
;
5165 return IWineD3DDeviceImpl_ClearSurface(This
, target
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
5171 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
,
5172 UINT PrimitiveCount
) {
5174 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5176 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This
, PrimitiveType
,
5177 debug_d3dprimitivetype(PrimitiveType
),
5178 StartVertex
, PrimitiveCount
);
5180 if(!This
->stateBlock
->vertexDecl
) {
5181 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5182 return WINED3DERR_INVALIDCALL
;
5185 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5186 if(This
->stateBlock
->streamIsUP
) {
5187 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5188 This
->stateBlock
->streamIsUP
= FALSE
;
5191 if(This
->stateBlock
->loadBaseVertexIndex
!= 0) {
5192 This
->stateBlock
->loadBaseVertexIndex
= 0;
5193 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5195 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5196 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, StartVertex
, 0/* NumVertices */, -1 /* indxStart */,
5197 0 /* indxSize */, NULL
/* indxData */, 0 /* minIndex */);
5201 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5202 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
,
5203 WINED3DPRIMITIVETYPE PrimitiveType
,
5204 UINT minIndex
, UINT NumVertices
, UINT startIndex
, UINT primCount
) {
5206 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5208 IWineD3DIndexBuffer
*pIB
;
5209 WINED3DINDEXBUFFER_DESC IdxBufDsc
;
5212 pIB
= This
->stateBlock
->pIndexData
;
5214 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5215 * without an index buffer set. (The first time at least...)
5216 * D3D8 simply dies, but I doubt it can do much harm to return
5217 * D3DERR_INVALIDCALL there as well. */
5218 ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This
);
5219 return WINED3DERR_INVALIDCALL
;
5222 if(!This
->stateBlock
->vertexDecl
) {
5223 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5224 return WINED3DERR_INVALIDCALL
;
5227 if(This
->stateBlock
->streamIsUP
) {
5228 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5229 This
->stateBlock
->streamIsUP
= FALSE
;
5231 vbo
= ((IWineD3DIndexBufferImpl
*) pIB
)->vbo
;
5233 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This
,
5234 PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5235 minIndex
, NumVertices
, startIndex
, primCount
);
5237 IWineD3DIndexBuffer_GetDesc(pIB
, &IdxBufDsc
);
5238 if (IdxBufDsc
.Format
== WINED3DFMT_INDEX16
) {
5244 if(This
->stateBlock
->loadBaseVertexIndex
!= This
->stateBlock
->baseVertexIndex
) {
5245 This
->stateBlock
->loadBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
5246 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5249 drawPrimitive(iface
, PrimitiveType
, primCount
, 0, NumVertices
, startIndex
,
5250 idxStride
, vbo
? NULL
: ((IWineD3DIndexBufferImpl
*) pIB
)->resource
.allocatedMemory
, minIndex
);
5255 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
,
5256 UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
,
5257 UINT VertexStreamZeroStride
) {
5258 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5259 IWineD3DVertexBuffer
*vb
;
5261 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This
, PrimitiveType
,
5262 debug_d3dprimitivetype(PrimitiveType
),
5263 PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5265 if(!This
->stateBlock
->vertexDecl
) {
5266 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5267 return WINED3DERR_INVALIDCALL
;
5270 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5271 vb
= This
->stateBlock
->streamSource
[0];
5272 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5273 if(vb
) IWineD3DVertexBuffer_Release(vb
);
5274 This
->stateBlock
->streamOffset
[0] = 0;
5275 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5276 This
->stateBlock
->streamIsUP
= TRUE
;
5277 This
->stateBlock
->loadBaseVertexIndex
= 0;
5279 /* TODO: Only mark dirty if drawing from a different UP address */
5280 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5282 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* start vertex */, 0 /* NumVertices */,
5283 0 /* indxStart*/, 0 /* indxSize*/, NULL
/* indxData */, 0 /* indxMin */);
5285 /* MSDN specifies stream zero settings must be set to NULL */
5286 This
->stateBlock
->streamStride
[0] = 0;
5287 This
->stateBlock
->streamSource
[0] = NULL
;
5289 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5290 * the new stream sources or use UP drawing again
5295 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
,
5296 UINT MinVertexIndex
, UINT NumVertices
,
5297 UINT PrimitiveCount
, CONST
void* pIndexData
,
5298 WINED3DFORMAT IndexDataFormat
,CONST
void* pVertexStreamZeroData
,
5299 UINT VertexStreamZeroStride
) {
5301 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5302 IWineD3DVertexBuffer
*vb
;
5303 IWineD3DIndexBuffer
*ib
;
5305 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5306 This
, PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5307 MinVertexIndex
, NumVertices
, PrimitiveCount
, pIndexData
,
5308 IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5310 if(!This
->stateBlock
->vertexDecl
) {
5311 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5312 return WINED3DERR_INVALIDCALL
;
5315 if (IndexDataFormat
== WINED3DFMT_INDEX16
) {
5321 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5322 vb
= This
->stateBlock
->streamSource
[0];
5323 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5324 if(vb
) IWineD3DVertexBuffer_Release(vb
);
5325 This
->stateBlock
->streamIsUP
= TRUE
;
5326 This
->stateBlock
->streamOffset
[0] = 0;
5327 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5329 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5330 This
->stateBlock
->baseVertexIndex
= 0;
5331 This
->stateBlock
->loadBaseVertexIndex
= 0;
5332 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5333 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5334 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5336 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* vertexStart */, NumVertices
, 0 /* indxStart */, idxStride
, pIndexData
, MinVertexIndex
);
5338 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5339 This
->stateBlock
->streamSource
[0] = NULL
;
5340 This
->stateBlock
->streamStride
[0] = 0;
5341 ib
= This
->stateBlock
->pIndexData
;
5343 IWineD3DIndexBuffer_Release(ib
);
5344 This
->stateBlock
->pIndexData
= NULL
;
5346 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5347 * SetStreamSource to specify a vertex buffer
5353 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, WineDirect3DVertexStridedData
*DrawPrimStrideData
) {
5354 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5356 /* Mark the state dirty until we have nicer tracking
5357 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5360 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5361 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5362 This
->stateBlock
->baseVertexIndex
= 0;
5363 This
->up_strided
= DrawPrimStrideData
;
5364 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, 0, 0, NULL
, 0);
5365 This
->up_strided
= NULL
;
5369 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
, WineDirect3DVertexStridedData
*DrawPrimStrideData
, UINT NumVertices
, CONST
void *pIndexData
, WINED3DFORMAT IndexDataFormat
) {
5370 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5371 DWORD idxSize
= (IndexDataFormat
== WINED3DFMT_INDEX32
? 4 : 2);
5373 /* Mark the state dirty until we have nicer tracking
5374 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5377 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5378 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5379 This
->stateBlock
->streamIsUP
= TRUE
;
5380 This
->stateBlock
->baseVertexIndex
= 0;
5381 This
->up_strided
= DrawPrimStrideData
;
5382 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize
, pIndexData
, 0 /* minindex */);
5383 This
->up_strided
= NULL
;
5387 static HRESULT
IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice
*iface
, IWineD3DVolume
*pSourceVolume
, IWineD3DVolume
*pDestinationVolume
) {
5388 /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5389 * not callable by the app directly no parameter validation checks are needed here.
5391 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5392 WINED3DLOCKED_BOX src
;
5393 WINED3DLOCKED_BOX dst
;
5395 TRACE("(%p)->(%p, %p)\n", This
, pSourceVolume
, pDestinationVolume
);
5397 /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5398 * dirtification to improve loading performance.
5400 hr
= IWineD3DVolume_LockBox(pSourceVolume
, &src
, NULL
, WINED3DLOCK_READONLY
);
5401 if(FAILED(hr
)) return hr
;
5402 hr
= IWineD3DVolume_LockBox(pDestinationVolume
, &dst
, NULL
, WINED3DLOCK_DISCARD
);
5404 IWineD3DVolume_UnlockBox(pSourceVolume
);
5408 memcpy(dst
.pBits
, src
.pBits
, ((IWineD3DVolumeImpl
*) pDestinationVolume
)->resource
.size
);
5410 hr
= IWineD3DVolume_UnlockBox(pDestinationVolume
);
5412 IWineD3DVolume_UnlockBox(pSourceVolume
);
5414 hr
= IWineD3DVolume_UnlockBox(pSourceVolume
);
5419 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5420 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice
*iface
, IWineD3DBaseTexture
*pSourceTexture
, IWineD3DBaseTexture
*pDestinationTexture
){
5421 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5422 HRESULT hr
= WINED3D_OK
;
5423 WINED3DRESOURCETYPE sourceType
;
5424 WINED3DRESOURCETYPE destinationType
;
5427 /* TODO: think about moving the code into IWineD3DBaseTexture */
5429 TRACE("(%p) Source %p Destination %p\n", This
, pSourceTexture
, pDestinationTexture
);
5431 /* verify that the source and destination textures aren't NULL */
5432 if (NULL
== pSourceTexture
|| NULL
== pDestinationTexture
) {
5433 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5434 This
, pSourceTexture
, pDestinationTexture
);
5435 hr
= WINED3DERR_INVALIDCALL
;
5438 if (pSourceTexture
== pDestinationTexture
) {
5439 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5440 This
, pSourceTexture
, pDestinationTexture
);
5441 hr
= WINED3DERR_INVALIDCALL
;
5443 /* Verify that the source and destination textures are the same type */
5444 sourceType
= IWineD3DBaseTexture_GetType(pSourceTexture
);
5445 destinationType
= IWineD3DBaseTexture_GetType(pDestinationTexture
);
5447 if (sourceType
!= destinationType
) {
5448 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5450 hr
= WINED3DERR_INVALIDCALL
;
5453 /* check that both textures have the identical numbers of levels */
5454 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture
)) {
5455 WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This
, pSourceTexture
, pDestinationTexture
);
5456 hr
= WINED3DERR_INVALIDCALL
;
5459 if (WINED3D_OK
== hr
) {
5461 /* Make sure that the destination texture is loaded */
5462 IWineD3DBaseTexture_PreLoad(pDestinationTexture
);
5464 /* Update every surface level of the texture */
5465 levels
= IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
);
5467 switch (sourceType
) {
5468 case WINED3DRTYPE_TEXTURE
:
5470 IWineD3DSurface
*srcSurface
;
5471 IWineD3DSurface
*destSurface
;
5473 for (i
= 0 ; i
< levels
; ++i
) {
5474 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pSourceTexture
, i
, &srcSurface
);
5475 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pDestinationTexture
, i
, &destSurface
);
5476 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5477 IWineD3DSurface_Release(srcSurface
);
5478 IWineD3DSurface_Release(destSurface
);
5479 if (WINED3D_OK
!= hr
) {
5480 WARN("(%p) : Call to update surface failed\n", This
);
5486 case WINED3DRTYPE_CUBETEXTURE
:
5488 IWineD3DSurface
*srcSurface
;
5489 IWineD3DSurface
*destSurface
;
5490 WINED3DCUBEMAP_FACES faceType
;
5492 for (i
= 0 ; i
< levels
; ++i
) {
5493 /* Update each cube face */
5494 for (faceType
= WINED3DCUBEMAP_FACE_POSITIVE_X
; faceType
<= WINED3DCUBEMAP_FACE_NEGATIVE_Z
; ++faceType
){
5495 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pSourceTexture
, faceType
, i
, &srcSurface
);
5496 if (WINED3D_OK
!= hr
) {
5497 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5499 TRACE("Got srcSurface %p\n", srcSurface
);
5501 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pDestinationTexture
, faceType
, i
, &destSurface
);
5502 if (WINED3D_OK
!= hr
) {
5503 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5505 TRACE("Got desrSurface %p\n", destSurface
);
5507 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5508 IWineD3DSurface_Release(srcSurface
);
5509 IWineD3DSurface_Release(destSurface
);
5510 if (WINED3D_OK
!= hr
) {
5511 WARN("(%p) : Call to update surface failed\n", This
);
5519 case WINED3DRTYPE_VOLUMETEXTURE
:
5521 IWineD3DVolume
*srcVolume
= NULL
;
5522 IWineD3DVolume
*destVolume
= NULL
;
5524 for (i
= 0 ; i
< levels
; ++i
) {
5525 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)pSourceTexture
, i
, &srcVolume
);
5526 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)pDestinationTexture
, i
, &destVolume
);
5527 hr
= IWineD3DDeviceImpl_UpdateVolume(iface
, srcVolume
, destVolume
);
5528 IWineD3DVolume_Release(srcVolume
);
5529 IWineD3DVolume_Release(destVolume
);
5530 if (WINED3D_OK
!= hr
) {
5531 WARN("(%p) : Call to update volume failed\n", This
);
5539 FIXME("(%p) : Unsupported source and destination type\n", This
);
5540 hr
= WINED3DERR_INVALIDCALL
;
5547 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
5548 IWineD3DSwapChain
*swapChain
;
5550 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5551 if(hr
== WINED3D_OK
) {
5552 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
5553 IWineD3DSwapChain_Release(swapChain
);
5558 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
5559 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5560 /* return a sensible default */
5562 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5563 FIXME("(%p) : stub\n", This
);
5567 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl
*device
)
5571 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
5572 IWineD3DBaseTextureImpl
*texture
= (IWineD3DBaseTextureImpl
*)device
->stateBlock
->textures
[i
];
5573 if (texture
&& (texture
->resource
.format
== WINED3DFMT_P8
|| texture
->resource
.format
== WINED3DFMT_A8P8
)) {
5574 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SAMPLER(i
));
5579 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
5580 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5583 PALETTEENTRY
**palettes
;
5585 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5587 if (PaletteNumber
>= MAX_PALETTES
) {
5588 ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5589 return WINED3DERR_INVALIDCALL
;
5592 if (PaletteNumber
>= This
->NumberOfPalettes
) {
5593 NewSize
= This
->NumberOfPalettes
;
5596 } while(PaletteNumber
>= NewSize
);
5597 palettes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->palettes
, sizeof(PALETTEENTRY
*) * NewSize
);
5599 ERR("Out of memory!\n");
5600 return E_OUTOFMEMORY
;
5602 This
->palettes
= palettes
;
5603 This
->NumberOfPalettes
= NewSize
;
5606 if (!This
->palettes
[PaletteNumber
]) {
5607 This
->palettes
[PaletteNumber
] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
5608 if (!This
->palettes
[PaletteNumber
]) {
5609 ERR("Out of memory!\n");
5610 return E_OUTOFMEMORY
;
5614 for (j
= 0; j
< 256; ++j
) {
5615 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
5616 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
5617 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
5618 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
5620 if (PaletteNumber
== This
->currentPalette
) dirtify_p8_texture_samplers(This
);
5621 TRACE("(%p) : returning\n", This
);
5625 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
5626 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5628 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5629 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5630 /* What happens in such situation isn't documented; Native seems to silently abort
5631 on such conditions. Return Invalid Call. */
5632 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5633 return WINED3DERR_INVALIDCALL
;
5635 for (j
= 0; j
< 256; ++j
) {
5636 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
5637 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
5638 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
5639 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
5641 TRACE("(%p) : returning\n", This
);
5645 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
5646 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5647 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5648 /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5649 (tested with reference rasterizer). Return Invalid Call. */
5650 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5651 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5652 return WINED3DERR_INVALIDCALL
;
5654 /*TODO: stateblocks */
5655 if (This
->currentPalette
!= PaletteNumber
) {
5656 This
->currentPalette
= PaletteNumber
;
5657 dirtify_p8_texture_samplers(This
);
5659 TRACE("(%p) : returning\n", This
);
5663 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
5664 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5665 if (PaletteNumber
== NULL
) {
5666 WARN("(%p) : returning Invalid Call\n", This
);
5667 return WINED3DERR_INVALIDCALL
;
5669 /*TODO: stateblocks */
5670 *PaletteNumber
= This
->currentPalette
;
5671 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
5675 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
5676 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5677 static BOOL showFixmes
= TRUE
;
5679 FIXME("(%p) : stub\n", This
);
5683 This
->softwareVertexProcessing
= bSoftware
;
5688 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
5689 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5690 static BOOL showFixmes
= TRUE
;
5692 FIXME("(%p) : stub\n", This
);
5695 return This
->softwareVertexProcessing
;
5699 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DRASTER_STATUS
* pRasterStatus
) {
5700 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5701 IWineD3DSwapChain
*swapChain
;
5704 TRACE("(%p) : SwapChain %d returning %p\n", This
, iSwapChain
, pRasterStatus
);
5706 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5707 if(hr
== WINED3D_OK
){
5708 hr
= IWineD3DSwapChain_GetRasterStatus(swapChain
, pRasterStatus
);
5709 IWineD3DSwapChain_Release(swapChain
);
5711 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This
);
5717 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
) {
5718 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5719 static BOOL showfixmes
= TRUE
;
5720 if(nSegments
!= 0.0f
) {
5722 FIXME("(%p) : stub nSegments(%f)\n", This
, nSegments
);
5729 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
) {
5730 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5731 static BOOL showfixmes
= TRUE
;
5733 FIXME("(%p) : stub returning(%f)\n", This
, 0.0f
);
5739 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
5740 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5741 /** TODO: remove casts to IWineD3DSurfaceImpl
5742 * NOTE: move code to surface to accomplish this
5743 ****************************************/
5744 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
5745 int srcWidth
, srcHeight
;
5746 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
5747 WINED3DFORMAT destFormat
, srcFormat
;
5749 int srcLeft
, destLeft
, destTop
;
5750 WINED3DPOOL srcPool
, destPool
;
5752 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5753 glDescriptor
*glDescription
= NULL
;
5757 CONVERT_TYPES convert
= NO_CONVERSION
;
5759 WINED3DSURFACE_DESC winedesc
;
5761 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This
, pSourceSurface
, pSourceRect
, pDestinationSurface
, pDestPoint
);
5762 memset(&winedesc
, 0, sizeof(winedesc
));
5763 winedesc
.Width
= &srcSurfaceWidth
;
5764 winedesc
.Height
= &srcSurfaceHeight
;
5765 winedesc
.Pool
= &srcPool
;
5766 winedesc
.Format
= &srcFormat
;
5768 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
5770 winedesc
.Width
= &destSurfaceWidth
;
5771 winedesc
.Height
= &destSurfaceHeight
;
5772 winedesc
.Pool
= &destPool
;
5773 winedesc
.Format
= &destFormat
;
5774 winedesc
.Size
= &destSize
;
5776 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
5778 if(srcPool
!= WINED3DPOOL_SYSTEMMEM
|| destPool
!= WINED3DPOOL_DEFAULT
){
5779 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface
, pDestinationSurface
);
5780 return WINED3DERR_INVALIDCALL
;
5783 /* This call loads the opengl surface directly, instead of copying the surface to the
5784 * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5785 * copy in sysmem and use regular surface loading.
5787 d3dfmt_get_conv((IWineD3DSurfaceImpl
*) pDestinationSurface
, FALSE
, TRUE
,
5788 &dummy
, &dummy
, &dummy
, &convert
, &bpp
, FALSE
);
5789 if(convert
!= NO_CONVERSION
) {
5790 return IWineD3DSurface_BltFast(pDestinationSurface
,
5791 pDestPoint
? pDestPoint
->x
: 0,
5792 pDestPoint
? pDestPoint
->y
: 0,
5793 pSourceSurface
, (RECT
*) pSourceRect
, 0);
5796 if (destFormat
== WINED3DFMT_UNKNOWN
) {
5797 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
5798 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
5800 /* Get the update surface description */
5801 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
5804 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
5808 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
5809 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5810 checkGLcall("glActiveTextureARB");
5813 /* Make sure the surface is loaded and up to date */
5814 IWineD3DSurface_PreLoad(pDestinationSurface
);
5816 IWineD3DSurface_GetGlDesc(pDestinationSurface
, &glDescription
);
5818 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5819 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
5820 srcHeight
= pSourceRect
? pSourceRect
->bottom
- pSourceRect
->top
: srcSurfaceHeight
;
5821 srcLeft
= pSourceRect
? pSourceRect
->left
: 0;
5822 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
5823 destTop
= pDestPoint
? pDestPoint
->y
: 0;
5826 /* This function doesn't support compressed textures
5827 the pitch is just bytesPerPixel * width */
5828 if(srcWidth
!= srcSurfaceWidth
|| srcLeft
){
5829 rowoffset
= srcSurfaceWidth
* pSrcSurface
->bytesPerPixel
;
5830 offset
+= srcLeft
* pSrcSurface
->bytesPerPixel
;
5831 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5833 /* TODO DXT formats */
5835 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
5836 offset
+= pSourceRect
->top
* srcSurfaceWidth
* pSrcSurface
->bytesPerPixel
;
5838 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5840 ,glDescription
->level
5845 ,glDescription
->glFormat
5846 ,glDescription
->glType
5847 ,IWineD3DSurface_GetData(pSourceSurface
)
5851 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
5853 /* need to lock the surface to get the data */
5854 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5857 /* TODO: Cube and volume support */
5859 /* not a whole row so we have to do it a line at a time */
5862 /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5863 const unsigned char* data
=((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
5865 for(j
= destTop
; j
< (srcHeight
+ destTop
) ; j
++){
5867 glTexSubImage2D(glDescription
->target
5868 ,glDescription
->level
5873 ,glDescription
->glFormat
5874 ,glDescription
->glType
5875 ,data
/* could be quicker using */
5880 } else { /* Full width, so just write out the whole texture */
5882 if (WINED3DFMT_DXT1
== destFormat
||
5883 WINED3DFMT_DXT2
== destFormat
||
5884 WINED3DFMT_DXT3
== destFormat
||
5885 WINED3DFMT_DXT4
== destFormat
||
5886 WINED3DFMT_DXT5
== destFormat
) {
5887 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
5888 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
) {
5889 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5890 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5891 } if (destFormat
!= srcFormat
) {
5892 FIXME("Updating mixed format compressed texture is not curretly support\n");
5894 GL_EXTCALL(glCompressedTexImage2DARB
)(glDescription
->target
,
5895 glDescription
->level
,
5896 glDescription
->glFormatInternal
,
5901 IWineD3DSurface_GetData(pSourceSurface
));
5904 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5909 glTexSubImage2D(glDescription
->target
5910 ,glDescription
->level
5915 ,glDescription
->glFormat
5916 ,glDescription
->glType
5917 ,IWineD3DSurface_GetData(pSourceSurface
)
5921 checkGLcall("glTexSubImage2D");
5925 IWineD3DSurface_ModifyLocation(pDestinationSurface
, SFLAG_INTEXTURE
, TRUE
);
5926 sampler
= This
->rev_tex_unit_map
[0];
5927 if (sampler
!= -1) {
5928 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5934 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
5935 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5936 struct WineD3DRectPatch
*patch
;
5940 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
5942 if(!(Handle
|| pRectPatchInfo
)) {
5943 /* TODO: Write a test for the return value, thus the FIXME */
5944 FIXME("Both Handle and pRectPatchInfo are NULL\n");
5945 return WINED3DERR_INVALIDCALL
;
5949 i
= PATCHMAP_HASHFUNC(Handle
);
5951 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5952 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5953 if(patch
->Handle
== Handle
) {
5960 TRACE("Patch does not exist. Creating a new one\n");
5961 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5962 patch
->Handle
= Handle
;
5963 list_add_head(&This
->patches
[i
], &patch
->entry
);
5965 TRACE("Found existing patch %p\n", patch
);
5968 /* Since opengl does not load tesselated vertex attributes into numbered vertex
5969 * attributes we have to tesselate, read back, and draw. This needs a patch
5970 * management structure instance. Create one.
5972 * A possible improvement is to check if a vertex shader is used, and if not directly
5975 FIXME("Drawing an uncached patch. This is slow\n");
5976 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5979 if(pNumSegs
[0] != patch
->numSegs
[0] || pNumSegs
[1] != patch
->numSegs
[1] ||
5980 pNumSegs
[2] != patch
->numSegs
[2] || pNumSegs
[3] != patch
->numSegs
[3] ||
5981 (pRectPatchInfo
&& memcmp(pRectPatchInfo
, &patch
->RectPatchInfo
, sizeof(*pRectPatchInfo
)) != 0) ) {
5983 TRACE("Tesselation density or patch info changed, retesselating\n");
5985 if(pRectPatchInfo
) {
5986 patch
->RectPatchInfo
= *pRectPatchInfo
;
5988 patch
->numSegs
[0] = pNumSegs
[0];
5989 patch
->numSegs
[1] = pNumSegs
[1];
5990 patch
->numSegs
[2] = pNumSegs
[2];
5991 patch
->numSegs
[3] = pNumSegs
[3];
5993 hr
= tesselate_rectpatch(This
, patch
);
5995 WARN("Patch tesselation failed\n");
5997 /* Do not release the handle to store the params of the patch */
5999 HeapFree(GetProcessHeap(), 0, patch
);
6005 This
->currentPatch
= patch
;
6006 IWineD3DDevice_DrawPrimitiveStrided(iface
, WINED3DPT_TRIANGLELIST
, patch
->numSegs
[0] * patch
->numSegs
[1] * 2, &patch
->strided
);
6007 This
->currentPatch
= NULL
;
6009 /* Destroy uncached patches */
6011 HeapFree(GetProcessHeap(), 0, patch
->mem
);
6012 HeapFree(GetProcessHeap(), 0, patch
);
6017 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DTRIPATCH_INFO
* pTriPatchInfo
) {
6018 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6019 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This
, Handle
, pNumSegs
, pTriPatchInfo
);
6020 FIXME("(%p) : Stub\n", This
);
6024 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
6025 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6027 struct WineD3DRectPatch
*patch
;
6029 TRACE("(%p) Handle(%d)\n", This
, Handle
);
6031 i
= PATCHMAP_HASHFUNC(Handle
);
6032 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
6033 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
6034 if(patch
->Handle
== Handle
) {
6035 TRACE("Deleting patch %p\n", patch
);
6036 list_remove(&patch
->entry
);
6037 HeapFree(GetProcessHeap(), 0, patch
->mem
);
6038 HeapFree(GetProcessHeap(), 0, patch
);
6043 /* TODO: Write a test for the return value */
6044 FIXME("Attempt to destroy nonexistent patch\n");
6045 return WINED3DERR_INVALIDCALL
;
6048 static IWineD3DSwapChain
*get_swapchain(IWineD3DSurface
*target
) {
6050 IWineD3DSwapChain
*swapchain
;
6052 hr
= IWineD3DSurface_GetContainer(target
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
6053 if (SUCCEEDED(hr
)) {
6054 IWineD3DSwapChain_Release((IUnknown
*)swapchain
);
6061 void bind_fbo(IWineD3DDevice
*iface
, GLenum target
, GLuint
*fbo
) {
6062 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6065 GL_EXTCALL(glGenFramebuffersEXT(1, fbo
));
6066 checkGLcall("glGenFramebuffersEXT()");
6068 GL_EXTCALL(glBindFramebufferEXT(target
, *fbo
));
6069 checkGLcall("glBindFramebuffer()");
6072 /* TODO: Handle stencil attachments */
6073 void attach_depth_stencil_fbo(IWineD3DDeviceImpl
*This
, GLenum fbo_target
, IWineD3DSurface
*depth_stencil
, BOOL use_render_buffer
) {
6074 IWineD3DSurfaceImpl
*depth_stencil_impl
= (IWineD3DSurfaceImpl
*)depth_stencil
;
6076 if (use_render_buffer
&& depth_stencil_impl
->current_renderbuffer
) {
6077 GL_EXTCALL(glFramebufferRenderbufferEXT(fbo_target
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, depth_stencil_impl
->current_renderbuffer
->id
));
6078 checkGLcall("glFramebufferRenderbufferEXT()");
6080 IWineD3DBaseTextureImpl
*texture_impl
;
6081 GLenum texttarget
, target
;
6082 GLint old_binding
= 0;
6084 texttarget
= depth_stencil_impl
->glDescription
.target
;
6085 if(texttarget
== GL_TEXTURE_2D
) {
6086 target
= GL_TEXTURE_2D
;
6087 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &old_binding
);
6088 } else if(texttarget
== GL_TEXTURE_RECTANGLE_ARB
) {
6089 target
= GL_TEXTURE_RECTANGLE_ARB
;
6090 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB
, &old_binding
);
6092 target
= GL_TEXTURE_CUBE_MAP_ARB
;
6093 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB
, &old_binding
);
6096 IWineD3DSurface_PreLoad(depth_stencil
);
6098 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
6099 glTexParameteri(target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
6100 glTexParameteri(target
, GL_DEPTH_TEXTURE_MODE_ARB
, GL_LUMINANCE
);
6101 glBindTexture(target
, old_binding
);
6103 /* Update base texture states array */
6104 if (SUCCEEDED(IWineD3DSurface_GetContainer(depth_stencil
, &IID_IWineD3DBaseTexture
, (void **)&texture_impl
))) {
6105 texture_impl
->baseTexture
.states
[WINED3DTEXSTA_MINFILTER
] = WINED3DTEXF_POINT
;
6106 texture_impl
->baseTexture
.states
[WINED3DTEXSTA_MAGFILTER
] = WINED3DTEXF_POINT
;
6107 if (texture_impl
->baseTexture
.bindCount
) {
6108 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(texture_impl
->baseTexture
.sampler
));
6111 IWineD3DBaseTexture_Release((IWineD3DBaseTexture
*)texture_impl
);
6114 GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target
, GL_DEPTH_ATTACHMENT_EXT
, texttarget
,
6115 depth_stencil_impl
->glDescription
.textureName
, depth_stencil_impl
->glDescription
.level
));
6116 checkGLcall("glFramebufferTexture2DEXT()");
6120 static void attach_surface_fbo(IWineD3DDeviceImpl
*This
, GLenum fbo_target
, DWORD idx
, IWineD3DSurface
*surface
) {
6121 const IWineD3DSurfaceImpl
*surface_impl
= (IWineD3DSurfaceImpl
*)surface
;
6122 IWineD3DBaseTextureImpl
*texture_impl
;
6123 GLenum texttarget
, target
;
6126 texttarget
= surface_impl
->glDescription
.target
;
6127 if(texttarget
== GL_TEXTURE_2D
) {
6128 target
= GL_TEXTURE_2D
;
6129 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &old_binding
);
6130 } else if(texttarget
== GL_TEXTURE_RECTANGLE_ARB
) {
6131 target
= GL_TEXTURE_RECTANGLE_ARB
;
6132 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB
, &old_binding
);
6134 target
= GL_TEXTURE_CUBE_MAP_ARB
;
6135 glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB
, &old_binding
);
6138 IWineD3DSurface_PreLoad(surface
);
6140 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
6141 glTexParameteri(target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
6142 glBindTexture(target
, old_binding
);
6144 /* Update base texture states array */
6145 if (SUCCEEDED(IWineD3DSurface_GetContainer(surface
, &IID_IWineD3DBaseTexture
, (void **)&texture_impl
))) {
6146 texture_impl
->baseTexture
.states
[WINED3DTEXSTA_MINFILTER
] = WINED3DTEXF_POINT
;
6147 texture_impl
->baseTexture
.states
[WINED3DTEXSTA_MAGFILTER
] = WINED3DTEXF_POINT
;
6148 if (texture_impl
->baseTexture
.bindCount
) {
6149 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(texture_impl
->baseTexture
.sampler
));
6152 IWineD3DBaseTexture_Release((IWineD3DBaseTexture
*)texture_impl
);
6155 GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target
, GL_COLOR_ATTACHMENT0_EXT
+ idx
, texttarget
,
6156 surface_impl
->glDescription
.textureName
, surface_impl
->glDescription
.level
));
6158 checkGLcall("attach_surface_fbo");
6161 static void color_fill_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*surface
, CONST WINED3DRECT
*rect
, WINED3DCOLOR color
) {
6162 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6163 IWineD3DSwapChain
*swapchain
;
6165 swapchain
= get_swapchain(surface
);
6169 TRACE("Surface %p is onscreen\n", surface
);
6171 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6172 buffer
= surface_get_gl_buffer(surface
, swapchain
);
6173 glDrawBuffer(buffer
);
6174 checkGLcall("glDrawBuffer()");
6176 TRACE("Surface %p is offscreen\n", surface
);
6177 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->dst_fbo
);
6178 attach_surface_fbo(This
, GL_FRAMEBUFFER_EXT
, 0, surface
);
6179 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6180 checkGLcall("glFramebufferRenderbufferEXT");
6184 glEnable(GL_SCISSOR_TEST
);
6186 glScissor(rect
->x1
, rect
->y1
, rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
6188 glScissor(rect
->x1
, ((IWineD3DSurfaceImpl
*)surface
)->currentDesc
.Height
- rect
->y2
,
6189 rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
6191 checkGLcall("glScissor");
6193 glDisable(GL_SCISSOR_TEST
);
6195 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
6197 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6198 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE
));
6200 glClearColor(D3DCOLOR_R(color
), D3DCOLOR_G(color
), D3DCOLOR_B(color
), D3DCOLOR_A(color
));
6201 glClear(GL_COLOR_BUFFER_BIT
);
6202 checkGLcall("glClear");
6204 if (This
->render_offscreen
) {
6205 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->fbo
);
6207 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6208 checkGLcall("glBindFramebuffer()");
6211 if (swapchain
&& surface
== ((IWineD3DSwapChainImpl
*)swapchain
)->frontBuffer
6212 && ((IWineD3DSwapChainImpl
*)swapchain
)->backBuffer
) {
6213 glDrawBuffer(GL_BACK
);
6214 checkGLcall("glDrawBuffer()");
6218 static inline DWORD
argb_to_fmt(DWORD color
, WINED3DFORMAT destfmt
) {
6219 unsigned int r
, g
, b
, a
;
6222 if(destfmt
== WINED3DFMT_A8R8G8B8
|| destfmt
== WINED3DFMT_X8R8G8B8
||
6223 destfmt
== WINED3DFMT_R8G8B8
)
6226 TRACE("Converting color %08x to format %s\n", color
, debug_d3dformat(destfmt
));
6228 a
= (color
& 0xff000000) >> 24;
6229 r
= (color
& 0x00ff0000) >> 16;
6230 g
= (color
& 0x0000ff00) >> 8;
6231 b
= (color
& 0x000000ff) >> 0;
6235 case WINED3DFMT_R5G6B5
:
6236 if(r
== 0xff && g
== 0xff && b
== 0xff) return 0xffff;
6243 TRACE("Returning %08x\n", ret
);
6246 case WINED3DFMT_X1R5G5B5
:
6247 case WINED3DFMT_A1R5G5B5
:
6256 TRACE("Returning %08x\n", ret
);
6260 TRACE("Returning %08x\n", a
);
6263 case WINED3DFMT_X4R4G4B4
:
6264 case WINED3DFMT_A4R4G4B4
:
6273 TRACE("Returning %08x\n", ret
);
6276 case WINED3DFMT_R3G3B2
:
6283 TRACE("Returning %08x\n", ret
);
6286 case WINED3DFMT_X8B8G8R8
:
6287 case WINED3DFMT_A8B8G8R8
:
6292 TRACE("Returning %08x\n", ret
);
6295 case WINED3DFMT_A2R10G10B10
:
6297 r
= (r
* 1024) / 256;
6298 g
= (g
* 1024) / 256;
6299 b
= (b
* 1024) / 256;
6304 TRACE("Returning %08x\n", ret
);
6307 case WINED3DFMT_A2B10G10R10
:
6309 r
= (r
* 1024) / 256;
6310 g
= (g
* 1024) / 256;
6311 b
= (b
* 1024) / 256;
6316 TRACE("Returning %08x\n", ret
);
6320 FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt
));
6325 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, CONST WINED3DRECT
* pRect
, WINED3DCOLOR color
) {
6326 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6327 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*) pSurface
;
6329 TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This
, pSurface
, pRect
, color
);
6331 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
6332 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6333 return WINED3DERR_INVALIDCALL
;
6336 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
6338 color_fill_fbo(iface
, pSurface
, pRect
, color
);
6342 /* Just forward this to the DirectDraw blitting engine */
6343 memset(&BltFx
, 0, sizeof(BltFx
));
6344 BltFx
.dwSize
= sizeof(BltFx
);
6345 BltFx
.u5
.dwFillColor
= argb_to_fmt(color
, surface
->resource
.format
);
6346 return IWineD3DSurface_Blt(pSurface
, (RECT
*) pRect
, NULL
, NULL
, WINEDDBLT_COLORFILL
, &BltFx
, WINED3DTEXF_NONE
);
6350 /* rendertarget and depth stencil functions */
6351 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
6352 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6354 if (RenderTargetIndex
>= GL_LIMITS(buffers
)) {
6355 ERR("(%p) : Only %d render targets are supported.\n", This
, GL_LIMITS(buffers
));
6356 return WINED3DERR_INVALIDCALL
;
6359 *ppRenderTarget
= This
->render_targets
[RenderTargetIndex
];
6360 TRACE("(%p) : RenderTarget %d Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
6361 /* Note inc ref on returned surface */
6362 if(*ppRenderTarget
!= NULL
)
6363 IWineD3DSurface_AddRef(*ppRenderTarget
);
6367 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice
*iface
, IWineD3DSurface
*Front
, IWineD3DSurface
*Back
) {
6368 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6369 IWineD3DSurfaceImpl
*FrontImpl
= (IWineD3DSurfaceImpl
*) Front
;
6370 IWineD3DSurfaceImpl
*BackImpl
= (IWineD3DSurfaceImpl
*) Back
;
6371 IWineD3DSwapChainImpl
*Swapchain
;
6374 TRACE("(%p)->(%p,%p)\n", This
, FrontImpl
, BackImpl
);
6376 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &Swapchain
);
6377 if(hr
!= WINED3D_OK
) {
6378 ERR("Can't get the swapchain\n");
6382 /* Make sure to release the swapchain */
6383 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) Swapchain
);
6385 if(FrontImpl
&& !(FrontImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) {
6386 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6387 return WINED3DERR_INVALIDCALL
;
6389 else if(BackImpl
&& !(BackImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6390 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6391 return WINED3DERR_INVALIDCALL
;
6394 if(Swapchain
->frontBuffer
!= Front
) {
6395 TRACE("Changing the front buffer from %p to %p\n", Swapchain
->frontBuffer
, Front
);
6397 if(Swapchain
->frontBuffer
)
6398 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, NULL
);
6399 Swapchain
->frontBuffer
= Front
;
6401 if(Swapchain
->frontBuffer
) {
6402 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, (IWineD3DBase
*) Swapchain
);
6406 if(Back
&& !Swapchain
->backBuffer
) {
6407 /* We need memory for the back buffer array - only one back buffer this way */
6408 Swapchain
->backBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*));
6409 if(!Swapchain
->backBuffer
) {
6410 ERR("Out of memory\n");
6411 return E_OUTOFMEMORY
;
6415 if(Swapchain
->backBuffer
[0] != Back
) {
6416 TRACE("Changing the back buffer from %p to %p\n", Swapchain
->backBuffer
, Back
);
6418 /* What to do about the context here in the case of multithreading? Not sure.
6419 * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6422 if(!Swapchain
->backBuffer
[0]) {
6423 /* GL was told to draw to the front buffer at creation,
6426 glDrawBuffer(GL_BACK
);
6427 checkGLcall("glDrawBuffer(GL_BACK)");
6428 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6429 Swapchain
->presentParms
.BackBufferCount
= 1;
6431 /* That makes problems - disable for now */
6432 /* glDrawBuffer(GL_FRONT); */
6433 checkGLcall("glDrawBuffer(GL_FRONT)");
6434 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6435 Swapchain
->presentParms
.BackBufferCount
= 0;
6439 if(Swapchain
->backBuffer
[0])
6440 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], NULL
);
6441 Swapchain
->backBuffer
[0] = Back
;
6443 if(Swapchain
->backBuffer
[0]) {
6444 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], (IWineD3DBase
*) Swapchain
);
6446 HeapFree(GetProcessHeap(), 0, Swapchain
->backBuffer
);
6447 Swapchain
->backBuffer
= NULL
;
6455 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
6456 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6457 *ppZStencilSurface
= This
->stencilBufferTarget
;
6458 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
6460 if(*ppZStencilSurface
!= NULL
) {
6461 /* Note inc ref on returned surface */
6462 IWineD3DSurface_AddRef(*ppZStencilSurface
);
6465 return WINED3DERR_NOTFOUND
;
6469 /* TODO: Handle stencil attachments */
6470 static void set_depth_stencil_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*depth_stencil
) {
6471 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6473 TRACE("Set depth stencil to %p\n", depth_stencil
);
6475 if (depth_stencil
) {
6476 attach_depth_stencil_fbo(This
, GL_FRAMEBUFFER_EXT
, depth_stencil
, TRUE
);
6478 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_TEXTURE_2D
, 0, 0));
6479 checkGLcall("glFramebufferTexture2DEXT()");
6483 static void set_render_target_fbo(IWineD3DDevice
*iface
, DWORD idx
, IWineD3DSurface
*render_target
) {
6484 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6486 TRACE("Set render target %u to %p\n", idx
, render_target
);
6488 if (render_target
) {
6489 attach_surface_fbo(This
, GL_FRAMEBUFFER_EXT
, idx
, render_target
);
6490 This
->draw_buffers
[idx
] = GL_COLOR_ATTACHMENT0_EXT
+ idx
;
6492 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
+ idx
, GL_TEXTURE_2D
, 0, 0));
6493 checkGLcall("glFramebufferTexture2DEXT()");
6495 This
->draw_buffers
[idx
] = GL_NONE
;
6499 static void check_fbo_status(IWineD3DDevice
*iface
) {
6500 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6503 status
= GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
));
6504 if (status
== GL_FRAMEBUFFER_COMPLETE_EXT
) {
6505 TRACE("FBO complete\n");
6507 IWineD3DSurfaceImpl
*attachment
;
6509 FIXME("FBO status %s (%#x)\n", debug_fbostatus(status
), status
);
6511 /* Dump the FBO attachments */
6512 for (i
= 0; i
< GL_LIMITS(buffers
); ++i
) {
6513 attachment
= (IWineD3DSurfaceImpl
*)This
->fbo_color_attachments
[i
];
6515 FIXME("\tColor attachment %d: (%p) %s %ux%u\n", i
, attachment
, debug_d3dformat(attachment
->resource
.format
),
6516 attachment
->pow2Width
, attachment
->pow2Height
);
6519 attachment
= (IWineD3DSurfaceImpl
*)This
->fbo_depth_attachment
;
6521 FIXME("\tDepth attachment: (%p) %s %ux%u\n", attachment
, debug_d3dformat(attachment
->resource
.format
),
6522 attachment
->pow2Width
, attachment
->pow2Height
);
6527 static BOOL
depth_mismatch_fbo(IWineD3DDevice
*iface
) {
6528 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6529 IWineD3DSurfaceImpl
*rt_impl
= (IWineD3DSurfaceImpl
*)This
->render_targets
[0];
6530 IWineD3DSurfaceImpl
*ds_impl
= (IWineD3DSurfaceImpl
*)This
->stencilBufferTarget
;
6532 if (!ds_impl
) return FALSE
;
6534 if (ds_impl
->current_renderbuffer
) {
6535 return (rt_impl
->pow2Width
!= ds_impl
->current_renderbuffer
->width
||
6536 rt_impl
->pow2Height
!= ds_impl
->current_renderbuffer
->height
);
6539 return (rt_impl
->pow2Width
!= ds_impl
->pow2Width
||
6540 rt_impl
->pow2Height
!= ds_impl
->pow2Height
);
6543 void apply_fbo_state(IWineD3DDevice
*iface
) {
6544 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6547 if (This
->render_offscreen
) {
6548 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->fbo
);
6550 /* Apply render targets */
6551 for (i
= 0; i
< GL_LIMITS(buffers
); ++i
) {
6552 IWineD3DSurface
*render_target
= This
->render_targets
[i
];
6553 if (This
->fbo_color_attachments
[i
] != render_target
) {
6554 set_render_target_fbo(iface
, i
, render_target
);
6555 This
->fbo_color_attachments
[i
] = render_target
;
6559 /* Apply depth targets */
6560 if (This
->fbo_depth_attachment
!= This
->stencilBufferTarget
|| depth_mismatch_fbo(iface
)) {
6561 unsigned int w
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->pow2Width
;
6562 unsigned int h
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->pow2Height
;
6564 if (This
->stencilBufferTarget
) {
6565 surface_set_compatible_renderbuffer(This
->stencilBufferTarget
, w
, h
);
6567 set_depth_stencil_fbo(iface
, This
->stencilBufferTarget
);
6568 This
->fbo_depth_attachment
= This
->stencilBufferTarget
;
6571 if (GL_SUPPORT(ARB_DRAW_BUFFERS
)) {
6572 GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers
), This
->draw_buffers
));
6573 checkGLcall("glDrawBuffers()");
6575 glDrawBuffer(This
->draw_buffers
[0]);
6576 checkGLcall("glDrawBuffer()");
6579 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6582 check_fbo_status(iface
);
6585 void stretch_rect_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*src_surface
, WINED3DRECT
*src_rect
,
6586 IWineD3DSurface
*dst_surface
, WINED3DRECT
*dst_rect
, const WINED3DTEXTUREFILTERTYPE filter
, BOOL flip
) {
6587 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6588 GLbitfield mask
= GL_COLOR_BUFFER_BIT
; /* TODO: Support blitting depth/stencil surfaces */
6589 IWineD3DSwapChain
*src_swapchain
, *dst_swapchain
;
6592 TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6593 This
, src_surface
, src_rect
, dst_surface
, dst_rect
, debug_d3dtexturefiltertype(filter
), filter
, flip
);
6594 TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
);
6595 TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
);
6598 case WINED3DTEXF_LINEAR
:
6599 gl_filter
= GL_LINEAR
;
6603 FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter
), filter
);
6604 case WINED3DTEXF_NONE
:
6605 case WINED3DTEXF_POINT
:
6606 gl_filter
= GL_NEAREST
;
6610 /* Attach src surface to src fbo */
6611 src_swapchain
= get_swapchain(src_surface
);
6612 if (src_swapchain
) {
6615 TRACE("Source surface %p is onscreen\n", src_surface
);
6616 ActivateContext(This
, src_surface
, CTXUSAGE_RESOURCELOAD
);
6617 /* Make sure the drawable is up to date. In the offscreen case
6618 * attach_surface_fbo() implicitly takes care of this. */
6619 IWineD3DSurface_LoadLocation(src_surface
, SFLAG_INDRAWABLE
, NULL
);
6622 GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0));
6623 buffer
= surface_get_gl_buffer(src_surface
, src_swapchain
);
6624 glReadBuffer(buffer
);
6625 checkGLcall("glReadBuffer()");
6627 src_rect
->y1
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y1
;
6628 src_rect
->y2
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y2
;
6630 TRACE("Source surface %p is offscreen\n", src_surface
);
6632 bind_fbo(iface
, GL_READ_FRAMEBUFFER_EXT
, &This
->src_fbo
);
6633 attach_surface_fbo(This
, GL_READ_FRAMEBUFFER_EXT
, 0, src_surface
);
6634 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT
);
6635 checkGLcall("glReadBuffer()");
6636 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6637 checkGLcall("glFramebufferRenderbufferEXT");
6641 /* Attach dst surface to dst fbo */
6642 dst_swapchain
= get_swapchain(dst_surface
);
6643 if (dst_swapchain
) {
6646 TRACE("Destination surface %p is onscreen\n", dst_surface
);
6647 ActivateContext(This
, dst_surface
, CTXUSAGE_RESOURCELOAD
);
6648 /* Make sure the drawable is up to date. In the offscreen case
6649 * attach_surface_fbo() implicitly takes care of this. */
6650 IWineD3DSurface_LoadLocation(dst_surface
, SFLAG_INDRAWABLE
, NULL
);
6653 GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, 0));
6654 buffer
= surface_get_gl_buffer(dst_surface
, dst_swapchain
);
6655 glDrawBuffer(buffer
);
6656 checkGLcall("glDrawBuffer()");
6658 dst_rect
->y1
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y1
;
6659 dst_rect
->y2
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y2
;
6661 TRACE("Destination surface %p is offscreen\n", dst_surface
);
6663 /* No src or dst swapchain? Make sure some context is active(multithreading) */
6664 if(!src_swapchain
) {
6665 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6669 bind_fbo(iface
, GL_DRAW_FRAMEBUFFER_EXT
, &This
->dst_fbo
);
6670 attach_surface_fbo(This
, GL_DRAW_FRAMEBUFFER_EXT
, 0, dst_surface
);
6671 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT
);
6672 checkGLcall("glDrawBuffer()");
6673 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6674 checkGLcall("glFramebufferRenderbufferEXT");
6676 glDisable(GL_SCISSOR_TEST
);
6677 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
6680 GL_EXTCALL(glBlitFramebufferEXT(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
6681 dst_rect
->x1
, dst_rect
->y2
, dst_rect
->x2
, dst_rect
->y1
, mask
, gl_filter
));
6682 checkGLcall("glBlitFramebuffer()");
6684 GL_EXTCALL(glBlitFramebufferEXT(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
6685 dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
, mask
, gl_filter
));
6686 checkGLcall("glBlitFramebuffer()");
6689 IWineD3DSurface_ModifyLocation(dst_surface
, SFLAG_INDRAWABLE
, TRUE
);
6691 if (This
->render_offscreen
) {
6692 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->fbo
);
6694 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6695 checkGLcall("glBindFramebuffer()");
6698 /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6699 if (dst_swapchain
&& dst_surface
== ((IWineD3DSwapChainImpl
*)dst_swapchain
)->frontBuffer
6700 && ((IWineD3DSwapChainImpl
*)dst_swapchain
)->backBuffer
) {
6701 glDrawBuffer(GL_BACK
);
6702 checkGLcall("glDrawBuffer()");
6707 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
) {
6708 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6709 WINED3DVIEWPORT viewport
;
6711 TRACE("(%p) : Setting rendertarget %d to %p\n", This
, RenderTargetIndex
, pRenderTarget
);
6713 if (RenderTargetIndex
>= GL_LIMITS(buffers
)) {
6714 WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6715 This
, RenderTargetIndex
, GL_LIMITS(buffers
));
6716 return WINED3DERR_INVALIDCALL
;
6719 /* MSDN says that null disables the render target
6720 but a device must always be associated with a render target
6721 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6723 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
6724 FIXME("Trying to set render target 0 to NULL\n");
6725 return WINED3DERR_INVALIDCALL
;
6727 if (pRenderTarget
&& !(((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6728 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This
,pRenderTarget
);
6729 return WINED3DERR_INVALIDCALL
;
6732 /* If we are trying to set what we already have, don't bother */
6733 if (pRenderTarget
== This
->render_targets
[RenderTargetIndex
]) {
6734 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6737 if(pRenderTarget
) IWineD3DSurface_AddRef(pRenderTarget
);
6738 if(This
->render_targets
[RenderTargetIndex
]) IWineD3DSurface_Release(This
->render_targets
[RenderTargetIndex
]);
6739 This
->render_targets
[RenderTargetIndex
] = pRenderTarget
;
6741 /* Render target 0 is special */
6742 if(RenderTargetIndex
== 0) {
6743 /* Finally, reset the viewport as the MSDN states. */
6744 viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Height
;
6745 viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Width
;
6748 viewport
.MaxZ
= 1.0f
;
6749 viewport
.MinZ
= 0.0f
;
6750 IWineD3DDeviceImpl_SetViewport(iface
, &viewport
);
6751 /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6752 * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6754 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
6759 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
6760 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6761 HRESULT hr
= WINED3D_OK
;
6762 IWineD3DSurface
*tmp
;
6764 TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This
, This
->stencilBufferTarget
, pNewZStencil
);
6766 if (pNewZStencil
== This
->stencilBufferTarget
) {
6767 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6769 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6770 * depending on the renter target implementation being used.
6771 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6772 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6773 * stencil buffer and incur an extra memory overhead
6774 ******************************************************/
6776 if (This
->stencilBufferTarget
) {
6777 ActivateContext(This
, This
->render_targets
[0], CTXUSAGE_RESOURCELOAD
);
6778 surface_load_ds_location(This
->stencilBufferTarget
, SFLAG_DS_OFFSCREEN
);
6779 surface_modify_ds_location(This
->stencilBufferTarget
, SFLAG_DS_OFFSCREEN
);
6782 tmp
= This
->stencilBufferTarget
;
6783 This
->stencilBufferTarget
= pNewZStencil
;
6784 /* should we be calling the parent or the wined3d surface? */
6785 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
6786 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
6789 if((!tmp
&& pNewZStencil
) || (!pNewZStencil
&& tmp
)) {
6790 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6791 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZENABLE
));
6792 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILENABLE
));
6793 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
6800 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
6801 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
6802 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6803 /* TODO: the use of Impl is deprecated. */
6804 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
6805 WINED3DLOCKED_RECT lockedRect
;
6807 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
6809 /* some basic validation checks */
6810 if(This
->cursorTexture
) {
6811 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6813 glDeleteTextures(1, &This
->cursorTexture
);
6815 This
->cursorTexture
= 0;
6818 if ( (pSur
->currentDesc
.Width
== 32) && (pSur
->currentDesc
.Height
== 32) )
6819 This
->haveHardwareCursor
= TRUE
;
6821 This
->haveHardwareCursor
= FALSE
;
6824 WINED3DLOCKED_RECT rect
;
6826 /* MSDN: Cursor must be A8R8G8B8 */
6827 if (WINED3DFMT_A8R8G8B8
!= pSur
->resource
.format
) {
6828 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
6829 return WINED3DERR_INVALIDCALL
;
6832 /* MSDN: Cursor must be smaller than the display mode */
6833 if(pSur
->currentDesc
.Width
> This
->ddraw_width
||
6834 pSur
->currentDesc
.Height
> This
->ddraw_height
) {
6835 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This
, pSur
, pSur
->currentDesc
.Width
, pSur
->currentDesc
.Height
, This
->ddraw_width
, This
->ddraw_height
);
6836 return WINED3DERR_INVALIDCALL
;
6839 if (!This
->haveHardwareCursor
) {
6840 /* TODO: MSDN: Cursor sizes must be a power of 2 */
6842 /* Do not store the surface's pointer because the application may
6843 * release it after setting the cursor image. Windows doesn't
6844 * addref the set surface, so we can't do this either without
6845 * creating circular refcount dependencies. Copy out the gl texture
6848 This
->cursorWidth
= pSur
->currentDesc
.Width
;
6849 This
->cursorHeight
= pSur
->currentDesc
.Height
;
6850 if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap
, &rect
, NULL
, WINED3DLOCK_READONLY
)))
6852 const GlPixelFormatDesc
*glDesc
;
6853 const StaticPixelFormatDesc
*tableEntry
= getFormatDescEntry(WINED3DFMT_A8R8G8B8
, &GLINFO_LOCATION
, &glDesc
);
6854 char *mem
, *bits
= (char *)rect
.pBits
;
6855 GLint intfmt
= glDesc
->glInternal
;
6856 GLint format
= glDesc
->glFormat
;
6857 GLint type
= glDesc
->glType
;
6858 INT height
= This
->cursorHeight
;
6859 INT width
= This
->cursorWidth
;
6860 INT bpp
= tableEntry
->bpp
;
6863 /* Reformat the texture memory (pitch and width can be
6865 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
6866 for(i
= 0; i
< height
; i
++)
6867 memcpy(&mem
[width
* bpp
* i
], &bits
[rect
.Pitch
* i
], width
* bpp
);
6868 IWineD3DSurface_UnlockRect(pCursorBitmap
);
6871 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
6872 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
6873 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6876 /* Make sure that a proper texture unit is selected */
6877 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
6878 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
6879 checkGLcall("glActiveTextureARB");
6881 sampler
= This
->rev_tex_unit_map
[0];
6882 if (sampler
!= -1) {
6883 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
6885 /* Create a new cursor texture */
6886 glGenTextures(1, &This
->cursorTexture
);
6887 checkGLcall("glGenTextures");
6888 glBindTexture(GL_TEXTURE_2D
, This
->cursorTexture
);
6889 checkGLcall("glBindTexture");
6890 /* Copy the bitmap memory into the cursor texture */
6891 glTexImage2D(GL_TEXTURE_2D
, 0, intfmt
, width
, height
, 0, format
, type
, mem
);
6892 HeapFree(GetProcessHeap(), 0, mem
);
6893 checkGLcall("glTexImage2D");
6895 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
6896 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
6897 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6904 FIXME("A cursor texture was not returned.\n");
6905 This
->cursorTexture
= 0;
6910 /* Draw a hardware cursor */
6911 ICONINFO cursorInfo
;
6913 /* Create and clear maskBits because it is not needed for
6914 * 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
6916 DWORD
*maskBits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6917 (pSur
->currentDesc
.Width
* pSur
->currentDesc
.Height
/ 8));
6918 IWineD3DSurface_LockRect(pCursorBitmap
, &lockedRect
, NULL
,
6919 WINED3DLOCK_NO_DIRTY_UPDATE
|
6920 WINED3DLOCK_READONLY
6922 TRACE("width: %i height: %i\n", pSur
->currentDesc
.Width
,
6923 pSur
->currentDesc
.Height
);
6925 cursorInfo
.fIcon
= FALSE
;
6926 cursorInfo
.xHotspot
= XHotSpot
;
6927 cursorInfo
.yHotspot
= YHotSpot
;
6928 cursorInfo
.hbmMask
= CreateBitmap(pSur
->currentDesc
.Width
,
6929 pSur
->currentDesc
.Height
, 1,
6931 cursorInfo
.hbmColor
= CreateBitmap(pSur
->currentDesc
.Width
,
6932 pSur
->currentDesc
.Height
, 1,
6933 32, lockedRect
.pBits
);
6934 IWineD3DSurface_UnlockRect(pCursorBitmap
);
6935 /* Create our cursor and clean up. */
6936 cursor
= CreateIconIndirect(&cursorInfo
);
6938 if (cursorInfo
.hbmMask
) DeleteObject(cursorInfo
.hbmMask
);
6939 if (cursorInfo
.hbmColor
) DeleteObject(cursorInfo
.hbmColor
);
6940 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
6941 This
->hardwareCursor
= cursor
;
6942 HeapFree(GetProcessHeap(), 0, maskBits
);
6946 This
->xHotSpot
= XHotSpot
;
6947 This
->yHotSpot
= YHotSpot
;
6951 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
6952 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6953 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
6955 This
->xScreenSpace
= XScreenSpace
;
6956 This
->yScreenSpace
= YScreenSpace
;
6962 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
6963 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6964 BOOL oldVisible
= This
->bCursorVisible
;
6967 TRACE("(%p) : visible(%d)\n", This
, bShow
);
6970 * When ShowCursor is first called it should make the cursor appear at the OS's last
6971 * known cursor position. Because of this, some applications just repetitively call
6972 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
6975 This
->xScreenSpace
= pt
.x
;
6976 This
->yScreenSpace
= pt
.y
;
6978 if (This
->haveHardwareCursor
) {
6979 This
->bCursorVisible
= bShow
;
6981 SetCursor(This
->hardwareCursor
);
6987 if (This
->cursorTexture
)
6988 This
->bCursorVisible
= bShow
;
6994 static HRESULT WINAPI
IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice
* iface
) {
6995 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6996 IWineD3DResourceImpl
*resource
;
6997 TRACE("(%p) : state (%u)\n", This
, This
->state
);
6999 /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
7000 switch (This
->state
) {
7003 case WINED3DERR_DEVICELOST
:
7005 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, IWineD3DResourceImpl
, resource
.resource_list_entry
) {
7006 if (resource
->resource
.pool
== WINED3DPOOL_DEFAULT
)
7007 return WINED3DERR_DEVICENOTRESET
;
7009 return WINED3DERR_DEVICELOST
;
7011 case WINED3DERR_DRIVERINTERNALERROR
:
7012 return WINED3DERR_DRIVERINTERNALERROR
;
7016 return WINED3DERR_DRIVERINTERNALERROR
;
7020 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
* iface
) {
7021 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7022 /** FIXME: Resource tracking needs to be done,
7023 * The closes we can do to this is set the priorities of all managed textures low
7024 * and then reset them.
7025 ***********************************************************/
7026 FIXME("(%p) : stub\n", This
);
7030 static void updateSurfaceDesc(IWineD3DSurfaceImpl
*surface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
7031 IWineD3DDeviceImpl
*This
= surface
->resource
.wineD3DDevice
; /* for GL_SUPPORT */
7033 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
7034 if(surface
->Flags
& SFLAG_DIBSECTION
) {
7035 /* Release the DC */
7036 SelectObject(surface
->hDC
, surface
->dib
.holdbitmap
);
7037 DeleteDC(surface
->hDC
);
7038 /* Release the DIB section */
7039 DeleteObject(surface
->dib
.DIBsection
);
7040 surface
->dib
.bitmap_data
= NULL
;
7041 surface
->resource
.allocatedMemory
= NULL
;
7042 surface
->Flags
&= ~SFLAG_DIBSECTION
;
7044 surface
->currentDesc
.Width
= pPresentationParameters
->BackBufferWidth
;
7045 surface
->currentDesc
.Height
= pPresentationParameters
->BackBufferHeight
;
7046 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE
)) {
7047 surface
->pow2Width
= pPresentationParameters
->BackBufferWidth
;
7048 surface
->pow2Height
= pPresentationParameters
->BackBufferHeight
;
7050 surface
->pow2Width
= surface
->pow2Height
= 1;
7051 while (surface
->pow2Width
< pPresentationParameters
->BackBufferWidth
) surface
->pow2Width
<<= 1;
7052 while (surface
->pow2Height
< pPresentationParameters
->BackBufferHeight
) surface
->pow2Height
<<= 1;
7054 surface
->glRect
.left
= 0;
7055 surface
->glRect
.top
= 0;
7056 surface
->glRect
.right
= surface
->pow2Width
;
7057 surface
->glRect
.bottom
= surface
->pow2Height
;
7059 if(surface
->glDescription
.textureName
) {
7060 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
7062 glDeleteTextures(1, &surface
->glDescription
.textureName
);
7064 surface
->glDescription
.textureName
= 0;
7065 surface
->Flags
&= ~SFLAG_CLIENT
;
7067 if(surface
->pow2Width
!= pPresentationParameters
->BackBufferWidth
||
7068 surface
->pow2Height
!= pPresentationParameters
->BackBufferHeight
) {
7069 surface
->Flags
|= SFLAG_NONPOW2
;
7071 surface
->Flags
&= ~SFLAG_NONPOW2
;
7073 HeapFree(GetProcessHeap(), 0, surface
->resource
.heapMemory
);
7074 surface
->resource
.allocatedMemory
= NULL
;
7075 surface
->resource
.heapMemory
= NULL
;
7076 surface
->resource
.size
= IWineD3DSurface_GetPitch((IWineD3DSurface
*) surface
) * surface
->pow2Width
;
7077 /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
7078 if (surface
->resource
.usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
7079 IWineD3DSurface_ModifyLocation((IWineD3DSurface
*) surface
, SFLAG_INSYSMEM
, TRUE
);
7081 IWineD3DSurface_ModifyLocation((IWineD3DSurface
*) surface
, SFLAG_INDRAWABLE
, TRUE
);
7085 static HRESULT WINAPI
reset_unload_resources(IWineD3DResource
*resource
, void *data
) {
7086 TRACE("Unloading resource %p\n", resource
);
7087 IWineD3DResource_UnLoad(resource
);
7088 IWineD3DResource_Release(resource
);
7092 static void reset_fbo_state(IWineD3DDevice
*iface
) {
7093 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7097 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
7098 checkGLcall("glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)");
7101 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->fbo
));
7104 if (This
->src_fbo
) {
7105 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->src_fbo
));
7108 if (This
->dst_fbo
) {
7109 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This
->dst_fbo
));
7112 checkGLcall("Tear down FBOs\n");
7115 for (i
= 0; i
< GL_LIMITS(buffers
); ++i
) {
7116 This
->fbo_color_attachments
[i
] = NULL
;
7118 This
->fbo_depth_attachment
= NULL
;
7121 static BOOL
is_display_mode_supported(IWineD3DDeviceImpl
*This
, WINED3DPRESENT_PARAMETERS
*pp
) {
7123 WINED3DDISPLAYMODE m
;
7126 /* All Windowed modes are supported, as is leaving the current mode */
7127 if(pp
->Windowed
) return TRUE
;
7128 if(!pp
->BackBufferWidth
) return TRUE
;
7129 if(!pp
->BackBufferHeight
) return TRUE
;
7131 count
= IWineD3D_GetAdapterModeCount(This
->wineD3D
, This
->adapter
->num
, WINED3DFMT_UNKNOWN
);
7132 for(i
= 0; i
< count
; i
++) {
7133 memset(&m
, 0, sizeof(m
));
7134 hr
= IWineD3D_EnumAdapterModes(This
->wineD3D
, This
->adapter
->num
, WINED3DFMT_UNKNOWN
, i
, &m
);
7136 ERR("EnumAdapterModes failed\n");
7138 if(m
.Width
== pp
->BackBufferWidth
&& m
.Height
== pp
->BackBufferHeight
) {
7139 /* Mode found, it is supported */
7143 /* Mode not found -> not supported */
7147 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
7148 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7149 IWineD3DSwapChainImpl
*swapchain
;
7151 BOOL DisplayModeChanged
= FALSE
;
7152 WINED3DDISPLAYMODE mode
;
7153 IWineD3DBaseShaderImpl
*shader
;
7154 IWineD3DSurfaceImpl
*target
;
7156 TRACE("(%p)\n", This
);
7158 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &swapchain
);
7160 ERR("Failed to get the first implicit swapchain\n");
7164 if(!is_display_mode_supported(This
, pPresentationParameters
)) {
7165 WARN("Rejecting Reset() call because the requested display mode is not supported\n");
7166 WARN("Requested mode: %d, %d\n", pPresentationParameters
->BackBufferWidth
,
7167 pPresentationParameters
->BackBufferHeight
);
7168 return WINED3DERR_INVALIDCALL
;
7171 /* Is it necessary to recreate the gl context? Actually every setting can be changed
7172 * on an existing gl context, so there's no real need for recreation.
7174 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7176 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7178 TRACE("New params:\n");
7179 TRACE("BackBufferWidth = %d\n", pPresentationParameters
->BackBufferWidth
);
7180 TRACE("BackBufferHeight = %d\n", pPresentationParameters
->BackBufferHeight
);
7181 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters
->BackBufferFormat
));
7182 TRACE("BackBufferCount = %d\n", pPresentationParameters
->BackBufferCount
);
7183 TRACE("MultiSampleType = %d\n", pPresentationParameters
->MultiSampleType
);
7184 TRACE("MultiSampleQuality = %d\n", pPresentationParameters
->MultiSampleQuality
);
7185 TRACE("SwapEffect = %d\n", pPresentationParameters
->SwapEffect
);
7186 TRACE("hDeviceWindow = %p\n", pPresentationParameters
->hDeviceWindow
);
7187 TRACE("Windowed = %s\n", pPresentationParameters
->Windowed
? "true" : "false");
7188 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters
->EnableAutoDepthStencil
? "true" : "false");
7189 TRACE("Flags = %08x\n", pPresentationParameters
->Flags
);
7190 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters
->FullScreen_RefreshRateInHz
);
7191 TRACE("PresentationInterval = %d\n", pPresentationParameters
->PresentationInterval
);
7193 /* No special treatment of these parameters. Just store them */
7194 swapchain
->presentParms
.SwapEffect
= pPresentationParameters
->SwapEffect
;
7195 swapchain
->presentParms
.Flags
= pPresentationParameters
->Flags
;
7196 swapchain
->presentParms
.PresentationInterval
= pPresentationParameters
->PresentationInterval
;
7197 swapchain
->presentParms
.FullScreen_RefreshRateInHz
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
7199 /* What to do about these? */
7200 if(pPresentationParameters
->BackBufferCount
!= 0 &&
7201 pPresentationParameters
->BackBufferCount
!= swapchain
->presentParms
.BackBufferCount
) {
7202 ERR("Cannot change the back buffer count yet\n");
7204 if(pPresentationParameters
->BackBufferFormat
!= WINED3DFMT_UNKNOWN
&&
7205 pPresentationParameters
->BackBufferFormat
!= swapchain
->presentParms
.BackBufferFormat
) {
7206 ERR("Cannot change the back buffer format yet\n");
7208 if(pPresentationParameters
->hDeviceWindow
!= NULL
&&
7209 pPresentationParameters
->hDeviceWindow
!= swapchain
->presentParms
.hDeviceWindow
) {
7210 ERR("Cannot change the device window yet\n");
7212 if(pPresentationParameters
->EnableAutoDepthStencil
!= swapchain
->presentParms
.EnableAutoDepthStencil
) {
7213 ERR("What do do about a changed auto depth stencil parameter?\n");
7216 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
7217 reset_fbo_state((IWineD3DDevice
*) This
);
7220 IWineD3DDevice_EnumResources(iface
, reset_unload_resources
, NULL
);
7221 LIST_FOR_EACH_ENTRY(shader
, &This
->shaders
, IWineD3DBaseShaderImpl
, baseShader
.shader_list_entry
) {
7222 This
->shader_backend
->shader_destroy((IWineD3DBaseShader
*) shader
);
7226 if(This
->depth_blt_texture
) {
7227 glDeleteTextures(1, &This
->depth_blt_texture
);
7228 This
->depth_blt_texture
= 0;
7230 if (This
->depth_blt_rb
) {
7231 GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This
->depth_blt_rb
));
7232 This
->depth_blt_rb
= 0;
7233 This
->depth_blt_rb_w
= 0;
7234 This
->depth_blt_rb_h
= 0;
7236 This
->shader_backend
->shader_free_private(iface
);
7237 This
->frag_pipe
->free_private(iface
);
7239 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
7240 /* Textures are recreated below */
7241 glDeleteTextures(1, &This
->dummyTextureName
[i
]);
7242 checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
7243 This
->dummyTextureName
[i
] = 0;
7247 while(This
->numContexts
) {
7248 DestroyContext(This
, This
->contexts
[0]);
7250 This
->activeContext
= NULL
;
7251 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
7252 swapchain
->context
= NULL
;
7253 swapchain
->num_contexts
= 0;
7255 if(pPresentationParameters
->Windowed
) {
7256 mode
.Width
= swapchain
->orig_width
;
7257 mode
.Height
= swapchain
->orig_height
;
7258 mode
.RefreshRate
= 0;
7259 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
7261 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
7262 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
7263 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
7264 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
7267 /* Should Width == 800 && Height == 0 set 800x600? */
7268 if(pPresentationParameters
->BackBufferWidth
!= 0 && pPresentationParameters
->BackBufferHeight
!= 0 &&
7269 (pPresentationParameters
->BackBufferWidth
!= swapchain
->presentParms
.BackBufferWidth
||
7270 pPresentationParameters
->BackBufferHeight
!= swapchain
->presentParms
.BackBufferHeight
))
7277 vp
.Width
= pPresentationParameters
->BackBufferWidth
;
7278 vp
.Height
= pPresentationParameters
->BackBufferHeight
;
7282 if(!pPresentationParameters
->Windowed
) {
7283 DisplayModeChanged
= TRUE
;
7285 swapchain
->presentParms
.BackBufferWidth
= pPresentationParameters
->BackBufferWidth
;
7286 swapchain
->presentParms
.BackBufferHeight
= pPresentationParameters
->BackBufferHeight
;
7288 updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->frontBuffer
, pPresentationParameters
);
7289 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
7290 updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->backBuffer
[i
], pPresentationParameters
);
7292 if(This
->auto_depth_stencil_buffer
) {
7293 updateSurfaceDesc((IWineD3DSurfaceImpl
*)This
->auto_depth_stencil_buffer
, pPresentationParameters
);
7297 /* Now set the new viewport */
7298 IWineD3DDevice_SetViewport(iface
, &vp
);
7301 if((pPresentationParameters
->Windowed
&& !swapchain
->presentParms
.Windowed
) ||
7302 (swapchain
->presentParms
.Windowed
&& !pPresentationParameters
->Windowed
) ||
7303 DisplayModeChanged
) {
7305 IWineD3DDevice_SetFullscreen(iface
, !pPresentationParameters
->Windowed
);
7306 swapchain
->presentParms
.Windowed
= pPresentationParameters
->Windowed
;
7307 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
7308 } else if(!pPresentationParameters
->Windowed
) {
7309 DWORD style
= This
->style
, exStyle
= This
->exStyle
;
7310 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
7311 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
7312 * Reset to clear up their mess. Guild Wars also loses the device during that.
7316 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, This
->ddraw_window
);
7317 This
->style
= style
;
7318 This
->exStyle
= exStyle
;
7321 /* Recreate the primary swapchain's context */
7322 swapchain
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain
->context
));
7323 if(swapchain
->backBuffer
) {
7324 target
= (IWineD3DSurfaceImpl
*) swapchain
->backBuffer
[0];
7326 target
= (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
;
7328 swapchain
->context
[0] = CreateContext(This
, target
, swapchain
->win_handle
, FALSE
,
7329 &swapchain
->presentParms
);
7330 swapchain
->num_contexts
= 1;
7331 This
->activeContext
= swapchain
->context
[0];
7332 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
7334 hr
= IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*) This
->stateBlock
);
7336 ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
7338 create_dummy_textures(This
);
7341 hr
= This
->shader_backend
->shader_alloc_private(iface
);
7343 ERR("Failed to recreate shader private data\n");
7346 hr
= This
->frag_pipe
->alloc_private(iface
);
7348 TRACE("Fragment pipeline private data couldn't be allocated\n");
7352 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
7358 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL bEnableDialogs
) {
7359 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7360 /** FIXME: always true at the moment **/
7361 if(!bEnableDialogs
) {
7362 FIXME("(%p) Dialogs cannot be disabled yet\n", This
);
7368 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
7369 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7370 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
7372 *pParameters
= This
->createParms
;
7376 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST WINED3DGAMMARAMP
* pRamp
) {
7377 IWineD3DSwapChain
*swapchain
;
7379 TRACE("Relaying to swapchain\n");
7381 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
7382 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, (WINED3DGAMMARAMP
*)pRamp
);
7383 IWineD3DSwapChain_Release(swapchain
);
7388 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
7389 IWineD3DSwapChain
*swapchain
;
7391 TRACE("Relaying to swapchain\n");
7393 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
7394 IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
7395 IWineD3DSwapChain_Release(swapchain
);
7401 /** ********************************************************
7402 * Notification functions
7403 ** ********************************************************/
7404 /** This function must be called in the release of a resource when ref == 0,
7405 * the contents of resource must still be correct,
7406 * any handles to other resource held by the caller must be closed
7407 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7408 *****************************************************/
7409 static void WINAPI
IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7410 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7412 TRACE("(%p) : Adding Resource %p\n", This
, resource
);
7413 list_add_head(&This
->resources
, &((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
7416 static void WINAPI
IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7417 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7419 TRACE("(%p) : Removing resource %p\n", This
, resource
);
7421 list_remove(&((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
7425 static void WINAPI
IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7426 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7429 TRACE("(%p) : resource %p\n", This
, resource
);
7430 switch(IWineD3DResource_GetType(resource
)){
7431 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7432 case WINED3DRTYPE_SURFACE
: {
7435 /* Cleanup any FBO attachments if d3d is enabled */
7436 if(This
->d3d_initialized
) {
7437 if((IWineD3DSurface
*)resource
== This
->lastActiveRenderTarget
) {
7438 IWineD3DSwapChainImpl
*swapchain
= This
->swapchains
? (IWineD3DSwapChainImpl
*) This
->swapchains
[0] : NULL
;
7440 TRACE("Last active render target destroyed\n");
7441 /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
7442 * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
7443 * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
7444 * and the lastActiveRenderTarget member shouldn't matter
7447 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0] != (IWineD3DSurface
*)resource
) {
7448 TRACE("Activating primary back buffer\n");
7449 ActivateContext(This
, swapchain
->backBuffer
[0], CTXUSAGE_RESOURCELOAD
);
7450 } else if(!swapchain
->backBuffer
&& swapchain
->frontBuffer
!= (IWineD3DSurface
*)resource
) {
7451 /* Single buffering environment */
7452 TRACE("Activating primary front buffer\n");
7453 ActivateContext(This
, swapchain
->frontBuffer
, CTXUSAGE_RESOURCELOAD
);
7455 TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
7456 /* Implicit render target destroyed, that means the device is being destroyed
7457 * whatever we set here, it shouldn't matter
7459 This
->lastActiveRenderTarget
= (IWineD3DSurface
*) 0xdeadbabe;
7462 /* May happen during ddraw uninitialization */
7463 TRACE("Render target set, but swapchain does not exist!\n");
7464 This
->lastActiveRenderTarget
= (IWineD3DSurface
*) 0xdeadcafe;
7469 for (i
= 0; i
< GL_LIMITS(buffers
); ++i
) {
7470 if (This
->fbo_color_attachments
[i
] == (IWineD3DSurface
*)resource
) {
7471 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->fbo
);
7472 set_render_target_fbo(iface
, i
, NULL
);
7473 This
->fbo_color_attachments
[i
] = NULL
;
7476 if (This
->fbo_depth_attachment
== (IWineD3DSurface
*)resource
) {
7477 bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->fbo
);
7478 set_depth_stencil_fbo(iface
, NULL
);
7479 This
->fbo_depth_attachment
= NULL
;
7486 case WINED3DRTYPE_TEXTURE
:
7487 case WINED3DRTYPE_CUBETEXTURE
:
7488 case WINED3DRTYPE_VOLUMETEXTURE
:
7489 for (counter
= 0; counter
< MAX_COMBINED_SAMPLERS
; counter
++) {
7490 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7491 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7492 This
->stateBlock
->textures
[counter
] = NULL
;
7494 if (This
->updateStateBlock
!= This
->stateBlock
){
7495 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7496 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7497 This
->updateStateBlock
->textures
[counter
] = NULL
;
7502 case WINED3DRTYPE_VOLUME
:
7503 /* TODO: nothing really? */
7505 case WINED3DRTYPE_VERTEXBUFFER
:
7506 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
7509 TRACE("Cleaning up stream pointers\n");
7511 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
7512 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7513 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7515 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7516 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
7517 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
7518 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
7519 /* Set changed flag? */
7522 if (This
->stateBlock
!= NULL
) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
7523 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
7524 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
7525 This
->stateBlock
->streamSource
[streamNumber
] = 0;
7528 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
7529 else { /* This shouldn't happen */
7530 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
7537 case WINED3DRTYPE_INDEXBUFFER
:
7538 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
7539 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7540 if (This
->updateStateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7541 This
->updateStateBlock
->pIndexData
= NULL
;
7544 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7545 if (This
->stateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7546 This
->stateBlock
->pIndexData
= NULL
;
7552 FIXME("(%p) unknown resource type %p %u\n", This
, resource
, IWineD3DResource_GetType(resource
));
7557 /* Remove the resource from the resourceStore */
7558 IWineD3DDeviceImpl_RemoveResource(iface
, resource
);
7560 TRACE("Resource released\n");
7564 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumResources(IWineD3DDevice
*iface
, D3DCB_ENUMRESOURCES pCallback
, void *pData
) {
7565 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7566 IWineD3DResourceImpl
*resource
, *cursor
;
7568 TRACE("(%p)->(%p,%p)\n", This
, pCallback
, pData
);
7570 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &This
->resources
, IWineD3DResourceImpl
, resource
.resource_list_entry
) {
7571 TRACE("enumerating resource %p\n", resource
);
7572 IWineD3DResource_AddRef((IWineD3DResource
*) resource
);
7573 ret
= pCallback((IWineD3DResource
*) resource
, pData
);
7574 if(ret
== S_FALSE
) {
7575 TRACE("Canceling enumeration\n");
7582 /**********************************************************
7583 * IWineD3DDevice VTbl follows
7584 **********************************************************/
7586 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
7588 /*** IUnknown methods ***/
7589 IWineD3DDeviceImpl_QueryInterface
,
7590 IWineD3DDeviceImpl_AddRef
,
7591 IWineD3DDeviceImpl_Release
,
7592 /*** IWineD3DDevice methods ***/
7593 IWineD3DDeviceImpl_GetParent
,
7594 /*** Creation methods**/
7595 IWineD3DDeviceImpl_CreateVertexBuffer
,
7596 IWineD3DDeviceImpl_CreateIndexBuffer
,
7597 IWineD3DDeviceImpl_CreateStateBlock
,
7598 IWineD3DDeviceImpl_CreateSurface
,
7599 IWineD3DDeviceImpl_CreateTexture
,
7600 IWineD3DDeviceImpl_CreateVolumeTexture
,
7601 IWineD3DDeviceImpl_CreateVolume
,
7602 IWineD3DDeviceImpl_CreateCubeTexture
,
7603 IWineD3DDeviceImpl_CreateQuery
,
7604 IWineD3DDeviceImpl_CreateAdditionalSwapChain
,
7605 IWineD3DDeviceImpl_CreateVertexDeclaration
,
7606 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
7607 IWineD3DDeviceImpl_CreateVertexShader
,
7608 IWineD3DDeviceImpl_CreatePixelShader
,
7609 IWineD3DDeviceImpl_CreatePalette
,
7610 /*** Odd functions **/
7611 IWineD3DDeviceImpl_Init3D
,
7612 IWineD3DDeviceImpl_Uninit3D
,
7613 IWineD3DDeviceImpl_SetFullscreen
,
7614 IWineD3DDeviceImpl_SetMultithreaded
,
7615 IWineD3DDeviceImpl_EvictManagedResources
,
7616 IWineD3DDeviceImpl_GetAvailableTextureMem
,
7617 IWineD3DDeviceImpl_GetBackBuffer
,
7618 IWineD3DDeviceImpl_GetCreationParameters
,
7619 IWineD3DDeviceImpl_GetDeviceCaps
,
7620 IWineD3DDeviceImpl_GetDirect3D
,
7621 IWineD3DDeviceImpl_GetDisplayMode
,
7622 IWineD3DDeviceImpl_SetDisplayMode
,
7623 IWineD3DDeviceImpl_GetHWND
,
7624 IWineD3DDeviceImpl_SetHWND
,
7625 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
7626 IWineD3DDeviceImpl_GetRasterStatus
,
7627 IWineD3DDeviceImpl_GetSwapChain
,
7628 IWineD3DDeviceImpl_Reset
,
7629 IWineD3DDeviceImpl_SetDialogBoxMode
,
7630 IWineD3DDeviceImpl_SetCursorProperties
,
7631 IWineD3DDeviceImpl_SetCursorPosition
,
7632 IWineD3DDeviceImpl_ShowCursor
,
7633 IWineD3DDeviceImpl_TestCooperativeLevel
,
7634 /*** Getters and setters **/
7635 IWineD3DDeviceImpl_SetClipPlane
,
7636 IWineD3DDeviceImpl_GetClipPlane
,
7637 IWineD3DDeviceImpl_SetClipStatus
,
7638 IWineD3DDeviceImpl_GetClipStatus
,
7639 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
7640 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
7641 IWineD3DDeviceImpl_SetDepthStencilSurface
,
7642 IWineD3DDeviceImpl_GetDepthStencilSurface
,
7643 IWineD3DDeviceImpl_SetFVF
,
7644 IWineD3DDeviceImpl_GetFVF
,
7645 IWineD3DDeviceImpl_SetGammaRamp
,
7646 IWineD3DDeviceImpl_GetGammaRamp
,
7647 IWineD3DDeviceImpl_SetIndices
,
7648 IWineD3DDeviceImpl_GetIndices
,
7649 IWineD3DDeviceImpl_SetBaseVertexIndex
,
7650 IWineD3DDeviceImpl_GetBaseVertexIndex
,
7651 IWineD3DDeviceImpl_SetLight
,
7652 IWineD3DDeviceImpl_GetLight
,
7653 IWineD3DDeviceImpl_SetLightEnable
,
7654 IWineD3DDeviceImpl_GetLightEnable
,
7655 IWineD3DDeviceImpl_SetMaterial
,
7656 IWineD3DDeviceImpl_GetMaterial
,
7657 IWineD3DDeviceImpl_SetNPatchMode
,
7658 IWineD3DDeviceImpl_GetNPatchMode
,
7659 IWineD3DDeviceImpl_SetPaletteEntries
,
7660 IWineD3DDeviceImpl_GetPaletteEntries
,
7661 IWineD3DDeviceImpl_SetPixelShader
,
7662 IWineD3DDeviceImpl_GetPixelShader
,
7663 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
7664 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
7665 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
7666 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
7667 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
7668 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
7669 IWineD3DDeviceImpl_SetRenderState
,
7670 IWineD3DDeviceImpl_GetRenderState
,
7671 IWineD3DDeviceImpl_SetRenderTarget
,
7672 IWineD3DDeviceImpl_GetRenderTarget
,
7673 IWineD3DDeviceImpl_SetFrontBackBuffers
,
7674 IWineD3DDeviceImpl_SetSamplerState
,
7675 IWineD3DDeviceImpl_GetSamplerState
,
7676 IWineD3DDeviceImpl_SetScissorRect
,
7677 IWineD3DDeviceImpl_GetScissorRect
,
7678 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
7679 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
7680 IWineD3DDeviceImpl_SetStreamSource
,
7681 IWineD3DDeviceImpl_GetStreamSource
,
7682 IWineD3DDeviceImpl_SetStreamSourceFreq
,
7683 IWineD3DDeviceImpl_GetStreamSourceFreq
,
7684 IWineD3DDeviceImpl_SetTexture
,
7685 IWineD3DDeviceImpl_GetTexture
,
7686 IWineD3DDeviceImpl_SetTextureStageState
,
7687 IWineD3DDeviceImpl_GetTextureStageState
,
7688 IWineD3DDeviceImpl_SetTransform
,
7689 IWineD3DDeviceImpl_GetTransform
,
7690 IWineD3DDeviceImpl_SetVertexDeclaration
,
7691 IWineD3DDeviceImpl_GetVertexDeclaration
,
7692 IWineD3DDeviceImpl_SetVertexShader
,
7693 IWineD3DDeviceImpl_GetVertexShader
,
7694 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
7695 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
7696 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
7697 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
7698 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
7699 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
7700 IWineD3DDeviceImpl_SetViewport
,
7701 IWineD3DDeviceImpl_GetViewport
,
7702 IWineD3DDeviceImpl_MultiplyTransform
,
7703 IWineD3DDeviceImpl_ValidateDevice
,
7704 IWineD3DDeviceImpl_ProcessVertices
,
7705 /*** State block ***/
7706 IWineD3DDeviceImpl_BeginStateBlock
,
7707 IWineD3DDeviceImpl_EndStateBlock
,
7708 /*** Scene management ***/
7709 IWineD3DDeviceImpl_BeginScene
,
7710 IWineD3DDeviceImpl_EndScene
,
7711 IWineD3DDeviceImpl_Present
,
7712 IWineD3DDeviceImpl_Clear
,
7714 IWineD3DDeviceImpl_DrawPrimitive
,
7715 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
7716 IWineD3DDeviceImpl_DrawPrimitiveUP
,
7717 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
7718 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
7719 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
7720 IWineD3DDeviceImpl_DrawRectPatch
,
7721 IWineD3DDeviceImpl_DrawTriPatch
,
7722 IWineD3DDeviceImpl_DeletePatch
,
7723 IWineD3DDeviceImpl_ColorFill
,
7724 IWineD3DDeviceImpl_UpdateTexture
,
7725 IWineD3DDeviceImpl_UpdateSurface
,
7726 IWineD3DDeviceImpl_GetFrontBufferData
,
7727 /*** object tracking ***/
7728 IWineD3DDeviceImpl_ResourceReleased
,
7729 IWineD3DDeviceImpl_EnumResources
7732 const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl
=
7734 /*** IUnknown methods ***/
7735 IWineD3DDeviceImpl_QueryInterface
,
7736 IWineD3DDeviceImpl_AddRef
,
7737 IWineD3DDeviceImpl_Release
,
7738 /*** IWineD3DDevice methods ***/
7739 IWineD3DDeviceImpl_GetParent
,
7740 /*** Creation methods**/
7741 IWineD3DDeviceImpl_CreateVertexBuffer
,
7742 IWineD3DDeviceImpl_CreateIndexBuffer
,
7743 IWineD3DDeviceImpl_CreateStateBlock
,
7744 IWineD3DDeviceImpl_CreateSurface
,
7745 IWineD3DDeviceImpl_CreateTexture
,
7746 IWineD3DDeviceImpl_CreateVolumeTexture
,
7747 IWineD3DDeviceImpl_CreateVolume
,
7748 IWineD3DDeviceImpl_CreateCubeTexture
,
7749 IWineD3DDeviceImpl_CreateQuery
,
7750 IWineD3DDeviceImpl_CreateAdditionalSwapChain
,
7751 IWineD3DDeviceImpl_CreateVertexDeclaration
,
7752 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
7753 IWineD3DDeviceImpl_CreateVertexShader
,
7754 IWineD3DDeviceImpl_CreatePixelShader
,
7755 IWineD3DDeviceImpl_CreatePalette
,
7756 /*** Odd functions **/
7757 IWineD3DDeviceImpl_Init3D
,
7758 IWineD3DDeviceImpl_Uninit3D
,
7759 IWineD3DDeviceImpl_SetFullscreen
,
7760 IWineD3DDeviceImpl_SetMultithreaded
,
7761 IWineD3DDeviceImpl_EvictManagedResources
,
7762 IWineD3DDeviceImpl_GetAvailableTextureMem
,
7763 IWineD3DDeviceImpl_GetBackBuffer
,
7764 IWineD3DDeviceImpl_GetCreationParameters
,
7765 IWineD3DDeviceImpl_GetDeviceCaps
,
7766 IWineD3DDeviceImpl_GetDirect3D
,
7767 IWineD3DDeviceImpl_GetDisplayMode
,
7768 IWineD3DDeviceImpl_SetDisplayMode
,
7769 IWineD3DDeviceImpl_GetHWND
,
7770 IWineD3DDeviceImpl_SetHWND
,
7771 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
7772 IWineD3DDeviceImpl_GetRasterStatus
,
7773 IWineD3DDeviceImpl_GetSwapChain
,
7774 IWineD3DDeviceImpl_Reset
,
7775 IWineD3DDeviceImpl_SetDialogBoxMode
,
7776 IWineD3DDeviceImpl_SetCursorProperties
,
7777 IWineD3DDeviceImpl_SetCursorPosition
,
7778 IWineD3DDeviceImpl_ShowCursor
,
7779 IWineD3DDeviceImpl_TestCooperativeLevel
,
7780 /*** Getters and setters **/
7781 IWineD3DDeviceImpl_SetClipPlane
,
7782 IWineD3DDeviceImpl_GetClipPlane
,
7783 IWineD3DDeviceImpl_SetClipStatus
,
7784 IWineD3DDeviceImpl_GetClipStatus
,
7785 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
7786 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
7787 IWineD3DDeviceImpl_SetDepthStencilSurface
,
7788 IWineD3DDeviceImpl_GetDepthStencilSurface
,
7789 IWineD3DDeviceImpl_SetFVF
,
7790 IWineD3DDeviceImpl_GetFVF
,
7791 IWineD3DDeviceImpl_SetGammaRamp
,
7792 IWineD3DDeviceImpl_GetGammaRamp
,
7793 IWineD3DDeviceImpl_SetIndices
,
7794 IWineD3DDeviceImpl_GetIndices
,
7795 IWineD3DDeviceImpl_SetBaseVertexIndex
,
7796 IWineD3DDeviceImpl_GetBaseVertexIndex
,
7797 IWineD3DDeviceImpl_SetLight
,
7798 IWineD3DDeviceImpl_GetLight
,
7799 IWineD3DDeviceImpl_SetLightEnable
,
7800 IWineD3DDeviceImpl_GetLightEnable
,
7801 IWineD3DDeviceImpl_SetMaterial
,
7802 IWineD3DDeviceImpl_GetMaterial
,
7803 IWineD3DDeviceImpl_SetNPatchMode
,
7804 IWineD3DDeviceImpl_GetNPatchMode
,
7805 IWineD3DDeviceImpl_SetPaletteEntries
,
7806 IWineD3DDeviceImpl_GetPaletteEntries
,
7807 IWineD3DDeviceImpl_SetPixelShader
,
7808 IWineD3DDeviceImpl_GetPixelShader
,
7809 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
7810 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
7811 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
7812 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
7813 IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst
,
7814 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
7815 IWineD3DDeviceImpl_SetRenderState
,
7816 IWineD3DDeviceImpl_GetRenderState
,
7817 IWineD3DDeviceImpl_SetRenderTarget
,
7818 IWineD3DDeviceImpl_GetRenderTarget
,
7819 IWineD3DDeviceImpl_SetFrontBackBuffers
,
7820 IWineD3DDeviceImpl_SetSamplerState
,
7821 IWineD3DDeviceImpl_GetSamplerState
,
7822 IWineD3DDeviceImpl_SetScissorRect
,
7823 IWineD3DDeviceImpl_GetScissorRect
,
7824 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
7825 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
7826 IWineD3DDeviceImpl_SetStreamSource
,
7827 IWineD3DDeviceImpl_GetStreamSource
,
7828 IWineD3DDeviceImpl_SetStreamSourceFreq
,
7829 IWineD3DDeviceImpl_GetStreamSourceFreq
,
7830 IWineD3DDeviceImpl_SetTexture
,
7831 IWineD3DDeviceImpl_GetTexture
,
7832 IWineD3DDeviceImpl_SetTextureStageState
,
7833 IWineD3DDeviceImpl_GetTextureStageState
,
7834 IWineD3DDeviceImpl_SetTransform
,
7835 IWineD3DDeviceImpl_GetTransform
,
7836 IWineD3DDeviceImpl_SetVertexDeclaration
,
7837 IWineD3DDeviceImpl_GetVertexDeclaration
,
7838 IWineD3DDeviceImpl_SetVertexShader
,
7839 IWineD3DDeviceImpl_GetVertexShader
,
7840 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
7841 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
7842 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
7843 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
7844 IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst
,
7845 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
7846 IWineD3DDeviceImpl_SetViewport
,
7847 IWineD3DDeviceImpl_GetViewport
,
7848 IWineD3DDeviceImpl_MultiplyTransform
,
7849 IWineD3DDeviceImpl_ValidateDevice
,
7850 IWineD3DDeviceImpl_ProcessVertices
,
7851 /*** State block ***/
7852 IWineD3DDeviceImpl_BeginStateBlock
,
7853 IWineD3DDeviceImpl_EndStateBlock
,
7854 /*** Scene management ***/
7855 IWineD3DDeviceImpl_BeginScene
,
7856 IWineD3DDeviceImpl_EndScene
,
7857 IWineD3DDeviceImpl_Present
,
7858 IWineD3DDeviceImpl_Clear
,
7860 IWineD3DDeviceImpl_DrawPrimitive
,
7861 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
7862 IWineD3DDeviceImpl_DrawPrimitiveUP
,
7863 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
7864 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
7865 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
7866 IWineD3DDeviceImpl_DrawRectPatch
,
7867 IWineD3DDeviceImpl_DrawTriPatch
,
7868 IWineD3DDeviceImpl_DeletePatch
,
7869 IWineD3DDeviceImpl_ColorFill
,
7870 IWineD3DDeviceImpl_UpdateTexture
,
7871 IWineD3DDeviceImpl_UpdateSurface
,
7872 IWineD3DDeviceImpl_GetFrontBufferData
,
7873 /*** object tracking ***/
7874 IWineD3DDeviceImpl_ResourceReleased
,
7875 IWineD3DDeviceImpl_EnumResources
7878 const DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
7879 WINED3DRS_ALPHABLENDENABLE
,
7880 WINED3DRS_ALPHAFUNC
,
7881 WINED3DRS_ALPHAREF
,
7882 WINED3DRS_ALPHATESTENABLE
,
7884 WINED3DRS_COLORWRITEENABLE
,
7885 WINED3DRS_DESTBLEND
,
7886 WINED3DRS_DITHERENABLE
,
7887 WINED3DRS_FILLMODE
,
7888 WINED3DRS_FOGDENSITY
,
7890 WINED3DRS_FOGSTART
,
7891 WINED3DRS_LASTPIXEL
,
7892 WINED3DRS_SHADEMODE
,
7893 WINED3DRS_SRCBLEND
,
7894 WINED3DRS_STENCILENABLE
,
7895 WINED3DRS_STENCILFAIL
,
7896 WINED3DRS_STENCILFUNC
,
7897 WINED3DRS_STENCILMASK
,
7898 WINED3DRS_STENCILPASS
,
7899 WINED3DRS_STENCILREF
,
7900 WINED3DRS_STENCILWRITEMASK
,
7901 WINED3DRS_STENCILZFAIL
,
7902 WINED3DRS_TEXTUREFACTOR
,
7913 WINED3DRS_ZWRITEENABLE
7916 const DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
7917 WINED3DTSS_ADDRESSW
,
7918 WINED3DTSS_ALPHAARG0
,
7919 WINED3DTSS_ALPHAARG1
,
7920 WINED3DTSS_ALPHAARG2
,
7921 WINED3DTSS_ALPHAOP
,
7922 WINED3DTSS_BUMPENVLOFFSET
,
7923 WINED3DTSS_BUMPENVLSCALE
,
7924 WINED3DTSS_BUMPENVMAT00
,
7925 WINED3DTSS_BUMPENVMAT01
,
7926 WINED3DTSS_BUMPENVMAT10
,
7927 WINED3DTSS_BUMPENVMAT11
,
7928 WINED3DTSS_COLORARG0
,
7929 WINED3DTSS_COLORARG1
,
7930 WINED3DTSS_COLORARG2
,
7931 WINED3DTSS_COLOROP
,
7932 WINED3DTSS_RESULTARG
,
7933 WINED3DTSS_TEXCOORDINDEX
,
7934 WINED3DTSS_TEXTURETRANSFORMFLAGS
7937 const DWORD SavedPixelStates_S
[NUM_SAVEDPIXELSTATES_S
] = {
7938 WINED3DSAMP_ADDRESSU
,
7939 WINED3DSAMP_ADDRESSV
,
7940 WINED3DSAMP_ADDRESSW
,
7941 WINED3DSAMP_BORDERCOLOR
,
7942 WINED3DSAMP_MAGFILTER
,
7943 WINED3DSAMP_MINFILTER
,
7944 WINED3DSAMP_MIPFILTER
,
7945 WINED3DSAMP_MIPMAPLODBIAS
,
7946 WINED3DSAMP_MAXMIPLEVEL
,
7947 WINED3DSAMP_MAXANISOTROPY
,
7948 WINED3DSAMP_SRGBTEXTURE
,
7949 WINED3DSAMP_ELEMENTINDEX
7952 const DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
7954 WINED3DRS_AMBIENTMATERIALSOURCE
,
7955 WINED3DRS_CLIPPING
,
7956 WINED3DRS_CLIPPLANEENABLE
,
7957 WINED3DRS_COLORVERTEX
,
7958 WINED3DRS_DIFFUSEMATERIALSOURCE
,
7959 WINED3DRS_EMISSIVEMATERIALSOURCE
,
7960 WINED3DRS_FOGDENSITY
,
7962 WINED3DRS_FOGSTART
,
7963 WINED3DRS_FOGTABLEMODE
,
7964 WINED3DRS_FOGVERTEXMODE
,
7965 WINED3DRS_INDEXEDVERTEXBLENDENABLE
,
7966 WINED3DRS_LIGHTING
,
7967 WINED3DRS_LOCALVIEWER
,
7968 WINED3DRS_MULTISAMPLEANTIALIAS
,
7969 WINED3DRS_MULTISAMPLEMASK
,
7970 WINED3DRS_NORMALIZENORMALS
,
7971 WINED3DRS_PATCHEDGESTYLE
,
7972 WINED3DRS_POINTSCALE_A
,
7973 WINED3DRS_POINTSCALE_B
,
7974 WINED3DRS_POINTSCALE_C
,
7975 WINED3DRS_POINTSCALEENABLE
,
7976 WINED3DRS_POINTSIZE
,
7977 WINED3DRS_POINTSIZE_MAX
,
7978 WINED3DRS_POINTSIZE_MIN
,
7979 WINED3DRS_POINTSPRITEENABLE
,
7980 WINED3DRS_RANGEFOGENABLE
,
7981 WINED3DRS_SPECULARMATERIALSOURCE
,
7982 WINED3DRS_TWEENFACTOR
,
7983 WINED3DRS_VERTEXBLEND
,
7984 WINED3DRS_CULLMODE
,
7988 const DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
7989 WINED3DTSS_TEXCOORDINDEX
,
7990 WINED3DTSS_TEXTURETRANSFORMFLAGS
7993 const DWORD SavedVertexStates_S
[NUM_SAVEDVERTEXSTATES_S
] = {
7994 WINED3DSAMP_DMAPOFFSET
7997 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl
*This
, DWORD state
) {
7998 DWORD rep
= This
->StateTable
[state
].representative
;
8002 WineD3DContext
*context
;
8005 for(i
= 0; i
< This
->numContexts
; i
++) {
8006 context
= This
->contexts
[i
];
8007 if(isStateDirty(context
, rep
)) continue;
8009 context
->dirtyArray
[context
->numDirtyEntries
++] = rep
;
8012 context
->isStateDirty
[idx
] |= (1 << shift
);
8016 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
8017 IWineD3DDeviceImpl
*dev
= This
->resource
.wineD3DDevice
;
8018 /* The drawable size of a pbuffer render target is the current pbuffer size
8020 *width
= dev
->pbufferWidth
;
8021 *height
= dev
->pbufferHeight
;
8024 void get_drawable_size_fbo(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
8025 /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
8027 *width
= This
->pow2Width
;
8028 *height
= This
->pow2Height
;
8031 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
8032 IWineD3DDeviceImpl
*dev
= This
->resource
.wineD3DDevice
;
8033 /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
8034 * current context's drawable, which is the size of the back buffer of the swapchain
8035 * the active context belongs to. The back buffer of the swapchain is stored as the
8036 * surface the context belongs to.
8038 *width
= ((IWineD3DSurfaceImpl
*) dev
->activeContext
->surface
)->currentDesc
.Width
;
8039 *height
= ((IWineD3DSurfaceImpl
*) dev
->activeContext
->surface
)->currentDesc
.Height
;