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 */
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;
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;
68 unsigned int stage
, state
;
71 struct wined3d_stateblock
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
,
96 WINED3D_RS_ALPHATESTENABLE
,
97 WINED3D_RS_ANTIALIASEDLINEENABLE
,
98 WINED3D_RS_BLENDFACTOR
,
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
,
113 WINED3D_RS_FOGDENSITY
,
116 WINED3D_RS_LASTPIXEL
,
117 WINED3D_RS_SCISSORTESTENABLE
,
118 WINED3D_RS_SEPARATEALPHABLENDENABLE
,
119 WINED3D_RS_SHADEMODE
,
120 WINED3D_RS_SLOPESCALEDEPTHBIAS
,
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
,
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
,
199 WINED3D_RS_AMBIENTMATERIALSOURCE
,
201 WINED3D_RS_CLIPPLANEENABLE
,
202 WINED3D_RS_COLORVERTEX
,
204 WINED3D_RS_DIFFUSEMATERIALSOURCE
,
205 WINED3D_RS_EMISSIVEMATERIALSOURCE
,
206 WINED3D_RS_ENABLEADAPTIVETESSELLATION
,
208 WINED3D_RS_FOGDENSITY
,
209 WINED3D_RS_FOGENABLE
,
212 WINED3D_RS_FOGTABLEMODE
,
213 WINED3D_RS_FOGVERTEXMODE
,
214 WINED3D_RS_INDEXEDVERTEXBLENDENABLE
,
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
)
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;
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;
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;
324 states
->vertexDecl
= 1;
325 states
->vertexShader
= 1;
326 states
->alpha_to_coverage
= 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
)
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
);
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
;
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
;
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
))
575 wined3d_shader_decref(shader
);
578 if ((shader
= state
->ps
))
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
)
596 list_remove(&light
->changed_entry
);
597 rb_remove(&state
->light_state
->lights_tree
, &light
->entry
);
602 void state_cleanup(struct wined3d_state
*state
)
604 struct wined3d_light_info
*light
, *cursor
;
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
)
618 list_remove(&light
->changed_entry
);
619 rb_remove(&state
->light_state
.lights_tree
, &light
->entry
);
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
);
632 wined3d_mutex_lock();
633 wined3d_stateblock_state_cleanup(&stateblock
->stateblock_state
);
635 wined3d_mutex_unlock();
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
)))
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(¶ms
->diffuse
),
687 debug_color(¶ms
->specular
), debug_color(¶ms
->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
:
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
;
703 case WINED3D_LIGHT_DIRECTIONAL
:
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
;
711 case WINED3D_LIGHT_SPOT
:
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
;
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
;
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
;
735 FIXME("Unrecognized params type %#x.\n", params
->type
);
738 *light_info
= object
;
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");
755 state
->lights
[light_info
->glIndex
] = NULL
;
756 light_info
->glIndex
= -1;
760 if (light_info
->glIndex
!= -1)
762 TRACE("Light already enabled, nothing to do.\n");
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
])
773 state
->lights
[i
] = light_info
;
774 light_info
->glIndex
= i
;
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");
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
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)
811 dst_state
->lights
[src
->glIndex
] = dst
;
813 dst
->glIndex
= src
->glIndex
;
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
;
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
;
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
);
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
))
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
))
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
))
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
))
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
))
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
))
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
;
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
;
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
;
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
];
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
];
1050 map
= stateblock
->changed
.textures
;
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
)
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
;
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
))
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
))
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
))
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
))
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
))
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
))
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
;
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
;
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
;
1244 i
= wined3d_bit_scan(&map
);
1245 wined3d_stateblock_set_texture(device_state
, i
, state
->textures
[i
]);
1248 map
= stateblock
->changed
.clipplane
;
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
);
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
)
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
;
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
);
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
)
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
);
1334 HRESULT CDECL
wined3d_stateblock_set_vs_consts_b(struct wined3d_stateblock
*stateblock
,
1335 unsigned int start_idx
, unsigned int count
, const BOOL
*constants
)
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
);
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
));
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
));
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
));
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
);
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
);
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
)
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
);
1446 HRESULT CDECL
wined3d_stateblock_set_ps_consts_b(struct wined3d_stateblock
*stateblock
,
1447 unsigned int start_idx
, unsigned int count
, const BOOL
*constants
)
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
);
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
));
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
));
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
));
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
);
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
);
1532 stateblock
->stateblock_state
.rs
[state
] = value
;
1533 stateblock
->changed
.renderState
[state
>> 5] |= 1u << (state
& 0x1f);
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
);
1545 case WINED3D_RS_SPECULARENABLE
:
1546 case WINED3D_RS_TEXTUREFACTOR
:
1547 stateblock
->changed
.ffp_ps_constants
= 1;
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
);
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
);
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);
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
);
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
;
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
));
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
];
1726 wined3d_buffer_incref(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
;
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
;
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
;
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
;
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. */
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
;
1793 case WINED3D_LIGHT_DIRECTIONAL
:
1794 case WINED3D_LIGHT_PARALLELPOINT
:
1795 /* Ignores attenuation */
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
);
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
;
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
)))
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
);
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;
1849 static void init_default_render_states(unsigned int rs
[WINEHIGHEST_RENDER_STATE
+ 1], const struct wined3d_d3d_info
*d3d_info
)
1853 struct wined3d_line_pattern lp
;
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
;
1885 rs
[WINED3D_RS_FOGSTART
] = tmpfloat
.d
;
1887 rs
[WINED3D_RS_FOGEND
] = tmpfloat
.d
;
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
;
1923 rs
[WINED3D_RS_POINTSIZE
] = tmpfloat
.d
;
1925 rs
[WINED3D_RS_POINTSIZE_MIN
] = tmpfloat
.d
;
1926 rs
[WINED3D_RS_POINTSPRITEENABLE
] = FALSE
;
1927 rs
[WINED3D_RS_POINTSCALEENABLE
] = FALSE
;
1929 rs
[WINED3D_RS_POINTSCALE_A
] = tmpfloat
.d
;
1931 rs
[WINED3D_RS_POINTSCALE_B
] = tmpfloat
.d
;
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
;
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;
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;
1953 rs
[WINED3D_RS_MINTESSELLATIONLEVEL
] = tmpfloat
.d
;
1954 rs
[WINED3D_RS_MAXTESSELLATIONLEVEL
] = tmpfloat
.d
;
1955 rs
[WINED3D_RS_ANTIALIASEDLINEENABLE
] = FALSE
;
1957 rs
[WINED3D_RS_ADAPTIVETESS_X
] = tmpfloat
.d
;
1958 rs
[WINED3D_RS_ADAPTIVETESS_Y
] = tmpfloat
.d
;
1960 rs
[WINED3D_RS_ADAPTIVETESS_Z
] = tmpfloat
.d
;
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])
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
;
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
;
2108 for (i
= 0; i
< level_count
; ++i
)
2110 if (levels
[i
] && d3d_info
->feature_level
>= levels
[i
])
2112 *selected_level
= levels
[i
];
2117 FIXME_(winediag
)("None of the requested D3D feature levels is supported on this GPU "
2118 "with the current shader backend.\n");
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
))
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
);
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
);
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
;
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
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
)
2225 TRACE("Updating changed flags appropriate for type %#x.\n", 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
);
2235 case WINED3D_SBT_PIXEL_STATE
:
2236 stateblock_savedstates_set_pixel(&stateblock
->changed
,
2237 d3d_info
->limits
.ps_uniform_count
);
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
);
2247 FIXME("Unrecognized state block type %#x.\n", type
);
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;
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
;
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
);
2278 WARN("Failed to initialize stateblock, hr %#lx.\n", hr
);
2283 TRACE("Created stateblock %p.\n", object
);
2284 *stateblock
= object
;
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
)
2312 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
)
2329 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
)
2346 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
)
2363 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
)
2380 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
)
2397 TRACE("device %p, start_idx %u, count %u, constants %p.\n", device
, start_idx
, count
, constants
);
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
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
)))
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");
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");
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)))
2478 dst_resource
= &dst_texture
->resource
;
2479 if (!dst_resource
->format
->depth_size
)
2481 if (!(src_view
= state
->fb
.depth_stencil
))
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");
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");
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
)))
2543 prev
= state
->shader_resource_view
[shader_type
][stage
];
2544 TRACE("Previous texture %p.\n", prev
);
2548 TRACE("App is setting the same texture again, nothing to do.\n");
2552 state
->shader_resource_view
[shader_type
][stage
] = srv
;
2555 wined3d_shader_resource_view_incref(srv
);
2556 wined3d_device_context_emit_set_texture(&device
->cs
->c
, shader_type
, stage
, srv
);
2558 wined3d_shader_resource_view_decref(prev
);
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");
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
;
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
;
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
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
;
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
))
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
))
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
))
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
))
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
))
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
))
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
];
2758 j
= wined3d_bit_scan(&map
);
2759 idx
= i
* word_bit_count
+ j
;
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;
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;
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;
2808 case WINED3D_RS_ADAPTIVETESS_X
:
2809 case WINED3D_RS_ADAPTIVETESS_Z
:
2810 case WINED3D_RS_ADAPTIVETESS_W
:
2811 set_depth_bounds
= true;
2814 case WINED3D_RS_AMBIENT
:
2815 changed
->lights
= 1;
2818 case WINED3D_RS_ADAPTIVETESS_Y
:
2819 case WINED3D_RS_TEXTUREFACTOR
:
2822 case WINED3D_RS_ANTIALIAS
:
2823 if (state
->rs
[WINED3D_RS_ANTIALIAS
])
2824 FIXME("Antialias not supported yet.\n");
2827 case WINED3D_RS_TEXTUREPERSPECTIVE
:
2830 case WINED3D_RS_WRAPU
:
2831 if (state
->rs
[WINED3D_RS_WRAPU
])
2832 FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n");
2835 case WINED3D_RS_WRAPV
:
2836 if (state
->rs
[WINED3D_RS_WRAPV
])
2837 FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n");
2840 case WINED3D_RS_MONOENABLE
:
2841 if (state
->rs
[WINED3D_RS_MONOENABLE
])
2842 FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n");
2845 case WINED3D_RS_ROP2
:
2846 if (state
->rs
[WINED3D_RS_ROP2
])
2847 FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n");
2850 case WINED3D_RS_PLANEMASK
:
2851 if (state
->rs
[WINED3D_RS_PLANEMASK
])
2852 FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n");
2855 case WINED3D_RS_LASTPIXEL
:
2856 if (!state
->rs
[WINED3D_RS_LASTPIXEL
])
2861 FIXME("Last Pixel Drawing Disabled, not handled yet.\n");
2867 case WINED3D_RS_ZVISIBLE
:
2868 if (state
->rs
[WINED3D_RS_ZVISIBLE
])
2869 FIXME("WINED3D_RS_ZVISIBLE not implemented.\n");
2872 case WINED3D_RS_SUBPIXEL
:
2873 if (state
->rs
[WINED3D_RS_SUBPIXEL
])
2874 FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n");
2877 case WINED3D_RS_SUBPIXELX
:
2878 if (state
->rs
[WINED3D_RS_SUBPIXELX
])
2879 FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n");
2882 case WINED3D_RS_STIPPLEDALPHA
:
2883 if (state
->rs
[WINED3D_RS_STIPPLEDALPHA
])
2884 FIXME("Stippled Alpha not supported yet.\n");
2887 case WINED3D_RS_STIPPLEENABLE
:
2888 if (state
->rs
[WINED3D_RS_STIPPLEENABLE
])
2889 FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n");
2892 case WINED3D_RS_MIPMAPLODBIAS
:
2893 if (state
->rs
[WINED3D_RS_MIPMAPLODBIAS
])
2894 FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n");
2897 case WINED3D_RS_ANISOTROPY
:
2898 if (state
->rs
[WINED3D_RS_ANISOTROPY
])
2899 FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n");
2902 case WINED3D_RS_FLUSHBATCH
:
2903 if (state
->rs
[WINED3D_RS_FLUSHBATCH
])
2904 FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n");
2907 case WINED3D_RS_TRANSLUCENTSORTINDEPENDENT
:
2908 if (state
->rs
[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT
])
2909 FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
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");
2936 case WINED3D_RS_EXTENTS
:
2937 if (state
->rs
[WINED3D_RS_EXTENTS
])
2938 FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n");
2941 case WINED3D_RS_COLORKEYBLENDENABLE
:
2942 if (state
->rs
[WINED3D_RS_COLORKEYBLENDENABLE
])
2943 FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n");
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");
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
]);
2961 case WINED3D_RS_PATCHSEGMENTS
:
2970 if (state
->rs
[WINED3D_RS_PATCHSEGMENTS
] != tmpvalue
.d
)
2972 static bool displayed
= false;
2974 tmpvalue
.d
= state
->rs
[WINED3D_RS_PATCHSEGMENTS
];
2976 FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented.\n", tmpvalue
.f
);
2983 case WINED3D_RS_DEBUGMONITORTOKEN
:
2984 WARN("token: %#x.\n", state
->rs
[WINED3D_RS_DEBUGMONITORTOKEN
]);
2987 case WINED3D_RS_INDEXEDVERTEXBLENDENABLE
:
2990 case WINED3D_RS_TWEENFACTOR
:
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
]);
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
]);
3005 case WINED3D_RS_MINTESSELLATIONLEVEL
:
3008 case WINED3D_RS_MAXTESSELLATIONLEVEL
:
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
]);
3018 wined3d_device_set_render_state(device
, idx
, state
->rs
[idx
]);
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
;
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
];
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
]);
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
:
3152 case WINED3D_ZB_USEW
:
3153 FIXME("W buffer is not well handled.\n");
3154 case WINED3D_ZB_TRUE
:
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
];
3180 desc
.back
= desc
.front
;
3183 if (wined3d_bitmap_is_set(changed
->renderState
, WINED3D_RS_STENCILREF
))
3184 stencil_ref
= state
->rs
[WINED3D_RS_STENCILREF
];
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
];
3218 j
= wined3d_bit_scan(&map
);
3222 case WINED3D_TSS_CONSTANT
:
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
)))
3243 if (!(texture
= state
->textures
[i
]))
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
];
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
;
3302 i
= wined3d_bit_scan(&map
);
3303 wined3d_device_context_set_stream_sources(context
, i
, 1, &state
->streams
[i
]);
3306 map
= changed
->textures
;
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
);
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
;
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
)
3379 TRACE("texture %p, lod %u.\n", texture
, lod
);
3381 old
= wined3d_texture_set_lod(texture
, 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
);
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
);