2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23 #include "stateblock9.h"
25 #include "basetexture9.h"
26 #include "nine_helpers.h"
27 #include "vertexdeclaration9.h"
29 #define DBG_CHANNEL DBG_STATEBLOCK
31 /* XXX TODO: handling of lights is broken */
33 #define VS_CONST_I_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_I_SWVP * sizeof(int[4])) : (NINE_MAX_CONST_I * sizeof(int[4])))
34 #define VS_CONST_B_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_B_SWVP * sizeof(BOOL)) : (NINE_MAX_CONST_B * sizeof(BOOL)))
35 #define VS_CONST_F_SWVP_SIZE (NINE_MAX_CONST_F_SWVP * sizeof(float[4]))
38 NineStateBlock9_ctor( struct NineStateBlock9
*This
,
39 struct NineUnknownParams
*pParams
,
40 enum nine_stateblock_type type
)
42 HRESULT hr
= NineUnknown_ctor(&This
->base
, pParams
);
44 DBG("This=%p pParams=%p type=%d\n", This
, pParams
, type
);
51 This
->state
.vs_const_f
= MALLOC(This
->base
.device
->vs_const_size
);
52 This
->state
.ps_const_f
= MALLOC(This
->base
.device
->ps_const_size
);
53 This
->state
.vs_const_i
= MALLOC(VS_CONST_I_SIZE(This
->base
.device
));
54 This
->state
.vs_const_b
= MALLOC(VS_CONST_B_SIZE(This
->base
.device
));
55 if (!This
->state
.vs_const_f
|| !This
->state
.ps_const_f
||
56 !This
->state
.vs_const_i
|| !This
->state
.vs_const_b
)
59 if (This
->base
.device
->may_swvp
) {
60 This
->state
.vs_const_f_swvp
= MALLOC(VS_CONST_F_SWVP_SIZE
);
61 if (!This
->state
.vs_const_f_swvp
)
64 This
->state
.vs_const_f_swvp
= NULL
;
70 NineStateBlock9_dtor( struct NineStateBlock9
*This
)
72 struct nine_state
*state
= &This
->state
;
74 struct nine_range_pool
*pool
= &This
->base
.device
->range_pool
;
76 nine_state_clear(state
, false);
78 FREE(state
->vs_const_f
);
79 FREE(state
->ps_const_f
);
80 FREE(state
->vs_const_i
);
81 FREE(state
->vs_const_b
);
82 FREE(state
->vs_const_f_swvp
);
84 FREE(state
->ff
.light
);
86 FREE(state
->ff
.transform
);
88 if (This
->state
.changed
.ps_const_f
) {
89 for (r
= This
->state
.changed
.ps_const_f
; r
->next
; r
= r
->next
);
90 nine_range_pool_put_chain(pool
, This
->state
.changed
.ps_const_f
, r
);
92 if (This
->state
.changed
.vs_const_f
) {
93 for (r
= This
->state
.changed
.vs_const_f
; r
->next
; r
= r
->next
);
94 nine_range_pool_put_chain(pool
, This
->state
.changed
.vs_const_f
, r
);
96 if (This
->state
.changed
.vs_const_i
) {
97 for (r
= This
->state
.changed
.vs_const_i
; r
->next
; r
= r
->next
);
98 nine_range_pool_put_chain(pool
, This
->state
.changed
.vs_const_i
, r
);
100 if (This
->state
.changed
.vs_const_b
) {
101 for (r
= This
->state
.changed
.vs_const_b
; r
->next
; r
= r
->next
);
102 nine_range_pool_put_chain(pool
, This
->state
.changed
.vs_const_b
, r
);
105 NineUnknown_dtor(&This
->base
);
108 /* Copy state marked changed in @mask from @src to @dst.
109 * If @apply is false, updating dst->changed can be omitted.
113 nine_state_copy_common(struct NineDevice9
*device
,
114 struct nine_state
*dst
,
115 struct nine_state
*src
,
116 struct nine_state
*mask
, /* aliases either src or dst */
118 struct nine_range_pool
*pool
)
122 DBG("apply:%d changed.group: %x\n", (int)apply
, (int)mask
->changed
.group
);
124 dst
->changed
.group
|= mask
->changed
.group
;
126 if (mask
->changed
.group
& NINE_STATE_VIEWPORT
)
127 dst
->viewport
= src
->viewport
;
128 if (mask
->changed
.group
& NINE_STATE_SCISSOR
)
129 dst
->scissor
= src
->scissor
;
131 if (mask
->changed
.group
& NINE_STATE_VS
)
132 nine_bind(&dst
->vs
, src
->vs
);
133 if (mask
->changed
.group
& NINE_STATE_PS
)
134 nine_bind(&dst
->ps
, src
->ps
);
138 * Various possibilities for optimization here, like creating a per-SB
139 * constant buffer, or memcmp'ing for changes.
140 * Will do that later depending on what works best for specific apps.
142 if (mask
->changed
.group
& NINE_STATE_VS_CONST
) {
143 struct nine_range
*r
;
144 if (device
->may_swvp
) {
145 for (r
= mask
->changed
.vs_const_f
; r
; r
= r
->next
) {
148 memcpy(&dst
->vs_const_f_swvp
[bgn
* 4],
149 &src
->vs_const_f_swvp
[bgn
* 4],
150 (end
- bgn
) * 4 * sizeof(float));
152 nine_ranges_insert(&dst
->changed
.vs_const_f
, bgn
, end
,
154 if (bgn
< device
->max_vs_const_f
) {
155 end
= MIN2(end
, device
->max_vs_const_f
);
156 memcpy(&dst
->vs_const_f
[bgn
* 4],
157 &src
->vs_const_f
[bgn
* 4],
158 (end
- bgn
) * 4 * sizeof(float));
162 for (r
= mask
->changed
.vs_const_f
; r
; r
= r
->next
) {
163 memcpy(&dst
->vs_const_f
[r
->bgn
* 4],
164 &src
->vs_const_f
[r
->bgn
* 4],
165 (r
->end
- r
->bgn
) * 4 * sizeof(float));
167 nine_ranges_insert(&dst
->changed
.vs_const_f
, r
->bgn
, r
->end
,
171 for (r
= mask
->changed
.vs_const_i
; r
; r
= r
->next
) {
172 memcpy(&dst
->vs_const_i
[r
->bgn
* 4],
173 &src
->vs_const_i
[r
->bgn
* 4],
174 (r
->end
- r
->bgn
) * 4 * sizeof(int));
176 nine_ranges_insert(&dst
->changed
.vs_const_i
, r
->bgn
, r
->end
,
179 for (r
= mask
->changed
.vs_const_b
; r
; r
= r
->next
) {
180 memcpy(&dst
->vs_const_b
[r
->bgn
],
181 &src
->vs_const_b
[r
->bgn
],
182 (r
->end
- r
->bgn
) * sizeof(int));
184 nine_ranges_insert(&dst
->changed
.vs_const_b
, r
->bgn
, r
->end
,
189 /* Pixel constants. */
190 if (mask
->changed
.group
& NINE_STATE_PS_CONST
) {
191 struct nine_range
*r
;
192 for (r
= mask
->changed
.ps_const_f
; r
; r
= r
->next
) {
193 memcpy(&dst
->ps_const_f
[r
->bgn
* 4],
194 &src
->ps_const_f
[r
->bgn
* 4],
195 (r
->end
- r
->bgn
) * 4 * sizeof(float));
197 nine_ranges_insert(&dst
->changed
.ps_const_f
, r
->bgn
, r
->end
,
200 if (mask
->changed
.ps_const_i
) {
201 uint16_t m
= mask
->changed
.ps_const_i
;
202 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
204 memcpy(dst
->ps_const_i
[i
], src
->ps_const_i
[i
], 4 * sizeof(int));
206 dst
->changed
.ps_const_i
|= mask
->changed
.ps_const_i
;
208 if (mask
->changed
.ps_const_b
) {
209 uint16_t m
= mask
->changed
.ps_const_b
;
210 for (i
= ffs(m
) - 1, m
>>= i
; m
; ++i
, m
>>= 1)
212 dst
->ps_const_b
[i
] = src
->ps_const_b
[i
];
214 dst
->changed
.ps_const_b
|= mask
->changed
.ps_const_b
;
219 * TODO: Maybe build a list ?
221 for (i
= 0; i
< ARRAY_SIZE(dst
->changed
.rs
); ++i
) {
222 uint32_t m
= mask
->changed
.rs
[i
];
224 dst
->changed
.rs
[i
] |= m
;
226 const int r
= ffs(m
) - 1;
228 DBG("State %d %s = %d\n", i
* 32 + r
, nine_d3drs_to_string(i
* 32 + r
), (int)src
->rs_advertised
[i
* 32 + r
]);
229 dst
->rs_advertised
[i
* 32 + r
] = src
->rs_advertised
[i
* 32 + r
];
235 if (mask
->changed
.ucp
) {
236 DBG("ucp: %x\n", mask
->changed
.ucp
);
237 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
238 if (mask
->changed
.ucp
& (1 << i
))
239 memcpy(dst
->clip
.ucp
[i
],
240 src
->clip
.ucp
[i
], sizeof(src
->clip
.ucp
[0]));
242 dst
->changed
.ucp
|= mask
->changed
.ucp
;
246 if (mask
->changed
.group
& NINE_STATE_SAMPLER
) {
247 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
248 if (mask
->changed
.sampler
[s
] == 0x3ffe) {
249 memcpy(&dst
->samp
[s
], &src
->samp
[s
], sizeof(dst
->samp
[s
]));
250 memcpy(&dst
->samp_advertised
[s
], &src
->samp_advertised
[s
], sizeof(dst
->samp_advertised
[s
]));
252 uint32_t m
= mask
->changed
.sampler
[s
];
253 DBG("samp %d: changed = %x\n", i
, (int)m
);
255 const int i
= ffs(m
) - 1;
257 dst
->samp
[s
][i
] = src
->samp
[s
][i
];
258 dst
->samp_advertised
[s
][i
] = src
->samp_advertised
[s
][i
];
262 dst
->changed
.sampler
[s
] |= mask
->changed
.sampler
[s
];
267 if (mask
->changed
.group
& NINE_STATE_IDXBUF
)
268 nine_bind(&dst
->idxbuf
, src
->idxbuf
);
270 /* Vertex streams. */
271 if (mask
->changed
.vtxbuf
| mask
->changed
.stream_freq
) {
272 DBG("vtxbuf/stream_freq: %x/%x\n", mask
->changed
.vtxbuf
, mask
->changed
.stream_freq
);
273 uint32_t m
= mask
->changed
.vtxbuf
| mask
->changed
.stream_freq
;
274 for (i
= 0; m
; ++i
, m
>>= 1) {
275 if (mask
->changed
.vtxbuf
& (1 << i
)) {
276 nine_bind(&dst
->stream
[i
], src
->stream
[i
]);
277 if (src
->stream
[i
]) {
278 dst
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
279 pipe_resource_reference(&dst
->vtxbuf
[i
].buffer
, src
->vtxbuf
[i
].buffer
);
280 dst
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
283 if (mask
->changed
.stream_freq
& (1 << i
))
284 dst
->stream_freq
[i
] = src
->stream_freq
[i
];
286 dst
->stream_instancedata_mask
&= ~mask
->changed
.stream_freq
;
287 dst
->stream_instancedata_mask
|=
288 src
->stream_instancedata_mask
& mask
->changed
.stream_freq
;
290 dst
->changed
.vtxbuf
|= mask
->changed
.vtxbuf
;
291 dst
->changed
.stream_freq
|= mask
->changed
.stream_freq
;
295 if (!(mask
->changed
.group
& NINE_STATE_FF
))
297 WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
299 /* Fixed function state. */
301 if (mask
->changed
.group
& NINE_STATE_FF_MATERIAL
)
302 dst
->ff
.material
= src
->ff
.material
;
304 if (mask
->changed
.group
& NINE_STATE_FF_PSSTAGES
) {
305 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
306 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
307 if (mask
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
308 dst
->ff
.tex_stage
[s
][i
] = src
->ff
.tex_stage
[s
][i
];
310 /* TODO: it's 32 exactly, just offset by 1 as 0 is unused */
311 dst
->ff
.changed
.tex_stage
[s
][0] |=
312 mask
->ff
.changed
.tex_stage
[s
][0];
313 dst
->ff
.changed
.tex_stage
[s
][1] |=
314 mask
->ff
.changed
.tex_stage
[s
][1];
318 if (mask
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
319 unsigned num_lights
= MAX2(dst
->ff
.num_lights
, src
->ff
.num_lights
);
320 /* Can happen in Capture() if device state has created new lights after
321 * the stateblock was created.
322 * Can happen in Apply() if the stateblock had recorded the creation of
324 if (dst
->ff
.num_lights
< num_lights
) {
325 dst
->ff
.light
= REALLOC(dst
->ff
.light
,
326 dst
->ff
.num_lights
* sizeof(D3DLIGHT9
),
327 num_lights
* sizeof(D3DLIGHT9
));
328 memset(&dst
->ff
.light
[dst
->ff
.num_lights
], 0, (num_lights
- dst
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
329 /* if mask == dst, a Type of 0 will trigger
330 * "dst->ff.light[i] = src->ff.light[i];" later,
331 * which is what we want in that case. */
333 for (i
= dst
->ff
.num_lights
; i
< num_lights
; ++i
)
334 dst
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
336 dst
->ff
.num_lights
= num_lights
;
338 /* Can happen in Capture() if the stateblock had recorded the creation of
340 * Can happen in Apply() if device state has created new lights after
341 * the stateblock was created. */
342 if (src
->ff
.num_lights
< num_lights
) {
343 src
->ff
.light
= REALLOC(src
->ff
.light
,
344 src
->ff
.num_lights
* sizeof(D3DLIGHT9
),
345 num_lights
* sizeof(D3DLIGHT9
));
346 memset(&src
->ff
.light
[src
->ff
.num_lights
], 0, (num_lights
- src
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
347 for (i
= src
->ff
.num_lights
; i
< num_lights
; ++i
)
348 src
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
349 src
->ff
.num_lights
= num_lights
;
351 /* Note: mask is either src or dst, so at this point src, dst and mask
352 * have num_lights lights. */
353 for (i
= 0; i
< num_lights
; ++i
)
354 if (mask
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
355 dst
->ff
.light
[i
] = src
->ff
.light
[i
];
357 memcpy(dst
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
358 dst
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
360 if (mask
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
361 for (i
= 0; i
< ARRAY_SIZE(mask
->ff
.changed
.transform
); ++i
) {
362 if (!mask
->ff
.changed
.transform
[i
])
364 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
365 if (!(mask
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
367 *nine_state_access_transform(dst
, s
, TRUE
) =
368 *nine_state_access_transform( /* const because !alloc */
369 (struct nine_state
*)src
, s
, FALSE
);
372 dst
->ff
.changed
.transform
[i
] |= mask
->ff
.changed
.transform
[i
];
378 nine_state_copy_common_all(struct NineDevice9
*device
,
379 struct nine_state
*dst
,
380 const struct nine_state
*src
,
381 struct nine_state
*help
,
383 struct nine_range_pool
*pool
,
384 const int MaxStreams
)
389 dst
->changed
.group
|= src
->changed
.group
;
391 dst
->viewport
= src
->viewport
;
392 dst
->scissor
= src
->scissor
;
394 nine_bind(&dst
->vs
, src
->vs
);
395 nine_bind(&dst
->ps
, src
->ps
);
399 * Various possibilities for optimization here, like creating a per-SB
400 * constant buffer, or memcmp'ing for changes.
401 * Will do that later depending on what works best for specific apps.
404 struct nine_range
*r
= help
->changed
.vs_const_f
;
405 memcpy(&dst
->vs_const_f
[0],
406 &src
->vs_const_f
[0], device
->max_vs_const_f
* 4 * sizeof(float));
407 if (device
->may_swvp
)
408 memcpy(dst
->vs_const_f_swvp
,
409 src
->vs_const_f_swvp
, VS_CONST_F_SWVP_SIZE
);
411 nine_ranges_insert(&dst
->changed
.vs_const_f
, r
->bgn
, r
->end
, pool
);
413 memcpy(dst
->vs_const_i
, src
->vs_const_i
, VS_CONST_I_SIZE(device
));
414 memcpy(dst
->vs_const_b
, src
->vs_const_b
, VS_CONST_B_SIZE(device
));
416 r
= help
->changed
.vs_const_i
;
417 nine_ranges_insert(&dst
->changed
.vs_const_i
, r
->bgn
, r
->end
, pool
);
418 r
= help
->changed
.vs_const_b
;
419 nine_ranges_insert(&dst
->changed
.vs_const_b
, r
->bgn
, r
->end
, pool
);
423 /* Pixel constants. */
425 struct nine_range
*r
= help
->changed
.ps_const_f
;
426 memcpy(&dst
->ps_const_f
[0],
427 &src
->ps_const_f
[0], (r
->end
- r
->bgn
) * 4 * sizeof(float));
429 nine_ranges_insert(&dst
->changed
.ps_const_f
, r
->bgn
, r
->end
, pool
);
431 memcpy(dst
->ps_const_i
, src
->ps_const_i
, sizeof(dst
->ps_const_i
));
432 memcpy(dst
->ps_const_b
, src
->ps_const_b
, sizeof(dst
->ps_const_b
));
434 dst
->changed
.ps_const_i
|= src
->changed
.ps_const_i
;
435 dst
->changed
.ps_const_b
|= src
->changed
.ps_const_b
;
440 memcpy(dst
->rs_advertised
, src
->rs_advertised
, sizeof(dst
->rs_advertised
));
442 memcpy(dst
->changed
.rs
, src
->changed
.rs
, sizeof(dst
->changed
.rs
));
446 memcpy(&dst
->clip
, &src
->clip
, sizeof(dst
->clip
));
448 dst
->changed
.ucp
= src
->changed
.ucp
;
451 memcpy(dst
->samp
, src
->samp
, sizeof(dst
->samp
));
452 memcpy(dst
->samp_advertised
, src
->samp_advertised
, sizeof(dst
->samp_advertised
));
454 memcpy(dst
->changed
.sampler
,
455 src
->changed
.sampler
, sizeof(dst
->changed
.sampler
));
458 nine_bind(&dst
->idxbuf
, src
->idxbuf
);
460 /* Vertex streams. */
462 for (i
= 0; i
< ARRAY_SIZE(dst
->stream
); ++i
) {
463 nine_bind(&dst
->stream
[i
], src
->stream
[i
]);
464 if (src
->stream
[i
]) {
465 dst
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
466 pipe_resource_reference(&dst
->vtxbuf
[i
].buffer
, src
->vtxbuf
[i
].buffer
);
467 dst
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
469 dst
->stream_freq
[i
] = src
->stream_freq
[i
];
471 dst
->stream_instancedata_mask
= src
->stream_instancedata_mask
;
473 dst
->changed
.vtxbuf
= (1ULL << MaxStreams
) - 1;
474 dst
->changed
.stream_freq
= (1ULL << MaxStreams
) - 1;
478 /* keep this check in case we want to disable FF */
479 if (!(help
->changed
.group
& NINE_STATE_FF
))
481 WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
483 /* Fixed function state. */
484 dst
->ff
.material
= src
->ff
.material
;
486 memcpy(dst
->ff
.tex_stage
, src
->ff
.tex_stage
, sizeof(dst
->ff
.tex_stage
));
487 if (apply
) /* TODO: memset */
488 memcpy(dst
->ff
.changed
.tex_stage
,
489 src
->ff
.changed
.tex_stage
, sizeof(dst
->ff
.changed
.tex_stage
));
493 if (dst
->ff
.num_lights
< src
->ff
.num_lights
) {
494 dst
->ff
.light
= REALLOC(dst
->ff
.light
,
495 dst
->ff
.num_lights
* sizeof(D3DLIGHT9
),
496 src
->ff
.num_lights
* sizeof(D3DLIGHT9
));
497 dst
->ff
.num_lights
= src
->ff
.num_lights
;
499 memcpy(dst
->ff
.light
,
500 src
->ff
.light
, src
->ff
.num_lights
* sizeof(dst
->ff
.light
[0]));
502 memcpy(dst
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
503 dst
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
508 if (dst
->ff
.num_transforms
< src
->ff
.num_transforms
) {
509 dst
->ff
.transform
= REALLOC(dst
->ff
.transform
,
510 dst
->ff
.num_transforms
* sizeof(dst
->ff
.transform
[0]),
511 src
->ff
.num_transforms
* sizeof(src
->ff
.transform
[0]));
512 dst
->ff
.num_transforms
= src
->ff
.num_transforms
;
514 memcpy(dst
->ff
.transform
,
515 src
->ff
.transform
, src
->ff
.num_transforms
* sizeof(D3DMATRIX
));
516 if (apply
) /* TODO: memset */
517 memcpy(dst
->ff
.changed
.transform
,
518 src
->ff
.changed
.transform
, sizeof(dst
->ff
.changed
.transform
));
522 /* Capture those bits of current device state that have been changed between
523 * BeginStateBlock and EndStateBlock.
526 NineStateBlock9_Capture( struct NineStateBlock9
*This
)
528 struct NineDevice9
*device
= This
->base
.device
;
529 struct nine_state
*dst
= &This
->state
;
530 struct nine_state
*src
= &device
->state
;
531 const int MaxStreams
= device
->caps
.MaxStreams
;
534 DBG("This=%p\n", This
);
536 if (This
->type
== NINESBT_ALL
)
537 nine_state_copy_common_all(device
, dst
, src
, dst
, FALSE
, NULL
, MaxStreams
);
539 nine_state_copy_common(device
, dst
, src
, dst
, FALSE
, NULL
);
541 if (dst
->changed
.group
& NINE_STATE_VDECL
)
542 nine_bind(&dst
->vdecl
, src
->vdecl
);
545 if (dst
->changed
.texture
) {
546 uint32_t m
= dst
->changed
.texture
;
547 for (s
= 0; m
; ++s
, m
>>= 1)
549 nine_bind(&dst
->texture
[s
], src
->texture
[s
]);
555 /* Set state managed by this StateBlock as current device state. */
557 NineStateBlock9_Apply( struct NineStateBlock9
*This
)
559 struct NineDevice9
*device
= This
->base
.device
;
560 struct nine_state
*dst
= &device
->state
;
561 struct nine_state
*src
= &This
->state
;
562 struct nine_range_pool
*pool
= &device
->range_pool
;
563 const int MaxStreams
= device
->caps
.MaxStreams
;
566 DBG("This=%p\n", This
);
568 if (This
->type
== NINESBT_ALL
)
569 nine_state_copy_common_all(device
, dst
, src
, src
, TRUE
, pool
, MaxStreams
);
571 nine_state_copy_common(device
, dst
, src
, src
, TRUE
, pool
);
573 nine_context_apply_stateblock(device
, src
);
575 if ((src
->changed
.group
& NINE_STATE_VDECL
) && src
->vdecl
)
576 NineDevice9_SetVertexDeclaration(This
->base
.device
, (IDirect3DVertexDeclaration9
*)src
->vdecl
);
578 /* Recomputing it is needed if we changed vs but not vdecl */
579 dst
->programmable_vs
= dst
->vs
&& !(dst
->vdecl
&& dst
->vdecl
->position_t
);
582 if (src
->changed
.texture
) {
583 uint32_t m
= src
->changed
.texture
;
585 for (s
= 0; m
; ++s
, m
>>= 1) {
586 struct NineBaseTexture9
*tex
= src
->texture
[s
];
591 if ((tex
->managed
.dirty
| tex
->dirty_mip
) && LIST_IS_EMPTY(&tex
->list
))
592 list_add(&tex
->list
, &This
->base
.device
->update_textures
);
595 src
->texture
[s
]->bind_count
--;
596 nine_bind(&dst
->texture
[s
], src
->texture
[s
]);
603 IDirect3DStateBlock9Vtbl NineStateBlock9_vtable
= {
604 (void *)NineUnknown_QueryInterface
,
605 (void *)NineUnknown_AddRef
,
606 (void *)NineUnknown_Release
,
607 (void *)NineUnknown_GetDevice
, /* actually part of StateBlock9 iface */
608 (void *)NineStateBlock9_Capture
,
609 (void *)NineStateBlock9_Apply
612 static const GUID
*NineStateBlock9_IIDs
[] = {
613 &IID_IDirect3DStateBlock9
,
619 NineStateBlock9_new( struct NineDevice9
*pDevice
,
620 struct NineStateBlock9
**ppOut
,
621 enum nine_stateblock_type type
)
623 NINE_DEVICE_CHILD_NEW(StateBlock9
, ppOut
, pDevice
, type
);