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 dst
->rs
[i
* 32 + r
] = src
->rs
[i
* 32 + r
];
229 DBG("State %d %s = %d\n", i
* 32 + r
, nine_d3drs_to_string(i
* 32 + r
), (int)src
->rs
[i
* 32 + r
]);
230 dst
->rs_advertised
[i
* 32 + r
] = src
->rs_advertised
[i
* 32 + r
];
236 if (mask
->changed
.ucp
) {
237 DBG("ucp: %x\n", mask
->changed
.ucp
);
238 for (i
= 0; i
< PIPE_MAX_CLIP_PLANES
; ++i
)
239 if (mask
->changed
.ucp
& (1 << i
))
240 memcpy(dst
->clip
.ucp
[i
],
241 src
->clip
.ucp
[i
], sizeof(src
->clip
.ucp
[0]));
243 dst
->changed
.ucp
|= mask
->changed
.ucp
;
247 if (mask
->changed
.group
& NINE_STATE_SAMPLER
) {
248 for (s
= 0; s
< NINE_MAX_SAMPLERS
; ++s
) {
249 if (mask
->changed
.sampler
[s
] == 0x3ffe) {
250 memcpy(&dst
->samp
[s
], &src
->samp
[s
], sizeof(dst
->samp
[s
]));
251 memcpy(&dst
->samp_advertised
[s
], &src
->samp_advertised
[s
], sizeof(dst
->samp_advertised
[s
]));
253 uint32_t m
= mask
->changed
.sampler
[s
];
254 DBG("samp %d: changed = %x\n", i
, (int)m
);
256 const int i
= ffs(m
) - 1;
258 dst
->samp
[s
][i
] = src
->samp
[s
][i
];
259 dst
->samp_advertised
[s
][i
] = src
->samp_advertised
[s
][i
];
263 dst
->changed
.sampler
[s
] |= mask
->changed
.sampler
[s
];
268 if (mask
->changed
.group
& NINE_STATE_IDXBUF
)
269 nine_bind(&dst
->idxbuf
, src
->idxbuf
);
271 /* Vertex streams. */
272 if (mask
->changed
.vtxbuf
| mask
->changed
.stream_freq
) {
273 DBG("vtxbuf/stream_freq: %x/%x\n", mask
->changed
.vtxbuf
, mask
->changed
.stream_freq
);
274 uint32_t m
= mask
->changed
.vtxbuf
| mask
->changed
.stream_freq
;
275 for (i
= 0; m
; ++i
, m
>>= 1) {
276 if (mask
->changed
.vtxbuf
& (1 << i
)) {
277 nine_bind(&dst
->stream
[i
], src
->stream
[i
]);
278 if (src
->stream
[i
]) {
279 dst
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
280 pipe_resource_reference(&dst
->vtxbuf
[i
].buffer
, src
->vtxbuf
[i
].buffer
);
281 dst
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
284 if (mask
->changed
.stream_freq
& (1 << i
))
285 dst
->stream_freq
[i
] = src
->stream_freq
[i
];
287 dst
->stream_instancedata_mask
&= ~mask
->changed
.stream_freq
;
288 dst
->stream_instancedata_mask
|=
289 src
->stream_instancedata_mask
& mask
->changed
.stream_freq
;
291 dst
->changed
.vtxbuf
|= mask
->changed
.vtxbuf
;
292 dst
->changed
.stream_freq
|= mask
->changed
.stream_freq
;
296 if (!(mask
->changed
.group
& NINE_STATE_FF
))
298 WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
300 /* Fixed function state. */
302 if (mask
->changed
.group
& NINE_STATE_FF_MATERIAL
)
303 dst
->ff
.material
= src
->ff
.material
;
305 if (mask
->changed
.group
& NINE_STATE_FF_PSSTAGES
) {
306 for (s
= 0; s
< NINE_MAX_TEXTURE_STAGES
; ++s
) {
307 for (i
= 0; i
< NINED3DTSS_COUNT
; ++i
)
308 if (mask
->ff
.changed
.tex_stage
[s
][i
/ 32] & (1 << (i
% 32)))
309 dst
->ff
.tex_stage
[s
][i
] = src
->ff
.tex_stage
[s
][i
];
311 /* TODO: it's 32 exactly, just offset by 1 as 0 is unused */
312 dst
->ff
.changed
.tex_stage
[s
][0] |=
313 mask
->ff
.changed
.tex_stage
[s
][0];
314 dst
->ff
.changed
.tex_stage
[s
][1] |=
315 mask
->ff
.changed
.tex_stage
[s
][1];
319 if (mask
->changed
.group
& NINE_STATE_FF_LIGHTING
) {
320 unsigned num_lights
= MAX2(dst
->ff
.num_lights
, src
->ff
.num_lights
);
321 /* Can happen in Capture() if device state has created new lights after
322 * the stateblock was created.
323 * Can happen in Apply() if the stateblock had recorded the creation of
325 if (dst
->ff
.num_lights
< num_lights
) {
326 dst
->ff
.light
= REALLOC(dst
->ff
.light
,
327 dst
->ff
.num_lights
* sizeof(D3DLIGHT9
),
328 num_lights
* sizeof(D3DLIGHT9
));
329 memset(&dst
->ff
.light
[dst
->ff
.num_lights
], 0, (num_lights
- dst
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
330 /* if mask == dst, a Type of 0 will trigger
331 * "dst->ff.light[i] = src->ff.light[i];" later,
332 * which is what we want in that case. */
334 for (i
= dst
->ff
.num_lights
; i
< num_lights
; ++i
)
335 dst
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
337 dst
->ff
.num_lights
= num_lights
;
339 /* Can happen in Capture() if the stateblock had recorded the creation of
341 * Can happen in Apply() if device state has created new lights after
342 * the stateblock was created. */
343 if (src
->ff
.num_lights
< num_lights
) {
344 src
->ff
.light
= REALLOC(src
->ff
.light
,
345 src
->ff
.num_lights
* sizeof(D3DLIGHT9
),
346 num_lights
* sizeof(D3DLIGHT9
));
347 memset(&src
->ff
.light
[src
->ff
.num_lights
], 0, (num_lights
- src
->ff
.num_lights
) * sizeof(D3DLIGHT9
));
348 for (i
= src
->ff
.num_lights
; i
< num_lights
; ++i
)
349 src
->ff
.light
[i
].Type
= (D3DLIGHTTYPE
)NINED3DLIGHT_INVALID
;
350 src
->ff
.num_lights
= num_lights
;
352 /* Note: mask is either src or dst, so at this point src, dst and mask
353 * have num_lights lights. */
354 for (i
= 0; i
< num_lights
; ++i
)
355 if (mask
->ff
.light
[i
].Type
!= NINED3DLIGHT_INVALID
)
356 dst
->ff
.light
[i
] = src
->ff
.light
[i
];
358 memcpy(dst
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
359 dst
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
361 if (mask
->changed
.group
& NINE_STATE_FF_VSTRANSF
) {
362 for (i
= 0; i
< ARRAY_SIZE(mask
->ff
.changed
.transform
); ++i
) {
363 if (!mask
->ff
.changed
.transform
[i
])
365 for (s
= i
* 32; s
< (i
* 32 + 32); ++s
) {
366 if (!(mask
->ff
.changed
.transform
[i
] & (1 << (s
% 32))))
368 *nine_state_access_transform(dst
, s
, TRUE
) =
369 *nine_state_access_transform( /* const because !alloc */
370 (struct nine_state
*)src
, s
, FALSE
);
373 dst
->ff
.changed
.transform
[i
] |= mask
->ff
.changed
.transform
[i
];
379 nine_state_copy_common_all(struct NineDevice9
*device
,
380 struct nine_state
*dst
,
381 const struct nine_state
*src
,
382 struct nine_state
*help
,
384 struct nine_range_pool
*pool
,
385 const int MaxStreams
)
390 dst
->changed
.group
|= src
->changed
.group
;
392 dst
->viewport
= src
->viewport
;
393 dst
->scissor
= src
->scissor
;
395 nine_bind(&dst
->vs
, src
->vs
);
396 nine_bind(&dst
->ps
, src
->ps
);
400 * Various possibilities for optimization here, like creating a per-SB
401 * constant buffer, or memcmp'ing for changes.
402 * Will do that later depending on what works best for specific apps.
405 struct nine_range
*r
= help
->changed
.vs_const_f
;
406 memcpy(&dst
->vs_const_f
[0],
407 &src
->vs_const_f
[0], device
->max_vs_const_f
* 4 * sizeof(float));
408 if (device
->may_swvp
)
409 memcpy(dst
->vs_const_f_swvp
,
410 src
->vs_const_f_swvp
, VS_CONST_F_SWVP_SIZE
);
412 nine_ranges_insert(&dst
->changed
.vs_const_f
, r
->bgn
, r
->end
, pool
);
414 memcpy(dst
->vs_const_i
, src
->vs_const_i
, VS_CONST_I_SIZE(device
));
415 memcpy(dst
->vs_const_b
, src
->vs_const_b
, VS_CONST_B_SIZE(device
));
417 r
= help
->changed
.vs_const_i
;
418 nine_ranges_insert(&dst
->changed
.vs_const_i
, r
->bgn
, r
->end
, pool
);
419 r
= help
->changed
.vs_const_b
;
420 nine_ranges_insert(&dst
->changed
.vs_const_b
, r
->bgn
, r
->end
, pool
);
424 /* Pixel constants. */
426 struct nine_range
*r
= help
->changed
.ps_const_f
;
427 memcpy(&dst
->ps_const_f
[0],
428 &src
->ps_const_f
[0], (r
->end
- r
->bgn
) * 4 * sizeof(float));
430 nine_ranges_insert(&dst
->changed
.ps_const_f
, r
->bgn
, r
->end
, pool
);
432 memcpy(dst
->ps_const_i
, src
->ps_const_i
, sizeof(dst
->ps_const_i
));
433 memcpy(dst
->ps_const_b
, src
->ps_const_b
, sizeof(dst
->ps_const_b
));
435 dst
->changed
.ps_const_i
|= src
->changed
.ps_const_i
;
436 dst
->changed
.ps_const_b
|= src
->changed
.ps_const_b
;
441 memcpy(dst
->rs
, src
->rs
, sizeof(dst
->rs
));
442 memcpy(dst
->rs_advertised
, src
->rs_advertised
, sizeof(dst
->rs_advertised
));
444 memcpy(dst
->changed
.rs
, src
->changed
.rs
, sizeof(dst
->changed
.rs
));
448 memcpy(&dst
->clip
, &src
->clip
, sizeof(dst
->clip
));
450 dst
->changed
.ucp
= src
->changed
.ucp
;
453 memcpy(dst
->samp
, src
->samp
, sizeof(dst
->samp
));
454 memcpy(dst
->samp_advertised
, src
->samp_advertised
, sizeof(dst
->samp_advertised
));
456 memcpy(dst
->changed
.sampler
,
457 src
->changed
.sampler
, sizeof(dst
->changed
.sampler
));
460 nine_bind(&dst
->idxbuf
, src
->idxbuf
);
462 /* Vertex streams. */
464 for (i
= 0; i
< ARRAY_SIZE(dst
->stream
); ++i
) {
465 nine_bind(&dst
->stream
[i
], src
->stream
[i
]);
466 if (src
->stream
[i
]) {
467 dst
->vtxbuf
[i
].buffer_offset
= src
->vtxbuf
[i
].buffer_offset
;
468 pipe_resource_reference(&dst
->vtxbuf
[i
].buffer
, src
->vtxbuf
[i
].buffer
);
469 dst
->vtxbuf
[i
].stride
= src
->vtxbuf
[i
].stride
;
471 dst
->stream_freq
[i
] = src
->stream_freq
[i
];
473 dst
->stream_instancedata_mask
= src
->stream_instancedata_mask
;
475 dst
->changed
.vtxbuf
= (1ULL << MaxStreams
) - 1;
476 dst
->changed
.stream_freq
= (1ULL << MaxStreams
) - 1;
480 /* keep this check in case we want to disable FF */
481 if (!(help
->changed
.group
& NINE_STATE_FF
))
483 WARN_ONCE("Fixed function state not handled properly by StateBlocks.\n");
485 /* Fixed function state. */
486 dst
->ff
.material
= src
->ff
.material
;
488 memcpy(dst
->ff
.tex_stage
, src
->ff
.tex_stage
, sizeof(dst
->ff
.tex_stage
));
489 if (apply
) /* TODO: memset */
490 memcpy(dst
->ff
.changed
.tex_stage
,
491 src
->ff
.changed
.tex_stage
, sizeof(dst
->ff
.changed
.tex_stage
));
495 if (dst
->ff
.num_lights
< src
->ff
.num_lights
) {
496 dst
->ff
.light
= REALLOC(dst
->ff
.light
,
497 dst
->ff
.num_lights
* sizeof(D3DLIGHT9
),
498 src
->ff
.num_lights
* sizeof(D3DLIGHT9
));
499 dst
->ff
.num_lights
= src
->ff
.num_lights
;
501 memcpy(dst
->ff
.light
,
502 src
->ff
.light
, src
->ff
.num_lights
* sizeof(dst
->ff
.light
[0]));
504 memcpy(dst
->ff
.active_light
, src
->ff
.active_light
, sizeof(src
->ff
.active_light
) );
505 dst
->ff
.num_lights_active
= src
->ff
.num_lights_active
;
510 if (dst
->ff
.num_transforms
< src
->ff
.num_transforms
) {
511 dst
->ff
.transform
= REALLOC(dst
->ff
.transform
,
512 dst
->ff
.num_transforms
* sizeof(dst
->ff
.transform
[0]),
513 src
->ff
.num_transforms
* sizeof(src
->ff
.transform
[0]));
514 dst
->ff
.num_transforms
= src
->ff
.num_transforms
;
516 memcpy(dst
->ff
.transform
,
517 src
->ff
.transform
, src
->ff
.num_transforms
* sizeof(D3DMATRIX
));
518 if (apply
) /* TODO: memset */
519 memcpy(dst
->ff
.changed
.transform
,
520 src
->ff
.changed
.transform
, sizeof(dst
->ff
.changed
.transform
));
524 /* Capture those bits of current device state that have been changed between
525 * BeginStateBlock and EndStateBlock.
528 NineStateBlock9_Capture( struct NineStateBlock9
*This
)
530 struct NineDevice9
*device
= This
->base
.device
;
531 struct nine_state
*dst
= &This
->state
;
532 struct nine_state
*src
= &device
->state
;
533 const int MaxStreams
= device
->caps
.MaxStreams
;
536 DBG("This=%p\n", This
);
538 if (This
->type
== NINESBT_ALL
)
539 nine_state_copy_common_all(device
, dst
, src
, dst
, FALSE
, NULL
, MaxStreams
);
541 nine_state_copy_common(device
, dst
, src
, dst
, FALSE
, NULL
);
543 if (dst
->changed
.group
& NINE_STATE_VDECL
)
544 nine_bind(&dst
->vdecl
, src
->vdecl
);
547 if (dst
->changed
.texture
) {
548 uint32_t m
= dst
->changed
.texture
;
549 for (s
= 0; m
; ++s
, m
>>= 1)
551 nine_bind(&dst
->texture
[s
], src
->texture
[s
]);
557 /* Set state managed by this StateBlock as current device state. */
559 NineStateBlock9_Apply( struct NineStateBlock9
*This
)
561 struct NineDevice9
*device
= This
->base
.device
;
562 struct nine_state
*dst
= &device
->state
;
563 struct nine_state
*src
= &This
->state
;
564 struct nine_range_pool
*pool
= &device
->range_pool
;
565 const int MaxStreams
= device
->caps
.MaxStreams
;
568 DBG("This=%p\n", This
);
570 if (This
->type
== NINESBT_ALL
)
571 nine_state_copy_common_all(device
, dst
, src
, src
, TRUE
, pool
, MaxStreams
);
573 nine_state_copy_common(device
, dst
, src
, src
, TRUE
, pool
);
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
;
584 dst
->changed
.texture
|= m
;
586 dst
->samplers_shadow
&= ~m
;
588 for (s
= 0; m
; ++s
, m
>>= 1) {
589 struct NineBaseTexture9
*tex
= src
->texture
[s
];
594 if ((tex
->managed
.dirty
| tex
->dirty_mip
) && LIST_IS_EMPTY(&tex
->list
))
595 list_add(&tex
->list
, &This
->base
.device
->update_textures
);
596 dst
->samplers_shadow
|= tex
->shadow
<< s
;
599 src
->texture
[s
]->bind_count
--;
600 nine_bind(&dst
->texture
[s
], src
->texture
[s
]);
607 IDirect3DStateBlock9Vtbl NineStateBlock9_vtable
= {
608 (void *)NineUnknown_QueryInterface
,
609 (void *)NineUnknown_AddRef
,
610 (void *)NineUnknown_Release
,
611 (void *)NineUnknown_GetDevice
, /* actually part of StateBlock9 iface */
612 (void *)NineStateBlock9_Capture
,
613 (void *)NineStateBlock9_Apply
616 static const GUID
*NineStateBlock9_IIDs
[] = {
617 &IID_IDirect3DStateBlock9
,
623 NineStateBlock9_new( struct NineDevice9
*pDevice
,
624 struct NineStateBlock9
**ppOut
,
625 enum nine_stateblock_type type
)
627 NINE_DEVICE_CHILD_NEW(StateBlock9
, ppOut
, pDevice
, type
);