[D3D8][D3D9][DDRAW][WINED3D] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / reactos / dll / directx / wine / wined3d / stateblock.c
1 /*
2 * state block implementation
3 *
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
9 *
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.
14 *
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.
19 *
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
23 */
24
25 #include "wined3d_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28
29 static const DWORD pixel_states_render[] =
30 {
31 WINED3D_RS_ALPHABLENDENABLE,
32 WINED3D_RS_ALPHAFUNC,
33 WINED3D_RS_ALPHAREF,
34 WINED3D_RS_ALPHATESTENABLE,
35 WINED3D_RS_ANTIALIASEDLINEENABLE,
36 WINED3D_RS_BLENDFACTOR,
37 WINED3D_RS_BLENDOP,
38 WINED3D_RS_BLENDOPALPHA,
39 WINED3D_RS_CCW_STENCILFAIL,
40 WINED3D_RS_CCW_STENCILPASS,
41 WINED3D_RS_CCW_STENCILZFAIL,
42 WINED3D_RS_COLORWRITEENABLE,
43 WINED3D_RS_COLORWRITEENABLE1,
44 WINED3D_RS_COLORWRITEENABLE2,
45 WINED3D_RS_COLORWRITEENABLE3,
46 WINED3D_RS_DEPTHBIAS,
47 WINED3D_RS_DESTBLEND,
48 WINED3D_RS_DESTBLENDALPHA,
49 WINED3D_RS_DITHERENABLE,
50 WINED3D_RS_FILLMODE,
51 WINED3D_RS_FOGDENSITY,
52 WINED3D_RS_FOGEND,
53 WINED3D_RS_FOGSTART,
54 WINED3D_RS_LASTPIXEL,
55 WINED3D_RS_SCISSORTESTENABLE,
56 WINED3D_RS_SEPARATEALPHABLENDENABLE,
57 WINED3D_RS_SHADEMODE,
58 WINED3D_RS_SLOPESCALEDEPTHBIAS,
59 WINED3D_RS_SRCBLEND,
60 WINED3D_RS_SRCBLENDALPHA,
61 WINED3D_RS_SRGBWRITEENABLE,
62 WINED3D_RS_STENCILENABLE,
63 WINED3D_RS_STENCILFAIL,
64 WINED3D_RS_STENCILFUNC,
65 WINED3D_RS_STENCILMASK,
66 WINED3D_RS_STENCILPASS,
67 WINED3D_RS_STENCILREF,
68 WINED3D_RS_STENCILWRITEMASK,
69 WINED3D_RS_STENCILZFAIL,
70 WINED3D_RS_TEXTUREFACTOR,
71 WINED3D_RS_TWOSIDEDSTENCILMODE,
72 WINED3D_RS_WRAP0,
73 WINED3D_RS_WRAP1,
74 WINED3D_RS_WRAP10,
75 WINED3D_RS_WRAP11,
76 WINED3D_RS_WRAP12,
77 WINED3D_RS_WRAP13,
78 WINED3D_RS_WRAP14,
79 WINED3D_RS_WRAP15,
80 WINED3D_RS_WRAP2,
81 WINED3D_RS_WRAP3,
82 WINED3D_RS_WRAP4,
83 WINED3D_RS_WRAP5,
84 WINED3D_RS_WRAP6,
85 WINED3D_RS_WRAP7,
86 WINED3D_RS_WRAP8,
87 WINED3D_RS_WRAP9,
88 WINED3D_RS_ZENABLE,
89 WINED3D_RS_ZFUNC,
90 WINED3D_RS_ZWRITEENABLE,
91 };
92
93 static const DWORD pixel_states_texture[] =
94 {
95 WINED3D_TSS_ALPHA_ARG0,
96 WINED3D_TSS_ALPHA_ARG1,
97 WINED3D_TSS_ALPHA_ARG2,
98 WINED3D_TSS_ALPHA_OP,
99 WINED3D_TSS_BUMPENV_LOFFSET,
100 WINED3D_TSS_BUMPENV_LSCALE,
101 WINED3D_TSS_BUMPENV_MAT00,
102 WINED3D_TSS_BUMPENV_MAT01,
103 WINED3D_TSS_BUMPENV_MAT10,
104 WINED3D_TSS_BUMPENV_MAT11,
105 WINED3D_TSS_COLOR_ARG0,
106 WINED3D_TSS_COLOR_ARG1,
107 WINED3D_TSS_COLOR_ARG2,
108 WINED3D_TSS_COLOR_OP,
109 WINED3D_TSS_RESULT_ARG,
110 WINED3D_TSS_TEXCOORD_INDEX,
111 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
112 };
113
114 static const DWORD pixel_states_sampler[] =
115 {
116 WINED3D_SAMP_ADDRESS_U,
117 WINED3D_SAMP_ADDRESS_V,
118 WINED3D_SAMP_ADDRESS_W,
119 WINED3D_SAMP_BORDER_COLOR,
120 WINED3D_SAMP_MAG_FILTER,
121 WINED3D_SAMP_MIN_FILTER,
122 WINED3D_SAMP_MIP_FILTER,
123 WINED3D_SAMP_MIPMAP_LOD_BIAS,
124 WINED3D_SAMP_MAX_MIP_LEVEL,
125 WINED3D_SAMP_MAX_ANISOTROPY,
126 WINED3D_SAMP_SRGB_TEXTURE,
127 WINED3D_SAMP_ELEMENT_INDEX,
128 };
129
130 static const DWORD vertex_states_render[] =
131 {
132 WINED3D_RS_ADAPTIVETESS_W,
133 WINED3D_RS_ADAPTIVETESS_X,
134 WINED3D_RS_ADAPTIVETESS_Y,
135 WINED3D_RS_ADAPTIVETESS_Z,
136 WINED3D_RS_AMBIENT,
137 WINED3D_RS_AMBIENTMATERIALSOURCE,
138 WINED3D_RS_CLIPPING,
139 WINED3D_RS_CLIPPLANEENABLE,
140 WINED3D_RS_COLORVERTEX,
141 WINED3D_RS_CULLMODE,
142 WINED3D_RS_DIFFUSEMATERIALSOURCE,
143 WINED3D_RS_EMISSIVEMATERIALSOURCE,
144 WINED3D_RS_ENABLEADAPTIVETESSELLATION,
145 WINED3D_RS_FOGCOLOR,
146 WINED3D_RS_FOGDENSITY,
147 WINED3D_RS_FOGENABLE,
148 WINED3D_RS_FOGEND,
149 WINED3D_RS_FOGSTART,
150 WINED3D_RS_FOGTABLEMODE,
151 WINED3D_RS_FOGVERTEXMODE,
152 WINED3D_RS_INDEXEDVERTEXBLENDENABLE,
153 WINED3D_RS_LIGHTING,
154 WINED3D_RS_LOCALVIEWER,
155 WINED3D_RS_MAXTESSELLATIONLEVEL,
156 WINED3D_RS_MINTESSELLATIONLEVEL,
157 WINED3D_RS_MULTISAMPLEANTIALIAS,
158 WINED3D_RS_MULTISAMPLEMASK,
159 WINED3D_RS_NORMALDEGREE,
160 WINED3D_RS_NORMALIZENORMALS,
161 WINED3D_RS_PATCHEDGESTYLE,
162 WINED3D_RS_POINTSCALE_A,
163 WINED3D_RS_POINTSCALE_B,
164 WINED3D_RS_POINTSCALE_C,
165 WINED3D_RS_POINTSCALEENABLE,
166 WINED3D_RS_POINTSIZE,
167 WINED3D_RS_POINTSIZE_MAX,
168 WINED3D_RS_POINTSIZE_MIN,
169 WINED3D_RS_POINTSPRITEENABLE,
170 WINED3D_RS_POSITIONDEGREE,
171 WINED3D_RS_RANGEFOGENABLE,
172 WINED3D_RS_SHADEMODE,
173 WINED3D_RS_SPECULARENABLE,
174 WINED3D_RS_SPECULARMATERIALSOURCE,
175 WINED3D_RS_TWEENFACTOR,
176 WINED3D_RS_VERTEXBLEND,
177 };
178
179 static const DWORD vertex_states_texture[] =
180 {
181 WINED3D_TSS_TEXCOORD_INDEX,
182 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
183 };
184
185 static const DWORD vertex_states_sampler[] =
186 {
187 WINED3D_SAMP_DMAP_OFFSET,
188 };
189
190 /* Allocates the correct amount of space for pixel and vertex shader constants,
191 * along with their set/changed flags on the given stateblock object
192 */
193 static HRESULT stateblock_allocate_shader_constants(struct wined3d_stateblock *object)
194 {
195 const struct wined3d_d3d_info *d3d_info = &object->device->adapter->d3d_info;
196
197 object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
198 sizeof(BOOL) * d3d_info->limits.ps_uniform_count);
199 if (!object->changed.pixelShaderConstantsF) goto fail;
200
201 object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
202 sizeof(BOOL) * d3d_info->limits.vs_uniform_count);
203 if (!object->changed.vertexShaderConstantsF) goto fail;
204
205 object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0,
206 sizeof(DWORD) * d3d_info->limits.vs_uniform_count);
207 if (!object->contained_vs_consts_f) goto fail;
208
209 object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0,
210 sizeof(DWORD) * d3d_info->limits.ps_uniform_count);
211 if (!object->contained_ps_consts_f) goto fail;
212
213 return WINED3D_OK;
214
215 fail:
216 ERR("Failed to allocate memory\n");
217 HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
218 HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
219 HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
220 HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
221 return E_OUTOFMEMORY;
222 }
223
224 static inline void stateblock_set_bits(DWORD *map, UINT map_size)
225 {
226 DWORD mask = (1u << (map_size & 0x1f)) - 1;
227 memset(map, 0xff, (map_size >> 5) * sizeof(*map));
228 if (mask) map[map_size >> 5] = mask;
229 }
230
231 /* Set all members of a stateblock savedstate to the given value */
232 static void stateblock_savedstates_set_all(struct wined3d_saved_states *states, DWORD vs_consts, DWORD ps_consts)
233 {
234 unsigned int i;
235
236 /* Single values */
237 states->primitive_type = 1;
238 states->indices = 1;
239 states->material = 1;
240 states->viewport = 1;
241 states->vertexDecl = 1;
242 states->pixelShader = 1;
243 states->vertexShader = 1;
244 states->scissorRect = 1;
245
246 /* Fixed size arrays */
247 states->streamSource = 0xffff;
248 states->streamFreq = 0xffff;
249 states->textures = 0xfffff;
250 stateblock_set_bits(states->transform, HIGHEST_TRANSFORMSTATE + 1);
251 stateblock_set_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
252 for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
253 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3ffe;
254 states->clipplane = 0xffffffff;
255 states->pixelShaderConstantsB = 0xffff;
256 states->pixelShaderConstantsI = 0xffff;
257 states->vertexShaderConstantsB = 0xffff;
258 states->vertexShaderConstantsI = 0xffff;
259
260 /* Dynamically sized arrays */
261 memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * ps_consts);
262 memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * vs_consts);
263 }
264
265 static void stateblock_savedstates_set_pixel(struct wined3d_saved_states *states, const DWORD num_constants)
266 {
267 DWORD texture_mask = 0;
268 WORD sampler_mask = 0;
269 unsigned int i;
270
271 states->pixelShader = 1;
272
273 for (i = 0; i < sizeof(pixel_states_render) / sizeof(*pixel_states_render); ++i)
274 {
275 DWORD rs = pixel_states_render[i];
276 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
277 }
278
279 for (i = 0; i < sizeof(pixel_states_texture) / sizeof(*pixel_states_texture); ++i)
280 texture_mask |= 1u << pixel_states_texture[i];
281 for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
282 for (i = 0; i < sizeof(pixel_states_sampler) / sizeof(*pixel_states_sampler); ++i)
283 sampler_mask |= 1u << pixel_states_sampler[i];
284 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
285 states->pixelShaderConstantsB = 0xffff;
286 states->pixelShaderConstantsI = 0xffff;
287
288 memset(states->pixelShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
289 }
290
291 static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *states, const DWORD num_constants)
292 {
293 DWORD texture_mask = 0;
294 WORD sampler_mask = 0;
295 unsigned int i;
296
297 states->vertexDecl = 1;
298 states->vertexShader = 1;
299
300 for (i = 0; i < sizeof(vertex_states_render) / sizeof(*vertex_states_render); ++i)
301 {
302 DWORD rs = vertex_states_render[i];
303 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
304 }
305
306 for (i = 0; i < sizeof(vertex_states_texture) / sizeof(*vertex_states_texture); ++i)
307 texture_mask |= 1u << vertex_states_texture[i];
308 for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
309 for (i = 0; i < sizeof(vertex_states_sampler) / sizeof(*vertex_states_sampler); ++i)
310 sampler_mask |= 1u << vertex_states_sampler[i];
311 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
312 states->vertexShaderConstantsB = 0xffff;
313 states->vertexShaderConstantsI = 0xffff;
314
315 memset(states->vertexShaderConstantsF, TRUE, sizeof(BOOL) * num_constants);
316 }
317
318 void stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
319 {
320 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
321 unsigned int i, j;
322
323 for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
324 {
325 DWORD map = stateblock->changed.renderState[i];
326 for (j = 0; map; map >>= 1, ++j)
327 {
328 if (!(map & 1)) continue;
329
330 stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
331 ++stateblock->num_contained_render_states;
332 }
333 }
334
335 for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i)
336 {
337 DWORD map = stateblock->changed.transform[i];
338 for (j = 0; map; map >>= 1, ++j)
339 {
340 if (!(map & 1)) continue;
341
342 stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
343 ++stateblock->num_contained_transform_states;
344 }
345 }
346
347 for (i = 0; i < d3d_info->limits.vs_uniform_count; ++i)
348 {
349 if (stateblock->changed.vertexShaderConstantsF[i])
350 {
351 stateblock->contained_vs_consts_f[stateblock->num_contained_vs_consts_f] = i;
352 ++stateblock->num_contained_vs_consts_f;
353 }
354 }
355
356 for (i = 0; i < MAX_CONST_I; ++i)
357 {
358 if (stateblock->changed.vertexShaderConstantsI & (1u << i))
359 {
360 stateblock->contained_vs_consts_i[stateblock->num_contained_vs_consts_i] = i;
361 ++stateblock->num_contained_vs_consts_i;
362 }
363 }
364
365 for (i = 0; i < MAX_CONST_B; ++i)
366 {
367 if (stateblock->changed.vertexShaderConstantsB & (1u << i))
368 {
369 stateblock->contained_vs_consts_b[stateblock->num_contained_vs_consts_b] = i;
370 ++stateblock->num_contained_vs_consts_b;
371 }
372 }
373
374 for (i = 0; i < d3d_info->limits.ps_uniform_count; ++i)
375 {
376 if (stateblock->changed.pixelShaderConstantsF[i])
377 {
378 stateblock->contained_ps_consts_f[stateblock->num_contained_ps_consts_f] = i;
379 ++stateblock->num_contained_ps_consts_f;
380 }
381 }
382
383 for (i = 0; i < MAX_CONST_I; ++i)
384 {
385 if (stateblock->changed.pixelShaderConstantsI & (1u << i))
386 {
387 stateblock->contained_ps_consts_i[stateblock->num_contained_ps_consts_i] = i;
388 ++stateblock->num_contained_ps_consts_i;
389 }
390 }
391
392 for (i = 0; i < MAX_CONST_B; ++i)
393 {
394 if (stateblock->changed.pixelShaderConstantsB & (1u << i))
395 {
396 stateblock->contained_ps_consts_b[stateblock->num_contained_ps_consts_b] = i;
397 ++stateblock->num_contained_ps_consts_b;
398 }
399 }
400
401 for (i = 0; i < MAX_TEXTURES; ++i)
402 {
403 DWORD map = stateblock->changed.textureState[i];
404
405 for(j = 0; map; map >>= 1, ++j)
406 {
407 if (!(map & 1)) continue;
408
409 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
410 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
411 ++stateblock->num_contained_tss_states;
412 }
413 }
414
415 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
416 {
417 DWORD map = stateblock->changed.samplerState[i];
418
419 for (j = 0; map; map >>= 1, ++j)
420 {
421 if (!(map & 1)) continue;
422
423 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
424 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
425 ++stateblock->num_contained_sampler_states;
426 }
427 }
428 }
429
430 static void stateblock_init_lights(struct wined3d_stateblock *stateblock, struct list *light_map)
431 {
432 unsigned int i;
433
434 for (i = 0; i < LIGHTMAP_SIZE; ++i)
435 {
436 const struct wined3d_light_info *src_light;
437
438 LIST_FOR_EACH_ENTRY(src_light, &light_map[i], struct wined3d_light_info, entry)
439 {
440 struct wined3d_light_info *dst_light = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_light));
441
442 *dst_light = *src_light;
443 list_add_tail(&stateblock->state.light_map[i], &dst_light->entry);
444 }
445 }
446 }
447
448 ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
449 {
450 ULONG refcount = InterlockedIncrement(&stateblock->ref);
451
452 TRACE("%p increasing refcount to %u.\n", stateblock, refcount);
453
454 return refcount;
455 }
456
457 void state_unbind_resources(struct wined3d_state *state)
458 {
459 struct wined3d_shader_resource_view *srv;
460 struct wined3d_vertex_declaration *decl;
461 struct wined3d_sampler *sampler;
462 struct wined3d_texture *texture;
463 struct wined3d_buffer *buffer;
464 struct wined3d_shader *shader;
465 #if defined(STAGING_CSMT)
466 struct wined3d_rendertarget_view *view;
467 #endif /* STAGING_CSMT */
468 unsigned int i, j;
469
470 if ((decl = state->vertex_declaration))
471 {
472 state->vertex_declaration = NULL;
473 wined3d_vertex_declaration_decref(decl);
474 }
475
476 for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
477 {
478 if ((texture = state->textures[i]))
479 {
480 state->textures[i] = NULL;
481 wined3d_texture_decref(texture);
482 }
483 }
484
485 for (i = 0; i < MAX_STREAM_OUT; ++i)
486 {
487 if ((buffer = state->stream_output[i].buffer))
488 {
489 state->stream_output[i].buffer = NULL;
490 wined3d_buffer_decref(buffer);
491 }
492 }
493
494 for (i = 0; i < MAX_STREAMS; ++i)
495 {
496 if ((buffer = state->streams[i].buffer))
497 {
498 state->streams[i].buffer = NULL;
499 wined3d_buffer_decref(buffer);
500 }
501 }
502
503 if ((buffer = state->index_buffer))
504 {
505 state->index_buffer = NULL;
506 wined3d_buffer_decref(buffer);
507 }
508
509 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
510 {
511 if ((shader = state->shader[i]))
512 {
513 state->shader[i] = NULL;
514 wined3d_shader_decref(shader);
515 }
516
517 for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
518 {
519 if ((buffer = state->cb[i][j]))
520 {
521 state->cb[i][j] = NULL;
522 wined3d_buffer_decref(buffer);
523 }
524 }
525
526 for (j = 0; j < MAX_SAMPLER_OBJECTS; ++j)
527 {
528 if ((sampler = state->sampler[i][j]))
529 {
530 state->sampler[i][j] = NULL;
531 wined3d_sampler_decref(sampler);
532 }
533 }
534
535 for (j = 0; j < MAX_SHADER_RESOURCE_VIEWS; ++j)
536 {
537 if ((srv = state->shader_resource_view[i][j]))
538 {
539 state->shader_resource_view[i][j] = NULL;
540 wined3d_shader_resource_view_decref(srv);
541 }
542 }
543 }
544 #if defined(STAGING_CSMT)
545
546 if (state->fb.depth_stencil)
547 {
548 view = state->fb.depth_stencil;
549
550 TRACE("Releasing depth/stencil buffer %p.\n", view);
551
552 state->fb.depth_stencil = NULL;
553 wined3d_rendertarget_view_decref(view);
554 }
555
556 if (state->fb.render_targets)
557 {
558 for (i = 0; i < state->fb.rt_size; i++)
559 {
560 view = state->fb.render_targets[i];
561 TRACE("Setting rendertarget %u to NULL\n", i);
562 state->fb.render_targets[i] = NULL;
563 if (view)
564 {
565 TRACE("Releasing the rendertarget view at %p\n", view);
566 wined3d_rendertarget_view_decref(view);
567 }
568 }
569 }
570 #endif /* STAGING_CSMT */
571 }
572
573 void state_cleanup(struct wined3d_state *state)
574 {
575 unsigned int counter;
576
577 if (!(state->flags & WINED3D_STATE_NO_REF))
578 state_unbind_resources(state);
579
580 for (counter = 0; counter < MAX_ACTIVE_LIGHTS; ++counter)
581 {
582 state->lights[counter] = NULL;
583 }
584
585 for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
586 {
587 struct list *e1, *e2;
588 LIST_FOR_EACH_SAFE(e1, e2, &state->light_map[counter])
589 {
590 struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
591 list_remove(&light->entry);
592 HeapFree(GetProcessHeap(), 0, light);
593 }
594 }
595
596 HeapFree(GetProcessHeap(), 0, state->vs_consts_f);
597 HeapFree(GetProcessHeap(), 0, state->ps_consts_f);
598 #if defined(STAGING_CSMT)
599 HeapFree(GetProcessHeap(), 0, state->fb.render_targets);
600 #endif /* STAGING_CSMT */
601 }
602
603 ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
604 {
605 ULONG refcount = InterlockedDecrement(&stateblock->ref);
606
607 TRACE("%p decreasing refcount to %u\n", stateblock, refcount);
608
609 if (!refcount)
610 {
611 state_cleanup(&stateblock->state);
612
613 HeapFree(GetProcessHeap(), 0, stateblock->changed.vertexShaderConstantsF);
614 HeapFree(GetProcessHeap(), 0, stateblock->changed.pixelShaderConstantsF);
615 HeapFree(GetProcessHeap(), 0, stateblock->contained_vs_consts_f);
616 HeapFree(GetProcessHeap(), 0, stateblock->contained_ps_consts_f);
617 HeapFree(GetProcessHeap(), 0, stateblock);
618 }
619
620 return refcount;
621 }
622
623 static void wined3d_state_record_lights(struct wined3d_state *dst_state, const struct wined3d_state *src_state)
624 {
625 UINT i;
626
627 /* Lights... For a recorded state block, we just had a chain of actions
628 * to perform, so we need to walk that chain and update any actions which
629 * differ. */
630 for (i = 0; i < LIGHTMAP_SIZE; ++i)
631 {
632 struct list *e, *f;
633 LIST_FOR_EACH(e, &dst_state->light_map[i])
634 {
635 BOOL updated = FALSE;
636 struct wined3d_light_info *src = LIST_ENTRY(e, struct wined3d_light_info, entry), *realLight;
637
638 /* Look up the light in the destination */
639 LIST_FOR_EACH(f, &src_state->light_map[i])
640 {
641 realLight = LIST_ENTRY(f, struct wined3d_light_info, entry);
642 if (realLight->OriginalIndex == src->OriginalIndex)
643 {
644 src->OriginalParms = realLight->OriginalParms;
645
646 if (realLight->glIndex == -1 && src->glIndex != -1)
647 {
648 /* Light disabled */
649 dst_state->lights[src->glIndex] = NULL;
650 }
651 else if (realLight->glIndex != -1 && src->glIndex == -1)
652 {
653 /* Light enabled */
654 dst_state->lights[realLight->glIndex] = src;
655 }
656 src->glIndex = realLight->glIndex;
657 updated = TRUE;
658 break;
659 }
660 }
661
662 if (!updated)
663 {
664 /* This can happen if the light was originally created as a
665 * default light for SetLightEnable() while recording. */
666 WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
667 src->OriginalIndex, dst_state, src_state);
668
669 src->OriginalParms = WINED3D_default_light;
670 if (src->glIndex != -1)
671 {
672 dst_state->lights[src->glIndex] = NULL;
673 src->glIndex = -1;
674 }
675 }
676 }
677 }
678 }
679
680 void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock)
681 {
682 const struct wined3d_state *src_state = &stateblock->device->state;
683 unsigned int i;
684 DWORD map;
685
686 TRACE("stateblock %p.\n", stateblock);
687
688 TRACE("Capturing state %p.\n", src_state);
689
690 if (stateblock->changed.vertexShader && stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]
691 != src_state->shader[WINED3D_SHADER_TYPE_VERTEX])
692 {
693 TRACE("Updating vertex shader from %p to %p\n",
694 stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX],
695 src_state->shader[WINED3D_SHADER_TYPE_VERTEX]);
696
697 if (src_state->shader[WINED3D_SHADER_TYPE_VERTEX])
698 wined3d_shader_incref(src_state->shader[WINED3D_SHADER_TYPE_VERTEX]);
699 if (stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX])
700 wined3d_shader_decref(stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]);
701 stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX] = src_state->shader[WINED3D_SHADER_TYPE_VERTEX];
702 }
703
704 /* Vertex shader float constants. */
705 for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i)
706 {
707 unsigned int idx = stateblock->contained_vs_consts_f[i];
708
709 TRACE("Setting vs_consts_f[%u] to {%.8e, %.8e, %.8e, %.8e}.\n", idx,
710 src_state->vs_consts_f[idx * 4 + 0],
711 src_state->vs_consts_f[idx * 4 + 1],
712 src_state->vs_consts_f[idx * 4 + 2],
713 src_state->vs_consts_f[idx * 4 + 3]);
714
715 stateblock->state.vs_consts_f[idx * 4 + 0] = src_state->vs_consts_f[idx * 4 + 0];
716 stateblock->state.vs_consts_f[idx * 4 + 1] = src_state->vs_consts_f[idx * 4 + 1];
717 stateblock->state.vs_consts_f[idx * 4 + 2] = src_state->vs_consts_f[idx * 4 + 2];
718 stateblock->state.vs_consts_f[idx * 4 + 3] = src_state->vs_consts_f[idx * 4 + 3];
719 }
720
721 /* Vertex shader integer constants. */
722 for (i = 0; i < stateblock->num_contained_vs_consts_i; ++i)
723 {
724 unsigned int idx = stateblock->contained_vs_consts_i[i];
725
726 TRACE("Setting vs_consts[%u] to {%d, %d, %d, %d}.\n", idx,
727 src_state->vs_consts_i[idx * 4 + 0],
728 src_state->vs_consts_i[idx * 4 + 1],
729 src_state->vs_consts_i[idx * 4 + 2],
730 src_state->vs_consts_i[idx * 4 + 3]);
731
732 stateblock->state.vs_consts_i[idx * 4 + 0] = src_state->vs_consts_i[idx * 4 + 0];
733 stateblock->state.vs_consts_i[idx * 4 + 1] = src_state->vs_consts_i[idx * 4 + 1];
734 stateblock->state.vs_consts_i[idx * 4 + 2] = src_state->vs_consts_i[idx * 4 + 2];
735 stateblock->state.vs_consts_i[idx * 4 + 3] = src_state->vs_consts_i[idx * 4 + 3];
736 }
737
738 /* Vertex shader boolean constants. */
739 for (i = 0; i < stateblock->num_contained_vs_consts_b; ++i)
740 {
741 unsigned int idx = stateblock->contained_vs_consts_b[i];
742
743 TRACE("Setting vs_consts_b[%u] to %s.\n",
744 idx, src_state->vs_consts_b[idx] ? "TRUE" : "FALSE");
745
746 stateblock->state.vs_consts_b[idx] = src_state->vs_consts_b[idx];
747 }
748
749 /* Pixel shader float constants. */
750 for (i = 0; i < stateblock->num_contained_ps_consts_f; ++i)
751 {
752 unsigned int idx = stateblock->contained_ps_consts_f[i];
753
754 TRACE("Setting ps_consts_f[%u] to {%.8e, %.8e, %.8e, %.8e}.\n", idx,
755 src_state->ps_consts_f[idx * 4 + 0],
756 src_state->ps_consts_f[idx * 4 + 1],
757 src_state->ps_consts_f[idx * 4 + 2],
758 src_state->ps_consts_f[idx * 4 + 3]);
759
760 stateblock->state.ps_consts_f[idx * 4 + 0] = src_state->ps_consts_f[idx * 4 + 0];
761 stateblock->state.ps_consts_f[idx * 4 + 1] = src_state->ps_consts_f[idx * 4 + 1];
762 stateblock->state.ps_consts_f[idx * 4 + 2] = src_state->ps_consts_f[idx * 4 + 2];
763 stateblock->state.ps_consts_f[idx * 4 + 3] = src_state->ps_consts_f[idx * 4 + 3];
764 }
765
766 /* Pixel shader integer constants. */
767 for (i = 0; i < stateblock->num_contained_ps_consts_i; ++i)
768 {
769 unsigned int idx = stateblock->contained_ps_consts_i[i];
770 TRACE("Setting ps_consts_i[%u] to {%d, %d, %d, %d}.\n", idx,
771 src_state->ps_consts_i[idx * 4 + 0],
772 src_state->ps_consts_i[idx * 4 + 1],
773 src_state->ps_consts_i[idx * 4 + 2],
774 src_state->ps_consts_i[idx * 4 + 3]);
775
776 stateblock->state.ps_consts_i[idx * 4 + 0] = src_state->ps_consts_i[idx * 4 + 0];
777 stateblock->state.ps_consts_i[idx * 4 + 1] = src_state->ps_consts_i[idx * 4 + 1];
778 stateblock->state.ps_consts_i[idx * 4 + 2] = src_state->ps_consts_i[idx * 4 + 2];
779 stateblock->state.ps_consts_i[idx * 4 + 3] = src_state->ps_consts_i[idx * 4 + 3];
780 }
781
782 /* Pixel shader boolean constants. */
783 for (i = 0; i < stateblock->num_contained_ps_consts_b; ++i)
784 {
785 unsigned int idx = stateblock->contained_ps_consts_b[i];
786 TRACE("Setting ps_consts_b[%u] to %s.\n",
787 idx, src_state->ps_consts_b[idx] ? "TRUE" : "FALSE");
788
789 stateblock->state.ps_consts_b[idx] = src_state->ps_consts_b[idx];
790 }
791
792 /* Others + Render & Texture */
793 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
794 {
795 enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
796
797 TRACE("Updating transform %#x.\n", transform);
798
799 stateblock->state.transforms[transform] = src_state->transforms[transform];
800 }
801
802 if (stateblock->changed.primitive_type)
803 stateblock->state.gl_primitive_type = src_state->gl_primitive_type;
804
805 if (stateblock->changed.indices
806 && ((stateblock->state.index_buffer != src_state->index_buffer)
807 || (stateblock->state.base_vertex_index != src_state->base_vertex_index)
808 || (stateblock->state.index_format != src_state->index_format)))
809 {
810 TRACE("Updating index buffer to %p, base vertex index to %d.\n",
811 src_state->index_buffer, src_state->base_vertex_index);
812
813 if (src_state->index_buffer)
814 wined3d_buffer_incref(src_state->index_buffer);
815 if (stateblock->state.index_buffer)
816 wined3d_buffer_decref(stateblock->state.index_buffer);
817 stateblock->state.index_buffer = src_state->index_buffer;
818 stateblock->state.base_vertex_index = src_state->base_vertex_index;
819 stateblock->state.index_format = src_state->index_format;
820 }
821
822 if (stateblock->changed.vertexDecl && stateblock->state.vertex_declaration != src_state->vertex_declaration)
823 {
824 TRACE("Updating vertex declaration from %p to %p.\n",
825 stateblock->state.vertex_declaration, src_state->vertex_declaration);
826
827 if (src_state->vertex_declaration)
828 wined3d_vertex_declaration_incref(src_state->vertex_declaration);
829 if (stateblock->state.vertex_declaration)
830 wined3d_vertex_declaration_decref(stateblock->state.vertex_declaration);
831 stateblock->state.vertex_declaration = src_state->vertex_declaration;
832 }
833
834 if (stateblock->changed.material
835 && memcmp(&src_state->material, &stateblock->state.material, sizeof(stateblock->state.material)))
836 {
837 TRACE("Updating material.\n");
838
839 stateblock->state.material = src_state->material;
840 }
841
842 if (stateblock->changed.viewport
843 && memcmp(&src_state->viewport, &stateblock->state.viewport, sizeof(stateblock->state.viewport)))
844 {
845 TRACE("Updating viewport.\n");
846
847 stateblock->state.viewport = src_state->viewport;
848 }
849
850 if (stateblock->changed.scissorRect && memcmp(&src_state->scissor_rect,
851 &stateblock->state.scissor_rect, sizeof(stateblock->state.scissor_rect)))
852 {
853 TRACE("Updating scissor rect.\n");
854
855 stateblock->state.scissor_rect = src_state->scissor_rect;
856 }
857
858 map = stateblock->changed.streamSource;
859 for (i = 0; map; map >>= 1, ++i)
860 {
861 if (!(map & 1)) continue;
862
863 if (stateblock->state.streams[i].stride != src_state->streams[i].stride
864 || stateblock->state.streams[i].buffer != src_state->streams[i].buffer)
865 {
866 TRACE("Updating stream source %u to %p, stride to %u.\n",
867 i, src_state->streams[i].buffer,
868 src_state->streams[i].stride);
869
870 stateblock->state.streams[i].stride = src_state->streams[i].stride;
871 if (src_state->streams[i].buffer)
872 wined3d_buffer_incref(src_state->streams[i].buffer);
873 if (stateblock->state.streams[i].buffer)
874 wined3d_buffer_decref(stateblock->state.streams[i].buffer);
875 stateblock->state.streams[i].buffer = src_state->streams[i].buffer;
876 }
877 }
878
879 map = stateblock->changed.streamFreq;
880 for (i = 0; map; map >>= 1, ++i)
881 {
882 if (!(map & 1)) continue;
883
884 if (stateblock->state.streams[i].frequency != src_state->streams[i].frequency
885 || stateblock->state.streams[i].flags != src_state->streams[i].flags)
886 {
887 TRACE("Updating stream frequency %u to %u flags to %#x.\n",
888 i, src_state->streams[i].frequency, src_state->streams[i].flags);
889
890 stateblock->state.streams[i].frequency = src_state->streams[i].frequency;
891 stateblock->state.streams[i].flags = src_state->streams[i].flags;
892 }
893 }
894
895 map = stateblock->changed.clipplane;
896 for (i = 0; map; map >>= 1, ++i)
897 {
898 if (!(map & 1)) continue;
899
900 if (memcmp(&stateblock->state.clip_planes[i], &src_state->clip_planes[i], sizeof(src_state->clip_planes[i])))
901 {
902 TRACE("Updating clipplane %u.\n", i);
903 stateblock->state.clip_planes[i] = src_state->clip_planes[i];
904 }
905 }
906
907 /* Render */
908 for (i = 0; i < stateblock->num_contained_render_states; ++i)
909 {
910 enum wined3d_render_state rs = stateblock->contained_render_states[i];
911
912 TRACE("Updating render state %#x to %u.\n", rs, src_state->render_states[rs]);
913
914 stateblock->state.render_states[rs] = src_state->render_states[rs];
915 }
916
917 /* Texture states */
918 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
919 {
920 DWORD stage = stateblock->contained_tss_states[i].stage;
921 DWORD state = stateblock->contained_tss_states[i].state;
922
923 TRACE("Updating texturestage state %u, %u to %#x (was %#x).\n", stage, state,
924 src_state->texture_states[stage][state], stateblock->state.texture_states[stage][state]);
925
926 stateblock->state.texture_states[stage][state] = src_state->texture_states[stage][state];
927 }
928
929 /* Samplers */
930 map = stateblock->changed.textures;
931 for (i = 0; map; map >>= 1, ++i)
932 {
933 if (!(map & 1)) continue;
934
935 TRACE("Updating texture %u to %p (was %p).\n",
936 i, src_state->textures[i], stateblock->state.textures[i]);
937
938 if (src_state->textures[i])
939 wined3d_texture_incref(src_state->textures[i]);
940 if (stateblock->state.textures[i])
941 wined3d_texture_decref(stateblock->state.textures[i]);
942 stateblock->state.textures[i] = src_state->textures[i];
943 }
944
945 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
946 {
947 DWORD stage = stateblock->contained_sampler_states[i].stage;
948 DWORD state = stateblock->contained_sampler_states[i].state;
949
950 TRACE("Updating sampler state %u, %u to %#x (was %#x).\n", stage, state,
951 src_state->sampler_states[stage][state], stateblock->state.sampler_states[stage][state]);
952
953 stateblock->state.sampler_states[stage][state] = src_state->sampler_states[stage][state];
954 }
955
956 if (stateblock->changed.pixelShader && stateblock->state.shader[WINED3D_SHADER_TYPE_PIXEL]
957 != src_state->shader[WINED3D_SHADER_TYPE_PIXEL])
958 {
959 if (src_state->shader[WINED3D_SHADER_TYPE_PIXEL])
960 wined3d_shader_incref(src_state->shader[WINED3D_SHADER_TYPE_PIXEL]);
961 if (stateblock->state.shader[WINED3D_SHADER_TYPE_PIXEL])
962 wined3d_shader_decref(stateblock->state.shader[WINED3D_SHADER_TYPE_PIXEL]);
963 stateblock->state.shader[WINED3D_SHADER_TYPE_PIXEL] = src_state->shader[WINED3D_SHADER_TYPE_PIXEL];
964 }
965
966 wined3d_state_record_lights(&stateblock->state, src_state);
967
968 TRACE("Capture done.\n");
969 }
970
971 static void apply_lights(struct wined3d_device *device, const struct wined3d_state *state)
972 {
973 UINT i;
974
975 for (i = 0; i < LIGHTMAP_SIZE; ++i)
976 {
977 struct list *e;
978
979 LIST_FOR_EACH(e, &state->light_map[i])
980 {
981 const struct wined3d_light_info *light = LIST_ENTRY(e, struct wined3d_light_info, entry);
982
983 wined3d_device_set_light(device, light->OriginalIndex, &light->OriginalParms);
984 wined3d_device_set_light_enable(device, light->OriginalIndex, light->glIndex != -1);
985 }
986 }
987 }
988
989 void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock)
990 {
991 struct wined3d_device *device = stateblock->device;
992 unsigned int i;
993 DWORD map;
994
995 TRACE("Applying stateblock %p to device %p.\n", stateblock, device);
996
997 if (stateblock->changed.vertexShader)
998 wined3d_device_set_vertex_shader(device, stateblock->state.shader[WINED3D_SHADER_TYPE_VERTEX]);
999
1000 /* Vertex Shader Constants. */
1001 for (i = 0; i < stateblock->num_contained_vs_consts_f; ++i)
1002 {
1003 wined3d_device_set_vs_consts_f(device, stateblock->contained_vs_consts_f[i],
1004 stateblock->state.vs_consts_f + stateblock->contained_vs_consts_f[i] * 4, 1);
1005 }
1006 for (i = 0; i < stateblock->num_contained_vs_consts_i; ++i)
1007 {
1008 wined3d_device_set_vs_consts_i(device, stateblock->contained_vs_consts_i[i],
1009 stateblock->state.vs_consts_i + stateblock->contained_vs_consts_i[i] * 4, 1);
1010 }
1011 for (i = 0; i < stateblock->num_contained_vs_consts_b; ++i)
1012 {
1013 wined3d_device_set_vs_consts_b(device, stateblock->contained_vs_consts_b[i],
1014 stateblock->state.vs_consts_b + stateblock->contained_vs_consts_b[i], 1);
1015 }
1016
1017 apply_lights(device, &stateblock->state);
1018
1019 if (stateblock->changed.pixelShader)
1020 wined3d_device_set_pixel_shader(device, stateblock->state.shader[WINED3D_SHADER_TYPE_PIXEL]);
1021
1022 /* Pixel Shader Constants. */
1023 for (i = 0; i < stateblock->num_contained_ps_consts_f; ++i)
1024 {
1025 wined3d_device_set_ps_consts_f(device, stateblock->contained_ps_consts_f[i],
1026 stateblock->state.ps_consts_f + stateblock->contained_ps_consts_f[i] * 4, 1);
1027 }
1028 for (i = 0; i < stateblock->num_contained_ps_consts_i; ++i)
1029 {
1030 wined3d_device_set_ps_consts_i(device, stateblock->contained_ps_consts_i[i],
1031 stateblock->state.ps_consts_i + stateblock->contained_ps_consts_i[i] * 4, 1);
1032 }
1033 for (i = 0; i < stateblock->num_contained_ps_consts_b; ++i)
1034 {
1035 wined3d_device_set_ps_consts_b(device, stateblock->contained_ps_consts_b[i],
1036 stateblock->state.ps_consts_b + stateblock->contained_ps_consts_b[i], 1);
1037 }
1038
1039 /* Render states. */
1040 for (i = 0; i < stateblock->num_contained_render_states; ++i)
1041 {
1042 wined3d_device_set_render_state(device, stateblock->contained_render_states[i],
1043 stateblock->state.render_states[stateblock->contained_render_states[i]]);
1044 }
1045
1046 /* Texture states. */
1047 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
1048 {
1049 DWORD stage = stateblock->contained_tss_states[i].stage;
1050 DWORD state = stateblock->contained_tss_states[i].state;
1051
1052 wined3d_device_set_texture_stage_state(device, stage, state, stateblock->state.texture_states[stage][state]);
1053 }
1054
1055 /* Sampler states. */
1056 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
1057 {
1058 DWORD stage = stateblock->contained_sampler_states[i].stage;
1059 DWORD state = stateblock->contained_sampler_states[i].state;
1060 DWORD value = stateblock->state.sampler_states[stage][state];
1061
1062 if (stage >= MAX_FRAGMENT_SAMPLERS) stage += WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS;
1063 wined3d_device_set_sampler_state(device, stage, state, value);
1064 }
1065
1066 /* Transform states. */
1067 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
1068 {
1069 wined3d_device_set_transform(device, stateblock->contained_transform_states[i],
1070 &stateblock->state.transforms[stateblock->contained_transform_states[i]]);
1071 }
1072
1073 if (stateblock->changed.primitive_type)
1074 {
1075 GLenum gl_primitive_type, prev;
1076
1077 if (device->recording)
1078 device->recording->changed.primitive_type = TRUE;
1079 gl_primitive_type = stateblock->state.gl_primitive_type;
1080 prev = device->update_state->gl_primitive_type;
1081 device->update_state->gl_primitive_type = gl_primitive_type;
1082 #if defined(STAGING_CSMT)
1083 if (gl_primitive_type != prev)
1084 wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type);
1085 #else /* STAGING_CSMT */
1086 if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS))
1087 device_invalidate_state(device, STATE_POINT_ENABLE);
1088 #endif /* STAGING_CSMT */
1089 }
1090
1091 if (stateblock->changed.indices)
1092 {
1093 wined3d_device_set_index_buffer(device, stateblock->state.index_buffer, stateblock->state.index_format);
1094 wined3d_device_set_base_vertex_index(device, stateblock->state.base_vertex_index);
1095 }
1096
1097 if (stateblock->changed.vertexDecl && stateblock->state.vertex_declaration)
1098 wined3d_device_set_vertex_declaration(device, stateblock->state.vertex_declaration);
1099
1100 if (stateblock->changed.material)
1101 wined3d_device_set_material(device, &stateblock->state.material);
1102
1103 if (stateblock->changed.viewport)
1104 wined3d_device_set_viewport(device, &stateblock->state.viewport);
1105
1106 if (stateblock->changed.scissorRect)
1107 wined3d_device_set_scissor_rect(device, &stateblock->state.scissor_rect);
1108
1109 map = stateblock->changed.streamSource;
1110 for (i = 0; map; map >>= 1, ++i)
1111 {
1112 if (map & 1)
1113 wined3d_device_set_stream_source(device, i,
1114 stateblock->state.streams[i].buffer,
1115 0, stateblock->state.streams[i].stride);
1116 }
1117
1118 map = stateblock->changed.streamFreq;
1119 for (i = 0; map; map >>= 1, ++i)
1120 {
1121 if (map & 1)
1122 wined3d_device_set_stream_source_freq(device, i,
1123 stateblock->state.streams[i].frequency | stateblock->state.streams[i].flags);
1124 }
1125
1126 map = stateblock->changed.textures;
1127 for (i = 0; map; map >>= 1, ++i)
1128 {
1129 DWORD stage;
1130
1131 if (!(map & 1)) continue;
1132
1133 stage = i < MAX_FRAGMENT_SAMPLERS ? i : WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS;
1134 wined3d_device_set_texture(device, stage, stateblock->state.textures[i]);
1135 }
1136
1137 map = stateblock->changed.clipplane;
1138 for (i = 0; map; map >>= 1, ++i)
1139 {
1140 if (!(map & 1)) continue;
1141
1142 wined3d_device_set_clip_plane(device, i, &stateblock->state.clip_planes[i]);
1143 }
1144
1145 TRACE("Applied stateblock %p.\n", stateblock);
1146 }
1147
1148 static void state_init_default(struct wined3d_state *state, const struct wined3d_gl_info *gl_info)
1149 {
1150 union
1151 {
1152 struct wined3d_line_pattern lp;
1153 DWORD d;
1154 } lp;
1155 union {
1156 float f;
1157 DWORD d;
1158 } tmpfloat;
1159 unsigned int i;
1160 struct wined3d_matrix identity;
1161
1162 TRACE("state %p, gl_info %p.\n", state, gl_info);
1163
1164 get_identity_matrix(&identity);
1165 state->gl_primitive_type = ~0u;
1166
1167 /* Set some of the defaults for lights, transforms etc */
1168 state->transforms[WINED3D_TS_PROJECTION] = identity;
1169 state->transforms[WINED3D_TS_VIEW] = identity;
1170 for (i = 0; i < 256; ++i)
1171 {
1172 state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
1173 }
1174
1175 TRACE("Render states\n");
1176 /* Render states: */
1177 state->render_states[WINED3D_RS_ZENABLE] = WINED3D_ZB_TRUE;
1178 state->render_states[WINED3D_RS_FILLMODE] = WINED3D_FILL_SOLID;
1179 state->render_states[WINED3D_RS_SHADEMODE] = WINED3D_SHADE_GOURAUD;
1180 lp.lp.repeat_factor = 0;
1181 lp.lp.line_pattern = 0;
1182 state->render_states[WINED3D_RS_LINEPATTERN] = lp.d;
1183 state->render_states[WINED3D_RS_ZWRITEENABLE] = TRUE;
1184 state->render_states[WINED3D_RS_ALPHATESTENABLE] = FALSE;
1185 state->render_states[WINED3D_RS_LASTPIXEL] = TRUE;
1186 state->render_states[WINED3D_RS_SRCBLEND] = WINED3D_BLEND_ONE;
1187 state->render_states[WINED3D_RS_DESTBLEND] = WINED3D_BLEND_ZERO;
1188 state->render_states[WINED3D_RS_CULLMODE] = WINED3D_CULL_CCW;
1189 state->render_states[WINED3D_RS_ZFUNC] = WINED3D_CMP_LESSEQUAL;
1190 state->render_states[WINED3D_RS_ALPHAFUNC] = WINED3D_CMP_ALWAYS;
1191 state->render_states[WINED3D_RS_ALPHAREF] = 0;
1192 state->render_states[WINED3D_RS_DITHERENABLE] = FALSE;
1193 state->render_states[WINED3D_RS_ALPHABLENDENABLE] = FALSE;
1194 state->render_states[WINED3D_RS_FOGENABLE] = FALSE;
1195 state->render_states[WINED3D_RS_SPECULARENABLE] = FALSE;
1196 state->render_states[WINED3D_RS_ZVISIBLE] = 0;
1197 state->render_states[WINED3D_RS_FOGCOLOR] = 0;
1198 state->render_states[WINED3D_RS_FOGTABLEMODE] = WINED3D_FOG_NONE;
1199 tmpfloat.f = 0.0f;
1200 state->render_states[WINED3D_RS_FOGSTART] = tmpfloat.d;
1201 tmpfloat.f = 1.0f;
1202 state->render_states[WINED3D_RS_FOGEND] = tmpfloat.d;
1203 tmpfloat.f = 1.0f;
1204 state->render_states[WINED3D_RS_FOGDENSITY] = tmpfloat.d;
1205 state->render_states[WINED3D_RS_EDGEANTIALIAS] = FALSE;
1206 state->render_states[WINED3D_RS_RANGEFOGENABLE] = FALSE;
1207 state->render_states[WINED3D_RS_STENCILENABLE] = FALSE;
1208 state->render_states[WINED3D_RS_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1209 state->render_states[WINED3D_RS_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1210 state->render_states[WINED3D_RS_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1211 state->render_states[WINED3D_RS_STENCILREF] = 0;
1212 state->render_states[WINED3D_RS_STENCILMASK] = 0xffffffff;
1213 state->render_states[WINED3D_RS_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1214 state->render_states[WINED3D_RS_STENCILWRITEMASK] = 0xffffffff;
1215 state->render_states[WINED3D_RS_TEXTUREFACTOR] = 0xffffffff;
1216 state->render_states[WINED3D_RS_WRAP0] = 0;
1217 state->render_states[WINED3D_RS_WRAP1] = 0;
1218 state->render_states[WINED3D_RS_WRAP2] = 0;
1219 state->render_states[WINED3D_RS_WRAP3] = 0;
1220 state->render_states[WINED3D_RS_WRAP4] = 0;
1221 state->render_states[WINED3D_RS_WRAP5] = 0;
1222 state->render_states[WINED3D_RS_WRAP6] = 0;
1223 state->render_states[WINED3D_RS_WRAP7] = 0;
1224 state->render_states[WINED3D_RS_CLIPPING] = TRUE;
1225 state->render_states[WINED3D_RS_LIGHTING] = TRUE;
1226 state->render_states[WINED3D_RS_AMBIENT] = 0;
1227 state->render_states[WINED3D_RS_FOGVERTEXMODE] = WINED3D_FOG_NONE;
1228 state->render_states[WINED3D_RS_COLORVERTEX] = TRUE;
1229 state->render_states[WINED3D_RS_LOCALVIEWER] = TRUE;
1230 state->render_states[WINED3D_RS_NORMALIZENORMALS] = FALSE;
1231 state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE] = WINED3D_MCS_COLOR1;
1232 state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] = WINED3D_MCS_COLOR2;
1233 state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1234 state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1235 state->render_states[WINED3D_RS_VERTEXBLEND] = WINED3D_VBF_DISABLE;
1236 state->render_states[WINED3D_RS_CLIPPLANEENABLE] = 0;
1237 state->render_states[WINED3D_RS_SOFTWAREVERTEXPROCESSING] = FALSE;
1238 tmpfloat.f = 1.0f;
1239 state->render_states[WINED3D_RS_POINTSIZE] = tmpfloat.d;
1240 tmpfloat.f = 1.0f;
1241 state->render_states[WINED3D_RS_POINTSIZE_MIN] = tmpfloat.d;
1242 state->render_states[WINED3D_RS_POINTSPRITEENABLE] = FALSE;
1243 state->render_states[WINED3D_RS_POINTSCALEENABLE] = FALSE;
1244 tmpfloat.f = 1.0f;
1245 state->render_states[WINED3D_RS_POINTSCALE_A] = tmpfloat.d;
1246 tmpfloat.f = 0.0f;
1247 state->render_states[WINED3D_RS_POINTSCALE_B] = tmpfloat.d;
1248 tmpfloat.f = 0.0f;
1249 state->render_states[WINED3D_RS_POINTSCALE_C] = tmpfloat.d;
1250 state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS] = TRUE;
1251 state->render_states[WINED3D_RS_MULTISAMPLEMASK] = 0xffffffff;
1252 state->render_states[WINED3D_RS_PATCHEDGESTYLE] = WINED3D_PATCH_EDGE_DISCRETE;
1253 tmpfloat.f = 1.0f;
1254 state->render_states[WINED3D_RS_PATCHSEGMENTS] = tmpfloat.d;
1255 state->render_states[WINED3D_RS_DEBUGMONITORTOKEN] = 0xbaadcafe;
1256 tmpfloat.f = gl_info->limits.pointsize_max;
1257 state->render_states[WINED3D_RS_POINTSIZE_MAX] = tmpfloat.d;
1258 state->render_states[WINED3D_RS_INDEXEDVERTEXBLENDENABLE] = FALSE;
1259 state->render_states[WINED3D_RS_COLORWRITEENABLE] = 0x0000000f;
1260 tmpfloat.f = 0.0f;
1261 state->render_states[WINED3D_RS_TWEENFACTOR] = tmpfloat.d;
1262 state->render_states[WINED3D_RS_BLENDOP] = WINED3D_BLEND_OP_ADD;
1263 state->render_states[WINED3D_RS_POSITIONDEGREE] = WINED3D_DEGREE_CUBIC;
1264 state->render_states[WINED3D_RS_NORMALDEGREE] = WINED3D_DEGREE_LINEAR;
1265 /* states new in d3d9 */
1266 state->render_states[WINED3D_RS_SCISSORTESTENABLE] = FALSE;
1267 state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS] = 0;
1268 tmpfloat.f = 1.0f;
1269 state->render_states[WINED3D_RS_MINTESSELLATIONLEVEL] = tmpfloat.d;
1270 state->render_states[WINED3D_RS_MAXTESSELLATIONLEVEL] = tmpfloat.d;
1271 state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE] = FALSE;
1272 tmpfloat.f = 0.0f;
1273 state->render_states[WINED3D_RS_ADAPTIVETESS_X] = tmpfloat.d;
1274 state->render_states[WINED3D_RS_ADAPTIVETESS_Y] = tmpfloat.d;
1275 tmpfloat.f = 1.0f;
1276 state->render_states[WINED3D_RS_ADAPTIVETESS_Z] = tmpfloat.d;
1277 tmpfloat.f = 0.0f;
1278 state->render_states[WINED3D_RS_ADAPTIVETESS_W] = tmpfloat.d;
1279 state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION] = FALSE;
1280 state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE] = FALSE;
1281 state->render_states[WINED3D_RS_CCW_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1282 state->render_states[WINED3D_RS_CCW_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1283 state->render_states[WINED3D_RS_CCW_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1284 state->render_states[WINED3D_RS_CCW_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1285 state->render_states[WINED3D_RS_COLORWRITEENABLE1] = 0x0000000f;
1286 state->render_states[WINED3D_RS_COLORWRITEENABLE2] = 0x0000000f;
1287 state->render_states[WINED3D_RS_COLORWRITEENABLE3] = 0x0000000f;
1288 state->render_states[WINED3D_RS_BLENDFACTOR] = 0xffffffff;
1289 state->render_states[WINED3D_RS_SRGBWRITEENABLE] = 0;
1290 state->render_states[WINED3D_RS_DEPTHBIAS] = 0;
1291 state->render_states[WINED3D_RS_WRAP8] = 0;
1292 state->render_states[WINED3D_RS_WRAP9] = 0;
1293 state->render_states[WINED3D_RS_WRAP10] = 0;
1294 state->render_states[WINED3D_RS_WRAP11] = 0;
1295 state->render_states[WINED3D_RS_WRAP12] = 0;
1296 state->render_states[WINED3D_RS_WRAP13] = 0;
1297 state->render_states[WINED3D_RS_WRAP14] = 0;
1298 state->render_states[WINED3D_RS_WRAP15] = 0;
1299 state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE] = FALSE;
1300 state->render_states[WINED3D_RS_SRCBLENDALPHA] = WINED3D_BLEND_ONE;
1301 state->render_states[WINED3D_RS_DESTBLENDALPHA] = WINED3D_BLEND_ZERO;
1302 state->render_states[WINED3D_RS_BLENDOPALPHA] = WINED3D_BLEND_OP_ADD;
1303
1304 /* Texture Stage States - Put directly into state block, we will call function below */
1305 for (i = 0; i < MAX_TEXTURES; ++i)
1306 {
1307 TRACE("Setting up default texture states for texture Stage %u.\n", i);
1308 state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
1309 state->texture_states[i][WINED3D_TSS_COLOR_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_MODULATE;
1310 state->texture_states[i][WINED3D_TSS_COLOR_ARG1] = WINED3DTA_TEXTURE;
1311 state->texture_states[i][WINED3D_TSS_COLOR_ARG2] = WINED3DTA_CURRENT;
1312 state->texture_states[i][WINED3D_TSS_ALPHA_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_SELECT_ARG1;
1313 state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] = WINED3DTA_TEXTURE;
1314 state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] = WINED3DTA_CURRENT;
1315 state->texture_states[i][WINED3D_TSS_BUMPENV_MAT00] = 0;
1316 state->texture_states[i][WINED3D_TSS_BUMPENV_MAT01] = 0;
1317 state->texture_states[i][WINED3D_TSS_BUMPENV_MAT10] = 0;
1318 state->texture_states[i][WINED3D_TSS_BUMPENV_MAT11] = 0;
1319 state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] = i;
1320 state->texture_states[i][WINED3D_TSS_BUMPENV_LSCALE] = 0;
1321 state->texture_states[i][WINED3D_TSS_BUMPENV_LOFFSET] = 0;
1322 state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS] = WINED3D_TTFF_DISABLE;
1323 state->texture_states[i][WINED3D_TSS_COLOR_ARG0] = WINED3DTA_CURRENT;
1324 state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] = WINED3DTA_CURRENT;
1325 state->texture_states[i][WINED3D_TSS_RESULT_ARG] = WINED3DTA_CURRENT;
1326 }
1327
1328 for (i = 0 ; i < MAX_COMBINED_SAMPLERS; ++i)
1329 {
1330 TRACE("Setting up default samplers states for sampler %u.\n", i);
1331 state->sampler_states[i][WINED3D_SAMP_ADDRESS_U] = WINED3D_TADDRESS_WRAP;
1332 state->sampler_states[i][WINED3D_SAMP_ADDRESS_V] = WINED3D_TADDRESS_WRAP;
1333 state->sampler_states[i][WINED3D_SAMP_ADDRESS_W] = WINED3D_TADDRESS_WRAP;
1334 state->sampler_states[i][WINED3D_SAMP_BORDER_COLOR] = 0;
1335 state->sampler_states[i][WINED3D_SAMP_MAG_FILTER] = WINED3D_TEXF_POINT;
1336 state->sampler_states[i][WINED3D_SAMP_MIN_FILTER] = WINED3D_TEXF_POINT;
1337 state->sampler_states[i][WINED3D_SAMP_MIP_FILTER] = WINED3D_TEXF_NONE;
1338 state->sampler_states[i][WINED3D_SAMP_MIPMAP_LOD_BIAS] = 0;
1339 state->sampler_states[i][WINED3D_SAMP_MAX_MIP_LEVEL] = 0;
1340 state->sampler_states[i][WINED3D_SAMP_MAX_ANISOTROPY] = 1;
1341 state->sampler_states[i][WINED3D_SAMP_SRGB_TEXTURE] = 0;
1342 /* TODO: Indicates which element of a multielement texture to use. */
1343 state->sampler_states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0;
1344 /* TODO: Vertex offset in the presampled displacement map. */
1345 state->sampler_states[i][WINED3D_SAMP_DMAP_OFFSET] = 0;
1346 #if defined(STAGING_CSMT)
1347 state->textures[i] = NULL;
1348 }
1349
1350 state->index_buffer = NULL;
1351 for (i = 0; i < sizeof(state->streams) / sizeof(*state->streams); i++)
1352 memset(&state->streams[i], 0, sizeof(state->streams[i]));
1353
1354 state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL;
1355 state->shader[WINED3D_SHADER_TYPE_PIXEL] = NULL;
1356 }
1357
1358 HRESULT state_init(struct wined3d_state *state, const struct wined3d_gl_info *gl_info,
1359 const struct wined3d_d3d_info *d3d_info, DWORD flags)
1360 {
1361 unsigned int i;
1362
1363 state->flags = flags;
1364 #else /* STAGING_CSMT */
1365 }
1366 }
1367
1368 HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb,
1369 const struct wined3d_gl_info *gl_info, const struct wined3d_d3d_info *d3d_info,
1370 DWORD flags)
1371 {
1372 unsigned int i;
1373
1374 state->flags = flags;
1375 state->fb = fb;
1376 #endif /* STAGING_CSMT */
1377
1378 for (i = 0; i < LIGHTMAP_SIZE; i++)
1379 {
1380 list_init(&state->light_map[i]);
1381 }
1382
1383 if (!(state->vs_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1384 4 * sizeof(float) * d3d_info->limits.vs_uniform_count)))
1385 return E_OUTOFMEMORY;
1386
1387 if (!(state->ps_consts_f = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1388 4 * sizeof(float) * d3d_info->limits.ps_uniform_count)))
1389 {
1390 HeapFree(GetProcessHeap(), 0, state->vs_consts_f);
1391 return E_OUTOFMEMORY;
1392 }
1393
1394 #if defined(STAGING_CSMT)
1395 if (!(state->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1396 sizeof(*state->fb.render_targets) * gl_info->limits.buffers)))
1397 {
1398 HeapFree(GetProcessHeap(), 0, state->ps_consts_f);
1399 HeapFree(GetProcessHeap(), 0, state->vs_consts_f);
1400 return E_OUTOFMEMORY;
1401 }
1402 state->fb.rt_size = gl_info->limits.buffers;
1403
1404 #endif /* STAGING_CSMT */
1405 if (flags & WINED3D_STATE_INIT_DEFAULT)
1406 state_init_default(state, gl_info);
1407
1408 return WINED3D_OK;
1409 }
1410
1411 static HRESULT stateblock_init(struct wined3d_stateblock *stateblock,
1412 struct wined3d_device *device, enum wined3d_stateblock_type type)
1413 {
1414 HRESULT hr;
1415 #if defined(STAGING_CSMT)
1416 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1417 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
1418
1419 stateblock->ref = 1;
1420 stateblock->device = device;
1421
1422 if (FAILED(hr = state_init(&stateblock->state, gl_info, d3d_info, 0)))
1423 #else /* STAGING_CSMT */
1424 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
1425
1426 stateblock->ref = 1;
1427 stateblock->device = device;
1428
1429 if (FAILED(hr = state_init(&stateblock->state, NULL, &device->adapter->gl_info, d3d_info, 0)))
1430 #endif /* STAGING_CSMT */
1431 return hr;
1432
1433 if (FAILED(hr = stateblock_allocate_shader_constants(stateblock)))
1434 {
1435 state_cleanup(&stateblock->state);
1436 return hr;
1437 }
1438
1439 if (type == WINED3D_SBT_RECORDED)
1440 return WINED3D_OK;
1441
1442 TRACE("Updating changed flags appropriate for type %#x.\n", type);
1443
1444 switch (type)
1445 {
1446 case WINED3D_SBT_ALL:
1447 stateblock_init_lights(stateblock, device->state.light_map);
1448 stateblock_savedstates_set_all(&stateblock->changed,
1449 d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
1450 break;
1451
1452 case WINED3D_SBT_PIXEL_STATE:
1453 stateblock_savedstates_set_pixel(&stateblock->changed,
1454 d3d_info->limits.ps_uniform_count);
1455 break;
1456
1457 case WINED3D_SBT_VERTEX_STATE:
1458 stateblock_init_lights(stateblock, device->state.light_map);
1459 stateblock_savedstates_set_vertex(&stateblock->changed,
1460 d3d_info->limits.vs_uniform_count);
1461 break;
1462
1463 default:
1464 FIXME("Unrecognized state block type %#x.\n", type);
1465 break;
1466 }
1467
1468 stateblock_init_contained_states(stateblock);
1469 wined3d_stateblock_capture(stateblock);
1470
1471 return WINED3D_OK;
1472 }
1473
1474 HRESULT CDECL wined3d_stateblock_create(struct wined3d_device *device,
1475 enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock)
1476 {
1477 struct wined3d_stateblock *object;
1478 HRESULT hr;
1479
1480 TRACE("device %p, type %#x, stateblock %p.\n",
1481 device, type, stateblock);
1482
1483 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1484 if (!object)
1485 return E_OUTOFMEMORY;
1486
1487 hr = stateblock_init(object, device, type);
1488 if (FAILED(hr))
1489 {
1490 WARN("Failed to initialize stateblock, hr %#x.\n", hr);
1491 HeapFree(GetProcessHeap(), 0, object);
1492 return hr;
1493 }
1494
1495 TRACE("Created stateblock %p.\n", object);
1496 *stateblock = object;
1497
1498 return WINED3D_OK;
1499 }