wined3d: Use stateblock_init_contained_states() for WINED3DSBT_ALL stateblocks.
[wine/multimedia.git] / dlls / wined3d / stateblock.c
blob0df179ae1ed4e3e726c89ef6d2fb79cce1f1fd29
1 /*
2 * state block implementation
4 * Copyright 2002 Raphael Junqueira
5 * Copyright 2004 Jason Edmeades
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2007 Stefan Dösinger for CodeWeavers
8 * Copyright 2009 Henri Verbeet for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
31 /***************************************
32 * Stateblock helper functions follow
33 **************************************/
35 /* Allocates the correct amount of space for pixel and vertex shader constants,
36 * along with their set/changed flags on the given stateblock object
38 static HRESULT stateblock_allocate_shader_constants(IWineD3DStateBlockImpl *object)
40 IWineD3DStateBlockImpl *This = object;
42 /* Allocate space for floating point constants */
43 object->pixelShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
44 if (!object->pixelShaderConstantF) goto fail;
46 object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF));
47 if (!object->changed.pixelShaderConstantsF) goto fail;
49 object->vertexShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
50 if (!object->vertexShaderConstantF) goto fail;
52 object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
53 if (!object->changed.vertexShaderConstantsF) goto fail;
55 object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(vshader_constantsF));
56 if (!object->contained_vs_consts_f) goto fail;
58 object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(pshader_constantsF));
59 if (!object->contained_ps_consts_f) goto fail;
61 return WINED3D_OK;
63 fail:
64 ERR("Failed to allocate memory\n");
65 HeapFree(GetProcessHeap(), 0, object->pixelShaderConstantF);
66 HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
67 HeapFree(GetProcessHeap(), 0, object->vertexShaderConstantF);
68 HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
69 HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
70 HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
71 return E_OUTOFMEMORY;
74 static inline void stateblock_set_bits(DWORD *map, UINT map_size)
76 DWORD mask = (1 << (map_size & 0x1f)) - 1;
77 memset(map, 0xff, (map_size >> 5) * sizeof(*map));
78 if (mask) map[map_size >> 5] = mask;
81 /* Set all members of a stateblock savedstate to the given value */
82 static void stateblock_savedstates_set(SAVEDSTATES *states, const struct wined3d_gl_info *gl_info)
84 unsigned int i;
86 /* Single values */
87 states->primitive_type = 1;
88 states->indices = 1;
89 states->material = 1;
90 states->viewport = 1;
91 states->vertexDecl = 1;
92 states->pixelShader = 1;
93 states->vertexShader = 1;
94 states->scissorRect = 1;
96 /* Fixed size arrays */
97 states->streamSource = 0xffff;
98 states->streamFreq = 0xffff;
99 states->textures = 0xfffff;
100 stateblock_set_bits(states->transform, HIGHEST_TRANSFORMSTATE + 1);
101 stateblock_set_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
102 for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
103 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3fff;
104 states->clipplane = 0xffffffff;
105 states->pixelShaderConstantsB = 0xffff;
106 states->pixelShaderConstantsI = 0xffff;
107 states->vertexShaderConstantsB = 0xffff;
108 states->vertexShaderConstantsI = 0xffff;
110 /* Dynamically sized arrays */
111 memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * gl_info->max_pshader_constantsF);
112 memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * gl_info->max_vshader_constantsF);
115 static void stateblock_copy_values(IWineD3DStateBlockImpl *dst, const IWineD3DStateBlockImpl *src,
116 const struct wined3d_gl_info *gl_info)
118 unsigned int l;
120 /* Single items */
121 dst->gl_primitive_type = src->gl_primitive_type;
122 dst->vertexDecl = src->vertexDecl;
123 dst->vertexShader = src->vertexShader;
124 dst->streamIsUP = src->streamIsUP;
125 dst->pIndexData = src->pIndexData;
126 dst->IndexFmt = src->IndexFmt;
127 dst->baseVertexIndex = src->baseVertexIndex;
128 dst->clip_status = src->clip_status;
129 dst->viewport = src->viewport;
130 dst->material = src->material;
131 dst->pixelShader = src->pixelShader;
132 dst->scissorRect = src->scissorRect;
134 /* Lights */
135 memset(dst->activeLights, 0, sizeof(dst->activeLights));
136 for (l = 0; l < LIGHTMAP_SIZE; ++l)
138 struct list *e1, *e2;
139 LIST_FOR_EACH_SAFE(e1, e2, &dst->lightMap[l])
141 PLIGHTINFOEL *light = LIST_ENTRY(e1, PLIGHTINFOEL, entry);
142 list_remove(&light->entry);
143 HeapFree(GetProcessHeap(), 0, light);
146 LIST_FOR_EACH(e1, &src->lightMap[l])
148 PLIGHTINFOEL *light = LIST_ENTRY(e1, PLIGHTINFOEL, entry), *light2;
149 light2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*light));
150 *light2 = *light;
151 list_add_tail(&dst->lightMap[l], &light2->entry);
152 if (light2->glIndex != -1) dst->activeLights[light2->glIndex] = light2;
156 /* Fixed size arrays */
157 memcpy(dst->vertexShaderConstantB, src->vertexShaderConstantB, sizeof(dst->vertexShaderConstantB));
158 memcpy(dst->vertexShaderConstantI, src->vertexShaderConstantI, sizeof(dst->vertexShaderConstantI));
159 memcpy(dst->pixelShaderConstantB, src->pixelShaderConstantB, sizeof(dst->pixelShaderConstantB));
160 memcpy(dst->pixelShaderConstantI, src->pixelShaderConstantI, sizeof(dst->pixelShaderConstantI));
162 memcpy(dst->streamStride, src->streamStride, sizeof(dst->streamStride));
163 memcpy(dst->streamOffset, src->streamOffset, sizeof(dst->streamOffset));
164 memcpy(dst->streamSource, src->streamSource, sizeof(dst->streamSource));
165 memcpy(dst->streamFreq, src->streamFreq, sizeof(dst->streamFreq));
166 memcpy(dst->streamFlags, src->streamFlags, sizeof(dst->streamFlags));
167 memcpy(dst->transforms, src->transforms, sizeof(dst->transforms));
168 memcpy(dst->clipplane, src->clipplane, sizeof(dst->clipplane));
169 memcpy(dst->renderState, src->renderState, sizeof(dst->renderState));
170 memcpy(dst->textures, src->textures, sizeof(dst->textures));
171 memcpy(dst->textureState, src->textureState, sizeof(dst->textureState));
172 memcpy(dst->samplerState, src->samplerState, sizeof(dst->samplerState));
174 /* Dynamically sized arrays */
175 memcpy(dst->vertexShaderConstantF, src->vertexShaderConstantF, sizeof(float) * gl_info->max_vshader_constantsF * 4);
176 memcpy(dst->pixelShaderConstantF, src->pixelShaderConstantF, sizeof(float) * gl_info->max_pshader_constantsF * 4);
179 void stateblock_init_contained_states(IWineD3DStateBlockImpl *stateblock)
181 const struct wined3d_gl_info *gl_info = &stateblock->wineD3DDevice->adapter->gl_info;
182 unsigned int i, j;
184 for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
186 DWORD map = stateblock->changed.renderState[i];
187 for (j = 0; map; map >>= 1, ++j)
189 if (!(map & 1)) continue;
191 stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
192 ++stateblock->num_contained_render_states;
196 for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
198 DWORD map = stateblock->changed.transform[i];
199 for (j = 0; map; map >>= 1, ++j)
201 if (!(map & 1)) continue;
203 stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
204 ++stateblock->num_contained_transform_states;
208 for (i = 0; i < gl_info->max_vshader_constantsF; ++i)
210 if (stateblock->changed.vertexShaderConstantsF[i])
212 stateblock->contained_vs_consts_f[stateblock->num_contained_vs_consts_f] = i;
213 ++stateblock->num_contained_vs_consts_f;
217 for (i = 0; i < MAX_CONST_I; ++i)
219 if (stateblock->changed.vertexShaderConstantsI & (1 << i))
221 stateblock->contained_vs_consts_i[stateblock->num_contained_vs_consts_i] = i;
222 ++stateblock->num_contained_vs_consts_i;
226 for (i = 0; i < MAX_CONST_B; ++i)
228 if (stateblock->changed.vertexShaderConstantsB & (1 << i))
230 stateblock->contained_vs_consts_b[stateblock->num_contained_vs_consts_b] = i;
231 ++stateblock->num_contained_vs_consts_b;
235 for (i = 0; i < gl_info->max_pshader_constantsF; ++i)
237 if (stateblock->changed.pixelShaderConstantsF[i])
239 stateblock->contained_ps_consts_f[stateblock->num_contained_ps_consts_f] = i;
240 ++stateblock->num_contained_ps_consts_f;
244 for (i = 0; i < MAX_CONST_I; ++i)
246 if (stateblock->changed.pixelShaderConstantsI & (1 << i))
248 stateblock->contained_ps_consts_i[stateblock->num_contained_ps_consts_i] = i;
249 ++stateblock->num_contained_ps_consts_i;
253 for (i = 0; i < MAX_CONST_B; ++i)
255 if (stateblock->changed.pixelShaderConstantsB & (1 << i))
257 stateblock->contained_ps_consts_b[stateblock->num_contained_ps_consts_b] = i;
258 ++stateblock->num_contained_ps_consts_b;
262 for (i = 0; i < MAX_TEXTURES; ++i)
264 DWORD map = stateblock->changed.textureState[i];
266 for(j = 0; map; map >>= 1, ++j)
268 if (!(map & 1)) continue;
270 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
271 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
272 ++stateblock->num_contained_tss_states;
276 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
278 DWORD map = stateblock->changed.samplerState[i];
280 for (j = 0; map; map >>= 1, ++j)
282 if (!(map & 1)) continue;
284 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
285 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
286 ++stateblock->num_contained_sampler_states;
291 /**********************************************************
292 * IWineD3DStateBlockImpl IUnknown parts follows
293 **********************************************************/
294 static HRESULT WINAPI IWineD3DStateBlockImpl_QueryInterface(IWineD3DStateBlock *iface,REFIID riid,LPVOID *ppobj)
296 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
297 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
298 if (IsEqualGUID(riid, &IID_IUnknown)
299 || IsEqualGUID(riid, &IID_IWineD3DBase)
300 || IsEqualGUID(riid, &IID_IWineD3DStateBlock)){
301 IUnknown_AddRef(iface);
302 *ppobj = This;
303 return S_OK;
305 *ppobj = NULL;
306 return E_NOINTERFACE;
309 static ULONG WINAPI IWineD3DStateBlockImpl_AddRef(IWineD3DStateBlock *iface) {
310 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
311 ULONG refCount = InterlockedIncrement(&This->ref);
313 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
314 return refCount;
317 static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
318 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
319 ULONG refCount = InterlockedDecrement(&This->ref);
321 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
323 if (!refCount) {
324 int counter;
326 if (This->vertexDecl) IWineD3DVertexDeclaration_Release(This->vertexDecl);
328 for (counter = 0; counter < MAX_COMBINED_SAMPLERS; counter++)
330 if (This->textures[counter]) IWineD3DBaseTexture_Release(This->textures[counter]);
333 for (counter = 0; counter < MAX_STREAMS; counter++) {
334 if(This->streamSource[counter]) {
335 if (IWineD3DBuffer_Release(This->streamSource[counter]))
337 TRACE("Vertex buffer still referenced by stateblock, applications has leaked Stream %u, buffer %p\n", counter, This->streamSource[counter]);
341 if(This->pIndexData) IWineD3DBuffer_Release(This->pIndexData);
342 if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
343 if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
345 for(counter = 0; counter < LIGHTMAP_SIZE; counter++) {
346 struct list *e1, *e2;
347 LIST_FOR_EACH_SAFE(e1, e2, &This->lightMap[counter]) {
348 PLIGHTINFOEL *light = LIST_ENTRY(e1, PLIGHTINFOEL, entry);
349 list_remove(&light->entry);
350 HeapFree(GetProcessHeap(), 0, light);
354 HeapFree(GetProcessHeap(), 0, This->vertexShaderConstantF);
355 HeapFree(GetProcessHeap(), 0, This->changed.vertexShaderConstantsF);
356 HeapFree(GetProcessHeap(), 0, This->pixelShaderConstantF);
357 HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
358 HeapFree(GetProcessHeap(), 0, This->contained_vs_consts_f);
359 HeapFree(GetProcessHeap(), 0, This->contained_ps_consts_f);
360 HeapFree(GetProcessHeap(), 0, This);
362 return refCount;
365 /**********************************************************
366 * IWineD3DStateBlockImpl parts follows
367 **********************************************************/
368 static HRESULT WINAPI IWineD3DStateBlockImpl_GetParent(IWineD3DStateBlock *iface, IUnknown **pParent) {
369 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
370 IUnknown_AddRef(This->parent);
371 *pParent = This->parent;
372 return WINED3D_OK;
375 static HRESULT WINAPI IWineD3DStateBlockImpl_GetDevice(IWineD3DStateBlock *iface, IWineD3DDevice** ppDevice){
377 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
379 *ppDevice = (IWineD3DDevice*)This->wineD3DDevice;
380 IWineD3DDevice_AddRef(*ppDevice);
381 return WINED3D_OK;
385 static void record_lights(IWineD3DStateBlockImpl *This, const IWineD3DStateBlockImpl *targetStateBlock)
387 UINT i;
389 /* Lights... For a recorded state block, we just had a chain of actions to perform,
390 * so we need to walk that chain and update any actions which differ
392 for(i = 0; i < LIGHTMAP_SIZE; i++) {
393 struct list *e, *f;
394 LIST_FOR_EACH(e, &This->lightMap[i]) {
395 BOOL updated = FALSE;
396 PLIGHTINFOEL *src = LIST_ENTRY(e, PLIGHTINFOEL, entry), *realLight;
397 if (!src->changed && !src->enabledChanged) continue;
399 /* Look up the light in the destination */
400 LIST_FOR_EACH(f, &targetStateBlock->lightMap[i]) {
401 realLight = LIST_ENTRY(f, PLIGHTINFOEL, entry);
402 if(realLight->OriginalIndex == src->OriginalIndex) {
403 if(src->changed) {
404 src->OriginalParms = realLight->OriginalParms;
406 if(src->enabledChanged) {
407 /* Need to double check because enabledChanged does not catch enabled -> disabled -> enabled
408 * or disabled -> enabled -> disabled changes
410 if(realLight->glIndex == -1 && src->glIndex != -1) {
411 /* Light disabled */
412 This->activeLights[src->glIndex] = NULL;
413 } else if(realLight->glIndex != -1 && src->glIndex == -1){
414 /* Light enabled */
415 This->activeLights[realLight->glIndex] = src;
417 src->glIndex = realLight->glIndex;
419 updated = TRUE;
420 break;
424 if(updated) {
425 /* Found a light, all done, proceed with next hash entry */
426 continue;
427 } else if(src->changed) {
428 /* Otherwise assign defaul params */
429 src->OriginalParms = WINED3D_default_light;
430 } else {
431 /* Not enabled by default */
432 src->glIndex = -1;
438 static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface){
440 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
441 IWineD3DStateBlockImpl *targetStateBlock = This->wineD3DDevice->stateBlock;
442 unsigned int i, j;
443 DWORD map;
445 TRACE("(%p) : Updating state block %p ------------------v\n", targetStateBlock, This);
447 /* If not recorded, then update can just recapture */
448 if (This->blockType == WINED3DSBT_RECORDED) {
450 /* Recorded => Only update 'changed' values */
451 if (This->changed.vertexShader && This->vertexShader != targetStateBlock->vertexShader) {
452 TRACE("Updating vertex shader from %p to %p\n", This->vertexShader, targetStateBlock->vertexShader);
454 if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
455 if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
456 This->vertexShader = targetStateBlock->vertexShader;
459 /* Vertex Shader Float Constants */
460 for (j = 0; j < This->num_contained_vs_consts_f; ++j) {
461 i = This->contained_vs_consts_f[j];
462 TRACE("Setting %p from %p %u to {%f, %f, %f, %f}\n", This, targetStateBlock, i,
463 targetStateBlock->vertexShaderConstantF[i * 4],
464 targetStateBlock->vertexShaderConstantF[i * 4 + 1],
465 targetStateBlock->vertexShaderConstantF[i * 4 + 2],
466 targetStateBlock->vertexShaderConstantF[i * 4 + 3]);
468 This->vertexShaderConstantF[i * 4] = targetStateBlock->vertexShaderConstantF[i * 4];
469 This->vertexShaderConstantF[i * 4 + 1] = targetStateBlock->vertexShaderConstantF[i * 4 + 1];
470 This->vertexShaderConstantF[i * 4 + 2] = targetStateBlock->vertexShaderConstantF[i * 4 + 2];
471 This->vertexShaderConstantF[i * 4 + 3] = targetStateBlock->vertexShaderConstantF[i * 4 + 3];
474 /* Vertex Shader Integer Constants */
475 for (j = 0; j < This->num_contained_vs_consts_i; ++j) {
476 i = This->contained_vs_consts_i[j];
477 TRACE("Setting %p from %p %u to {%d, %d, %d, %d}\n", This, targetStateBlock, i,
478 targetStateBlock->vertexShaderConstantI[i * 4],
479 targetStateBlock->vertexShaderConstantI[i * 4 + 1],
480 targetStateBlock->vertexShaderConstantI[i * 4 + 2],
481 targetStateBlock->vertexShaderConstantI[i * 4 + 3]);
483 This->vertexShaderConstantI[i * 4] = targetStateBlock->vertexShaderConstantI[i * 4];
484 This->vertexShaderConstantI[i * 4 + 1] = targetStateBlock->vertexShaderConstantI[i * 4 + 1];
485 This->vertexShaderConstantI[i * 4 + 2] = targetStateBlock->vertexShaderConstantI[i * 4 + 2];
486 This->vertexShaderConstantI[i * 4 + 3] = targetStateBlock->vertexShaderConstantI[i * 4 + 3];
489 /* Vertex Shader Boolean Constants */
490 for (j = 0; j < This->num_contained_vs_consts_b; ++j) {
491 i = This->contained_vs_consts_b[j];
492 TRACE("Setting %p from %p %u to %s\n", This, targetStateBlock, i,
493 targetStateBlock->vertexShaderConstantB[i] ? "TRUE" : "FALSE");
495 This->vertexShaderConstantB[i] = targetStateBlock->vertexShaderConstantB[i];
498 /* Pixel Shader Float Constants */
499 for (j = 0; j < This->num_contained_ps_consts_f; ++j) {
500 i = This->contained_ps_consts_f[j];
501 TRACE("Setting %p from %p %u to {%f, %f, %f, %f}\n", This, targetStateBlock, i,
502 targetStateBlock->pixelShaderConstantF[i * 4],
503 targetStateBlock->pixelShaderConstantF[i * 4 + 1],
504 targetStateBlock->pixelShaderConstantF[i * 4 + 2],
505 targetStateBlock->pixelShaderConstantF[i * 4 + 3]);
507 This->pixelShaderConstantF[i * 4] = targetStateBlock->pixelShaderConstantF[i * 4];
508 This->pixelShaderConstantF[i * 4 + 1] = targetStateBlock->pixelShaderConstantF[i * 4 + 1];
509 This->pixelShaderConstantF[i * 4 + 2] = targetStateBlock->pixelShaderConstantF[i * 4 + 2];
510 This->pixelShaderConstantF[i * 4 + 3] = targetStateBlock->pixelShaderConstantF[i * 4 + 3];
513 /* Pixel Shader Integer Constants */
514 for (j = 0; j < This->num_contained_ps_consts_i; ++j) {
515 i = This->contained_ps_consts_i[j];
516 TRACE("Setting %p from %p %u to {%d, %d, %d, %d}\n", This, targetStateBlock, i,
517 targetStateBlock->pixelShaderConstantI[i * 4],
518 targetStateBlock->pixelShaderConstantI[i * 4 + 1],
519 targetStateBlock->pixelShaderConstantI[i * 4 + 2],
520 targetStateBlock->pixelShaderConstantI[i * 4 + 3]);
522 This->pixelShaderConstantI[i * 4] = targetStateBlock->pixelShaderConstantI[i * 4];
523 This->pixelShaderConstantI[i * 4 + 1] = targetStateBlock->pixelShaderConstantI[i * 4 + 1];
524 This->pixelShaderConstantI[i * 4 + 2] = targetStateBlock->pixelShaderConstantI[i * 4 + 2];
525 This->pixelShaderConstantI[i * 4 + 3] = targetStateBlock->pixelShaderConstantI[i * 4 + 3];
528 /* Pixel Shader Boolean Constants */
529 for (j = 0; j < This->num_contained_ps_consts_b; ++j) {
530 i = This->contained_ps_consts_b[j];
531 TRACE("Setting %p from %p %u to %s\n", This, targetStateBlock, i,
532 targetStateBlock->pixelShaderConstantB[i] ? "TRUE" : "FALSE");
534 This->pixelShaderConstantB[i] = targetStateBlock->pixelShaderConstantB[i];
537 /* Others + Render & Texture */
538 for (i = 0; i < This->num_contained_transform_states; i++) {
539 TRACE("Updating transform %u\n", i);
540 This->transforms[This->contained_transform_states[i]] =
541 targetStateBlock->transforms[This->contained_transform_states[i]];
544 if (This->changed.primitive_type) This->gl_primitive_type = targetStateBlock->gl_primitive_type;
546 if (This->changed.indices && ((This->pIndexData != targetStateBlock->pIndexData)
547 || (This->baseVertexIndex != targetStateBlock->baseVertexIndex)
548 || (This->IndexFmt != targetStateBlock->IndexFmt))) {
549 TRACE("Updating pIndexData to %p, baseVertexIndex to %d\n",
550 targetStateBlock->pIndexData, targetStateBlock->baseVertexIndex);
551 if(targetStateBlock->pIndexData) IWineD3DBuffer_AddRef(targetStateBlock->pIndexData);
552 if(This->pIndexData) IWineD3DBuffer_Release(This->pIndexData);
553 This->pIndexData = targetStateBlock->pIndexData;
554 This->baseVertexIndex = targetStateBlock->baseVertexIndex;
555 This->IndexFmt = targetStateBlock->IndexFmt;
558 if(This->changed.vertexDecl && This->vertexDecl != targetStateBlock->vertexDecl){
559 TRACE("Updating vertex declaration from %p to %p\n", This->vertexDecl, targetStateBlock->vertexDecl);
561 if (targetStateBlock->vertexDecl) IWineD3DVertexDeclaration_AddRef(targetStateBlock->vertexDecl);
562 if (This->vertexDecl) IWineD3DVertexDeclaration_Release(This->vertexDecl);
563 This->vertexDecl = targetStateBlock->vertexDecl;
566 if (This->changed.material && memcmp(&targetStateBlock->material,
567 &This->material,
568 sizeof(WINED3DMATERIAL)) != 0) {
569 TRACE("Updating material\n");
570 This->material = targetStateBlock->material;
573 if (This->changed.viewport && memcmp(&targetStateBlock->viewport,
574 &This->viewport,
575 sizeof(WINED3DVIEWPORT)) != 0) {
576 TRACE("Updating viewport\n");
577 This->viewport = targetStateBlock->viewport;
580 if(This->changed.scissorRect && memcmp(&targetStateBlock->scissorRect,
581 &This->scissorRect,
582 sizeof(targetStateBlock->scissorRect)))
584 TRACE("Updating scissor rect\n");
585 targetStateBlock->scissorRect = This->scissorRect;
588 map = This->changed.streamSource;
589 for (i = 0; map; map >>= 1, ++i)
591 if (!(map & 1)) continue;
593 if (This->streamStride[i] != targetStateBlock->streamStride[i]
594 || This->streamSource[i] != targetStateBlock->streamSource[i])
596 TRACE("Updating stream source %u to %p, stride to %u\n",
597 i, targetStateBlock->streamSource[i], targetStateBlock->streamStride[i]);
598 This->streamStride[i] = targetStateBlock->streamStride[i];
599 if (targetStateBlock->streamSource[i]) IWineD3DBuffer_AddRef(targetStateBlock->streamSource[i]);
600 if (This->streamSource[i]) IWineD3DBuffer_Release(This->streamSource[i]);
601 This->streamSource[i] = targetStateBlock->streamSource[i];
605 map = This->changed.streamFreq;
606 for (i = 0; map; map >>= 1, ++i)
608 if (!(map & 1)) continue;
610 if (This->streamFreq[i] != targetStateBlock->streamFreq[i]
611 || This->streamFlags[i] != targetStateBlock->streamFlags[i])
613 TRACE("Updating stream frequency %u to %u flags to %#x\n",
614 i, targetStateBlock->streamFreq[i], targetStateBlock->streamFlags[i]);
615 This->streamFreq[i] = targetStateBlock->streamFreq[i];
616 This->streamFlags[i] = targetStateBlock->streamFlags[i];
620 map = This->changed.clipplane;
621 for (i = 0; map; map >>= 1, ++i)
623 if (!(map & 1)) continue;
625 if (memcmp(targetStateBlock->clipplane[i], This->clipplane[i], sizeof(*This->clipplane)))
627 TRACE("Updating clipplane %u\n", i);
628 memcpy(This->clipplane[i], targetStateBlock->clipplane[i], sizeof(*This->clipplane));
632 /* Render */
633 for (i = 0; i < This->num_contained_render_states; i++) {
634 TRACE("Updating renderState %u to %u\n", This->contained_render_states[i],
635 targetStateBlock->renderState[This->contained_render_states[i]]);
636 This->renderState[This->contained_render_states[i]] = targetStateBlock->renderState[This->contained_render_states[i]];
639 /* Texture states */
640 for (j = 0; j < This->num_contained_tss_states; j++) {
641 DWORD stage = This->contained_tss_states[j].stage;
642 DWORD state = This->contained_tss_states[j].state;
644 TRACE("Updating texturestage state %u, %u to %u (was %u)\n", stage, state,
645 targetStateBlock->textureState[stage][state], This->textureState[stage][state]);
646 This->textureState[stage][state] = targetStateBlock->textureState[stage][state];
649 /* Samplers */
650 map = This->changed.textures;
651 for (i = 0; map; map >>= 1, ++i)
653 if (!(map & 1)) continue;
655 TRACE("Updating texture %u to %p (was %p)\n", i, targetStateBlock->textures[i], This->textures[i]);
656 if (targetStateBlock->textures[i]) IWineD3DBaseTexture_AddRef(targetStateBlock->textures[i]);
657 if (This->textures[i]) IWineD3DBaseTexture_Release(This->textures[i]);
658 This->textures[i] = targetStateBlock->textures[i];
661 for (j = 0; j < This->num_contained_sampler_states; j++) {
662 DWORD stage = This->contained_sampler_states[j].stage;
663 DWORD state = This->contained_sampler_states[j].state;
664 TRACE("Updating sampler state %u, %u to %u (was %u)\n", stage, state,
665 targetStateBlock->samplerState[stage][state], This->samplerState[stage][state]);
666 This->samplerState[stage][state] = targetStateBlock->samplerState[stage][state];
668 if(This->changed.pixelShader && This->pixelShader != targetStateBlock->pixelShader) {
669 if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
670 if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
671 This->pixelShader = targetStateBlock->pixelShader;
674 record_lights(This, targetStateBlock);
675 } else if(This->blockType == WINED3DSBT_ALL) {
676 memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI));
677 memcpy(This->vertexShaderConstantI, targetStateBlock->vertexShaderConstantI, sizeof(This->vertexShaderConstantF));
678 memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
679 This->gl_primitive_type = targetStateBlock->gl_primitive_type;
680 memcpy(This->streamStride, targetStateBlock->streamStride, sizeof(This->streamStride));
681 memcpy(This->streamOffset, targetStateBlock->streamOffset, sizeof(This->streamOffset));
682 memcpy(This->streamFreq, targetStateBlock->streamFreq, sizeof(This->streamFreq));
683 memcpy(This->streamFlags, targetStateBlock->streamFlags, sizeof(This->streamFlags));
684 This->baseVertexIndex = targetStateBlock->baseVertexIndex;
685 memcpy(This->transforms, targetStateBlock->transforms, sizeof(This->transforms));
686 record_lights(This, targetStateBlock);
687 memcpy(This->clipplane, targetStateBlock->clipplane, sizeof(This->clipplane));
688 This->clip_status = targetStateBlock->clip_status;
689 This->viewport = targetStateBlock->viewport;
690 This->material = targetStateBlock->material;
691 memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));
692 memcpy(This->pixelShaderConstantI, targetStateBlock->pixelShaderConstantI, sizeof(This->pixelShaderConstantF));
693 memcpy(This->pixelShaderConstantF, targetStateBlock->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
694 memcpy(This->renderState, targetStateBlock->renderState, sizeof(This->renderState));
695 memcpy(This->textureState, targetStateBlock->textureState, sizeof(This->textureState));
696 memcpy(This->samplerState, targetStateBlock->samplerState, sizeof(This->samplerState));
697 This->scissorRect = targetStateBlock->scissorRect;
699 if (This->vertexDecl != targetStateBlock->vertexDecl)
701 if (targetStateBlock->vertexDecl) IWineD3DVertexDeclaration_AddRef(targetStateBlock->vertexDecl);
702 if (This->vertexDecl) IWineD3DVertexDeclaration_Release(This->vertexDecl);
703 This->vertexDecl = targetStateBlock->vertexDecl;
706 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
708 if (targetStateBlock->textures[i] != This->textures[i])
710 if (targetStateBlock->textures[i]) IWineD3DBaseTexture_AddRef(targetStateBlock->textures[i]);
711 if (This->textures[i]) IWineD3DBaseTexture_Release(This->textures[i]);
712 This->textures[i] = targetStateBlock->textures[i];
716 if(targetStateBlock->pIndexData != This->pIndexData ||
717 targetStateBlock->IndexFmt != This->IndexFmt) {
718 if (targetStateBlock->pIndexData) IWineD3DBuffer_AddRef(targetStateBlock->pIndexData);
719 if (This->pIndexData) IWineD3DBuffer_Release(This->pIndexData);
720 This->pIndexData = targetStateBlock->pIndexData;
721 This->IndexFmt = targetStateBlock->IndexFmt;
723 for(i = 0; i < MAX_STREAMS; i++) {
724 if(targetStateBlock->streamSource[i] != This->streamSource[i]) {
725 if(targetStateBlock->streamSource[i]) IWineD3DBuffer_AddRef(targetStateBlock->streamSource[i]);
726 if(This->streamSource[i]) IWineD3DBuffer_Release(This->streamSource[i]);
727 This->streamSource[i] = targetStateBlock->streamSource[i];
730 if(This->vertexShader != targetStateBlock->vertexShader) {
731 if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
732 if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
733 This->vertexShader = targetStateBlock->vertexShader;
735 if(This->pixelShader != targetStateBlock->pixelShader) {
736 if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
737 if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
738 This->pixelShader = targetStateBlock->pixelShader;
740 } else if(This->blockType == WINED3DSBT_VERTEXSTATE) {
741 memcpy(This->vertexShaderConstantB, targetStateBlock->vertexShaderConstantB, sizeof(This->vertexShaderConstantI));
742 memcpy(This->vertexShaderConstantI, targetStateBlock->vertexShaderConstantI, sizeof(This->vertexShaderConstantF));
743 memcpy(This->vertexShaderConstantF, targetStateBlock->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
744 record_lights(This, targetStateBlock);
745 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
746 This->renderState[SavedVertexStates_R[i]] = targetStateBlock->renderState[SavedVertexStates_R[i]];
748 for (j = 0; j < MAX_COMBINED_SAMPLERS; j++) {
749 for (i = 0; i < NUM_SAVEDVERTEXSTATES_S; i++) {
750 This->samplerState[j][SavedVertexStates_S[i]] = targetStateBlock->samplerState[j][SavedVertexStates_S[i]];
753 for (j = 0; j < MAX_TEXTURES; j++) {
754 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
755 This->textureState[j][SavedVertexStates_R[i]] = targetStateBlock->textureState[j][SavedVertexStates_R[i]];
758 for(i = 0; i < MAX_STREAMS; i++) {
759 if(targetStateBlock->streamSource[i] != This->streamSource[i]) {
760 if (targetStateBlock->streamSource[i]) IWineD3DBuffer_AddRef(targetStateBlock->streamSource[i]);
761 if (This->streamSource[i]) IWineD3DBuffer_Release(This->streamSource[i]);
762 This->streamSource[i] = targetStateBlock->streamSource[i];
765 if(This->vertexShader != targetStateBlock->vertexShader) {
766 if(targetStateBlock->vertexShader) IWineD3DVertexShader_AddRef(targetStateBlock->vertexShader);
767 if(This->vertexShader) IWineD3DVertexShader_Release(This->vertexShader);
768 This->vertexShader = targetStateBlock->vertexShader;
770 } else if(This->blockType == WINED3DSBT_PIXELSTATE) {
771 memcpy(This->pixelShaderConstantB, targetStateBlock->pixelShaderConstantB, sizeof(This->pixelShaderConstantI));
772 memcpy(This->pixelShaderConstantI, targetStateBlock->pixelShaderConstantI, sizeof(This->pixelShaderConstantF));
773 memcpy(This->pixelShaderConstantF, targetStateBlock->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
774 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
775 This->renderState[SavedPixelStates_R[i]] = targetStateBlock->renderState[SavedPixelStates_R[i]];
777 for (j = 0; j < MAX_COMBINED_SAMPLERS; j++) {
778 for (i = 0; i < NUM_SAVEDPIXELSTATES_S; i++) {
779 This->samplerState[j][SavedPixelStates_S[i]] = targetStateBlock->samplerState[j][SavedPixelStates_S[i]];
782 for (j = 0; j < MAX_TEXTURES; j++) {
783 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
784 This->textureState[j][SavedPixelStates_R[i]] = targetStateBlock->textureState[j][SavedPixelStates_R[i]];
787 if(This->pixelShader != targetStateBlock->pixelShader) {
788 if(targetStateBlock->pixelShader) IWineD3DPixelShader_AddRef(targetStateBlock->pixelShader);
789 if(This->pixelShader) IWineD3DPixelShader_Release(This->pixelShader);
790 This->pixelShader = targetStateBlock->pixelShader;
794 TRACE("(%p) : Updated state block %p ------------------^\n", targetStateBlock, This);
796 return WINED3D_OK;
799 static void apply_lights(IWineD3DDevice *pDevice, const IWineD3DStateBlockImpl *This)
801 UINT i;
802 for(i = 0; i < LIGHTMAP_SIZE; i++) {
803 struct list *e;
805 LIST_FOR_EACH(e, &This->lightMap[i]) {
806 const PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
808 if(light->changed) {
809 IWineD3DDevice_SetLight(pDevice, light->OriginalIndex, &light->OriginalParms);
811 if(light->enabledChanged) {
812 IWineD3DDevice_SetLightEnable(pDevice, light->OriginalIndex, light->glIndex != -1);
818 static HRESULT WINAPI IWineD3DStateBlockImpl_Apply(IWineD3DStateBlock *iface){
819 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
820 IWineD3DDevice* pDevice = (IWineD3DDevice*)This->wineD3DDevice;
822 /*Copy thing over to updateBlock is isRecording otherwise StateBlock,
823 should really perform a delta so that only the changes get updated*/
825 UINT i;
826 UINT j;
827 DWORD map;
829 TRACE("(%p) : Applying state block %p ------------------v\n", This, pDevice);
831 TRACE("Blocktype: %d\n", This->blockType);
833 if(This->blockType == WINED3DSBT_RECORDED) {
834 if (This->changed.vertexShader) {
835 IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader);
837 /* Vertex Shader Constants */
838 for (i = 0; i < This->num_contained_vs_consts_f; i++) {
839 IWineD3DDevice_SetVertexShaderConstantF(pDevice, This->contained_vs_consts_f[i],
840 This->vertexShaderConstantF + This->contained_vs_consts_f[i] * 4, 1);
842 for (i = 0; i < This->num_contained_vs_consts_i; i++) {
843 IWineD3DDevice_SetVertexShaderConstantI(pDevice, This->contained_vs_consts_i[i],
844 This->vertexShaderConstantI + This->contained_vs_consts_i[i] * 4, 1);
846 for (i = 0; i < This->num_contained_vs_consts_b; i++) {
847 IWineD3DDevice_SetVertexShaderConstantB(pDevice, This->contained_vs_consts_b[i],
848 This->vertexShaderConstantB + This->contained_vs_consts_b[i], 1);
851 apply_lights(pDevice, This);
853 if (This->changed.pixelShader) {
854 IWineD3DDevice_SetPixelShader(pDevice, This->pixelShader);
856 /* Pixel Shader Constants */
857 for (i = 0; i < This->num_contained_ps_consts_f; i++) {
858 IWineD3DDevice_SetPixelShaderConstantF(pDevice, This->contained_ps_consts_f[i],
859 This->pixelShaderConstantF + This->contained_ps_consts_f[i] * 4, 1);
861 for (i = 0; i < This->num_contained_ps_consts_i; i++) {
862 IWineD3DDevice_SetPixelShaderConstantI(pDevice, This->contained_ps_consts_i[i],
863 This->pixelShaderConstantI + This->contained_ps_consts_i[i] * 4, 1);
865 for (i = 0; i < This->num_contained_ps_consts_b; i++) {
866 IWineD3DDevice_SetPixelShaderConstantB(pDevice, This->contained_ps_consts_b[i],
867 This->pixelShaderConstantB + This->contained_ps_consts_b[i], 1);
870 /* Render */
871 for (i = 0; i <= This->num_contained_render_states; i++) {
872 IWineD3DDevice_SetRenderState(pDevice, This->contained_render_states[i],
873 This->renderState[This->contained_render_states[i]]);
875 /* Texture states */
876 for (i = 0; i < This->num_contained_tss_states; i++) {
877 DWORD stage = This->contained_tss_states[i].stage;
878 DWORD state = This->contained_tss_states[i].state;
879 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->textureState[stage][state] = This->textureState[stage][state];
880 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.textureState[stage] |= 1 << state;
881 /* TODO: Record a display list to apply all gl states. For now apply by brute force */
882 IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)pDevice, STATE_TEXTURESTAGE(stage, state));
884 /* Sampler states */
885 for (i = 0; i < This->num_contained_sampler_states; i++) {
886 DWORD stage = This->contained_sampler_states[i].stage;
887 DWORD state = This->contained_sampler_states[i].state;
888 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->samplerState[stage][state] = This->samplerState[stage][state];
889 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.samplerState[stage] |= 1 << state;
890 IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)pDevice, STATE_SAMPLER(stage));
893 for (i = 0; i < This->num_contained_transform_states; i++) {
894 IWineD3DDevice_SetTransform(pDevice, This->contained_transform_states[i],
895 &This->transforms[This->contained_transform_states[i]]);
898 if (This->changed.primitive_type)
900 This->wineD3DDevice->updateStateBlock->changed.primitive_type = TRUE;
901 This->wineD3DDevice->updateStateBlock->gl_primitive_type = This->gl_primitive_type;
904 if (This->changed.indices)
906 IWineD3DDevice_SetIndexBuffer(pDevice, This->pIndexData, This->IndexFmt);
907 IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex);
910 if (This->changed.vertexDecl) {
911 IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl);
914 if (This->changed.material ) {
915 IWineD3DDevice_SetMaterial(pDevice, &This->material);
918 if (This->changed.viewport) {
919 IWineD3DDevice_SetViewport(pDevice, &This->viewport);
922 if (This->changed.scissorRect) {
923 IWineD3DDevice_SetScissorRect(pDevice, &This->scissorRect);
926 /* TODO: Proper implementation using SetStreamSource offset (set to 0 for the moment)\n") */
927 map = This->changed.streamSource;
928 for (i = 0; map; map >>= 1, ++i)
930 if (map & 1) IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]);
933 map = This->changed.streamFreq;
934 for (i = 0; map; map >>= 1, ++i)
936 if (map & 1) IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]);
939 map = This->changed.textures;
940 for (i = 0; map; map >>= 1, ++i)
942 if (!(map & 1)) continue;
944 if (i < MAX_FRAGMENT_SAMPLERS) IWineD3DDevice_SetTexture(pDevice, i, This->textures[i]);
945 else IWineD3DDevice_SetTexture(pDevice, WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS,
946 This->textures[i]);
949 map = This->changed.clipplane;
950 for (i = 0; map; map >>= 1, ++i)
952 float clip[4];
954 if (!(map & 1)) continue;
956 clip[0] = This->clipplane[i][0];
957 clip[1] = This->clipplane[i][1];
958 clip[2] = This->clipplane[i][2];
959 clip[3] = This->clipplane[i][3];
960 IWineD3DDevice_SetClipPlane(pDevice, i, clip);
962 } else if(This->blockType == WINED3DSBT_VERTEXSTATE) {
963 IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader);
964 for (i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
965 IWineD3DDevice_SetVertexShaderConstantF(pDevice, i,
966 This->vertexShaderConstantF + i * 4, 1);
968 for (i = 0; i < MAX_CONST_I; i++) {
969 IWineD3DDevice_SetVertexShaderConstantI(pDevice, i,
970 This->vertexShaderConstantI + i * 4, 1);
972 for (i = 0; i < MAX_CONST_B; i++) {
973 IWineD3DDevice_SetVertexShaderConstantB(pDevice, i,
974 This->vertexShaderConstantB + i, 1);
977 apply_lights(pDevice, This);
979 for(i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
980 IWineD3DDevice_SetRenderState(pDevice, SavedVertexStates_R[i], This->renderState[SavedVertexStates_R[i]]);
982 for(j = 0; j < MAX_TEXTURES; j++) {
983 for(i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
984 IWineD3DDevice_SetTextureStageState(pDevice, j, SavedVertexStates_T[i],
985 This->textureState[j][SavedVertexStates_T[i]]);
989 for(j = 0; j < MAX_FRAGMENT_SAMPLERS; j++) {
990 for(i = 0; i < NUM_SAVEDVERTEXSTATES_S; i++) {
991 IWineD3DDevice_SetSamplerState(pDevice, j, SavedVertexStates_S[i],
992 This->samplerState[j][SavedVertexStates_S[i]]);
995 for(j = MAX_FRAGMENT_SAMPLERS; j < MAX_COMBINED_SAMPLERS; j++) {
996 for(i = 0; i < NUM_SAVEDVERTEXSTATES_S; i++) {
997 IWineD3DDevice_SetSamplerState(pDevice,
998 WINED3DVERTEXTEXTURESAMPLER0 + j - MAX_FRAGMENT_SAMPLERS,
999 SavedVertexStates_S[i],
1000 This->samplerState[j][SavedVertexStates_S[i]]);
1003 } else if(This->blockType == WINED3DSBT_PIXELSTATE) {
1004 IWineD3DDevice_SetPixelShader(pDevice, This->pixelShader);
1005 for (i = 0; i < GL_LIMITS(pshader_constantsF); i++) {
1006 IWineD3DDevice_SetPixelShaderConstantF(pDevice, i,
1007 This->pixelShaderConstantF + i * 4, 1);
1009 for (i = 0; i < MAX_CONST_I; i++) {
1010 IWineD3DDevice_SetPixelShaderConstantI(pDevice, i,
1011 This->pixelShaderConstantI + i * 4, 1);
1013 for (i = 0; i < MAX_CONST_B; i++) {
1014 IWineD3DDevice_SetPixelShaderConstantB(pDevice, i,
1015 This->pixelShaderConstantB + i, 1);
1018 for(i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
1019 IWineD3DDevice_SetRenderState(pDevice, SavedPixelStates_R[i], This->renderState[SavedPixelStates_R[i]]);
1021 for(j = 0; j < MAX_TEXTURES; j++) {
1022 for(i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
1023 IWineD3DDevice_SetTextureStageState(pDevice, j, SavedPixelStates_T[i],
1024 This->textureState[j][SavedPixelStates_T[i]]);
1028 for(j = 0; j < MAX_FRAGMENT_SAMPLERS; j++) {
1029 for(i = 0; i < NUM_SAVEDPIXELSTATES_S; i++) {
1030 IWineD3DDevice_SetSamplerState(pDevice, j, SavedPixelStates_S[i],
1031 This->samplerState[j][SavedPixelStates_S[i]]);
1034 for(j = MAX_FRAGMENT_SAMPLERS; j < MAX_COMBINED_SAMPLERS; j++) {
1035 for(i = 0; i < NUM_SAVEDPIXELSTATES_S; i++) {
1036 IWineD3DDevice_SetSamplerState(pDevice,
1037 WINED3DVERTEXTEXTURESAMPLER0 + j - MAX_FRAGMENT_SAMPLERS,
1038 SavedPixelStates_S[i],
1039 This->samplerState[j][SavedPixelStates_S[i]]);
1042 } else if(This->blockType == WINED3DSBT_ALL) {
1043 IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader);
1044 for (i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
1045 IWineD3DDevice_SetVertexShaderConstantF(pDevice, i,
1046 This->vertexShaderConstantF + i * 4, 1);
1048 for (i = 0; i < MAX_CONST_I; i++) {
1049 IWineD3DDevice_SetVertexShaderConstantI(pDevice, i,
1050 This->vertexShaderConstantI + i * 4, 1);
1052 for (i = 0; i < MAX_CONST_B; i++) {
1053 IWineD3DDevice_SetVertexShaderConstantB(pDevice, i,
1054 This->vertexShaderConstantB + i, 1);
1057 IWineD3DDevice_SetPixelShader(pDevice, This->pixelShader);
1058 for (i = 0; i < GL_LIMITS(pshader_constantsF); i++) {
1059 IWineD3DDevice_SetPixelShaderConstantF(pDevice, i,
1060 This->pixelShaderConstantF + i * 4, 1);
1062 for (i = 0; i < MAX_CONST_I; i++) {
1063 IWineD3DDevice_SetPixelShaderConstantI(pDevice, i,
1064 This->pixelShaderConstantI + i * 4, 1);
1066 for (i = 0; i < MAX_CONST_B; i++) {
1067 IWineD3DDevice_SetPixelShaderConstantB(pDevice, i,
1068 This->pixelShaderConstantB + i, 1);
1071 apply_lights(pDevice, This);
1073 for(i = 1; i <= WINEHIGHEST_RENDER_STATE; i++) {
1074 IWineD3DDevice_SetRenderState(pDevice, i, This->renderState[i]);
1076 for(j = 0; j < MAX_TEXTURES; j++) {
1077 for (i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
1079 IWineD3DDevice_SetTextureStageState(pDevice, j, i, This->textureState[j][i]);
1083 /* Skip unused values between TEXTURE8 and WORLD0 ? */
1084 for(i = 1; i <= HIGHEST_TRANSFORMSTATE; i++) {
1085 IWineD3DDevice_SetTransform(pDevice, i, &This->transforms[i]);
1087 This->wineD3DDevice->updateStateBlock->gl_primitive_type = This->gl_primitive_type;
1088 IWineD3DDevice_SetIndexBuffer(pDevice, This->pIndexData, This->IndexFmt);
1089 IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex);
1090 IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl);
1091 IWineD3DDevice_SetMaterial(pDevice, &This->material);
1092 IWineD3DDevice_SetViewport(pDevice, &This->viewport);
1093 IWineD3DDevice_SetScissorRect(pDevice, &This->scissorRect);
1095 /* TODO: Proper implementation using SetStreamSource offset (set to 0 for the moment)\n") */
1096 for (i=0; i<MAX_STREAMS; i++) {
1097 IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]);
1098 IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]);
1100 for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
1101 UINT sampler = j < MAX_FRAGMENT_SAMPLERS ? j : WINED3DVERTEXTEXTURESAMPLER0 + j - MAX_FRAGMENT_SAMPLERS;
1103 IWineD3DDevice_SetTexture(pDevice, sampler, This->textures[j]);
1104 for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE; ++i)
1106 IWineD3DDevice_SetSamplerState(pDevice, sampler, i, This->samplerState[j][i]);
1109 for (i = 0; i < GL_LIMITS(clipplanes); i++) {
1110 float clip[4];
1112 clip[0] = This->clipplane[i][0];
1113 clip[1] = This->clipplane[i][1];
1114 clip[2] = This->clipplane[i][2];
1115 clip[3] = This->clipplane[i][3];
1116 IWineD3DDevice_SetClipPlane(pDevice, i, clip);
1120 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->lowest_disabled_stage = MAX_TEXTURES - 1;
1121 for(j = 0; j < MAX_TEXTURES - 1; j++) {
1122 if(((IWineD3DDeviceImpl *)pDevice)->stateBlock->textureState[j][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
1123 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->lowest_disabled_stage = j;
1124 break;
1127 TRACE("(%p) : Applied state block %p ------------------^\n", This, pDevice);
1129 return WINED3D_OK;
1132 static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock* iface) {
1133 IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
1134 IWineD3DDevice *device = (IWineD3DDevice *)This->wineD3DDevice;
1135 IWineD3DDeviceImpl *ThisDevice = (IWineD3DDeviceImpl *)device;
1136 union {
1137 WINED3DLINEPATTERN lp;
1138 DWORD d;
1139 } lp;
1140 union {
1141 float f;
1142 DWORD d;
1143 } tmpfloat;
1144 unsigned int i;
1145 IWineD3DSwapChain *swapchain;
1146 IWineD3DSurface *backbuffer;
1147 HRESULT hr;
1149 /* Note this may have a large overhead but it should only be executed
1150 once, in order to initialize the complete state of the device and
1151 all opengl equivalents */
1152 TRACE("(%p) -----------------------> Setting up device defaults... %p\n", This, This->wineD3DDevice);
1153 /* TODO: make a special stateblock type for the primary stateblock (it never gets applied so it doesn't need a real type) */
1154 This->blockType = WINED3DSBT_INIT;
1156 /* Set some of the defaults for lights, transforms etc */
1157 memcpy(&This->transforms[WINED3DTS_PROJECTION], identity, sizeof(identity));
1158 memcpy(&This->transforms[WINED3DTS_VIEW], identity, sizeof(identity));
1159 for (i = 0; i < 256; ++i) {
1160 memcpy(&This->transforms[WINED3DTS_WORLDMATRIX(i)], identity, sizeof(identity));
1163 TRACE("Render states\n");
1164 /* Render states: */
1165 if (ThisDevice->auto_depth_stencil_buffer != NULL) {
1166 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE, WINED3DZB_TRUE);
1167 } else {
1168 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZENABLE, WINED3DZB_FALSE);
1170 IWineD3DDevice_SetRenderState(device, WINED3DRS_FILLMODE, WINED3DFILL_SOLID);
1171 IWineD3DDevice_SetRenderState(device, WINED3DRS_SHADEMODE, WINED3DSHADE_GOURAUD);
1172 lp.lp.wRepeatFactor = 0;
1173 lp.lp.wLinePattern = 0;
1174 IWineD3DDevice_SetRenderState(device, WINED3DRS_LINEPATTERN, lp.d);
1175 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZWRITEENABLE, TRUE);
1176 IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHATESTENABLE, FALSE);
1177 IWineD3DDevice_SetRenderState(device, WINED3DRS_LASTPIXEL, TRUE);
1178 IWineD3DDevice_SetRenderState(device, WINED3DRS_SRCBLEND, WINED3DBLEND_ONE);
1179 IWineD3DDevice_SetRenderState(device, WINED3DRS_DESTBLEND, WINED3DBLEND_ZERO);
1180 IWineD3DDevice_SetRenderState(device, WINED3DRS_CULLMODE, WINED3DCULL_CCW);
1181 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZFUNC, WINED3DCMP_LESSEQUAL);
1182 IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHAFUNC, WINED3DCMP_ALWAYS);
1183 IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHAREF, 0);
1184 IWineD3DDevice_SetRenderState(device, WINED3DRS_DITHERENABLE, FALSE);
1185 IWineD3DDevice_SetRenderState(device, WINED3DRS_ALPHABLENDENABLE, FALSE);
1186 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGENABLE, FALSE);
1187 IWineD3DDevice_SetRenderState(device, WINED3DRS_SPECULARENABLE, FALSE);
1188 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZVISIBLE, 0);
1189 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGCOLOR, 0);
1190 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGTABLEMODE, WINED3DFOG_NONE);
1191 tmpfloat.f = 0.0f;
1192 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGSTART, tmpfloat.d);
1193 tmpfloat.f = 1.0f;
1194 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGEND, tmpfloat.d);
1195 tmpfloat.f = 1.0f;
1196 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGDENSITY, tmpfloat.d);
1197 IWineD3DDevice_SetRenderState(device, WINED3DRS_EDGEANTIALIAS, FALSE);
1198 IWineD3DDevice_SetRenderState(device, WINED3DRS_ZBIAS, 0);
1199 IWineD3DDevice_SetRenderState(device, WINED3DRS_RANGEFOGENABLE, FALSE);
1200 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILENABLE, FALSE);
1201 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILFAIL, WINED3DSTENCILOP_KEEP);
1202 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILZFAIL, WINED3DSTENCILOP_KEEP);
1203 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILPASS, WINED3DSTENCILOP_KEEP);
1204 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILREF, 0);
1205 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILMASK, 0xFFFFFFFF);
1206 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILFUNC, WINED3DCMP_ALWAYS);
1207 IWineD3DDevice_SetRenderState(device, WINED3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
1208 IWineD3DDevice_SetRenderState(device, WINED3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
1209 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP0, 0);
1210 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP1, 0);
1211 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP2, 0);
1212 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP3, 0);
1213 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP4, 0);
1214 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP5, 0);
1215 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP6, 0);
1216 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP7, 0);
1217 IWineD3DDevice_SetRenderState(device, WINED3DRS_CLIPPING, TRUE);
1218 IWineD3DDevice_SetRenderState(device, WINED3DRS_LIGHTING, TRUE);
1219 IWineD3DDevice_SetRenderState(device, WINED3DRS_AMBIENT, 0);
1220 IWineD3DDevice_SetRenderState(device, WINED3DRS_FOGVERTEXMODE, WINED3DFOG_NONE);
1221 IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORVERTEX, TRUE);
1222 IWineD3DDevice_SetRenderState(device, WINED3DRS_LOCALVIEWER, TRUE);
1223 IWineD3DDevice_SetRenderState(device, WINED3DRS_NORMALIZENORMALS, FALSE);
1224 IWineD3DDevice_SetRenderState(device, WINED3DRS_DIFFUSEMATERIALSOURCE, WINED3DMCS_COLOR1);
1225 IWineD3DDevice_SetRenderState(device, WINED3DRS_SPECULARMATERIALSOURCE, WINED3DMCS_COLOR2);
1226 IWineD3DDevice_SetRenderState(device, WINED3DRS_AMBIENTMATERIALSOURCE, WINED3DMCS_MATERIAL);
1227 IWineD3DDevice_SetRenderState(device, WINED3DRS_EMISSIVEMATERIALSOURCE, WINED3DMCS_MATERIAL);
1228 IWineD3DDevice_SetRenderState(device, WINED3DRS_VERTEXBLEND, WINED3DVBF_DISABLE);
1229 IWineD3DDevice_SetRenderState(device, WINED3DRS_CLIPPLANEENABLE, 0);
1230 IWineD3DDevice_SetRenderState(device, WINED3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
1231 tmpfloat.f = 1.0f;
1232 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE, tmpfloat.d);
1233 tmpfloat.f = ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion < 9 ? 0.0f : 1.0f;
1234 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MIN, tmpfloat.d);
1235 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSPRITEENABLE, FALSE);
1236 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALEENABLE, FALSE);
1237 tmpfloat.f = 1.0f;
1238 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_A, tmpfloat.d);
1239 tmpfloat.f = 0.0f;
1240 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_B, tmpfloat.d);
1241 tmpfloat.f = 0.0f;
1242 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALE_C, tmpfloat.d);
1243 IWineD3DDevice_SetRenderState(device, WINED3DRS_MULTISAMPLEANTIALIAS, TRUE);
1244 IWineD3DDevice_SetRenderState(device, WINED3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
1245 IWineD3DDevice_SetRenderState(device, WINED3DRS_PATCHEDGESTYLE, WINED3DPATCHEDGE_DISCRETE);
1246 tmpfloat.f = 1.0f;
1247 IWineD3DDevice_SetRenderState(device, WINED3DRS_PATCHSEGMENTS, tmpfloat.d);
1248 IWineD3DDevice_SetRenderState(device, WINED3DRS_DEBUGMONITORTOKEN, 0xbaadcafe);
1249 tmpfloat.f = GL_LIMITS(pointsize);
1250 IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MAX, tmpfloat.d);
1251 IWineD3DDevice_SetRenderState(device, WINED3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
1252 IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE, 0x0000000F);
1253 tmpfloat.f = 0.0f;
1254 IWineD3DDevice_SetRenderState(device, WINED3DRS_TWEENFACTOR, tmpfloat.d);
1255 IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDOP, WINED3DBLENDOP_ADD);
1256 IWineD3DDevice_SetRenderState(device, WINED3DRS_POSITIONDEGREE, WINED3DDEGREE_CUBIC);
1257 IWineD3DDevice_SetRenderState(device, WINED3DRS_NORMALDEGREE, WINED3DDEGREE_LINEAR);
1258 /* states new in d3d9 */
1259 IWineD3DDevice_SetRenderState(device, WINED3DRS_SCISSORTESTENABLE, FALSE);
1260 IWineD3DDevice_SetRenderState(device, WINED3DRS_SLOPESCALEDEPTHBIAS, 0);
1261 tmpfloat.f = 1.0f;
1262 IWineD3DDevice_SetRenderState(device, WINED3DRS_MINTESSELLATIONLEVEL, tmpfloat.d);
1263 IWineD3DDevice_SetRenderState(device, WINED3DRS_MAXTESSELLATIONLEVEL, tmpfloat.d);
1264 IWineD3DDevice_SetRenderState(device, WINED3DRS_ANTIALIASEDLINEENABLE, FALSE);
1265 tmpfloat.f = 0.0f;
1266 IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_X, tmpfloat.d);
1267 IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_Y, tmpfloat.d);
1268 tmpfloat.f = 1.0f;
1269 IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_Z, tmpfloat.d);
1270 tmpfloat.f = 0.0f;
1271 IWineD3DDevice_SetRenderState(device, WINED3DRS_ADAPTIVETESS_W, tmpfloat.d);
1272 IWineD3DDevice_SetRenderState(device, WINED3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
1273 IWineD3DDevice_SetRenderState(device, WINED3DRS_TWOSIDEDSTENCILMODE, FALSE);
1274 IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILFAIL, WINED3DSTENCILOP_KEEP);
1275 IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILZFAIL, WINED3DSTENCILOP_KEEP);
1276 IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILPASS, WINED3DSTENCILOP_KEEP);
1277 IWineD3DDevice_SetRenderState(device, WINED3DRS_CCW_STENCILFUNC, WINED3DCMP_ALWAYS);
1278 IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE1, 0x0000000F);
1279 IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE2, 0x0000000F);
1280 IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE3, 0x0000000F);
1281 IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDFACTOR, 0xFFFFFFFF);
1282 IWineD3DDevice_SetRenderState(device, WINED3DRS_SRGBWRITEENABLE, 0);
1283 IWineD3DDevice_SetRenderState(device, WINED3DRS_DEPTHBIAS, 0);
1284 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP8, 0);
1285 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP9, 0);
1286 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP10, 0);
1287 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP11, 0);
1288 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP12, 0);
1289 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP13, 0);
1290 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP14, 0);
1291 IWineD3DDevice_SetRenderState(device, WINED3DRS_WRAP15, 0);
1292 IWineD3DDevice_SetRenderState(device, WINED3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1293 IWineD3DDevice_SetRenderState(device, WINED3DRS_SRCBLENDALPHA, WINED3DBLEND_ONE);
1294 IWineD3DDevice_SetRenderState(device, WINED3DRS_DESTBLENDALPHA, WINED3DBLEND_ZERO);
1295 IWineD3DDevice_SetRenderState(device, WINED3DRS_BLENDOPALPHA, WINED3DBLENDOP_ADD);
1297 /* clipping status */
1298 This->clip_status.ClipUnion = 0;
1299 This->clip_status.ClipIntersection = 0xFFFFFFFF;
1301 /* Texture Stage States - Put directly into state block, we will call function below */
1302 for (i = 0; i < MAX_TEXTURES; i++) {
1303 TRACE("Setting up default texture states for texture Stage %d\n", i);
1304 memcpy(&This->transforms[WINED3DTS_TEXTURE0 + i], identity, sizeof(identity));
1305 This->textureState[i][WINED3DTSS_COLOROP ] = (i==0)? WINED3DTOP_MODULATE : WINED3DTOP_DISABLE;
1306 This->textureState[i][WINED3DTSS_COLORARG1 ] = WINED3DTA_TEXTURE;
1307 This->textureState[i][WINED3DTSS_COLORARG2 ] = WINED3DTA_CURRENT;
1308 This->textureState[i][WINED3DTSS_ALPHAOP ] = (i==0)? WINED3DTOP_SELECTARG1 : WINED3DTOP_DISABLE;
1309 This->textureState[i][WINED3DTSS_ALPHAARG1 ] = WINED3DTA_TEXTURE;
1310 This->textureState[i][WINED3DTSS_ALPHAARG2 ] = WINED3DTA_CURRENT;
1311 This->textureState[i][WINED3DTSS_BUMPENVMAT00 ] = 0;
1312 This->textureState[i][WINED3DTSS_BUMPENVMAT01 ] = 0;
1313 This->textureState[i][WINED3DTSS_BUMPENVMAT10 ] = 0;
1314 This->textureState[i][WINED3DTSS_BUMPENVMAT11 ] = 0;
1315 This->textureState[i][WINED3DTSS_TEXCOORDINDEX ] = i;
1316 This->textureState[i][WINED3DTSS_BUMPENVLSCALE ] = 0;
1317 This->textureState[i][WINED3DTSS_BUMPENVLOFFSET ] = 0;
1318 This->textureState[i][WINED3DTSS_TEXTURETRANSFORMFLAGS ] = WINED3DTTFF_DISABLE;
1319 This->textureState[i][WINED3DTSS_COLORARG0 ] = WINED3DTA_CURRENT;
1320 This->textureState[i][WINED3DTSS_ALPHAARG0 ] = WINED3DTA_CURRENT;
1321 This->textureState[i][WINED3DTSS_RESULTARG ] = WINED3DTA_CURRENT;
1323 This->lowest_disabled_stage = 1;
1325 /* Sampler states*/
1326 for (i = 0 ; i < MAX_COMBINED_SAMPLERS; i++) {
1327 TRACE("Setting up default samplers states for sampler %d\n", i);
1328 This->samplerState[i][WINED3DSAMP_ADDRESSU ] = WINED3DTADDRESS_WRAP;
1329 This->samplerState[i][WINED3DSAMP_ADDRESSV ] = WINED3DTADDRESS_WRAP;
1330 This->samplerState[i][WINED3DSAMP_ADDRESSW ] = WINED3DTADDRESS_WRAP;
1331 This->samplerState[i][WINED3DSAMP_BORDERCOLOR ] = 0x00;
1332 This->samplerState[i][WINED3DSAMP_MAGFILTER ] = WINED3DTEXF_POINT;
1333 This->samplerState[i][WINED3DSAMP_MINFILTER ] = WINED3DTEXF_POINT;
1334 This->samplerState[i][WINED3DSAMP_MIPFILTER ] = WINED3DTEXF_NONE;
1335 This->samplerState[i][WINED3DSAMP_MIPMAPLODBIAS ] = 0;
1336 This->samplerState[i][WINED3DSAMP_MAXMIPLEVEL ] = 0;
1337 This->samplerState[i][WINED3DSAMP_MAXANISOTROPY ] = 1;
1338 This->samplerState[i][WINED3DSAMP_SRGBTEXTURE ] = 0;
1339 This->samplerState[i][WINED3DSAMP_ELEMENTINDEX ] = 0; /* TODO: Indicates which element of a multielement texture to use */
1340 This->samplerState[i][WINED3DSAMP_DMAPOFFSET ] = 0; /* TODO: Vertex offset in the presampled displacement map */
1343 for(i = 0; i < GL_LIMITS(textures); i++) {
1344 /* Note: This avoids calling SetTexture, so pretend it has been called */
1345 This->changed.textures |= 1 << i;
1346 This->textures[i] = NULL;
1349 /* check the return values, because the GetBackBuffer call isn't valid for ddraw */
1350 hr = IWineD3DDevice_GetSwapChain(device, 0, &swapchain);
1351 if( hr == WINED3D_OK && swapchain != NULL) {
1352 WINED3DVIEWPORT vp;
1354 hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer);
1355 if (SUCCEEDED(hr) && backbuffer)
1357 WINED3DSURFACE_DESC desc;
1358 RECT scissorrect;
1360 IWineD3DSurface_GetDesc(backbuffer, &desc);
1361 IWineD3DSurface_Release(backbuffer);
1363 /* Set the default scissor rect values */
1364 scissorrect.left = 0;
1365 scissorrect.right = desc.width;
1366 scissorrect.top = 0;
1367 scissorrect.bottom = desc.height;
1368 hr = IWineD3DDevice_SetScissorRect(device, &scissorrect);
1369 if (FAILED(hr)) ERR("This should never happen, expect rendering issues!\n");
1372 /* Set the default viewport */
1373 vp.X = 0;
1374 vp.Y = 0;
1375 vp.Width = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferWidth;
1376 vp.Height = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferHeight;
1377 vp.MinZ = 0.0f;
1378 vp.MaxZ = 1.0f;
1379 IWineD3DDevice_SetViewport(device, &vp);
1381 IWineD3DSwapChain_Release(swapchain);
1384 TRACE("-----------------------> Device defaults now set up...\n");
1385 return WINED3D_OK;
1388 /**********************************************************
1389 * IWineD3DStateBlock VTbl follows
1390 **********************************************************/
1392 static const IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl =
1394 /* IUnknown */
1395 IWineD3DStateBlockImpl_QueryInterface,
1396 IWineD3DStateBlockImpl_AddRef,
1397 IWineD3DStateBlockImpl_Release,
1398 /* IWineD3DStateBlock */
1399 IWineD3DStateBlockImpl_GetParent,
1400 IWineD3DStateBlockImpl_GetDevice,
1401 IWineD3DStateBlockImpl_Capture,
1402 IWineD3DStateBlockImpl_Apply,
1403 IWineD3DStateBlockImpl_InitStartupStateBlock
1406 HRESULT stateblock_init(IWineD3DStateBlockImpl *stateblock, IWineD3DDeviceImpl *device,
1407 WINED3DSTATEBLOCKTYPE type, IUnknown *parent)
1409 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1410 unsigned int i, j;
1411 HRESULT hr;
1413 stateblock->lpVtbl = &IWineD3DStateBlock_Vtbl;
1414 stateblock->ref = 1;
1415 stateblock->parent = parent;
1416 stateblock->wineD3DDevice = device;
1417 stateblock->blockType = type;
1419 for (i = 0; i < LIGHTMAP_SIZE; i++)
1421 list_init(&stateblock->lightMap[i]);
1424 hr = stateblock_allocate_shader_constants(stateblock);
1425 if (FAILED(hr)) return hr;
1427 /* The WINED3DSBT_INIT stateblock type is used during initialization to
1428 * produce a placeholder stateblock so other functions called can update a
1429 * state block. */
1430 if (type == WINED3DSBT_INIT || type == WINED3DSBT_RECORDED) return WINED3D_OK;
1432 /* Otherwise, might as well set the whole state block to the appropriate values */
1433 if (device->stateBlock)
1435 /* Saved values */
1436 stateblock_copy_values(stateblock, device->stateBlock, gl_info);
1438 else
1440 memset(stateblock->streamFreq, 1, sizeof(stateblock->streamFreq));
1443 TRACE("Updating changed flags appropriate for type %#x.\n", type);
1445 if (type == WINED3DSBT_ALL)
1447 TRACE("ALL => Pretend everything has changed.\n");
1449 stateblock_savedstates_set(&stateblock->changed, gl_info);
1450 stateblock_init_contained_states(stateblock);
1452 /* Lights are not part of the changed / set structure. */
1453 for (i = 0; i < LIGHTMAP_SIZE; ++i)
1455 struct list *e;
1456 LIST_FOR_EACH(e, &stateblock->lightMap[i])
1458 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
1459 light->changed = TRUE;
1460 light->enabledChanged = TRUE;
1464 for (i = 0; i < MAX_STREAMS; ++i)
1466 if (stateblock->streamSource[i]) IWineD3DBuffer_AddRef(stateblock->streamSource[i]);
1469 if (stateblock->pIndexData) IWineD3DBuffer_AddRef(stateblock->pIndexData);
1470 if (stateblock->vertexShader) IWineD3DVertexShader_AddRef(stateblock->vertexShader);
1471 if (stateblock->pixelShader) IWineD3DPixelShader_AddRef(stateblock->pixelShader);
1473 else if (type == WINED3DSBT_PIXELSTATE)
1475 TRACE("PIXELSTATE => Pretend all pixel states have changed.\n");
1477 /* Pixel Shader Constants. */
1478 for (i = 0; i < gl_info->max_pshader_constantsF; ++i)
1480 stateblock->contained_ps_consts_f[i] = i;
1481 stateblock->changed.pixelShaderConstantsF[i] = TRUE;
1483 stateblock->num_contained_ps_consts_f = gl_info->max_pshader_constantsF;
1485 for (i = 0; i < MAX_CONST_B; ++i)
1487 stateblock->contained_ps_consts_b[i] = i;
1488 stateblock->changed.pixelShaderConstantsB |= (1 << i);
1490 stateblock->num_contained_ps_consts_b = MAX_CONST_B;
1492 for (i = 0; i < MAX_CONST_I; ++i)
1494 stateblock->contained_ps_consts_i[i] = i;
1495 stateblock->changed.pixelShaderConstantsI |= (1 << i);
1497 stateblock->num_contained_ps_consts_i = MAX_CONST_I;
1499 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++)
1501 DWORD rs = SavedPixelStates_R[i];
1502 stateblock->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
1503 stateblock->contained_render_states[i] = rs;
1505 stateblock->num_contained_render_states = NUM_SAVEDPIXELSTATES_R;
1507 for (i = 0; i < MAX_TEXTURES; ++i)
1509 for (j = 0; j < NUM_SAVEDPIXELSTATES_T; ++j)
1511 DWORD state = SavedPixelStates_T[j];
1512 stateblock->changed.textureState[i] |= 1 << state;
1513 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
1514 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = state;
1515 ++stateblock->num_contained_tss_states;
1519 for (i = 0 ; i < MAX_COMBINED_SAMPLERS; ++i)
1521 for (j = 0; j < NUM_SAVEDPIXELSTATES_S; ++j)
1523 DWORD state = SavedPixelStates_S[j];
1524 stateblock->changed.samplerState[i] |= 1 << state;
1525 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
1526 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = state;
1527 stateblock->num_contained_sampler_states++;
1531 stateblock->changed.pixelShader = TRUE;
1532 if (stateblock->pixelShader) IWineD3DPixelShader_AddRef(stateblock->pixelShader);
1534 /* Pixel state blocks do not contain vertex buffers. Set them to NULL
1535 * to avoid wrong refcounting on them. This makes releasing the buffer
1536 * easier. */
1537 for (i = 0; i < MAX_STREAMS; ++i)
1539 stateblock->streamSource[i] = NULL;
1541 stateblock->pIndexData = NULL;
1542 stateblock->vertexShader = NULL;
1544 else if (type == WINED3DSBT_VERTEXSTATE)
1546 TRACE("VERTEXSTATE => Pretend all vertex shates have changed.\n");
1548 /* Vertex Shader Constants. */
1549 for (i = 0; i < gl_info->max_vshader_constantsF; ++i)
1551 stateblock->changed.vertexShaderConstantsF[i] = TRUE;
1552 stateblock->contained_vs_consts_f[i] = i;
1554 stateblock->num_contained_vs_consts_f = gl_info->max_vshader_constantsF;
1556 for (i = 0; i < MAX_CONST_B; ++i)
1558 stateblock->contained_vs_consts_b[i] = i;
1559 stateblock->changed.vertexShaderConstantsB |= (1 << i);
1561 stateblock->num_contained_vs_consts_b = MAX_CONST_B;
1563 for (i = 0; i < MAX_CONST_I; ++i)
1565 stateblock->contained_vs_consts_i[i] = i;
1566 stateblock->changed.vertexShaderConstantsI |= (1 << i);
1568 stateblock->num_contained_vs_consts_i = MAX_CONST_I;
1570 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++)
1572 DWORD rs = SavedVertexStates_R[i];
1573 stateblock->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f);
1574 stateblock->contained_render_states[i] = rs;
1576 stateblock->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R;
1578 for (i = 0; i < MAX_TEXTURES; ++i)
1580 for (j = 0; j < NUM_SAVEDVERTEXSTATES_T; ++j)
1582 DWORD state = SavedVertexStates_T[j];
1583 stateblock->changed.textureState[i] |= 1 << state;
1584 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
1585 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = state;
1586 ++stateblock->num_contained_tss_states;
1590 for (i = 0 ; i < MAX_COMBINED_SAMPLERS; ++i)
1592 for (j = 0; j < NUM_SAVEDVERTEXSTATES_S; ++j)
1594 DWORD state = SavedVertexStates_S[j];
1595 stateblock->changed.samplerState[i] |= 1 << state;
1596 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
1597 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = state;
1598 ++stateblock->num_contained_sampler_states;
1602 for (i = 0; i < LIGHTMAP_SIZE; ++i)
1604 struct list *e;
1605 LIST_FOR_EACH(e, &stateblock->lightMap[i])
1607 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
1608 light->changed = TRUE;
1609 light->enabledChanged = TRUE;
1613 for (i = 0; i < MAX_STREAMS; ++i)
1615 if (stateblock->streamSource[i]) IWineD3DBuffer_AddRef(stateblock->streamSource[i]);
1618 stateblock->changed.vertexShader = TRUE;
1619 if (stateblock->vertexShader) IWineD3DVertexShader_AddRef(stateblock->vertexShader);
1621 stateblock->pIndexData = NULL;
1622 stateblock->pixelShader = NULL;
1624 else
1626 FIXME("Unrecognized state block type %#x.\n", type);
1629 return WINED3D_OK;