include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / wined3d / stateblock.c
blob548bf9aa477c854202cc205c49d3110f371ea4b0
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
9 * Copyright 2019,2020,2022 Zebediah Figura for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 WINE_DECLARE_DEBUG_CHANNEL(winediag);
31 struct wined3d_saved_states
33 struct list changed_lights;
35 uint32_t vs_consts_f[WINED3D_BITMAP_SIZE(WINED3D_MAX_VS_CONSTS_F)];
36 uint16_t vertexShaderConstantsI; /* WINED3D_MAX_CONSTS_I, 16 */
37 uint16_t vertexShaderConstantsB; /* WINED3D_MAX_CONSTS_B, 16 */
38 uint32_t ps_consts_f[WINED3D_BITMAP_SIZE(WINED3D_MAX_PS_CONSTS_F)];
39 uint16_t pixelShaderConstantsI; /* WINED3D_MAX_CONSTS_I, 16 */
40 uint16_t pixelShaderConstantsB; /* WINED3D_MAX_CONSTS_B, 16 */
41 uint32_t transform[WINED3D_BITMAP_SIZE(WINED3D_HIGHEST_TRANSFORM_STATE + 1)];
42 uint16_t streamSource; /* WINED3D_MAX_STREAMS, 16 */
43 uint16_t streamFreq; /* WINED3D_MAX_STREAMS, 16 */
44 uint32_t renderState[WINED3D_BITMAP_SIZE(WINEHIGHEST_RENDER_STATE + 1)];
45 uint32_t textureState[WINED3D_MAX_FFP_TEXTURES]; /* WINED3D_HIGHEST_TEXTURE_STATE + 1, 18 */
46 uint16_t samplerState[WINED3D_MAX_COMBINED_SAMPLERS]; /* WINED3D_HIGHEST_SAMPLER_STATE + 1, 14 */
47 uint32_t clipplane; /* WINED3D_MAX_CLIP_DISTANCES, 8 */
48 uint32_t textures : 20; /* WINED3D_MAX_COMBINED_SAMPLERS, 20 */
49 uint32_t indices : 1;
50 uint32_t material : 1;
51 uint32_t viewport : 1;
52 uint32_t vertexDecl : 1;
53 uint32_t pixelShader : 1;
54 uint32_t vertexShader : 1;
55 uint32_t scissorRect : 1;
56 uint32_t store_stream_offset : 1;
57 uint32_t alpha_to_coverage : 1;
58 uint32_t lights : 1;
59 uint32_t transforms : 1;
61 /* Flags only consumed by wined3d_device_apply_stateblock(), concerned with
62 * translation from stateblock formats to wined3d_state formats. */
63 uint32_t ffp_ps_constants : 1;
66 struct stage_state
68 unsigned int stage, state;
71 struct wined3d_stateblock
73 LONG ref;
74 struct wined3d_device *device;
76 struct wined3d_saved_states changed;
78 struct wined3d_stateblock_state stateblock_state;
79 struct wined3d_light_state light_state;
81 unsigned int contained_render_states[WINEHIGHEST_RENDER_STATE + 1];
82 unsigned int num_contained_render_states;
83 unsigned int contained_transform_states[WINED3D_HIGHEST_TRANSFORM_STATE + 1];
84 unsigned int num_contained_transform_states;
85 struct stage_state contained_tss_states[WINED3D_MAX_FFP_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)];
86 unsigned int num_contained_tss_states;
87 struct stage_state contained_sampler_states[WINED3D_MAX_COMBINED_SAMPLERS * WINED3D_HIGHEST_SAMPLER_STATE];
88 unsigned int num_contained_sampler_states;
91 static const DWORD pixel_states_render[] =
93 WINED3D_RS_ALPHABLENDENABLE,
94 WINED3D_RS_ALPHAFUNC,
95 WINED3D_RS_ALPHAREF,
96 WINED3D_RS_ALPHATESTENABLE,
97 WINED3D_RS_ANTIALIASEDLINEENABLE,
98 WINED3D_RS_BLENDFACTOR,
99 WINED3D_RS_BLENDOP,
100 WINED3D_RS_BLENDOPALPHA,
101 WINED3D_RS_BACK_STENCILFAIL,
102 WINED3D_RS_BACK_STENCILPASS,
103 WINED3D_RS_BACK_STENCILZFAIL,
104 WINED3D_RS_COLORWRITEENABLE,
105 WINED3D_RS_COLORWRITEENABLE1,
106 WINED3D_RS_COLORWRITEENABLE2,
107 WINED3D_RS_COLORWRITEENABLE3,
108 WINED3D_RS_DEPTHBIAS,
109 WINED3D_RS_DESTBLEND,
110 WINED3D_RS_DESTBLENDALPHA,
111 WINED3D_RS_DITHERENABLE,
112 WINED3D_RS_FILLMODE,
113 WINED3D_RS_FOGDENSITY,
114 WINED3D_RS_FOGEND,
115 WINED3D_RS_FOGSTART,
116 WINED3D_RS_LASTPIXEL,
117 WINED3D_RS_SCISSORTESTENABLE,
118 WINED3D_RS_SEPARATEALPHABLENDENABLE,
119 WINED3D_RS_SHADEMODE,
120 WINED3D_RS_SLOPESCALEDEPTHBIAS,
121 WINED3D_RS_SRCBLEND,
122 WINED3D_RS_SRCBLENDALPHA,
123 WINED3D_RS_SRGBWRITEENABLE,
124 WINED3D_RS_STENCILENABLE,
125 WINED3D_RS_STENCILFAIL,
126 WINED3D_RS_STENCILFUNC,
127 WINED3D_RS_STENCILMASK,
128 WINED3D_RS_STENCILPASS,
129 WINED3D_RS_STENCILREF,
130 WINED3D_RS_STENCILWRITEMASK,
131 WINED3D_RS_STENCILZFAIL,
132 WINED3D_RS_TEXTUREFACTOR,
133 WINED3D_RS_TWOSIDEDSTENCILMODE,
134 WINED3D_RS_WRAP0,
135 WINED3D_RS_WRAP1,
136 WINED3D_RS_WRAP10,
137 WINED3D_RS_WRAP11,
138 WINED3D_RS_WRAP12,
139 WINED3D_RS_WRAP13,
140 WINED3D_RS_WRAP14,
141 WINED3D_RS_WRAP15,
142 WINED3D_RS_WRAP2,
143 WINED3D_RS_WRAP3,
144 WINED3D_RS_WRAP4,
145 WINED3D_RS_WRAP5,
146 WINED3D_RS_WRAP6,
147 WINED3D_RS_WRAP7,
148 WINED3D_RS_WRAP8,
149 WINED3D_RS_WRAP9,
150 WINED3D_RS_ZENABLE,
151 WINED3D_RS_ZFUNC,
152 WINED3D_RS_ZWRITEENABLE,
155 static const DWORD pixel_states_texture[] =
157 WINED3D_TSS_ALPHA_ARG0,
158 WINED3D_TSS_ALPHA_ARG1,
159 WINED3D_TSS_ALPHA_ARG2,
160 WINED3D_TSS_ALPHA_OP,
161 WINED3D_TSS_BUMPENV_LOFFSET,
162 WINED3D_TSS_BUMPENV_LSCALE,
163 WINED3D_TSS_BUMPENV_MAT00,
164 WINED3D_TSS_BUMPENV_MAT01,
165 WINED3D_TSS_BUMPENV_MAT10,
166 WINED3D_TSS_BUMPENV_MAT11,
167 WINED3D_TSS_COLOR_ARG0,
168 WINED3D_TSS_COLOR_ARG1,
169 WINED3D_TSS_COLOR_ARG2,
170 WINED3D_TSS_COLOR_OP,
171 WINED3D_TSS_RESULT_ARG,
172 WINED3D_TSS_TEXCOORD_INDEX,
173 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
176 static const DWORD pixel_states_sampler[] =
178 WINED3D_SAMP_ADDRESS_U,
179 WINED3D_SAMP_ADDRESS_V,
180 WINED3D_SAMP_ADDRESS_W,
181 WINED3D_SAMP_BORDER_COLOR,
182 WINED3D_SAMP_MAG_FILTER,
183 WINED3D_SAMP_MIN_FILTER,
184 WINED3D_SAMP_MIP_FILTER,
185 WINED3D_SAMP_MIPMAP_LOD_BIAS,
186 WINED3D_SAMP_MAX_MIP_LEVEL,
187 WINED3D_SAMP_MAX_ANISOTROPY,
188 WINED3D_SAMP_SRGB_TEXTURE,
189 WINED3D_SAMP_ELEMENT_INDEX,
192 static const DWORD vertex_states_render[] =
194 WINED3D_RS_ADAPTIVETESS_W,
195 WINED3D_RS_ADAPTIVETESS_X,
196 WINED3D_RS_ADAPTIVETESS_Y,
197 WINED3D_RS_ADAPTIVETESS_Z,
198 WINED3D_RS_AMBIENT,
199 WINED3D_RS_AMBIENTMATERIALSOURCE,
200 WINED3D_RS_CLIPPING,
201 WINED3D_RS_CLIPPLANEENABLE,
202 WINED3D_RS_COLORVERTEX,
203 WINED3D_RS_CULLMODE,
204 WINED3D_RS_DIFFUSEMATERIALSOURCE,
205 WINED3D_RS_EMISSIVEMATERIALSOURCE,
206 WINED3D_RS_ENABLEADAPTIVETESSELLATION,
207 WINED3D_RS_FOGCOLOR,
208 WINED3D_RS_FOGDENSITY,
209 WINED3D_RS_FOGENABLE,
210 WINED3D_RS_FOGEND,
211 WINED3D_RS_FOGSTART,
212 WINED3D_RS_FOGTABLEMODE,
213 WINED3D_RS_FOGVERTEXMODE,
214 WINED3D_RS_INDEXEDVERTEXBLENDENABLE,
215 WINED3D_RS_LIGHTING,
216 WINED3D_RS_LOCALVIEWER,
217 WINED3D_RS_MAXTESSELLATIONLEVEL,
218 WINED3D_RS_MINTESSELLATIONLEVEL,
219 WINED3D_RS_MULTISAMPLEANTIALIAS,
220 WINED3D_RS_MULTISAMPLEMASK,
221 WINED3D_RS_NORMALDEGREE,
222 WINED3D_RS_NORMALIZENORMALS,
223 WINED3D_RS_PATCHEDGESTYLE,
224 WINED3D_RS_POINTSCALE_A,
225 WINED3D_RS_POINTSCALE_B,
226 WINED3D_RS_POINTSCALE_C,
227 WINED3D_RS_POINTSCALEENABLE,
228 WINED3D_RS_POINTSIZE,
229 WINED3D_RS_POINTSIZE_MAX,
230 WINED3D_RS_POINTSIZE_MIN,
231 WINED3D_RS_POINTSPRITEENABLE,
232 WINED3D_RS_POSITIONDEGREE,
233 WINED3D_RS_RANGEFOGENABLE,
234 WINED3D_RS_SHADEMODE,
235 WINED3D_RS_SPECULARENABLE,
236 WINED3D_RS_SPECULARMATERIALSOURCE,
237 WINED3D_RS_TWEENFACTOR,
238 WINED3D_RS_VERTEXBLEND,
241 static const DWORD vertex_states_texture[] =
243 WINED3D_TSS_TEXCOORD_INDEX,
244 WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS,
247 static const DWORD vertex_states_sampler[] =
249 WINED3D_SAMP_DMAP_OFFSET,
252 static inline void stateblock_set_all_bits(uint32_t *map, UINT map_size)
254 DWORD mask = (1u << (map_size & 0x1f)) - 1;
255 memset(map, 0xff, (map_size >> 5) * sizeof(*map));
256 if (mask) map[map_size >> 5] = mask;
259 /* Set all members of a stateblock savedstate to the given value */
260 static void stateblock_savedstates_set_all(struct wined3d_saved_states *states, DWORD vs_consts, DWORD ps_consts)
262 unsigned int i;
264 states->indices = 1;
265 states->material = 1;
266 states->viewport = 1;
267 states->vertexDecl = 1;
268 states->pixelShader = 1;
269 states->vertexShader = 1;
270 states->scissorRect = 1;
271 states->alpha_to_coverage = 1;
272 states->lights = 1;
273 states->transforms = 1;
275 states->streamSource = 0xffff;
276 states->streamFreq = 0xffff;
277 states->textures = 0xfffff;
278 stateblock_set_all_bits(states->transform, WINED3D_HIGHEST_TRANSFORM_STATE + 1);
279 stateblock_set_all_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
280 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
281 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3ffe;
282 states->clipplane = wined3d_mask_from_size(WINED3D_MAX_CLIP_DISTANCES);
283 states->pixelShaderConstantsB = 0xffff;
284 states->pixelShaderConstantsI = 0xffff;
285 states->vertexShaderConstantsB = 0xffff;
286 states->vertexShaderConstantsI = 0xffff;
288 memset(states->ps_consts_f, 0xffu, sizeof(states->ps_consts_f));
289 memset(states->vs_consts_f, 0xffu, sizeof(states->vs_consts_f));
292 static void stateblock_savedstates_set_pixel(struct wined3d_saved_states *states, const DWORD num_constants)
294 DWORD texture_mask = 0;
295 WORD sampler_mask = 0;
296 unsigned int i;
298 states->pixelShader = 1;
300 for (i = 0; i < ARRAY_SIZE(pixel_states_render); ++i)
302 DWORD rs = pixel_states_render[i];
303 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
306 for (i = 0; i < ARRAY_SIZE(pixel_states_texture); ++i)
307 texture_mask |= 1u << pixel_states_texture[i];
308 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) states->textureState[i] = texture_mask;
309 for (i = 0; i < ARRAY_SIZE(pixel_states_sampler); ++i)
310 sampler_mask |= 1u << pixel_states_sampler[i];
311 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
312 states->pixelShaderConstantsB = 0xffff;
313 states->pixelShaderConstantsI = 0xffff;
315 memset(states->ps_consts_f, 0xffu, sizeof(states->ps_consts_f));
318 static void stateblock_savedstates_set_vertex(struct wined3d_saved_states *states, const DWORD num_constants)
320 DWORD texture_mask = 0;
321 WORD sampler_mask = 0;
322 unsigned int i;
324 states->vertexDecl = 1;
325 states->vertexShader = 1;
326 states->alpha_to_coverage = 1;
327 states->lights = 1;
329 for (i = 0; i < ARRAY_SIZE(vertex_states_render); ++i)
331 DWORD rs = vertex_states_render[i];
332 states->renderState[rs >> 5] |= 1u << (rs & 0x1f);
335 for (i = 0; i < ARRAY_SIZE(vertex_states_texture); ++i)
336 texture_mask |= 1u << vertex_states_texture[i];
337 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i) states->textureState[i] = texture_mask;
338 for (i = 0; i < ARRAY_SIZE(vertex_states_sampler); ++i)
339 sampler_mask |= 1u << vertex_states_sampler[i];
340 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = sampler_mask;
341 states->vertexShaderConstantsB = 0xffff;
342 states->vertexShaderConstantsI = 0xffff;
344 memset(states->vs_consts_f, 0xffu, sizeof(states->vs_consts_f));
347 void CDECL wined3d_stateblock_init_contained_states(struct wined3d_stateblock *stateblock)
349 unsigned int i, j;
351 for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i)
353 DWORD map = stateblock->changed.renderState[i];
354 for (j = 0; map; map >>= 1, ++j)
356 if (!(map & 1)) continue;
358 stateblock->contained_render_states[stateblock->num_contained_render_states] = (i << 5) | j;
359 ++stateblock->num_contained_render_states;
363 for (i = 0; i <= WINED3D_HIGHEST_TRANSFORM_STATE >> 5; ++i)
365 DWORD map = stateblock->changed.transform[i];
366 for (j = 0; map; map >>= 1, ++j)
368 if (!(map & 1)) continue;
370 stateblock->contained_transform_states[stateblock->num_contained_transform_states] = (i << 5) | j;
371 ++stateblock->num_contained_transform_states;
375 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
377 DWORD map = stateblock->changed.textureState[i];
379 for(j = 0; map; map >>= 1, ++j)
381 if (!(map & 1)) continue;
383 stateblock->contained_tss_states[stateblock->num_contained_tss_states].stage = i;
384 stateblock->contained_tss_states[stateblock->num_contained_tss_states].state = j;
385 ++stateblock->num_contained_tss_states;
389 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
391 DWORD map = stateblock->changed.samplerState[i];
393 for (j = 0; map; map >>= 1, ++j)
395 if (!(map & 1)) continue;
397 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].stage = i;
398 stateblock->contained_sampler_states[stateblock->num_contained_sampler_states].state = j;
399 ++stateblock->num_contained_sampler_states;
404 static void stateblock_init_lights(struct wined3d_stateblock *stateblock, const struct rb_tree *src_tree)
406 struct rb_tree *dst_tree = &stateblock->stateblock_state.light_state->lights_tree;
407 struct wined3d_light_info *src_light;
409 RB_FOR_EACH_ENTRY(src_light, src_tree, struct wined3d_light_info, entry)
411 struct wined3d_light_info *dst_light = malloc(sizeof(*dst_light));
413 *dst_light = *src_light;
414 rb_put(dst_tree, (void *)(ULONG_PTR)dst_light->OriginalIndex, &dst_light->entry);
415 dst_light->changed = true;
416 list_add_tail(&stateblock->changed.changed_lights, &dst_light->changed_entry);
420 ULONG CDECL wined3d_stateblock_incref(struct wined3d_stateblock *stateblock)
422 unsigned int refcount = InterlockedIncrement(&stateblock->ref);
424 TRACE("%p increasing refcount to %u.\n", stateblock, refcount);
426 return refcount;
429 void state_unbind_resources(struct wined3d_state *state)
431 struct wined3d_unordered_access_view *uav;
432 struct wined3d_shader_resource_view *srv;
433 struct wined3d_vertex_declaration *decl;
434 struct wined3d_blend_state *blend_state;
435 struct wined3d_rendertarget_view *rtv;
436 struct wined3d_sampler *sampler;
437 struct wined3d_buffer *buffer;
438 struct wined3d_shader *shader;
439 unsigned int i, j;
441 if ((decl = state->vertex_declaration))
443 state->vertex_declaration = NULL;
444 wined3d_vertex_declaration_decref(decl);
447 for (i = 0; i < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++i)
449 if ((buffer = state->stream_output[i].buffer))
451 state->stream_output[i].buffer = NULL;
452 wined3d_buffer_decref(buffer);
456 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
458 if ((buffer = state->streams[i].buffer))
460 state->streams[i].buffer = NULL;
461 wined3d_buffer_decref(buffer);
465 if ((buffer = state->index_buffer))
467 state->index_buffer = NULL;
468 wined3d_buffer_decref(buffer);
471 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
473 if ((shader = state->shader[i]))
475 state->shader[i] = NULL;
476 wined3d_shader_decref(shader);
479 for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
481 if ((buffer = state->cb[i][j].buffer))
483 state->cb[i][j].buffer = NULL;
484 wined3d_buffer_decref(buffer);
488 for (j = 0; j < MAX_SAMPLER_OBJECTS; ++j)
490 if ((sampler = state->sampler[i][j]))
492 state->sampler[i][j] = NULL;
493 wined3d_sampler_decref(sampler);
497 for (j = 0; j < MAX_SHADER_RESOURCE_VIEWS; ++j)
499 if ((srv = state->shader_resource_view[i][j]))
501 state->shader_resource_view[i][j] = NULL;
502 wined3d_srv_bind_count_dec(srv);
503 wined3d_shader_resource_view_decref(srv);
508 for (i = 0; i < WINED3D_PIPELINE_COUNT; ++i)
510 for (j = 0; j < MAX_UNORDERED_ACCESS_VIEWS; ++j)
512 if ((uav = state->unordered_access_view[i][j]))
514 state->unordered_access_view[i][j] = NULL;
515 wined3d_unordered_access_view_decref(uav);
520 if ((blend_state = state->blend_state))
522 state->blend_state = NULL;
523 wined3d_blend_state_decref(blend_state);
526 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
528 if ((rtv = state->fb.render_targets[i]))
530 state->fb.render_targets[i] = NULL;
531 wined3d_rendertarget_view_decref(rtv);
535 if ((rtv = state->fb.depth_stencil))
537 state->fb.depth_stencil = NULL;
538 wined3d_rendertarget_view_decref(rtv);
542 static void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state)
544 struct wined3d_light_info *light, *cursor;
545 struct wined3d_vertex_declaration *decl;
546 struct wined3d_texture *texture;
547 struct wined3d_buffer *buffer;
548 struct wined3d_shader *shader;
549 unsigned int i;
551 if ((decl = state->vertex_declaration))
553 state->vertex_declaration = NULL;
554 wined3d_vertex_declaration_decref(decl);
557 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
559 if ((buffer = state->streams[i].buffer))
561 state->streams[i].buffer = NULL;
562 wined3d_buffer_decref(buffer);
566 if ((buffer = state->index_buffer))
568 state->index_buffer = NULL;
569 wined3d_buffer_decref(buffer);
572 if ((shader = state->vs))
574 state->vs = NULL;
575 wined3d_shader_decref(shader);
578 if ((shader = state->ps))
580 state->ps = NULL;
581 wined3d_shader_decref(shader);
584 for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
586 if ((texture = state->textures[i]))
588 state->textures[i] = NULL;
589 wined3d_texture_decref(texture);
593 RB_FOR_EACH_ENTRY_DESTRUCTOR(light, cursor, &state->light_state->lights_tree, struct wined3d_light_info, entry)
595 if (light->changed)
596 list_remove(&light->changed_entry);
597 rb_remove(&state->light_state->lights_tree, &light->entry);
598 free(light);
602 void state_cleanup(struct wined3d_state *state)
604 struct wined3d_light_info *light, *cursor;
605 unsigned int i;
607 if (!(state->flags & WINED3D_STATE_NO_REF))
608 state_unbind_resources(state);
610 for (i = 0; i < WINED3D_MAX_ACTIVE_LIGHTS; ++i)
612 state->light_state.lights[i] = NULL;
615 RB_FOR_EACH_ENTRY_DESTRUCTOR(light, cursor, &state->light_state.lights_tree, struct wined3d_light_info, entry)
617 if (light->changed)
618 list_remove(&light->changed_entry);
619 rb_remove(&state->light_state.lights_tree, &light->entry);
620 free(light);
624 ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
626 unsigned int refcount = InterlockedDecrement(&stateblock->ref);
628 TRACE("%p decreasing refcount to %u\n", stateblock, refcount);
630 if (!refcount)
632 wined3d_mutex_lock();
633 wined3d_stateblock_state_cleanup(&stateblock->stateblock_state);
634 free(stateblock);
635 wined3d_mutex_unlock();
638 return refcount;
641 struct wined3d_light_info *wined3d_light_state_get_light(const struct wined3d_light_state *state, unsigned int idx)
643 struct rb_entry *entry;
645 if (!(entry = rb_get(&state->lights_tree, (void *)(ULONG_PTR)idx)))
646 return NULL;
648 return RB_ENTRY_VALUE(entry, struct wined3d_light_info, entry);
651 static void set_light_changed(struct wined3d_stateblock *stateblock, struct wined3d_light_info *light_info)
653 if (!light_info->changed)
655 list_add_tail(&stateblock->changed.changed_lights, &light_info->changed_entry);
656 light_info->changed = true;
658 stateblock->changed.lights = 1;
661 static HRESULT wined3d_light_state_set_light(struct wined3d_light_state *state, unsigned int light_idx,
662 const struct wined3d_light *params, struct wined3d_light_info **light_info)
664 struct wined3d_light_info *object;
666 if (!(object = wined3d_light_state_get_light(state, light_idx)))
668 TRACE("Adding new light.\n");
669 if (!(object = calloc(1, sizeof(*object))))
671 ERR("Failed to allocate light info.\n");
672 return E_OUTOFMEMORY;
675 object->glIndex = -1;
676 object->OriginalIndex = light_idx;
677 rb_put(&state->lights_tree, (void *)(ULONG_PTR)light_idx, &object->entry);
680 object->OriginalParms = *params;
682 /* Initialize the object. */
683 TRACE("Light %u setting to type %#x, diffuse %s, specular %s, ambient %s, "
684 "position {%.8e, %.8e, %.8e}, direction {%.8e, %.8e, %.8e}, "
685 "range %.8e, falloff %.8e, theta %.8e, phi %.8e.\n",
686 light_idx, params->type, debug_color(&params->diffuse),
687 debug_color(&params->specular), debug_color(&params->ambient),
688 params->position.x, params->position.y, params->position.z,
689 params->direction.x, params->direction.y, params->direction.z,
690 params->range, params->falloff, params->theta, params->phi);
692 switch (params->type)
694 case WINED3D_LIGHT_POINT:
695 /* Position */
696 object->position.x = params->position.x;
697 object->position.y = params->position.y;
698 object->position.z = params->position.z;
699 object->position.w = 1.0f;
700 /* FIXME: Range */
701 break;
703 case WINED3D_LIGHT_DIRECTIONAL:
704 /* Direction */
705 object->direction.x = -params->direction.x;
706 object->direction.y = -params->direction.y;
707 object->direction.z = -params->direction.z;
708 object->direction.w = 0.0f;
709 break;
711 case WINED3D_LIGHT_SPOT:
712 /* Position */
713 object->position.x = params->position.x;
714 object->position.y = params->position.y;
715 object->position.z = params->position.z;
716 object->position.w = 1.0f;
718 /* Direction */
719 object->direction.x = params->direction.x;
720 object->direction.y = params->direction.y;
721 object->direction.z = params->direction.z;
722 object->direction.w = 0.0f;
724 /* FIXME: Range */
725 break;
727 case WINED3D_LIGHT_PARALLELPOINT:
728 object->position.x = params->position.x;
729 object->position.y = params->position.y;
730 object->position.z = params->position.z;
731 object->position.w = 1.0f;
732 break;
734 default:
735 FIXME("Unrecognized params type %#x.\n", params->type);
738 *light_info = object;
739 return WINED3D_OK;
742 bool wined3d_light_state_enable_light(struct wined3d_light_state *state, const struct wined3d_d3d_info *d3d_info,
743 struct wined3d_light_info *light_info, BOOL enable)
745 unsigned int light_count, i;
747 if (!(light_info->enabled = enable))
749 if (light_info->glIndex == -1)
751 TRACE("Light already disabled, nothing to do.\n");
752 return false;
755 state->lights[light_info->glIndex] = NULL;
756 light_info->glIndex = -1;
757 return true;
760 if (light_info->glIndex != -1)
762 TRACE("Light already enabled, nothing to do.\n");
763 return false;
766 /* Find a free light. */
767 light_count = d3d_info->limits.active_light_count;
768 for (i = 0; i < light_count; ++i)
770 if (state->lights[i])
771 continue;
773 state->lights[i] = light_info;
774 light_info->glIndex = i;
775 return true;
778 /* Our tests show that Windows returns D3D_OK in this situation, even with
779 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices.
780 * This is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns
781 * TRUE * as well for those lights.
783 * TODO: Test how this affects rendering. */
784 WARN("Too many concurrently active lights.\n");
785 return false;
788 static void wined3d_state_record_lights(struct wined3d_light_state *dst_state,
789 const struct wined3d_light_state *src_state)
791 const struct wined3d_light_info *src;
792 struct wined3d_light_info *dst;
794 /* Lights... For a recorded state block, we just had a chain of actions
795 * to perform, so we need to walk that chain and update any actions which
796 * differ. */
797 RB_FOR_EACH_ENTRY(dst, &dst_state->lights_tree, struct wined3d_light_info, entry)
799 if ((src = wined3d_light_state_get_light(src_state, dst->OriginalIndex)))
801 dst->OriginalParms = src->OriginalParms;
803 if (src->glIndex == -1 && dst->glIndex != -1)
805 /* Light disabled. */
806 dst_state->lights[dst->glIndex] = NULL;
808 else if (src->glIndex != -1 && dst->glIndex == -1)
810 /* Light enabled. */
811 dst_state->lights[src->glIndex] = dst;
813 dst->glIndex = src->glIndex;
815 else
817 /* This can happen if the light was originally created as a
818 * default light for SetLightEnable() while recording. */
819 WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
820 dst->OriginalIndex, dst_state, src_state);
822 dst->OriginalParms = WINED3D_default_light;
823 if (dst->glIndex != -1)
825 dst_state->lights[dst->glIndex] = NULL;
826 dst->glIndex = -1;
832 void CDECL wined3d_stateblock_capture(struct wined3d_stateblock *stateblock,
833 const struct wined3d_stateblock *device_state)
835 const struct wined3d_stateblock_state *state = &device_state->stateblock_state;
836 struct wined3d_range range;
837 unsigned int i, start;
838 uint32_t map;
840 TRACE("stateblock %p, device_state %p.\n", stateblock, device_state);
842 if (stateblock->changed.vertexShader && stateblock->stateblock_state.vs != state->vs)
844 TRACE("Updating vertex shader from %p to %p.\n", stateblock->stateblock_state.vs, state->vs);
846 if (state->vs)
847 wined3d_shader_incref(state->vs);
848 if (stateblock->stateblock_state.vs)
849 wined3d_shader_decref(stateblock->stateblock_state.vs);
850 stateblock->stateblock_state.vs = state->vs;
853 for (start = 0; ; start = range.offset + range.size)
855 if (!wined3d_bitmap_get_range(stateblock->changed.vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range))
856 break;
858 memcpy(&stateblock->stateblock_state.vs_consts_f[range.offset], &state->vs_consts_f[range.offset],
859 sizeof(*state->vs_consts_f) * range.size);
861 map = stateblock->changed.vertexShaderConstantsI;
862 for (start = 0; ; start = range.offset + range.size)
864 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
865 break;
867 memcpy(&stateblock->stateblock_state.vs_consts_i[range.offset], &state->vs_consts_i[range.offset],
868 sizeof(*state->vs_consts_i) * range.size);
870 map = stateblock->changed.vertexShaderConstantsB;
871 for (start = 0; ; start = range.offset + range.size)
873 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
874 break;
876 memcpy(&stateblock->stateblock_state.vs_consts_b[range.offset], &state->vs_consts_b[range.offset],
877 sizeof(*state->vs_consts_b) * range.size);
880 for (start = 0; ; start = range.offset + range.size)
882 if (!wined3d_bitmap_get_range(stateblock->changed.ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range))
883 break;
885 memcpy(&stateblock->stateblock_state.ps_consts_f[range.offset], &state->ps_consts_f[range.offset],
886 sizeof(*state->ps_consts_f) * range.size);
888 map = stateblock->changed.pixelShaderConstantsI;
889 for (start = 0; ; start = range.offset + range.size)
891 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
892 break;
894 memcpy(&stateblock->stateblock_state.ps_consts_i[range.offset], &state->ps_consts_i[range.offset],
895 sizeof(*state->ps_consts_i) * range.size);
897 map = stateblock->changed.pixelShaderConstantsB;
898 for (start = 0; ; start = range.offset + range.size)
900 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
901 break;
903 memcpy(&stateblock->stateblock_state.ps_consts_b[range.offset], &state->ps_consts_b[range.offset],
904 sizeof(*state->ps_consts_b) * range.size);
907 if (stateblock->changed.transforms)
909 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
911 enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
913 TRACE("Updating transform %#x.\n", transform);
915 stateblock->stateblock_state.transforms[transform] = state->transforms[transform];
919 if (stateblock->changed.indices
920 && ((stateblock->stateblock_state.index_buffer != state->index_buffer)
921 || (stateblock->stateblock_state.base_vertex_index != state->base_vertex_index)
922 || (stateblock->stateblock_state.index_format != state->index_format)))
924 TRACE("Updating index buffer to %p, base vertex index to %d.\n",
925 state->index_buffer, state->base_vertex_index);
927 if (state->index_buffer)
928 wined3d_buffer_incref(state->index_buffer);
929 if (stateblock->stateblock_state.index_buffer)
930 wined3d_buffer_decref(stateblock->stateblock_state.index_buffer);
931 stateblock->stateblock_state.index_buffer = state->index_buffer;
932 stateblock->stateblock_state.base_vertex_index = state->base_vertex_index;
933 stateblock->stateblock_state.index_format = state->index_format;
936 if (stateblock->changed.vertexDecl && stateblock->stateblock_state.vertex_declaration != state->vertex_declaration)
938 TRACE("Updating vertex declaration from %p to %p.\n",
939 stateblock->stateblock_state.vertex_declaration, state->vertex_declaration);
941 if (state->vertex_declaration)
942 wined3d_vertex_declaration_incref(state->vertex_declaration);
943 if (stateblock->stateblock_state.vertex_declaration)
944 wined3d_vertex_declaration_decref(stateblock->stateblock_state.vertex_declaration);
945 stateblock->stateblock_state.vertex_declaration = state->vertex_declaration;
948 if (stateblock->changed.material
949 && memcmp(&state->material, &stateblock->stateblock_state.material,
950 sizeof(stateblock->stateblock_state.material)))
952 TRACE("Updating material.\n");
954 stateblock->stateblock_state.material = state->material;
957 if (stateblock->changed.viewport
958 && memcmp(&state->viewport, &stateblock->stateblock_state.viewport, sizeof(state->viewport)))
960 TRACE("Updating viewport.\n");
962 stateblock->stateblock_state.viewport = state->viewport;
965 if (stateblock->changed.scissorRect
966 && memcmp(&state->scissor_rect, &stateblock->stateblock_state.scissor_rect, sizeof(state->scissor_rect)))
968 TRACE("Updating scissor rect.\n");
970 stateblock->stateblock_state.scissor_rect = state->scissor_rect;
973 map = stateblock->changed.streamSource;
974 while (map)
976 i = wined3d_bit_scan(&map);
978 if (stateblock->stateblock_state.streams[i].stride != state->streams[i].stride
979 || stateblock->stateblock_state.streams[i].offset != state->streams[i].offset
980 || stateblock->stateblock_state.streams[i].buffer != state->streams[i].buffer)
982 TRACE("stateblock %p, stream source %u, buffer %p, stride %u, offset %u.\n",
983 stateblock, i, state->streams[i].buffer, state->streams[i].stride,
984 state->streams[i].offset);
986 stateblock->stateblock_state.streams[i].stride = state->streams[i].stride;
987 if (stateblock->changed.store_stream_offset)
988 stateblock->stateblock_state.streams[i].offset = state->streams[i].offset;
990 if (state->streams[i].buffer)
991 wined3d_buffer_incref(state->streams[i].buffer);
992 if (stateblock->stateblock_state.streams[i].buffer)
993 wined3d_buffer_decref(stateblock->stateblock_state.streams[i].buffer);
994 stateblock->stateblock_state.streams[i].buffer = state->streams[i].buffer;
998 map = stateblock->changed.streamFreq;
999 while (map)
1001 i = wined3d_bit_scan(&map);
1003 if (stateblock->stateblock_state.streams[i].frequency != state->streams[i].frequency
1004 || stateblock->stateblock_state.streams[i].flags != state->streams[i].flags)
1006 TRACE("Updating stream frequency %u to %u flags to %#x.\n",
1007 i, state->streams[i].frequency, state->streams[i].flags);
1009 stateblock->stateblock_state.streams[i].frequency = state->streams[i].frequency;
1010 stateblock->stateblock_state.streams[i].flags = state->streams[i].flags;
1014 map = stateblock->changed.clipplane;
1015 while (map)
1017 i = wined3d_bit_scan(&map);
1019 if (memcmp(&stateblock->stateblock_state.clip_planes[i], &state->clip_planes[i], sizeof(state->clip_planes[i])))
1021 TRACE("Updating clipplane %u.\n", i);
1022 stateblock->stateblock_state.clip_planes[i] = state->clip_planes[i];
1026 /* Render */
1027 for (i = 0; i < stateblock->num_contained_render_states; ++i)
1029 enum wined3d_render_state rs = stateblock->contained_render_states[i];
1031 TRACE("Updating render state %#x to %u.\n", rs, state->rs[rs]);
1033 stateblock->stateblock_state.rs[rs] = state->rs[rs];
1036 /* Texture states */
1037 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
1039 unsigned int stage = stateblock->contained_tss_states[i].stage;
1040 unsigned int texture_state = stateblock->contained_tss_states[i].state;
1042 TRACE("Updating texturestage state %u, %u to %#x (was %#x).\n", stage, texture_state,
1043 state->texture_states[stage][texture_state],
1044 stateblock->stateblock_state.texture_states[stage][texture_state]);
1046 stateblock->stateblock_state.texture_states[stage][texture_state] = state->texture_states[stage][texture_state];
1049 /* Samplers */
1050 map = stateblock->changed.textures;
1051 while (map)
1053 i = wined3d_bit_scan(&map);
1055 TRACE("Updating texture %u to %p (was %p).\n",
1056 i, state->textures[i], stateblock->stateblock_state.textures[i]);
1058 if (state->textures[i])
1059 wined3d_texture_incref(state->textures[i]);
1060 if (stateblock->stateblock_state.textures[i])
1061 wined3d_texture_decref(stateblock->stateblock_state.textures[i]);
1062 stateblock->stateblock_state.textures[i] = state->textures[i];
1065 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
1067 unsigned int stage = stateblock->contained_sampler_states[i].stage;
1068 unsigned int sampler_state = stateblock->contained_sampler_states[i].state;
1070 TRACE("Updating sampler state %u, %u to %#x (was %#x).\n", stage, sampler_state,
1071 state->sampler_states[stage][sampler_state],
1072 stateblock->stateblock_state.sampler_states[stage][sampler_state]);
1074 stateblock->stateblock_state.sampler_states[stage][sampler_state] = state->sampler_states[stage][sampler_state];
1077 if (stateblock->changed.pixelShader && stateblock->stateblock_state.ps != state->ps)
1079 if (state->ps)
1080 wined3d_shader_incref(state->ps);
1081 if (stateblock->stateblock_state.ps)
1082 wined3d_shader_decref(stateblock->stateblock_state.ps);
1083 stateblock->stateblock_state.ps = state->ps;
1086 if (stateblock->changed.lights)
1087 wined3d_state_record_lights(stateblock->stateblock_state.light_state, state->light_state);
1089 if (stateblock->changed.alpha_to_coverage)
1090 stateblock->stateblock_state.alpha_to_coverage = state->alpha_to_coverage;
1092 TRACE("Capture done.\n");
1095 void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock,
1096 struct wined3d_stateblock *device_state)
1098 const struct wined3d_stateblock_state *state = &stateblock->stateblock_state;
1099 struct wined3d_range range;
1100 unsigned int i, start;
1101 uint32_t map;
1103 TRACE("stateblock %p, device_state %p.\n", stateblock, device_state);
1105 if (stateblock->changed.vertexShader)
1106 wined3d_stateblock_set_vertex_shader(device_state, state->vs);
1107 if (stateblock->changed.pixelShader)
1108 wined3d_stateblock_set_pixel_shader(device_state, state->ps);
1110 for (start = 0; ; start = range.offset + range.size)
1112 if (!wined3d_bitmap_get_range(stateblock->changed.vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range))
1113 break;
1114 wined3d_stateblock_set_vs_consts_f(device_state, range.offset, range.size, &state->vs_consts_f[range.offset]);
1116 map = stateblock->changed.vertexShaderConstantsI;
1117 for (start = 0; ; start = range.offset + range.size)
1119 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
1120 break;
1121 wined3d_stateblock_set_vs_consts_i(device_state, range.offset, range.size, &state->vs_consts_i[range.offset]);
1123 map = stateblock->changed.vertexShaderConstantsB;
1124 for (start = 0; ; start = range.offset + range.size)
1126 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
1127 break;
1128 wined3d_stateblock_set_vs_consts_b(device_state, range.offset, range.size, &state->vs_consts_b[range.offset]);
1131 for (start = 0; ; start = range.offset + range.size)
1133 if (!wined3d_bitmap_get_range(stateblock->changed.ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range))
1134 break;
1135 wined3d_stateblock_set_ps_consts_f(device_state, range.offset, range.size, &state->ps_consts_f[range.offset]);
1137 map = stateblock->changed.pixelShaderConstantsI;
1138 for (start = 0; ; start = range.offset + range.size)
1140 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
1141 break;
1142 wined3d_stateblock_set_ps_consts_i(device_state, range.offset, range.size, &state->ps_consts_i[range.offset]);
1144 map = stateblock->changed.pixelShaderConstantsB;
1145 for (start = 0; ; start = range.offset + range.size)
1147 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
1148 break;
1149 wined3d_stateblock_set_ps_consts_b(device_state, range.offset, range.size, &state->ps_consts_b[range.offset]);
1152 if (stateblock->changed.transforms)
1154 for (i = 0; i < stateblock->num_contained_transform_states; ++i)
1156 enum wined3d_transform_state transform = stateblock->contained_transform_states[i];
1158 wined3d_stateblock_set_transform(device_state, transform, &state->transforms[transform]);
1162 if (stateblock->changed.lights)
1164 const struct wined3d_light_info *light;
1166 LIST_FOR_EACH_ENTRY(light, &stateblock->changed.changed_lights, struct wined3d_light_info, changed_entry)
1168 wined3d_stateblock_set_light(device_state, light->OriginalIndex, &light->OriginalParms);
1169 wined3d_stateblock_set_light_enable(device_state, light->OriginalIndex, light->glIndex != -1);
1173 if (stateblock->changed.alpha_to_coverage)
1175 device_state->stateblock_state.alpha_to_coverage = state->alpha_to_coverage;
1176 device_state->changed.alpha_to_coverage = 1;
1179 /* Render states. */
1180 for (i = 0; i < stateblock->num_contained_render_states; ++i)
1182 enum wined3d_render_state rs = stateblock->contained_render_states[i];
1184 wined3d_stateblock_set_render_state(device_state, rs, state->rs[rs]);
1187 /* Texture states. */
1188 for (i = 0; i < stateblock->num_contained_tss_states; ++i)
1190 DWORD stage = stateblock->contained_tss_states[i].stage;
1191 DWORD texture_state = stateblock->contained_tss_states[i].state;
1193 wined3d_stateblock_set_texture_stage_state(device_state, stage, texture_state,
1194 state->texture_states[stage][texture_state]);
1197 /* Sampler states. */
1198 for (i = 0; i < stateblock->num_contained_sampler_states; ++i)
1200 DWORD stage = stateblock->contained_sampler_states[i].stage;
1201 DWORD sampler_state = stateblock->contained_sampler_states[i].state;
1203 wined3d_stateblock_set_sampler_state(device_state, stage, sampler_state,
1204 state->sampler_states[stage][sampler_state]);
1207 if (stateblock->changed.indices)
1209 wined3d_stateblock_set_index_buffer(device_state, state->index_buffer, state->index_format);
1210 wined3d_stateblock_set_base_vertex_index(device_state, state->base_vertex_index);
1213 if (stateblock->changed.vertexDecl && state->vertex_declaration)
1214 wined3d_stateblock_set_vertex_declaration(device_state, state->vertex_declaration);
1216 if (stateblock->changed.material)
1217 wined3d_stateblock_set_material(device_state, &state->material);
1219 if (stateblock->changed.viewport)
1220 wined3d_stateblock_set_viewport(device_state, &state->viewport);
1222 if (stateblock->changed.scissorRect)
1223 wined3d_stateblock_set_scissor_rect(device_state, &state->scissor_rect);
1225 map = stateblock->changed.streamSource;
1226 while (map)
1228 i = wined3d_bit_scan(&map);
1229 wined3d_stateblock_set_stream_source(device_state, i, state->streams[i].buffer,
1230 state->streams[i].offset, state->streams[i].stride);
1233 map = stateblock->changed.streamFreq;
1234 while (map)
1236 i = wined3d_bit_scan(&map);
1237 wined3d_stateblock_set_stream_source_freq(device_state, i,
1238 state->streams[i].frequency | state->streams[i].flags);
1241 map = stateblock->changed.textures;
1242 while (map)
1244 i = wined3d_bit_scan(&map);
1245 wined3d_stateblock_set_texture(device_state, i, state->textures[i]);
1248 map = stateblock->changed.clipplane;
1249 while (map)
1251 i = wined3d_bit_scan(&map);
1252 wined3d_stateblock_set_clip_plane(device_state, i, &state->clip_planes[i]);
1255 TRACE("Applied stateblock %p.\n", stateblock);
1258 void CDECL wined3d_stateblock_set_vertex_shader(struct wined3d_stateblock *stateblock, struct wined3d_shader *shader)
1260 TRACE("stateblock %p, shader %p.\n", stateblock, shader);
1262 if (shader)
1263 wined3d_shader_incref(shader);
1264 if (stateblock->stateblock_state.vs)
1265 wined3d_shader_decref(stateblock->stateblock_state.vs);
1266 stateblock->stateblock_state.vs = shader;
1267 stateblock->changed.vertexShader = TRUE;
1270 static void wined3d_bitmap_set_bits(uint32_t *bitmap, unsigned int start, unsigned int count)
1272 const unsigned int word_bit_count = sizeof(*bitmap) * CHAR_BIT;
1273 const unsigned int shift = start % word_bit_count;
1274 uint32_t mask, last_mask;
1275 unsigned int mask_size;
1277 bitmap += start / word_bit_count;
1278 mask = ~0u << shift;
1279 mask_size = word_bit_count - shift;
1280 last_mask = (1u << (start + count) % word_bit_count) - 1;
1281 if (mask_size <= count)
1283 *bitmap |= mask;
1284 ++bitmap;
1285 count -= mask_size;
1286 mask = ~0u;
1288 if (count >= word_bit_count)
1290 memset(bitmap, 0xffu, count / word_bit_count * sizeof(*bitmap));
1291 bitmap += count / word_bit_count;
1292 count = count % word_bit_count;
1294 if (count)
1295 *bitmap |= mask & last_mask;
1298 HRESULT CDECL wined3d_stateblock_set_vs_consts_f(struct wined3d_stateblock *stateblock,
1299 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
1301 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
1303 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1304 stateblock, start_idx, count, constants);
1306 if (!constants || !wined3d_bound_range(start_idx, count, d3d_info->limits.vs_uniform_count))
1307 return WINED3DERR_INVALIDCALL;
1309 memcpy(&stateblock->stateblock_state.vs_consts_f[start_idx], constants, count * sizeof(*constants));
1310 wined3d_bitmap_set_bits(stateblock->changed.vs_consts_f, start_idx, count);
1311 return WINED3D_OK;
1314 HRESULT CDECL wined3d_stateblock_set_vs_consts_i(struct wined3d_stateblock *stateblock,
1315 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
1317 unsigned int i;
1319 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1320 stateblock, start_idx, count, constants);
1322 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1323 return WINED3DERR_INVALIDCALL;
1325 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1326 count = WINED3D_MAX_CONSTS_I - start_idx;
1328 memcpy(&stateblock->stateblock_state.vs_consts_i[start_idx], constants, count * sizeof(*constants));
1329 for (i = start_idx; i < count + start_idx; ++i)
1330 stateblock->changed.vertexShaderConstantsI |= (1u << i);
1331 return WINED3D_OK;
1334 HRESULT CDECL wined3d_stateblock_set_vs_consts_b(struct wined3d_stateblock *stateblock,
1335 unsigned int start_idx, unsigned int count, const BOOL *constants)
1337 unsigned int i;
1339 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1340 stateblock, start_idx, count, constants);
1342 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1343 return WINED3DERR_INVALIDCALL;
1345 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1346 count = WINED3D_MAX_CONSTS_B - start_idx;
1348 memcpy(&stateblock->stateblock_state.vs_consts_b[start_idx], constants, count * sizeof(*constants));
1349 for (i = start_idx; i < count + start_idx; ++i)
1350 stateblock->changed.vertexShaderConstantsB |= (1u << i);
1351 return WINED3D_OK;
1354 HRESULT CDECL wined3d_stateblock_get_vs_consts_f(struct wined3d_stateblock *stateblock,
1355 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
1357 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
1359 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1361 if (!constants || !wined3d_bound_range(start_idx, count, d3d_info->limits.vs_uniform_count))
1362 return WINED3DERR_INVALIDCALL;
1364 memcpy(constants, &stateblock->stateblock_state.vs_consts_f[start_idx], count * sizeof(*constants));
1365 return WINED3D_OK;
1368 HRESULT CDECL wined3d_stateblock_get_vs_consts_i(struct wined3d_stateblock *stateblock,
1369 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
1371 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1373 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1374 return WINED3DERR_INVALIDCALL;
1376 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1377 count = WINED3D_MAX_CONSTS_I - start_idx;
1379 memcpy(constants, &stateblock->stateblock_state.vs_consts_i[start_idx], count * sizeof(*constants));
1380 return WINED3D_OK;
1383 HRESULT CDECL wined3d_stateblock_get_vs_consts_b(struct wined3d_stateblock *stateblock,
1384 unsigned int start_idx, unsigned int count, BOOL *constants)
1386 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1388 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1389 return WINED3DERR_INVALIDCALL;
1391 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1392 count = WINED3D_MAX_CONSTS_B - start_idx;
1394 memcpy(constants, &stateblock->stateblock_state.vs_consts_b[start_idx], count * sizeof(*constants));
1395 return WINED3D_OK;
1398 void CDECL wined3d_stateblock_set_pixel_shader(struct wined3d_stateblock *stateblock, struct wined3d_shader *shader)
1400 TRACE("stateblock %p, shader %p.\n", stateblock, shader);
1402 if (shader)
1403 wined3d_shader_incref(shader);
1404 if (stateblock->stateblock_state.ps)
1405 wined3d_shader_decref(stateblock->stateblock_state.ps);
1406 stateblock->stateblock_state.ps = shader;
1407 stateblock->changed.pixelShader = TRUE;
1410 HRESULT CDECL wined3d_stateblock_set_ps_consts_f(struct wined3d_stateblock *stateblock,
1411 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
1413 const struct wined3d_d3d_info *d3d_info = &stateblock->device->adapter->d3d_info;
1415 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1416 stateblock, start_idx, count, constants);
1418 if (!constants || !wined3d_bound_range(start_idx, count, d3d_info->limits.ps_uniform_count))
1419 return WINED3DERR_INVALIDCALL;
1421 memcpy(&stateblock->stateblock_state.ps_consts_f[start_idx], constants, count * sizeof(*constants));
1422 wined3d_bitmap_set_bits(stateblock->changed.ps_consts_f, start_idx, count);
1423 return WINED3D_OK;
1426 HRESULT CDECL wined3d_stateblock_set_ps_consts_i(struct wined3d_stateblock *stateblock,
1427 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
1429 unsigned int i;
1431 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1432 stateblock, start_idx, count, constants);
1434 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1435 return WINED3DERR_INVALIDCALL;
1437 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1438 count = WINED3D_MAX_CONSTS_I - start_idx;
1440 memcpy(&stateblock->stateblock_state.ps_consts_i[start_idx], constants, count * sizeof(*constants));
1441 for (i = start_idx; i < count + start_idx; ++i)
1442 stateblock->changed.pixelShaderConstantsI |= (1u << i);
1443 return WINED3D_OK;
1446 HRESULT CDECL wined3d_stateblock_set_ps_consts_b(struct wined3d_stateblock *stateblock,
1447 unsigned int start_idx, unsigned int count, const BOOL *constants)
1449 unsigned int i;
1451 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n",
1452 stateblock, start_idx, count, constants);
1454 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1455 return WINED3DERR_INVALIDCALL;
1457 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1458 count = WINED3D_MAX_CONSTS_B - start_idx;
1460 memcpy(&stateblock->stateblock_state.ps_consts_b[start_idx], constants, count * sizeof(*constants));
1461 for (i = start_idx; i < count + start_idx; ++i)
1462 stateblock->changed.pixelShaderConstantsB |= (1u << i);
1463 return WINED3D_OK;
1466 HRESULT CDECL wined3d_stateblock_get_ps_consts_f(struct wined3d_stateblock *stateblock,
1467 unsigned int start_idx, unsigned int count, struct wined3d_vec4 *constants)
1469 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1471 if (!constants || !wined3d_bound_range(start_idx, count, WINED3D_MAX_PS_CONSTS_F))
1472 return WINED3DERR_INVALIDCALL;
1474 memcpy(constants, &stateblock->stateblock_state.ps_consts_f[start_idx], count * sizeof(*constants));
1475 return WINED3D_OK;
1478 HRESULT CDECL wined3d_stateblock_get_ps_consts_i(struct wined3d_stateblock *stateblock,
1479 unsigned int start_idx, unsigned int count, struct wined3d_ivec4 *constants)
1481 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1483 if (!constants || start_idx >= WINED3D_MAX_CONSTS_I)
1484 return WINED3DERR_INVALIDCALL;
1486 if (count > WINED3D_MAX_CONSTS_I - start_idx)
1487 count = WINED3D_MAX_CONSTS_I - start_idx;
1489 memcpy(constants, &stateblock->stateblock_state.ps_consts_i[start_idx], count * sizeof(*constants));
1490 return WINED3D_OK;
1493 HRESULT CDECL wined3d_stateblock_get_ps_consts_b(struct wined3d_stateblock *stateblock,
1494 unsigned int start_idx, unsigned int count, BOOL *constants)
1496 TRACE("stateblock %p, start_idx %u, count %u, constants %p.\n", stateblock, start_idx, count, constants);
1498 if (!constants || start_idx >= WINED3D_MAX_CONSTS_B)
1499 return WINED3DERR_INVALIDCALL;
1501 if (count > WINED3D_MAX_CONSTS_B - start_idx)
1502 count = WINED3D_MAX_CONSTS_B - start_idx;
1504 memcpy(constants, &stateblock->stateblock_state.ps_consts_b[start_idx], count * sizeof(*constants));
1505 return WINED3D_OK;
1508 void CDECL wined3d_stateblock_set_vertex_declaration(struct wined3d_stateblock *stateblock,
1509 struct wined3d_vertex_declaration *declaration)
1511 TRACE("stateblock %p, declaration %p.\n", stateblock, declaration);
1513 if (declaration)
1514 wined3d_vertex_declaration_incref(declaration);
1515 if (stateblock->stateblock_state.vertex_declaration)
1516 wined3d_vertex_declaration_decref(stateblock->stateblock_state.vertex_declaration);
1517 stateblock->stateblock_state.vertex_declaration = declaration;
1518 stateblock->changed.vertexDecl = TRUE;
1521 void CDECL wined3d_stateblock_set_render_state(struct wined3d_stateblock *stateblock,
1522 enum wined3d_render_state state, unsigned int value)
1524 TRACE("stateblock %p, state %s (%#x), value %#x.\n", stateblock, debug_d3drenderstate(state), state, value);
1526 if (state > WINEHIGHEST_RENDER_STATE)
1528 WARN("Unhandled render state %#x.\n", state);
1529 return;
1532 stateblock->stateblock_state.rs[state] = value;
1533 stateblock->changed.renderState[state >> 5] |= 1u << (state & 0x1f);
1535 switch (state)
1537 case WINED3D_RS_POINTSIZE:
1538 if (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE || value == WINED3D_ALPHA_TO_COVERAGE_DISABLE)
1540 stateblock->changed.alpha_to_coverage = 1;
1541 stateblock->stateblock_state.alpha_to_coverage = (value == WINED3D_ALPHA_TO_COVERAGE_ENABLE);
1543 break;
1545 case WINED3D_RS_SPECULARENABLE:
1546 case WINED3D_RS_TEXTUREFACTOR:
1547 stateblock->changed.ffp_ps_constants = 1;
1548 break;
1550 default:
1551 break;
1555 void CDECL wined3d_stateblock_set_sampler_state(struct wined3d_stateblock *stateblock,
1556 UINT sampler_idx, enum wined3d_sampler_state state, unsigned int value)
1558 TRACE("stateblock %p, sampler_idx %u, state %s, value %#x.\n",
1559 stateblock, sampler_idx, debug_d3dsamplerstate(state), value);
1561 if (sampler_idx >= ARRAY_SIZE(stateblock->stateblock_state.sampler_states))
1563 WARN("Invalid sampler %u.\n", sampler_idx);
1564 return;
1567 stateblock->stateblock_state.sampler_states[sampler_idx][state] = value;
1568 stateblock->changed.samplerState[sampler_idx] |= 1u << state;
1571 void CDECL wined3d_stateblock_set_texture_stage_state(struct wined3d_stateblock *stateblock,
1572 UINT stage, enum wined3d_texture_stage_state state, unsigned int value)
1574 TRACE("stateblock %p, stage %u, state %s, value %#x.\n",
1575 stateblock, stage, debug_d3dtexturestate(state), value);
1577 if (state > WINED3D_HIGHEST_TEXTURE_STATE)
1579 WARN("Invalid state %#x passed.\n", state);
1580 return;
1583 if (stage >= WINED3D_MAX_FFP_TEXTURES)
1585 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
1586 stage, WINED3D_MAX_FFP_TEXTURES - 1);
1587 return;
1590 stateblock->stateblock_state.texture_states[stage][state] = value;
1591 stateblock->changed.textureState[stage] |= 1u << state;
1593 if (state == WINED3D_TSS_CONSTANT)
1594 stateblock->changed.ffp_ps_constants = 1;
1597 void CDECL wined3d_stateblock_set_texture(struct wined3d_stateblock *stateblock,
1598 UINT stage, struct wined3d_texture *texture)
1600 TRACE("stateblock %p, stage %u, texture %p.\n", stateblock, stage, texture);
1602 if (stage >= ARRAY_SIZE(stateblock->stateblock_state.textures))
1604 WARN("Ignoring invalid stage %u.\n", stage);
1605 return;
1608 if (texture)
1609 wined3d_texture_incref(texture);
1610 if (stateblock->stateblock_state.textures[stage])
1611 wined3d_texture_decref(stateblock->stateblock_state.textures[stage]);
1612 stateblock->stateblock_state.textures[stage] = texture;
1613 stateblock->changed.textures |= 1u << stage;
1616 void CDECL wined3d_stateblock_set_transform(struct wined3d_stateblock *stateblock,
1617 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1619 TRACE("stateblock %p, state %s, matrix %p.\n", stateblock, debug_d3dtstype(d3dts), matrix);
1620 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1621 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1622 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1623 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1625 stateblock->stateblock_state.transforms[d3dts] = *matrix;
1626 stateblock->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1627 stateblock->changed.transforms = 1;
1630 void CDECL wined3d_stateblock_multiply_transform(struct wined3d_stateblock *stateblock,
1631 enum wined3d_transform_state d3dts, const struct wined3d_matrix *matrix)
1633 struct wined3d_matrix *mat = &stateblock->stateblock_state.transforms[d3dts];
1635 TRACE("stateblock %p, state %s, matrix %p.\n", stateblock, debug_d3dtstype(d3dts), matrix);
1636 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
1637 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
1638 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
1639 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
1641 multiply_matrix(mat, mat, matrix);
1642 stateblock->changed.transform[d3dts >> 5] |= 1u << (d3dts & 0x1f);
1643 stateblock->changed.transforms = 1;
1646 HRESULT CDECL wined3d_stateblock_set_clip_plane(struct wined3d_stateblock *stateblock,
1647 UINT plane_idx, const struct wined3d_vec4 *plane)
1649 TRACE("stateblock %p, plane_idx %u, plane %p.\n", stateblock, plane_idx, plane);
1651 if (plane_idx >= stateblock->device->adapter->d3d_info.limits.max_clip_distances)
1653 TRACE("Application has requested clipplane this device doesn't support.\n");
1654 return WINED3DERR_INVALIDCALL;
1657 stateblock->stateblock_state.clip_planes[plane_idx] = *plane;
1658 stateblock->changed.clipplane |= 1u << plane_idx;
1659 return S_OK;
1662 void CDECL wined3d_stateblock_set_material(struct wined3d_stateblock *stateblock,
1663 const struct wined3d_material *material)
1665 TRACE("stateblock %p, material %p.\n", stateblock, material);
1667 stateblock->stateblock_state.material = *material;
1668 stateblock->changed.material = TRUE;
1671 void CDECL wined3d_stateblock_set_viewport(struct wined3d_stateblock *stateblock,
1672 const struct wined3d_viewport *viewport)
1674 TRACE("stateblock %p, viewport %p.\n", stateblock, viewport);
1676 stateblock->stateblock_state.viewport = *viewport;
1677 stateblock->changed.viewport = TRUE;
1680 void CDECL wined3d_stateblock_set_scissor_rect(struct wined3d_stateblock *stateblock, const RECT *rect)
1682 TRACE("stateblock %p, rect %s.\n", stateblock, wine_dbgstr_rect(rect));
1684 stateblock->stateblock_state.scissor_rect = *rect;
1685 stateblock->changed.scissorRect = TRUE;
1688 void CDECL wined3d_stateblock_set_index_buffer(struct wined3d_stateblock *stateblock,
1689 struct wined3d_buffer *buffer, enum wined3d_format_id format_id)
1691 TRACE("stateblock %p, buffer %p, format %s.\n", stateblock, buffer, debug_d3dformat(format_id));
1693 if (buffer)
1694 wined3d_buffer_incref(buffer);
1695 if (stateblock->stateblock_state.index_buffer)
1696 wined3d_buffer_decref(stateblock->stateblock_state.index_buffer);
1697 stateblock->stateblock_state.index_buffer = buffer;
1698 stateblock->stateblock_state.index_format = format_id;
1699 stateblock->changed.indices = TRUE;
1702 void CDECL wined3d_stateblock_set_base_vertex_index(struct wined3d_stateblock *stateblock, INT base_index)
1704 TRACE("stateblock %p, base_index %d.\n", stateblock, base_index);
1706 stateblock->stateblock_state.base_vertex_index = base_index;
1709 HRESULT CDECL wined3d_stateblock_set_stream_source(struct wined3d_stateblock *stateblock,
1710 UINT stream_idx, struct wined3d_buffer *buffer, UINT offset, UINT stride)
1712 struct wined3d_stream_state *stream;
1714 TRACE("stateblock %p, stream_idx %u, buffer %p, stride %u.\n",
1715 stateblock, stream_idx, buffer, stride);
1717 if (stream_idx >= WINED3D_MAX_STREAMS)
1719 WARN("Stream index %u out of range.\n", stream_idx);
1720 return WINED3DERR_INVALIDCALL;
1723 stream = &stateblock->stateblock_state.streams[stream_idx];
1725 if (buffer)
1726 wined3d_buffer_incref(buffer);
1727 if (stream->buffer)
1728 wined3d_buffer_decref(stream->buffer);
1729 stream->buffer = buffer;
1730 stream->stride = stride;
1731 stream->offset = offset;
1732 stateblock->changed.streamSource |= 1u << stream_idx;
1733 return WINED3D_OK;
1736 HRESULT CDECL wined3d_stateblock_set_stream_source_freq(struct wined3d_stateblock *stateblock,
1737 UINT stream_idx, UINT divider)
1739 struct wined3d_stream_state *stream;
1741 TRACE("stateblock %p, stream_idx %u, divider %#x.\n", stateblock, stream_idx, divider);
1743 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && (divider & WINED3DSTREAMSOURCE_INDEXEDDATA))
1745 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL.\n");
1746 return WINED3DERR_INVALIDCALL;
1748 if ((divider & WINED3DSTREAMSOURCE_INSTANCEDATA) && !stream_idx)
1750 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL.\n");
1751 return WINED3DERR_INVALIDCALL;
1753 if (!divider)
1755 WARN("Divider is 0, returning D3DERR_INVALIDCALL.\n");
1756 return WINED3DERR_INVALIDCALL;
1759 stream = &stateblock->stateblock_state.streams[stream_idx];
1760 stream->flags = divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA);
1761 stream->frequency = divider & 0x7fffff;
1762 stateblock->changed.streamFreq |= 1u << stream_idx;
1763 return WINED3D_OK;
1766 HRESULT CDECL wined3d_stateblock_set_light(struct wined3d_stateblock *stateblock,
1767 UINT light_idx, const struct wined3d_light *light)
1769 struct wined3d_light_info *object = NULL;
1770 HRESULT hr;
1772 TRACE("stateblock %p, light_idx %u, light %p.\n", stateblock, light_idx, light);
1774 /* Check the parameter range. Need for speed most wanted sets junk lights
1775 * which confuse the GL driver. */
1776 if (!light)
1777 return WINED3DERR_INVALIDCALL;
1779 switch (light->type)
1781 case WINED3D_LIGHT_POINT:
1782 case WINED3D_LIGHT_SPOT:
1783 case WINED3D_LIGHT_GLSPOT:
1784 /* Incorrect attenuation values can cause the gl driver to crash.
1785 * Happens with Need for speed most wanted. */
1786 if (light->attenuation0 < 0.0f || light->attenuation1 < 0.0f || light->attenuation2 < 0.0f)
1788 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL.\n");
1789 return WINED3DERR_INVALIDCALL;
1791 break;
1793 case WINED3D_LIGHT_DIRECTIONAL:
1794 case WINED3D_LIGHT_PARALLELPOINT:
1795 /* Ignores attenuation */
1796 break;
1798 default:
1799 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL.\n");
1800 return WINED3DERR_INVALIDCALL;
1803 if (SUCCEEDED(hr = wined3d_light_state_set_light(stateblock->stateblock_state.light_state, light_idx, light, &object)))
1804 set_light_changed(stateblock, object);
1805 return hr;
1808 HRESULT CDECL wined3d_stateblock_set_light_enable(struct wined3d_stateblock *stateblock, UINT light_idx, BOOL enable)
1810 struct wined3d_light_state *light_state = stateblock->stateblock_state.light_state;
1811 struct wined3d_light_info *light_info;
1812 HRESULT hr;
1814 TRACE("stateblock %p, light_idx %u, enable %#x.\n", stateblock, light_idx, enable);
1816 if (!(light_info = wined3d_light_state_get_light(light_state, light_idx)))
1818 if (FAILED(hr = wined3d_light_state_set_light(light_state, light_idx, &WINED3D_default_light, &light_info)))
1819 return hr;
1820 set_light_changed(stateblock, light_info);
1823 if (wined3d_light_state_enable_light(light_state, &stateblock->device->adapter->d3d_info, light_info, enable))
1824 set_light_changed(stateblock, light_info);
1826 return S_OK;
1829 const struct wined3d_stateblock_state * CDECL wined3d_stateblock_get_state(const struct wined3d_stateblock *stateblock)
1831 return &stateblock->stateblock_state;
1834 HRESULT CDECL wined3d_stateblock_get_light(const struct wined3d_stateblock *stateblock,
1835 UINT light_idx, struct wined3d_light *light, BOOL *enabled)
1837 struct wined3d_light_info *light_info;
1839 if (!(light_info = wined3d_light_state_get_light(&stateblock->light_state, light_idx)))
1841 TRACE("Light %u is not defined.\n", light_idx);
1842 return WINED3DERR_INVALIDCALL;
1844 *light = light_info->OriginalParms;
1845 *enabled = light_info->enabled ? 128 : 0;
1846 return WINED3D_OK;
1849 static void init_default_render_states(unsigned int rs[WINEHIGHEST_RENDER_STATE + 1], const struct wined3d_d3d_info *d3d_info)
1851 union
1853 struct wined3d_line_pattern lp;
1854 DWORD d;
1855 } lp;
1856 union
1858 float f;
1859 DWORD d;
1860 } tmpfloat;
1862 rs[WINED3D_RS_ZENABLE] = WINED3D_ZB_TRUE;
1863 rs[WINED3D_RS_FILLMODE] = WINED3D_FILL_SOLID;
1864 rs[WINED3D_RS_SHADEMODE] = WINED3D_SHADE_GOURAUD;
1865 lp.lp.repeat_factor = 0;
1866 lp.lp.line_pattern = 0;
1867 rs[WINED3D_RS_LINEPATTERN] = lp.d;
1868 rs[WINED3D_RS_ZWRITEENABLE] = TRUE;
1869 rs[WINED3D_RS_ALPHATESTENABLE] = FALSE;
1870 rs[WINED3D_RS_LASTPIXEL] = TRUE;
1871 rs[WINED3D_RS_SRCBLEND] = WINED3D_BLEND_ONE;
1872 rs[WINED3D_RS_DESTBLEND] = WINED3D_BLEND_ZERO;
1873 rs[WINED3D_RS_CULLMODE] = WINED3D_CULL_BACK;
1874 rs[WINED3D_RS_ZFUNC] = WINED3D_CMP_LESSEQUAL;
1875 rs[WINED3D_RS_ALPHAFUNC] = WINED3D_CMP_ALWAYS;
1876 rs[WINED3D_RS_ALPHAREF] = 0;
1877 rs[WINED3D_RS_DITHERENABLE] = FALSE;
1878 rs[WINED3D_RS_ALPHABLENDENABLE] = FALSE;
1879 rs[WINED3D_RS_FOGENABLE] = FALSE;
1880 rs[WINED3D_RS_SPECULARENABLE] = FALSE;
1881 rs[WINED3D_RS_ZVISIBLE] = 0;
1882 rs[WINED3D_RS_FOGCOLOR] = 0;
1883 rs[WINED3D_RS_FOGTABLEMODE] = WINED3D_FOG_NONE;
1884 tmpfloat.f = 0.0f;
1885 rs[WINED3D_RS_FOGSTART] = tmpfloat.d;
1886 tmpfloat.f = 1.0f;
1887 rs[WINED3D_RS_FOGEND] = tmpfloat.d;
1888 tmpfloat.f = 1.0f;
1889 rs[WINED3D_RS_FOGDENSITY] = tmpfloat.d;
1890 rs[WINED3D_RS_RANGEFOGENABLE] = FALSE;
1891 rs[WINED3D_RS_STENCILENABLE] = FALSE;
1892 rs[WINED3D_RS_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1893 rs[WINED3D_RS_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1894 rs[WINED3D_RS_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1895 rs[WINED3D_RS_STENCILREF] = 0;
1896 rs[WINED3D_RS_STENCILMASK] = 0xffffffff;
1897 rs[WINED3D_RS_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1898 rs[WINED3D_RS_STENCILWRITEMASK] = 0xffffffff;
1899 rs[WINED3D_RS_TEXTUREFACTOR] = 0xffffffff;
1900 rs[WINED3D_RS_WRAP0] = 0;
1901 rs[WINED3D_RS_WRAP1] = 0;
1902 rs[WINED3D_RS_WRAP2] = 0;
1903 rs[WINED3D_RS_WRAP3] = 0;
1904 rs[WINED3D_RS_WRAP4] = 0;
1905 rs[WINED3D_RS_WRAP5] = 0;
1906 rs[WINED3D_RS_WRAP6] = 0;
1907 rs[WINED3D_RS_WRAP7] = 0;
1908 rs[WINED3D_RS_CLIPPING] = TRUE;
1909 rs[WINED3D_RS_LIGHTING] = TRUE;
1910 rs[WINED3D_RS_AMBIENT] = 0;
1911 rs[WINED3D_RS_FOGVERTEXMODE] = WINED3D_FOG_NONE;
1912 rs[WINED3D_RS_COLORVERTEX] = TRUE;
1913 rs[WINED3D_RS_LOCALVIEWER] = TRUE;
1914 rs[WINED3D_RS_NORMALIZENORMALS] = FALSE;
1915 rs[WINED3D_RS_DIFFUSEMATERIALSOURCE] = WINED3D_MCS_COLOR1;
1916 rs[WINED3D_RS_SPECULARMATERIALSOURCE] = WINED3D_MCS_COLOR2;
1917 rs[WINED3D_RS_AMBIENTMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1918 rs[WINED3D_RS_EMISSIVEMATERIALSOURCE] = WINED3D_MCS_MATERIAL;
1919 rs[WINED3D_RS_VERTEXBLEND] = WINED3D_VBF_DISABLE;
1920 rs[WINED3D_RS_CLIPPLANEENABLE] = 0;
1921 rs[WINED3D_RS_SOFTWAREVERTEXPROCESSING] = FALSE;
1922 tmpfloat.f = 1.0f;
1923 rs[WINED3D_RS_POINTSIZE] = tmpfloat.d;
1924 tmpfloat.f = 1.0f;
1925 rs[WINED3D_RS_POINTSIZE_MIN] = tmpfloat.d;
1926 rs[WINED3D_RS_POINTSPRITEENABLE] = FALSE;
1927 rs[WINED3D_RS_POINTSCALEENABLE] = FALSE;
1928 tmpfloat.f = 1.0f;
1929 rs[WINED3D_RS_POINTSCALE_A] = tmpfloat.d;
1930 tmpfloat.f = 0.0f;
1931 rs[WINED3D_RS_POINTSCALE_B] = tmpfloat.d;
1932 tmpfloat.f = 0.0f;
1933 rs[WINED3D_RS_POINTSCALE_C] = tmpfloat.d;
1934 rs[WINED3D_RS_MULTISAMPLEANTIALIAS] = TRUE;
1935 rs[WINED3D_RS_MULTISAMPLEMASK] = 0xffffffff;
1936 rs[WINED3D_RS_PATCHEDGESTYLE] = WINED3D_PATCH_EDGE_DISCRETE;
1937 tmpfloat.f = 1.0f;
1938 rs[WINED3D_RS_PATCHSEGMENTS] = tmpfloat.d;
1939 rs[WINED3D_RS_DEBUGMONITORTOKEN] = 0xbaadcafe;
1940 tmpfloat.f = d3d_info->limits.pointsize_max;
1941 rs[WINED3D_RS_POINTSIZE_MAX] = tmpfloat.d;
1942 rs[WINED3D_RS_INDEXEDVERTEXBLENDENABLE] = FALSE;
1943 rs[WINED3D_RS_COLORWRITEENABLE] = 0x0000000f;
1944 tmpfloat.f = 0.0f;
1945 rs[WINED3D_RS_TWEENFACTOR] = tmpfloat.d;
1946 rs[WINED3D_RS_BLENDOP] = WINED3D_BLEND_OP_ADD;
1947 rs[WINED3D_RS_POSITIONDEGREE] = WINED3D_DEGREE_CUBIC;
1948 rs[WINED3D_RS_NORMALDEGREE] = WINED3D_DEGREE_LINEAR;
1949 /* states new in d3d9 */
1950 rs[WINED3D_RS_SCISSORTESTENABLE] = FALSE;
1951 rs[WINED3D_RS_SLOPESCALEDEPTHBIAS] = 0;
1952 tmpfloat.f = 1.0f;
1953 rs[WINED3D_RS_MINTESSELLATIONLEVEL] = tmpfloat.d;
1954 rs[WINED3D_RS_MAXTESSELLATIONLEVEL] = tmpfloat.d;
1955 rs[WINED3D_RS_ANTIALIASEDLINEENABLE] = FALSE;
1956 tmpfloat.f = 0.0f;
1957 rs[WINED3D_RS_ADAPTIVETESS_X] = tmpfloat.d;
1958 rs[WINED3D_RS_ADAPTIVETESS_Y] = tmpfloat.d;
1959 tmpfloat.f = 1.0f;
1960 rs[WINED3D_RS_ADAPTIVETESS_Z] = tmpfloat.d;
1961 tmpfloat.f = 0.0f;
1962 rs[WINED3D_RS_ADAPTIVETESS_W] = tmpfloat.d;
1963 rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION] = FALSE;
1964 rs[WINED3D_RS_TWOSIDEDSTENCILMODE] = FALSE;
1965 rs[WINED3D_RS_BACK_STENCILFAIL] = WINED3D_STENCIL_OP_KEEP;
1966 rs[WINED3D_RS_BACK_STENCILZFAIL] = WINED3D_STENCIL_OP_KEEP;
1967 rs[WINED3D_RS_BACK_STENCILPASS] = WINED3D_STENCIL_OP_KEEP;
1968 rs[WINED3D_RS_BACK_STENCILFUNC] = WINED3D_CMP_ALWAYS;
1969 rs[WINED3D_RS_COLORWRITEENABLE1] = 0x0000000f;
1970 rs[WINED3D_RS_COLORWRITEENABLE2] = 0x0000000f;
1971 rs[WINED3D_RS_COLORWRITEENABLE3] = 0x0000000f;
1972 rs[WINED3D_RS_BLENDFACTOR] = 0xffffffff;
1973 rs[WINED3D_RS_SRGBWRITEENABLE] = 0;
1974 rs[WINED3D_RS_DEPTHBIAS] = 0;
1975 rs[WINED3D_RS_WRAP8] = 0;
1976 rs[WINED3D_RS_WRAP9] = 0;
1977 rs[WINED3D_RS_WRAP10] = 0;
1978 rs[WINED3D_RS_WRAP11] = 0;
1979 rs[WINED3D_RS_WRAP12] = 0;
1980 rs[WINED3D_RS_WRAP13] = 0;
1981 rs[WINED3D_RS_WRAP14] = 0;
1982 rs[WINED3D_RS_WRAP15] = 0;
1983 rs[WINED3D_RS_SEPARATEALPHABLENDENABLE] = FALSE;
1984 rs[WINED3D_RS_SRCBLENDALPHA] = WINED3D_BLEND_ONE;
1985 rs[WINED3D_RS_DESTBLENDALPHA] = WINED3D_BLEND_ZERO;
1986 rs[WINED3D_RS_BLENDOPALPHA] = WINED3D_BLEND_OP_ADD;
1989 static void init_default_texture_state(unsigned int i, uint32_t stage[WINED3D_HIGHEST_TEXTURE_STATE + 1])
1991 stage[WINED3D_TSS_COLOR_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_MODULATE;
1992 stage[WINED3D_TSS_COLOR_ARG1] = WINED3DTA_TEXTURE;
1993 stage[WINED3D_TSS_COLOR_ARG2] = WINED3DTA_CURRENT;
1994 stage[WINED3D_TSS_ALPHA_OP] = i ? WINED3D_TOP_DISABLE : WINED3D_TOP_SELECT_ARG1;
1995 stage[WINED3D_TSS_ALPHA_ARG1] = WINED3DTA_TEXTURE;
1996 stage[WINED3D_TSS_ALPHA_ARG2] = WINED3DTA_CURRENT;
1997 stage[WINED3D_TSS_BUMPENV_MAT00] = 0;
1998 stage[WINED3D_TSS_BUMPENV_MAT01] = 0;
1999 stage[WINED3D_TSS_BUMPENV_MAT10] = 0;
2000 stage[WINED3D_TSS_BUMPENV_MAT11] = 0;
2001 stage[WINED3D_TSS_TEXCOORD_INDEX] = i;
2002 stage[WINED3D_TSS_BUMPENV_LSCALE] = 0;
2003 stage[WINED3D_TSS_BUMPENV_LOFFSET] = 0;
2004 stage[WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS] = WINED3D_TTFF_DISABLE;
2005 stage[WINED3D_TSS_COLOR_ARG0] = WINED3DTA_CURRENT;
2006 stage[WINED3D_TSS_ALPHA_ARG0] = WINED3DTA_CURRENT;
2007 stage[WINED3D_TSS_RESULT_ARG] = WINED3DTA_CURRENT;
2010 static void init_default_sampler_states(uint32_t states[WINED3D_MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1])
2012 unsigned int i;
2014 for (i = 0 ; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
2016 TRACE("Setting up default samplers states for sampler %u.\n", i);
2017 states[i][WINED3D_SAMP_ADDRESS_U] = WINED3D_TADDRESS_WRAP;
2018 states[i][WINED3D_SAMP_ADDRESS_V] = WINED3D_TADDRESS_WRAP;
2019 states[i][WINED3D_SAMP_ADDRESS_W] = WINED3D_TADDRESS_WRAP;
2020 states[i][WINED3D_SAMP_BORDER_COLOR] = 0;
2021 states[i][WINED3D_SAMP_MAG_FILTER] = WINED3D_TEXF_POINT;
2022 states[i][WINED3D_SAMP_MIN_FILTER] = WINED3D_TEXF_POINT;
2023 states[i][WINED3D_SAMP_MIP_FILTER] = WINED3D_TEXF_NONE;
2024 states[i][WINED3D_SAMP_MIPMAP_LOD_BIAS] = 0;
2025 states[i][WINED3D_SAMP_MAX_MIP_LEVEL] = 0;
2026 states[i][WINED3D_SAMP_MAX_ANISOTROPY] = 1;
2027 states[i][WINED3D_SAMP_SRGB_TEXTURE] = 0;
2028 /* TODO: Indicates which element of a multielement texture to use. */
2029 states[i][WINED3D_SAMP_ELEMENT_INDEX] = 0;
2030 /* TODO: Vertex offset in the presampled displacement map. */
2031 states[i][WINED3D_SAMP_DMAP_OFFSET] = 0;
2035 static void state_init_default(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info)
2037 struct wined3d_matrix identity;
2038 unsigned int i, j;
2040 TRACE("state %p, d3d_info %p.\n", state, d3d_info);
2042 get_identity_matrix(&identity);
2043 state->primitive_type = WINED3D_PT_UNDEFINED;
2044 state->patch_vertex_count = 0;
2046 /* Set some of the defaults for lights, transforms etc */
2047 state->transforms[WINED3D_TS_PROJECTION] = identity;
2048 state->transforms[WINED3D_TS_VIEW] = identity;
2049 for (i = 0; i < 256; ++i)
2051 state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
2054 init_default_render_states(state->render_states, d3d_info);
2056 /* Texture Stage States - Put directly into state block, we will call function below */
2057 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
2059 TRACE("Setting up default texture states for texture Stage %u.\n", i);
2060 state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
2061 init_default_texture_state(i, state->texture_states[i]);
2064 state->blend_factor.r = 1.0f;
2065 state->blend_factor.g = 1.0f;
2066 state->blend_factor.b = 1.0f;
2067 state->blend_factor.a = 1.0f;
2069 state->sample_mask = 0xffffffff;
2071 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
2072 state->streams[i].frequency = 1;
2074 for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
2076 for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j)
2077 state->cb[i][j].size = WINED3D_MAX_CONSTANT_BUFFER_SIZE * 16;
2081 static int lights_compare(const void *key, const struct rb_entry *entry)
2083 const struct wined3d_light_info *light = RB_ENTRY_VALUE(entry, struct wined3d_light_info, entry);
2084 unsigned int original_index = (ULONG_PTR)key;
2086 return wined3d_uint32_compare(light->OriginalIndex, original_index);
2089 void state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info,
2090 uint32_t flags, enum wined3d_feature_level feature_level)
2092 state->feature_level = feature_level;
2093 state->flags = flags;
2095 rb_init(&state->light_state.lights_tree, lights_compare);
2097 if (flags & WINED3D_STATE_INIT_DEFAULT)
2098 state_init_default(state, d3d_info);
2101 static bool wined3d_select_feature_level(const struct wined3d_adapter *adapter,
2102 const enum wined3d_feature_level *levels, unsigned int level_count,
2103 enum wined3d_feature_level *selected_level)
2105 const struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
2106 unsigned int i;
2108 for (i = 0; i < level_count; ++i)
2110 if (levels[i] && d3d_info->feature_level >= levels[i])
2112 *selected_level = levels[i];
2113 return true;
2117 FIXME_(winediag)("None of the requested D3D feature levels is supported on this GPU "
2118 "with the current shader backend.\n");
2119 return false;
2122 HRESULT CDECL wined3d_state_create(struct wined3d_device *device,
2123 const enum wined3d_feature_level *levels, unsigned int level_count, struct wined3d_state **state)
2125 enum wined3d_feature_level feature_level;
2126 struct wined3d_state *object;
2128 TRACE("device %p, levels %p, level_count %u, state %p.\n", device, levels, level_count, state);
2130 if (!wined3d_select_feature_level(device->adapter, levels, level_count, &feature_level))
2131 return E_FAIL;
2133 TRACE("Selected feature level %s.\n", wined3d_debug_feature_level(feature_level));
2135 if (!(object = calloc(1, sizeof(*object))))
2136 return E_OUTOFMEMORY;
2137 state_init(object, &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT, feature_level);
2139 *state = object;
2140 return S_OK;
2143 enum wined3d_feature_level CDECL wined3d_state_get_feature_level(const struct wined3d_state *state)
2145 TRACE("state %p.\n", state);
2147 return state->feature_level;
2150 void CDECL wined3d_state_destroy(struct wined3d_state *state)
2152 TRACE("state %p.\n", state);
2154 state_cleanup(state);
2155 free(state);
2158 static void stateblock_state_init_default(struct wined3d_stateblock_state *state,
2159 const struct wined3d_d3d_info *d3d_info)
2161 struct wined3d_matrix identity;
2162 unsigned int i;
2164 get_identity_matrix(&identity);
2166 state->transforms[WINED3D_TS_PROJECTION] = identity;
2167 state->transforms[WINED3D_TS_VIEW] = identity;
2168 for (i = 0; i < 256; ++i)
2170 state->transforms[WINED3D_TS_WORLD_MATRIX(i)] = identity;
2173 init_default_render_states(state->rs, d3d_info);
2175 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
2177 state->transforms[WINED3D_TS_TEXTURE0 + i] = identity;
2178 init_default_texture_state(i, state->texture_states[i]);
2181 init_default_sampler_states(state->sampler_states);
2183 for (i = 0; i < WINED3D_MAX_STREAMS; ++i)
2184 state->streams[i].frequency = 1;
2187 static void wined3d_stateblock_state_init(struct wined3d_stateblock_state *state,
2188 const struct wined3d_device *device, uint32_t flags)
2190 rb_init(&state->light_state->lights_tree, lights_compare);
2192 if (flags & WINED3D_STATE_INIT_DEFAULT)
2193 stateblock_state_init_default(state, &device->adapter->d3d_info);
2197 /* FFP push constant buffers do not have a "default" state on the CS side.
2198 * We need to explicitly invalidate them when initializing the context or
2199 * resetting. */
2200 static void wined3d_stateblock_invalidate_push_constants(struct wined3d_stateblock *stateblock)
2202 stateblock->changed.ffp_ps_constants = 1;
2203 stateblock->changed.lights = 1;
2206 static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const struct wined3d_stateblock *device_state,
2207 struct wined3d_device *device, enum wined3d_stateblock_type type)
2209 const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
2211 stateblock->ref = 1;
2212 stateblock->device = device;
2213 stateblock->stateblock_state.light_state = &stateblock->light_state;
2214 wined3d_stateblock_state_init(&stateblock->stateblock_state, device,
2215 type == WINED3D_SBT_PRIMARY ? WINED3D_STATE_INIT_DEFAULT : 0);
2217 stateblock->changed.store_stream_offset = 1;
2218 list_init(&stateblock->changed.changed_lights);
2220 wined3d_stateblock_invalidate_push_constants(stateblock);
2222 if (type == WINED3D_SBT_RECORDED || type == WINED3D_SBT_PRIMARY)
2223 return WINED3D_OK;
2225 TRACE("Updating changed flags appropriate for type %#x.\n", type);
2227 switch (type)
2229 case WINED3D_SBT_ALL:
2230 stateblock_init_lights(stateblock, &device_state->stateblock_state.light_state->lights_tree);
2231 stateblock_savedstates_set_all(&stateblock->changed,
2232 d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
2233 break;
2235 case WINED3D_SBT_PIXEL_STATE:
2236 stateblock_savedstates_set_pixel(&stateblock->changed,
2237 d3d_info->limits.ps_uniform_count);
2238 break;
2240 case WINED3D_SBT_VERTEX_STATE:
2241 stateblock_init_lights(stateblock, &device_state->stateblock_state.light_state->lights_tree);
2242 stateblock_savedstates_set_vertex(&stateblock->changed,
2243 d3d_info->limits.vs_uniform_count);
2244 break;
2246 default:
2247 FIXME("Unrecognized state block type %#x.\n", type);
2248 break;
2251 wined3d_stateblock_init_contained_states(stateblock);
2252 wined3d_stateblock_capture(stateblock, device_state);
2254 /* According to the tests, stream offset is not updated in the captured state if
2255 * the state was captured on state block creation. This is not the case for
2256 * state blocks initialized with BeginStateBlock / EndStateBlock, multiple
2257 * captures get stream offsets updated. */
2258 stateblock->changed.store_stream_offset = 0;
2260 return WINED3D_OK;
2263 HRESULT CDECL wined3d_stateblock_create(struct wined3d_device *device, const struct wined3d_stateblock *device_state,
2264 enum wined3d_stateblock_type type, struct wined3d_stateblock **stateblock)
2266 struct wined3d_stateblock *object;
2267 HRESULT hr;
2269 TRACE("device %p, device_state %p, type %#x, stateblock %p.\n",
2270 device, device_state, type, stateblock);
2272 if (!(object = calloc(1, sizeof(*object))))
2273 return E_OUTOFMEMORY;
2275 hr = stateblock_init(object, device_state, device, type);
2276 if (FAILED(hr))
2278 WARN("Failed to initialize stateblock, hr %#lx.\n", hr);
2279 free(object);
2280 return hr;
2283 TRACE("Created stateblock %p.\n", object);
2284 *stateblock = object;
2286 return WINED3D_OK;
2289 void CDECL wined3d_stateblock_reset(struct wined3d_stateblock *stateblock)
2291 TRACE("stateblock %p.\n", stateblock);
2293 wined3d_stateblock_state_cleanup(&stateblock->stateblock_state);
2294 memset(&stateblock->stateblock_state, 0, sizeof(stateblock->stateblock_state));
2295 stateblock->stateblock_state.light_state = &stateblock->light_state;
2296 wined3d_stateblock_state_init(&stateblock->stateblock_state, stateblock->device, WINED3D_STATE_INIT_DEFAULT);
2297 wined3d_stateblock_invalidate_push_constants(stateblock);
2300 static void wined3d_device_set_base_vertex_index(struct wined3d_device *device, int base_index)
2302 TRACE("device %p, base_index %d.\n", device, base_index);
2304 device->cs->c.state->base_vertex_index = base_index;
2307 static void wined3d_device_set_vs_consts_b(struct wined3d_device *device,
2308 unsigned int start_idx, unsigned int count, const BOOL *constants)
2310 unsigned int i;
2312 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2314 if (TRACE_ON(d3d))
2316 for (i = 0; i < count; ++i)
2317 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2320 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_B,
2321 WINED3D_SHADER_CONST_VS_B, start_idx, count, constants);
2324 static void wined3d_device_set_vs_consts_i(struct wined3d_device *device,
2325 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2327 unsigned int i;
2329 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2331 if (TRACE_ON(d3d))
2333 for (i = 0; i < count; ++i)
2334 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2337 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_I,
2338 WINED3D_SHADER_CONST_VS_I, start_idx, count, constants);
2341 static void wined3d_device_set_vs_consts_f(struct wined3d_device *device,
2342 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2344 unsigned int i;
2346 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2348 if (TRACE_ON(d3d))
2350 for (i = 0; i < count; ++i)
2351 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2354 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_VS_F,
2355 WINED3D_SHADER_CONST_VS_F, start_idx, count, constants);
2358 static void wined3d_device_set_ps_consts_b(struct wined3d_device *device,
2359 unsigned int start_idx, unsigned int count, const BOOL *constants)
2361 unsigned int i;
2363 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2365 if (TRACE_ON(d3d))
2367 for (i = 0; i < count; ++i)
2368 TRACE("Set BOOL constant %u to %#x.\n", start_idx + i, constants[i]);
2371 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_B,
2372 WINED3D_SHADER_CONST_PS_B, start_idx, count, constants);
2375 static void wined3d_device_set_ps_consts_i(struct wined3d_device *device,
2376 unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants)
2378 unsigned int i;
2380 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2382 if (TRACE_ON(d3d))
2384 for (i = 0; i < count; ++i)
2385 TRACE("Set ivec4 constant %u to %s.\n", start_idx + i, debug_ivec4(&constants[i]));
2388 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_I,
2389 WINED3D_SHADER_CONST_PS_I, start_idx, count, constants);
2392 static void wined3d_device_set_ps_consts_f(struct wined3d_device *device,
2393 unsigned int start_idx, unsigned int count, const struct wined3d_vec4 *constants)
2395 unsigned int i;
2397 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device, start_idx, count, constants);
2399 if (TRACE_ON(d3d))
2401 for (i = 0; i < count; ++i)
2402 TRACE("Set vec4 constant %u to %s.\n", start_idx + i, debug_vec4(&constants[i]));
2405 wined3d_device_context_push_constants(&device->cs->c, WINED3D_PUSH_CONSTANTS_PS_F,
2406 WINED3D_SHADER_CONST_PS_F, start_idx, count, constants);
2409 /* Note lights are real special cases. Although the device caps state only
2410 * e.g. 8 are supported, you can reference any indexes you want as long as
2411 * that number max are enabled at any one point in time. Therefore since the
2412 * indices can be anything, we need a hashmap of them. However, this causes
2413 * stateblock problems. When capturing the state block, I duplicate the
2414 * hashmap, but when recording, just build a chain pretty much of commands to
2415 * be replayed. */
2416 static void wined3d_device_context_set_light(struct wined3d_device_context *context,
2417 unsigned int light_idx, const struct wined3d_light *light)
2419 struct wined3d_light_info *object = NULL;
2421 if (FAILED(wined3d_light_state_set_light(&context->state->light_state, light_idx, light, &object)))
2422 return;
2424 wined3d_device_context_emit_set_light(context, object);
2427 static void wined3d_device_set_light_enable(struct wined3d_device *device, unsigned int light_idx, bool enable)
2429 struct wined3d_light_state *light_state = &device->cs->c.state->light_state;
2430 struct wined3d_light_info *light_info;
2432 TRACE("device %p, light_idx %u, enable %#x.\n", device, light_idx, enable);
2434 /* Special case - enabling an undefined light creates one with a strict set of parameters. */
2435 if (!(light_info = wined3d_light_state_get_light(light_state, light_idx)))
2437 TRACE("Light enabled requested but light not defined, so defining one!\n");
2438 wined3d_device_context_set_light(&device->cs->c, light_idx, &WINED3D_default_light);
2440 if (!(light_info = wined3d_light_state_get_light(light_state, light_idx)))
2442 ERR("Adding default lights has failed dismally.\n");
2443 return;
2447 if (wined3d_light_state_enable_light(light_state, &device->adapter->d3d_info, light_info, enable))
2448 wined3d_device_context_emit_set_light_enable(&device->cs->c, light_idx, enable);
2451 static void wined3d_device_set_clip_plane(struct wined3d_device *device,
2452 unsigned int plane_idx, const struct wined3d_vec4 *plane)
2454 struct wined3d_vec4 *clip_planes = device->cs->c.state->clip_planes;
2456 TRACE("device %p, plane_idx %u, plane %p.\n", device, plane_idx, plane);
2458 if (!memcmp(&clip_planes[plane_idx], plane, sizeof(*plane)))
2460 TRACE("Application is setting old values over, nothing to do.\n");
2461 return;
2464 clip_planes[plane_idx] = *plane;
2466 wined3d_device_context_emit_set_clip_plane(&device->cs->c, plane_idx, plane);
2469 static void resolve_depth_buffer(struct wined3d_device *device)
2471 const struct wined3d_state *state = device->cs->c.state;
2472 struct wined3d_rendertarget_view *src_view;
2473 struct wined3d_resource *dst_resource;
2474 struct wined3d_texture *dst_texture;
2476 if (!(dst_texture = wined3d_state_get_ffp_texture(state, 0)))
2477 return;
2478 dst_resource = &dst_texture->resource;
2479 if (!dst_resource->format->depth_size)
2480 return;
2481 if (!(src_view = state->fb.depth_stencil))
2482 return;
2484 wined3d_device_context_resolve_sub_resource(&device->cs->c, dst_resource, 0,
2485 src_view->resource, src_view->sub_resource_idx, dst_resource->format->id);
2488 static void wined3d_device_set_render_state(struct wined3d_device *device,
2489 enum wined3d_render_state state, unsigned int value)
2491 if (value == device->cs->c.state->render_states[state])
2493 TRACE("Application is setting the old value over, nothing to do.\n");
2495 else
2497 device->cs->c.state->render_states[state] = value;
2498 wined3d_device_context_emit_set_render_state(&device->cs->c, state, value);
2501 if (state == WINED3D_RS_POINTSIZE && value == WINED3D_RESZ_CODE)
2503 TRACE("RESZ multisampled depth buffer resolve triggered.\n");
2504 resolve_depth_buffer(device);
2508 static void wined3d_device_set_texture_stage_state(struct wined3d_device *device,
2509 unsigned int stage, enum wined3d_texture_stage_state state, uint32_t value)
2511 TRACE("device %p, stage %u, state %s, value %#x.\n",
2512 device, stage, debug_d3dtexturestate(state), value);
2514 if (value == device->cs->c.state->texture_states[stage][state])
2516 TRACE("Application is setting the old value over, nothing to do.\n");
2517 return;
2520 device->cs->c.state->texture_states[stage][state] = value;
2522 wined3d_device_context_emit_set_texture_state(&device->cs->c, stage, state, value);
2525 static void wined3d_device_set_texture(struct wined3d_device *device,
2526 unsigned int stage, struct wined3d_texture *texture)
2528 enum wined3d_shader_type shader_type = WINED3D_SHADER_TYPE_PIXEL;
2529 struct wined3d_shader_resource_view *srv = NULL, *prev;
2530 struct wined3d_state *state = device->cs->c.state;
2532 TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
2534 if (stage >= WINED3D_VERTEX_SAMPLER_OFFSET)
2536 shader_type = WINED3D_SHADER_TYPE_VERTEX;
2537 stage -= WINED3D_VERTEX_SAMPLER_OFFSET;
2540 if (texture && !(srv = wined3d_texture_acquire_identity_srv(texture)))
2541 return;
2543 prev = state->shader_resource_view[shader_type][stage];
2544 TRACE("Previous texture %p.\n", prev);
2546 if (srv == prev)
2548 TRACE("App is setting the same texture again, nothing to do.\n");
2549 return;
2552 state->shader_resource_view[shader_type][stage] = srv;
2554 if (srv)
2555 wined3d_shader_resource_view_incref(srv);
2556 wined3d_device_context_emit_set_texture(&device->cs->c, shader_type, stage, srv);
2557 if (prev)
2558 wined3d_shader_resource_view_decref(prev);
2560 return;
2563 static void wined3d_device_set_material(struct wined3d_device *device, const struct wined3d_material *material)
2565 TRACE("device %p, material %p.\n", device, material);
2567 device->cs->c.state->material = *material;
2568 wined3d_device_context_emit_set_material(&device->cs->c, material);
2571 static void wined3d_device_set_transform(struct wined3d_device *device,
2572 enum wined3d_transform_state state, const struct wined3d_matrix *matrix)
2574 TRACE("device %p, state %s, matrix %p.\n", device, debug_d3dtstype(state), matrix);
2575 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_11, matrix->_12, matrix->_13, matrix->_14);
2576 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_21, matrix->_22, matrix->_23, matrix->_24);
2577 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_31, matrix->_32, matrix->_33, matrix->_34);
2578 TRACE("%.8e %.8e %.8e %.8e\n", matrix->_41, matrix->_42, matrix->_43, matrix->_44);
2580 /* If the new matrix is the same as the current one,
2581 * we cut off any further processing. this seems to be a reasonable
2582 * optimization because as was noticed, some apps (warcraft3 for example)
2583 * tend towards setting the same matrix repeatedly for some reason.
2585 * From here on we assume that the new matrix is different, wherever it matters. */
2586 if (!memcmp(&device->cs->c.state->transforms[state], matrix, sizeof(*matrix)))
2588 TRACE("The application is setting the same matrix over again.\n");
2589 return;
2592 device->cs->c.state->transforms[state] = *matrix;
2593 wined3d_device_context_emit_set_transform(&device->cs->c, state, matrix);
2596 static enum wined3d_texture_address get_texture_address_mode(const struct wined3d_texture *texture,
2597 enum wined3d_texture_address t)
2599 if (t < WINED3D_TADDRESS_WRAP || t > WINED3D_TADDRESS_MIRROR_ONCE)
2601 FIXME("Unrecognized or unsupported texture address mode %#x.\n", t);
2602 return WINED3D_TADDRESS_WRAP;
2605 /* Cubemaps are always set to clamp, regardless of the sampler state. */
2606 if ((texture->resource.usage & WINED3DUSAGE_LEGACY_CUBEMAP)
2607 || ((texture->flags & WINED3D_TEXTURE_COND_NP2) && t == WINED3D_TADDRESS_WRAP))
2608 return WINED3D_TADDRESS_CLAMP;
2610 return t;
2613 static void sampler_desc_from_sampler_states(struct wined3d_sampler_desc *desc,
2614 const uint32_t *sampler_states, const struct wined3d_texture *texture)
2616 const struct wined3d_d3d_info *d3d_info = &texture->resource.device->adapter->d3d_info;
2618 desc->address_u = get_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_U]);
2619 desc->address_v = get_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_V]);
2620 desc->address_w = get_texture_address_mode(texture, sampler_states[WINED3D_SAMP_ADDRESS_W]);
2621 wined3d_color_from_d3dcolor((struct wined3d_color *)desc->border_color,
2622 sampler_states[WINED3D_SAMP_BORDER_COLOR]);
2623 if (sampler_states[WINED3D_SAMP_MAG_FILTER] > WINED3D_TEXF_ANISOTROPIC)
2624 FIXME("Unrecognized or unsupported WINED3D_SAMP_MAG_FILTER %#x.\n",
2625 sampler_states[WINED3D_SAMP_MAG_FILTER]);
2626 desc->mag_filter = min(max(sampler_states[WINED3D_SAMP_MAG_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
2627 if (sampler_states[WINED3D_SAMP_MIN_FILTER] > WINED3D_TEXF_ANISOTROPIC)
2628 FIXME("Unrecognized or unsupported WINED3D_SAMP_MIN_FILTER %#x.\n",
2629 sampler_states[WINED3D_SAMP_MIN_FILTER]);
2630 desc->min_filter = min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
2631 if (sampler_states[WINED3D_SAMP_MIP_FILTER] > WINED3D_TEXF_ANISOTROPIC)
2632 FIXME("Unrecognized or unsupported WINED3D_SAMP_MIP_FILTER %#x.\n",
2633 sampler_states[WINED3D_SAMP_MIP_FILTER]);
2634 desc->mip_filter = min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR);
2635 desc->lod_bias = int_to_float(sampler_states[WINED3D_SAMP_MIPMAP_LOD_BIAS]);
2636 desc->min_lod = -1000.0f;
2637 desc->max_lod = 1000.0f;
2639 /* The LOD is already clamped to texture->level_count in wined3d_stateblock_set_texture_lod(). */
2640 if (texture->flags & WINED3D_TEXTURE_COND_NP2)
2641 desc->mip_base_level = 0;
2642 else if (desc->mip_filter == WINED3D_TEXF_NONE)
2643 desc->mip_base_level = texture->lod;
2644 else
2645 desc->mip_base_level = min(max(sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL], texture->lod), texture->level_count - 1);
2647 desc->max_anisotropy = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY];
2648 if ((sampler_states[WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_ANISOTROPIC
2649 && sampler_states[WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_ANISOTROPIC
2650 && sampler_states[WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_ANISOTROPIC)
2651 || (texture->flags & WINED3D_TEXTURE_COND_NP2))
2652 desc->max_anisotropy = 1;
2653 desc->compare = texture->resource.format_caps & WINED3D_FORMAT_CAP_SHADOW;
2654 desc->comparison_func = WINED3D_CMP_LESSEQUAL;
2656 /* Only use the LSB of the WINED3D_SAMP_SRGB_TEXTURE value. This matches
2657 * the behaviour of the AMD Windows driver.
2659 * Might & Magic: Heroes VI - Shades of Darkness sets
2660 * WINED3D_SAMP_SRGB_TEXTURE to a large value that looks like a
2661 * pointer—presumably by accident—and expects sRGB decoding to be
2662 * disabled. */
2663 desc->srgb_decode = sampler_states[WINED3D_SAMP_SRGB_TEXTURE] & 0x1;
2665 if (!(texture->resource.format_caps & WINED3D_FORMAT_CAP_FILTERING))
2667 desc->mag_filter = WINED3D_TEXF_POINT;
2668 desc->min_filter = WINED3D_TEXF_POINT;
2669 desc->mip_filter = WINED3D_TEXF_NONE;
2672 if (texture->flags & WINED3D_TEXTURE_COND_NP2)
2674 desc->mip_filter = WINED3D_TEXF_NONE;
2675 if (!d3d_info->unconditional_npot)
2676 desc->min_filter = WINED3D_TEXF_POINT;
2680 void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
2681 struct wined3d_stateblock *stateblock)
2683 bool set_blend_state = false, set_depth_stencil_state = false, set_rasterizer_state = false;
2685 const struct wined3d_stateblock_state *state = &stateblock->stateblock_state;
2686 const unsigned int word_bit_count = sizeof(DWORD) * CHAR_BIT;
2687 struct wined3d_saved_states *changed = &stateblock->changed;
2688 struct wined3d_device_context *context = &device->cs->c;
2689 unsigned int i, j, start, idx;
2690 bool set_depth_bounds = false;
2691 struct wined3d_range range;
2692 uint32_t map;
2694 TRACE("device %p, stateblock %p.\n", device, stateblock);
2696 if (changed->vertexShader)
2697 wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_VERTEX, state->vs);
2698 if (changed->pixelShader)
2699 wined3d_device_context_set_shader(context, WINED3D_SHADER_TYPE_PIXEL, state->ps);
2701 for (start = 0; ; start = range.offset + range.size)
2703 if (!wined3d_bitmap_get_range(changed->vs_consts_f, WINED3D_MAX_VS_CONSTS_F, start, &range))
2704 break;
2706 wined3d_device_set_vs_consts_f(device, range.offset, range.size, &state->vs_consts_f[range.offset]);
2709 map = changed->vertexShaderConstantsI;
2710 for (start = 0; ; start = range.offset + range.size)
2712 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
2713 break;
2715 wined3d_device_set_vs_consts_i(device, range.offset, range.size, &state->vs_consts_i[range.offset]);
2718 map = changed->vertexShaderConstantsB;
2719 for (start = 0; ; start = range.offset + range.size)
2721 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
2722 break;
2724 wined3d_device_set_vs_consts_b(device, range.offset, range.size, &state->vs_consts_b[range.offset]);
2727 for (start = 0; ; start = range.offset + range.size)
2729 if (!wined3d_bitmap_get_range(changed->ps_consts_f, WINED3D_MAX_PS_CONSTS_F, start, &range))
2730 break;
2732 wined3d_device_set_ps_consts_f(device, range.offset, range.size, &state->ps_consts_f[range.offset]);
2735 map = changed->pixelShaderConstantsI;
2736 for (start = 0; ; start = range.offset + range.size)
2738 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_I, start, &range))
2739 break;
2741 wined3d_device_set_ps_consts_i(device, range.offset, range.size, &state->ps_consts_i[range.offset]);
2744 map = changed->pixelShaderConstantsB;
2745 for (start = 0; ; start = range.offset + range.size)
2747 if (!wined3d_bitmap_get_range(&map, WINED3D_MAX_CONSTS_B, start, &range))
2748 break;
2750 wined3d_device_set_ps_consts_b(device, range.offset, range.size, &state->ps_consts_b[range.offset]);
2753 for (i = 0; i < ARRAY_SIZE(changed->renderState); ++i)
2755 map = changed->renderState[i];
2756 while (map)
2758 j = wined3d_bit_scan(&map);
2759 idx = i * word_bit_count + j;
2761 switch (idx)
2763 case WINED3D_RS_BLENDFACTOR:
2764 case WINED3D_RS_MULTISAMPLEMASK:
2765 case WINED3D_RS_ALPHABLENDENABLE:
2766 case WINED3D_RS_SRCBLEND:
2767 case WINED3D_RS_DESTBLEND:
2768 case WINED3D_RS_BLENDOP:
2769 case WINED3D_RS_SEPARATEALPHABLENDENABLE:
2770 case WINED3D_RS_SRCBLENDALPHA:
2771 case WINED3D_RS_DESTBLENDALPHA:
2772 case WINED3D_RS_BLENDOPALPHA:
2773 case WINED3D_RS_COLORWRITEENABLE:
2774 case WINED3D_RS_COLORWRITEENABLE1:
2775 case WINED3D_RS_COLORWRITEENABLE2:
2776 case WINED3D_RS_COLORWRITEENABLE3:
2777 set_blend_state = true;
2778 break;
2780 case WINED3D_RS_BACK_STENCILFAIL:
2781 case WINED3D_RS_BACK_STENCILFUNC:
2782 case WINED3D_RS_BACK_STENCILPASS:
2783 case WINED3D_RS_BACK_STENCILZFAIL:
2784 case WINED3D_RS_STENCILENABLE:
2785 case WINED3D_RS_STENCILFAIL:
2786 case WINED3D_RS_STENCILFUNC:
2787 case WINED3D_RS_STENCILREF:
2788 case WINED3D_RS_STENCILMASK:
2789 case WINED3D_RS_STENCILPASS:
2790 case WINED3D_RS_STENCILWRITEMASK:
2791 case WINED3D_RS_STENCILZFAIL:
2792 case WINED3D_RS_TWOSIDEDSTENCILMODE:
2793 case WINED3D_RS_ZENABLE:
2794 case WINED3D_RS_ZFUNC:
2795 case WINED3D_RS_ZWRITEENABLE:
2796 set_depth_stencil_state = true;
2797 break;
2799 case WINED3D_RS_FILLMODE:
2800 case WINED3D_RS_CULLMODE:
2801 case WINED3D_RS_SLOPESCALEDEPTHBIAS:
2802 case WINED3D_RS_DEPTHBIAS:
2803 case WINED3D_RS_SCISSORTESTENABLE:
2804 case WINED3D_RS_ANTIALIASEDLINEENABLE:
2805 set_rasterizer_state = true;
2806 break;
2808 case WINED3D_RS_ADAPTIVETESS_X:
2809 case WINED3D_RS_ADAPTIVETESS_Z:
2810 case WINED3D_RS_ADAPTIVETESS_W:
2811 set_depth_bounds = true;
2812 break;
2814 case WINED3D_RS_AMBIENT:
2815 changed->lights = 1;
2816 break;
2818 case WINED3D_RS_ADAPTIVETESS_Y:
2819 case WINED3D_RS_TEXTUREFACTOR:
2820 break;
2822 case WINED3D_RS_ANTIALIAS:
2823 if (state->rs[WINED3D_RS_ANTIALIAS])
2824 FIXME("Antialias not supported yet.\n");
2825 break;
2827 case WINED3D_RS_TEXTUREPERSPECTIVE:
2828 break;
2830 case WINED3D_RS_WRAPU:
2831 if (state->rs[WINED3D_RS_WRAPU])
2832 FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n");
2833 break;
2835 case WINED3D_RS_WRAPV:
2836 if (state->rs[WINED3D_RS_WRAPV])
2837 FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n");
2838 break;
2840 case WINED3D_RS_MONOENABLE:
2841 if (state->rs[WINED3D_RS_MONOENABLE])
2842 FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n");
2843 break;
2845 case WINED3D_RS_ROP2:
2846 if (state->rs[WINED3D_RS_ROP2])
2847 FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n");
2848 break;
2850 case WINED3D_RS_PLANEMASK:
2851 if (state->rs[WINED3D_RS_PLANEMASK])
2852 FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n");
2853 break;
2855 case WINED3D_RS_LASTPIXEL:
2856 if (!state->rs[WINED3D_RS_LASTPIXEL])
2858 static bool warned;
2859 if (!warned)
2861 FIXME("Last Pixel Drawing Disabled, not handled yet.\n");
2862 warned = true;
2865 break;
2867 case WINED3D_RS_ZVISIBLE:
2868 if (state->rs[WINED3D_RS_ZVISIBLE])
2869 FIXME("WINED3D_RS_ZVISIBLE not implemented.\n");
2870 break;
2872 case WINED3D_RS_SUBPIXEL:
2873 if (state->rs[WINED3D_RS_SUBPIXEL])
2874 FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n");
2875 break;
2877 case WINED3D_RS_SUBPIXELX:
2878 if (state->rs[WINED3D_RS_SUBPIXELX])
2879 FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n");
2880 break;
2882 case WINED3D_RS_STIPPLEDALPHA:
2883 if (state->rs[WINED3D_RS_STIPPLEDALPHA])
2884 FIXME("Stippled Alpha not supported yet.\n");
2885 break;
2887 case WINED3D_RS_STIPPLEENABLE:
2888 if (state->rs[WINED3D_RS_STIPPLEENABLE])
2889 FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n");
2890 break;
2892 case WINED3D_RS_MIPMAPLODBIAS:
2893 if (state->rs[WINED3D_RS_MIPMAPLODBIAS])
2894 FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n");
2895 break;
2897 case WINED3D_RS_ANISOTROPY:
2898 if (state->rs[WINED3D_RS_ANISOTROPY])
2899 FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n");
2900 break;
2902 case WINED3D_RS_FLUSHBATCH:
2903 if (state->rs[WINED3D_RS_FLUSHBATCH])
2904 FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n");
2905 break;
2907 case WINED3D_RS_TRANSLUCENTSORTINDEPENDENT:
2908 if (state->rs[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT])
2909 FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
2910 break;
2912 case WINED3D_RS_WRAP0:
2913 case WINED3D_RS_WRAP1:
2914 case WINED3D_RS_WRAP2:
2915 case WINED3D_RS_WRAP3:
2916 case WINED3D_RS_WRAP4:
2917 case WINED3D_RS_WRAP5:
2918 case WINED3D_RS_WRAP6:
2919 case WINED3D_RS_WRAP7:
2920 case WINED3D_RS_WRAP8:
2921 case WINED3D_RS_WRAP9:
2922 case WINED3D_RS_WRAP10:
2923 case WINED3D_RS_WRAP11:
2924 case WINED3D_RS_WRAP12:
2925 case WINED3D_RS_WRAP13:
2926 case WINED3D_RS_WRAP14:
2927 case WINED3D_RS_WRAP15:
2929 static unsigned int once;
2931 if ((state->rs[idx]) && !once++)
2932 FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n");
2933 break;
2936 case WINED3D_RS_EXTENTS:
2937 if (state->rs[WINED3D_RS_EXTENTS])
2938 FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n");
2939 break;
2941 case WINED3D_RS_COLORKEYBLENDENABLE:
2942 if (state->rs[WINED3D_RS_COLORKEYBLENDENABLE])
2943 FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n");
2944 break;
2946 case WINED3D_RS_SOFTWAREVERTEXPROCESSING:
2948 static unsigned int once;
2950 if ((state->rs[WINED3D_RS_SOFTWAREVERTEXPROCESSING]) && !once++)
2951 FIXME("Software vertex processing not implemented.\n");
2952 break;
2955 case WINED3D_RS_PATCHEDGESTYLE:
2956 if (state->rs[WINED3D_RS_PATCHEDGESTYLE] != WINED3D_PATCH_EDGE_DISCRETE)
2957 FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n",
2958 state->rs[WINED3D_RS_PATCHEDGESTYLE]);
2959 break;
2961 case WINED3D_RS_PATCHSEGMENTS:
2963 union
2965 uint32_t d;
2966 float f;
2967 } tmpvalue;
2968 tmpvalue.f = 1.0f;
2970 if (state->rs[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d)
2972 static bool displayed = false;
2974 tmpvalue.d = state->rs[WINED3D_RS_PATCHSEGMENTS];
2975 if(!displayed)
2976 FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented.\n", tmpvalue.f);
2978 displayed = true;
2980 break;
2983 case WINED3D_RS_DEBUGMONITORTOKEN:
2984 WARN("token: %#x.\n", state->rs[WINED3D_RS_DEBUGMONITORTOKEN]);
2985 break;
2987 case WINED3D_RS_INDEXEDVERTEXBLENDENABLE:
2988 break;
2990 case WINED3D_RS_TWEENFACTOR:
2991 break;
2993 case WINED3D_RS_POSITIONDEGREE:
2994 if (state->rs[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC)
2995 FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n",
2996 state->rs[WINED3D_RS_POSITIONDEGREE]);
2997 break;
2999 case WINED3D_RS_NORMALDEGREE:
3000 if (state->rs[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR)
3001 FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n",
3002 state->rs[WINED3D_RS_NORMALDEGREE]);
3003 break;
3005 case WINED3D_RS_MINTESSELLATIONLEVEL:
3006 break;
3008 case WINED3D_RS_MAXTESSELLATIONLEVEL:
3009 break;
3011 case WINED3D_RS_ENABLEADAPTIVETESSELLATION:
3012 if (state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION])
3013 FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n",
3014 state->rs[WINED3D_RS_ENABLEADAPTIVETESSELLATION]);
3015 break;
3017 default:
3018 wined3d_device_set_render_state(device, idx, state->rs[idx]);
3019 break;
3024 if (set_rasterizer_state)
3026 struct wined3d_rasterizer_state *rasterizer_state;
3027 struct wined3d_rasterizer_state_desc desc;
3028 struct wine_rb_entry *entry;
3029 union
3031 DWORD d;
3032 float f;
3033 } bias;
3035 memset(&desc, 0, sizeof(desc));
3036 desc.fill_mode = state->rs[WINED3D_RS_FILLMODE];
3037 desc.cull_mode = state->rs[WINED3D_RS_CULLMODE];
3038 bias.d = state->rs[WINED3D_RS_DEPTHBIAS];
3039 desc.depth_bias = bias.f;
3040 bias.d = state->rs[WINED3D_RS_SLOPESCALEDEPTHBIAS];
3041 desc.scale_bias = bias.f;
3042 desc.depth_clip = TRUE;
3043 desc.scissor = state->rs[WINED3D_RS_SCISSORTESTENABLE];
3044 desc.line_antialias = state->rs[WINED3D_RS_ANTIALIASEDLINEENABLE];
3046 if ((entry = wine_rb_get(&device->rasterizer_states, &desc)))
3048 rasterizer_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry);
3049 wined3d_device_context_set_rasterizer_state(context, rasterizer_state);
3051 else if (SUCCEEDED(wined3d_rasterizer_state_create(device, &desc, NULL,
3052 &wined3d_null_parent_ops, &rasterizer_state)))
3054 wined3d_device_context_set_rasterizer_state(context, rasterizer_state);
3055 if (wine_rb_put(&device->rasterizer_states, &desc, &rasterizer_state->entry) == -1)
3057 ERR("Failed to insert rasterizer state.\n");
3058 wined3d_rasterizer_state_decref(rasterizer_state);
3063 if (set_blend_state || changed->alpha_to_coverage
3064 || wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_ADAPTIVETESS_Y))
3066 struct wined3d_blend_state *blend_state;
3067 struct wined3d_blend_state_desc desc;
3068 struct wine_rb_entry *entry;
3069 struct wined3d_color colour;
3070 unsigned int sample_mask;
3072 memset(&desc, 0, sizeof(desc));
3073 desc.alpha_to_coverage = state->alpha_to_coverage;
3074 desc.independent = FALSE;
3075 if (state->rs[WINED3D_RS_ADAPTIVETESS_Y] == WINED3DFMT_ATOC)
3076 desc.alpha_to_coverage = TRUE;
3077 desc.rt[0].enable = state->rs[WINED3D_RS_ALPHABLENDENABLE];
3078 desc.rt[0].src = state->rs[WINED3D_RS_SRCBLEND];
3079 desc.rt[0].dst = state->rs[WINED3D_RS_DESTBLEND];
3080 desc.rt[0].op = state->rs[WINED3D_RS_BLENDOP];
3081 if (state->rs[WINED3D_RS_SEPARATEALPHABLENDENABLE])
3083 desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLENDALPHA];
3084 desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLENDALPHA];
3085 desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOPALPHA];
3087 else
3089 desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLEND];
3090 desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLEND];
3091 desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOP];
3093 desc.rt[0].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE];
3094 desc.rt[1].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE1];
3095 desc.rt[2].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE2];
3096 desc.rt[3].writemask = state->rs[WINED3D_RS_COLORWRITEENABLE3];
3097 if (desc.rt[1].writemask != desc.rt[0].writemask
3098 || desc.rt[2].writemask != desc.rt[0].writemask
3099 || desc.rt[3].writemask != desc.rt[0].writemask)
3101 desc.independent = TRUE;
3102 for (i = 1; i < 4; ++i)
3104 desc.rt[i].enable = desc.rt[0].enable;
3105 desc.rt[i].src = desc.rt[0].src;
3106 desc.rt[i].dst = desc.rt[0].dst;
3107 desc.rt[i].op = desc.rt[0].op;
3108 desc.rt[i].src_alpha = desc.rt[0].src_alpha;
3109 desc.rt[i].dst_alpha = desc.rt[0].dst_alpha;
3110 desc.rt[i].op_alpha = desc.rt[0].op_alpha;
3114 if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_BLENDFACTOR))
3115 wined3d_color_from_d3dcolor(&colour, state->rs[WINED3D_RS_BLENDFACTOR]);
3116 else
3117 wined3d_device_context_get_blend_state(context, &colour, &sample_mask);
3119 if ((entry = wine_rb_get(&device->blend_states, &desc)))
3121 blend_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_blend_state, entry);
3122 wined3d_device_context_set_blend_state(context, blend_state, &colour,
3123 state->rs[WINED3D_RS_MULTISAMPLEMASK]);
3125 else if (SUCCEEDED(wined3d_blend_state_create(device, &desc, NULL,
3126 &wined3d_null_parent_ops, &blend_state)))
3128 wined3d_device_context_set_blend_state(context, blend_state, &colour,
3129 state->rs[WINED3D_RS_MULTISAMPLEMASK]);
3130 if (wine_rb_put(&device->blend_states, &desc, &blend_state->entry) == -1)
3132 ERR("Failed to insert blend state.\n");
3133 wined3d_blend_state_decref(blend_state);
3138 if (set_depth_stencil_state)
3140 struct wined3d_depth_stencil_state *depth_stencil_state;
3141 struct wined3d_depth_stencil_state_desc desc;
3142 struct wine_rb_entry *entry;
3143 unsigned int stencil_ref;
3145 memset(&desc, 0, sizeof(desc));
3146 switch (state->rs[WINED3D_RS_ZENABLE])
3148 case WINED3D_ZB_FALSE:
3149 desc.depth = FALSE;
3150 break;
3152 case WINED3D_ZB_USEW:
3153 FIXME("W buffer is not well handled.\n");
3154 case WINED3D_ZB_TRUE:
3155 desc.depth = TRUE;
3156 break;
3158 default:
3159 FIXME("Unrecognized depth buffer type %#x.\n", state->rs[WINED3D_RS_ZENABLE]);
3161 desc.depth_write = state->rs[WINED3D_RS_ZWRITEENABLE];
3162 desc.depth_func = state->rs[WINED3D_RS_ZFUNC];
3163 desc.stencil = state->rs[WINED3D_RS_STENCILENABLE];
3164 desc.stencil_read_mask = state->rs[WINED3D_RS_STENCILMASK];
3165 desc.stencil_write_mask = state->rs[WINED3D_RS_STENCILWRITEMASK];
3166 desc.front.fail_op = state->rs[WINED3D_RS_STENCILFAIL];
3167 desc.front.depth_fail_op = state->rs[WINED3D_RS_STENCILZFAIL];
3168 desc.front.pass_op = state->rs[WINED3D_RS_STENCILPASS];
3169 desc.front.func = state->rs[WINED3D_RS_STENCILFUNC];
3171 if (state->rs[WINED3D_RS_TWOSIDEDSTENCILMODE])
3173 desc.back.fail_op = state->rs[WINED3D_RS_BACK_STENCILFAIL];
3174 desc.back.depth_fail_op = state->rs[WINED3D_RS_BACK_STENCILZFAIL];
3175 desc.back.pass_op = state->rs[WINED3D_RS_BACK_STENCILPASS];
3176 desc.back.func = state->rs[WINED3D_RS_BACK_STENCILFUNC];
3178 else
3180 desc.back = desc.front;
3183 if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_STENCILREF))
3184 stencil_ref = state->rs[WINED3D_RS_STENCILREF];
3185 else
3186 wined3d_device_context_get_depth_stencil_state(context, &stencil_ref);
3188 if ((entry = wine_rb_get(&device->depth_stencil_states, &desc)))
3190 depth_stencil_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_depth_stencil_state, entry);
3191 wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref);
3193 else if (SUCCEEDED(wined3d_depth_stencil_state_create(device, &desc, NULL,
3194 &wined3d_null_parent_ops, &depth_stencil_state)))
3196 wined3d_device_context_set_depth_stencil_state(context, depth_stencil_state, stencil_ref);
3197 if (wine_rb_put(&device->depth_stencil_states, &desc, &depth_stencil_state->entry) == -1)
3199 ERR("Failed to insert depth/stencil state.\n");
3200 wined3d_depth_stencil_state_decref(depth_stencil_state);
3205 if (set_depth_bounds)
3207 wined3d_device_context_set_depth_bounds(context,
3208 state->rs[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB,
3209 int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_Z]),
3210 int_to_float(state->rs[WINED3D_RS_ADAPTIVETESS_W]));
3213 for (i = 0; i < ARRAY_SIZE(changed->textureState); ++i)
3215 map = changed->textureState[i];
3216 while (map)
3218 j = wined3d_bit_scan(&map);
3220 switch (j)
3222 case WINED3D_TSS_CONSTANT:
3223 break;
3225 default:
3226 wined3d_device_set_texture_stage_state(device, i, j, state->texture_states[i][j]);
3231 for (i = 0; i < ARRAY_SIZE(changed->samplerState); ++i)
3233 enum wined3d_shader_type shader_type = WINED3D_SHADER_TYPE_PIXEL;
3234 struct wined3d_sampler_desc desc;
3235 struct wined3d_texture *texture;
3236 struct wined3d_sampler *sampler;
3237 unsigned int bind_index = i;
3238 struct wine_rb_entry *entry;
3240 if (!changed->samplerState[i] && !(changed->textures & (1u << i)))
3241 continue;
3243 if (!(texture = state->textures[i]))
3244 continue;
3246 memset(&desc, 0, sizeof(desc));
3247 sampler_desc_from_sampler_states(&desc, state->sampler_states[i], texture);
3249 if (i >= WINED3D_VERTEX_SAMPLER_OFFSET)
3251 shader_type = WINED3D_SHADER_TYPE_VERTEX;
3252 bind_index -= WINED3D_VERTEX_SAMPLER_OFFSET;
3255 if ((entry = wine_rb_get(&device->samplers, &desc)))
3257 sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
3259 wined3d_device_context_set_samplers(context, shader_type, bind_index, 1, &sampler);
3261 else if (SUCCEEDED(wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &sampler)))
3263 wined3d_device_context_set_samplers(context, shader_type, bind_index, 1, &sampler);
3265 if (wine_rb_put(&device->samplers, &desc, &sampler->entry) == -1)
3267 ERR("Failed to insert sampler.\n");
3268 wined3d_sampler_decref(sampler);
3273 if (changed->transforms)
3275 for (i = 0; i < ARRAY_SIZE(changed->transform); ++i)
3277 map = changed->transform[i];
3278 while (map)
3280 j = wined3d_bit_scan(&map);
3281 idx = i * word_bit_count + j;
3282 wined3d_device_set_transform(device, idx, &state->transforms[idx]);
3287 if (changed->indices)
3288 wined3d_device_context_set_index_buffer(context, state->index_buffer, state->index_format, 0);
3289 wined3d_device_set_base_vertex_index(device, state->base_vertex_index);
3290 if (changed->vertexDecl)
3291 wined3d_device_context_set_vertex_declaration(context, state->vertex_declaration);
3292 if (changed->material)
3293 wined3d_device_set_material(device, &state->material);
3294 if (changed->viewport)
3295 wined3d_device_context_set_viewports(context, 1, &state->viewport);
3296 if (changed->scissorRect)
3297 wined3d_device_context_set_scissor_rects(context, 1, &state->scissor_rect);
3299 map = changed->streamSource | changed->streamFreq;
3300 while (map)
3302 i = wined3d_bit_scan(&map);
3303 wined3d_device_context_set_stream_sources(context, i, 1, &state->streams[i]);
3306 map = changed->textures;
3307 while (map)
3309 struct wined3d_color float_key[2];
3310 struct wined3d_texture *texture;
3312 i = wined3d_bit_scan(&map);
3313 texture = state->textures[i];
3314 wined3d_device_set_texture(device, i, texture);
3316 if (!i && texture)
3318 wined3d_format_get_float_color_key(texture->resource.format, &texture->src_blt_color_key, float_key);
3319 wined3d_device_context_push_constants(context,
3320 WINED3D_PUSH_CONSTANTS_PS_FFP, WINED3D_SHADER_CONST_FFP_COLOR_KEY,
3321 offsetof(struct wined3d_ffp_ps_constants, color_key), sizeof(float_key), float_key);
3325 map = changed->clipplane;
3326 while (map)
3328 i = wined3d_bit_scan(&map);
3329 wined3d_device_set_clip_plane(device, i, &state->clip_planes[i]);
3332 if (changed->lights)
3334 struct wined3d_ffp_light_constants constants;
3335 struct wined3d_light_info *light, *cursor;
3337 LIST_FOR_EACH_ENTRY_SAFE(light, cursor, &changed->changed_lights, struct wined3d_light_info, changed_entry)
3339 wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms);
3340 wined3d_device_set_light_enable(device, light->OriginalIndex, light->glIndex != -1);
3341 list_remove(&light->changed_entry);
3342 light->changed = false;
3345 wined3d_color_from_d3dcolor(&constants.ambient, state->rs[WINED3D_RS_AMBIENT]);
3346 wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_VS_FFP, WINED3D_SHADER_CONST_FFP_LIGHTS,
3347 offsetof(struct wined3d_ffp_vs_constants, light), sizeof(constants), &constants);
3350 if (changed->ffp_ps_constants)
3352 static const struct wined3d_color specular_enabled = {1.0f, 1.0f, 1.0f, 0.0f};
3353 static const struct wined3d_color specular_disabled;
3354 struct wined3d_ffp_ps_constants constants;
3356 for (i = 0; i < WINED3D_MAX_FFP_TEXTURES; ++i)
3357 wined3d_color_from_d3dcolor(&constants.texture_constants[i], state->texture_states[i][WINED3D_TSS_CONSTANT]);
3359 wined3d_color_from_d3dcolor(&constants.texture_factor, state->rs[WINED3D_RS_TEXTUREFACTOR]);
3361 constants.specular_enable = state->rs[WINED3D_RS_SPECULARENABLE] ? specular_enabled : specular_disabled;
3363 wined3d_device_context_push_constants(context, WINED3D_PUSH_CONSTANTS_PS_FFP,
3364 WINED3D_SHADER_CONST_FFP_PS, 0, offsetof(struct wined3d_ffp_ps_constants, color_key), &constants);
3367 assert(list_empty(&stateblock->changed.changed_lights));
3368 memset(&stateblock->changed, 0, sizeof(stateblock->changed));
3369 list_init(&stateblock->changed.changed_lights);
3371 TRACE("Applied stateblock %p.\n", stateblock);
3374 unsigned int CDECL wined3d_stateblock_set_texture_lod(struct wined3d_stateblock *stateblock,
3375 struct wined3d_texture *texture, unsigned int lod)
3377 unsigned int old;
3379 TRACE("texture %p, lod %u.\n", texture, lod);
3381 old = wined3d_texture_set_lod(texture, lod);
3383 if (old != lod)
3385 for (unsigned int i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
3387 /* Mark the texture as changed. The next time the appplication
3388 * draws from this texture, wined3d_device_apply_stateblock() will
3389 * recompute the texture LOD.
3391 * We only need to do this for the primary stateblock.
3392 * If a recording stateblock uses a texture whose LOD is changed,
3393 * that texture will be invalidated on the primary stateblock
3394 * anyway when the recording stateblock is applied. */
3395 if (stateblock->stateblock_state.textures[i] == texture)
3396 stateblock->changed.textures |= (1u << i);
3400 return old;
3403 void CDECL wined3d_stateblock_texture_changed(struct wined3d_stateblock *stateblock,
3404 const struct wined3d_texture *texture)
3406 for (unsigned int i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i)
3408 if (stateblock->stateblock_state.textures[i] == texture)
3409 stateblock->changed.textures |= (1u << i);