wined3d: Introduce public API to set a wined3d_state object on a device.
[wine/zf.git] / dlls / wined3d / stateblock.c
blob97020e1cd407f9329d554a88d0782f7ab519fad1
1 /*
2 * state block implementation
4 * Copyright 2002 Raphael Junqueira
5 * Copyright 2004 Jason Edmeades
6 * Copyright 2005 Oliver Stieber
7 * Copyright 2007 Stefan Dösinger for CodeWeavers
8 * Copyright 2009 Henri Verbeet for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 static const DWORD pixel_states_render[] =
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_DEPTHBIAS,
49 WINED3D_RS_DESTBLEND,
50 WINED3D_RS_DESTBLENDALPHA,
51 WINED3D_RS_DITHERENABLE,
52 WINED3D_RS_FILLMODE,
53 WINED3D_RS_FOGDENSITY,
54 WINED3D_RS_FOGEND,
55 WINED3D_RS_FOGSTART,
56 WINED3D_RS_LASTPIXEL,
57 WINED3D_RS_SCISSORTESTENABLE,
58 WINED3D_RS_SEPARATEALPHABLENDENABLE,
59 WINED3D_RS_SHADEMODE,
60 WINED3D_RS_SLOPESCALEDEPTHBIAS,
61 WINED3D_RS_SRCBLEND,
62 WINED3D_RS_SRCBLENDALPHA,
63 WINED3D_RS_SRGBWRITEENABLE,
64 WINED3D_RS_STENCILENABLE,
65 WINED3D_RS_STENCILFAIL,
66 WINED3D_RS_STENCILFUNC,
67 WINED3D_RS_STENCILMASK,
68 WINED3D_RS_STENCILPASS,
69 WINED3D_RS_STENCILREF,
70 WINED3D_RS_STENCILWRITEMASK,
71 WINED3D_RS_STENCILZFAIL,
72 WINED3D_RS_TEXTUREFACTOR,
73 WINED3D_RS_TWOSIDEDSTENCILMODE,
74 WINED3D_RS_WRAP0,
75 WINED3D_RS_WRAP1,
76 WINED3D_RS_WRAP10,
77 WINED3D_RS_WRAP11,
78 WINED3D_RS_WRAP12,
79 WINED3D_RS_WRAP13,
80 WINED3D_RS_WRAP14,
81 WINED3D_RS_WRAP15,
82 WINED3D_RS_WRAP2,
83 WINED3D_RS_WRAP3,
84 WINED3D_RS_WRAP4,
85 WINED3D_RS_WRAP5,
86 WINED3D_RS_WRAP6,
87 WINED3D_RS_WRAP7,
88 WINED3D_RS_WRAP8,
89 WINED3D_RS_WRAP9,
90 WINED3D_RS_ZENABLE,
91 WINED3D_RS_ZFUNC,
92 WINED3D_RS_ZWRITEENABLE,
95 static const DWORD pixel_states_texture[] =
97 WINED3D_TSS_ALPHA_ARG0,
98 WINED3D_TSS_ALPHA_ARG1,
99 WINED3D_TSS_ALPHA_ARG2,
100 WINED3D_TSS_ALPHA_OP,
101 WINED3D_TSS_BUMPENV_LOFFSET,
102 WINED3D_TSS_BUMPENV_LSCALE,
103 WINED3D_TSS_BUMPENV_MAT00,
104 WINED3D_TSS_BUMPENV_MAT01,
105 WINED3D_TSS_BUMPENV_MAT10,
106 WINED3D_TSS_BUMPENV_MAT11,
107 WINED3D_TSS_COLOR_ARG0,
108 WINED3D_TSS_COLOR_ARG1,
109 WINED3D_TSS_COLOR_ARG2,
110 WINED3D_TSS_COLOR_OP,
111 WINED3D_TSS_RESULT_ARG,
112 WINED3D_TSS_TEXCOORD_INDEX,
113 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
116 static const DWORD pixel_states_sampler[] =
118 WINED3D_SAMP_ADDRESS_U,
119 WINED3D_SAMP_ADDRESS_V,
120 WINED3D_SAMP_ADDRESS_W,
121 WINED3D_SAMP_BORDER_COLOR,
122 WINED3D_SAMP_MAG_FILTER,
123 WINED3D_SAMP_MIN_FILTER,
124 WINED3D_SAMP_MIP_FILTER,
125 WINED3D_SAMP_MIPMAP_LOD_BIAS,
126 WINED3D_SAMP_MAX_MIP_LEVEL,
127 WINED3D_SAMP_MAX_ANISOTROPY,
128 WINED3D_SAMP_SRGB_TEXTURE,
129 WINED3D_SAMP_ELEMENT_INDEX,
132 static const DWORD vertex_states_render[] =
134 WINED3D_RS_ADAPTIVETESS_W,
135 WINED3D_RS_ADAPTIVETESS_X,
136 WINED3D_RS_ADAPTIVETESS_Y,
137 WINED3D_RS_ADAPTIVETESS_Z,
138 WINED3D_RS_AMBIENT,
139 WINED3D_RS_AMBIENTMATERIALSOURCE,
140 WINED3D_RS_CLIPPING,
141 WINED3D_RS_CLIPPLANEENABLE,
142 WINED3D_RS_COLORVERTEX,
143 WINED3D_RS_CULLMODE,
144 WINED3D_RS_DIFFUSEMATERIALSOURCE,
145 WINED3D_RS_EMISSIVEMATERIALSOURCE,
146 WINED3D_RS_ENABLEADAPTIVETESSELLATION,
147 WINED3D_RS_FOGCOLOR,
148 WINED3D_RS_FOGDENSITY,
149 WINED3D_RS_FOGENABLE,
150 WINED3D_RS_FOGEND,
151 WINED3D_RS_FOGSTART,
152 WINED3D_RS_FOGTABLEMODE,
153 WINED3D_RS_FOGVERTEXMODE,
154 WINED3D_RS_INDEXEDVERTEXBLENDENABLE,
155 WINED3D_RS_LIGHTING,
156 WINED3D_RS_LOCALVIEWER,
157 WINED3D_RS_MAXTESSELLATIONLEVEL,
158 WINED3D_RS_MINTESSELLATIONLEVEL,
159 WINED3D_RS_MULTISAMPLEANTIALIAS,
160 WINED3D_RS_MULTISAMPLEMASK,
161 WINED3D_RS_NORMALDEGREE,
162 WINED3D_RS_NORMALIZENORMALS,
163 WINED3D_RS_PATCHEDGESTYLE,
164 WINED3D_RS_POINTSCALE_A,
165 WINED3D_RS_POINTSCALE_B,
166 WINED3D_RS_POINTSCALE_C,
167 WINED3D_RS_POINTSCALEENABLE,
168 WINED3D_RS_POINTSIZE,
169 WINED3D_RS_POINTSIZE_MAX,
170 WINED3D_RS_POINTSIZE_MIN,
171 WINED3D_RS_POINTSPRITEENABLE,
172 WINED3D_RS_POSITIONDEGREE,
173 WINED3D_RS_RANGEFOGENABLE,
174 WINED3D_RS_SHADEMODE,
175 WINED3D_RS_SPECULARENABLE,
176 WINED3D_RS_SPECULARMATERIALSOURCE,
177 WINED3D_RS_TWEENFACTOR,
178 WINED3D_RS_VERTEXBLEND,
181 static const DWORD vertex_states_texture[] =
183 WINED3D_TSS_TEXCOORD_INDEX,
184 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
187 static const DWORD vertex_states_sampler[] =
189 WINED3D_SAMP_DMAP_OFFSET,
192 static inline void stateblock_set_all_bits(DWORD *map, UINT map_size)
194 DWORD mask = (1u << (map_size & 0x1f)) - 1;
195 memset(map, 0xff, (map_size >> 5) * sizeof(*map));
196 if (mask) map[map_size >> 5] = mask;
199 /* Set all members of a stateblock savedstate to the given value */
200 static void stateblock_savedstates_set_all(struct wined3d_saved_states *states, DWORD vs_consts, DWORD ps_consts)
202 unsigned int i;
204 states->indices = 1;
205 states->material = 1;
206 states->viewport = 1;
207 states->vertexDecl = 1;
208 states->pixelShader = 1;
209 states->vertexShader = 1;
210 states->scissorRect = 1;
211 states->alpha_to_coverage = 1;
212 states->lights = 1;
213 states->transforms = 1;
215 states->streamSource = 0xffff;
216 states->streamFreq = 0xffff;
217 states->textures = 0xfffff;
218 stateblock_set_all_bits(states->transform, WINED3D_HIGHEST_TRANSFORM_STATE + 1);
219 stateblock_set_all_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
220 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
221 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3ffe;
222 states->clipplane = (1u << WINED3D_MAX_CLIP_DISTANCES) - 1;
223 states->pixelShaderConstantsB = 0xffff;
224 states->pixelShaderConstantsI = 0xffff;
225 states->vertexShaderConstantsB = 0xffff;
226 states->vertexShaderConstantsI = 0xffff;
228 memset(states->ps_consts_f, 0xffu, sizeof(states->ps_consts_f));
229 memset(states->vs_consts_f, 0xffu, sizeof(states->vs_consts_f));
232 static void stateblock_savedstates_set_pixel(struct wined3d_saved_states *states, const DWORD num_constants)
234 DWORD texture_mask = 0;
235 WORD sampler_mask = 0;
236 unsigned int i;
238 states->pixelShader = 1;
240 for (i = 0; i < ARRAY_SIZE(pixel_states_render); ++i)
242 DWORD rs = pixel_states_render[i];
243 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
246 for (i = 0; i < ARRAY_SIZE(pixel_states_texture); ++i)
247 texture_mask |= 1u << pixel_states_texture[i];
248 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
249 for (i = 0; i < ARRAY_SIZE(pixel_states_sampler); ++i)
250 sampler_mask |= 1u << pixel_states_sampler[i];
251 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
252 states->pixelShaderConstantsB = 0xffff;
253 states->pixelShaderConstantsI = 0xffff;
255 memset(states->ps_consts_f, 0xffu, sizeof(states->ps_consts_f));
258 static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *states, const DWORD num_constants)
260 DWORD texture_mask = 0;
261 WORD sampler_mask = 0;
262 unsigned int i;
264 states->vertexDecl = 1;
265 states->vertexShader = 1;
266 states->alpha_to_coverage = 1;
267 states->lights = 1;
269 for (i = 0; i < ARRAY_SIZE(vertex_states_render); ++i)
271 DWORD rs = vertex_states_render[i];
272 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
275 for (i = 0; i < ARRAY_SIZE(vertex_states_texture); ++i)
276 texture_mask |= 1u << vertex_states_texture[i];
277 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i) states->textureState[i] = texture_mask;
278 for (i = 0; i < ARRAY_SIZE(vertex_states_sampler); ++i)
279 sampler_mask |= 1u << vertex_states_sampler[i];
280 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
281 states->vertexShaderConstantsB = 0xffff;
282 states->vertexShaderConstantsI = 0xffff;
284 memset(states->vs_consts_f, 0xffu, sizeof(states->vs_consts_f));
287 void CDECL wined3d_stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
289 unsigned int i, j;
291 for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
293 DWORD map = stateblock->changed.renderState[i];
294 for (j = 0; map; map >>= 1, ++j)
296 if (!(map & 1)) continue;
298 stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
299 ++stateblock->num_contained_render_states;
303 for (i = 0; i <= WINED3D_HIGHEST_TRANSFORM_STATE >> 5; ++i)
305 DWORD map = stateblock->changed.transform[i];
306 for (j = 0; map; map >>= 1, ++j)
308 if (!(map & 1)) continue;
310 stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
311 ++stateblock->num_contained_transform_states;
315 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i)
317 DWORD map = stateblock->changed.textureState[i];
319 for(j = 0; map; map >>= 1, ++j)
321 if (!(map & 1)) continue;
323 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
324 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
325 ++stateblock->num_contained_tss_states;
329 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
331 DWORD map = stateblock->changed.samplerState[i];
333 for (j = 0; map; map >>= 1, ++j)
335 if (!(map & 1)) continue;
337 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
338 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
339 ++stateblock->num_contained_sampler_states;
344 static void stateblock_init_lights(struct list *dst_map, const struct list *src_map)
346 unsigned int i;
348 for (i = 0; i < LIGHTMAP_SIZE; ++i)
350 const struct wined3d_light_info *src_light;
352 LIST_FOR_EACH_ENTRY(src_light, &src_map[i], struct wined3d_light_info, entry)
354 struct wined3d_light_info *dst_light = heap_alloc(sizeof(*dst_light));
356 *dst_light = *src_light;
357 list_add_tail(&dst_map[i], &dst_light->entry);
362 ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
364 ULONG refcount = InterlockedIncrement(&stateblock->ref);
366 TRACE("%p increasing refcount to %u.\n", stateblock, refcount);
368 return refcount;
371 void state_unbind_resources(struct wined3d_state *state)
373 struct wined3d_unordered_access_view *uav;
374 struct wined3d_shader_resource_view *srv;
375 struct wined3d_vertex_declaration *decl;
376 struct wined3d_blend_state *blend_state;
377 struct wined3d_rendertarget_view *rtv;
378 struct wined3d_sampler *sampler;
379 struct wined3d_texture *texture;
380 struct wined3d_buffer *buffer;
381 struct wined3d_shader *shader;
382 unsigned int i, j;
384 if ((decl = state->vertex_declaration))
386 state->vertex_declaration = NULL;
387 wined3d_vertex_declaration_decref(decl);
390 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
392 if ((texture = state->textures[i]))
394 state->textures[i] = NULL;
395 wined3d_texture_decref(texture);
399 for (i = 0; i < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++i)
401 if ((buffer = state->stream_output[i].buffer))
403 state->stream_output[i].buffer = NULL;
404 wined3d_buffer_decref(buffer);
408 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
410 if ((buffer = state->streams[i].buffer))
412 state->streams[i].buffer = NULL;
413 wined3d_buffer_decref(buffer);
417 if ((buffer = state->index_buffer))
419 state->index_buffer = NULL;
420 wined3d_buffer_decref(buffer);
423 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
425 if ((shader = state->shader[i]))
427 state->shader[i] = NULL;
428 wined3d_shader_decref(shader);
431 for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
433 if ((buffer = state->cb[i][j]))
435 state->cb[i][j] = NULL;
436 wined3d_buffer_decref(buffer);
440 for (j = 0; j < MAX_SAMPLER_OBJECTS; ++j)
442 if ((sampler = state->sampler[i][j]))
444 state->sampler[i][j] = NULL;
445 wined3d_sampler_decref(sampler);
449 for (j = 0; j < MAX_SHADER_RESOURCE_VIEWS; ++j)
451 if ((srv = state->shader_resource_view[i][j]))
453 state->shader_resource_view[i][j] = NULL;
454 wined3d_srv_bind_count_dec(srv);
455 wined3d_shader_resource_view_decref(srv);
460 for (i = 0; i < WINED3D_PIPELINE_COUNT; ++i)
462 for (j = 0; j < MAX_UNORDERED_ACCESS_VIEWS; ++j)
464 if ((uav = state->unordered_access_view[i][j]))
466 state->unordered_access_view[i][j] = NULL;
467 wined3d_unordered_access_view_decref(uav);
472 if ((blend_state = state->blend_state))
474 state->blend_state = NULL;
475 wined3d_blend_state_decref(blend_state);
478 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
480 if ((rtv = state->fb.render_targets[i]))
482 state->fb.render_targets[i] = NULL;
483 wined3d_rendertarget_view_decref(rtv);
487 if ((rtv = state->fb.depth_stencil))
489 state->fb.depth_stencil = NULL;
490 wined3d_rendertarget_view_decref(rtv);
494 void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state)
496 struct wined3d_light_info *light, *cursor;
497 struct wined3d_vertex_declaration *decl;
498 struct wined3d_texture *texture;
499 struct wined3d_buffer *buffer;
500 struct wined3d_shader *shader;
501 unsigned int i;
503 if ((decl = state->vertex_declaration))
505 state->vertex_declaration = NULL;
506 wined3d_vertex_declaration_decref(decl);
509 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
511 if ((buffer = state->streams[i].buffer))
513 state->streams[i].buffer = NULL;
514 wined3d_buffer_decref(buffer);
518 if ((buffer = state->index_buffer))
520 state->index_buffer = NULL;
521 wined3d_buffer_decref(buffer);
524 if ((shader = state->vs))
526 state->vs = NULL;
527 wined3d_shader_decref(shader);
530 if ((shader = state->ps))
532 state->ps = NULL;
533 wined3d_shader_decref(shader);
536 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
538 if ((texture = state->textures[i]))
540 state->textures[i] = NULL;
541 wined3d_texture_decref(texture);
545 for (i = 0; i < LIGHTMAP_SIZE; ++i)
547 LIST_FOR_EACH_ENTRY_SAFE(light, cursor, &state->light_state->light_map[i], struct wined3d_light_info, entry)
549 list_remove(&light->entry);
550 heap_free(light);
555 void state_cleanup(struct wined3d_state *state)
557 unsigned int counter;
559 if (!(state->flags & WINED3D_STATE_NO_REF))
560 state_unbind_resources(state);
562 for (counter = 0; counter < WINED3D_MAX_ACTIVE_LIGHTS; ++counter)
564 state->light_state.lights[counter] = NULL;
567 for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
569 struct list *e1, *e2;
570 LIST_FOR_EACH_SAFE(e1, e2, &state->light_state.light_map[counter])
572 struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
573 list_remove(&light->entry);
574 heap_free(light);
579 ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
581 ULONG refcount = InterlockedDecrement(&stateblock->ref);
583 TRACE("%p decreasing refcount to %u\n", stateblock, refcount);
585 if (!refcount)
587 wined3d_stateblock_state_cleanup(&stateblock->stateblock_state);
588 heap_free(stateblock);
591 return refcount;
594 struct wined3d_light_info *wined3d_light_state_get_light(const struct wined3d_light_state *state, unsigned int idx)
596 struct wined3d_light_info *light_info;
597 unsigned int hash_idx;
599 hash_idx = LIGHTMAP_HASHFUNC(idx);
600 LIST_FOR_EACH_ENTRY(light_info, &state->light_map[hash_idx], struct wined3d_light_info, entry)
602 if (light_info->OriginalIndex == idx)
603 return light_info;
606 return NULL;
609 HRESULT wined3d_light_state_set_light(struct wined3d_light_state *state, DWORD light_idx,
610 const struct wined3d_light *params, struct wined3d_light_info **light_info)
612 struct wined3d_light_info *object;
613 unsigned int hash_idx;
615 if (!(object = wined3d_light_state_get_light(state, light_idx)))
617 TRACE("Adding new light.\n");
618 if (!(object = heap_alloc_zero(sizeof(*object))))
620 ERR("Failed to allocate light info.\n");
621 return E_OUTOFMEMORY;
624 hash_idx = LIGHTMAP_HASHFUNC(light_idx);
625 list_add_head(&state->light_map[hash_idx], &object->entry);
626 object->glIndex = -1;
627 object->OriginalIndex = light_idx;
630 object->OriginalParms = *params;
632 *light_info = object;
633 return WINED3D_OK;
636 void wined3d_light_state_enable_light(struct wined3d_light_state *state, const struct wined3d_d3d_info *d3d_info,
637 struct wined3d_light_info *light_info, BOOL enable)
639 unsigned int light_count, i;
641 if (!(light_info->enabled = enable))
643 if (light_info->glIndex == -1)
645 TRACE("Light already disabled, nothing to do.\n");
646 return;
649 state->lights[light_info->glIndex] = NULL;
650 light_info->glIndex = -1;
651 return;
654 if (light_info->glIndex != -1)
656 TRACE("Light already enabled, nothing to do.\n");
657 return;
660 /* Find a free light. */
661 light_count = d3d_info->limits.active_light_count;
662 for (i = 0; i < light_count; ++i)
664 if (state->lights[i])
665 continue;
667 state->lights[i] = light_info;
668 light_info->glIndex = i;
669 return;
672 /* Our tests show that Windows returns D3D_OK in this situation, even with
673 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices.
674 * This is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns
675 * TRUE * as well for those lights.
677 * TODO: Test how this affects rendering. */
678 WARN("Too many concurrently active lights.\n");
681 static void wined3d_state_record_lights(struct wined3d_light_state *dst_state,
682 const struct wined3d_light_state *src_state)
684 const struct wined3d_light_info *src;
685 struct wined3d_light_info *dst;
686 UINT i;
688 /* Lights... For a recorded state block, we just had a chain of actions
689 * to perform, so we need to walk that chain and update any actions which
690 * differ. */
691 for (i = 0; i < LIGHTMAP_SIZE; ++i)
693 LIST_FOR_EACH_ENTRY(dst, &dst_state->light_map[i], struct wined3d_light_info, entry)
695 if ((src = wined3d_light_state_get_light(src_state, dst->OriginalIndex)))
697 dst->OriginalParms = src->OriginalParms;
699 if (src->glIndex == -1 && dst->glIndex != -1)
701 /* Light disabled. */
702 dst_state->lights[dst->glIndex] = NULL;
704 else if (src->glIndex != -1 && dst->glIndex == -1)
706 /* Light enabled. */
707 dst_state->lights[src->glIndex] = dst;
709 dst->glIndex = src->glIndex;
711 else
713 /* This can happen if the light was originally created as a
714 * default light for SetLightEnable() while recording. */
715 WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
716 dst->OriginalIndex, dst_state, src_state);
718 dst->OriginalParms = WINED3D_default_light;
719 if (dst->glIndex != -1)
721 dst_state->lights[dst->glIndex] = NULL;
722 dst->glIndex = -1;
729 void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock,
730 const struct wined3d_stateblock *device_state)
732 const struct wined3d_stateblock_state *state = &device_state->stateblock_state;
733 struct wined3d_range range;
734 unsigned int i, start;
735 DWORD map;
737 TRACE("stateblock %p, device_state %p.\n", stateblock, device_state);
739 if (stateblock->changed.vertexShader && stateblock->stateblock_state.vs != state->vs)
741 TRACE("Updating vertex shader from %p to %p.\n", stateblock->stateblock_state.vs, state->vs);
743 if (state->vs)
744 wined3d_shader_incref(state->vs);
745 if (stateblock->stateblock_state.vs)
746 wined3d_shader_decref(stateblock->stateblock_state.vs);
747 stateblock->stateblock_state.vs = state->vs;
750 for (start = 0; ; start = range.offset + range.size)
752 if (!wined3d_bitmap_get_range(stateblock->changed.vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range))
753 break;
755 memcpy(&stateblock->stateblock_state.vs_consts_f[range.offset], &state->vs_consts_f[range.offset],
756 sizeof(*state->vs_consts_f) * range.size);
758 map = stateblock->changed.vertexShaderConstantsI;
759 for (start = 0; ; start = range.offset + range.size)
761 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
762 break;
764 memcpy(&stateblock->stateblock_state.vs_consts_i[range.offset], &state->vs_consts_i[range.offset],
765 sizeof(*state->vs_consts_i) * range.size);
767 map = stateblock->changed.vertexShaderConstantsB;
768 for (start = 0; ; start = range.offset + range.size)
770 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
771 break;
773 memcpy(&stateblock->stateblock_state.vs_consts_b[range.offset], &state->vs_consts_b[range.offset],
774 sizeof(*state->vs_consts_b) * range.size);
777 for (start = 0; ; start = range.offset + range.size)
779 if (!wined3d_bitmap_get_range(stateblock->changed.ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range))
780 break;
782 memcpy(&stateblock->stateblock_state.ps_consts_f[range.offset], &state->ps_consts_f[range.offset],
783 sizeof(*state->ps_consts_f) * range.size);
785 map = stateblock->changed.pixelShaderConstantsI;
786 for (start = 0; ; start = range.offset + range.size)
788 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
789 break;
791 memcpy(&stateblock->stateblock_state.ps_consts_i[range.offset], &state->ps_consts_i[range.offset],
792 sizeof(*state->ps_consts_i) * range.size);
794 map = stateblock->changed.pixelShaderConstantsB;
795 for (start = 0; ; start = range.offset + range.size)
797 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
798 break;
800 memcpy(&stateblock->stateblock_state.ps_consts_b[range.offset], &state->ps_consts_b[range.offset],
801 sizeof(*state->ps_consts_b) * range.size);
804 if (stateblock->changed.transforms)
806 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
808 enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
810 TRACE("Updating transform %#x.\n", transform);
812 stateblock->stateblock_state.transforms[transform] = state->transforms[transform];
816 if (stateblock->changed.indices
817 && ((stateblock->stateblock_state.index_buffer != state->index_buffer)
818 || (stateblock->stateblock_state.base_vertex_index != state->base_vertex_index)
819 || (stateblock->stateblock_state.index_format != state->index_format)))
821 TRACE("Updating index buffer to %p, base vertex index to %d.\n",
822 state->index_buffer, state->base_vertex_index);
824 if (state->index_buffer)
825 wined3d_buffer_incref(state->index_buffer);
826 if (stateblock->stateblock_state.index_buffer)
827 wined3d_buffer_decref(stateblock->stateblock_state.index_buffer);
828 stateblock->stateblock_state.index_buffer = state->index_buffer;
829 stateblock->stateblock_state.base_vertex_index = state->base_vertex_index;
830 stateblock->stateblock_state.index_format = state->index_format;
833 if (stateblock->changed.vertexDecl && stateblock->stateblock_state.vertex_declaration != state->vertex_declaration)
835 TRACE("Updating vertex declaration from %p to %p.\n",
836 stateblock->stateblock_state.vertex_declaration, state->vertex_declaration);
838 if (state->vertex_declaration)
839 wined3d_vertex_declaration_incref(state->vertex_declaration);
840 if (stateblock->stateblock_state.vertex_declaration)
841 wined3d_vertex_declaration_decref(stateblock->stateblock_state.vertex_declaration);
842 stateblock->stateblock_state.vertex_declaration = state->vertex_declaration;
845 if (stateblock->changed.material
846 && memcmp(&state->material, &stateblock->stateblock_state.material,
847 sizeof(stateblock->stateblock_state.material)))
849 TRACE("Updating material.\n");
851 stateblock->stateblock_state.material = state->material;
854 if (stateblock->changed.viewport
855 && memcmp(&state->viewport, &stateblock->stateblock_state.viewport, sizeof(state->viewport)))
857 TRACE("Updating viewport.\n");
859 stateblock->stateblock_state.viewport = state->viewport;
862 if (stateblock->changed.scissorRect
863 && memcmp(&state->scissor_rect, &stateblock->stateblock_state.scissor_rect, sizeof(state->scissor_rect)))
865 TRACE("Updating scissor rect.\n");
867 stateblock->stateblock_state.scissor_rect = state->scissor_rect;
870 map = stateblock->changed.streamSource;
871 while (map)
873 i = wined3d_bit_scan(&map);
875 if (stateblock->stateblock_state.streams[i].stride != state->streams[i].stride
876 || stateblock->stateblock_state.streams[i].offset != state->streams[i].offset
877 || stateblock->stateblock_state.streams[i].buffer != state->streams[i].buffer)
879 TRACE("stateblock %p, stream source %u, buffer %p, stride %u, offset %u.\n",
880 stateblock, i, state->streams[i].buffer, state->streams[i].stride,
881 state->streams[i].offset);
883 stateblock->stateblock_state.streams[i].stride = state->streams[i].stride;
884 if (stateblock->changed.store_stream_offset)
885 stateblock->stateblock_state.streams[i].offset = state->streams[i].offset;
887 if (state->streams[i].buffer)
888 wined3d_buffer_incref(state->streams[i].buffer);
889 if (stateblock->stateblock_state.streams[i].buffer)
890 wined3d_buffer_decref(stateblock->stateblock_state.streams[i].buffer);
891 stateblock->stateblock_state.streams[i].buffer = state->streams[i].buffer;
895 map = stateblock->changed.streamFreq;
896 while (map)
898 i = wined3d_bit_scan(&map);
900 if (stateblock->stateblock_state.streams[i].frequency != state->streams[i].frequency
901 || stateblock->stateblock_state.streams[i].flags != state->streams[i].flags)
903 TRACE("Updating stream frequency %u to %u flags to %#x.\n",
904 i, state->streams[i].frequency, state->streams[i].flags);
906 stateblock->stateblock_state.streams[i].frequency = state->streams[i].frequency;
907 stateblock->stateblock_state.streams[i].flags = state->streams[i].flags;
911 map = stateblock->changed.clipplane;
912 while (map)
914 i = wined3d_bit_scan(&map);
916 if (memcmp(&stateblock->stateblock_state.clip_planes[i], &state->clip_planes[i], sizeof(state->clip_planes[i])))
918 TRACE("Updating clipplane %u.\n", i);
919 stateblock->stateblock_state.clip_planes[i] = state->clip_planes[i];
923 /* Render */
924 for (i = 0; i < stateblock->num_contained_render_states; ++i)
926 enum wined3d_render_state rs = stateblock->contained_render_states[i];
928 TRACE("Updating render state %#x to %u.\n", rs, state->rs[rs]);
930 stateblock->stateblock_state.rs[rs] = state->rs[rs];
933 /* Texture states */
934 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
936 DWORD stage = stateblock->contained_tss_states[i].stage;
937 DWORD texture_state = stateblock->contained_tss_states[i].state;
939 TRACE("Updating texturestage state %u, %u to %#x (was %#x).\n", stage, texture_state,
940 state->texture_states[stage][texture_state],
941 stateblock->stateblock_state.texture_states[stage][texture_state]);
943 stateblock->stateblock_state.texture_states[stage][texture_state] = state->texture_states[stage][texture_state];
946 /* Samplers */
947 map = stateblock->changed.textures;
948 while (map)
950 i = wined3d_bit_scan(&map);
952 TRACE("Updating texture %u to %p (was %p).\n",
953 i, state->textures[i], stateblock->stateblock_state.textures[i]);
955 if (state->textures[i])
956 wined3d_texture_incref(state->textures[i]);
957 if (stateblock->stateblock_state.textures[i])
958 wined3d_texture_decref(stateblock->stateblock_state.textures[i]);
959 stateblock->stateblock_state.textures[i] = state->textures[i];
962 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
964 DWORD stage = stateblock->contained_sampler_states[i].stage;
965 DWORD sampler_state = stateblock->contained_sampler_states[i].state;
967 TRACE("Updating sampler state %u, %u to %#x (was %#x).\n", stage, sampler_state,
968 state->sampler_states[stage][sampler_state],
969 stateblock->stateblock_state.sampler_states[stage][sampler_state]);
971 stateblock->stateblock_state.sampler_states[stage][sampler_state] = state->sampler_states[stage][sampler_state];
974 if (stateblock->changed.pixelShader && stateblock->stateblock_state.ps != state->ps)
976 if (state->ps)
977 wined3d_shader_incref(state->ps);
978 if (stateblock->stateblock_state.ps)
979 wined3d_shader_decref(stateblock->stateblock_state.ps);
980 stateblock->stateblock_state.ps = state->ps;
983 if (stateblock->changed.lights)
984 wined3d_state_record_lights(stateblock->stateblock_state.light_state, state->light_state);
986 if (stateblock->changed.alpha_to_coverage)
987 stateblock->stateblock_state.alpha_to_coverage = state->alpha_to_coverage;
989 TRACE("Capture done.\n");
992 void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock,
993 struct wined3d_stateblock *device_state)
995 const struct wined3d_stateblock_state *state = &stateblock->stateblock_state;
996 struct wined3d_range range;
997 unsigned int i, start;
998 DWORD map;
1000 TRACE("stateblock %p, device_state %p.\n", stateblock, device_state);
1002 if (stateblock->changed.vertexShader)
1003 wined3d_stateblock_set_vertex_shader(device_state, state->vs);
1004 if (stateblock->changed.pixelShader)
1005 wined3d_stateblock_set_pixel_shader(device_state, state->ps);
1007 for (start = 0; ; start = range.offset + range.size)
1009 if (!wined3d_bitmap_get_range(stateblock->changed.vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range))
1010 break;
1011 wined3d_stateblock_set_vs_consts_f(device_state, range.offset, range.size, &state->vs_consts_f[range.offset]);
1013 map = stateblock->changed.vertexShaderConstantsI;
1014 for (start = 0; ; start = range.offset + range.size)
1016 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
1017 break;
1018 wined3d_stateblock_set_vs_consts_i(device_state, range.offset, range.size, &state->vs_consts_i[range.offset]);
1020 map = stateblock->changed.vertexShaderConstantsB;
1021 for (start = 0; ; start = range.offset + range.size)
1023 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
1024 break;
1025 wined3d_stateblock_set_vs_consts_b(device_state, range.offset, range.size, &state->vs_consts_b[range.offset]);
1028 for (start = 0; ; start = range.offset + range.size)
1030 if (!wined3d_bitmap_get_range(stateblock->changed.ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range))
1031 break;
1032 wined3d_stateblock_set_ps_consts_f(device_state, range.offset, range.size, &state->ps_consts_f[range.offset]);
1034 map = stateblock->changed.pixelShaderConstantsI;
1035 for (start = 0; ; start = range.offset + range.size)
1037 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
1038 break;
1039 wined3d_stateblock_set_ps_consts_i(device_state, range.offset, range.size, &state->ps_consts_i[range.offset]);
1041 map = stateblock->changed.pixelShaderConstantsB;
1042 for (start = 0; ; start = range.offset + range.size)
1044 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
1045 break;
1046 wined3d_stateblock_set_ps_consts_b(device_state, range.offset, range.size, &state->ps_consts_b[range.offset]);
1049 if (stateblock->changed.transforms)
1051 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
1053 enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
1055 wined3d_stateblock_set_transform(device_state, transform, &state->transforms[transform]);
1059 if (stateblock->changed.lights)
1061 for (i = 0; i < ARRAY_SIZE(state->light_state->light_map); ++i)
1063 const struct wined3d_light_info *light;
1065 LIST_FOR_EACH_ENTRY(light, &state->light_state->light_map[i], struct wined3d_light_info, entry)
1067 wined3d_stateblock_set_light(device_state, light->OriginalIndex, &light->OriginalParms);
1068 wined3d_stateblock_set_light_enable(device_state, light->OriginalIndex, light->glIndex != -1);
1073 if (stateblock->changed.alpha_to_coverage)
1075 device_state->stateblock_state.alpha_to_coverage = state->alpha_to_coverage;
1076 device_state->changed.alpha_to_coverage = 1;
1079 /* Render states. */
1080 for (i = 0; i < stateblock->num_contained_render_states; ++i)
1082 enum wined3d_render_state rs = stateblock->contained_render_states[i];
1084 wined3d_stateblock_set_render_state(device_state, rs, state->rs[rs]);
1087 /* Texture states. */
1088 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
1090 DWORD stage = stateblock->contained_tss_states[i].stage;
1091 DWORD texture_state = stateblock->contained_tss_states[i].state;
1093 wined3d_stateblock_set_texture_stage_state(device_state, stage, texture_state,
1094 state->texture_states[stage][texture_state]);
1097 /* Sampler states. */
1098 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
1100 DWORD stage = stateblock->contained_sampler_states[i].stage;
1101 DWORD sampler_state = stateblock->contained_sampler_states[i].state;
1103 wined3d_stateblock_set_sampler_state(device_state, stage, sampler_state,
1104 state->sampler_states[stage][sampler_state]);
1107 if (stateblock->changed.indices)
1109 wined3d_stateblock_set_index_buffer(device_state, state->index_buffer, state->index_format);
1110 wined3d_stateblock_set_base_vertex_index(device_state, state->base_vertex_index);
1113 if (stateblock->changed.vertexDecl && state->vertex_declaration)
1114 wined3d_stateblock_set_vertex_declaration(device_state, state->vertex_declaration);
1116 if (stateblock->changed.material)
1117 wined3d_stateblock_set_material(device_state, &state->material);
1119 if (stateblock->changed.viewport)
1120 wined3d_stateblock_set_viewport(device_state, &state->viewport);
1122 if (stateblock->changed.scissorRect)
1123 wined3d_stateblock_set_scissor_rect(device_state, &state->scissor_rect);
1125 map = stateblock->changed.streamSource;
1126 while (map)
1128 i = wined3d_bit_scan(&map);
1129 wined3d_stateblock_set_stream_source(device_state, i, state->streams[i].buffer,
1130 state->streams[i].offset, state->streams[i].stride);
1133 map = stateblock->changed.streamFreq;
1134 while (map)
1136 i = wined3d_bit_scan(&map);
1137 wined3d_stateblock_set_stream_source_freq(device_state, i,
1138 state->streams[i].frequency | state->streams[i].flags);
1141 map = stateblock->changed.textures;
1142 while (map)
1144 i = wined3d_bit_scan(&map);
1145 wined3d_stateblock_set_texture(device_state, i, state->textures[i]);
1148 map = stateblock->changed.clipplane;
1149 while (map)
1151 i = wined3d_bit_scan(&map);
1152 wined3d_stateblock_set_clip_plane(device_state, i, &state->clip_planes[i]);
1155 TRACE("Applied stateblock %p.\n", stateblock);
1158 void CDECL wined3d_stateblock_set_vertex_shader(struct wined3d_stateblock *stateblock, struct wined3d_shader *shader)
1160 TRACE("stateblock %p, shader %p.\n", stateblock, shader);
1162 if (shader)
1163 wined3d_shader_incref(shader);
1164 if (stateblock->stateblock_state.vs)
1165 wined3d_shader_decref(stateblock->stateblock_state.vs);
1166 stateblock->stateblock_state.vs = shader;
1167 stateblock->changed.vertexShader = TRUE;
1170 static void wined3d_bitmap_set_bits(uint32_t *bitmap, unsigned int start, unsigned int count)
1172 const unsigned int word_bit_count = sizeof(*bitmap) * CHAR_BIT;
1173 const unsigned int shift = start % word_bit_count;
1174 uint32_t mask, last_mask;
1175 unsigned int mask_size;
1177 bitmap += start / word_bit_count;
1178 mask = ~0u << shift;
1179 mask_size = word_bit_count - shift;
1180 last_mask = (1u << (start + count) % word_bit_count) - 1;
1181 if (mask_size <= count)
1183 *bitmap |= mask;
1184 ++bitmap;
1185 count -= mask_size;
1186 mask = ~0u;
1188 if (count >= word_bit_count)
1190 memset(bitmap, 0xffu, count / word_bit_count * sizeof(*bitmap));
1191 bitmap += count / word_bit_count;
1192 count = count % word_bit_count;
1194 if (count)
1195 *bitmap |= mask & last_mask;
1198 HRESULT CDECL wined3d_stateblock_set_vs_consts_f(struct wined3d_stateblock *stateblock,
1199 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
1201 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
1203 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1204 stateblock, start_idx, count, constants);
1206 if (!constants || start_idx >= d3d_info->limits.vs_uniform_count
1207 || count > d3d_info->limits.vs_uniform_count - start_idx)
1208 return WINED3DERR_INVALIDCALL;
1210 memcpy(&stateblock->stateblock_state.vs_consts_f[start_idx], constants, count * sizeof(*constants));
1211 wined3d_bitmap_set_bits(stateblock->changed.vs_consts_f, start_idx, count);
1212 return WINED3D_OK;
1215 HRESULT CDECL wined3d_stateblock_set_vs_consts_i(struct wined3d_stateblock *stateblock,
1216 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
1218 unsigned int i;
1220 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1221 stateblock, start_idx, count, constants);
1223 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1224 return WINED3DERR_INVALIDCALL;
1226 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1227 count = WINED3D_MAX_CONSTS_I - start_idx;
1229 memcpy(&stateblock->stateblock_state.vs_consts_i[start_idx], constants, count * sizeof(*constants));
1230 for (i = start_idx; i < count + start_idx; ++i)
1231 stateblock->changed.vertexShaderConstantsI |= (1u << i);
1232 return WINED3D_OK;
1235 HRESULT CDECL wined3d_stateblock_set_vs_consts_b(struct wined3d_stateblock *stateblock,
1236 unsigned int start_idx, unsigned int count, const BOOL *constants)
1238 unsigned int i;
1240 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1241 stateblock, start_idx, count, constants);
1243 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1244 return WINED3DERR_INVALIDCALL;
1246 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1247 count = WINED3D_MAX_CONSTS_B - start_idx;
1249 memcpy(&stateblock->stateblock_state.vs_consts_b[start_idx], constants, count * sizeof(*constants));
1250 for (i = start_idx; i < count + start_idx; ++i)
1251 stateblock->changed.vertexShaderConstantsB |= (1u << i);
1252 return WINED3D_OK;
1255 void CDECL wined3d_stateblock_set_pixel_shader(struct wined3d_stateblock *stateblock, struct wined3d_shader *shader)
1257 TRACE("stateblock %p, shader %p.\n", stateblock, shader);
1259 if (shader)
1260 wined3d_shader_incref(shader);
1261 if (stateblock->stateblock_state.ps)
1262 wined3d_shader_decref(stateblock->stateblock_state.ps);
1263 stateblock->stateblock_state.ps = shader;
1264 stateblock->changed.pixelShader = TRUE;
1267 HRESULT CDECL wined3d_stateblock_set_ps_consts_f(struct wined3d_stateblock *stateblock,
1268 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
1270 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
1272 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1273 stateblock, start_idx, count, constants);
1275 if (!constants || start_idx >= d3d_info->limits.ps_uniform_count
1276 || count > d3d_info->limits.ps_uniform_count - start_idx)
1277 return WINED3DERR_INVALIDCALL;
1279 memcpy(&stateblock->stateblock_state.ps_consts_f[start_idx], constants, count * sizeof(*constants));
1280 wined3d_bitmap_set_bits(stateblock->changed.ps_consts_f, start_idx, count);
1281 return WINED3D_OK;
1284 HRESULT CDECL wined3d_stateblock_set_ps_consts_i(struct wined3d_stateblock *stateblock,
1285 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
1287 unsigned int i;
1289 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1290 stateblock, start_idx, count, constants);
1292 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1293 return WINED3DERR_INVALIDCALL;
1295 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1296 count = WINED3D_MAX_CONSTS_I - start_idx;
1298 memcpy(&stateblock->stateblock_state.ps_consts_i[start_idx], constants, count * sizeof(*constants));
1299 for (i = start_idx; i < count + start_idx; ++i)
1300 stateblock->changed.pixelShaderConstantsI |= (1u << i);
1301 return WINED3D_OK;
1304 HRESULT CDECL wined3d_stateblock_set_ps_consts_b(struct wined3d_stateblock *stateblock,
1305 unsigned int start_idx, unsigned int count, const BOOL *constants)
1307 unsigned int i;
1309 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1310 stateblock, start_idx, count, constants);
1312 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1313 return WINED3DERR_INVALIDCALL;
1315 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1316 count = WINED3D_MAX_CONSTS_B - start_idx;
1318 memcpy(&stateblock->stateblock_state.ps_consts_b[start_idx], constants, count * sizeof(*constants));
1319 for (i = start_idx; i < count + start_idx; ++i)
1320 stateblock->changed.pixelShaderConstantsB |= (1u << i);
1321 return WINED3D_OK;
1324 void CDECL wined3d_stateblock_set_vertex_declaration(struct wined3d_stateblock *stateblock,
1325 struct wined3d_vertex_declaration *declaration)
1327 TRACE("stateblock %p, declaration %p.\n", stateblock, declaration);
1329 if (declaration)
1330 wined3d_vertex_declaration_incref(declaration);
1331 if (stateblock->stateblock_state.vertex_declaration)
1332 wined3d_vertex_declaration_decref(stateblock->stateblock_state.vertex_declaration);
1333 stateblock->stateblock_state.vertex_declaration = declaration;
1334 stateblock->changed.vertexDecl = TRUE;
1337 void CDECL wined3d_stateblock_set_render_state(struct wined3d_stateblock *stateblock,
1338 enum wined3d_render_state state, DWORD value)
1340 TRACE("stateblock %p, state %s (%#x), value %#x.\n", stateblock, debug_d3drenderstate(state), state, value);
1342 if (state > WINEHIGHEST_RENDER_STATE)
1344 WARN("Unhandled render state %#x.\n", state);
1345 return;
1348 stateblock->stateblock_state.rs[state] = value;
1349 stateblock->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
1351 if (state == WINED3D_RS_POINTSIZE
1352 && (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE || value == WINED3D_ALPHA_TO_COVERAGE_DISABLE))
1354 stateblock->changed.alpha_to_coverage = 1;
1355 stateblock->stateblock_state.alpha_to_coverage = (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE);
1359 void CDECL wined3d_stateblock_set_sampler_state(struct wined3d_stateblock *stateblock,
1360 UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
1362 TRACE("stateblock %p, sampler_idx %u, state %s, value %#x.\n",
1363 stateblock, sampler_idx, debug_d3dsamplerstate(state), value);
1365 if (sampler_idx >= ARRAY_SIZE(stateblock->stateblock_state.sampler_states))
1367 WARN("Invalid sampler %u.\n", sampler_idx);
1368 return;
1371 stateblock->stateblock_state.sampler_states[sampler_idx][state] = value;
1372 stateblock->changed.samplerState[sampler_idx] |= 1u << state;
1375 void CDECL wined3d_stateblock_set_texture_stage_state(struct wined3d_stateblock *stateblock,
1376 UINT stage, enum wined3d_texture_stage_state state, DWORD value)
1378 TRACE("stateblock %p, stage %u, state %s, value %#x.\n",
1379 stateblock, stage, debug_d3dtexturestate(state), value);
1381 if (state > WINED3D_HIGHEST_TEXTURE_STATE)
1383 WARN("Invalid state %#x passed.\n", state);
1384 return;
1387 if (stage >= WINED3D_MAX_TEXTURES)
1389 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
1390 stage, WINED3D_MAX_TEXTURES - 1);
1391 return;
1394 stateblock->stateblock_state.texture_states[stage][state] = value;
1395 stateblock->changed.textureState[stage] |= 1u << state;
1398 void CDECL wined3d_stateblock_set_texture(struct wined3d_stateblock *stateblock,
1399 UINT stage, struct wined3d_texture *texture)
1401 TRACE("stateblock %p, stage %u, texture %p.\n", stateblock, stage, texture);
1403 if (stage >= ARRAY_SIZE(stateblock->stateblock_state.textures))
1405 WARN("Ignoring invalid stage %u.\n", stage);
1406 return;
1409 if (texture)
1410 wined3d_texture_incref(texture);
1411 if (stateblock->stateblock_state.textures[stage])
1412 wined3d_texture_decref(stateblock->stateblock_state.textures[stage]);
1413 stateblock->stateblock_state.textures[stage] = texture;
1414 stateblock->changed.textures |= 1u << stage;
1417 void CDECL wined3d_stateblock_set_transform(struct wined3d_stateblock *stateblock,
1418 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1420 TRACE("stateblock %p, state %s, matrix %p.\n", stateblock, debug_d3dtstype(d3dts), matrix);
1421 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1422 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1423 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1424 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1426 stateblock->stateblock_state.transforms[d3dts] = *matrix;
1427 stateblock->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1428 stateblock->changed.transforms = 1;
1431 void CDECL wined3d_stateblock_multiply_transform(struct wined3d_stateblock *stateblock,
1432 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1434 struct wined3d_matrix *mat = &stateblock->stateblock_state.transforms[d3dts];
1436 TRACE("stateblock %p, state %s, matrix %p.\n", stateblock, debug_d3dtstype(d3dts), matrix);
1437 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1438 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1439 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1440 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1442 multiply_matrix(mat, mat, matrix);
1443 stateblock->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1444 stateblock->changed.transforms = 1;
1447 HRESULT CDECL wined3d_stateblock_set_clip_plane(struct wined3d_stateblock *stateblock,
1448 UINT plane_idx, const struct wined3d_vec4 *plane)
1450 TRACE("stateblock %p, plane_idx %u, plane %p.\n", stateblock, plane_idx, plane);
1452 if (plane_idx >= stateblock->device->adapter->d3d_info.limits.max_clip_distances)
1454 TRACE("Application has requested clipplane this device doesn't support.\n");
1455 return WINED3DERR_INVALIDCALL;
1458 stateblock->stateblock_state.clip_planes[plane_idx] = *plane;
1459 stateblock->changed.clipplane |= 1u << plane_idx;
1460 return S_OK;
1463 void CDECL wined3d_stateblock_set_material(struct wined3d_stateblock *stateblock,
1464 const struct wined3d_material *material)
1466 TRACE("stateblock %p, material %p.\n", stateblock, material);
1468 stateblock->stateblock_state.material = *material;
1469 stateblock->changed.material = TRUE;
1472 void CDECL wined3d_stateblock_set_viewport(struct wined3d_stateblock *stateblock,
1473 const struct wined3d_viewport *viewport)
1475 TRACE("stateblock %p, viewport %p.\n", stateblock, viewport);
1477 stateblock->stateblock_state.viewport = *viewport;
1478 stateblock->changed.viewport = TRUE;
1481 void CDECL wined3d_stateblock_set_scissor_rect(struct wined3d_stateblock *stateblock, const RECT *rect)
1483 TRACE("stateblock %p, rect %s.\n", stateblock, wine_dbgstr_rect(rect));
1485 stateblock->stateblock_state.scissor_rect = *rect;
1486 stateblock->changed.scissorRect = TRUE;
1489 void CDECL wined3d_stateblock_set_index_buffer(struct wined3d_stateblock *stateblock,
1490 struct wined3d_buffer *buffer, enum wined3d_format_id format_id)
1492 TRACE("stateblock %p, buffer %p, format %s.\n", stateblock, buffer, debug_d3dformat(format_id));
1494 if (buffer)
1495 wined3d_buffer_incref(buffer);
1496 if (stateblock->stateblock_state.index_buffer)
1497 wined3d_buffer_decref(stateblock->stateblock_state.index_buffer);
1498 stateblock->stateblock_state.index_buffer = buffer;
1499 stateblock->stateblock_state.index_format = format_id;
1500 stateblock->changed.indices = TRUE;
1503 void CDECL wined3d_stateblock_set_base_vertex_index(struct wined3d_stateblock *stateblock, INT base_index)
1505 TRACE("stateblock %p, base_index %d.\n", stateblock, base_index);
1507 stateblock->stateblock_state.base_vertex_index = base_index;
1510 HRESULT CDECL wined3d_stateblock_set_stream_source(struct wined3d_stateblock *stateblock,
1511 UINT stream_idx, struct wined3d_buffer *buffer, UINT offset, UINT stride)
1513 struct wined3d_stream_state *stream;
1515 TRACE("stateblock %p, stream_idx %u, buffer %p, stride %u.\n",
1516 stateblock, stream_idx, buffer, stride);
1518 if (stream_idx >= WINED3D_MAX_STREAMS)
1520 WARN("Stream index %u out of range.\n", stream_idx);
1521 return WINED3DERR_INVALIDCALL;
1524 stream = &stateblock->stateblock_state.streams[stream_idx];
1526 if (buffer)
1527 wined3d_buffer_incref(buffer);
1528 if (stream->buffer)
1529 wined3d_buffer_decref(stream->buffer);
1530 stream->buffer = buffer;
1531 stream->stride = stride;
1532 stream->offset = offset;
1533 stateblock->changed.streamSource |= 1u << stream_idx;
1534 return WINED3D_OK;
1537 HRESULT CDECL wined3d_stateblock_set_stream_source_freq(struct wined3d_stateblock *stateblock,
1538 UINT stream_idx, UINT divider)
1540 struct wined3d_stream_state *stream;
1542 TRACE("stateblock %p, stream_idx %u, divider %#x.\n", stateblock, stream_idx, divider);
1544 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (divider & WINED3DSTREAMSOURCE_INDEXEDDATA))
1546 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
1547 return WINED3DERR_INVALIDCALL;
1549 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
1551 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
1552 return WINED3DERR_INVALIDCALL;
1554 if (!divider)
1556 WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
1557 return WINED3DERR_INVALIDCALL;
1560 stream = &stateblock->stateblock_state.streams[stream_idx];
1561 stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA);
1562 stream->frequency = divider & 0x7fffff;
1563 stateblock->changed.streamFreq |= 1u << stream_idx;
1564 return WINED3D_OK;
1567 HRESULT CDECL wined3d_stateblock_set_light(struct wined3d_stateblock *stateblock,
1568 UINT light_idx, const struct wined3d_light *light)
1570 struct wined3d_light_info *object = NULL;
1572 TRACE("stateblock %p, light_idx %u, light %p.\n", stateblock, light_idx, light);
1574 /* Check the parameter range. Need for speed most wanted sets junk lights
1575 * which confuse the GL driver. */
1576 if (!light)
1577 return WINED3DERR_INVALIDCALL;
1579 switch (light->type)
1581 case WINED3D_LIGHT_POINT:
1582 case WINED3D_LIGHT_SPOT:
1583 case WINED3D_LIGHT_GLSPOT:
1584 /* Incorrect attenuation values can cause the gl driver to crash.
1585 * Happens with Need for speed most wanted. */
1586 if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
1588 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
1589 return WINED3DERR_INVALIDCALL;
1591 break;
1593 case WINED3D_LIGHT_DIRECTIONAL:
1594 case WINED3D_LIGHT_PARALLELPOINT:
1595 /* Ignores attenuation */
1596 break;
1598 default:
1599 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL.\n");
1600 return WINED3DERR_INVALIDCALL;
1603 stateblock->changed.lights = 1;
1604 return wined3d_light_state_set_light(stateblock->stateblock_state.light_state, light_idx, light, &object);
1607 HRESULT CDECL wined3d_stateblock_set_light_enable(struct wined3d_stateblock *stateblock, UINT light_idx, BOOL enable)
1609 struct wined3d_light_state *light_state = stateblock->stateblock_state.light_state;
1610 struct wined3d_light_info *light_info;
1611 HRESULT hr;
1613 TRACE("stateblock %p, light_idx %u, enable %#x.\n", stateblock, light_idx, enable);
1615 if (!(light_info = wined3d_light_state_get_light(light_state, light_idx)))
1617 if (FAILED(hr = wined3d_light_state_set_light(light_state, light_idx, &WINED3D_default_light, &light_info)))
1618 return hr;
1620 wined3d_light_state_enable_light(light_state, &stateblock->device->adapter->d3d_info, light_info, enable);
1621 stateblock->changed.lights = 1;
1622 return S_OK;
1625 const struct wined3d_stateblock_state * CDECL wined3d_stateblock_get_state(const struct wined3d_stateblock *stateblock)
1627 return &stateblock->stateblock_state;
1630 HRESULT CDECL wined3d_stateblock_get_light(const struct wined3d_stateblock *stateblock,
1631 UINT light_idx, struct wined3d_light *light, BOOL *enabled)
1633 struct wined3d_light_info *light_info;
1635 if (!(light_info = wined3d_light_state_get_light(&stateblock->light_state, light_idx)))
1637 TRACE("Light %u is not defined.\n", light_idx);
1638 return WINED3DERR_INVALIDCALL;
1640 *light = light_info->OriginalParms;
1641 *enabled = light_info->enabled ? 128 : 0;
1642 return WINED3D_OK;
1645 static void init_default_render_states(DWORD rs[WINEHIGHEST_RENDER_STATE + 1], const struct wined3d_d3d_info *d3d_info)
1647 union
1649 struct wined3d_line_pattern lp;
1650 DWORD d;
1651 } lp;
1652 union
1654 float f;
1655 DWORD d;
1656 } tmpfloat;
1658 rs[WINED3D_RS_ZENABLE] = WINED3D_ZB_TRUE;
1659 rs[WINED3D_RS_FILLMODE] = WINED3D_FILL_SOLID;
1660 rs[WINED3D_RS_SHADEMODE] = WINED3D_SHADE_GOURAUD;
1661 lp.lp.repeat_factor = 0;
1662 lp.lp.line_pattern = 0;
1663 rs[WINED3D_RS_LINEPATTERN] = lp.d;
1664 rs[WINED3D_RS_ZWRITEENABLE] = TRUE;
1665 rs[WINED3D_RS_ALPHATESTENABLE] = FALSE;
1666 rs[WINED3D_RS_LASTPIXEL] = TRUE;
1667 rs[WINED3D_RS_SRCBLEND] = WINED3D_BLEND_ONE;
1668 rs[WINED3D_RS_DESTBLEND] = WINED3D_BLEND_ZERO;
1669 rs[WINED3D_RS_CULLMODE] = WINED3D_CULL_BACK;
1670 rs[WINED3D_RS_ZFUNC] = WINED3D_CMP_LESSEQUAL;
1671 rs[WINED3D_RS_ALPHAFUNC] = WINED3D_CMP_ALWAYS;
1672 rs[WINED3D_RS_ALPHAREF] = 0;
1673 rs[WINED3D_RS_DITHERENABLE] = FALSE;
1674 rs[WINED3D_RS_ALPHABLENDENABLE] = FALSE;
1675 rs[WINED3D_RS_FOGENABLE] = FALSE;
1676 rs[WINED3D_RS_SPECULARENABLE] = FALSE;
1677 rs[WINED3D_RS_ZVISIBLE] = 0;
1678 rs[WINED3D_RS_FOGCOLOR] = 0;
1679 rs[WINED3D_RS_FOGTABLEMODE] = WINED3D_FOG_NONE;
1680 tmpfloat.f = 0.0f;
1681 rs[WINED3D_RS_FOGSTART] = tmpfloat.d;
1682 tmpfloat.f = 1.0f;
1683 rs[WINED3D_RS_FOGEND] = tmpfloat.d;
1684 tmpfloat.f = 1.0f;
1685 rs[WINED3D_RS_FOGDENSITY] = tmpfloat.d;
1686 rs[WINED3D_RS_RANGEFOGENABLE] = FALSE;
1687 rs[WINED3D_RS_STENCILENABLE] = FALSE;
1688 rs[WINED3D_RS_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1689 rs[WINED3D_RS_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1690 rs[WINED3D_RS_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1691 rs[WINED3D_RS_STENCILREF] = 0;
1692 rs[WINED3D_RS_STENCILMASK] = 0xffffffff;
1693 rs[WINED3D_RS_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1694 rs[WINED3D_RS_STENCILWRITEMASK] = 0xffffffff;
1695 rs[WINED3D_RS_TEXTUREFACTOR] = 0xffffffff;
1696 rs[WINED3D_RS_WRAP0] = 0;
1697 rs[WINED3D_RS_WRAP1] = 0;
1698 rs[WINED3D_RS_WRAP2] = 0;
1699 rs[WINED3D_RS_WRAP3] = 0;
1700 rs[WINED3D_RS_WRAP4] = 0;
1701 rs[WINED3D_RS_WRAP5] = 0;
1702 rs[WINED3D_RS_WRAP6] = 0;
1703 rs[WINED3D_RS_WRAP7] = 0;
1704 rs[WINED3D_RS_CLIPPING] = TRUE;
1705 rs[WINED3D_RS_LIGHTING] = TRUE;
1706 rs[WINED3D_RS_AMBIENT] = 0;
1707 rs[WINED3D_RS_FOGVERTEXMODE] = WINED3D_FOG_NONE;
1708 rs[WINED3D_RS_COLORVERTEX] = TRUE;
1709 rs[WINED3D_RS_LOCALVIEWER] = TRUE;
1710 rs[WINED3D_RS_NORMALIZENORMALS] = FALSE;
1711 rs[WINED3D_RS_DIFFUSEMATERIALSOURCE] = WINED3D_MCS_COLOR1;
1712 rs[WINED3D_RS_SPECULARMATERIALSOURCE] = WINED3D_MCS_COLOR2;
1713 rs[WINED3D_RS_AMBIENTMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1714 rs[WINED3D_RS_EMISSIVEMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1715 rs[WINED3D_RS_VERTEXBLEND] = WINED3D_VBF_DISABLE;
1716 rs[WINED3D_RS_CLIPPLANEENABLE] = 0;
1717 rs[WINED3D_RS_SOFTWAREVERTEXPROCESSING] = FALSE;
1718 tmpfloat.f = 1.0f;
1719 rs[WINED3D_RS_POINTSIZE] = tmpfloat.d;
1720 tmpfloat.f = 1.0f;
1721 rs[WINED3D_RS_POINTSIZE_MIN] = tmpfloat.d;
1722 rs[WINED3D_RS_POINTSPRITEENABLE] = FALSE;
1723 rs[WINED3D_RS_POINTSCALEENABLE] = FALSE;
1724 tmpfloat.f = 1.0f;
1725 rs[WINED3D_RS_POINTSCALE_A] = tmpfloat.d;
1726 tmpfloat.f = 0.0f;
1727 rs[WINED3D_RS_POINTSCALE_B] = tmpfloat.d;
1728 tmpfloat.f = 0.0f;
1729 rs[WINED3D_RS_POINTSCALE_C] = tmpfloat.d;
1730 rs[WINED3D_RS_MULTISAMPLEANTIALIAS] = TRUE;
1731 rs[WINED3D_RS_MULTISAMPLEMASK] = 0xffffffff;
1732 rs[WINED3D_RS_PATCHEDGESTYLE] = WINED3D_PATCH_EDGE_DISCRETE;
1733 tmpfloat.f = 1.0f;
1734 rs[WINED3D_RS_PATCHSEGMENTS] = tmpfloat.d;
1735 rs[WINED3D_RS_DEBUGMONITORTOKEN] = 0xbaadcafe;
1736 tmpfloat.f = d3d_info->limits.pointsize_max;
1737 rs[WINED3D_RS_POINTSIZE_MAX] = tmpfloat.d;
1738 rs[WINED3D_RS_INDEXEDVERTEXBLENDENABLE] = FALSE;
1739 rs[WINED3D_RS_COLORWRITEENABLE] = 0x0000000f;
1740 tmpfloat.f = 0.0f;
1741 rs[WINED3D_RS_TWEENFACTOR] = tmpfloat.d;
1742 rs[WINED3D_RS_BLENDOP] = WINED3D_BLEND_OP_ADD;
1743 rs[WINED3D_RS_POSITIONDEGREE] = WINED3D_DEGREE_CUBIC;
1744 rs[WINED3D_RS_NORMALDEGREE] = WINED3D_DEGREE_LINEAR;
1745 /* states new in d3d9 */
1746 rs[WINED3D_RS_SCISSORTESTENABLE] = FALSE;
1747 rs[WINED3D_RS_SLOPESCALEDEPTHBIAS] = 0;
1748 tmpfloat.f = 1.0f;
1749 rs[WINED3D_RS_MINTESSELLATIONLEVEL] = tmpfloat.d;
1750 rs[WINED3D_RS_MAXTESSELLATIONLEVEL] = tmpfloat.d;
1751 rs[WINED3D_RS_ANTIALIASEDLINEENABLE] = FALSE;
1752 tmpfloat.f = 0.0f;
1753 rs[WINED3D_RS_ADAPTIVETESS_X] = tmpfloat.d;
1754 rs[WINED3D_RS_ADAPTIVETESS_Y] = tmpfloat.d;
1755 tmpfloat.f = 1.0f;
1756 rs[WINED3D_RS_ADAPTIVETESS_Z] = tmpfloat.d;
1757 tmpfloat.f = 0.0f;
1758 rs[WINED3D_RS_ADAPTIVETESS_W] = tmpfloat.d;
1759 rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION] = FALSE;
1760 rs[WINED3D_RS_TWOSIDEDSTENCILMODE] = FALSE;
1761 rs[WINED3D_RS_BACK_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1762 rs[WINED3D_RS_BACK_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1763 rs[WINED3D_RS_BACK_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1764 rs[WINED3D_RS_BACK_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1765 rs[WINED3D_RS_COLORWRITEENABLE1] = 0x0000000f;
1766 rs[WINED3D_RS_COLORWRITEENABLE2] = 0x0000000f;
1767 rs[WINED3D_RS_COLORWRITEENABLE3] = 0x0000000f;
1768 rs[WINED3D_RS_BLENDFACTOR] = 0xffffffff;
1769 rs[WINED3D_RS_SRGBWRITEENABLE] = 0;
1770 rs[WINED3D_RS_DEPTHBIAS] = 0;
1771 rs[WINED3D_RS_WRAP8] = 0;
1772 rs[WINED3D_RS_WRAP9] = 0;
1773 rs[WINED3D_RS_WRAP10] = 0;
1774 rs[WINED3D_RS_WRAP11] = 0;
1775 rs[WINED3D_RS_WRAP12] = 0;
1776 rs[WINED3D_RS_WRAP13] = 0;
1777 rs[WINED3D_RS_WRAP14] = 0;
1778 rs[WINED3D_RS_WRAP15] = 0;
1779 rs[WINED3D_RS_SEPARATEALPHABLENDENABLE] = FALSE;
1780 rs[WINED3D_RS_SRCBLENDALPHA] = WINED3D_BLEND_ONE;
1781 rs[WINED3D_RS_DESTBLENDALPHA] = WINED3D_BLEND_ZERO;
1782 rs[WINED3D_RS_BLENDOPALPHA] = WINED3D_BLEND_OP_ADD;
1785 static void init_default_texture_state(unsigned int i, DWORD stage[WINED3D_HIGHEST_TEXTURE_STATE + 1])
1787 stage[WINED3D_TSS_COLOR_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_MODULATE;
1788 stage[WINED3D_TSS_COLOR_ARG1] = WINED3DTA_TEXTURE;
1789 stage[WINED3D_TSS_COLOR_ARG2] = WINED3DTA_CURRENT;
1790 stage[WINED3D_TSS_ALPHA_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_SELECT_ARG1;
1791 stage[WINED3D_TSS_ALPHA_ARG1] = WINED3DTA_TEXTURE;
1792 stage[WINED3D_TSS_ALPHA_ARG2] = WINED3DTA_CURRENT;
1793 stage[WINED3D_TSS_BUMPENV_MAT00] = 0;
1794 stage[WINED3D_TSS_BUMPENV_MAT01] = 0;
1795 stage[WINED3D_TSS_BUMPENV_MAT10] = 0;
1796 stage[WINED3D_TSS_BUMPENV_MAT11] = 0;
1797 stage[WINED3D_TSS_TEXCOORD_INDEX] = i;
1798 stage[WINED3D_TSS_BUMPENV_LSCALE] = 0;
1799 stage[WINED3D_TSS_BUMPENV_LOFFSET] = 0;
1800 stage[WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS] = WINED3D_TTFF_DISABLE;
1801 stage[WINED3D_TSS_COLOR_ARG0] = WINED3DTA_CURRENT;
1802 stage[WINED3D_TSS_ALPHA_ARG0] = WINED3DTA_CURRENT;
1803 stage[WINED3D_TSS_RESULT_ARG] = WINED3DTA_CURRENT;
1806 static void init_default_sampler_states(DWORD states[WINED3D_MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1])
1808 unsigned int i;
1810 for (i = 0 ; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
1812 TRACE("Setting up default samplers states for sampler %u.\n", i);
1813 states[i][WINED3D_SAMP_ADDRESS_U] = WINED3D_TADDRESS_WRAP;
1814 states[i][WINED3D_SAMP_ADDRESS_V] = WINED3D_TADDRESS_WRAP;
1815 states[i][WINED3D_SAMP_ADDRESS_W] = WINED3D_TADDRESS_WRAP;
1816 states[i][WINED3D_SAMP_BORDER_COLOR] = 0;
1817 states[i][WINED3D_SAMP_MAG_FILTER] = WINED3D_TEXF_POINT;
1818 states[i][WINED3D_SAMP_MIN_FILTER] = WINED3D_TEXF_POINT;
1819 states[i][WINED3D_SAMP_MIP_FILTER] = WINED3D_TEXF_NONE;
1820 states[i][WINED3D_SAMP_MIPMAP_LOD_BIAS] = 0;
1821 states[i][WINED3D_SAMP_MAX_MIP_LEVEL] = 0;
1822 states[i][WINED3D_SAMP_MAX_ANISOTROPY] = 1;
1823 states[i][WINED3D_SAMP_SRGB_TEXTURE] = 0;
1824 /* TODO: Indicates which element of a multielement texture to use. */
1825 states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0;
1826 /* TODO: Vertex offset in the presampled displacement map. */
1827 states[i][WINED3D_SAMP_DMAP_OFFSET] = 0;
1831 static void state_init_default(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info)
1833 unsigned int i;
1834 struct wined3d_matrix identity;
1836 TRACE("state %p, d3d_info %p.\n", state, d3d_info);
1838 get_identity_matrix(&identity);
1839 state->primitive_type = WINED3D_PT_UNDEFINED;
1840 state->patch_vertex_count = 0;
1842 /* Set some of the defaults for lights, transforms etc */
1843 state->transforms[WINED3D_TS_PROJECTION] = identity;
1844 state->transforms[WINED3D_TS_VIEW] = identity;
1845 for (i = 0; i < 256; ++i)
1847 state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
1850 init_default_render_states(state->render_states, d3d_info);
1852 /* Texture Stage States - Put directly into state block, we will call function below */
1853 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i)
1855 TRACE("Setting up default texture states for texture Stage %u.\n", i);
1856 state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
1857 init_default_texture_state(i, state->texture_states[i]);
1860 init_default_sampler_states(state->sampler_states);
1862 state->blend_factor.r = 1.0f;
1863 state->blend_factor.g = 1.0f;
1864 state->blend_factor.b = 1.0f;
1865 state->blend_factor.a = 1.0f;
1867 state->sample_mask = 0xffffffff;
1869 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
1870 state->streams[i].frequency = 1;
1873 void state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info, DWORD flags)
1875 unsigned int i;
1877 state->flags = flags;
1879 for (i = 0; i < LIGHTMAP_SIZE; i++)
1881 list_init(&state->light_state.light_map[i]);
1884 if (flags & WINED3D_STATE_INIT_DEFAULT)
1885 state_init_default(state, d3d_info);
1888 HRESULT CDECL wined3d_state_create(struct wined3d_device *device, struct wined3d_state **state)
1890 struct wined3d_state *object;
1892 TRACE("device %p, state %p.\n", device, state);
1894 if (!(object = heap_alloc_zero(sizeof(*object))))
1895 return E_OUTOFMEMORY;
1896 state_init(object, &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT);
1898 *state = object;
1899 return S_OK;
1902 void CDECL wined3d_state_destroy(struct wined3d_state *state)
1904 TRACE("state %p.\n", state);
1906 state_cleanup(state);
1907 heap_free(state);
1910 static void stateblock_state_init_default(struct wined3d_stateblock_state *state,
1911 const struct wined3d_d3d_info *d3d_info)
1913 struct wined3d_matrix identity;
1914 unsigned int i;
1916 get_identity_matrix(&identity);
1918 state->transforms[WINED3D_TS_PROJECTION] = identity;
1919 state->transforms[WINED3D_TS_VIEW] = identity;
1920 for (i = 0; i < 256; ++i)
1922 state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
1925 init_default_render_states(state->rs, d3d_info);
1927 for (i = 0; i < WINED3D_MAX_TEXTURES; ++i)
1929 state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
1930 init_default_texture_state(i, state->texture_states[i]);
1933 init_default_sampler_states(state->sampler_states);
1935 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
1936 state->streams[i].frequency = 1;
1939 void wined3d_stateblock_state_init(struct wined3d_stateblock_state *state,
1940 const struct wined3d_device *device, DWORD flags)
1942 unsigned int i;
1944 for (i = 0; i < ARRAY_SIZE(state->light_state->light_map); i++)
1946 list_init(&state->light_state->light_map[i]);
1949 if (flags & WINED3D_STATE_INIT_DEFAULT)
1950 stateblock_state_init_default(state, &device->adapter->d3d_info);
1954 static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const struct wined3d_stateblock *device_state,
1955 struct wined3d_device *device, enum wined3d_stateblock_type type)
1957 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
1959 stateblock->ref = 1;
1960 stateblock->device = device;
1961 stateblock->stateblock_state.light_state = &stateblock->light_state;
1962 wined3d_stateblock_state_init(&stateblock->stateblock_state, device,
1963 type == WINED3D_SBT_PRIMARY ? WINED3D_STATE_INIT_DEFAULT : 0);
1965 stateblock->changed.store_stream_offset = 1;
1967 if (type == WINED3D_SBT_RECORDED || type == WINED3D_SBT_PRIMARY)
1968 return WINED3D_OK;
1970 TRACE("Updating changed flags appropriate for type %#x.\n", type);
1972 switch (type)
1974 case WINED3D_SBT_ALL:
1975 stateblock_init_lights(stateblock->stateblock_state.light_state->light_map,
1976 device_state->stateblock_state.light_state->light_map);
1977 stateblock_savedstates_set_all(&stateblock->changed,
1978 d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
1979 break;
1981 case WINED3D_SBT_PIXEL_STATE:
1982 stateblock_savedstates_set_pixel(&stateblock->changed,
1983 d3d_info->limits.ps_uniform_count);
1984 break;
1986 case WINED3D_SBT_VERTEX_STATE:
1987 stateblock_init_lights(stateblock->stateblock_state.light_state->light_map,
1988 device_state->stateblock_state.light_state->light_map);
1989 stateblock_savedstates_set_vertex(&stateblock->changed,
1990 d3d_info->limits.vs_uniform_count);
1991 break;
1993 default:
1994 FIXME("Unrecognized state block type %#x.\n", type);
1995 break;
1998 wined3d_stateblock_init_contained_states(stateblock);
1999 wined3d_stateblock_capture(stateblock, device_state);
2001 /* According to the tests, stream offset is not updated in the captured state if
2002 * the state was captured on state block creation. This is not the case for
2003 * state blocks initialized with BeginStateBlock / EndStateBlock, multiple
2004 * captures get stream offsets updated. */
2005 stateblock->changed.store_stream_offset = 0;
2007 return WINED3D_OK;
2010 HRESULT CDECL wined3d_stateblock_create(struct wined3d_device *device, const struct wined3d_stateblock *device_state,
2011 enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock)
2013 struct wined3d_stateblock *object;
2014 HRESULT hr;
2016 TRACE("device %p, device_state %p, type %#x, stateblock %p.\n",
2017 device, device_state, type, stateblock);
2019 if (!(object = heap_alloc_zero(sizeof(*object))))
2020 return E_OUTOFMEMORY;
2022 hr = stateblock_init(object, device_state, device, type);
2023 if (FAILED(hr))
2025 WARN("Failed to initialize stateblock, hr %#x.\n", hr);
2026 heap_free(object);
2027 return hr;
2030 TRACE("Created stateblock %p.\n", object);
2031 *stateblock = object;
2033 return WINED3D_OK;
2036 void CDECL wined3d_stateblock_reset(struct wined3d_stateblock *stateblock)
2038 TRACE("stateblock %p.\n", stateblock);
2040 wined3d_stateblock_state_cleanup(&stateblock->stateblock_state);
2041 memset(&stateblock->stateblock_state, 0, sizeof(stateblock->stateblock_state));
2042 stateblock->stateblock_state.light_state = &stateblock->light_state;
2043 wined3d_stateblock_state_init(&stateblock->stateblock_state, stateblock->device, WINED3D_STATE_INIT_DEFAULT);