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-2008 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 IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
);
57 /**********************************************************
58 * Global variable / Constants follow
59 **********************************************************/
60 const float identity
[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
62 /**********************************************************
63 * IUnknown parts follows
64 **********************************************************/
66 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
68 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
70 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
71 if (IsEqualGUID(riid
, &IID_IUnknown
)
72 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
73 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
74 IUnknown_AddRef(iface
);
82 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
83 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
84 ULONG refCount
= InterlockedIncrement(&This
->ref
);
86 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
90 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
91 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
92 ULONG refCount
= InterlockedDecrement(&This
->ref
);
94 TRACE("(%p) : Releasing from %d\n", This
, refCount
+ 1);
99 for (i
= 0; i
< sizeof(This
->multistate_funcs
)/sizeof(This
->multistate_funcs
[0]); ++i
) {
100 HeapFree(GetProcessHeap(), 0, This
->multistate_funcs
[i
]);
101 This
->multistate_funcs
[i
] = NULL
;
104 /* TODO: Clean up all the surfaces and textures! */
105 /* NOTE: You must release the parent if the object was created via a callback
106 ** ***************************/
108 if (!list_empty(&This
->resources
)) {
109 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
110 dumpResources(&This
->resources
);
113 if(This
->contexts
) ERR("Context array not freed!\n");
114 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
115 This
->haveHardwareCursor
= FALSE
;
117 IWineD3D_Release(This
->wineD3D
);
118 This
->wineD3D
= NULL
;
119 HeapFree(GetProcessHeap(), 0, This
);
120 TRACE("Freed device %p\n", This
);
126 /**********************************************************
127 * IWineD3DDevice implementation follows
128 **********************************************************/
129 static HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
130 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
131 *pParent
= This
->parent
;
132 IUnknown_AddRef(This
->parent
);
136 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
137 DWORD FVF
, WINED3DPOOL Pool
, IWineD3DVertexBuffer
** ppVertexBuffer
, HANDLE
*sharedHandle
,
139 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
140 IWineD3DVertexBufferImpl
*object
;
141 WINED3DFORMAT Format
= WINED3DFMT_VERTEXDATA
; /* Dummy format for now */
142 int dxVersion
= ( (IWineD3DImpl
*) This
->wineD3D
)->dxVersion
;
147 WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
148 *ppVertexBuffer
= NULL
;
149 return WINED3DERR_INVALIDCALL
;
150 } else if(Pool
== WINED3DPOOL_SCRATCH
) {
151 /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
152 * anyway, SCRATCH vertex buffers aren't usable anywhere
154 WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
155 *ppVertexBuffer
= NULL
;
156 return WINED3DERR_INVALIDCALL
;
159 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
162 ERR("Out of memory\n");
163 *ppVertexBuffer
= NULL
;
164 return WINED3DERR_OUTOFVIDEOMEMORY
;
167 object
->lpVtbl
= &IWineD3DVertexBuffer_Vtbl
;
168 hr
= resource_init(&object
->resource
, WINED3DRTYPE_VERTEXBUFFER
, This
, Size
, Usage
, Format
, Pool
, parent
);
171 WARN("Failed to initialize resource, returning %#x\n", hr
);
172 HeapFree(GetProcessHeap(), 0, object
);
173 *ppVertexBuffer
= NULL
;
177 TRACE("(%p) : Created resource %p\n", This
, object
);
179 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
181 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
);
182 *ppVertexBuffer
= (IWineD3DVertexBuffer
*)object
;
186 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
187 * drawStridedFast (half-life 2).
189 * Basically converting the vertices in the buffer is quite expensive, and observations
190 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
191 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
193 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
194 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
195 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
196 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
198 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
199 * more. In this call we can convert dx7 buffers too.
201 conv
= ((FVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) || (FVF
& (WINED3DFVF_DIFFUSE
| WINED3DFVF_SPECULAR
));
202 if(!GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
203 TRACE("Not creating a vbo because GL_ARB_vertex_buffer is not supported\n");
204 } else if(Pool
== WINED3DPOOL_SYSTEMMEM
) {
205 TRACE("Not creating a vbo because the vertex buffer is in system memory\n");
206 } else if(Usage
& WINED3DUSAGE_DYNAMIC
) {
207 TRACE("Not creating a vbo because the buffer has dynamic usage\n");
208 } else if(dxVersion
<= 7 && conv
) {
209 TRACE("Not creating a vbo because dxVersion is 7 and the fvf needs conversion\n");
211 object
->Flags
|= VBFLAG_CREATEVBO
;
216 static void CreateIndexBufferVBO(IWineD3DDeviceImpl
*This
, IWineD3DIndexBufferImpl
*object
) {
217 GLenum error
, glUsage
;
218 TRACE("Creating VBO for Index Buffer %p\n", object
);
220 /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
221 * restored on the next draw
223 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
225 /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
226 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
231 GL_EXTCALL(glGenBuffersARB(1, &object
->vbo
));
232 error
= glGetError();
233 if(error
!= GL_NO_ERROR
|| object
->vbo
== 0) {
234 ERR("Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error
), error
);
238 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, object
->vbo
));
239 error
= glGetError();
240 if(error
!= GL_NO_ERROR
) {
241 ERR("Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer\n", debug_glerror(error
), error
);
245 /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
246 * copy no readback will be needed
248 glUsage
= GL_STATIC_DRAW_ARB
;
249 GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, object
->resource
.size
, NULL
, glUsage
));
250 error
= glGetError();
251 if(error
!= GL_NO_ERROR
) {
252 ERR("Failed to initialize the index buffer with error %s (%#x)\n", debug_glerror(error
), error
);
256 TRACE("Successfully created vbo %d for index buffer %p\n", object
->vbo
, object
);
260 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0));
261 GL_EXTCALL(glDeleteBuffersARB(1, &object
->vbo
));
266 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
267 WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DIndexBuffer
** ppIndexBuffer
,
268 HANDLE
*sharedHandle
, IUnknown
*parent
) {
269 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
270 IWineD3DIndexBufferImpl
*object
;
273 TRACE("(%p) Creating index buffer\n", This
);
275 /* Allocate the storage for the device */
276 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
279 ERR("Out of memory\n");
280 *ppIndexBuffer
= NULL
;
281 return WINED3DERR_OUTOFVIDEOMEMORY
;
284 object
->lpVtbl
= &IWineD3DIndexBuffer_Vtbl
;
285 hr
= resource_init(&object
->resource
, WINED3DRTYPE_INDEXBUFFER
, This
, Length
, Usage
, Format
, Pool
, parent
);
288 WARN("Failed to initialize resource, returning %#x\n", hr
);
289 HeapFree(GetProcessHeap(), 0, object
);
290 *ppIndexBuffer
= NULL
;
294 TRACE("(%p) : Created resource %p\n", This
, object
);
296 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
298 if(Pool
!= WINED3DPOOL_SYSTEMMEM
&& !(Usage
& WINED3DUSAGE_DYNAMIC
) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
299 CreateIndexBufferVBO(This
, object
);
302 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This
, Length
, Usage
, Format
,
303 debug_d3dformat(Format
), Pool
, object
, object
->resource
.allocatedMemory
);
304 *ppIndexBuffer
= (IWineD3DIndexBuffer
*) object
;
309 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
* iface
, WINED3DSTATEBLOCKTYPE Type
, IWineD3DStateBlock
** ppStateBlock
, IUnknown
*parent
) {
311 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
312 IWineD3DStateBlockImpl
*object
;
316 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
319 ERR("Out of memory\n");
320 *ppStateBlock
= NULL
;
321 return WINED3DERR_OUTOFVIDEOMEMORY
;
324 object
->lpVtbl
= &IWineD3DStateBlock_Vtbl
;
325 object
->wineD3DDevice
= This
;
326 object
->parent
= parent
;
328 object
->blockType
= Type
;
330 *ppStateBlock
= (IWineD3DStateBlock
*)object
;
332 for(i
= 0; i
< LIGHTMAP_SIZE
; i
++) {
333 list_init(&object
->lightMap
[i
]);
336 temp_result
= allocate_shader_constants(object
);
337 if (FAILED(temp_result
))
339 HeapFree(GetProcessHeap(), 0, object
);
343 /* Special case - Used during initialization to produce a placeholder stateblock
344 so other functions called can update a state block */
345 if (Type
== WINED3DSBT_INIT
|| Type
== WINED3DSBT_RECORDED
)
347 /* Don't bother increasing the reference count otherwise a device will never
348 be freed due to circular dependencies */
352 /* Otherwise, might as well set the whole state block to the appropriate values */
353 if (This
->stateBlock
!= NULL
)
354 stateblock_copy((IWineD3DStateBlock
*) object
, (IWineD3DStateBlock
*) This
->stateBlock
);
356 memset(object
->streamFreq
, 1, sizeof(object
->streamFreq
));
358 /* Reset the ref and type after kludging it */
359 object
->wineD3DDevice
= This
;
361 object
->blockType
= Type
;
363 TRACE("Updating changed flags appropriate for type %d\n", Type
);
365 if (Type
== WINED3DSBT_ALL
) {
367 TRACE("ALL => Pretend everything has changed\n");
368 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, TRUE
);
370 /* Lights are not part of the changed / set structure */
371 for(j
= 0; j
< LIGHTMAP_SIZE
; j
++) {
373 LIST_FOR_EACH(e
, &object
->lightMap
[j
]) {
374 PLIGHTINFOEL
*light
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
375 light
->changed
= TRUE
;
376 light
->enabledChanged
= TRUE
;
379 for(j
= 1; j
<= WINEHIGHEST_RENDER_STATE
; j
++) {
380 object
->contained_render_states
[j
- 1] = j
;
382 object
->num_contained_render_states
= WINEHIGHEST_RENDER_STATE
;
383 /* TODO: Filter unused transforms between TEXTURE8 and WORLD0? */
384 for(j
= 1; j
<= HIGHEST_TRANSFORMSTATE
; j
++) {
385 object
->contained_transform_states
[j
- 1] = j
;
387 object
->num_contained_transform_states
= HIGHEST_TRANSFORMSTATE
;
388 for(j
= 0; j
< GL_LIMITS(vshader_constantsF
); j
++) {
389 object
->contained_vs_consts_f
[j
] = j
;
391 object
->num_contained_vs_consts_f
= GL_LIMITS(vshader_constantsF
);
392 for(j
= 0; j
< MAX_CONST_I
; j
++) {
393 object
->contained_vs_consts_i
[j
] = j
;
395 object
->num_contained_vs_consts_i
= MAX_CONST_I
;
396 for(j
= 0; j
< MAX_CONST_B
; j
++) {
397 object
->contained_vs_consts_b
[j
] = j
;
399 object
->num_contained_vs_consts_b
= MAX_CONST_B
;
400 for(j
= 0; j
< GL_LIMITS(pshader_constantsF
); j
++) {
401 object
->contained_ps_consts_f
[j
] = j
;
403 object
->num_contained_ps_consts_f
= GL_LIMITS(pshader_constantsF
);
404 for(j
= 0; j
< MAX_CONST_I
; j
++) {
405 object
->contained_ps_consts_i
[j
] = j
;
407 object
->num_contained_ps_consts_i
= MAX_CONST_I
;
408 for(j
= 0; j
< MAX_CONST_B
; j
++) {
409 object
->contained_ps_consts_b
[j
] = j
;
411 object
->num_contained_ps_consts_b
= MAX_CONST_B
;
412 for(i
= 0; i
< MAX_TEXTURES
; i
++) {
413 for (j
= 0; j
<= WINED3D_HIGHEST_TEXTURE_STATE
; ++j
)
415 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= i
;
416 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= j
;
417 object
->num_contained_tss_states
++;
420 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
421 for(j
= 1; j
<= WINED3D_HIGHEST_SAMPLER_STATE
; j
++) {
422 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= i
;
423 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= j
;
424 object
->num_contained_sampler_states
++;
428 for(i
= 0; i
< MAX_STREAMS
; i
++) {
429 if(object
->streamSource
[i
]) {
430 IWineD3DVertexBuffer_AddRef(object
->streamSource
[i
]);
433 if(object
->pIndexData
) {
434 IWineD3DIndexBuffer_AddRef(object
->pIndexData
);
436 if(object
->vertexShader
) {
437 IWineD3DVertexShader_AddRef(object
->vertexShader
);
439 if(object
->pixelShader
) {
440 IWineD3DPixelShader_AddRef(object
->pixelShader
);
443 } else if (Type
== WINED3DSBT_PIXELSTATE
) {
445 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
446 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
448 object
->changed
.pixelShader
= TRUE
;
450 /* Pixel Shader Constants */
451 for (i
= 0; i
< GL_LIMITS(pshader_constantsF
); ++i
) {
452 object
->contained_ps_consts_f
[i
] = i
;
453 object
->changed
.pixelShaderConstantsF
[i
] = TRUE
;
455 object
->num_contained_ps_consts_f
= GL_LIMITS(pshader_constantsF
);
456 for (i
= 0; i
< MAX_CONST_B
; ++i
) {
457 object
->contained_ps_consts_b
[i
] = i
;
458 object
->changed
.pixelShaderConstantsB
|= (1 << i
);
460 object
->num_contained_ps_consts_b
= MAX_CONST_B
;
461 for (i
= 0; i
< MAX_CONST_I
; ++i
) {
462 object
->contained_ps_consts_i
[i
] = i
;
463 object
->changed
.pixelShaderConstantsI
|= (1 << i
);
465 object
->num_contained_ps_consts_i
= MAX_CONST_I
;
467 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_R
; i
++) {
468 DWORD rs
= SavedPixelStates_R
[i
];
469 object
->changed
.renderState
[rs
>> 5] |= 1 << (rs
& 0x1f);
470 object
->contained_render_states
[i
] = rs
;
472 object
->num_contained_render_states
= NUM_SAVEDPIXELSTATES_R
;
473 for (j
= 0; j
< MAX_TEXTURES
; j
++) {
474 for (i
= 0; i
< NUM_SAVEDPIXELSTATES_T
; i
++) {
475 DWORD state
= SavedPixelStates_T
[i
];
476 object
->changed
.textureState
[j
] |= 1 << state
;
477 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= j
;
478 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= state
;
479 object
->num_contained_tss_states
++;
482 for (j
= 0 ; j
< MAX_COMBINED_SAMPLERS
; j
++) {
483 for (i
=0; i
< NUM_SAVEDPIXELSTATES_S
;i
++) {
484 DWORD state
= SavedPixelStates_S
[i
];
485 object
->changed
.samplerState
[j
] |= 1 << state
;
486 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= j
;
487 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= state
;
488 object
->num_contained_sampler_states
++;
491 if(object
->pixelShader
) {
492 IWineD3DPixelShader_AddRef(object
->pixelShader
);
495 /* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
496 * on them. This makes releasing the buffer easier
498 for(i
= 0; i
< MAX_STREAMS
; i
++) {
499 object
->streamSource
[i
] = NULL
;
501 object
->pIndexData
= NULL
;
502 object
->vertexShader
= NULL
;
504 } else if (Type
== WINED3DSBT_VERTEXSTATE
) {
506 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
507 stateblock_savedstates_set((IWineD3DStateBlock
*) object
, &object
->changed
, FALSE
);
509 object
->changed
.vertexShader
= TRUE
;
511 /* Vertex Shader Constants */
512 for (i
= 0; i
< GL_LIMITS(vshader_constantsF
); ++i
) {
513 object
->changed
.vertexShaderConstantsF
[i
] = TRUE
;
514 object
->contained_vs_consts_f
[i
] = i
;
516 object
->num_contained_vs_consts_f
= GL_LIMITS(vshader_constantsF
);
517 for (i
= 0; i
< MAX_CONST_B
; ++i
) {
518 object
->contained_vs_consts_b
[i
] = i
;
519 object
->changed
.vertexShaderConstantsB
|= (1 << i
);
521 object
->num_contained_vs_consts_b
= MAX_CONST_B
;
522 for (i
= 0; i
< MAX_CONST_I
; ++i
) {
523 object
->contained_vs_consts_i
[i
] = i
;
524 object
->changed
.vertexShaderConstantsI
|= (1 << i
);
526 object
->num_contained_vs_consts_i
= MAX_CONST_I
;
527 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_R
; i
++) {
528 DWORD rs
= SavedVertexStates_R
[i
];
529 object
->changed
.renderState
[rs
>> 5] |= 1 << (rs
& 0x1f);
530 object
->contained_render_states
[i
] = rs
;
532 object
->num_contained_render_states
= NUM_SAVEDVERTEXSTATES_R
;
533 for (j
= 0; j
< MAX_TEXTURES
; j
++) {
534 for (i
= 0; i
< NUM_SAVEDVERTEXSTATES_T
; i
++) {
535 DWORD state
= SavedVertexStates_T
[i
];
536 object
->changed
.textureState
[j
] |= 1 << state
;
537 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= j
;
538 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= state
;
539 object
->num_contained_tss_states
++;
542 for (j
= 0 ; j
< MAX_COMBINED_SAMPLERS
; j
++){
543 for (i
=0; i
< NUM_SAVEDVERTEXSTATES_S
;i
++) {
544 DWORD state
= SavedVertexStates_S
[i
];
545 object
->changed
.samplerState
[j
] |= 1 << state
;
546 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= j
;
547 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= state
;
548 object
->num_contained_sampler_states
++;
552 for(j
= 0; j
< LIGHTMAP_SIZE
; j
++) {
554 LIST_FOR_EACH(e
, &object
->lightMap
[j
]) {
555 PLIGHTINFOEL
*light
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
556 light
->changed
= TRUE
;
557 light
->enabledChanged
= TRUE
;
561 for(i
= 0; i
< MAX_STREAMS
; i
++) {
562 if(object
->streamSource
[i
]) {
563 IWineD3DVertexBuffer_AddRef(object
->streamSource
[i
]);
566 if(object
->vertexShader
) {
567 IWineD3DVertexShader_AddRef(object
->vertexShader
);
569 object
->pIndexData
= NULL
;
570 object
->pixelShader
= NULL
;
572 FIXME("Unrecognized state block type %d\n", Type
);
575 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, object
);
579 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
) {
580 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
581 IWineD3DSurfaceImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
582 unsigned int Size
= 1;
583 const struct GlPixelFormatDesc
*glDesc
;
584 const StaticPixelFormatDesc
*tableEntry
= getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
588 TRACE("(%p) Create surface\n",This
);
590 if(MultisampleQuality
> 0) {
591 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality
);
592 MultisampleQuality
=0;
595 /** FIXME: Check that the format is supported
597 *******************************/
599 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
600 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
602 *********************************/
603 mul_4w
= (Width
+ 3) & ~3;
604 mul_4h
= (Height
+ 3) & ~3;
605 if (WINED3DFMT_UNKNOWN
== Format
) {
607 } else if (Format
== WINED3DFMT_DXT1
) {
608 /* DXT1 is half byte per pixel */
609 Size
= (mul_4w
* tableEntry
->bpp
* mul_4h
) >> 1;
611 } else if (Format
== WINED3DFMT_DXT2
|| Format
== WINED3DFMT_DXT3
||
612 Format
== WINED3DFMT_DXT4
|| Format
== WINED3DFMT_DXT5
||
613 Format
== WINED3DFMT_ATI2N
) {
614 Size
= (mul_4w
* tableEntry
->bpp
* mul_4h
);
616 /* The pitch is a multiple of 4 bytes */
617 Size
= ((Width
* tableEntry
->bpp
) + This
->surface_alignment
- 1) & ~(This
->surface_alignment
- 1);
621 if(glDesc
->heightscale
!= 0.0) Size
*= glDesc
->heightscale
;
623 /** Create and initialise the surface resource **/
624 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
627 ERR("Out of memory\n");
629 return WINED3DERR_OUTOFVIDEOMEMORY
;
632 /* Look at the implementation and set the correct Vtable */
636 /* Check if a 3D adapter is available when creating gl surfaces */
639 ERR("OpenGL surfaces are not available without opengl\n");
640 HeapFree(GetProcessHeap(), 0, object
);
641 return WINED3DERR_NOTAVAILABLE
;
643 object
->lpVtbl
= &IWineD3DSurface_Vtbl
;
647 object
->lpVtbl
= &IWineGDISurface_Vtbl
;
651 /* To be sure to catch this */
652 ERR("Unknown requested surface implementation %d!\n", Impl
);
653 HeapFree(GetProcessHeap(), 0, object
);
654 return WINED3DERR_INVALIDCALL
;
657 hr
= resource_init(&object
->resource
, WINED3DRTYPE_SURFACE
, This
, Size
, Usage
, Format
, Pool
, parent
);
660 WARN("Failed to initialize resource, returning %#x\n", hr
);
661 HeapFree(GetProcessHeap(), 0, object
);
666 TRACE("(%p) : Created resource %p\n", This
, object
);
668 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
670 *ppSurface
= (IWineD3DSurface
*)object
;
672 /* "Standalone" surface */
673 IWineD3DSurface_SetContainer((IWineD3DSurface
*)object
, NULL
);
675 object
->currentDesc
.Width
= Width
;
676 object
->currentDesc
.Height
= Height
;
677 object
->currentDesc
.MultiSampleType
= MultiSample
;
678 object
->currentDesc
.MultiSampleQuality
= MultisampleQuality
;
679 object
->glDescription
.level
= Level
;
680 object
->heightscale
= glDesc
->heightscale
!= 0.0 ? glDesc
->heightscale
: 1.0;
681 list_init(&object
->overlays
);
684 object
->Flags
= SFLAG_NORMCOORD
; /* Default to normalized coords */
685 object
->Flags
|= Discard
? SFLAG_DISCARD
: 0;
686 object
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== Format
) ? SFLAG_LOCKABLE
: 0;
687 object
->Flags
|= Lockable
? SFLAG_LOCKABLE
: 0;
690 if (WINED3DFMT_UNKNOWN
!= Format
) {
691 object
->bytesPerPixel
= tableEntry
->bpp
;
693 object
->bytesPerPixel
= 0;
696 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
698 TRACE("Pool %d %d %d %d\n",Pool
, WINED3DPOOL_DEFAULT
, WINED3DPOOL_MANAGED
, WINED3DPOOL_SYSTEMMEM
);
700 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
701 * this function is too deep to need to care about things like this.
702 * Levels need to be checked too, and possibly Type since they all affect what can be done.
703 * ****************************************/
705 case WINED3DPOOL_SCRATCH
:
707 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
708 "which are mutually exclusive, setting lockable to TRUE\n");
711 case WINED3DPOOL_SYSTEMMEM
:
712 if(!Lockable
) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
713 "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
714 case WINED3DPOOL_MANAGED
:
715 if(Usage
== WINED3DUSAGE_DYNAMIC
) FIXME("Create surface called with a pool of MANAGED and a "
716 "Usage of DYNAMIC which are mutually exclusive, not doing "
717 "anything just telling you.\n");
719 case WINED3DPOOL_DEFAULT
: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
720 if(!(Usage
& WINED3DUSAGE_DYNAMIC
) && !(Usage
& WINED3DUSAGE_RENDERTARGET
)
721 && !(Usage
&& WINED3DUSAGE_DEPTHSTENCIL
) && Lockable
)
722 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
725 FIXME("(%p) Unknown pool %d\n", This
, Pool
);
729 if (Usage
& WINED3DUSAGE_RENDERTARGET
&& Pool
!= WINED3DPOOL_DEFAULT
) {
730 FIXME("Trying to create a render target that isn't in the default pool\n");
733 /* mark the texture as dirty so that it gets loaded first time around*/
734 surface_add_dirty_rect(*ppSurface
, NULL
);
735 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
736 This
, Width
, Height
, Format
, debug_d3dformat(Format
),
737 (WINED3DFMT_D16_LOCKABLE
== Format
), *ppSurface
, object
->resource
.allocatedMemory
, object
->resource
.size
);
739 list_init(&object
->renderbuffers
);
741 /* Call the private setup routine */
742 hr
= IWineD3DSurface_PrivateSetup((IWineD3DSurface
*)object
);
745 ERR("Private setup failed, returning %#x\n", hr
);
746 IWineD3DSurface_Release(*ppSurface
);
754 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
,
755 UINT Width
, UINT Height
, UINT Levels
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
756 IWineD3DTexture
**ppTexture
, HANDLE
*pSharedHandle
, IUnknown
*parent
)
758 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
759 IWineD3DTextureImpl
*object
;
764 unsigned int pow2Width
;
765 unsigned int pow2Height
;
766 const struct 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 /* Non-power2 support */
781 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
))
788 /* Find the nearest pow2 match */
789 pow2Width
= pow2Height
= 1;
790 while (pow2Width
< Width
) pow2Width
<<= 1;
791 while (pow2Height
< Height
) pow2Height
<<= 1;
793 if (pow2Width
!= Width
|| pow2Height
!= Height
)
797 WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n");
798 return WINED3DERR_INVALIDCALL
;
804 /* Calculate levels for mip mapping */
805 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
)
807 if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP
))
809 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
810 return WINED3DERR_INVALIDCALL
;
815 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
816 return WINED3DERR_INVALIDCALL
;
823 Levels
= wined3d_log2i(max(Width
, Height
)) + 1;
824 TRACE("Calculated levels = %d\n", Levels
);
827 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
830 ERR("Out of memory\n");
832 return WINED3DERR_OUTOFVIDEOMEMORY
;
835 object
->lpVtbl
= &IWineD3DTexture_Vtbl
;
836 hr
= resource_init(&object
->resource
, WINED3DRTYPE_TEXTURE
, This
, 0, Usage
, Format
, Pool
, parent
);
839 WARN("Failed to initialize resource, returning %#x\n", hr
);
840 HeapFree(GetProcessHeap(), 0, object
);
845 TRACE("(%p) : Created resource %p\n", This
, object
);
847 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
849 *ppTexture
= (IWineD3DTexture
*)object
;
851 basetexture_init(&object
->baseTexture
, Levels
, Usage
);
852 object
->width
= Width
;
853 object
->height
= Height
;
855 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
856 object
->baseTexture
.minMipLookup
= minMipLookup
;
857 object
->baseTexture
.magLookup
= magLookup
;
859 object
->baseTexture
.minMipLookup
= minMipLookup_noFilter
;
860 object
->baseTexture
.magLookup
= magLookup_noFilter
;
863 /** FIXME: add support for real non-power-two if it's provided by the video card **/
864 /* Precalculated scaling for 'faked' non power of two texture coords.
865 Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
866 is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
867 doesn't work in combination with ARB_TEXTURE_RECTANGLE.
869 if(GL_SUPPORT(WINE_NORMALIZED_TEXRECT
) && (Width
!= pow2Width
|| Height
!= pow2Height
)) {
870 object
->baseTexture
.pow2Matrix
[0] = 1.0;
871 object
->baseTexture
.pow2Matrix
[5] = 1.0;
872 object
->baseTexture
.pow2Matrix
[10] = 1.0;
873 object
->baseTexture
.pow2Matrix
[15] = 1.0;
874 object
->target
= GL_TEXTURE_2D
;
875 object
->cond_np2
= TRUE
;
876 object
->baseTexture
.minMipLookup
= minMipLookup_noFilter
;
877 } else if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE
) &&
878 (Width
!= pow2Width
|| Height
!= pow2Height
) &&
879 !((Format
== WINED3DFMT_P8
) && GL_SUPPORT(EXT_PALETTED_TEXTURE
) && (wined3d_settings
.rendertargetlock_mode
== RTL_READTEX
|| wined3d_settings
.rendertargetlock_mode
== RTL_TEXTEX
)))
881 object
->baseTexture
.pow2Matrix
[0] = (float)Width
;
882 object
->baseTexture
.pow2Matrix
[5] = (float)Height
;
883 object
->baseTexture
.pow2Matrix
[10] = 1.0;
884 object
->baseTexture
.pow2Matrix
[15] = 1.0;
885 object
->target
= GL_TEXTURE_RECTANGLE_ARB
;
886 object
->cond_np2
= TRUE
;
887 object
->baseTexture
.minMipLookup
= minMipLookup_noFilter
;
889 object
->baseTexture
.pow2Matrix
[0] = (((float)Width
) / ((float)pow2Width
));
890 object
->baseTexture
.pow2Matrix
[5] = (((float)Height
) / ((float)pow2Height
));
891 object
->baseTexture
.pow2Matrix
[10] = 1.0;
892 object
->baseTexture
.pow2Matrix
[15] = 1.0;
893 object
->target
= GL_TEXTURE_2D
;
894 object
->cond_np2
= FALSE
;
896 TRACE(" xf(%f) yf(%f)\n", object
->baseTexture
.pow2Matrix
[0], object
->baseTexture
.pow2Matrix
[5]);
898 /* Generate all the surfaces */
901 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
903 /* use the callback to create the texture surface */
904 hr
= IWineD3DDeviceParent_CreateSurface(This
->device_parent
, parent
, tmpW
, tmpH
, Format
,
905 Usage
, Pool
, i
, WINED3DCUBEMAP_FACE_POSITIVE_X
, &object
->surfaces
[i
]);
906 if (hr
!= WINED3D_OK
|| ( (IWineD3DSurfaceImpl
*) object
->surfaces
[i
])->Flags
& SFLAG_OVERSIZE
) {
907 FIXME("Failed to create surface %p\n", object
);
909 object
->surfaces
[i
] = NULL
;
910 IWineD3DTexture_Release((IWineD3DTexture
*)object
);
916 IWineD3DSurface_SetContainer(object
->surfaces
[i
], (IWineD3DBase
*)object
);
917 TRACE("Created surface level %d @ %p\n", i
, object
->surfaces
[i
]);
918 surface_set_texture_target(object
->surfaces
[i
], object
->target
);
919 /* calculate the next mipmap level */
920 tmpW
= max(1, tmpW
>> 1);
921 tmpH
= max(1, tmpH
>> 1);
923 object
->baseTexture
.shader_color_fixup
= glDesc
->color_fixup
;
924 object
->baseTexture
.internal_preload
= texture_internal_preload
;
926 TRACE("(%p) : Created texture %p\n", This
, object
);
930 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
931 UINT Width
, UINT Height
, UINT Depth
, UINT Levels
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
932 IWineD3DVolumeTexture
**ppVolumeTexture
, HANDLE
*pSharedHandle
, IUnknown
*parent
)
934 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
935 IWineD3DVolumeTextureImpl
*object
;
940 const struct GlPixelFormatDesc
*glDesc
;
943 getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
945 /* TODO: It should only be possible to create textures for formats
946 that are reported as supported */
947 if (WINED3DFMT_UNKNOWN
>= Format
) {
948 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This
);
949 return WINED3DERR_INVALIDCALL
;
951 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
952 WARN("(%p) : Texture cannot be created - no volume texture support\n", This
);
953 return WINED3DERR_INVALIDCALL
;
956 /* Calculate levels for mip mapping */
957 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
)
959 if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP
))
961 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
962 return WINED3DERR_INVALIDCALL
;
967 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
968 return WINED3DERR_INVALIDCALL
;
975 Levels
= wined3d_log2i(max(max(Width
, Height
), Depth
)) + 1;
976 TRACE("Calculated levels = %d\n", Levels
);
979 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
982 ERR("Out of memory\n");
983 *ppVolumeTexture
= NULL
;
984 return WINED3DERR_OUTOFVIDEOMEMORY
;
987 object
->lpVtbl
= &IWineD3DVolumeTexture_Vtbl
;
988 hr
= resource_init(&object
->resource
, WINED3DRTYPE_VOLUMETEXTURE
, This
, 0, Usage
, Format
, Pool
, parent
);
991 WARN("Failed to initialize resource, returning %#x\n", hr
);
992 HeapFree(GetProcessHeap(), 0, object
);
993 *ppVolumeTexture
= NULL
;
997 TRACE("(%p) : Created resource %p\n", This
, object
);
999 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
1001 basetexture_init(&object
->baseTexture
, Levels
, Usage
);
1003 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1004 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1006 /* Is NP2 support for volumes needed? */
1007 object
->baseTexture
.pow2Matrix
[ 0] = 1.0;
1008 object
->baseTexture
.pow2Matrix
[ 5] = 1.0;
1009 object
->baseTexture
.pow2Matrix
[10] = 1.0;
1010 object
->baseTexture
.pow2Matrix
[15] = 1.0;
1012 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
1013 object
->baseTexture
.minMipLookup
= minMipLookup
;
1014 object
->baseTexture
.magLookup
= magLookup
;
1016 object
->baseTexture
.minMipLookup
= minMipLookup_noFilter
;
1017 object
->baseTexture
.magLookup
= magLookup_noFilter
;
1020 /* Generate all the surfaces */
1025 for (i
= 0; i
< object
->baseTexture
.levels
; i
++)
1028 /* Create the volume */
1029 hr
= IWineD3DDeviceParent_CreateVolume(This
->device_parent
, parent
,
1030 tmpW
, tmpH
, tmpD
, Format
, Pool
, Usage
, &object
->volumes
[i
]);
1032 ERR("Creating a volume for the volume texture failed(%08x)\n", hr
);
1033 IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture
*) object
);
1034 *ppVolumeTexture
= NULL
;
1038 /* Set its container to this object */
1039 IWineD3DVolume_SetContainer(object
->volumes
[i
], (IWineD3DBase
*)object
);
1041 /* calculate the next mipmap level */
1042 tmpW
= max(1, tmpW
>> 1);
1043 tmpH
= max(1, tmpH
>> 1);
1044 tmpD
= max(1, tmpD
>> 1);
1046 object
->baseTexture
.shader_color_fixup
= glDesc
->color_fixup
;
1047 object
->baseTexture
.internal_preload
= volumetexture_internal_preload
;
1049 *ppVolumeTexture
= (IWineD3DVolumeTexture
*) object
;
1050 TRACE("(%p) : Created volume texture %p\n", This
, object
);
1054 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
,
1055 UINT Width
, UINT Height
, UINT Depth
,
1057 WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1058 IWineD3DVolume
** ppVolume
,
1059 HANDLE
* pSharedHandle
, IUnknown
*parent
) {
1061 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1062 IWineD3DVolumeImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1063 const StaticPixelFormatDesc
*formatDesc
= getFormatDescEntry(Format
, NULL
, NULL
);
1066 if(!GL_SUPPORT(EXT_TEXTURE3D
)) {
1067 WARN("(%p) : Volume cannot be created - no volume texture support\n", This
);
1068 return WINED3DERR_INVALIDCALL
;
1071 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1074 ERR("Out of memory\n");
1076 return WINED3DERR_OUTOFVIDEOMEMORY
;
1079 object
->lpVtbl
= &IWineD3DVolume_Vtbl
;
1080 hr
= resource_init(&object
->resource
, WINED3DRTYPE_VOLUME
, This
,
1081 Width
* Height
* Depth
* formatDesc
->bpp
, Usage
, Format
, Pool
, parent
);
1084 WARN("Failed to initialize resource, returning %#x\n", hr
);
1085 HeapFree(GetProcessHeap(), 0, object
);
1090 TRACE("(%p) : Created resource %p\n", This
, object
);
1092 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
1094 *ppVolume
= (IWineD3DVolume
*)object
;
1096 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1097 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1099 object
->currentDesc
.Width
= Width
;
1100 object
->currentDesc
.Height
= Height
;
1101 object
->currentDesc
.Depth
= Depth
;
1102 object
->bytesPerPixel
= formatDesc
->bpp
;
1104 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1105 object
->lockable
= TRUE
;
1106 object
->locked
= FALSE
;
1107 memset(&object
->lockedBox
, 0, sizeof(WINED3DBOX
));
1108 object
->dirty
= TRUE
;
1110 volume_add_dirty_box((IWineD3DVolume
*)object
, NULL
);
1115 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
,
1116 UINT EdgeLength
, UINT Levels
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
1117 IWineD3DCubeTexture
**ppCubeTexture
, HANDLE
*pSharedHandle
, IUnknown
*parent
)
1119 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1120 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1124 unsigned int pow2EdgeLength
;
1125 const struct GlPixelFormatDesc
*glDesc
;
1126 getFormatDescEntry(Format
, &GLINFO_LOCATION
, &glDesc
);
1128 /* TODO: It should only be possible to create textures for formats
1129 that are reported as supported */
1130 if (WINED3DFMT_UNKNOWN
>= Format
) {
1131 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This
);
1132 return WINED3DERR_INVALIDCALL
;
1135 if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
) && Pool
!= WINED3DPOOL_SCRATCH
) {
1136 WARN("(%p) : Tried to create not supported cube texture\n", This
);
1137 return WINED3DERR_INVALIDCALL
;
1140 /* Calculate levels for mip mapping */
1141 if (Usage
& WINED3DUSAGE_AUTOGENMIPMAP
)
1143 if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP
))
1145 WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
1146 return WINED3DERR_INVALIDCALL
;
1151 WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
1152 return WINED3DERR_INVALIDCALL
;
1159 Levels
= wined3d_log2i(EdgeLength
) + 1;
1160 TRACE("Calculated levels = %d\n", Levels
);
1163 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1166 ERR("Out of memory\n");
1167 *ppCubeTexture
= NULL
;
1168 return WINED3DERR_OUTOFVIDEOMEMORY
;
1171 object
->lpVtbl
= &IWineD3DCubeTexture_Vtbl
;
1172 hr
= resource_init(&object
->resource
, WINED3DRTYPE_CUBETEXTURE
, This
, 0, Usage
, Format
, Pool
, parent
);
1175 WARN("Failed to initialize resource, returning %#x\n", hr
);
1176 HeapFree(GetProcessHeap(), 0, object
);
1177 *ppCubeTexture
= NULL
;
1181 TRACE("(%p) : Created resource %p\n", This
, object
);
1183 IWineD3DDeviceImpl_AddResource(iface
, (IWineD3DResource
*)object
);
1185 basetexture_init(&object
->baseTexture
, Levels
, Usage
);
1187 TRACE("(%p) Create Cube Texture\n", This
);
1189 /* Find the nearest pow2 match */
1191 while (pow2EdgeLength
< EdgeLength
) pow2EdgeLength
<<= 1;
1193 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
)) {
1194 /* Precalculated scaling for 'faked' non power of two texture coords */
1195 object
->baseTexture
.pow2Matrix
[ 0] = 1.0;
1196 object
->baseTexture
.pow2Matrix
[ 5] = 1.0;
1197 object
->baseTexture
.pow2Matrix
[10] = 1.0;
1198 object
->baseTexture
.pow2Matrix
[15] = 1.0;
1200 /* Precalculated scaling for 'faked' non power of two texture coords */
1201 object
->baseTexture
.pow2Matrix
[ 0] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1202 object
->baseTexture
.pow2Matrix
[ 5] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1203 object
->baseTexture
.pow2Matrix
[10] = ((float)EdgeLength
) / ((float)pow2EdgeLength
);
1204 object
->baseTexture
.pow2Matrix
[15] = 1.0;
1207 if(glDesc
->Flags
& WINED3DFMT_FLAG_FILTERING
) {
1208 object
->baseTexture
.minMipLookup
= minMipLookup
;
1209 object
->baseTexture
.magLookup
= magLookup
;
1211 object
->baseTexture
.minMipLookup
= minMipLookup_noFilter
;
1212 object
->baseTexture
.magLookup
= magLookup_noFilter
;
1215 /* Generate all the surfaces */
1217 for (i
= 0; i
< object
->baseTexture
.levels
; i
++) {
1219 /* Create the 6 faces */
1220 for (j
= 0; j
< 6; j
++) {
1221 static const GLenum cube_targets
[6] = {
1222 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
,
1223 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
,
1224 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
,
1225 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
,
1226 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
,
1227 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
1230 hr
= IWineD3DDeviceParent_CreateSurface(This
->device_parent
, parent
, tmpW
, tmpW
,
1231 Format
, Usage
, Pool
, i
/* Level */, j
, &object
->surfaces
[j
][i
]);
1234 FIXME("(%p) Failed to create surface\n",object
);
1235 IWineD3DCubeTexture_Release((IWineD3DCubeTexture
*)object
);
1236 *ppCubeTexture
= NULL
;
1239 IWineD3DSurface_SetContainer(object
->surfaces
[j
][i
], (IWineD3DBase
*)object
);
1240 TRACE("Created surface level %d @ %p,\n", i
, object
->surfaces
[j
][i
]);
1241 surface_set_texture_target(object
->surfaces
[j
][i
], cube_targets
[j
]);
1243 tmpW
= max(1, tmpW
>> 1);
1245 object
->baseTexture
.shader_color_fixup
= glDesc
->color_fixup
;
1246 object
->baseTexture
.internal_preload
= cubetexture_internal_preload
;
1248 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1249 *ppCubeTexture
= (IWineD3DCubeTexture
*) object
;
1253 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
, WINED3DQUERYTYPE Type
, IWineD3DQuery
**ppQuery
, IUnknown
* parent
) {
1254 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1255 IWineD3DQueryImpl
*object
; /*NOTE: impl ref allowed since this is a create function */
1256 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1257 const IWineD3DQueryVtbl
*vtable
;
1259 /* Just a check to see if we support this type of query */
1261 case WINED3DQUERYTYPE_OCCLUSION
:
1262 TRACE("(%p) occlusion query\n", This
);
1263 if (GL_SUPPORT(ARB_OCCLUSION_QUERY
))
1266 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1268 vtable
= &IWineD3DOcclusionQuery_Vtbl
;
1271 case WINED3DQUERYTYPE_EVENT
:
1272 if(!(GL_SUPPORT(NV_FENCE
) || GL_SUPPORT(APPLE_FENCE
) )) {
1273 /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1274 * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1276 FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This
);
1278 vtable
= &IWineD3DEventQuery_Vtbl
;
1282 case WINED3DQUERYTYPE_VCACHE
:
1283 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1284 case WINED3DQUERYTYPE_VERTEXSTATS
:
1285 case WINED3DQUERYTYPE_TIMESTAMP
:
1286 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1287 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1288 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1289 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1290 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1291 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1292 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1293 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1295 /* Use the base Query vtable until we have a special one for each query */
1296 vtable
= &IWineD3DQuery_Vtbl
;
1297 FIXME("(%p) Unhandled query type %d\n", This
, Type
);
1299 if(NULL
== ppQuery
|| hr
!= WINED3D_OK
) {
1303 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1306 ERR("Out of memory\n");
1308 return WINED3DERR_OUTOFVIDEOMEMORY
;
1311 object
->lpVtbl
= vtable
;
1312 object
->type
= Type
;
1313 object
->state
= QUERY_CREATED
;
1314 object
->wineD3DDevice
= This
;
1315 object
->parent
= parent
;
1318 *ppQuery
= (IWineD3DQuery
*)object
;
1320 /* allocated the 'extended' data based on the type of query requested */
1322 case WINED3DQUERYTYPE_OCCLUSION
:
1323 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryOcclusionData
));
1324 ((WineQueryOcclusionData
*)(object
->extendedData
))->ctx
= This
->activeContext
;
1326 if(GL_SUPPORT(ARB_OCCLUSION_QUERY
)) {
1327 TRACE("(%p) Allocating data for an occlusion query\n", This
);
1329 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
1331 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData
*)(object
->extendedData
))->queryId
));
1335 case WINED3DQUERYTYPE_EVENT
:
1336 object
->extendedData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WineQueryEventData
));
1337 ((WineQueryEventData
*)(object
->extendedData
))->ctx
= This
->activeContext
;
1339 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
1341 if(GL_SUPPORT(APPLE_FENCE
)) {
1342 GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData
*)(object
->extendedData
))->fenceId
));
1343 checkGLcall("glGenFencesAPPLE");
1344 } else if(GL_SUPPORT(NV_FENCE
)) {
1345 GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData
*)(object
->extendedData
))->fenceId
));
1346 checkGLcall("glGenFencesNV");
1351 case WINED3DQUERYTYPE_VCACHE
:
1352 case WINED3DQUERYTYPE_RESOURCEMANAGER
:
1353 case WINED3DQUERYTYPE_VERTEXSTATS
:
1354 case WINED3DQUERYTYPE_TIMESTAMP
:
1355 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT
:
1356 case WINED3DQUERYTYPE_TIMESTAMPFREQ
:
1357 case WINED3DQUERYTYPE_PIPELINETIMINGS
:
1358 case WINED3DQUERYTYPE_INTERFACETIMINGS
:
1359 case WINED3DQUERYTYPE_VERTEXTIMINGS
:
1360 case WINED3DQUERYTYPE_PIXELTIMINGS
:
1361 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS
:
1362 case WINED3DQUERYTYPE_CACHEUTILIZATION
:
1364 object
->extendedData
= 0;
1365 FIXME("(%p) Unhandled query type %d\n",This
, Type
);
1367 TRACE("(%p) : Created Query %p\n", This
, object
);
1371 /*****************************************************************************
1372 * IWineD3DDeviceImpl_SetupFullscreenWindow
1374 * Helper function that modifies a HWND's Style and ExStyle for proper
1378 * iface: Pointer to the IWineD3DDevice interface
1379 * window: Window to setup
1381 *****************************************************************************/
1382 static LONG
fullscreen_style(LONG orig_style
) {
1383 LONG style
= orig_style
;
1384 style
&= ~WS_CAPTION
;
1385 style
&= ~WS_THICKFRAME
;
1387 /* Make sure the window is managed, otherwise we won't get keyboard input */
1388 style
|= WS_POPUP
| WS_SYSMENU
;
1393 static LONG
fullscreen_exStyle(LONG orig_exStyle
) {
1394 LONG exStyle
= orig_exStyle
;
1396 /* Filter out window decorations */
1397 exStyle
&= ~WS_EX_WINDOWEDGE
;
1398 exStyle
&= ~WS_EX_CLIENTEDGE
;
1403 static void IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice
*iface
, HWND window
, UINT w
, UINT h
) {
1404 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1406 LONG style
, exStyle
;
1407 /* Don't do anything if an original style is stored.
1408 * That shouldn't happen
1410 TRACE("(%p): Setting up window %p for exclusive mode\n", This
, window
);
1411 if (This
->style
|| This
->exStyle
) {
1412 ERR("(%p): Want to change the window parameters of HWND %p, but "
1413 "another style is stored for restoration afterwards\n", This
, window
);
1416 /* Get the parameters and save them */
1417 style
= GetWindowLongW(window
, GWL_STYLE
);
1418 exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1419 This
->style
= style
;
1420 This
->exStyle
= exStyle
;
1422 style
= fullscreen_style(style
);
1423 exStyle
= fullscreen_exStyle(exStyle
);
1425 TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1426 This
->style
, This
->exStyle
, style
, exStyle
);
1428 SetWindowLongW(window
, GWL_STYLE
, style
);
1429 SetWindowLongW(window
, GWL_EXSTYLE
, exStyle
);
1431 /* Inform the window about the update. */
1432 SetWindowPos(window
, HWND_TOP
, 0, 0,
1433 w
, h
, SWP_FRAMECHANGED
| SWP_SHOWWINDOW
);
1436 /*****************************************************************************
1437 * IWineD3DDeviceImpl_RestoreWindow
1439 * Helper function that restores a windows' properties when taking it out
1440 * of fullscreen mode
1443 * iface: Pointer to the IWineD3DDevice interface
1444 * window: Window to setup
1446 *****************************************************************************/
1447 static void IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice
*iface
, HWND window
) {
1448 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1449 LONG style
, exStyle
;
1451 /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1452 * switch, do nothing
1454 if (!This
->style
&& !This
->exStyle
) return;
1456 TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1457 This
, window
, This
->style
, This
->exStyle
);
1459 style
= GetWindowLongW(window
, GWL_STYLE
);
1460 exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1462 /* Only restore the style if the application didn't modify it during the fullscreen phase.
1463 * Some applications change it before calling Reset() when switching between windowed and
1464 * fullscreen modes(HL2), some depend on the original style(Eve Online)
1466 if(style
== fullscreen_style(This
->style
) &&
1467 exStyle
== fullscreen_style(This
->exStyle
)) {
1468 SetWindowLongW(window
, GWL_STYLE
, This
->style
);
1469 SetWindowLongW(window
, GWL_EXSTYLE
, This
->exStyle
);
1472 /* Delete the old values */
1476 /* Inform the window about the update */
1477 SetWindowPos(window
, 0 /* InsertAfter, ignored */,
1478 0, 0, 0, 0, /* Pos, Size, ignored */
1479 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
);
1482 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1483 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice
*iface
,
1484 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
, IWineD3DSwapChain
**ppSwapChain
,
1485 IUnknown
*parent
, WINED3DSURFTYPE surface_type
)
1487 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1490 IWineD3DSwapChainImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1492 IUnknown
*bufferParent
;
1493 BOOL displaymode_set
= FALSE
;
1494 WINED3DDISPLAYMODE Mode
;
1495 const StaticPixelFormatDesc
*formatDesc
;
1497 TRACE("(%p) : Created Additional Swap Chain\n", This
);
1499 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1500 * does a device hold a reference to a swap chain giving them a lifetime of the device
1501 * or does the swap chain notify the device of its destruction.
1502 *******************************/
1504 /* Check the params */
1505 if(pPresentationParameters
->BackBufferCount
> WINED3DPRESENT_BACK_BUFFER_MAX
) {
1506 ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters
->BackBufferCount
);
1507 return WINED3DERR_INVALIDCALL
;
1508 } else if (pPresentationParameters
->BackBufferCount
> 1) {
1509 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");
1512 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1515 ERR("Out of memory\n");
1516 *ppSwapChain
= NULL
;
1517 return WINED3DERR_OUTOFVIDEOMEMORY
;
1520 switch(surface_type
) {
1522 object
->lpVtbl
= &IWineGDISwapChain_Vtbl
;
1524 case SURFACE_OPENGL
:
1525 object
->lpVtbl
= &IWineD3DSwapChain_Vtbl
;
1527 case SURFACE_UNKNOWN
:
1528 FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n");
1529 HeapFree(GetProcessHeap(), 0, object
);
1530 return WINED3DERR_INVALIDCALL
;
1532 object
->wineD3DDevice
= This
;
1533 object
->parent
= parent
;
1536 *ppSwapChain
= (IWineD3DSwapChain
*)object
;
1538 /*********************
1539 * Lookup the window Handle and the relating X window handle
1540 ********************/
1542 /* Setup hwnd we are using, plus which display this equates to */
1543 object
->win_handle
= pPresentationParameters
->hDeviceWindow
;
1544 if (!object
->win_handle
) {
1545 object
->win_handle
= This
->createParms
.hFocusWindow
;
1547 if(!pPresentationParameters
->Windowed
&& object
->win_handle
) {
1548 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, object
->win_handle
,
1549 pPresentationParameters
->BackBufferWidth
,
1550 pPresentationParameters
->BackBufferHeight
);
1553 hDc
= GetDC(object
->win_handle
);
1554 TRACE("Using hDc %p\n", hDc
);
1557 WARN("Failed to get a HDc for Window %p\n", object
->win_handle
);
1558 return WINED3DERR_NOTAVAILABLE
;
1561 /* Get info on the current display setup */
1562 IWineD3D_GetAdapterDisplayMode(This
->wineD3D
, This
->adapter
->num
, &Mode
);
1563 object
->orig_width
= Mode
.Width
;
1564 object
->orig_height
= Mode
.Height
;
1565 object
->orig_fmt
= Mode
.Format
;
1566 formatDesc
= getFormatDescEntry(Mode
.Format
, NULL
, NULL
);
1568 if (pPresentationParameters
->Windowed
&&
1569 ((pPresentationParameters
->BackBufferWidth
== 0) ||
1570 (pPresentationParameters
->BackBufferHeight
== 0) ||
1571 (pPresentationParameters
->BackBufferFormat
== WINED3DFMT_UNKNOWN
))) {
1574 GetClientRect(object
->win_handle
, &Rect
);
1576 if (pPresentationParameters
->BackBufferWidth
== 0) {
1577 pPresentationParameters
->BackBufferWidth
= Rect
.right
;
1578 TRACE("Updating width to %d\n", pPresentationParameters
->BackBufferWidth
);
1580 if (pPresentationParameters
->BackBufferHeight
== 0) {
1581 pPresentationParameters
->BackBufferHeight
= Rect
.bottom
;
1582 TRACE("Updating height to %d\n", pPresentationParameters
->BackBufferHeight
);
1584 if (pPresentationParameters
->BackBufferFormat
== WINED3DFMT_UNKNOWN
) {
1585 pPresentationParameters
->BackBufferFormat
= object
->orig_fmt
;
1586 TRACE("Updating format to %s\n", debug_d3dformat(object
->orig_fmt
));
1590 /* Put the correct figures in the presentation parameters */
1591 TRACE("Copying across presentation parameters\n");
1592 object
->presentParms
= *pPresentationParameters
;
1594 TRACE("calling rendertarget CB\n");
1595 hr
= IWineD3DDeviceParent_CreateRenderTarget(This
->device_parent
, parent
,
1596 object
->presentParms
.BackBufferWidth
, object
->presentParms
.BackBufferHeight
,
1597 object
->presentParms
.BackBufferFormat
, object
->presentParms
.MultiSampleType
,
1598 object
->presentParms
.MultiSampleQuality
, TRUE
/* Lockable */, &object
->frontBuffer
);
1599 if (SUCCEEDED(hr
)) {
1600 IWineD3DSurface_SetContainer(object
->frontBuffer
, (IWineD3DBase
*)object
);
1601 if(surface_type
== SURFACE_OPENGL
) {
1602 IWineD3DSurface_ModifyLocation(object
->frontBuffer
, SFLAG_INDRAWABLE
, TRUE
);
1605 ERR("Failed to create the front buffer\n");
1609 /*********************
1610 * Windowed / Fullscreen
1611 *******************/
1614 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1615 * so we should really check to see if there is a fullscreen swapchain already
1616 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1617 **************************************/
1619 if (!pPresentationParameters
->Windowed
) {
1620 WINED3DDISPLAYMODE mode
;
1623 /* Change the display settings */
1624 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
1625 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
1626 mode
.Format
= pPresentationParameters
->BackBufferFormat
;
1627 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
1629 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
1630 displaymode_set
= TRUE
;
1634 * Create an opengl context for the display visual
1635 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1636 * use different properties after that point in time. FIXME: How to handle when requested format
1637 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1638 * it chooses is identical to the one already being used!
1639 **********************************/
1640 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1642 object
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(object
->context
));
1643 if(!object
->context
) {
1644 ERR("Failed to create the context array\n");
1648 object
->num_contexts
= 1;
1650 if(surface_type
== SURFACE_OPENGL
) {
1651 object
->context
[0] = CreateContext(This
, (IWineD3DSurfaceImpl
*) object
->frontBuffer
, object
->win_handle
, FALSE
/* pbuffer */, pPresentationParameters
);
1652 if (!object
->context
[0]) {
1653 ERR("Failed to create a new context\n");
1654 hr
= WINED3DERR_NOTAVAILABLE
;
1657 TRACE("Context created (HWND=%p, glContext=%p)\n",
1658 object
->win_handle
, object
->context
[0]->glCtx
);
1662 /*********************
1663 * Create the back, front and stencil buffers
1664 *******************/
1665 if(object
->presentParms
.BackBufferCount
> 0) {
1668 object
->backBuffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface
*) * object
->presentParms
.BackBufferCount
);
1669 if(!object
->backBuffer
) {
1670 ERR("Out of memory\n");
1675 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1676 TRACE("calling rendertarget CB\n");
1677 hr
= IWineD3DDeviceParent_CreateRenderTarget(This
->device_parent
, parent
,
1678 object
->presentParms
.BackBufferWidth
, object
->presentParms
.BackBufferHeight
,
1679 object
->presentParms
.BackBufferFormat
, object
->presentParms
.MultiSampleType
,
1680 object
->presentParms
.MultiSampleQuality
, TRUE
/* Lockable */, &object
->backBuffer
[i
]);
1682 IWineD3DSurface_SetContainer(object
->backBuffer
[i
], (IWineD3DBase
*)object
);
1684 ERR("Cannot create new back buffer\n");
1687 if(surface_type
== SURFACE_OPENGL
) {
1689 glDrawBuffer(GL_BACK
);
1690 checkGLcall("glDrawBuffer(GL_BACK)");
1695 object
->backBuffer
= NULL
;
1697 /* Single buffering - draw to front buffer */
1698 if(surface_type
== SURFACE_OPENGL
) {
1700 glDrawBuffer(GL_FRONT
);
1701 checkGLcall("glDrawBuffer(GL_FRONT)");
1706 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1707 if (pPresentationParameters
->EnableAutoDepthStencil
&& surface_type
== SURFACE_OPENGL
) {
1708 TRACE("Creating depth stencil buffer\n");
1709 if (This
->auto_depth_stencil_buffer
== NULL
) {
1710 hr
= IWineD3DDeviceParent_CreateDepthStencilSurface(This
->device_parent
, parent
,
1711 object
->presentParms
.BackBufferWidth
, object
->presentParms
.BackBufferHeight
,
1712 object
->presentParms
.AutoDepthStencilFormat
, object
->presentParms
.MultiSampleType
,
1713 object
->presentParms
.MultiSampleQuality
, FALSE
/* FIXME: Discard */,
1714 &This
->auto_depth_stencil_buffer
);
1715 if (SUCCEEDED(hr
)) {
1716 IWineD3DSurface_SetContainer(This
->auto_depth_stencil_buffer
, 0);
1718 ERR("Failed to create the auto depth stencil\n");
1724 IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain
*) object
, &object
->orig_gamma
);
1726 TRACE("Created swapchain %p\n", object
);
1727 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object
->frontBuffer
, object
->backBuffer
? object
->backBuffer
[0] : NULL
, pPresentationParameters
->EnableAutoDepthStencil
);
1731 if (displaymode_set
) {
1735 SetRect(&clip_rc
, 0, 0, object
->orig_width
, object
->orig_height
);
1738 /* Change the display settings */
1739 memset(&devmode
, 0, sizeof(devmode
));
1740 devmode
.dmSize
= sizeof(devmode
);
1741 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1742 devmode
.dmBitsPerPel
= formatDesc
->bpp
* 8;
1743 devmode
.dmPelsWidth
= object
->orig_width
;
1744 devmode
.dmPelsHeight
= object
->orig_height
;
1745 ChangeDisplaySettingsExW(This
->adapter
->DeviceName
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
1748 if (object
->backBuffer
) {
1750 for(i
= 0; i
< object
->presentParms
.BackBufferCount
; i
++) {
1751 if(object
->backBuffer
[i
]) {
1752 IWineD3DSurface_GetParent(object
->backBuffer
[i
], &bufferParent
);
1753 IUnknown_Release(bufferParent
); /* once for the get parent */
1754 if (IUnknown_Release(bufferParent
) > 0) {
1755 FIXME("(%p) Something's still holding the back buffer\n",This
);
1759 HeapFree(GetProcessHeap(), 0, object
->backBuffer
);
1760 object
->backBuffer
= NULL
;
1762 if(object
->context
&& object
->context
[0])
1763 DestroyContext(This
, object
->context
[0]);
1764 if(object
->frontBuffer
) {
1765 IWineD3DSurface_GetParent(object
->frontBuffer
, &bufferParent
);
1766 IUnknown_Release(bufferParent
); /* once for the get parent */
1767 if (IUnknown_Release(bufferParent
) > 0) {
1768 FIXME("(%p) Something's still holding the front buffer\n",This
);
1771 HeapFree(GetProcessHeap(), 0, object
);
1775 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1776 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1777 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1778 TRACE("(%p)\n", This
);
1780 return This
->NumberOfSwapChains
;
1783 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1784 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1785 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
1787 if(iSwapChain
< This
->NumberOfSwapChains
) {
1788 *pSwapChain
= This
->swapchains
[iSwapChain
];
1789 IWineD3DSwapChain_AddRef(*pSwapChain
);
1790 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1793 TRACE("Swapchain out of range\n");
1795 return WINED3DERR_INVALIDCALL
;
1800 * Vertex Declaration
1802 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppVertexDeclaration
,
1803 IUnknown
*parent
, const WINED3DVERTEXELEMENT
*elements
, UINT element_count
) {
1804 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1805 IWineD3DVertexDeclarationImpl
*object
= NULL
;
1806 HRESULT hr
= WINED3D_OK
;
1808 TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1809 This
, ((IWineD3DImpl
*)This
->wineD3D
)->dxVersion
, elements
, element_count
, ppVertexDeclaration
);
1811 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1814 ERR("Out of memory\n");
1815 *ppVertexDeclaration
= NULL
;
1816 return WINED3DERR_OUTOFVIDEOMEMORY
;
1819 object
->lpVtbl
= &IWineD3DVertexDeclaration_Vtbl
;
1820 object
->wineD3DDevice
= This
;
1821 object
->parent
= parent
;
1824 *ppVertexDeclaration
= (IWineD3DVertexDeclaration
*)object
;
1826 hr
= IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration
*)object
, elements
, element_count
);
1828 IWineD3DVertexDeclaration_Release((IWineD3DVertexDeclaration
*)object
);
1829 *ppVertexDeclaration
= NULL
;
1835 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl
*This
, /* For the GL info, which has the type table */
1836 DWORD fvf
, WINED3DVERTEXELEMENT
** ppVertexElements
) {
1838 unsigned int idx
, idx2
;
1839 unsigned int offset
;
1840 BOOL has_pos
= (fvf
& WINED3DFVF_POSITION_MASK
) != 0;
1841 BOOL has_blend
= (fvf
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
;
1842 BOOL has_blend_idx
= has_blend
&&
1843 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB5
) ||
1844 (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
) ||
1845 (fvf
& WINED3DFVF_LASTBETA_UBYTE4
));
1846 BOOL has_normal
= (fvf
& WINED3DFVF_NORMAL
) != 0;
1847 BOOL has_psize
= (fvf
& WINED3DFVF_PSIZE
) != 0;
1848 BOOL has_diffuse
= (fvf
& WINED3DFVF_DIFFUSE
) != 0;
1849 BOOL has_specular
= (fvf
& WINED3DFVF_SPECULAR
) !=0;
1851 DWORD num_textures
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
1852 DWORD texcoords
= (fvf
& 0xFFFF0000) >> 16;
1854 WINED3DVERTEXELEMENT end_element
= WINED3DDECL_END();
1855 WINED3DVERTEXELEMENT
*elements
= NULL
;
1858 DWORD num_blends
= 1 + (((fvf
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
1859 if (has_blend_idx
) num_blends
--;
1861 /* Compute declaration size */
1862 size
= has_pos
+ (has_blend
&& num_blends
> 0) + has_blend_idx
+ has_normal
+
1863 has_psize
+ has_diffuse
+ has_specular
+ num_textures
+ 1;
1865 /* convert the declaration */
1866 elements
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WINED3DVERTEXELEMENT
));
1870 elements
[size
-1] = end_element
;
1873 if (!has_blend
&& (fvf
& WINED3DFVF_XYZRHW
)) {
1874 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
;
1875 elements
[idx
].Usage
= WINED3DDECLUSAGE_POSITIONT
;
1877 else if ((fvf
& WINED3DFVF_XYZW
) == WINED3DFVF_XYZW
) {
1878 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
;
1879 elements
[idx
].Usage
= WINED3DDECLUSAGE_POSITION
;
1882 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1883 elements
[idx
].Usage
= WINED3DDECLUSAGE_POSITION
;
1885 elements
[idx
].UsageIndex
= 0;
1888 if (has_blend
&& (num_blends
> 0)) {
1889 if (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
))
1890 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1892 switch(num_blends
) {
1893 case 1: elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
; break;
1894 case 2: elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT2
; break;
1895 case 3: elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
; break;
1896 case 4: elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
; break;
1898 ERR("Unexpected amount of blend values: %u\n", num_blends
);
1901 elements
[idx
].Usage
= WINED3DDECLUSAGE_BLENDWEIGHT
;
1902 elements
[idx
].UsageIndex
= 0;
1905 if (has_blend_idx
) {
1906 if (fvf
& WINED3DFVF_LASTBETA_UBYTE4
||
1907 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)))
1908 elements
[idx
].Type
= WINED3DDECLTYPE_UBYTE4
;
1909 else if (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)
1910 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1912 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1913 elements
[idx
].Usage
= WINED3DDECLUSAGE_BLENDINDICES
;
1914 elements
[idx
].UsageIndex
= 0;
1918 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1919 elements
[idx
].Usage
= WINED3DDECLUSAGE_NORMAL
;
1920 elements
[idx
].UsageIndex
= 0;
1924 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1925 elements
[idx
].Usage
= WINED3DDECLUSAGE_PSIZE
;
1926 elements
[idx
].UsageIndex
= 0;
1930 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1931 elements
[idx
].Usage
= WINED3DDECLUSAGE_COLOR
;
1932 elements
[idx
].UsageIndex
= 0;
1936 elements
[idx
].Type
= WINED3DDECLTYPE_D3DCOLOR
;
1937 elements
[idx
].Usage
= WINED3DDECLUSAGE_COLOR
;
1938 elements
[idx
].UsageIndex
= 1;
1941 for (idx2
= 0; idx2
< num_textures
; idx2
++) {
1942 unsigned int numcoords
= (texcoords
>> (idx2
*2)) & 0x03;
1943 switch (numcoords
) {
1944 case WINED3DFVF_TEXTUREFORMAT1
:
1945 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT1
;
1947 case WINED3DFVF_TEXTUREFORMAT2
:
1948 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT2
;
1950 case WINED3DFVF_TEXTUREFORMAT3
:
1951 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT3
;
1953 case WINED3DFVF_TEXTUREFORMAT4
:
1954 elements
[idx
].Type
= WINED3DDECLTYPE_FLOAT4
;
1957 elements
[idx
].Usage
= WINED3DDECLUSAGE_TEXCOORD
;
1958 elements
[idx
].UsageIndex
= idx2
;
1962 /* Now compute offsets, and initialize the rest of the fields */
1963 for (idx
= 0, offset
= 0; idx
< size
-1; idx
++) {
1964 elements
[idx
].Stream
= 0;
1965 elements
[idx
].Method
= WINED3DDECLMETHOD_DEFAULT
;
1966 elements
[idx
].Offset
= offset
;
1967 offset
+= WINED3D_ATR_SIZE(elements
[idx
].Type
) * WINED3D_ATR_TYPESIZE(elements
[idx
].Type
);
1970 *ppVertexElements
= elements
;
1974 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppVertexDeclaration
, IUnknown
*Parent
, DWORD Fvf
) {
1975 WINED3DVERTEXELEMENT
* elements
= NULL
;
1976 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1980 size
= ConvertFvfToDeclaration(This
, Fvf
, &elements
);
1981 if (size
== 0) return WINED3DERR_OUTOFVIDEOMEMORY
;
1983 hr
= IWineD3DDevice_CreateVertexDeclaration(iface
, ppVertexDeclaration
, Parent
, elements
, size
);
1984 HeapFree(GetProcessHeap(), 0, elements
);
1985 if (hr
!= S_OK
) return hr
;
1990 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexDeclaration
*vertex_declaration
, CONST DWORD
*pFunction
, IWineD3DVertexShader
**ppVertexShader
, IUnknown
*parent
) {
1991 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1992 IWineD3DVertexShaderImpl
*object
; /* NOTE: impl usage is ok, this is a create */
1993 HRESULT hr
= WINED3D_OK
;
1995 if (!pFunction
) return WINED3DERR_INVALIDCALL
;
1997 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2000 ERR("Out of memory\n");
2001 *ppVertexShader
= NULL
;
2002 return WINED3DERR_OUTOFVIDEOMEMORY
;
2005 object
->lpVtbl
= &IWineD3DVertexShader_Vtbl
;
2006 object
->parent
= parent
;
2007 shader_init(&object
->baseShader
, iface
, IWineD3DVertexShaderImpl_shader_ins
);
2008 list_add_head(&This
->shaders
, &object
->baseShader
.shader_list_entry
);
2009 *ppVertexShader
= (IWineD3DVertexShader
*)object
;
2011 TRACE("(%p) : Created vertex shader %p\n", This
, *ppVertexShader
);
2013 if (vertex_declaration
) {
2014 IWineD3DVertexShader_FakeSemantics(*ppVertexShader
, vertex_declaration
);
2017 hr
= IWineD3DVertexShader_SetFunction(*ppVertexShader
, pFunction
);
2020 WARN("(%p) : Failed to set function, returning %#x\n", iface
, hr
);
2021 IWineD3DVertexShader_Release(*ppVertexShader
);
2022 *ppVertexShader
= NULL
;
2029 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
, CONST DWORD
*pFunction
, IWineD3DPixelShader
**ppPixelShader
, IUnknown
*parent
) {
2030 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2031 IWineD3DPixelShaderImpl
*object
; /* NOTE: impl allowed, this is a create */
2032 HRESULT hr
= WINED3D_OK
;
2034 if (!pFunction
) return WINED3DERR_INVALIDCALL
;
2036 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2039 ERR("Out of memory\n");
2040 *ppPixelShader
= NULL
;
2041 return WINED3DERR_OUTOFVIDEOMEMORY
;
2044 object
->lpVtbl
= &IWineD3DPixelShader_Vtbl
;
2045 object
->parent
= parent
;
2046 shader_init(&object
->baseShader
, iface
, IWineD3DPixelShaderImpl_shader_ins
);
2047 list_add_head(&This
->shaders
, &object
->baseShader
.shader_list_entry
);
2048 *ppPixelShader
= (IWineD3DPixelShader
*)object
;
2050 TRACE("(%p) : Created pixel shader %p\n", This
, *ppPixelShader
);
2052 hr
= IWineD3DPixelShader_SetFunction(*ppPixelShader
, pFunction
);
2055 WARN("(%p) : Failed to set function, returning %#x\n", iface
, hr
);
2056 IWineD3DPixelShader_Release(*ppPixelShader
);
2057 *ppPixelShader
= NULL
;
2064 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD Flags
,
2065 const PALETTEENTRY
*PalEnt
, IWineD3DPalette
**Palette
, IUnknown
*Parent
)
2067 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2068 IWineD3DPaletteImpl
*object
;
2070 TRACE("(%p)->(%x, %p, %p, %p)\n", This
, Flags
, PalEnt
, Palette
, Parent
);
2072 /* Create the new object */
2073 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DPaletteImpl
));
2075 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
2076 return E_OUTOFMEMORY
;
2079 object
->lpVtbl
= &IWineD3DPalette_Vtbl
;
2081 object
->Flags
= Flags
;
2082 object
->parent
= Parent
;
2083 object
->wineD3DDevice
= This
;
2084 object
->palNumEntries
= IWineD3DPaletteImpl_Size(Flags
);
2085 object
->hpal
= CreatePalette((const LOGPALETTE
*)&(object
->palVersion
));
2088 HeapFree( GetProcessHeap(), 0, object
);
2089 return E_OUTOFMEMORY
;
2092 hr
= IWineD3DPalette_SetEntries((IWineD3DPalette
*) object
, 0, 0, IWineD3DPaletteImpl_Size(Flags
), PalEnt
);
2094 IWineD3DPalette_Release((IWineD3DPalette
*) object
);
2098 *Palette
= (IWineD3DPalette
*) object
;
2103 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl
*This
, const char *filename
) {
2107 HDC dcb
= NULL
, dcs
= NULL
;
2108 WINEDDCOLORKEY colorkey
;
2110 hbm
= LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
);
2113 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
2114 dcb
= CreateCompatibleDC(NULL
);
2116 SelectObject(dcb
, hbm
);
2120 /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
2121 * couldn't be loaded
2123 memset(&bm
, 0, sizeof(bm
));
2128 hr
= IWineD3DDevice_CreateSurface((IWineD3DDevice
*) This
, bm
.bmWidth
, bm
.bmHeight
, WINED3DFMT_R5G6B5
,
2129 TRUE
, FALSE
, 0, &This
->logo_surface
, WINED3DRTYPE_SURFACE
, 0,
2130 WINED3DPOOL_DEFAULT
, WINED3DMULTISAMPLE_NONE
, 0, NULL
, SURFACE_OPENGL
, NULL
);
2132 ERR("Wine logo requested, but failed to create surface\n");
2137 hr
= IWineD3DSurface_GetDC(This
->logo_surface
, &dcs
);
2138 if(FAILED(hr
)) goto out
;
2139 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
2140 IWineD3DSurface_ReleaseDC(This
->logo_surface
, dcs
);
2142 colorkey
.dwColorSpaceLowValue
= 0;
2143 colorkey
.dwColorSpaceHighValue
= 0;
2144 IWineD3DSurface_SetColorKey(This
->logo_surface
, WINEDDCKEY_SRCBLT
, &colorkey
);
2146 /* Fill the surface with a white color to show that wined3d is there */
2147 IWineD3DDevice_ColorFill((IWineD3DDevice
*) This
, This
->logo_surface
, NULL
, 0xffffffff);
2160 static void create_dummy_textures(IWineD3DDeviceImpl
*This
) {
2162 /* Under DirectX you can have texture stage operations even if no texture is
2163 bound, whereas opengl will only do texture operations when a valid texture is
2164 bound. We emulate this by creating dummy textures and binding them to each
2165 texture stage, but disable all stages by default. Hence if a stage is enabled
2166 then the default texture will kick in until replaced by a SetTexture call */
2169 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
2170 /* The dummy texture does not have client storage backing */
2171 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
2172 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
2174 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
2175 GLubyte white
= 255;
2177 /* Make appropriate texture active */
2178 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
2179 checkGLcall("glActiveTextureARB");
2181 /* Generate an opengl texture name */
2182 glGenTextures(1, &This
->dummyTextureName
[i
]);
2183 checkGLcall("glGenTextures");
2184 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
2186 /* Generate a dummy 2d texture (not using 1d because they cause many
2187 * DRI drivers fall back to sw) */
2188 glBindTexture(GL_TEXTURE_2D
, This
->dummyTextureName
[i
]);
2189 checkGLcall("glBindTexture");
2191 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
, 1, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
2192 checkGLcall("glTexImage2D");
2194 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
2195 /* Reenable because if supported it is enabled by default */
2196 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
2197 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
2203 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
,
2204 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
2206 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2207 IWineD3DSwapChainImpl
*swapchain
= NULL
;
2212 TRACE("(%p)->(%p)\n", This
, pPresentationParameters
);
2214 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2215 if(!This
->adapter
->opengl
) return WINED3DERR_INVALIDCALL
;
2217 /* TODO: Test if OpenGL is compiled in and loaded */
2219 TRACE("(%p) : Creating stateblock\n", This
);
2220 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2221 hr
= IWineD3DDevice_CreateStateBlock(iface
,
2223 (IWineD3DStateBlock
**)&This
->stateBlock
,
2225 if (WINED3D_OK
!= hr
) { /* Note: No parent needed for initial internal stateblock */
2226 WARN("Failed to create stateblock\n");
2229 TRACE("(%p) : Created stateblock (%p)\n", This
, This
->stateBlock
);
2230 This
->updateStateBlock
= This
->stateBlock
;
2231 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
2233 This
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*) * GL_LIMITS(buffers
));
2234 This
->draw_buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLenum
) * GL_LIMITS(buffers
));
2236 This
->NumberOfPalettes
= 1;
2237 This
->palettes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PALETTEENTRY
*));
2238 if(!This
->palettes
|| !This
->render_targets
|| !This
->draw_buffers
) {
2239 ERR("Out of memory!\n");
2242 This
->palettes
[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
2243 if(!This
->palettes
[0]) {
2244 ERR("Out of memory!\n");
2247 for (i
= 0; i
< 256; ++i
) {
2248 This
->palettes
[0][i
].peRed
= 0xFF;
2249 This
->palettes
[0][i
].peGreen
= 0xFF;
2250 This
->palettes
[0][i
].peBlue
= 0xFF;
2251 This
->palettes
[0][i
].peFlags
= 0xFF;
2253 This
->currentPalette
= 0;
2255 /* Initialize the texture unit mapping to a 1:1 mapping */
2256 for (state
= 0; state
< MAX_COMBINED_SAMPLERS
; ++state
) {
2257 if (state
< GL_LIMITS(fragment_samplers
)) {
2258 This
->texUnitMap
[state
] = state
;
2259 This
->rev_tex_unit_map
[state
] = state
;
2261 This
->texUnitMap
[state
] = -1;
2262 This
->rev_tex_unit_map
[state
] = -1;
2266 /* Setup the implicit swapchain */
2267 TRACE("Creating implicit swapchain\n");
2268 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
2269 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
2272 WARN("Failed to create implicit swapchain\n");
2276 This
->NumberOfSwapChains
= 1;
2277 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
2278 if(!This
->swapchains
) {
2279 ERR("Out of memory!\n");
2282 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
2284 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0]) {
2285 TRACE("Setting rendertarget to %p\n", swapchain
->backBuffer
);
2286 This
->render_targets
[0] = swapchain
->backBuffer
[0];
2287 This
->lastActiveRenderTarget
= swapchain
->backBuffer
[0];
2290 TRACE("Setting rendertarget to %p\n", swapchain
->frontBuffer
);
2291 This
->render_targets
[0] = swapchain
->frontBuffer
;
2292 This
->lastActiveRenderTarget
= swapchain
->frontBuffer
;
2294 IWineD3DSurface_AddRef(This
->render_targets
[0]);
2295 This
->activeContext
= swapchain
->context
[0];
2296 This
->lastThread
= GetCurrentThreadId();
2298 /* Depth Stencil support */
2299 This
->stencilBufferTarget
= This
->auto_depth_stencil_buffer
;
2300 if (NULL
!= This
->stencilBufferTarget
) {
2301 IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
2304 hr
= This
->shader_backend
->shader_alloc_private(iface
);
2306 TRACE("Shader private data couldn't be allocated\n");
2309 hr
= This
->frag_pipe
->alloc_private(iface
);
2311 TRACE("Fragment pipeline private data couldn't be allocated\n");
2314 hr
= This
->blitter
->alloc_private(iface
);
2316 TRACE("Blitter private data couldn't be allocated\n");
2320 /* Set up some starting GL setup */
2322 /* Setup all the devices defaults */
2323 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)This
->stateBlock
);
2324 create_dummy_textures(This
);
2328 /* Initialize the current view state */
2329 This
->view_ident
= 1;
2330 This
->contexts
[0]->last_was_rhw
= 0;
2331 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
2332 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
2334 switch(wined3d_settings
.offscreen_rendering_mode
) {
2337 This
->offscreenBuffer
= GL_BACK
;
2340 case ORM_BACKBUFFER
:
2342 if(This
->activeContext
->aux_buffers
> 0) {
2343 TRACE("Using auxilliary buffer for offscreen rendering\n");
2344 This
->offscreenBuffer
= GL_AUX0
;
2346 TRACE("Using back buffer for offscreen rendering\n");
2347 This
->offscreenBuffer
= GL_BACK
;
2352 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
2355 /* Clear the screen */
2356 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
,
2357 WINED3DCLEAR_TARGET
| pPresentationParameters
->EnableAutoDepthStencil
? WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
: 0,
2360 This
->d3d_initialized
= TRUE
;
2362 if(wined3d_settings
.logo
) {
2363 IWineD3DDeviceImpl_LoadLogo(This
, wined3d_settings
.logo
);
2365 This
->highest_dirty_ps_const
= 0;
2366 This
->highest_dirty_vs_const
= 0;
2370 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2371 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
2372 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2373 This
->NumberOfSwapChains
= 0;
2374 if(This
->palettes
) {
2375 HeapFree(GetProcessHeap(), 0, This
->palettes
[0]);
2376 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2378 This
->NumberOfPalettes
= 0;
2380 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
2382 if(This
->stateBlock
) {
2383 IWineD3DStateBlock_Release((IWineD3DStateBlock
*) This
->stateBlock
);
2384 This
->stateBlock
= NULL
;
2386 if (This
->blit_priv
) {
2387 This
->blitter
->free_private(iface
);
2389 if (This
->fragment_priv
) {
2390 This
->frag_pipe
->free_private(iface
);
2392 if (This
->shader_priv
) {
2393 This
->shader_backend
->shader_free_private(iface
);
2398 static HRESULT WINAPI
IWineD3DDeviceImpl_InitGDI(IWineD3DDevice
*iface
,
2399 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
2401 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2402 IWineD3DSwapChainImpl
*swapchain
= NULL
;
2405 /* Setup the implicit swapchain */
2406 TRACE("Creating implicit swapchain\n");
2407 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
2408 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
2411 WARN("Failed to create implicit swapchain\n");
2415 This
->NumberOfSwapChains
= 1;
2416 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
2417 if(!This
->swapchains
) {
2418 ERR("Out of memory!\n");
2421 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
2425 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
2429 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface
, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
) {
2430 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2433 TRACE("(%p)\n", This
);
2435 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2437 /* I don't think that the interface guarantees that the device is destroyed from the same thread
2438 * it was created. Thus make sure a context is active for the glDelete* calls
2440 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
2442 if(This
->logo_surface
) IWineD3DSurface_Release(This
->logo_surface
);
2444 TRACE("Deleting high order patches\n");
2445 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2446 struct list
*e1
, *e2
;
2447 struct WineD3DRectPatch
*patch
;
2448 LIST_FOR_EACH_SAFE(e1
, e2
, &This
->patches
[i
]) {
2449 patch
= LIST_ENTRY(e1
, struct WineD3DRectPatch
, entry
);
2450 IWineD3DDevice_DeletePatch(iface
, patch
->Handle
);
2454 /* Delete the palette conversion shader if it is around */
2455 if(This
->paletteConversionShader
) {
2457 GL_EXTCALL(glDeleteProgramsARB(1, &This
->paletteConversionShader
));
2459 This
->paletteConversionShader
= 0;
2462 /* Delete the pbuffer context if there is any */
2463 if(This
->pbufferContext
) DestroyContext(This
, This
->pbufferContext
);
2465 /* Delete the mouse cursor texture */
2466 if(This
->cursorTexture
) {
2468 glDeleteTextures(1, &This
->cursorTexture
);
2470 This
->cursorTexture
= 0;
2473 for (sampler
= 0; sampler
< MAX_FRAGMENT_SAMPLERS
; ++sampler
) {
2474 IWineD3DDevice_SetTexture(iface
, sampler
, NULL
);
2476 for (sampler
= 0; sampler
< MAX_VERTEX_SAMPLERS
; ++sampler
) {
2477 IWineD3DDevice_SetTexture(iface
, WINED3DVERTEXTEXTURESAMPLER0
+ sampler
, NULL
);
2480 /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2481 * private data, it might contain opengl pointers
2483 if(This
->depth_blt_texture
) {
2484 glDeleteTextures(1, &This
->depth_blt_texture
);
2485 This
->depth_blt_texture
= 0;
2487 if (This
->depth_blt_rb
) {
2488 GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This
->depth_blt_rb
));
2489 This
->depth_blt_rb
= 0;
2490 This
->depth_blt_rb_w
= 0;
2491 This
->depth_blt_rb_h
= 0;
2494 /* Release the update stateblock */
2495 if(IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
) > 0){
2496 if(This
->updateStateBlock
!= This
->stateBlock
)
2497 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
2499 This
->updateStateBlock
= NULL
;
2501 { /* because were not doing proper internal refcounts releasing the primary state block
2502 causes recursion with the extra checks in ResourceReleased, to avoid this we have
2503 to set this->stateBlock = NULL; first */
2504 IWineD3DStateBlock
*stateBlock
= (IWineD3DStateBlock
*)This
->stateBlock
;
2505 This
->stateBlock
= NULL
;
2507 /* Release the stateblock */
2508 if(IWineD3DStateBlock_Release(stateBlock
) > 0){
2509 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
2513 /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2514 This
->blitter
->free_private(iface
);
2515 This
->frag_pipe
->free_private(iface
);
2516 This
->shader_backend
->shader_free_private(iface
);
2518 /* Release the buffers (with sanity checks)*/
2519 TRACE("Releasing the depth stencil buffer at %p\n", This
->stencilBufferTarget
);
2520 if(This
->stencilBufferTarget
!= NULL
&& (IWineD3DSurface_Release(This
->stencilBufferTarget
) >0)){
2521 if(This
->auto_depth_stencil_buffer
!= This
->stencilBufferTarget
)
2522 FIXME("(%p) Something's still holding the stencilBufferTarget\n",This
);
2524 This
->stencilBufferTarget
= NULL
;
2526 TRACE("Releasing the render target at %p\n", This
->render_targets
[0]);
2527 if(IWineD3DSurface_Release(This
->render_targets
[0]) >0){
2528 /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2530 TRACE("Setting rendertarget to NULL\n");
2531 This
->render_targets
[0] = NULL
;
2533 if (This
->auto_depth_stencil_buffer
) {
2534 if(D3DCB_DestroyDepthStencilSurface(This
->auto_depth_stencil_buffer
) > 0) {
2535 FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This
);
2537 This
->auto_depth_stencil_buffer
= NULL
;
2540 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
2541 TRACE("Releasing the implicit swapchain %d\n", i
);
2542 if (D3DCB_DestroySwapChain(This
->swapchains
[i
]) > 0) {
2543 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2547 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2548 This
->swapchains
= NULL
;
2549 This
->NumberOfSwapChains
= 0;
2551 for (i
= 0; i
< This
->NumberOfPalettes
; i
++) HeapFree(GetProcessHeap(), 0, This
->palettes
[i
]);
2552 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2553 This
->palettes
= NULL
;
2554 This
->NumberOfPalettes
= 0;
2556 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2557 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
2558 This
->render_targets
= NULL
;
2559 This
->draw_buffers
= NULL
;
2561 This
->d3d_initialized
= FALSE
;
2565 static HRESULT WINAPI
IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice
*iface
, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
) {
2566 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2569 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
2570 TRACE("Releasing the implicit swapchain %d\n", i
);
2571 if (D3DCB_DestroySwapChain(This
->swapchains
[i
]) > 0) {
2572 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2576 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2577 This
->swapchains
= NULL
;
2578 This
->NumberOfSwapChains
= 0;
2582 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2583 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2584 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2586 * There is no way to deactivate thread safety once it is enabled.
2588 static void WINAPI
IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice
*iface
) {
2589 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2591 /*For now just store the flag(needed in case of ddraw) */
2592 This
->createParms
.BehaviorFlags
|= WINED3DCREATE_MULTITHREADED
;
2597 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
,
2598 const WINED3DDISPLAYMODE
* pMode
) {
2600 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2602 const StaticPixelFormatDesc
*formatDesc
= getFormatDescEntry(pMode
->Format
, NULL
, NULL
);
2605 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
2607 /* Resize the screen even without a window:
2608 * The app could have unset it with SetCooperativeLevel, but not called
2609 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2610 * but we don't have any hwnd
2613 memset(&devmode
, 0, sizeof(devmode
));
2614 devmode
.dmSize
= sizeof(devmode
);
2615 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
2616 devmode
.dmBitsPerPel
= formatDesc
->bpp
* 8;
2617 devmode
.dmPelsWidth
= pMode
->Width
;
2618 devmode
.dmPelsHeight
= pMode
->Height
;
2620 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
2621 if (pMode
->RefreshRate
!= 0) {
2622 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
2625 /* Only change the mode if necessary */
2626 if( (This
->ddraw_width
== pMode
->Width
) &&
2627 (This
->ddraw_height
== pMode
->Height
) &&
2628 (This
->ddraw_format
== pMode
->Format
) &&
2629 (pMode
->RefreshRate
== 0) ) {
2633 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
2634 if (ret
!= DISP_CHANGE_SUCCESSFUL
) {
2635 if(devmode
.dmDisplayFrequency
!= 0) {
2636 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2637 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
2638 devmode
.dmDisplayFrequency
= 0;
2639 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
2641 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
2642 return WINED3DERR_NOTAVAILABLE
;
2646 /* Store the new values */
2647 This
->ddraw_width
= pMode
->Width
;
2648 This
->ddraw_height
= pMode
->Height
;
2649 This
->ddraw_format
= pMode
->Format
;
2651 /* And finally clip mouse to our screen */
2652 SetRect(&clip_rc
, 0, 0, pMode
->Width
, pMode
->Height
);
2653 ClipCursor(&clip_rc
);
2658 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, IWineD3D
**ppD3D
) {
2659 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2660 *ppD3D
= This
->wineD3D
;
2661 TRACE("(%p) : wineD3D returning %p\n", This
, *ppD3D
);
2662 IWineD3D_AddRef(*ppD3D
);
2666 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
2667 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2669 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
2670 (This
->adapter
->TextureRam
/(1024*1024)),
2671 ((This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
) / (1024*1024)));
2672 /* return simulated texture memory left */
2673 return (This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
);
2677 * Get / Set Stream Source
2679 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
* pStreamData
, UINT OffsetInBytes
, UINT Stride
) {
2680 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2681 IWineD3DVertexBuffer
*oldSrc
;
2683 if (StreamNumber
>= MAX_STREAMS
) {
2684 WARN("Stream out of range %d\n", StreamNumber
);
2685 return WINED3DERR_INVALIDCALL
;
2686 } else if(OffsetInBytes
& 0x3) {
2687 WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes
);
2688 return WINED3DERR_INVALIDCALL
;
2691 oldSrc
= This
->updateStateBlock
->streamSource
[StreamNumber
];
2692 TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This
, StreamNumber
, oldSrc
, pStreamData
, OffsetInBytes
, Stride
);
2694 This
->updateStateBlock
->changed
.streamSource
|= 1 << StreamNumber
;
2696 if(oldSrc
== pStreamData
&&
2697 This
->updateStateBlock
->streamStride
[StreamNumber
] == Stride
&&
2698 This
->updateStateBlock
->streamOffset
[StreamNumber
] == OffsetInBytes
) {
2699 TRACE("Application is setting the old values over, nothing to do\n");
2703 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
2705 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
2706 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
2709 /* Handle recording of state blocks */
2710 if (This
->isRecordingState
) {
2711 TRACE("Recording... not performing anything\n");
2712 if(pStreamData
) IWineD3DVertexBuffer_AddRef(pStreamData
);
2713 if(oldSrc
) IWineD3DVertexBuffer_Release(oldSrc
);
2717 if (pStreamData
!= NULL
) {
2718 IWineD3DVertexBufferImpl
*vbImpl
= (IWineD3DVertexBufferImpl
*) pStreamData
;
2719 InterlockedIncrement(&vbImpl
->bindCount
);
2720 IWineD3DVertexBuffer_AddRef(pStreamData
);
2722 if (oldSrc
!= NULL
) {
2723 InterlockedDecrement(&((IWineD3DVertexBufferImpl
*) oldSrc
)->bindCount
);
2724 IWineD3DVertexBuffer_Release(oldSrc
);
2727 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2732 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,IWineD3DVertexBuffer
** pStream
, UINT
*pOffset
, UINT
* pStride
) {
2733 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2735 TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This
, StreamNumber
,
2736 This
->stateBlock
->streamSource
[StreamNumber
],
2737 This
->stateBlock
->streamOffset
[StreamNumber
],
2738 This
->stateBlock
->streamStride
[StreamNumber
]);
2740 if (StreamNumber
>= MAX_STREAMS
) {
2741 WARN("Stream out of range %d\n", StreamNumber
);
2742 return WINED3DERR_INVALIDCALL
;
2744 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
2745 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
2747 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
2750 if (*pStream
!= NULL
) {
2751 IWineD3DVertexBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
2756 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2757 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2758 UINT oldFlags
= This
->updateStateBlock
->streamFlags
[StreamNumber
];
2759 UINT oldFreq
= This
->updateStateBlock
->streamFreq
[StreamNumber
];
2761 /* Verify input at least in d3d9 this is invalid*/
2762 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && (Divider
& WINED3DSTREAMSOURCE_INDEXEDDATA
)){
2763 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2764 return WINED3DERR_INVALIDCALL
;
2766 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && StreamNumber
== 0 ){
2767 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2768 return WINED3DERR_INVALIDCALL
;
2771 WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2772 return WINED3DERR_INVALIDCALL
;
2775 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This
, StreamNumber
, Divider
);
2776 This
->updateStateBlock
->streamFlags
[StreamNumber
] = Divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
2778 This
->updateStateBlock
->changed
.streamFreq
|= 1 << StreamNumber
;
2779 This
->updateStateBlock
->streamFreq
[StreamNumber
] = Divider
& 0x7FFFFF;
2781 if(This
->updateStateBlock
->streamFreq
[StreamNumber
] != oldFreq
||
2782 This
->updateStateBlock
->streamFlags
[StreamNumber
] != oldFlags
) {
2783 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2789 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2790 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2792 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This
, StreamNumber
, Divider
);
2793 *Divider
= This
->updateStateBlock
->streamFreq
[StreamNumber
] | This
->updateStateBlock
->streamFlags
[StreamNumber
];
2795 TRACE("(%p) : returning %d\n", This
, *Divider
);
2801 * Get / Set & Multiply Transform
2803 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE d3dts
, CONST WINED3DMATRIX
* lpmatrix
) {
2804 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2806 /* Most of this routine, comments included copied from ddraw tree initially: */
2807 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
2809 /* Handle recording of state blocks */
2810 if (This
->isRecordingState
) {
2811 TRACE("Recording... not performing anything\n");
2812 This
->updateStateBlock
->changed
.transform
[d3dts
>> 5] |= 1 << (d3dts
& 0x1f);
2813 This
->updateStateBlock
->transforms
[d3dts
] = *lpmatrix
;
2818 * If the new matrix is the same as the current one,
2819 * we cut off any further processing. this seems to be a reasonable
2820 * optimization because as was noticed, some apps (warcraft3 for example)
2821 * tend towards setting the same matrix repeatedly for some reason.
2823 * From here on we assume that the new matrix is different, wherever it matters.
2825 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(WINED3DMATRIX
))) {
2826 TRACE("The app is setting the same matrix over again\n");
2829 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
2833 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2834 where ViewMat = Camera space, WorldMat = world space.
2836 In OpenGL, camera and world space is combined into GL_MODELVIEW
2837 matrix. The Projection matrix stay projection matrix.
2840 /* Capture the times we can just ignore the change for now */
2841 if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrix */
2842 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2843 /* Handled by the state manager */
2846 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TRANSFORM(d3dts
));
2850 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, WINED3DMATRIX
* pMatrix
) {
2851 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2852 TRACE("(%p) : for Transform State %s\n", This
, debug_d3dtstype(State
));
2853 *pMatrix
= This
->stateBlock
->transforms
[State
];
2857 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, CONST WINED3DMATRIX
* pMatrix
) {
2858 const WINED3DMATRIX
*mat
= NULL
;
2861 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2862 * below means it will be recorded in a state block change, but it
2863 * works regardless where it is recorded.
2864 * If this is found to be wrong, change to StateBlock.
2866 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2867 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2869 if (State
<= HIGHEST_TRANSFORMSTATE
)
2871 mat
= &This
->updateStateBlock
->transforms
[State
];
2873 FIXME("Unhandled transform state!!\n");
2876 multiply_matrix(&temp
, mat
, pMatrix
);
2878 /* Apply change via set transform - will reapply to eg. lights this way */
2879 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2885 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2886 you can reference any indexes you want as long as that number max are enabled at any
2887 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2888 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2889 but when recording, just build a chain pretty much of commands to be replayed. */
2891 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2893 PLIGHTINFOEL
*object
= NULL
;
2894 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2897 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2898 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This
, Index
, pLight
, Hi
);
2900 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2904 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2905 return WINED3DERR_INVALIDCALL
;
2908 switch(pLight
->Type
) {
2909 case WINED3DLIGHT_POINT
:
2910 case WINED3DLIGHT_SPOT
:
2911 case WINED3DLIGHT_PARALLELPOINT
:
2912 case WINED3DLIGHT_GLSPOT
:
2913 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2916 if(pLight
->Attenuation0
< 0.0 || pLight
->Attenuation1
< 0.0 || pLight
->Attenuation2
< 0.0) {
2917 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2918 return WINED3DERR_INVALIDCALL
;
2922 case WINED3DLIGHT_DIRECTIONAL
:
2923 /* Ignores attenuation */
2927 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2928 return WINED3DERR_INVALIDCALL
;
2931 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
2932 object
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
2933 if(object
->OriginalIndex
== Index
) break;
2938 TRACE("Adding new light\n");
2939 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2941 ERR("Out of memory error when allocating a light\n");
2942 return E_OUTOFMEMORY
;
2944 list_add_head(&This
->updateStateBlock
->lightMap
[Hi
], &object
->entry
);
2945 object
->glIndex
= -1;
2946 object
->OriginalIndex
= Index
;
2947 object
->changed
= TRUE
;
2950 /* Initialize the object */
2951 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
,
2952 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2953 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2954 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2955 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2956 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2957 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2959 /* Save away the information */
2960 object
->OriginalParms
= *pLight
;
2962 switch (pLight
->Type
) {
2963 case WINED3DLIGHT_POINT
:
2965 object
->lightPosn
[0] = pLight
->Position
.x
;
2966 object
->lightPosn
[1] = pLight
->Position
.y
;
2967 object
->lightPosn
[2] = pLight
->Position
.z
;
2968 object
->lightPosn
[3] = 1.0f
;
2969 object
->cutoff
= 180.0f
;
2973 case WINED3DLIGHT_DIRECTIONAL
:
2975 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2976 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2977 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2978 object
->lightPosn
[3] = 0.0;
2979 object
->exponent
= 0.0f
;
2980 object
->cutoff
= 180.0f
;
2983 case WINED3DLIGHT_SPOT
:
2985 object
->lightPosn
[0] = pLight
->Position
.x
;
2986 object
->lightPosn
[1] = pLight
->Position
.y
;
2987 object
->lightPosn
[2] = pLight
->Position
.z
;
2988 object
->lightPosn
[3] = 1.0;
2991 object
->lightDirn
[0] = pLight
->Direction
.x
;
2992 object
->lightDirn
[1] = pLight
->Direction
.y
;
2993 object
->lightDirn
[2] = pLight
->Direction
.z
;
2994 object
->lightDirn
[3] = 1.0;
2997 * opengl-ish and d3d-ish spot lights use too different models for the
2998 * light "intensity" as a function of the angle towards the main light direction,
2999 * so we only can approximate very roughly.
3000 * however spot lights are rather rarely used in games (if ever used at all).
3001 * furthermore if still used, probably nobody pays attention to such details.
3003 if (pLight
->Falloff
== 0) {
3004 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
3005 * falloff resp. exponent parameter as an exponent, so the spot light lighting
3006 * will always be 1.0 for both of them, and we don't have to care for the
3007 * rest of the rather complex calculation
3009 object
->exponent
= 0;
3011 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
3012 if (rho
< 0.0001) rho
= 0.0001f
;
3013 object
->exponent
= -0.3/log(cos(rho
/2));
3015 if (object
->exponent
> 128.0) {
3016 object
->exponent
= 128.0;
3018 object
->cutoff
= pLight
->Phi
*90/M_PI
;
3024 FIXME("Unrecognized light type %d\n", pLight
->Type
);
3027 /* Update the live definitions if the light is currently assigned a glIndex */
3028 if (object
->glIndex
!= -1 && !This
->isRecordingState
) {
3029 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(object
->glIndex
));
3034 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
* pLight
) {
3035 PLIGHTINFOEL
*lightInfo
= NULL
;
3036 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3037 DWORD Hi
= LIGHTMAP_HASHFUNC(Index
);
3039 TRACE("(%p) : Idx(%d), pLight(%p)\n", This
, Index
, pLight
);
3041 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
]) {
3042 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
3043 if(lightInfo
->OriginalIndex
== Index
) break;
3047 if (lightInfo
== NULL
) {
3048 TRACE("Light information requested but light not defined\n");
3049 return WINED3DERR_INVALIDCALL
;
3052 *pLight
= lightInfo
->OriginalParms
;
3057 * Get / Set Light Enable
3058 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
3060 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
) {
3061 PLIGHTINFOEL
*lightInfo
= NULL
;
3062 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3063 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
3065 TRACE("(%p) : Idx(%d), enable? %d\n", This
, Index
, Enable
);
3067 /* Tests show true = 128...not clear why */
3068 Enable
= Enable
? 128: 0;
3070 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
3071 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
3072 if(lightInfo
->OriginalIndex
== Index
) break;
3075 TRACE("Found light: %p\n", lightInfo
);
3077 /* Special case - enabling an undefined light creates one with a strict set of parms! */
3078 if (lightInfo
== NULL
) {
3080 TRACE("Light enabled requested but light not defined, so defining one!\n");
3081 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
3083 /* Search for it again! Should be fairly quick as near head of list */
3084 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
]) {
3085 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
3086 if(lightInfo
->OriginalIndex
== Index
) break;
3089 if (lightInfo
== NULL
) {
3090 FIXME("Adding default lights has failed dismally\n");
3091 return WINED3DERR_INVALIDCALL
;
3095 lightInfo
->enabledChanged
= TRUE
;
3097 if(lightInfo
->glIndex
!= -1) {
3098 if(!This
->isRecordingState
) {
3099 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(lightInfo
->glIndex
));
3102 This
->updateStateBlock
->activeLights
[lightInfo
->glIndex
] = NULL
;
3103 lightInfo
->glIndex
= -1;
3105 TRACE("Light already disabled, nothing to do\n");
3107 lightInfo
->enabled
= FALSE
;
3109 lightInfo
->enabled
= TRUE
;
3110 if (lightInfo
->glIndex
!= -1) {
3112 TRACE("Nothing to do as light was enabled\n");
3115 /* Find a free gl light */
3116 for(i
= 0; i
< This
->maxConcurrentLights
; i
++) {
3117 if(This
->updateStateBlock
->activeLights
[i
] == NULL
) {
3118 This
->updateStateBlock
->activeLights
[i
] = lightInfo
;
3119 lightInfo
->glIndex
= i
;
3123 if(lightInfo
->glIndex
== -1) {
3124 /* Our tests show that Windows returns D3D_OK in this situation, even with
3125 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
3126 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
3127 * as well for those lights.
3129 * TODO: Test how this affects rendering
3131 WARN("Too many concurrently active lights\n");
3135 /* i == lightInfo->glIndex */
3136 if(!This
->isRecordingState
) {
3137 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(i
));
3145 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
) {
3147 PLIGHTINFOEL
*lightInfo
= NULL
;
3148 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3150 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
3151 TRACE("(%p) : for idx(%d)\n", This
, Index
);
3153 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
]) {
3154 lightInfo
= LIST_ENTRY(e
, PLIGHTINFOEL
, entry
);
3155 if(lightInfo
->OriginalIndex
== Index
) break;
3159 if (lightInfo
== NULL
) {
3160 TRACE("Light enabled state requested but light not defined\n");
3161 return WINED3DERR_INVALIDCALL
;
3163 /* true is 128 according to SetLightEnable */
3164 *pEnable
= lightInfo
->enabled
? 128 : 0;
3169 * Get / Set Clip Planes
3171 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
3172 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3173 TRACE("(%p) : for idx %d, %p\n", This
, Index
, pPlane
);
3175 /* Validate Index */
3176 if (Index
>= GL_LIMITS(clipplanes
)) {
3177 TRACE("Application has requested clipplane this device doesn't support\n");
3178 return WINED3DERR_INVALIDCALL
;
3181 This
->updateStateBlock
->changed
.clipplane
|= 1 << Index
;
3183 if(This
->updateStateBlock
->clipplane
[Index
][0] == pPlane
[0] &&
3184 This
->updateStateBlock
->clipplane
[Index
][1] == pPlane
[1] &&
3185 This
->updateStateBlock
->clipplane
[Index
][2] == pPlane
[2] &&
3186 This
->updateStateBlock
->clipplane
[Index
][3] == pPlane
[3]) {
3187 TRACE("Application is setting old values over, nothing to do\n");
3191 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
3192 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
3193 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
3194 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
3196 /* Handle recording of state blocks */
3197 if (This
->isRecordingState
) {
3198 TRACE("Recording... not performing anything\n");
3202 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_CLIPPLANE(Index
));
3207 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
3208 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3209 TRACE("(%p) : for idx %d\n", This
, Index
);
3211 /* Validate Index */
3212 if (Index
>= GL_LIMITS(clipplanes
)) {
3213 TRACE("Application has requested clipplane this device doesn't support\n");
3214 return WINED3DERR_INVALIDCALL
;
3217 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
3218 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
3219 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
3220 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
3225 * Get / Set Clip Plane Status
3226 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
3228 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
3229 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3230 FIXME("(%p) : stub\n", This
);
3231 if (NULL
== pClipStatus
) {
3232 return WINED3DERR_INVALIDCALL
;
3234 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
3235 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
3239 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
3240 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3241 FIXME("(%p) : stub\n", This
);
3242 if (NULL
== pClipStatus
) {
3243 return WINED3DERR_INVALIDCALL
;
3245 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
3246 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
3251 * Get / Set Material
3253 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
3254 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3256 This
->updateStateBlock
->changed
.material
= TRUE
;
3257 This
->updateStateBlock
->material
= *pMaterial
;
3259 /* Handle recording of state blocks */
3260 if (This
->isRecordingState
) {
3261 TRACE("Recording... not performing anything\n");
3265 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_MATERIAL
);
3269 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
3270 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3271 *pMaterial
= This
->updateStateBlock
->material
;
3272 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3273 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3274 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3275 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3276 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3277 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3278 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3279 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3280 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3288 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
* pIndexData
) {
3289 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3290 IWineD3DIndexBuffer
*oldIdxs
;
3292 TRACE("(%p) : Setting to %p\n", This
, pIndexData
);
3293 oldIdxs
= This
->updateStateBlock
->pIndexData
;
3295 This
->updateStateBlock
->changed
.indices
= TRUE
;
3296 This
->updateStateBlock
->pIndexData
= pIndexData
;
3298 /* Handle recording of state blocks */
3299 if (This
->isRecordingState
) {
3300 TRACE("Recording... not performing anything\n");
3301 if(pIndexData
) IWineD3DIndexBuffer_AddRef(pIndexData
);
3302 if(oldIdxs
) IWineD3DIndexBuffer_Release(oldIdxs
);
3306 if(oldIdxs
!= pIndexData
) {
3307 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
3308 if(pIndexData
) IWineD3DIndexBuffer_AddRef(pIndexData
);
3309 if(oldIdxs
) IWineD3DIndexBuffer_Release(oldIdxs
);
3314 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndices(IWineD3DDevice
*iface
, IWineD3DIndexBuffer
** ppIndexData
) {
3315 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3317 *ppIndexData
= This
->stateBlock
->pIndexData
;
3319 /* up ref count on ppindexdata */
3321 IWineD3DIndexBuffer_AddRef(*ppIndexData
);
3322 TRACE("(%p) index data set to %p\n", This
, ppIndexData
);
3324 TRACE("(%p) No index data set\n", This
);
3326 TRACE("Returning %p\n", *ppIndexData
);
3331 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3332 static HRESULT WINAPI
IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice
*iface
, INT BaseIndex
) {
3333 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3334 TRACE("(%p)->(%d)\n", This
, BaseIndex
);
3336 if(This
->updateStateBlock
->baseVertexIndex
== BaseIndex
) {
3337 TRACE("Application is setting the old value over, nothing to do\n");
3341 This
->updateStateBlock
->baseVertexIndex
= BaseIndex
;
3343 if (This
->isRecordingState
) {
3344 TRACE("Recording... not performing anything\n");
3347 /* The base vertex index affects the stream sources */
3348 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
3352 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice
*iface
, INT
* base_index
) {
3353 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3354 TRACE("(%p) : base_index %p\n", This
, base_index
);
3356 *base_index
= This
->stateBlock
->baseVertexIndex
;
3358 TRACE("Returning %u\n", *base_index
);
3364 * Get / Set Viewports
3366 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
3367 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3369 TRACE("(%p)\n", This
);
3370 This
->updateStateBlock
->changed
.viewport
= TRUE
;
3371 This
->updateStateBlock
->viewport
= *pViewport
;
3373 /* Handle recording of state blocks */
3374 if (This
->isRecordingState
) {
3375 TRACE("Recording... not performing anything\n");
3379 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This
,
3380 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
3382 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
3387 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
3388 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3389 TRACE("(%p)\n", This
);
3390 *pViewport
= This
->stateBlock
->viewport
;
3395 * Get / Set Render States
3396 * TODO: Verify against dx9 definitions
3398 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD Value
) {
3400 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3401 DWORD oldValue
= This
->stateBlock
->renderState
[State
];
3403 TRACE("(%p)->state = %s(%d), value = %d\n", This
, debug_d3drenderstate(State
), State
, Value
);
3405 This
->updateStateBlock
->changed
.renderState
[State
>> 5] |= 1 << (State
& 0x1f);
3406 This
->updateStateBlock
->renderState
[State
] = Value
;
3408 /* Handle recording of state blocks */
3409 if (This
->isRecordingState
) {
3410 TRACE("Recording... not performing anything\n");
3414 /* Compared here and not before the assignment to allow proper stateblock recording */
3415 if(Value
== oldValue
) {
3416 TRACE("Application is setting the old value over, nothing to do\n");
3418 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(State
));
3424 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD
*pValue
) {
3425 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3426 TRACE("(%p) for State %d = %d\n", This
, State
, This
->stateBlock
->renderState
[State
]);
3427 *pValue
= This
->stateBlock
->renderState
[State
];
3432 * Get / Set Sampler States
3433 * TODO: Verify against dx9 definitions
3436 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
3437 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3440 TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3441 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
, Value
);
3443 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3444 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3447 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
3448 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3449 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3452 * SetSampler is designed to allow for more than the standard up to 8 textures
3453 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3454 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3456 * http://developer.nvidia.com/object/General_FAQ.html#t6
3458 * There are two new settings for GForce
3460 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3461 * and the texture one:
3462 * GL_MAX_TEXTURE_COORDS_ARB.
3463 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3466 oldValue
= This
->stateBlock
->samplerState
[Sampler
][Type
];
3467 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
3468 This
->updateStateBlock
->changed
.samplerState
[Sampler
] |= 1 << Type
;
3470 /* Handle recording of state blocks */
3471 if (This
->isRecordingState
) {
3472 TRACE("Recording... not performing anything\n");
3476 if(oldValue
== Value
) {
3477 TRACE("Application is setting the old value over, nothing to do\n");
3481 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Sampler
));
3486 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
3487 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3489 TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3490 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
);
3492 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3493 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3496 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
3497 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3498 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3500 *Value
= This
->stateBlock
->samplerState
[Sampler
][Type
];
3501 TRACE("(%p) : Returning %#x\n", This
, *Value
);
3506 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
3507 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3509 This
->updateStateBlock
->changed
.scissorRect
= TRUE
;
3510 if(EqualRect(&This
->updateStateBlock
->scissorRect
, pRect
)) {
3511 TRACE("App is setting the old scissor rectangle over, nothing to do\n");
3514 CopyRect(&This
->updateStateBlock
->scissorRect
, pRect
);
3516 if(This
->isRecordingState
) {
3517 TRACE("Recording... not performing anything\n");
3521 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
3526 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
3527 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3529 *pRect
= This
->updateStateBlock
->scissorRect
;
3530 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3534 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
3535 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
3536 IWineD3DVertexDeclaration
*oldDecl
= This
->updateStateBlock
->vertexDecl
;
3538 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
3540 This
->updateStateBlock
->vertexDecl
= pDecl
;
3541 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
3543 if (This
->isRecordingState
) {
3544 TRACE("Recording... not performing anything\n");
3546 } else if(pDecl
== oldDecl
) {
3547 /* Checked after the assignment to allow proper stateblock recording */
3548 TRACE("Application is setting the old declaration over, nothing to do\n");
3552 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
3556 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
3557 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3559 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
3561 *ppDecl
= This
->stateBlock
->vertexDecl
;
3562 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
3566 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
3567 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3568 IWineD3DVertexShader
* oldShader
= This
->updateStateBlock
->vertexShader
;
3570 This
->updateStateBlock
->vertexShader
= pShader
;
3571 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3573 if (This
->isRecordingState
) {
3574 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3575 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3576 TRACE("Recording... not performing anything\n");
3578 } else if(oldShader
== pShader
) {
3579 /* Checked here to allow proper stateblock recording */
3580 TRACE("App is setting the old shader over, nothing to do\n");
3584 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3585 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3586 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3588 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VSHADER
);
3593 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
3594 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3596 if (NULL
== ppShader
) {
3597 return WINED3DERR_INVALIDCALL
;
3599 *ppShader
= This
->stateBlock
->vertexShader
;
3600 if( NULL
!= *ppShader
)
3601 IWineD3DVertexShader_AddRef(*ppShader
);
3603 TRACE("(%p) : returning %p\n", This
, *ppShader
);
3607 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
3608 IWineD3DDevice
*iface
,
3610 CONST BOOL
*srcData
,
3613 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3614 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3616 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3617 iface
, srcData
, start
, count
);
3619 if (srcData
== NULL
|| cnt
< 0)
3620 return WINED3DERR_INVALIDCALL
;
3622 memcpy(&This
->updateStateBlock
->vertexShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
3623 for (i
= 0; i
< cnt
; i
++)
3624 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3626 for (i
= start
; i
< cnt
+ start
; ++i
) {
3627 This
->updateStateBlock
->changed
.vertexShaderConstantsB
|= (1 << i
);
3630 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3635 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
3636 IWineD3DDevice
*iface
,
3641 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3642 int cnt
= min(count
, MAX_CONST_B
- start
);
3644 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3645 iface
, dstData
, start
, count
);
3647 if (dstData
== NULL
|| cnt
< 0)
3648 return WINED3DERR_INVALIDCALL
;
3650 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantB
[start
], cnt
* sizeof(BOOL
));
3654 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
3655 IWineD3DDevice
*iface
,
3660 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3661 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3663 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3664 iface
, srcData
, start
, count
);
3666 if (srcData
== NULL
|| cnt
< 0)
3667 return WINED3DERR_INVALIDCALL
;
3669 memcpy(&This
->updateStateBlock
->vertexShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3670 for (i
= 0; i
< cnt
; i
++)
3671 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3672 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3674 for (i
= start
; i
< cnt
+ start
; ++i
) {
3675 This
->updateStateBlock
->changed
.vertexShaderConstantsI
|= (1 << i
);
3678 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3683 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
3684 IWineD3DDevice
*iface
,
3689 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3690 int cnt
= min(count
, MAX_CONST_I
- start
);
3692 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3693 iface
, dstData
, start
, count
);
3695 if (dstData
== NULL
|| ((signed int) MAX_CONST_I
- (signed int) start
) <= (signed int) 0)
3696 return WINED3DERR_INVALIDCALL
;
3698 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
3702 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
3703 IWineD3DDevice
*iface
,
3705 CONST
float *srcData
,
3708 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3711 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3712 iface
, srcData
, start
, count
);
3714 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3715 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(vshader_constantsF
) || start
> GL_LIMITS(vshader_constantsF
))
3716 return WINED3DERR_INVALIDCALL
;
3718 memcpy(&This
->updateStateBlock
->vertexShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
3720 for (i
= 0; i
< count
; i
++)
3721 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3722 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3725 if (!This
->isRecordingState
)
3727 This
->shader_backend
->shader_update_float_vertex_constants(iface
, start
, count
);
3728 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3731 memset(This
->updateStateBlock
->changed
.vertexShaderConstantsF
+ start
, 1,
3732 sizeof(*This
->updateStateBlock
->changed
.vertexShaderConstantsF
) * count
);
3737 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
3738 IWineD3DDevice
*iface
,
3743 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3744 int cnt
= min(count
, GL_LIMITS(vshader_constantsF
) - start
);
3746 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3747 iface
, dstData
, start
, count
);
3749 if (dstData
== NULL
|| cnt
< 0)
3750 return WINED3DERR_INVALIDCALL
;
3752 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
3756 static inline void markTextureStagesDirty(IWineD3DDeviceImpl
*This
, DWORD stage
) {
3758 for(i
= 0; i
<= WINED3D_HIGHEST_TEXTURE_STATE
; ++i
)
3760 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, i
));
3764 static void device_map_stage(IWineD3DDeviceImpl
*This
, int stage
, int unit
) {
3765 int i
= This
->rev_tex_unit_map
[unit
];
3766 int j
= This
->texUnitMap
[stage
];
3768 This
->texUnitMap
[stage
] = unit
;
3769 if (i
!= -1 && i
!= stage
) {
3770 This
->texUnitMap
[i
] = -1;
3773 This
->rev_tex_unit_map
[unit
] = stage
;
3774 if (j
!= -1 && j
!= unit
) {
3775 This
->rev_tex_unit_map
[j
] = -1;
3779 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl
*This
) {
3782 This
->fixed_function_usage_map
= 0;
3783 for (i
= 0; i
< MAX_TEXTURES
; ++i
) {
3784 WINED3DTEXTUREOP color_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLOROP
];
3785 WINED3DTEXTUREOP alpha_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAOP
];
3786 DWORD color_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG1
] & WINED3DTA_SELECTMASK
;
3787 DWORD color_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG2
] & WINED3DTA_SELECTMASK
;
3788 DWORD color_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG0
] & WINED3DTA_SELECTMASK
;
3789 DWORD alpha_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG1
] & WINED3DTA_SELECTMASK
;
3790 DWORD alpha_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG2
] & WINED3DTA_SELECTMASK
;
3791 DWORD alpha_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG0
] & WINED3DTA_SELECTMASK
;
3793 if (color_op
== WINED3DTOP_DISABLE
) {
3794 /* Not used, and disable higher stages */
3798 if (((color_arg1
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG2
)
3799 || ((color_arg2
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG1
)
3800 || ((color_arg3
== WINED3DTA_TEXTURE
) && (color_op
== WINED3DTOP_MULTIPLYADD
|| color_op
== WINED3DTOP_LERP
))
3801 || ((alpha_arg1
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG2
)
3802 || ((alpha_arg2
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG1
)
3803 || ((alpha_arg3
== WINED3DTA_TEXTURE
) && (alpha_op
== WINED3DTOP_MULTIPLYADD
|| alpha_op
== WINED3DTOP_LERP
))) {
3804 This
->fixed_function_usage_map
|= (1 << i
);
3807 if ((color_op
== WINED3DTOP_BUMPENVMAP
|| color_op
== WINED3DTOP_BUMPENVMAPLUMINANCE
) && i
< MAX_TEXTURES
- 1) {
3808 This
->fixed_function_usage_map
|= (1 << (i
+ 1));
3813 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl
*This
) {
3817 device_update_fixed_function_usage_map(This
);
3818 ffu_map
= This
->fixed_function_usage_map
;
3820 if (This
->max_ffp_textures
== This
->max_ffp_texture_stages
||
3821 This
->stateBlock
->lowest_disabled_stage
<= This
->max_ffp_textures
) {
3822 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3824 if (!(ffu_map
& 1)) continue;
3826 if (This
->texUnitMap
[i
] != i
) {
3827 device_map_stage(This
, i
, i
);
3828 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3829 markTextureStagesDirty(This
, i
);
3835 /* Now work out the mapping */
3837 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3839 if (!(ffu_map
& 1)) continue;
3841 if (This
->texUnitMap
[i
] != tex
) {
3842 device_map_stage(This
, i
, tex
);
3843 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3844 markTextureStagesDirty(This
, i
);
3851 static void device_map_psamplers(IWineD3DDeviceImpl
*This
) {
3852 const DWORD
*sampler_tokens
=
3853 ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.reg_maps
.samplers
;
3856 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
) {
3857 if (sampler_tokens
[i
] && This
->texUnitMap
[i
] != i
) {
3858 device_map_stage(This
, i
, i
);
3859 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3860 if (i
< MAX_TEXTURES
) {
3861 markTextureStagesDirty(This
, i
);
3867 static BOOL
device_unit_free_for_vs(IWineD3DDeviceImpl
*This
, const DWORD
*pshader_sampler_tokens
,
3868 const DWORD
*vshader_sampler_tokens
, int unit
)
3870 int current_mapping
= This
->rev_tex_unit_map
[unit
];
3872 if (current_mapping
== -1) {
3873 /* Not currently used */
3877 if (current_mapping
< MAX_FRAGMENT_SAMPLERS
) {
3878 /* Used by a fragment sampler */
3880 if (!pshader_sampler_tokens
) {
3881 /* No pixel shader, check fixed function */
3882 return current_mapping
>= MAX_TEXTURES
|| !(This
->fixed_function_usage_map
& (1 << current_mapping
));
3885 /* Pixel shader, check the shader's sampler map */
3886 return !pshader_sampler_tokens
[current_mapping
];
3889 /* Used by a vertex sampler */
3890 return !vshader_sampler_tokens
[current_mapping
];
3893 static void device_map_vsamplers(IWineD3DDeviceImpl
*This
, BOOL ps
) {
3894 const DWORD
*vshader_sampler_tokens
=
3895 ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.reg_maps
.samplers
;
3896 const DWORD
*pshader_sampler_tokens
= NULL
;
3897 int start
= GL_LIMITS(combined_samplers
) - 1;
3901 IWineD3DPixelShaderImpl
*pshader
= (IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
;
3903 /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3904 * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3905 pshader_sampler_tokens
= pshader
->baseShader
.reg_maps
.samplers
;
3908 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
) {
3909 int vsampler_idx
= i
+ MAX_FRAGMENT_SAMPLERS
;
3910 if (vshader_sampler_tokens
[i
]) {
3911 if (This
->texUnitMap
[vsampler_idx
] != -1) {
3912 /* Already mapped somewhere */
3916 while (start
>= 0) {
3917 if (device_unit_free_for_vs(This
, pshader_sampler_tokens
, vshader_sampler_tokens
, start
)) {
3918 device_map_stage(This
, vsampler_idx
, start
);
3919 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(vsampler_idx
));
3931 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl
*This
) {
3932 BOOL vs
= use_vs(This
->stateBlock
);
3933 BOOL ps
= use_ps(This
->stateBlock
);
3936 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3937 * that would be really messy and require shader recompilation
3938 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3939 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3942 device_map_psamplers(This
);
3944 device_map_fixed_function_samplers(This
);
3948 device_map_vsamplers(This
, ps
);
3952 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
3953 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3954 IWineD3DPixelShader
*oldShader
= This
->updateStateBlock
->pixelShader
;
3955 This
->updateStateBlock
->pixelShader
= pShader
;
3956 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
3958 /* Handle recording of state blocks */
3959 if (This
->isRecordingState
) {
3960 TRACE("Recording... not performing anything\n");
3963 if (This
->isRecordingState
) {
3964 TRACE("Recording... not performing anything\n");
3965 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3966 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3970 if(pShader
== oldShader
) {
3971 TRACE("App is setting the old pixel shader over, nothing to do\n");
3975 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3976 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3978 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3979 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
3984 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
3985 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3987 if (NULL
== ppShader
) {
3988 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This
);
3989 return WINED3DERR_INVALIDCALL
;
3992 *ppShader
= This
->stateBlock
->pixelShader
;
3993 if (NULL
!= *ppShader
) {
3994 IWineD3DPixelShader_AddRef(*ppShader
);
3996 TRACE("(%p) : returning %p\n", This
, *ppShader
);
4000 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
4001 IWineD3DDevice
*iface
,
4003 CONST BOOL
*srcData
,
4006 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4007 int i
, cnt
= min(count
, MAX_CONST_B
- start
);
4009 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4010 iface
, srcData
, start
, count
);
4012 if (srcData
== NULL
|| cnt
< 0)
4013 return WINED3DERR_INVALIDCALL
;
4015 memcpy(&This
->updateStateBlock
->pixelShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
4016 for (i
= 0; i
< cnt
; i
++)
4017 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
4019 for (i
= start
; i
< cnt
+ start
; ++i
) {
4020 This
->updateStateBlock
->changed
.pixelShaderConstantsB
|= (1 << i
);
4023 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
4028 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
4029 IWineD3DDevice
*iface
,
4034 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4035 int cnt
= min(count
, MAX_CONST_B
- start
);
4037 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4038 iface
, dstData
, start
, count
);
4040 if (dstData
== NULL
|| cnt
< 0)
4041 return WINED3DERR_INVALIDCALL
;
4043 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantB
[start
], cnt
* sizeof(BOOL
));
4047 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
4048 IWineD3DDevice
*iface
,
4053 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4054 int i
, cnt
= min(count
, MAX_CONST_I
- start
);
4056 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4057 iface
, srcData
, start
, count
);
4059 if (srcData
== NULL
|| cnt
< 0)
4060 return WINED3DERR_INVALIDCALL
;
4062 memcpy(&This
->updateStateBlock
->pixelShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
4063 for (i
= 0; i
< cnt
; i
++)
4064 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
4065 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4067 for (i
= start
; i
< cnt
+ start
; ++i
) {
4068 This
->updateStateBlock
->changed
.pixelShaderConstantsI
|= (1 << i
);
4071 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
4076 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
4077 IWineD3DDevice
*iface
,
4082 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4083 int cnt
= min(count
, MAX_CONST_I
- start
);
4085 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4086 iface
, dstData
, start
, count
);
4088 if (dstData
== NULL
|| cnt
< 0)
4089 return WINED3DERR_INVALIDCALL
;
4091 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
4095 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
4096 IWineD3DDevice
*iface
,
4098 CONST
float *srcData
,
4101 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4104 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
4105 iface
, srcData
, start
, count
);
4107 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
4108 if (srcData
== NULL
|| start
+ count
> GL_LIMITS(pshader_constantsF
) || start
> GL_LIMITS(pshader_constantsF
))
4109 return WINED3DERR_INVALIDCALL
;
4111 memcpy(&This
->updateStateBlock
->pixelShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
4113 for (i
= 0; i
< count
; i
++)
4114 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
4115 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
4118 if (!This
->isRecordingState
)
4120 This
->shader_backend
->shader_update_float_pixel_constants(iface
, start
, count
);
4121 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
4124 memset(This
->updateStateBlock
->changed
.pixelShaderConstantsF
+ start
, 1,
4125 sizeof(*This
->updateStateBlock
->changed
.pixelShaderConstantsF
) * count
);
4130 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
4131 IWineD3DDevice
*iface
,
4136 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4137 int cnt
= min(count
, GL_LIMITS(pshader_constantsF
) - start
);
4139 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
4140 iface
, dstData
, start
, count
);
4142 if (dstData
== NULL
|| cnt
< 0)
4143 return WINED3DERR_INVALIDCALL
;
4145 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
4149 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
4150 static HRESULT
process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
,
4151 const WineDirect3DVertexStridedData
*lpStrideData
, IWineD3DVertexBufferImpl
*dest
, DWORD dwFlags
)
4153 char *dest_ptr
, *dest_conv
= NULL
, *dest_conv_addr
= NULL
;
4155 DWORD DestFVF
= dest
->fvf
;
4157 WINED3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
4161 if (lpStrideData
->u
.s
.normal
.lpData
) {
4162 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
4165 if (lpStrideData
->u
.s
.position
.lpData
== NULL
) {
4166 ERR("Source has no position mask\n");
4167 return WINED3DERR_INVALIDCALL
;
4170 /* We might access VBOs from this code, so hold the lock */
4173 if (dest
->resource
.allocatedMemory
== NULL
) {
4174 /* This may happen if we do direct locking into a vbo. Unlikely,
4175 * but theoretically possible(ddraw processvertices test)
4177 dest
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap(), 0, dest
->resource
.size
);
4178 if(!dest
->resource
.allocatedMemory
) {
4180 ERR("Out of memory\n");
4181 return E_OUTOFMEMORY
;
4185 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
4186 checkGLcall("glBindBufferARB");
4187 src
= GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_READ_ONLY_ARB
));
4189 memcpy(dest
->resource
.allocatedMemory
, src
, dest
->resource
.size
);
4191 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
));
4192 checkGLcall("glUnmapBufferARB");
4196 /* Get a pointer into the destination vbo(create one if none exists) and
4197 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
4199 if(!dest
->vbo
&& GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT
)) {
4200 dest
->Flags
|= VBFLAG_CREATEVBO
;
4201 IWineD3DVertexBuffer_PreLoad((IWineD3DVertexBuffer
*) dest
);
4205 unsigned char extrabytes
= 0;
4206 /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4207 * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4208 * this may write 4 extra bytes beyond the area that should be written
4210 if(DestFVF
== WINED3DFVF_XYZ
) extrabytes
= 4;
4211 dest_conv_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwCount
* get_flexible_vertex_size(DestFVF
) + extrabytes
);
4212 if(!dest_conv_addr
) {
4213 ERR("Out of memory\n");
4214 /* Continue without storing converted vertices */
4216 dest_conv
= dest_conv_addr
;
4220 * a) WINED3DRS_CLIPPING is enabled
4221 * b) WINED3DVOP_CLIP is passed
4223 if(This
->stateBlock
->renderState
[WINED3DRS_CLIPPING
]) {
4224 static BOOL warned
= FALSE
;
4226 * The clipping code is not quite correct. Some things need
4227 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4228 * so disable clipping for now.
4229 * (The graphics in Half-Life are broken, and my processvertices
4230 * test crashes with IDirect3DDevice3)
4236 FIXME("Clipping is broken and disabled for now\n");
4238 } else doClip
= FALSE
;
4239 dest_ptr
= ((char *) dest
->resource
.allocatedMemory
) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
4241 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4244 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4245 WINED3DTS_PROJECTION
,
4247 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4248 WINED3DTS_WORLDMATRIX(0),
4251 TRACE("View mat:\n");
4252 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
);
4253 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
);
4254 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
);
4255 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
);
4257 TRACE("Proj mat:\n");
4258 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
);
4259 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
);
4260 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
);
4261 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
);
4263 TRACE("World mat:\n");
4264 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
);
4265 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
);
4266 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
);
4267 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
);
4269 /* Get the viewport */
4270 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
4271 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4272 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
4274 multiply_matrix(&mat
,&view_mat
,&world_mat
);
4275 multiply_matrix(&mat
,&proj_mat
,&mat
);
4277 numTextures
= (DestFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
4279 for (i
= 0; i
< dwCount
; i
+= 1) {
4280 unsigned int tex_index
;
4282 if ( ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
4283 ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
4284 /* The position first */
4286 (const float *)(lpStrideData
->u
.s
.position
.lpData
+ i
* lpStrideData
->u
.s
.position
.dwStride
);
4288 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
4290 /* Multiplication with world, view and projection matrix */
4291 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
);
4292 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
);
4293 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
);
4294 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
);
4296 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
4298 /* WARNING: The following things are taken from d3d7 and were not yet checked
4299 * against d3d8 or d3d9!
4302 /* Clipping conditions: From msdn
4304 * A vertex is clipped if it does not match the following requirements
4308 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4310 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4311 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4316 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
4317 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
4320 /* "Normal" viewport transformation (not clipped)
4321 * 1) The values are divided by rhw
4322 * 2) The y axis is negative, so multiply it with -1
4323 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4324 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4325 * 4) Multiply x with Width/2 and add Width/2
4326 * 5) The same for the height
4327 * 6) Add the viewpoint X and Y to the 2D coordinates and
4328 * The minimum Z value to z
4329 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4331 * Well, basically it's simply a linear transformation into viewport
4343 z
*= vp
.MaxZ
- vp
.MinZ
;
4345 x
+= vp
.Width
/ 2 + vp
.X
;
4346 y
+= vp
.Height
/ 2 + vp
.Y
;
4351 /* That vertex got clipped
4352 * Contrary to OpenGL it is not dropped completely, it just
4353 * undergoes a different calculation.
4355 TRACE("Vertex got clipped\n");
4362 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4363 * outside of the main vertex buffer memory. That needs some more
4368 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
4371 ( (float *) dest_ptr
)[0] = x
;
4372 ( (float *) dest_ptr
)[1] = y
;
4373 ( (float *) dest_ptr
)[2] = z
;
4374 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
4376 dest_ptr
+= 3 * sizeof(float);
4378 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4379 dest_ptr
+= sizeof(float);
4384 ( (float *) dest_conv
)[0] = x
* w
;
4385 ( (float *) dest_conv
)[1] = y
* w
;
4386 ( (float *) dest_conv
)[2] = z
* w
;
4387 ( (float *) dest_conv
)[3] = w
;
4389 dest_conv
+= 3 * sizeof(float);
4391 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4392 dest_conv
+= sizeof(float);
4396 if (DestFVF
& WINED3DFVF_PSIZE
) {
4397 dest_ptr
+= sizeof(DWORD
);
4398 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
4400 if (DestFVF
& WINED3DFVF_NORMAL
) {
4401 const float *normal
=
4402 (const float *)(lpStrideData
->u
.s
.normal
.lpData
+ i
* lpStrideData
->u
.s
.normal
.dwStride
);
4403 /* AFAIK this should go into the lighting information */
4404 FIXME("Didn't expect the destination to have a normal\n");
4405 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
4407 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
4411 if (DestFVF
& WINED3DFVF_DIFFUSE
) {
4412 const DWORD
*color_d
=
4413 (const DWORD
*)(lpStrideData
->u
.s
.diffuse
.lpData
+ i
* lpStrideData
->u
.s
.diffuse
.dwStride
);
4415 static BOOL warned
= FALSE
;
4418 ERR("No diffuse color in source, but destination has one\n");
4422 *( (DWORD
*) dest_ptr
) = 0xffffffff;
4423 dest_ptr
+= sizeof(DWORD
);
4426 *( (DWORD
*) dest_conv
) = 0xffffffff;
4427 dest_conv
+= sizeof(DWORD
);
4431 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
4433 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
4434 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
4435 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
4436 dest_conv
+= sizeof(DWORD
);
4441 if (DestFVF
& WINED3DFVF_SPECULAR
) {
4442 /* What's the color value in the feedback buffer? */
4443 const DWORD
*color_s
=
4444 (const DWORD
*)(lpStrideData
->u
.s
.specular
.lpData
+ i
* lpStrideData
->u
.s
.specular
.dwStride
);
4446 static BOOL warned
= FALSE
;
4449 ERR("No specular color in source, but destination has one\n");
4453 *( (DWORD
*) dest_ptr
) = 0xFF000000;
4454 dest_ptr
+= sizeof(DWORD
);
4457 *( (DWORD
*) dest_conv
) = 0xFF000000;
4458 dest_conv
+= sizeof(DWORD
);
4462 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
4464 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
4465 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
4466 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
4467 dest_conv
+= sizeof(DWORD
);
4472 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
4473 const float *tex_coord
=
4474 (const float *)(lpStrideData
->u
.s
.texCoords
[tex_index
].lpData
+
4475 i
* lpStrideData
->u
.s
.texCoords
[tex_index
].dwStride
);
4477 ERR("No source texture, but destination requests one\n");
4478 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4479 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4482 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4484 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4491 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->vbo
));
4492 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4493 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, dwDestIndex
* get_flexible_vertex_size(DestFVF
),
4494 dwCount
* get_flexible_vertex_size(DestFVF
),
4496 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4497 HeapFree(GetProcessHeap(), 0, dest_conv_addr
);
4504 #undef copy_and_next
4506 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, IWineD3DVertexBuffer
* pDestBuffer
, IWineD3DVertexDeclaration
* pVertexDecl
, DWORD Flags
) {
4507 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4508 WineDirect3DVertexStridedData strided
;
4509 BOOL vbo
= FALSE
, streamWasUP
= This
->stateBlock
->streamIsUP
;
4510 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, Flags
);
4513 ERR("Output vertex declaration not implemented yet\n");
4516 /* Need any context to write to the vbo. */
4517 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
4519 /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4520 * control the streamIsUP flag, thus restore it afterwards.
4522 This
->stateBlock
->streamIsUP
= FALSE
;
4523 memset(&strided
, 0, sizeof(strided
));
4524 primitiveDeclarationConvertToStridedData(iface
, FALSE
, &strided
, &vbo
);
4525 This
->stateBlock
->streamIsUP
= streamWasUP
;
4527 if(vbo
|| SrcStartIndex
) {
4529 /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4530 * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the strided structure
4532 * Also get the start index in, but only loop over all elements if there's something to add at all.
4534 #define FIXSRC(type) \
4535 if(strided.u.s.type.VBO) { \
4536 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) This->stateBlock->streamSource[strided.u.s.type.streamNo]; \
4537 strided.u.s.type.VBO = 0; \
4538 strided.u.s.type.lpData = (BYTE *) ((unsigned long) strided.u.s.type.lpData + (unsigned long) vb->resource.allocatedMemory); \
4540 GL_EXTCALL(glDeleteBuffersARB(1, &vb->vbo)); \
4544 if(strided.u.s.type.lpData) { \
4545 strided.u.s.type.lpData += strided.u.s.type.dwStride * SrcStartIndex; \
4548 FIXSRC(blendWeights
);
4549 FIXSRC(blendMatrixIndices
);
4554 for(i
= 0; i
< WINED3DDP_MAXTEXCOORD
; i
++) {
4555 FIXSRC(texCoords
[i
]);
4568 return process_vertices_strided(This
, DestIndex
, VertexCount
, &strided
, (IWineD3DVertexBufferImpl
*) pDestBuffer
, Flags
);
4572 * Get / Set Texture Stage States
4573 * TODO: Verify against dx9 definitions
4575 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
4576 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4577 DWORD oldValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4579 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
4581 if (Stage
>= MAX_TEXTURES
) {
4582 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage
, MAX_TEXTURES
- 1);
4586 This
->updateStateBlock
->changed
.textureState
[Stage
] |= 1 << Type
;
4587 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
4589 if (This
->isRecordingState
) {
4590 TRACE("Recording... not performing anything\n");
4594 /* Checked after the assignments to allow proper stateblock recording */
4595 if(oldValue
== Value
) {
4596 TRACE("App is setting the old value over, nothing to do\n");
4600 if(Stage
> This
->stateBlock
->lowest_disabled_stage
&&
4601 This
->StateTable
[STATE_TEXTURESTAGE(0, Type
)].representative
== STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP
)) {
4602 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4603 * Changes in other states are important on disabled stages too
4608 if(Type
== WINED3DTSS_COLOROP
) {
4611 if(Value
== WINED3DTOP_DISABLE
&& oldValue
!= WINED3DTOP_DISABLE
) {
4612 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4613 * they have to be disabled
4615 * The current stage is dirtified below.
4617 for(i
= Stage
+ 1; i
< This
->stateBlock
->lowest_disabled_stage
; i
++) {
4618 TRACE("Additionally dirtifying stage %d\n", i
);
4619 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4621 This
->stateBlock
->lowest_disabled_stage
= Stage
;
4622 TRACE("New lowest disabled: %d\n", Stage
);
4623 } else if(Value
!= WINED3DTOP_DISABLE
&& oldValue
== WINED3DTOP_DISABLE
) {
4624 /* Previously disabled stage enabled. Stages above it may need enabling
4625 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4626 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4628 * Again stage Stage doesn't need to be dirtified here, it is handled below.
4631 for(i
= Stage
+ 1; i
< GL_LIMITS(texture_stages
); i
++) {
4632 if(This
->updateStateBlock
->textureState
[i
][WINED3DTSS_COLOROP
] == WINED3DTOP_DISABLE
) {
4635 TRACE("Additionally dirtifying stage %d due to enable\n", i
);
4636 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4638 This
->stateBlock
->lowest_disabled_stage
= i
;
4639 TRACE("New lowest disabled: %d\n", i
);
4643 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, Type
));
4648 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
4649 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4650 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
4651 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
4658 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
* pTexture
) {
4659 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4660 IWineD3DBaseTexture
*oldTexture
;
4662 TRACE("(%p) : Stage %#x, Texture %p\n", This
, Stage
, pTexture
);
4664 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
4665 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4668 if (Stage
>= sizeof(This
->stateBlock
->textures
)/sizeof(This
->stateBlock
->textures
[0])) {
4669 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
4670 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4673 oldTexture
= This
->updateStateBlock
->textures
[Stage
];
4675 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4676 if (pTexture
&& ((IWineD3DTextureImpl
*)pTexture
)->resource
.pool
== WINED3DPOOL_SCRATCH
)
4678 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture
);
4679 return WINED3DERR_INVALIDCALL
;
4682 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages
));
4683 TRACE("(%p) : oldtexture(%p)\n", This
,oldTexture
);
4685 This
->updateStateBlock
->changed
.textures
|= 1 << Stage
;
4686 TRACE("(%p) : setting new texture to %p\n", This
, pTexture
);
4687 This
->updateStateBlock
->textures
[Stage
] = pTexture
;
4689 /* Handle recording of state blocks */
4690 if (This
->isRecordingState
) {
4691 TRACE("Recording... not performing anything\n");
4695 if(oldTexture
== pTexture
) {
4696 TRACE("App is setting the same texture again, nothing to do\n");
4700 /** NOTE: MSDN says that setTexture increases the reference count,
4701 * and that the application must set the texture back to null (or have a leaky application),
4702 * This means we should pass the refcount up to the parent
4703 *******************************/
4704 if (NULL
!= This
->updateStateBlock
->textures
[Stage
]) {
4705 IWineD3DBaseTextureImpl
*new = (IWineD3DBaseTextureImpl
*) This
->updateStateBlock
->textures
[Stage
];
4706 ULONG bindCount
= InterlockedIncrement(&new->baseTexture
.bindCount
);
4707 UINT dimensions
= IWineD3DBaseTexture_GetTextureDimensions(pTexture
);
4709 IWineD3DBaseTexture_AddRef(This
->updateStateBlock
->textures
[Stage
]);
4711 if (!oldTexture
|| dimensions
!= IWineD3DBaseTexture_GetTextureDimensions(oldTexture
))
4713 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
4716 if(oldTexture
== NULL
&& Stage
< MAX_TEXTURES
) {
4717 /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4718 * so the COLOROP and ALPHAOP have to be dirtified.
4720 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_COLOROP
));
4721 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_ALPHAOP
));
4723 if(bindCount
== 1) {
4724 new->baseTexture
.sampler
= Stage
;
4726 /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4730 if (NULL
!= oldTexture
) {
4731 IWineD3DBaseTextureImpl
*old
= (IWineD3DBaseTextureImpl
*) oldTexture
;
4732 LONG bindCount
= InterlockedDecrement(&old
->baseTexture
.bindCount
);
4734 IWineD3DBaseTexture_Release(oldTexture
);
4735 if(pTexture
== NULL
&& Stage
< MAX_TEXTURES
) {
4736 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_COLOROP
));
4737 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, WINED3DTSS_ALPHAOP
));
4740 if(bindCount
&& old
->baseTexture
.sampler
== Stage
) {
4742 /* Have to do a search for the other sampler(s) where the texture is bound to
4743 * Shouldn't happen as long as apps bind a texture only to one stage
4745 TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4746 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
4747 if(This
->updateStateBlock
->textures
[i
] == oldTexture
) {
4748 old
->baseTexture
.sampler
= i
;
4755 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Stage
));
4760 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
4761 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4763 TRACE("(%p) : Stage %#x, ppTexture %p\n", This
, Stage
, ppTexture
);
4765 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
4766 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4769 if (Stage
>= sizeof(This
->stateBlock
->textures
)/sizeof(This
->stateBlock
->textures
[0])) {
4770 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
4771 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4774 *ppTexture
=This
->stateBlock
->textures
[Stage
];
4776 IWineD3DBaseTexture_AddRef(*ppTexture
);
4778 TRACE("(%p) : Returning %p\n", This
, *ppTexture
);
4786 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT iSwapChain
, UINT BackBuffer
, WINED3DBACKBUFFER_TYPE Type
,
4787 IWineD3DSurface
**ppBackBuffer
) {
4788 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4789 IWineD3DSwapChain
*swapChain
;
4792 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This
, BackBuffer
, Type
, iSwapChain
, *ppBackBuffer
);
4794 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4795 if (hr
== WINED3D_OK
) {
4796 hr
= IWineD3DSwapChain_GetBackBuffer(swapChain
, BackBuffer
, Type
, ppBackBuffer
);
4797 IWineD3DSwapChain_Release(swapChain
);
4799 *ppBackBuffer
= NULL
;
4804 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
4805 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4806 WARN("(%p) : stub, calling idirect3d for now\n", This
);
4807 return IWineD3D_GetDeviceCaps(This
->wineD3D
, This
->adapterNo
, This
->devType
, pCaps
);
4810 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
4811 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4812 IWineD3DSwapChain
*swapChain
;
4815 if(iSwapChain
> 0) {
4816 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4817 if (hr
== WINED3D_OK
) {
4818 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
4819 IWineD3DSwapChain_Release(swapChain
);
4821 FIXME("(%p) Error getting display mode\n", This
);
4824 /* Don't read the real display mode,
4825 but return the stored mode instead. X11 can't change the color
4826 depth, and some apps are pretty angry if they SetDisplayMode from
4827 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4829 Also don't relay to the swapchain because with ddraw it's possible
4830 that there isn't a swapchain at all */
4831 pMode
->Width
= This
->ddraw_width
;
4832 pMode
->Height
= This
->ddraw_height
;
4833 pMode
->Format
= This
->ddraw_format
;
4834 pMode
->RefreshRate
= 0;
4842 * Stateblock related functions
4845 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
4846 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4847 IWineD3DStateBlock
*stateblock
;
4850 TRACE("(%p)\n", This
);
4852 if (This
->isRecordingState
) return WINED3DERR_INVALIDCALL
;
4854 hr
= IWineD3DDeviceImpl_CreateStateBlock(iface
, WINED3DSBT_RECORDED
, &stateblock
, NULL
);
4855 if (FAILED(hr
)) return hr
;
4857 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
4858 This
->updateStateBlock
= (IWineD3DStateBlockImpl
*)stateblock
;
4859 This
->isRecordingState
= TRUE
;
4861 TRACE("(%p) recording stateblock %p\n", This
, stateblock
);
4866 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
4867 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4869 IWineD3DStateBlockImpl
*object
= This
->updateStateBlock
;
4871 if (!This
->isRecordingState
) {
4872 WARN("(%p) not recording! returning error\n", This
);
4873 *ppStateBlock
= NULL
;
4874 return WINED3DERR_INVALIDCALL
;
4877 for (i
= 0; i
<= WINEHIGHEST_RENDER_STATE
>> 5; ++i
)
4879 DWORD map
= object
->changed
.renderState
[i
];
4880 for (j
= 0; map
; map
>>= 1, ++j
)
4882 if (!(map
& 1)) continue;
4884 object
->contained_render_states
[object
->num_contained_render_states
++] = (i
<< 5) | j
;
4888 for (i
= 0; i
<= HIGHEST_TRANSFORMSTATE
>> 5; ++i
)
4890 DWORD map
= object
->changed
.transform
[i
];
4891 for (j
= 0; map
; map
>>= 1, ++j
)
4893 if (!(map
& 1)) continue;
4895 object
->contained_transform_states
[object
->num_contained_transform_states
++] = (i
<< 5) | j
;
4898 for(i
= 0; i
< GL_LIMITS(vshader_constantsF
); i
++) {
4899 if(object
->changed
.vertexShaderConstantsF
[i
]) {
4900 object
->contained_vs_consts_f
[object
->num_contained_vs_consts_f
] = i
;
4901 object
->num_contained_vs_consts_f
++;
4904 for(i
= 0; i
< MAX_CONST_I
; i
++) {
4905 if (object
->changed
.vertexShaderConstantsI
& (1 << i
))
4907 object
->contained_vs_consts_i
[object
->num_contained_vs_consts_i
] = i
;
4908 object
->num_contained_vs_consts_i
++;
4911 for(i
= 0; i
< MAX_CONST_B
; i
++) {
4912 if (object
->changed
.vertexShaderConstantsB
& (1 << i
))
4914 object
->contained_vs_consts_b
[object
->num_contained_vs_consts_b
] = i
;
4915 object
->num_contained_vs_consts_b
++;
4918 for (i
= 0; i
< GL_LIMITS(pshader_constantsF
); ++i
)
4920 if (object
->changed
.pixelShaderConstantsF
[i
])
4922 object
->contained_ps_consts_f
[object
->num_contained_ps_consts_f
] = i
;
4923 ++object
->num_contained_ps_consts_f
;
4926 for(i
= 0; i
< MAX_CONST_I
; i
++) {
4927 if (object
->changed
.pixelShaderConstantsI
& (1 << i
))
4929 object
->contained_ps_consts_i
[object
->num_contained_ps_consts_i
] = i
;
4930 object
->num_contained_ps_consts_i
++;
4933 for(i
= 0; i
< MAX_CONST_B
; i
++) {
4934 if (object
->changed
.pixelShaderConstantsB
& (1 << i
))
4936 object
->contained_ps_consts_b
[object
->num_contained_ps_consts_b
] = i
;
4937 object
->num_contained_ps_consts_b
++;
4940 for(i
= 0; i
< MAX_TEXTURES
; i
++) {
4941 DWORD map
= object
->changed
.textureState
[i
];
4943 for(j
= 0; map
; map
>>= 1, ++j
)
4945 if (!(map
& 1)) continue;
4947 object
->contained_tss_states
[object
->num_contained_tss_states
].stage
= i
;
4948 object
->contained_tss_states
[object
->num_contained_tss_states
].state
= j
;
4949 ++object
->num_contained_tss_states
;
4952 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++){
4953 DWORD map
= object
->changed
.samplerState
[i
];
4955 for (j
= 0; map
; map
>>= 1, ++j
)
4957 if (!(map
& 1)) continue;
4959 object
->contained_sampler_states
[object
->num_contained_sampler_states
].stage
= i
;
4960 object
->contained_sampler_states
[object
->num_contained_sampler_states
].state
= j
;
4961 ++object
->num_contained_sampler_states
;
4965 *ppStateBlock
= (IWineD3DStateBlock
*) object
;
4966 This
->isRecordingState
= FALSE
;
4967 This
->updateStateBlock
= This
->stateBlock
;
4968 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
4969 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4970 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
4975 * Scene related functions
4977 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4978 /* At the moment we have no need for any functionality at the beginning
4980 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4981 TRACE("(%p)\n", This
);
4984 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4985 return WINED3DERR_INVALIDCALL
;
4987 This
->inScene
= TRUE
;
4991 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
) {
4992 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4993 TRACE("(%p)\n", This
);
4995 if(!This
->inScene
) {
4996 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4997 return WINED3DERR_INVALIDCALL
;
5000 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
5001 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
5003 /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
5007 This
->inScene
= FALSE
;
5011 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
5012 CONST RECT
* pSourceRect
, CONST RECT
* pDestRect
,
5013 HWND hDestWindowOverride
, CONST RGNDATA
* pDirtyRegion
) {
5014 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5015 IWineD3DSwapChain
*swapChain
= NULL
;
5017 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
5019 TRACE("(%p) Presenting the frame\n", This
);
5021 for(i
= 0 ; i
< swapchains
; i
++) {
5023 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, &swapChain
);
5024 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
5025 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
5026 IWineD3DSwapChain_Release(swapChain
);
5032 /* Not called from the VTable (internal subroutine) */
5033 HRESULT
IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl
*This
, IWineD3DSurfaceImpl
*target
, DWORD Count
,
5034 CONST WINED3DRECT
* pRects
, DWORD Flags
, WINED3DCOLOR Color
,
5035 float Z
, DWORD Stencil
) {
5036 GLbitfield glMask
= 0;
5038 WINED3DRECT curRect
;
5040 const WINED3DVIEWPORT
*vp
= &This
->stateBlock
->viewport
;
5041 UINT drawable_width
, drawable_height
;
5042 IWineD3DSurfaceImpl
*depth_stencil
= (IWineD3DSurfaceImpl
*) This
->stencilBufferTarget
;
5043 IWineD3DSwapChainImpl
*swapchain
= NULL
;
5045 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
5046 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
5047 * for the cleared parts, and the untouched parts.
5049 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
5050 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
5051 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
5052 * checking all this if the dest surface is in the drawable anyway.
5054 if((Flags
& WINED3DCLEAR_TARGET
) && !(target
->Flags
& SFLAG_INDRAWABLE
)) {
5056 if(vp
->X
!= 0 || vp
->Y
!= 0 ||
5057 vp
->Width
< target
->currentDesc
.Width
|| vp
->Height
< target
->currentDesc
.Height
) {
5058 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
5061 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
5062 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
5063 This
->stateBlock
->scissorRect
.right
< target
->currentDesc
.Width
||
5064 This
->stateBlock
->scissorRect
.bottom
< target
->currentDesc
.Height
)) {
5065 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
5068 if(Count
> 0 && pRects
&& (
5069 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
5070 pRects
[0].x2
< target
->currentDesc
.Width
||
5071 pRects
[0].y2
< target
->currentDesc
.Height
)) {
5072 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
5079 target
->get_drawable_size(target
, &drawable_width
, &drawable_height
);
5081 ActivateContext(This
, (IWineD3DSurface
*) target
, CTXUSAGE_CLEAR
);
5084 /* Only set the values up once, as they are not changing */
5085 if (Flags
& WINED3DCLEAR_STENCIL
) {
5086 glClearStencil(Stencil
);
5087 checkGLcall("glClearStencil");
5088 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
5089 glStencilMask(0xFFFFFFFF);
5092 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
5093 DWORD location
= This
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
5094 glDepthMask(GL_TRUE
);
5096 checkGLcall("glClearDepth");
5097 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
5098 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZWRITEENABLE
));
5100 if (vp
->X
!= 0 || vp
->Y
!= 0 ||
5101 vp
->Width
< depth_stencil
->currentDesc
.Width
|| vp
->Height
< depth_stencil
->currentDesc
.Height
) {
5102 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5104 else if (This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
5105 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
5106 This
->stateBlock
->scissorRect
.right
< depth_stencil
->currentDesc
.Width
||
5107 This
->stateBlock
->scissorRect
.bottom
< depth_stencil
->currentDesc
.Height
)) {
5108 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5110 else if (Count
> 0 && pRects
&& (
5111 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
5112 pRects
[0].x2
< depth_stencil
->currentDesc
.Width
||
5113 pRects
[0].y2
< depth_stencil
->currentDesc
.Height
)) {
5114 surface_load_ds_location(This
->stencilBufferTarget
, location
);
5118 if (Flags
& WINED3DCLEAR_TARGET
) {
5119 TRACE("Clearing screen with glClear to color %x\n", Color
);
5120 glClearColor(D3DCOLOR_R(Color
),
5124 checkGLcall("glClearColor");
5126 /* Clear ALL colors! */
5127 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5128 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
5131 vp_rect
.left
= vp
->X
;
5132 vp_rect
.top
= vp
->Y
;
5133 vp_rect
.right
= vp
->X
+ vp
->Width
;
5134 vp_rect
.bottom
= vp
->Y
+ vp
->Height
;
5135 if (!(Count
> 0 && pRects
)) {
5136 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
5137 IntersectRect(&vp_rect
, &vp_rect
, &This
->stateBlock
->scissorRect
);
5139 if(This
->render_offscreen
) {
5140 glScissor(vp_rect
.left
, vp_rect
.top
,
5141 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
5143 glScissor(vp_rect
.left
, drawable_height
- vp_rect
.bottom
,
5144 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
5146 checkGLcall("glScissor");
5148 checkGLcall("glClear");
5150 /* Now process each rect in turn */
5151 for (i
= 0; i
< Count
; i
++) {
5152 /* Note gl uses lower left, width/height */
5153 IntersectRect((RECT
*)&curRect
, &vp_rect
, (const RECT
*)&pRects
[i
]);
5154 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
5155 IntersectRect((RECT
*) &curRect
, (RECT
*) &curRect
, &This
->stateBlock
->scissorRect
);
5157 TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This
,
5158 pRects
[i
].x1
, pRects
[i
].y1
, pRects
[i
].x2
, pRects
[i
].y2
,
5159 curRect
.x1
, (target
->currentDesc
.Height
- curRect
.y2
),
5160 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5162 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
5163 * The rectangle is not cleared, no error is returned, but further rectanlges are
5164 * still cleared if they are valid
5166 if(curRect
.x1
> curRect
.x2
|| curRect
.y1
> curRect
.y2
) {
5167 TRACE("Rectangle with negative dimensions, ignoring\n");
5171 if(This
->render_offscreen
) {
5172 glScissor(curRect
.x1
, curRect
.y1
,
5173 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5175 glScissor(curRect
.x1
, drawable_height
- curRect
.y2
,
5176 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
5178 checkGLcall("glScissor");
5181 checkGLcall("glClear");
5185 /* Restore the old values (why..?) */
5186 if (Flags
& WINED3DCLEAR_STENCIL
) {
5187 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
5189 if (Flags
& WINED3DCLEAR_TARGET
) {
5190 DWORD mask
= This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
];
5191 glColorMask(mask
& WINED3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
5192 mask
& WINED3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
5193 mask
& WINED3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
5194 mask
& WINED3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
5196 /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
5197 * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
5199 IWineD3DSurface_ModifyLocation(This
->lastActiveRenderTarget
, SFLAG_INDRAWABLE
, TRUE
);
5201 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
5202 /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
5203 DWORD location
= This
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
5204 surface_modify_ds_location(This
->stencilBufferTarget
, location
);
5209 if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface
*)target
, &IID_IWineD3DSwapChain
, (void **)&swapchain
))) {
5210 if (target
== (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
) {
5213 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
5219 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST WINED3DRECT
* pRects
,
5220 DWORD Flags
, WINED3DCOLOR Color
, float Z
, DWORD Stencil
) {
5221 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5222 IWineD3DSurfaceImpl
*target
= (IWineD3DSurfaceImpl
*)This
->render_targets
[0];
5224 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This
,
5225 Count
, pRects
, Flags
, Color
, Z
, Stencil
);
5227 if(Flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && This
->stencilBufferTarget
== NULL
) {
5228 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
5229 /* TODO: What about depth stencil buffers without stencil bits? */
5230 return WINED3DERR_INVALIDCALL
;
5233 return IWineD3DDeviceImpl_ClearSurface(This
, target
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
5239 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
, UINT StartVertex
,
5240 UINT PrimitiveCount
) {
5242 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5244 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This
, PrimitiveType
,
5245 debug_d3dprimitivetype(PrimitiveType
),
5246 StartVertex
, PrimitiveCount
);
5248 if(!This
->stateBlock
->vertexDecl
) {
5249 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5250 return WINED3DERR_INVALIDCALL
;
5253 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
5254 if(This
->stateBlock
->streamIsUP
) {
5255 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5256 This
->stateBlock
->streamIsUP
= FALSE
;
5259 if(This
->stateBlock
->loadBaseVertexIndex
!= 0) {
5260 This
->stateBlock
->loadBaseVertexIndex
= 0;
5261 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5263 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
5264 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0/* NumVertices */, StartVertex
/* start_idx */,
5265 0 /* indxSize */, NULL
/* indxData */, 0 /* minIndex */);
5269 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
5270 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
,
5271 WINED3DPRIMITIVETYPE PrimitiveType
,
5272 UINT minIndex
, UINT NumVertices
, UINT startIndex
, UINT primCount
) {
5274 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5276 IWineD3DIndexBuffer
*pIB
;
5277 WINED3DINDEXBUFFER_DESC IdxBufDsc
;
5280 pIB
= This
->stateBlock
->pIndexData
;
5282 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
5283 * without an index buffer set. (The first time at least...)
5284 * D3D8 simply dies, but I doubt it can do much harm to return
5285 * D3DERR_INVALIDCALL there as well. */
5286 WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This
);
5287 return WINED3DERR_INVALIDCALL
;
5290 if(!This
->stateBlock
->vertexDecl
) {
5291 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5292 return WINED3DERR_INVALIDCALL
;
5295 if(This
->stateBlock
->streamIsUP
) {
5296 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5297 This
->stateBlock
->streamIsUP
= FALSE
;
5299 vbo
= ((IWineD3DIndexBufferImpl
*) pIB
)->vbo
;
5301 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This
,
5302 PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5303 minIndex
, NumVertices
, startIndex
, primCount
);
5305 IWineD3DIndexBuffer_GetDesc(pIB
, &IdxBufDsc
);
5306 if (IdxBufDsc
.Format
== WINED3DFMT_INDEX16
) {
5312 if(This
->stateBlock
->loadBaseVertexIndex
!= This
->stateBlock
->baseVertexIndex
) {
5313 This
->stateBlock
->loadBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
5314 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5317 drawPrimitive(iface
, PrimitiveType
, primCount
, NumVertices
, startIndex
,
5318 idxStride
, vbo
? NULL
: ((IWineD3DIndexBufferImpl
*) pIB
)->resource
.allocatedMemory
, minIndex
);
5323 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
,
5324 UINT PrimitiveCount
, CONST
void* pVertexStreamZeroData
,
5325 UINT VertexStreamZeroStride
) {
5326 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5327 IWineD3DVertexBuffer
*vb
;
5329 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This
, PrimitiveType
,
5330 debug_d3dprimitivetype(PrimitiveType
),
5331 PrimitiveCount
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5333 if(!This
->stateBlock
->vertexDecl
) {
5334 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5335 return WINED3DERR_INVALIDCALL
;
5338 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5339 vb
= This
->stateBlock
->streamSource
[0];
5340 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5341 if(vb
) IWineD3DVertexBuffer_Release(vb
);
5342 This
->stateBlock
->streamOffset
[0] = 0;
5343 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5344 This
->stateBlock
->streamIsUP
= TRUE
;
5345 This
->stateBlock
->loadBaseVertexIndex
= 0;
5347 /* TODO: Only mark dirty if drawing from a different UP address */
5348 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
5350 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* NumVertices */,
5351 0 /* start_idx */, 0 /* indxSize*/, NULL
/* indxData */, 0 /* indxMin */);
5353 /* MSDN specifies stream zero settings must be set to NULL */
5354 This
->stateBlock
->streamStride
[0] = 0;
5355 This
->stateBlock
->streamSource
[0] = NULL
;
5357 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
5358 * the new stream sources or use UP drawing again
5363 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
, WINED3DPRIMITIVETYPE PrimitiveType
,
5364 UINT MinVertexIndex
, UINT NumVertices
,
5365 UINT PrimitiveCount
, CONST
void* pIndexData
,
5366 WINED3DFORMAT IndexDataFormat
,CONST
void* pVertexStreamZeroData
,
5367 UINT VertexStreamZeroStride
) {
5369 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5370 IWineD3DVertexBuffer
*vb
;
5371 IWineD3DIndexBuffer
*ib
;
5373 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
5374 This
, PrimitiveType
, debug_d3dprimitivetype(PrimitiveType
),
5375 MinVertexIndex
, NumVertices
, PrimitiveCount
, pIndexData
,
5376 IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
5378 if(!This
->stateBlock
->vertexDecl
) {
5379 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5380 return WINED3DERR_INVALIDCALL
;
5383 if (IndexDataFormat
== WINED3DFMT_INDEX16
) {
5389 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
5390 vb
= This
->stateBlock
->streamSource
[0];
5391 This
->stateBlock
->streamSource
[0] = (IWineD3DVertexBuffer
*)pVertexStreamZeroData
;
5392 if(vb
) IWineD3DVertexBuffer_Release(vb
);
5393 This
->stateBlock
->streamIsUP
= TRUE
;
5394 This
->stateBlock
->streamOffset
[0] = 0;
5395 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
5397 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5398 This
->stateBlock
->baseVertexIndex
= 0;
5399 This
->stateBlock
->loadBaseVertexIndex
= 0;
5400 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5401 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5402 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5404 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, NumVertices
, 0 /* start_idx */, idxStride
, pIndexData
, MinVertexIndex
);
5406 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5407 This
->stateBlock
->streamSource
[0] = NULL
;
5408 This
->stateBlock
->streamStride
[0] = 0;
5409 ib
= This
->stateBlock
->pIndexData
;
5411 IWineD3DIndexBuffer_Release(ib
);
5412 This
->stateBlock
->pIndexData
= NULL
;
5414 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5415 * SetStreamSource to specify a vertex buffer
5421 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice
*iface
,
5422 WINED3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
,
5423 const WineDirect3DVertexStridedData
*DrawPrimStrideData
)
5425 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5427 /* Mark the state dirty until we have nicer tracking
5428 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5431 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5432 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5433 This
->stateBlock
->baseVertexIndex
= 0;
5434 This
->up_strided
= DrawPrimStrideData
;
5435 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0, 0, 0, NULL
, 0);
5436 This
->up_strided
= NULL
;
5440 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice
*iface
,
5441 WINED3DPRIMITIVETYPE PrimitiveType
, UINT PrimitiveCount
,
5442 const WineDirect3DVertexStridedData
*DrawPrimStrideData
, UINT NumVertices
, const void *pIndexData
,
5443 WINED3DFORMAT IndexDataFormat
)
5445 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5446 DWORD idxSize
= (IndexDataFormat
== WINED3DFMT_INDEX32
? 4 : 2);
5448 /* Mark the state dirty until we have nicer tracking
5449 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5452 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5453 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5454 This
->stateBlock
->streamIsUP
= TRUE
;
5455 This
->stateBlock
->baseVertexIndex
= 0;
5456 This
->up_strided
= DrawPrimStrideData
;
5457 drawPrimitive(iface
, PrimitiveType
, PrimitiveCount
, 0 /* numindices */, 0 /* start_idx */, idxSize
, pIndexData
, 0 /* minindex */);
5458 This
->up_strided
= NULL
;
5462 static HRESULT
IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice
*iface
, IWineD3DVolume
*pSourceVolume
, IWineD3DVolume
*pDestinationVolume
) {
5463 /* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
5464 * not callable by the app directly no parameter validation checks are needed here.
5466 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5467 WINED3DLOCKED_BOX src
;
5468 WINED3DLOCKED_BOX dst
;
5470 TRACE("(%p)->(%p, %p)\n", This
, pSourceVolume
, pDestinationVolume
);
5472 /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5473 * dirtification to improve loading performance.
5475 hr
= IWineD3DVolume_LockBox(pSourceVolume
, &src
, NULL
, WINED3DLOCK_READONLY
);
5476 if(FAILED(hr
)) return hr
;
5477 hr
= IWineD3DVolume_LockBox(pDestinationVolume
, &dst
, NULL
, WINED3DLOCK_DISCARD
);
5479 IWineD3DVolume_UnlockBox(pSourceVolume
);
5483 memcpy(dst
.pBits
, src
.pBits
, ((IWineD3DVolumeImpl
*) pDestinationVolume
)->resource
.size
);
5485 hr
= IWineD3DVolume_UnlockBox(pDestinationVolume
);
5487 IWineD3DVolume_UnlockBox(pSourceVolume
);
5489 hr
= IWineD3DVolume_UnlockBox(pSourceVolume
);
5494 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
5495 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice
*iface
, IWineD3DBaseTexture
*pSourceTexture
, IWineD3DBaseTexture
*pDestinationTexture
){
5496 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5497 HRESULT hr
= WINED3D_OK
;
5498 WINED3DRESOURCETYPE sourceType
;
5499 WINED3DRESOURCETYPE destinationType
;
5502 /* TODO: think about moving the code into IWineD3DBaseTexture */
5504 TRACE("(%p) Source %p Destination %p\n", This
, pSourceTexture
, pDestinationTexture
);
5506 /* verify that the source and destination textures aren't NULL */
5507 if (NULL
== pSourceTexture
|| NULL
== pDestinationTexture
) {
5508 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
5509 This
, pSourceTexture
, pDestinationTexture
);
5510 hr
= WINED3DERR_INVALIDCALL
;
5513 if (pSourceTexture
== pDestinationTexture
) {
5514 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
5515 This
, pSourceTexture
, pDestinationTexture
);
5516 hr
= WINED3DERR_INVALIDCALL
;
5518 /* Verify that the source and destination textures are the same type */
5519 sourceType
= IWineD3DBaseTexture_GetType(pSourceTexture
);
5520 destinationType
= IWineD3DBaseTexture_GetType(pDestinationTexture
);
5522 if (sourceType
!= destinationType
) {
5523 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
5525 hr
= WINED3DERR_INVALIDCALL
;
5528 /* check that both textures have the identical numbers of levels */
5529 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture
)) {
5530 WARN("(%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL\n", This
, pSourceTexture
, pDestinationTexture
);
5531 hr
= WINED3DERR_INVALIDCALL
;
5534 if (WINED3D_OK
== hr
) {
5535 IWineD3DBaseTextureImpl
*pDestImpl
= (IWineD3DBaseTextureImpl
*) pDestinationTexture
;
5537 /* Make sure that the destination texture is loaded */
5538 pDestImpl
->baseTexture
.internal_preload(pDestinationTexture
, SRGB_RGB
);
5540 /* Update every surface level of the texture */
5541 levels
= IWineD3DBaseTexture_GetLevelCount(pDestinationTexture
);
5543 switch (sourceType
) {
5544 case WINED3DRTYPE_TEXTURE
:
5546 IWineD3DSurface
*srcSurface
;
5547 IWineD3DSurface
*destSurface
;
5549 for (i
= 0 ; i
< levels
; ++i
) {
5550 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pSourceTexture
, i
, &srcSurface
);
5551 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)pDestinationTexture
, i
, &destSurface
);
5552 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5553 IWineD3DSurface_Release(srcSurface
);
5554 IWineD3DSurface_Release(destSurface
);
5555 if (WINED3D_OK
!= hr
) {
5556 WARN("(%p) : Call to update surface failed\n", This
);
5562 case WINED3DRTYPE_CUBETEXTURE
:
5564 IWineD3DSurface
*srcSurface
;
5565 IWineD3DSurface
*destSurface
;
5566 WINED3DCUBEMAP_FACES faceType
;
5568 for (i
= 0 ; i
< levels
; ++i
) {
5569 /* Update each cube face */
5570 for (faceType
= WINED3DCUBEMAP_FACE_POSITIVE_X
; faceType
<= WINED3DCUBEMAP_FACE_NEGATIVE_Z
; ++faceType
){
5571 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pSourceTexture
, faceType
, i
, &srcSurface
);
5572 if (WINED3D_OK
!= hr
) {
5573 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5575 TRACE("Got srcSurface %p\n", srcSurface
);
5577 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)pDestinationTexture
, faceType
, i
, &destSurface
);
5578 if (WINED3D_OK
!= hr
) {
5579 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This
, faceType
, i
);
5581 TRACE("Got desrSurface %p\n", destSurface
);
5583 hr
= IWineD3DDevice_UpdateSurface(iface
, srcSurface
, NULL
, destSurface
, NULL
);
5584 IWineD3DSurface_Release(srcSurface
);
5585 IWineD3DSurface_Release(destSurface
);
5586 if (WINED3D_OK
!= hr
) {
5587 WARN("(%p) : Call to update surface failed\n", This
);
5595 case WINED3DRTYPE_VOLUMETEXTURE
:
5597 IWineD3DVolume
*srcVolume
= NULL
;
5598 IWineD3DVolume
*destVolume
= NULL
;
5600 for (i
= 0 ; i
< levels
; ++i
) {
5601 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)pSourceTexture
, i
, &srcVolume
);
5602 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)pDestinationTexture
, i
, &destVolume
);
5603 hr
= IWineD3DDeviceImpl_UpdateVolume(iface
, srcVolume
, destVolume
);
5604 IWineD3DVolume_Release(srcVolume
);
5605 IWineD3DVolume_Release(destVolume
);
5606 if (WINED3D_OK
!= hr
) {
5607 WARN("(%p) : Call to update volume failed\n", This
);
5615 FIXME("(%p) : Unsupported source and destination type\n", This
);
5616 hr
= WINED3DERR_INVALIDCALL
;
5623 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
5624 IWineD3DSwapChain
*swapChain
;
5626 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5627 if(hr
== WINED3D_OK
) {
5628 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
5629 IWineD3DSwapChain_Release(swapChain
);
5634 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
5635 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5636 IWineD3DBaseTextureImpl
*texture
;
5637 const struct GlPixelFormatDesc
*gl_info
;
5640 TRACE("(%p) : %p\n", This
, pNumPasses
);
5642 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
5643 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MINFILTER
] == WINED3DTEXF_NONE
) {
5644 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5645 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5647 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MAGFILTER
] == WINED3DTEXF_NONE
) {
5648 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5649 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5652 texture
= (IWineD3DBaseTextureImpl
*) This
->stateBlock
->textures
[i
];
5653 if(!texture
) continue;
5654 getFormatDescEntry(texture
->resource
.format
, &GLINFO_LOCATION
, &gl_info
);
5655 if(gl_info
->Flags
& WINED3DFMT_FLAG_FILTERING
) continue;
5657 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MAGFILTER
] != WINED3DTEXF_POINT
) {
5658 WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i
);
5661 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MINFILTER
] != WINED3DTEXF_POINT
) {
5662 WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i
);
5665 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_NONE
&&
5666 This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_POINT
/* sic! */) {
5667 WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i
);
5672 /* return a sensible default */
5675 TRACE("returning D3D_OK\n");
5679 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl
*device
)
5683 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
5684 IWineD3DBaseTextureImpl
*texture
= (IWineD3DBaseTextureImpl
*)device
->stateBlock
->textures
[i
];
5685 if (texture
&& (texture
->resource
.format
== WINED3DFMT_P8
|| texture
->resource
.format
== WINED3DFMT_A8P8
)) {
5686 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SAMPLER(i
));
5691 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
5692 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5695 PALETTEENTRY
**palettes
;
5697 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5699 if (PaletteNumber
>= MAX_PALETTES
) {
5700 ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5701 return WINED3DERR_INVALIDCALL
;
5704 if (PaletteNumber
>= This
->NumberOfPalettes
) {
5705 NewSize
= This
->NumberOfPalettes
;
5708 } while(PaletteNumber
>= NewSize
);
5709 palettes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->palettes
, sizeof(PALETTEENTRY
*) * NewSize
);
5711 ERR("Out of memory!\n");
5712 return E_OUTOFMEMORY
;
5714 This
->palettes
= palettes
;
5715 This
->NumberOfPalettes
= NewSize
;
5718 if (!This
->palettes
[PaletteNumber
]) {
5719 This
->palettes
[PaletteNumber
] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
5720 if (!This
->palettes
[PaletteNumber
]) {
5721 ERR("Out of memory!\n");
5722 return E_OUTOFMEMORY
;
5726 for (j
= 0; j
< 256; ++j
) {
5727 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
5728 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
5729 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
5730 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
5732 if (PaletteNumber
== This
->currentPalette
) dirtify_p8_texture_samplers(This
);
5733 TRACE("(%p) : returning\n", This
);
5737 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
5738 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5740 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5741 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5742 /* What happens in such situation isn't documented; Native seems to silently abort
5743 on such conditions. Return Invalid Call. */
5744 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5745 return WINED3DERR_INVALIDCALL
;
5747 for (j
= 0; j
< 256; ++j
) {
5748 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
5749 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
5750 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
5751 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
5753 TRACE("(%p) : returning\n", This
);
5757 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
5758 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5759 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5760 /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5761 (tested with reference rasterizer). Return Invalid Call. */
5762 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5763 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5764 return WINED3DERR_INVALIDCALL
;
5766 /*TODO: stateblocks */
5767 if (This
->currentPalette
!= PaletteNumber
) {
5768 This
->currentPalette
= PaletteNumber
;
5769 dirtify_p8_texture_samplers(This
);
5771 TRACE("(%p) : returning\n", This
);
5775 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
5776 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5777 if (PaletteNumber
== NULL
) {
5778 WARN("(%p) : returning Invalid Call\n", This
);
5779 return WINED3DERR_INVALIDCALL
;
5781 /*TODO: stateblocks */
5782 *PaletteNumber
= This
->currentPalette
;
5783 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
5787 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
5788 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5792 FIXME("(%p) : stub\n", This
);
5796 This
->softwareVertexProcessing
= bSoftware
;
5801 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
5802 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5806 FIXME("(%p) : stub\n", This
);
5809 return This
->softwareVertexProcessing
;
5813 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DRASTER_STATUS
* pRasterStatus
) {
5814 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5815 IWineD3DSwapChain
*swapChain
;
5818 TRACE("(%p) : SwapChain %d returning %p\n", This
, iSwapChain
, pRasterStatus
);
5820 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
5821 if(hr
== WINED3D_OK
){
5822 hr
= IWineD3DSwapChain_GetRasterStatus(swapChain
, pRasterStatus
);
5823 IWineD3DSwapChain_Release(swapChain
);
5825 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This
);
5831 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
) {
5832 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5834 if(nSegments
!= 0.0f
) {
5837 FIXME("(%p) : stub nSegments(%f)\n", This
, nSegments
);
5844 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
) {
5845 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5849 FIXME("(%p) : stub returning(%f)\n", This
, 0.0f
);
5855 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
5856 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5857 /** TODO: remove casts to IWineD3DSurfaceImpl
5858 * NOTE: move code to surface to accomplish this
5859 ****************************************/
5860 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
5861 int srcWidth
, srcHeight
;
5862 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
5863 WINED3DFORMAT destFormat
, srcFormat
;
5865 int srcLeft
, destLeft
, destTop
;
5866 WINED3DPOOL srcPool
, destPool
;
5868 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5869 glDescriptor
*glDescription
= NULL
;
5873 CONVERT_TYPES convert
= NO_CONVERSION
;
5875 WINED3DSURFACE_DESC winedesc
;
5877 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This
, pSourceSurface
, pSourceRect
, pDestinationSurface
, pDestPoint
);
5878 memset(&winedesc
, 0, sizeof(winedesc
));
5879 winedesc
.Width
= &srcSurfaceWidth
;
5880 winedesc
.Height
= &srcSurfaceHeight
;
5881 winedesc
.Pool
= &srcPool
;
5882 winedesc
.Format
= &srcFormat
;
5884 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
5886 winedesc
.Width
= &destSurfaceWidth
;
5887 winedesc
.Height
= &destSurfaceHeight
;
5888 winedesc
.Pool
= &destPool
;
5889 winedesc
.Format
= &destFormat
;
5890 winedesc
.Size
= &destSize
;
5892 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
5894 if(srcPool
!= WINED3DPOOL_SYSTEMMEM
|| destPool
!= WINED3DPOOL_DEFAULT
){
5895 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface
, pDestinationSurface
);
5896 return WINED3DERR_INVALIDCALL
;
5899 /* This call loads the opengl surface directly, instead of copying the surface to the
5900 * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5901 * copy in sysmem and use regular surface loading.
5903 d3dfmt_get_conv((IWineD3DSurfaceImpl
*) pDestinationSurface
, FALSE
, TRUE
,
5904 &dummy
, &dummy
, &dummy
, &convert
, &bpp
, FALSE
);
5905 if(convert
!= NO_CONVERSION
) {
5906 return IWineD3DSurface_BltFast(pDestinationSurface
,
5907 pDestPoint
? pDestPoint
->x
: 0,
5908 pDestPoint
? pDestPoint
->y
: 0,
5909 pSourceSurface
, pSourceRect
, 0);
5912 if (destFormat
== WINED3DFMT_UNKNOWN
) {
5913 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
5914 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
5916 /* Get the update surface description */
5917 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
5920 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
5923 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5924 checkGLcall("glActiveTextureARB");
5927 /* Make sure the surface is loaded and up to date */
5928 surface_internal_preload(pDestinationSurface
, SRGB_RGB
);
5929 IWineD3DSurface_BindTexture(pDestinationSurface
, FALSE
);
5931 IWineD3DSurface_GetGlDesc(pDestinationSurface
, &glDescription
);
5933 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5934 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
5935 srcHeight
= pSourceRect
? pSourceRect
->bottom
- pSourceRect
->top
: srcSurfaceHeight
;
5936 srcLeft
= pSourceRect
? pSourceRect
->left
: 0;
5937 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
5938 destTop
= pDestPoint
? pDestPoint
->y
: 0;
5941 /* This function doesn't support compressed textures
5942 the pitch is just bytesPerPixel * width */
5943 if(srcWidth
!= srcSurfaceWidth
|| srcLeft
){
5944 rowoffset
= srcSurfaceWidth
* pSrcSurface
->bytesPerPixel
;
5945 offset
+= srcLeft
* pSrcSurface
->bytesPerPixel
;
5946 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5948 /* TODO DXT formats */
5950 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
5951 offset
+= pSourceRect
->top
* srcSurfaceWidth
* pSrcSurface
->bytesPerPixel
;
5953 TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
5954 This
, glDescription
->level
, destLeft
, destTop
, srcWidth
, srcHeight
, glDescription
->glFormat
,
5955 glDescription
->glType
, IWineD3DSurface_GetData(pSourceSurface
), offset
);
5958 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
5960 /* need to lock the surface to get the data */
5961 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5966 /* TODO: Cube and volume support */
5968 /* not a whole row so we have to do it a line at a time */
5971 /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5972 const unsigned char* data
=((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
5974 for(j
= destTop
; j
< (srcHeight
+ destTop
) ; j
++){
5976 glTexSubImage2D(glDescription
->target
5977 ,glDescription
->level
5982 ,glDescription
->glFormat
5983 ,glDescription
->glType
5984 ,data
/* could be quicker using */
5989 } else { /* Full width, so just write out the whole texture */
5990 const unsigned char* data
= ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
5992 if (WINED3DFMT_DXT1
== destFormat
||
5993 WINED3DFMT_DXT2
== destFormat
||
5994 WINED3DFMT_DXT3
== destFormat
||
5995 WINED3DFMT_DXT4
== destFormat
||
5996 WINED3DFMT_DXT5
== destFormat
) {
5997 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
5998 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
) {
5999 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
6000 FIXME("Updating part of a compressed texture is not supported at the moment\n");
6001 } if (destFormat
!= srcFormat
) {
6002 FIXME("Updating mixed format compressed texture is not curretly support\n");
6004 GL_EXTCALL(glCompressedTexImage2DARB(glDescription
->target
, glDescription
->level
,
6005 glDescription
->glFormatInternal
, srcWidth
, srcHeight
, 0, destSize
, data
));
6008 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
6013 glTexSubImage2D(glDescription
->target
, glDescription
->level
, destLeft
, destTop
,
6014 srcWidth
, srcHeight
, glDescription
->glFormat
, glDescription
->glType
, data
);
6017 checkGLcall("glTexSubImage2D");
6021 IWineD3DSurface_ModifyLocation(pDestinationSurface
, SFLAG_INTEXTURE
, TRUE
);
6022 sampler
= This
->rev_tex_unit_map
[0];
6023 if (sampler
!= -1) {
6024 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
6030 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
6031 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6032 struct WineD3DRectPatch
*patch
;
6036 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
6038 if(!(Handle
|| pRectPatchInfo
)) {
6039 /* TODO: Write a test for the return value, thus the FIXME */
6040 FIXME("Both Handle and pRectPatchInfo are NULL\n");
6041 return WINED3DERR_INVALIDCALL
;
6045 i
= PATCHMAP_HASHFUNC(Handle
);
6047 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
6048 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
6049 if(patch
->Handle
== Handle
) {
6056 TRACE("Patch does not exist. Creating a new one\n");
6057 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
6058 patch
->Handle
= Handle
;
6059 list_add_head(&This
->patches
[i
], &patch
->entry
);
6061 TRACE("Found existing patch %p\n", patch
);
6064 /* Since opengl does not load tesselated vertex attributes into numbered vertex
6065 * attributes we have to tesselate, read back, and draw. This needs a patch
6066 * management structure instance. Create one.
6068 * A possible improvement is to check if a vertex shader is used, and if not directly
6071 FIXME("Drawing an uncached patch. This is slow\n");
6072 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
6075 if(pNumSegs
[0] != patch
->numSegs
[0] || pNumSegs
[1] != patch
->numSegs
[1] ||
6076 pNumSegs
[2] != patch
->numSegs
[2] || pNumSegs
[3] != patch
->numSegs
[3] ||
6077 (pRectPatchInfo
&& memcmp(pRectPatchInfo
, &patch
->RectPatchInfo
, sizeof(*pRectPatchInfo
)) != 0) ) {
6079 TRACE("Tesselation density or patch info changed, retesselating\n");
6081 if(pRectPatchInfo
) {
6082 patch
->RectPatchInfo
= *pRectPatchInfo
;
6084 patch
->numSegs
[0] = pNumSegs
[0];
6085 patch
->numSegs
[1] = pNumSegs
[1];
6086 patch
->numSegs
[2] = pNumSegs
[2];
6087 patch
->numSegs
[3] = pNumSegs
[3];
6089 hr
= tesselate_rectpatch(This
, patch
);
6091 WARN("Patch tesselation failed\n");
6093 /* Do not release the handle to store the params of the patch */
6095 HeapFree(GetProcessHeap(), 0, patch
);
6101 This
->currentPatch
= patch
;
6102 IWineD3DDevice_DrawPrimitiveStrided(iface
, WINED3DPT_TRIANGLELIST
, patch
->numSegs
[0] * patch
->numSegs
[1] * 2, &patch
->strided
);
6103 This
->currentPatch
= NULL
;
6105 /* Destroy uncached patches */
6107 HeapFree(GetProcessHeap(), 0, patch
->mem
);
6108 HeapFree(GetProcessHeap(), 0, patch
);
6113 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DTRIPATCH_INFO
* pTriPatchInfo
) {
6114 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6115 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This
, Handle
, pNumSegs
, pTriPatchInfo
);
6116 FIXME("(%p) : Stub\n", This
);
6120 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
6121 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6123 struct WineD3DRectPatch
*patch
;
6125 TRACE("(%p) Handle(%d)\n", This
, Handle
);
6127 i
= PATCHMAP_HASHFUNC(Handle
);
6128 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
6129 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
6130 if(patch
->Handle
== Handle
) {
6131 TRACE("Deleting patch %p\n", patch
);
6132 list_remove(&patch
->entry
);
6133 HeapFree(GetProcessHeap(), 0, patch
->mem
);
6134 HeapFree(GetProcessHeap(), 0, patch
);
6139 /* TODO: Write a test for the return value */
6140 FIXME("Attempt to destroy nonexistent patch\n");
6141 return WINED3DERR_INVALIDCALL
;
6144 static IWineD3DSwapChain
*get_swapchain(IWineD3DSurface
*target
) {
6146 IWineD3DSwapChain
*swapchain
;
6148 hr
= IWineD3DSurface_GetContainer(target
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
6149 if (SUCCEEDED(hr
)) {
6150 IWineD3DSwapChain_Release((IUnknown
*)swapchain
);
6157 static void color_fill_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*surface
, CONST WINED3DRECT
*rect
, WINED3DCOLOR color
) {
6158 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6159 IWineD3DSwapChain
*swapchain
;
6161 swapchain
= get_swapchain(surface
);
6165 TRACE("Surface %p is onscreen\n", surface
);
6167 ActivateContext(This
, surface
, CTXUSAGE_RESOURCELOAD
);
6169 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6170 buffer
= surface_get_gl_buffer(surface
, swapchain
);
6171 glDrawBuffer(buffer
);
6172 checkGLcall("glDrawBuffer()");
6174 TRACE("Surface %p is offscreen\n", surface
);
6176 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6178 context_bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->activeContext
->dst_fbo
);
6179 context_attach_surface_fbo(This
, GL_FRAMEBUFFER_EXT
, 0, surface
);
6180 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6181 checkGLcall("glFramebufferRenderbufferEXT");
6185 glEnable(GL_SCISSOR_TEST
);
6187 glScissor(rect
->x1
, rect
->y1
, rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
6189 glScissor(rect
->x1
, ((IWineD3DSurfaceImpl
*)surface
)->currentDesc
.Height
- rect
->y2
,
6190 rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
6192 checkGLcall("glScissor");
6193 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
6195 glDisable(GL_SCISSOR_TEST
);
6197 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
6199 glDisable(GL_BLEND
);
6200 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE
));
6202 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
6203 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE
));
6205 glClearColor(D3DCOLOR_R(color
), D3DCOLOR_G(color
), D3DCOLOR_B(color
), D3DCOLOR_A(color
));
6206 glClear(GL_COLOR_BUFFER_BIT
);
6207 checkGLcall("glClear");
6209 if (This
->activeContext
->current_fbo
) {
6210 context_bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->activeContext
->current_fbo
->id
);
6212 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6213 checkGLcall("glBindFramebuffer()");
6216 if (swapchain
&& surface
== ((IWineD3DSwapChainImpl
*)swapchain
)->frontBuffer
6217 && ((IWineD3DSwapChainImpl
*)swapchain
)->backBuffer
) {
6218 glDrawBuffer(GL_BACK
);
6219 checkGLcall("glDrawBuffer()");
6225 static inline DWORD
argb_to_fmt(DWORD color
, WINED3DFORMAT destfmt
) {
6226 unsigned int r
, g
, b
, a
;
6229 if(destfmt
== WINED3DFMT_A8R8G8B8
|| destfmt
== WINED3DFMT_X8R8G8B8
||
6230 destfmt
== WINED3DFMT_R8G8B8
)
6233 TRACE("Converting color %08x to format %s\n", color
, debug_d3dformat(destfmt
));
6235 a
= (color
& 0xff000000) >> 24;
6236 r
= (color
& 0x00ff0000) >> 16;
6237 g
= (color
& 0x0000ff00) >> 8;
6238 b
= (color
& 0x000000ff) >> 0;
6242 case WINED3DFMT_R5G6B5
:
6243 if(r
== 0xff && g
== 0xff && b
== 0xff) return 0xffff;
6250 TRACE("Returning %08x\n", ret
);
6253 case WINED3DFMT_X1R5G5B5
:
6254 case WINED3DFMT_A1R5G5B5
:
6263 TRACE("Returning %08x\n", ret
);
6267 TRACE("Returning %08x\n", a
);
6270 case WINED3DFMT_X4R4G4B4
:
6271 case WINED3DFMT_A4R4G4B4
:
6280 TRACE("Returning %08x\n", ret
);
6283 case WINED3DFMT_R3G3B2
:
6290 TRACE("Returning %08x\n", ret
);
6293 case WINED3DFMT_X8B8G8R8
:
6294 case WINED3DFMT_A8B8G8R8
:
6299 TRACE("Returning %08x\n", ret
);
6302 case WINED3DFMT_A2R10G10B10
:
6304 r
= (r
* 1024) / 256;
6305 g
= (g
* 1024) / 256;
6306 b
= (b
* 1024) / 256;
6311 TRACE("Returning %08x\n", ret
);
6314 case WINED3DFMT_A2B10G10R10
:
6316 r
= (r
* 1024) / 256;
6317 g
= (g
* 1024) / 256;
6318 b
= (b
* 1024) / 256;
6323 TRACE("Returning %08x\n", ret
);
6327 FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt
));
6332 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
, IWineD3DSurface
*pSurface
, CONST WINED3DRECT
* pRect
, WINED3DCOLOR color
) {
6333 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6334 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*) pSurface
;
6336 TRACE("(%p) Colour fill Surface: %p rect: %p color: 0x%08x\n", This
, pSurface
, pRect
, color
);
6338 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
6339 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
6340 return WINED3DERR_INVALIDCALL
;
6343 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
6344 color_fill_fbo(iface
, pSurface
, pRect
, color
);
6347 /* Just forward this to the DirectDraw blitting engine */
6348 memset(&BltFx
, 0, sizeof(BltFx
));
6349 BltFx
.dwSize
= sizeof(BltFx
);
6350 BltFx
.u5
.dwFillColor
= argb_to_fmt(color
, surface
->resource
.format
);
6351 return IWineD3DSurface_Blt(pSurface
, (const RECT
*)pRect
, NULL
, NULL
,
6352 WINEDDBLT_COLORFILL
, &BltFx
, WINED3DTEXF_NONE
);
6356 /* rendertarget and depth stencil functions */
6357 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
6358 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6360 if (RenderTargetIndex
>= GL_LIMITS(buffers
)) {
6361 ERR("(%p) : Only %d render targets are supported.\n", This
, GL_LIMITS(buffers
));
6362 return WINED3DERR_INVALIDCALL
;
6365 *ppRenderTarget
= This
->render_targets
[RenderTargetIndex
];
6366 TRACE("(%p) : RenderTarget %d Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
6367 /* Note inc ref on returned surface */
6368 if(*ppRenderTarget
!= NULL
)
6369 IWineD3DSurface_AddRef(*ppRenderTarget
);
6373 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice
*iface
, IWineD3DSurface
*Front
, IWineD3DSurface
*Back
) {
6374 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6375 IWineD3DSurfaceImpl
*FrontImpl
= (IWineD3DSurfaceImpl
*) Front
;
6376 IWineD3DSurfaceImpl
*BackImpl
= (IWineD3DSurfaceImpl
*) Back
;
6377 IWineD3DSwapChainImpl
*Swapchain
;
6380 TRACE("(%p)->(%p,%p)\n", This
, FrontImpl
, BackImpl
);
6382 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &Swapchain
);
6383 if(hr
!= WINED3D_OK
) {
6384 ERR("Can't get the swapchain\n");
6388 /* Make sure to release the swapchain */
6389 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) Swapchain
);
6391 if(FrontImpl
&& !(FrontImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) {
6392 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6393 return WINED3DERR_INVALIDCALL
;
6395 else if(BackImpl
&& !(BackImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6396 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
6397 return WINED3DERR_INVALIDCALL
;
6400 if(Swapchain
->frontBuffer
!= Front
) {
6401 TRACE("Changing the front buffer from %p to %p\n", Swapchain
->frontBuffer
, Front
);
6403 if(Swapchain
->frontBuffer
)
6404 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, NULL
);
6405 Swapchain
->frontBuffer
= Front
;
6407 if(Swapchain
->frontBuffer
) {
6408 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, (IWineD3DBase
*) Swapchain
);
6412 if(Back
&& !Swapchain
->backBuffer
) {
6413 /* We need memory for the back buffer array - only one back buffer this way */
6414 Swapchain
->backBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*));
6415 if(!Swapchain
->backBuffer
) {
6416 ERR("Out of memory\n");
6417 return E_OUTOFMEMORY
;
6421 if(Swapchain
->backBuffer
[0] != Back
) {
6422 TRACE("Changing the back buffer from %p to %p\n", Swapchain
->backBuffer
, Back
);
6424 /* What to do about the context here in the case of multithreading? Not sure.
6425 * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
6428 if(!Swapchain
->backBuffer
[0]) {
6429 /* GL was told to draw to the front buffer at creation,
6432 glDrawBuffer(GL_BACK
);
6433 checkGLcall("glDrawBuffer(GL_BACK)");
6434 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
6435 Swapchain
->presentParms
.BackBufferCount
= 1;
6437 /* That makes problems - disable for now */
6438 /* glDrawBuffer(GL_FRONT); */
6439 checkGLcall("glDrawBuffer(GL_FRONT)");
6440 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
6441 Swapchain
->presentParms
.BackBufferCount
= 0;
6445 if(Swapchain
->backBuffer
[0])
6446 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], NULL
);
6447 Swapchain
->backBuffer
[0] = Back
;
6449 if(Swapchain
->backBuffer
[0]) {
6450 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], (IWineD3DBase
*) Swapchain
);
6452 HeapFree(GetProcessHeap(), 0, Swapchain
->backBuffer
);
6453 Swapchain
->backBuffer
= NULL
;
6461 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
6462 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6463 *ppZStencilSurface
= This
->stencilBufferTarget
;
6464 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
6466 if(*ppZStencilSurface
!= NULL
) {
6467 /* Note inc ref on returned surface */
6468 IWineD3DSurface_AddRef(*ppZStencilSurface
);
6471 return WINED3DERR_NOTFOUND
;
6475 void stretch_rect_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*src_surface
, WINED3DRECT
*src_rect
,
6476 IWineD3DSurface
*dst_surface
, WINED3DRECT
*dst_rect
, const WINED3DTEXTUREFILTERTYPE filter
, BOOL flip
)
6478 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6479 GLbitfield mask
= GL_COLOR_BUFFER_BIT
; /* TODO: Support blitting depth/stencil surfaces */
6480 IWineD3DSwapChain
*src_swapchain
, *dst_swapchain
;
6482 POINT offset
= {0, 0};
6484 TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
6485 This
, src_surface
, src_rect
, dst_surface
, dst_rect
, debug_d3dtexturefiltertype(filter
), filter
, flip
);
6486 TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
);
6487 TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
);
6490 case WINED3DTEXF_LINEAR
:
6491 gl_filter
= GL_LINEAR
;
6495 FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter
), filter
);
6496 case WINED3DTEXF_NONE
:
6497 case WINED3DTEXF_POINT
:
6498 gl_filter
= GL_NEAREST
;
6502 /* Attach src surface to src fbo */
6503 src_swapchain
= get_swapchain(src_surface
);
6504 if (src_swapchain
) {
6505 GLenum buffer
= surface_get_gl_buffer(src_surface
, src_swapchain
);
6507 TRACE("Source surface %p is onscreen\n", src_surface
);
6508 ActivateContext(This
, src_surface
, CTXUSAGE_RESOURCELOAD
);
6509 /* Make sure the drawable is up to date. In the offscreen case
6510 * attach_surface_fbo() implicitly takes care of this. */
6511 IWineD3DSurface_LoadLocation(src_surface
, SFLAG_INDRAWABLE
, NULL
);
6513 if(buffer
== GL_FRONT
) {
6516 ClientToScreen(((IWineD3DSwapChainImpl
*)src_swapchain
)->win_handle
, &offset
);
6517 GetClientRect(((IWineD3DSwapChainImpl
*)src_swapchain
)->win_handle
, &windowsize
);
6518 h
= windowsize
.bottom
- windowsize
.top
;
6519 src_rect
->x1
-= offset
.x
; src_rect
->x2
-=offset
.x
;
6520 src_rect
->y1
= offset
.y
+ h
- src_rect
->y1
;
6521 src_rect
->y2
= offset
.y
+ h
- src_rect
->y2
;
6523 src_rect
->y1
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y1
;
6524 src_rect
->y2
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y2
;
6528 GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT
, 0));
6529 glReadBuffer(buffer
);
6530 checkGLcall("glReadBuffer()");
6532 TRACE("Source surface %p is offscreen\n", src_surface
);
6534 context_bind_fbo(iface
, GL_READ_FRAMEBUFFER_EXT
, &This
->activeContext
->src_fbo
);
6535 context_attach_surface_fbo(This
, GL_READ_FRAMEBUFFER_EXT
, 0, src_surface
);
6536 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT
);
6537 checkGLcall("glReadBuffer()");
6538 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6539 checkGLcall("glFramebufferRenderbufferEXT");
6543 /* Attach dst surface to dst fbo */
6544 dst_swapchain
= get_swapchain(dst_surface
);
6545 if (dst_swapchain
) {
6546 GLenum buffer
= surface_get_gl_buffer(dst_surface
, dst_swapchain
);
6548 TRACE("Destination surface %p is onscreen\n", dst_surface
);
6549 ActivateContext(This
, dst_surface
, CTXUSAGE_RESOURCELOAD
);
6550 /* Make sure the drawable is up to date. In the offscreen case
6551 * attach_surface_fbo() implicitly takes care of this. */
6552 IWineD3DSurface_LoadLocation(dst_surface
, SFLAG_INDRAWABLE
, NULL
);
6554 if(buffer
== GL_FRONT
) {
6557 ClientToScreen(((IWineD3DSwapChainImpl
*)dst_swapchain
)->win_handle
, &offset
);
6558 GetClientRect(((IWineD3DSwapChainImpl
*)dst_swapchain
)->win_handle
, &windowsize
);
6559 h
= windowsize
.bottom
- windowsize
.top
;
6560 dst_rect
->x1
-= offset
.x
; dst_rect
->x2
-=offset
.x
;
6561 dst_rect
->y1
= offset
.y
+ h
- dst_rect
->y1
;
6562 dst_rect
->y2
= offset
.y
+ h
- dst_rect
->y2
;
6564 /* Screen coords = window coords, surface height = window height */
6565 dst_rect
->y1
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y1
;
6566 dst_rect
->y2
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y2
;
6570 GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, 0));
6571 glDrawBuffer(buffer
);
6572 checkGLcall("glDrawBuffer()");
6574 TRACE("Destination surface %p is offscreen\n", dst_surface
);
6576 /* No src or dst swapchain? Make sure some context is active(multithreading) */
6577 if(!src_swapchain
) {
6578 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6582 context_bind_fbo(iface
, GL_DRAW_FRAMEBUFFER_EXT
, &This
->activeContext
->dst_fbo
);
6583 context_attach_surface_fbo(This
, GL_DRAW_FRAMEBUFFER_EXT
, 0, dst_surface
);
6584 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT
);
6585 checkGLcall("glDrawBuffer()");
6586 GL_EXTCALL(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
, 0));
6587 checkGLcall("glFramebufferRenderbufferEXT");
6589 glDisable(GL_SCISSOR_TEST
);
6590 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
6593 GL_EXTCALL(glBlitFramebufferEXT(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
6594 dst_rect
->x1
, dst_rect
->y2
, dst_rect
->x2
, dst_rect
->y1
, mask
, gl_filter
));
6595 checkGLcall("glBlitFramebuffer()");
6597 GL_EXTCALL(glBlitFramebufferEXT(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
6598 dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
, mask
, gl_filter
));
6599 checkGLcall("glBlitFramebuffer()");
6602 IWineD3DSurface_ModifyLocation(dst_surface
, SFLAG_INDRAWABLE
, TRUE
);
6604 if (This
->activeContext
->current_fbo
) {
6605 context_bind_fbo(iface
, GL_FRAMEBUFFER_EXT
, &This
->activeContext
->current_fbo
->id
);
6607 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0));
6608 checkGLcall("glBindFramebuffer()");
6611 /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
6612 if (dst_swapchain
&& dst_surface
== ((IWineD3DSwapChainImpl
*)dst_swapchain
)->frontBuffer
6613 && ((IWineD3DSwapChainImpl
*)dst_swapchain
)->backBuffer
) {
6614 glDrawBuffer(GL_BACK
);
6615 checkGLcall("glDrawBuffer()");
6620 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
) {
6621 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6622 WINED3DVIEWPORT viewport
;
6624 TRACE("(%p) : Setting rendertarget %d to %p\n", This
, RenderTargetIndex
, pRenderTarget
);
6626 if (RenderTargetIndex
>= GL_LIMITS(buffers
)) {
6627 WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
6628 This
, RenderTargetIndex
, GL_LIMITS(buffers
));
6629 return WINED3DERR_INVALIDCALL
;
6632 /* MSDN says that null disables the render target
6633 but a device must always be associated with a render target
6634 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
6636 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
6637 FIXME("Trying to set render target 0 to NULL\n");
6638 return WINED3DERR_INVALIDCALL
;
6640 if (pRenderTarget
&& !(((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
6641 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
);
6642 return WINED3DERR_INVALIDCALL
;
6645 /* If we are trying to set what we already have, don't bother */
6646 if (pRenderTarget
== This
->render_targets
[RenderTargetIndex
]) {
6647 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6650 if(pRenderTarget
) IWineD3DSurface_AddRef(pRenderTarget
);
6651 if(This
->render_targets
[RenderTargetIndex
]) IWineD3DSurface_Release(This
->render_targets
[RenderTargetIndex
]);
6652 This
->render_targets
[RenderTargetIndex
] = pRenderTarget
;
6654 /* Render target 0 is special */
6655 if(RenderTargetIndex
== 0) {
6656 /* Finally, reset the viewport as the MSDN states. */
6657 viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Height
;
6658 viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Width
;
6661 viewport
.MaxZ
= 1.0f
;
6662 viewport
.MinZ
= 0.0f
;
6663 IWineD3DDeviceImpl_SetViewport(iface
, &viewport
);
6664 /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
6665 * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
6667 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
6672 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
6673 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6674 HRESULT hr
= WINED3D_OK
;
6675 IWineD3DSurface
*tmp
;
6677 TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This
, This
->stencilBufferTarget
, pNewZStencil
);
6679 if (pNewZStencil
== This
->stencilBufferTarget
) {
6680 TRACE("Trying to do a NOP SetRenderTarget operation\n");
6682 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
6683 * depending on the renter target implementation being used.
6684 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
6685 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
6686 * stencil buffer and incur an extra memory overhead
6687 ******************************************************/
6689 if (This
->stencilBufferTarget
) {
6690 if (((IWineD3DSwapChainImpl
*)This
->swapchains
[0])->presentParms
.Flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
6691 || ((IWineD3DSurfaceImpl
*)This
->stencilBufferTarget
)->Flags
& SFLAG_DISCARD
) {
6692 surface_modify_ds_location(This
->stencilBufferTarget
, SFLAG_DS_DISCARDED
);
6694 ActivateContext(This
, This
->render_targets
[0], CTXUSAGE_RESOURCELOAD
);
6695 surface_load_ds_location(This
->stencilBufferTarget
, SFLAG_DS_OFFSCREEN
);
6696 surface_modify_ds_location(This
->stencilBufferTarget
, SFLAG_DS_OFFSCREEN
);
6700 tmp
= This
->stencilBufferTarget
;
6701 This
->stencilBufferTarget
= pNewZStencil
;
6702 /* should we be calling the parent or the wined3d surface? */
6703 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
6704 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
6707 if((!tmp
&& pNewZStencil
) || (!pNewZStencil
&& tmp
)) {
6708 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
6709 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZENABLE
));
6710 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILENABLE
));
6711 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
6718 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
6719 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
6720 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6721 /* TODO: the use of Impl is deprecated. */
6722 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
6723 WINED3DLOCKED_RECT lockedRect
;
6725 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
6727 /* some basic validation checks */
6728 if(This
->cursorTexture
) {
6729 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6731 glDeleteTextures(1, &This
->cursorTexture
);
6733 This
->cursorTexture
= 0;
6736 if ( (pSur
->currentDesc
.Width
== 32) && (pSur
->currentDesc
.Height
== 32) )
6737 This
->haveHardwareCursor
= TRUE
;
6739 This
->haveHardwareCursor
= FALSE
;
6742 WINED3DLOCKED_RECT rect
;
6744 /* MSDN: Cursor must be A8R8G8B8 */
6745 if (WINED3DFMT_A8R8G8B8
!= pSur
->resource
.format
) {
6746 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
6747 return WINED3DERR_INVALIDCALL
;
6750 /* MSDN: Cursor must be smaller than the display mode */
6751 if(pSur
->currentDesc
.Width
> This
->ddraw_width
||
6752 pSur
->currentDesc
.Height
> This
->ddraw_height
) {
6753 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
);
6754 return WINED3DERR_INVALIDCALL
;
6757 if (!This
->haveHardwareCursor
) {
6758 /* TODO: MSDN: Cursor sizes must be a power of 2 */
6760 /* Do not store the surface's pointer because the application may
6761 * release it after setting the cursor image. Windows doesn't
6762 * addref the set surface, so we can't do this either without
6763 * creating circular refcount dependencies. Copy out the gl texture
6766 This
->cursorWidth
= pSur
->currentDesc
.Width
;
6767 This
->cursorHeight
= pSur
->currentDesc
.Height
;
6768 if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap
, &rect
, NULL
, WINED3DLOCK_READONLY
)))
6770 const struct GlPixelFormatDesc
*glDesc
;
6771 const StaticPixelFormatDesc
*tableEntry
= getFormatDescEntry(WINED3DFMT_A8R8G8B8
, &GLINFO_LOCATION
, &glDesc
);
6772 char *mem
, *bits
= rect
.pBits
;
6773 GLint intfmt
= glDesc
->glInternal
;
6774 GLint format
= glDesc
->glFormat
;
6775 GLint type
= glDesc
->glType
;
6776 INT height
= This
->cursorHeight
;
6777 INT width
= This
->cursorWidth
;
6778 INT bpp
= tableEntry
->bpp
;
6781 /* Reformat the texture memory (pitch and width can be
6783 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
6784 for(i
= 0; i
< height
; i
++)
6785 memcpy(&mem
[width
* bpp
* i
], &bits
[rect
.Pitch
* i
], width
* bpp
);
6786 IWineD3DSurface_UnlockRect(pCursorBitmap
);
6789 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
6790 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
6791 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6794 /* Make sure that a proper texture unit is selected */
6795 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
6796 checkGLcall("glActiveTextureARB");
6797 sampler
= This
->rev_tex_unit_map
[0];
6798 if (sampler
!= -1) {
6799 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
6801 /* Create a new cursor texture */
6802 glGenTextures(1, &This
->cursorTexture
);
6803 checkGLcall("glGenTextures");
6804 glBindTexture(GL_TEXTURE_2D
, This
->cursorTexture
);
6805 checkGLcall("glBindTexture");
6806 /* Copy the bitmap memory into the cursor texture */
6807 glTexImage2D(GL_TEXTURE_2D
, 0, intfmt
, width
, height
, 0, format
, type
, mem
);
6808 HeapFree(GetProcessHeap(), 0, mem
);
6809 checkGLcall("glTexImage2D");
6811 if(GL_SUPPORT(APPLE_CLIENT_STORAGE
)) {
6812 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
6813 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6820 FIXME("A cursor texture was not returned.\n");
6821 This
->cursorTexture
= 0;
6826 /* Draw a hardware cursor */
6827 ICONINFO cursorInfo
;
6829 /* Create and clear maskBits because it is not needed for
6830 * 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
6832 DWORD
*maskBits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6833 (pSur
->currentDesc
.Width
* pSur
->currentDesc
.Height
/ 8));
6834 IWineD3DSurface_LockRect(pCursorBitmap
, &lockedRect
, NULL
,
6835 WINED3DLOCK_NO_DIRTY_UPDATE
|
6836 WINED3DLOCK_READONLY
6838 TRACE("width: %i height: %i\n", pSur
->currentDesc
.Width
,
6839 pSur
->currentDesc
.Height
);
6841 cursorInfo
.fIcon
= FALSE
;
6842 cursorInfo
.xHotspot
= XHotSpot
;
6843 cursorInfo
.yHotspot
= YHotSpot
;
6844 cursorInfo
.hbmMask
= CreateBitmap(pSur
->currentDesc
.Width
,
6845 pSur
->currentDesc
.Height
, 1,
6847 cursorInfo
.hbmColor
= CreateBitmap(pSur
->currentDesc
.Width
,
6848 pSur
->currentDesc
.Height
, 1,
6849 32, lockedRect
.pBits
);
6850 IWineD3DSurface_UnlockRect(pCursorBitmap
);
6851 /* Create our cursor and clean up. */
6852 cursor
= CreateIconIndirect(&cursorInfo
);
6854 if (cursorInfo
.hbmMask
) DeleteObject(cursorInfo
.hbmMask
);
6855 if (cursorInfo
.hbmColor
) DeleteObject(cursorInfo
.hbmColor
);
6856 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
6857 This
->hardwareCursor
= cursor
;
6858 HeapFree(GetProcessHeap(), 0, maskBits
);
6862 This
->xHotSpot
= XHotSpot
;
6863 This
->yHotSpot
= YHotSpot
;
6867 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
6868 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6869 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
6871 This
->xScreenSpace
= XScreenSpace
;
6872 This
->yScreenSpace
= YScreenSpace
;
6878 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
6879 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6880 BOOL oldVisible
= This
->bCursorVisible
;
6883 TRACE("(%p) : visible(%d)\n", This
, bShow
);
6886 * When ShowCursor is first called it should make the cursor appear at the OS's last
6887 * known cursor position. Because of this, some applications just repetitively call
6888 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
6891 This
->xScreenSpace
= pt
.x
;
6892 This
->yScreenSpace
= pt
.y
;
6894 if (This
->haveHardwareCursor
) {
6895 This
->bCursorVisible
= bShow
;
6897 SetCursor(This
->hardwareCursor
);
6903 if (This
->cursorTexture
)
6904 This
->bCursorVisible
= bShow
;
6910 static HRESULT WINAPI
IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice
* iface
) {
6911 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6912 IWineD3DResourceImpl
*resource
;
6913 TRACE("(%p) : state (%u)\n", This
, This
->state
);
6915 /* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
6916 switch (This
->state
) {
6919 case WINED3DERR_DEVICELOST
:
6921 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, IWineD3DResourceImpl
, resource
.resource_list_entry
) {
6922 if (resource
->resource
.pool
== WINED3DPOOL_DEFAULT
)
6923 return WINED3DERR_DEVICENOTRESET
;
6925 return WINED3DERR_DEVICELOST
;
6927 case WINED3DERR_DRIVERINTERNALERROR
:
6928 return WINED3DERR_DRIVERINTERNALERROR
;
6932 return WINED3DERR_DRIVERINTERNALERROR
;
6936 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
* iface
) {
6937 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6938 /** FIXME: Resource tracking needs to be done,
6939 * The closes we can do to this is set the priorities of all managed textures low
6940 * and then reset them.
6941 ***********************************************************/
6942 FIXME("(%p) : stub\n", This
);
6946 static void updateSurfaceDesc(IWineD3DSurfaceImpl
*surface
, const WINED3DPRESENT_PARAMETERS
* pPresentationParameters
)
6948 IWineD3DDeviceImpl
*This
= surface
->resource
.wineD3DDevice
; /* for GL_SUPPORT */
6950 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6951 if(surface
->Flags
& SFLAG_DIBSECTION
) {
6952 /* Release the DC */
6953 SelectObject(surface
->hDC
, surface
->dib
.holdbitmap
);
6954 DeleteDC(surface
->hDC
);
6955 /* Release the DIB section */
6956 DeleteObject(surface
->dib
.DIBsection
);
6957 surface
->dib
.bitmap_data
= NULL
;
6958 surface
->resource
.allocatedMemory
= NULL
;
6959 surface
->Flags
&= ~SFLAG_DIBSECTION
;
6961 surface
->currentDesc
.Width
= pPresentationParameters
->BackBufferWidth
;
6962 surface
->currentDesc
.Height
= pPresentationParameters
->BackBufferHeight
;
6963 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO
) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE
) ||
6964 GL_SUPPORT(WINE_NORMALIZED_TEXRECT
)) {
6965 surface
->pow2Width
= pPresentationParameters
->BackBufferWidth
;
6966 surface
->pow2Height
= pPresentationParameters
->BackBufferHeight
;
6968 surface
->pow2Width
= surface
->pow2Height
= 1;
6969 while (surface
->pow2Width
< pPresentationParameters
->BackBufferWidth
) surface
->pow2Width
<<= 1;
6970 while (surface
->pow2Height
< pPresentationParameters
->BackBufferHeight
) surface
->pow2Height
<<= 1;
6972 surface
->glRect
.left
= 0;
6973 surface
->glRect
.top
= 0;
6974 surface
->glRect
.right
= surface
->pow2Width
;
6975 surface
->glRect
.bottom
= surface
->pow2Height
;
6977 if(surface
->glDescription
.textureName
) {
6978 ActivateContext(This
, This
->lastActiveRenderTarget
, CTXUSAGE_RESOURCELOAD
);
6980 glDeleteTextures(1, &surface
->glDescription
.textureName
);
6982 surface
->glDescription
.textureName
= 0;
6983 surface
->Flags
&= ~SFLAG_CLIENT
;
6985 if(surface
->pow2Width
!= pPresentationParameters
->BackBufferWidth
||
6986 surface
->pow2Height
!= pPresentationParameters
->BackBufferHeight
) {
6987 surface
->Flags
|= SFLAG_NONPOW2
;
6989 surface
->Flags
&= ~SFLAG_NONPOW2
;
6991 HeapFree(GetProcessHeap(), 0, surface
->resource
.heapMemory
);
6992 surface
->resource
.allocatedMemory
= NULL
;
6993 surface
->resource
.heapMemory
= NULL
;
6994 surface
->resource
.size
= IWineD3DSurface_GetPitch((IWineD3DSurface
*) surface
) * surface
->pow2Width
;
6995 /* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
6996 if (surface
->resource
.usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
6997 IWineD3DSurface_ModifyLocation((IWineD3DSurface
*) surface
, SFLAG_INSYSMEM
, TRUE
);
6999 IWineD3DSurface_ModifyLocation((IWineD3DSurface
*) surface
, SFLAG_INDRAWABLE
, TRUE
);
7003 static HRESULT WINAPI
reset_unload_resources(IWineD3DResource
*resource
, void *data
) {
7004 TRACE("Unloading resource %p\n", resource
);
7005 IWineD3DResource_UnLoad(resource
);
7006 IWineD3DResource_Release(resource
);
7010 static BOOL
is_display_mode_supported(IWineD3DDeviceImpl
*This
, const WINED3DPRESENT_PARAMETERS
*pp
)
7013 WINED3DDISPLAYMODE m
;
7016 /* All Windowed modes are supported, as is leaving the current mode */
7017 if(pp
->Windowed
) return TRUE
;
7018 if(!pp
->BackBufferWidth
) return TRUE
;
7019 if(!pp
->BackBufferHeight
) return TRUE
;
7021 count
= IWineD3D_GetAdapterModeCount(This
->wineD3D
, This
->adapter
->num
, WINED3DFMT_UNKNOWN
);
7022 for(i
= 0; i
< count
; i
++) {
7023 memset(&m
, 0, sizeof(m
));
7024 hr
= IWineD3D_EnumAdapterModes(This
->wineD3D
, This
->adapter
->num
, WINED3DFMT_UNKNOWN
, i
, &m
);
7026 ERR("EnumAdapterModes failed\n");
7028 if(m
.Width
== pp
->BackBufferWidth
&& m
.Height
== pp
->BackBufferHeight
) {
7029 /* Mode found, it is supported */
7033 /* Mode not found -> not supported */
7037 void delete_opengl_contexts(IWineD3DDevice
*iface
, IWineD3DSwapChain
*swapchain_iface
) {
7038 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7039 IWineD3DSwapChainImpl
*swapchain
= (IWineD3DSwapChainImpl
*) swapchain_iface
;
7041 IWineD3DBaseShaderImpl
*shader
;
7043 IWineD3DDevice_EnumResources(iface
, reset_unload_resources
, NULL
);
7044 LIST_FOR_EACH_ENTRY(shader
, &This
->shaders
, IWineD3DBaseShaderImpl
, baseShader
.shader_list_entry
) {
7045 This
->shader_backend
->shader_destroy((IWineD3DBaseShader
*) shader
);
7049 if(This
->depth_blt_texture
) {
7050 glDeleteTextures(1, &This
->depth_blt_texture
);
7051 This
->depth_blt_texture
= 0;
7053 if (This
->depth_blt_rb
) {
7054 GL_EXTCALL(glDeleteRenderbuffersEXT(1, &This
->depth_blt_rb
));
7055 This
->depth_blt_rb
= 0;
7056 This
->depth_blt_rb_w
= 0;
7057 This
->depth_blt_rb_h
= 0;
7061 This
->blitter
->free_private(iface
);
7062 This
->frag_pipe
->free_private(iface
);
7063 This
->shader_backend
->shader_free_private(iface
);
7066 for (i
= 0; i
< GL_LIMITS(textures
); i
++) {
7067 /* Textures are recreated below */
7068 glDeleteTextures(1, &This
->dummyTextureName
[i
]);
7069 checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])");
7070 This
->dummyTextureName
[i
] = 0;
7074 while(This
->numContexts
) {
7075 DestroyContext(This
, This
->contexts
[0]);
7077 This
->activeContext
= NULL
;
7078 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
7079 swapchain
->context
= NULL
;
7080 swapchain
->num_contexts
= 0;
7083 HRESULT
create_primary_opengl_context(IWineD3DDevice
*iface
, IWineD3DSwapChain
*swapchain_iface
) {
7084 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7085 IWineD3DSwapChainImpl
*swapchain
= (IWineD3DSwapChainImpl
*) swapchain_iface
;
7087 IWineD3DSurfaceImpl
*target
;
7089 /* Recreate the primary swapchain's context */
7090 swapchain
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain
->context
));
7091 if(swapchain
->backBuffer
) {
7092 target
= (IWineD3DSurfaceImpl
*) swapchain
->backBuffer
[0];
7094 target
= (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
;
7096 swapchain
->context
[0] = CreateContext(This
, target
, swapchain
->win_handle
, FALSE
,
7097 &swapchain
->presentParms
);
7098 swapchain
->num_contexts
= 1;
7099 This
->activeContext
= swapchain
->context
[0];
7101 create_dummy_textures(This
);
7103 hr
= This
->shader_backend
->shader_alloc_private(iface
);
7105 ERR("Failed to recreate shader private data\n");
7108 hr
= This
->frag_pipe
->alloc_private(iface
);
7110 TRACE("Fragment pipeline private data couldn't be allocated\n");
7113 hr
= This
->blitter
->alloc_private(iface
);
7115 TRACE("Blitter private data couldn't be allocated\n");
7122 This
->blitter
->free_private(iface
);
7123 This
->frag_pipe
->free_private(iface
);
7124 This
->shader_backend
->shader_free_private(iface
);
7128 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
7129 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7130 IWineD3DSwapChainImpl
*swapchain
;
7132 BOOL DisplayModeChanged
= FALSE
;
7133 WINED3DDISPLAYMODE mode
;
7134 TRACE("(%p)\n", This
);
7136 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &swapchain
);
7138 ERR("Failed to get the first implicit swapchain\n");
7142 if(!is_display_mode_supported(This
, pPresentationParameters
)) {
7143 WARN("Rejecting Reset() call because the requested display mode is not supported\n");
7144 WARN("Requested mode: %d, %d\n", pPresentationParameters
->BackBufferWidth
,
7145 pPresentationParameters
->BackBufferHeight
);
7146 return WINED3DERR_INVALIDCALL
;
7149 /* Is it necessary to recreate the gl context? Actually every setting can be changed
7150 * on an existing gl context, so there's no real need for recreation.
7152 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
7154 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
7156 TRACE("New params:\n");
7157 TRACE("BackBufferWidth = %d\n", pPresentationParameters
->BackBufferWidth
);
7158 TRACE("BackBufferHeight = %d\n", pPresentationParameters
->BackBufferHeight
);
7159 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters
->BackBufferFormat
));
7160 TRACE("BackBufferCount = %d\n", pPresentationParameters
->BackBufferCount
);
7161 TRACE("MultiSampleType = %d\n", pPresentationParameters
->MultiSampleType
);
7162 TRACE("MultiSampleQuality = %d\n", pPresentationParameters
->MultiSampleQuality
);
7163 TRACE("SwapEffect = %d\n", pPresentationParameters
->SwapEffect
);
7164 TRACE("hDeviceWindow = %p\n", pPresentationParameters
->hDeviceWindow
);
7165 TRACE("Windowed = %s\n", pPresentationParameters
->Windowed
? "true" : "false");
7166 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters
->EnableAutoDepthStencil
? "true" : "false");
7167 TRACE("Flags = %08x\n", pPresentationParameters
->Flags
);
7168 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters
->FullScreen_RefreshRateInHz
);
7169 TRACE("PresentationInterval = %d\n", pPresentationParameters
->PresentationInterval
);
7171 /* No special treatment of these parameters. Just store them */
7172 swapchain
->presentParms
.SwapEffect
= pPresentationParameters
->SwapEffect
;
7173 swapchain
->presentParms
.Flags
= pPresentationParameters
->Flags
;
7174 swapchain
->presentParms
.PresentationInterval
= pPresentationParameters
->PresentationInterval
;
7175 swapchain
->presentParms
.FullScreen_RefreshRateInHz
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
7177 /* What to do about these? */
7178 if(pPresentationParameters
->BackBufferCount
!= 0 &&
7179 pPresentationParameters
->BackBufferCount
!= swapchain
->presentParms
.BackBufferCount
) {
7180 ERR("Cannot change the back buffer count yet\n");
7182 if(pPresentationParameters
->BackBufferFormat
!= WINED3DFMT_UNKNOWN
&&
7183 pPresentationParameters
->BackBufferFormat
!= swapchain
->presentParms
.BackBufferFormat
) {
7184 ERR("Cannot change the back buffer format yet\n");
7186 if(pPresentationParameters
->hDeviceWindow
!= NULL
&&
7187 pPresentationParameters
->hDeviceWindow
!= swapchain
->presentParms
.hDeviceWindow
) {
7188 ERR("Cannot change the device window yet\n");
7190 if (pPresentationParameters
->EnableAutoDepthStencil
&& !This
->auto_depth_stencil_buffer
) {
7191 WARN("Auto depth stencil enabled, but no auto depth stencil present, returning WINED3DERR_INVALIDCALL\n");
7192 return WINED3DERR_INVALIDCALL
;
7195 /* Reset the depth stencil */
7196 if (pPresentationParameters
->EnableAutoDepthStencil
)
7197 IWineD3DDevice_SetDepthStencilSurface(iface
, This
->auto_depth_stencil_buffer
);
7199 IWineD3DDevice_SetDepthStencilSurface(iface
, NULL
);
7201 delete_opengl_contexts(iface
, (IWineD3DSwapChain
*) swapchain
);
7203 if(pPresentationParameters
->Windowed
) {
7204 mode
.Width
= swapchain
->orig_width
;
7205 mode
.Height
= swapchain
->orig_height
;
7206 mode
.RefreshRate
= 0;
7207 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
7209 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
7210 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
7211 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
7212 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
7215 /* Should Width == 800 && Height == 0 set 800x600? */
7216 if(pPresentationParameters
->BackBufferWidth
!= 0 && pPresentationParameters
->BackBufferHeight
!= 0 &&
7217 (pPresentationParameters
->BackBufferWidth
!= swapchain
->presentParms
.BackBufferWidth
||
7218 pPresentationParameters
->BackBufferHeight
!= swapchain
->presentParms
.BackBufferHeight
))
7222 if(!pPresentationParameters
->Windowed
) {
7223 DisplayModeChanged
= TRUE
;
7225 swapchain
->presentParms
.BackBufferWidth
= pPresentationParameters
->BackBufferWidth
;
7226 swapchain
->presentParms
.BackBufferHeight
= pPresentationParameters
->BackBufferHeight
;
7228 updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->frontBuffer
, pPresentationParameters
);
7229 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
7230 updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->backBuffer
[i
], pPresentationParameters
);
7232 if(This
->auto_depth_stencil_buffer
) {
7233 updateSurfaceDesc((IWineD3DSurfaceImpl
*)This
->auto_depth_stencil_buffer
, pPresentationParameters
);
7237 if((pPresentationParameters
->Windowed
&& !swapchain
->presentParms
.Windowed
) ||
7238 (swapchain
->presentParms
.Windowed
&& !pPresentationParameters
->Windowed
) ||
7239 DisplayModeChanged
) {
7241 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
7243 if(swapchain
->win_handle
&& !pPresentationParameters
->Windowed
) {
7244 if(swapchain
->presentParms
.Windowed
) {
7245 /* switch from windowed to fs */
7246 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, swapchain
->win_handle
,
7247 pPresentationParameters
->BackBufferWidth
,
7248 pPresentationParameters
->BackBufferHeight
);
7250 /* Fullscreen -> fullscreen mode change */
7251 MoveWindow(swapchain
->win_handle
, 0, 0,
7252 pPresentationParameters
->BackBufferWidth
, pPresentationParameters
->BackBufferHeight
,
7255 } else if(swapchain
->win_handle
&& !swapchain
->presentParms
.Windowed
) {
7256 /* Fullscreen -> windowed switch */
7257 IWineD3DDeviceImpl_RestoreWindow(iface
, swapchain
->win_handle
);
7259 swapchain
->presentParms
.Windowed
= pPresentationParameters
->Windowed
;
7260 } else if(!pPresentationParameters
->Windowed
) {
7261 DWORD style
= This
->style
, exStyle
= This
->exStyle
;
7262 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
7263 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
7264 * Reset to clear up their mess. Guild Wars also loses the device during that.
7268 IWineD3DDeviceImpl_SetupFullscreenWindow(iface
, swapchain
->win_handle
,
7269 pPresentationParameters
->BackBufferWidth
,
7270 pPresentationParameters
->BackBufferHeight
);
7271 This
->style
= style
;
7272 This
->exStyle
= exStyle
;
7275 TRACE("Resetting stateblock\n");
7276 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
7277 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->stateBlock
);
7279 /* Note: No parent needed for initial internal stateblock */
7280 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, (IWineD3DStateBlock
**)&This
->stateBlock
, NULL
);
7281 if (FAILED(hr
)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
7282 else TRACE("Created stateblock %p\n", This
->stateBlock
);
7283 This
->updateStateBlock
= This
->stateBlock
;
7284 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
7286 hr
= IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*) This
->stateBlock
);
7288 ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
7291 hr
= create_primary_opengl_context(iface
, (IWineD3DSwapChain
*) swapchain
);
7292 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
7294 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
7300 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL bEnableDialogs
) {
7301 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7302 /** FIXME: always true at the moment **/
7303 if(!bEnableDialogs
) {
7304 FIXME("(%p) Dialogs cannot be disabled yet\n", This
);
7310 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
7311 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7312 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
7314 *pParameters
= This
->createParms
;
7318 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST WINED3DGAMMARAMP
* pRamp
) {
7319 IWineD3DSwapChain
*swapchain
;
7321 TRACE("Relaying to swapchain\n");
7323 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
7324 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, pRamp
);
7325 IWineD3DSwapChain_Release(swapchain
);
7330 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
7331 IWineD3DSwapChain
*swapchain
;
7333 TRACE("Relaying to swapchain\n");
7335 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
7336 IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
7337 IWineD3DSwapChain_Release(swapchain
);
7343 /** ********************************************************
7344 * Notification functions
7345 ** ********************************************************/
7346 /** This function must be called in the release of a resource when ref == 0,
7347 * the contents of resource must still be correct,
7348 * any handles to other resource held by the caller must be closed
7349 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
7350 *****************************************************/
7351 static void IWineD3DDeviceImpl_AddResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7352 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7354 TRACE("(%p) : Adding Resource %p\n", This
, resource
);
7355 list_add_head(&This
->resources
, &((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
7358 static void IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7359 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
7361 TRACE("(%p) : Removing resource %p\n", This
, resource
);
7363 list_remove(&((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
7367 static void WINAPI
IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice
*iface
, IWineD3DResource
*resource
){
7368 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7369 WINED3DRESOURCETYPE type
= IWineD3DResource_GetType(resource
);
7372 TRACE("(%p) : resource %p\n", This
, resource
);
7374 context_resource_released(iface
, resource
, type
);
7377 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
7378 case WINED3DRTYPE_SURFACE
: {
7381 /* Cleanup any FBO attachments if d3d is enabled */
7382 if(This
->d3d_initialized
) {
7383 if((IWineD3DSurface
*)resource
== This
->lastActiveRenderTarget
) {
7384 IWineD3DSwapChainImpl
*swapchain
= This
->swapchains
? (IWineD3DSwapChainImpl
*) This
->swapchains
[0] : NULL
;
7386 TRACE("Last active render target destroyed\n");
7387 /* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
7388 * checks, so switch to a valid target as long as the currently set surface is still valid. Use the
7389 * surface of the implicit swpchain. If that is the same as the destroyed surface the device is destroyed
7390 * and the lastActiveRenderTarget member shouldn't matter
7393 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0] != (IWineD3DSurface
*)resource
) {
7394 TRACE("Activating primary back buffer\n");
7395 ActivateContext(This
, swapchain
->backBuffer
[0], CTXUSAGE_RESOURCELOAD
);
7396 } else if(!swapchain
->backBuffer
&& swapchain
->frontBuffer
!= (IWineD3DSurface
*)resource
) {
7397 /* Single buffering environment */
7398 TRACE("Activating primary front buffer\n");
7399 ActivateContext(This
, swapchain
->frontBuffer
, CTXUSAGE_RESOURCELOAD
);
7401 TRACE("Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe\n");
7402 /* Implicit render target destroyed, that means the device is being destroyed
7403 * whatever we set here, it shouldn't matter
7405 This
->lastActiveRenderTarget
= (IWineD3DSurface
*) 0xdeadbabe;
7408 /* May happen during ddraw uninitialization */
7409 TRACE("Render target set, but swapchain does not exist!\n");
7410 This
->lastActiveRenderTarget
= (IWineD3DSurface
*) 0xdeadcafe;
7414 for (i
= 0; i
< GL_LIMITS(buffers
); ++i
) {
7415 if (This
->render_targets
[i
] == (IWineD3DSurface
*)resource
) {
7416 This
->render_targets
[i
] = NULL
;
7419 if (This
->stencilBufferTarget
== (IWineD3DSurface
*)resource
) {
7420 This
->stencilBufferTarget
= NULL
;
7426 case WINED3DRTYPE_TEXTURE
:
7427 case WINED3DRTYPE_CUBETEXTURE
:
7428 case WINED3DRTYPE_VOLUMETEXTURE
:
7429 for (counter
= 0; counter
< MAX_COMBINED_SAMPLERS
; counter
++) {
7430 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7431 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7432 This
->stateBlock
->textures
[counter
] = NULL
;
7434 if (This
->updateStateBlock
!= This
->stateBlock
){
7435 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
7436 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
7437 This
->updateStateBlock
->textures
[counter
] = NULL
;
7442 case WINED3DRTYPE_VOLUME
:
7443 /* TODO: nothing really? */
7445 case WINED3DRTYPE_VERTEXBUFFER
:
7448 TRACE("Cleaning up stream pointers\n");
7450 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
7451 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
7452 FINDOUT: should changes.streamSource[StreamNumber] be set ?
7454 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7455 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
7456 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
7457 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
7458 /* Set changed flag? */
7461 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) */
7462 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
7463 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
7464 This
->stateBlock
->streamSource
[streamNumber
] = 0;
7470 case WINED3DRTYPE_INDEXBUFFER
:
7471 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7472 if (This
->updateStateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7473 This
->updateStateBlock
->pIndexData
= NULL
;
7476 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
7477 if (This
->stateBlock
->pIndexData
== (IWineD3DIndexBuffer
*)resource
) {
7478 This
->stateBlock
->pIndexData
= NULL
;
7484 FIXME("(%p) unknown resource type %p %u\n", This
, resource
, IWineD3DResource_GetType(resource
));
7489 /* Remove the resource from the resourceStore */
7490 IWineD3DDeviceImpl_RemoveResource(iface
, resource
);
7492 TRACE("Resource released\n");
7496 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumResources(IWineD3DDevice
*iface
, D3DCB_ENUMRESOURCES pCallback
, void *pData
) {
7497 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
7498 IWineD3DResourceImpl
*resource
, *cursor
;
7500 TRACE("(%p)->(%p,%p)\n", This
, pCallback
, pData
);
7502 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &This
->resources
, IWineD3DResourceImpl
, resource
.resource_list_entry
) {
7503 TRACE("enumerating resource %p\n", resource
);
7504 IWineD3DResource_AddRef((IWineD3DResource
*) resource
);
7505 ret
= pCallback((IWineD3DResource
*) resource
, pData
);
7506 if(ret
== S_FALSE
) {
7507 TRACE("Canceling enumeration\n");
7514 /**********************************************************
7515 * IWineD3DDevice VTbl follows
7516 **********************************************************/
7518 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
7520 /*** IUnknown methods ***/
7521 IWineD3DDeviceImpl_QueryInterface
,
7522 IWineD3DDeviceImpl_AddRef
,
7523 IWineD3DDeviceImpl_Release
,
7524 /*** IWineD3DDevice methods ***/
7525 IWineD3DDeviceImpl_GetParent
,
7526 /*** Creation methods**/
7527 IWineD3DDeviceImpl_CreateVertexBuffer
,
7528 IWineD3DDeviceImpl_CreateIndexBuffer
,
7529 IWineD3DDeviceImpl_CreateStateBlock
,
7530 IWineD3DDeviceImpl_CreateSurface
,
7531 IWineD3DDeviceImpl_CreateTexture
,
7532 IWineD3DDeviceImpl_CreateVolumeTexture
,
7533 IWineD3DDeviceImpl_CreateVolume
,
7534 IWineD3DDeviceImpl_CreateCubeTexture
,
7535 IWineD3DDeviceImpl_CreateQuery
,
7536 IWineD3DDeviceImpl_CreateSwapChain
,
7537 IWineD3DDeviceImpl_CreateVertexDeclaration
,
7538 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
7539 IWineD3DDeviceImpl_CreateVertexShader
,
7540 IWineD3DDeviceImpl_CreatePixelShader
,
7541 IWineD3DDeviceImpl_CreatePalette
,
7542 /*** Odd functions **/
7543 IWineD3DDeviceImpl_Init3D
,
7544 IWineD3DDeviceImpl_InitGDI
,
7545 IWineD3DDeviceImpl_Uninit3D
,
7546 IWineD3DDeviceImpl_UninitGDI
,
7547 IWineD3DDeviceImpl_SetMultithreaded
,
7548 IWineD3DDeviceImpl_EvictManagedResources
,
7549 IWineD3DDeviceImpl_GetAvailableTextureMem
,
7550 IWineD3DDeviceImpl_GetBackBuffer
,
7551 IWineD3DDeviceImpl_GetCreationParameters
,
7552 IWineD3DDeviceImpl_GetDeviceCaps
,
7553 IWineD3DDeviceImpl_GetDirect3D
,
7554 IWineD3DDeviceImpl_GetDisplayMode
,
7555 IWineD3DDeviceImpl_SetDisplayMode
,
7556 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
7557 IWineD3DDeviceImpl_GetRasterStatus
,
7558 IWineD3DDeviceImpl_GetSwapChain
,
7559 IWineD3DDeviceImpl_Reset
,
7560 IWineD3DDeviceImpl_SetDialogBoxMode
,
7561 IWineD3DDeviceImpl_SetCursorProperties
,
7562 IWineD3DDeviceImpl_SetCursorPosition
,
7563 IWineD3DDeviceImpl_ShowCursor
,
7564 IWineD3DDeviceImpl_TestCooperativeLevel
,
7565 /*** Getters and setters **/
7566 IWineD3DDeviceImpl_SetClipPlane
,
7567 IWineD3DDeviceImpl_GetClipPlane
,
7568 IWineD3DDeviceImpl_SetClipStatus
,
7569 IWineD3DDeviceImpl_GetClipStatus
,
7570 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
7571 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
7572 IWineD3DDeviceImpl_SetDepthStencilSurface
,
7573 IWineD3DDeviceImpl_GetDepthStencilSurface
,
7574 IWineD3DDeviceImpl_SetGammaRamp
,
7575 IWineD3DDeviceImpl_GetGammaRamp
,
7576 IWineD3DDeviceImpl_SetIndices
,
7577 IWineD3DDeviceImpl_GetIndices
,
7578 IWineD3DDeviceImpl_SetBaseVertexIndex
,
7579 IWineD3DDeviceImpl_GetBaseVertexIndex
,
7580 IWineD3DDeviceImpl_SetLight
,
7581 IWineD3DDeviceImpl_GetLight
,
7582 IWineD3DDeviceImpl_SetLightEnable
,
7583 IWineD3DDeviceImpl_GetLightEnable
,
7584 IWineD3DDeviceImpl_SetMaterial
,
7585 IWineD3DDeviceImpl_GetMaterial
,
7586 IWineD3DDeviceImpl_SetNPatchMode
,
7587 IWineD3DDeviceImpl_GetNPatchMode
,
7588 IWineD3DDeviceImpl_SetPaletteEntries
,
7589 IWineD3DDeviceImpl_GetPaletteEntries
,
7590 IWineD3DDeviceImpl_SetPixelShader
,
7591 IWineD3DDeviceImpl_GetPixelShader
,
7592 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
7593 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
7594 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
7595 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
7596 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
7597 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
7598 IWineD3DDeviceImpl_SetRenderState
,
7599 IWineD3DDeviceImpl_GetRenderState
,
7600 IWineD3DDeviceImpl_SetRenderTarget
,
7601 IWineD3DDeviceImpl_GetRenderTarget
,
7602 IWineD3DDeviceImpl_SetFrontBackBuffers
,
7603 IWineD3DDeviceImpl_SetSamplerState
,
7604 IWineD3DDeviceImpl_GetSamplerState
,
7605 IWineD3DDeviceImpl_SetScissorRect
,
7606 IWineD3DDeviceImpl_GetScissorRect
,
7607 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
7608 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
7609 IWineD3DDeviceImpl_SetStreamSource
,
7610 IWineD3DDeviceImpl_GetStreamSource
,
7611 IWineD3DDeviceImpl_SetStreamSourceFreq
,
7612 IWineD3DDeviceImpl_GetStreamSourceFreq
,
7613 IWineD3DDeviceImpl_SetTexture
,
7614 IWineD3DDeviceImpl_GetTexture
,
7615 IWineD3DDeviceImpl_SetTextureStageState
,
7616 IWineD3DDeviceImpl_GetTextureStageState
,
7617 IWineD3DDeviceImpl_SetTransform
,
7618 IWineD3DDeviceImpl_GetTransform
,
7619 IWineD3DDeviceImpl_SetVertexDeclaration
,
7620 IWineD3DDeviceImpl_GetVertexDeclaration
,
7621 IWineD3DDeviceImpl_SetVertexShader
,
7622 IWineD3DDeviceImpl_GetVertexShader
,
7623 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
7624 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
7625 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
7626 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
7627 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
7628 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
7629 IWineD3DDeviceImpl_SetViewport
,
7630 IWineD3DDeviceImpl_GetViewport
,
7631 IWineD3DDeviceImpl_MultiplyTransform
,
7632 IWineD3DDeviceImpl_ValidateDevice
,
7633 IWineD3DDeviceImpl_ProcessVertices
,
7634 /*** State block ***/
7635 IWineD3DDeviceImpl_BeginStateBlock
,
7636 IWineD3DDeviceImpl_EndStateBlock
,
7637 /*** Scene management ***/
7638 IWineD3DDeviceImpl_BeginScene
,
7639 IWineD3DDeviceImpl_EndScene
,
7640 IWineD3DDeviceImpl_Present
,
7641 IWineD3DDeviceImpl_Clear
,
7643 IWineD3DDeviceImpl_DrawPrimitive
,
7644 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
7645 IWineD3DDeviceImpl_DrawPrimitiveUP
,
7646 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
7647 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
7648 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
7649 IWineD3DDeviceImpl_DrawRectPatch
,
7650 IWineD3DDeviceImpl_DrawTriPatch
,
7651 IWineD3DDeviceImpl_DeletePatch
,
7652 IWineD3DDeviceImpl_ColorFill
,
7653 IWineD3DDeviceImpl_UpdateTexture
,
7654 IWineD3DDeviceImpl_UpdateSurface
,
7655 IWineD3DDeviceImpl_GetFrontBufferData
,
7656 /*** object tracking ***/
7657 IWineD3DDeviceImpl_ResourceReleased
,
7658 IWineD3DDeviceImpl_EnumResources
7661 const DWORD SavedPixelStates_R
[NUM_SAVEDPIXELSTATES_R
] = {
7662 WINED3DRS_ALPHABLENDENABLE
,
7663 WINED3DRS_ALPHAFUNC
,
7664 WINED3DRS_ALPHAREF
,
7665 WINED3DRS_ALPHATESTENABLE
,
7667 WINED3DRS_COLORWRITEENABLE
,
7668 WINED3DRS_DESTBLEND
,
7669 WINED3DRS_DITHERENABLE
,
7670 WINED3DRS_FILLMODE
,
7671 WINED3DRS_FOGDENSITY
,
7673 WINED3DRS_FOGSTART
,
7674 WINED3DRS_LASTPIXEL
,
7675 WINED3DRS_SHADEMODE
,
7676 WINED3DRS_SRCBLEND
,
7677 WINED3DRS_STENCILENABLE
,
7678 WINED3DRS_STENCILFAIL
,
7679 WINED3DRS_STENCILFUNC
,
7680 WINED3DRS_STENCILMASK
,
7681 WINED3DRS_STENCILPASS
,
7682 WINED3DRS_STENCILREF
,
7683 WINED3DRS_STENCILWRITEMASK
,
7684 WINED3DRS_STENCILZFAIL
,
7685 WINED3DRS_TEXTUREFACTOR
,
7696 WINED3DRS_ZWRITEENABLE
7699 const DWORD SavedPixelStates_T
[NUM_SAVEDPIXELSTATES_T
] = {
7700 WINED3DTSS_ALPHAARG0
,
7701 WINED3DTSS_ALPHAARG1
,
7702 WINED3DTSS_ALPHAARG2
,
7703 WINED3DTSS_ALPHAOP
,
7704 WINED3DTSS_BUMPENVLOFFSET
,
7705 WINED3DTSS_BUMPENVLSCALE
,
7706 WINED3DTSS_BUMPENVMAT00
,
7707 WINED3DTSS_BUMPENVMAT01
,
7708 WINED3DTSS_BUMPENVMAT10
,
7709 WINED3DTSS_BUMPENVMAT11
,
7710 WINED3DTSS_COLORARG0
,
7711 WINED3DTSS_COLORARG1
,
7712 WINED3DTSS_COLORARG2
,
7713 WINED3DTSS_COLOROP
,
7714 WINED3DTSS_RESULTARG
,
7715 WINED3DTSS_TEXCOORDINDEX
,
7716 WINED3DTSS_TEXTURETRANSFORMFLAGS
7719 const DWORD SavedPixelStates_S
[NUM_SAVEDPIXELSTATES_S
] = {
7720 WINED3DSAMP_ADDRESSU
,
7721 WINED3DSAMP_ADDRESSV
,
7722 WINED3DSAMP_ADDRESSW
,
7723 WINED3DSAMP_BORDERCOLOR
,
7724 WINED3DSAMP_MAGFILTER
,
7725 WINED3DSAMP_MINFILTER
,
7726 WINED3DSAMP_MIPFILTER
,
7727 WINED3DSAMP_MIPMAPLODBIAS
,
7728 WINED3DSAMP_MAXMIPLEVEL
,
7729 WINED3DSAMP_MAXANISOTROPY
,
7730 WINED3DSAMP_SRGBTEXTURE
,
7731 WINED3DSAMP_ELEMENTINDEX
7734 const DWORD SavedVertexStates_R
[NUM_SAVEDVERTEXSTATES_R
] = {
7736 WINED3DRS_AMBIENTMATERIALSOURCE
,
7737 WINED3DRS_CLIPPING
,
7738 WINED3DRS_CLIPPLANEENABLE
,
7739 WINED3DRS_COLORVERTEX
,
7740 WINED3DRS_DIFFUSEMATERIALSOURCE
,
7741 WINED3DRS_EMISSIVEMATERIALSOURCE
,
7742 WINED3DRS_FOGDENSITY
,
7744 WINED3DRS_FOGSTART
,
7745 WINED3DRS_FOGTABLEMODE
,
7746 WINED3DRS_FOGVERTEXMODE
,
7747 WINED3DRS_INDEXEDVERTEXBLENDENABLE
,
7748 WINED3DRS_LIGHTING
,
7749 WINED3DRS_LOCALVIEWER
,
7750 WINED3DRS_MULTISAMPLEANTIALIAS
,
7751 WINED3DRS_MULTISAMPLEMASK
,
7752 WINED3DRS_NORMALIZENORMALS
,
7753 WINED3DRS_PATCHEDGESTYLE
,
7754 WINED3DRS_POINTSCALE_A
,
7755 WINED3DRS_POINTSCALE_B
,
7756 WINED3DRS_POINTSCALE_C
,
7757 WINED3DRS_POINTSCALEENABLE
,
7758 WINED3DRS_POINTSIZE
,
7759 WINED3DRS_POINTSIZE_MAX
,
7760 WINED3DRS_POINTSIZE_MIN
,
7761 WINED3DRS_POINTSPRITEENABLE
,
7762 WINED3DRS_RANGEFOGENABLE
,
7763 WINED3DRS_SPECULARMATERIALSOURCE
,
7764 WINED3DRS_TWEENFACTOR
,
7765 WINED3DRS_VERTEXBLEND
,
7766 WINED3DRS_CULLMODE
,
7770 const DWORD SavedVertexStates_T
[NUM_SAVEDVERTEXSTATES_T
] = {
7771 WINED3DTSS_TEXCOORDINDEX
,
7772 WINED3DTSS_TEXTURETRANSFORMFLAGS
7775 const DWORD SavedVertexStates_S
[NUM_SAVEDVERTEXSTATES_S
] = {
7776 WINED3DSAMP_DMAPOFFSET
7779 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl
*This
, DWORD state
) {
7780 DWORD rep
= This
->StateTable
[state
].representative
;
7784 WineD3DContext
*context
;
7787 for(i
= 0; i
< This
->numContexts
; i
++) {
7788 context
= This
->contexts
[i
];
7789 if(isStateDirty(context
, rep
)) continue;
7791 context
->dirtyArray
[context
->numDirtyEntries
++] = rep
;
7794 context
->isStateDirty
[idx
] |= (1 << shift
);
7798 void get_drawable_size_pbuffer(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
7799 IWineD3DDeviceImpl
*dev
= This
->resource
.wineD3DDevice
;
7800 /* The drawable size of a pbuffer render target is the current pbuffer size
7802 *width
= dev
->pbufferWidth
;
7803 *height
= dev
->pbufferHeight
;
7806 void get_drawable_size_fbo(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
7807 /* The drawable size of a fbo target is the opengl texture size, which is the power of two size
7809 *width
= This
->pow2Width
;
7810 *height
= This
->pow2Height
;
7813 void get_drawable_size_backbuffer(IWineD3DSurfaceImpl
*This
, UINT
*width
, UINT
*height
) {
7814 IWineD3DDeviceImpl
*dev
= This
->resource
.wineD3DDevice
;
7815 /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7816 * current context's drawable, which is the size of the back buffer of the swapchain
7817 * the active context belongs to. The back buffer of the swapchain is stored as the
7818 * surface the context belongs to.
7820 *width
= ((IWineD3DSurfaceImpl
*) dev
->activeContext
->surface
)->currentDesc
.Width
;
7821 *height
= ((IWineD3DSurfaceImpl
*) dev
->activeContext
->surface
)->currentDesc
.Height
;