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