We avoid allocating space for never unused matrices.
However we must do as if we had captured them.
Thus when a D3DSBT_ALL stateblock apply has fewer matrices
than device state, allocate the default matrices for the stateblock
before applying.
Signed-off-by: Axel Davy <davyaxel0@gmail.com>
/* Misc */
+static D3DMATRIX nine_state_identity = { .m[0] = { 1, 0, 0, 0 },
+ .m[1] = { 0, 1, 0, 0 },
+ .m[2] = { 0, 0, 1, 0 },
+ .m[3] = { 0, 0, 0, 1 } };
+
+void
+nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N)
+{
+ unsigned n = ff_state->num_transforms;
+
+ if (N <= n)
+ return;
+
+ ff_state->transform = REALLOC(ff_state->transform,
+ n * sizeof(D3DMATRIX),
+ N * sizeof(D3DMATRIX));
+ for (; n < N; ++n)
+ ff_state->transform[n] = nine_state_identity;
+ ff_state->num_transforms = N;
+}
+
D3DMATRIX *
nine_state_access_transform(struct nine_ff_state *ff_state, D3DTRANSFORMSTATETYPE t,
boolean alloc)
{
- static D3DMATRIX Identity = { .m[0] = { 1, 0, 0, 0 },
- .m[1] = { 0, 1, 0, 0 },
- .m[2] = { 0, 0, 1, 0 },
- .m[3] = { 0, 0, 0, 1 } };
unsigned index;
switch (t) {
}
if (index >= ff_state->num_transforms) {
- unsigned N = index + 1;
- unsigned n = ff_state->num_transforms;
-
if (!alloc)
- return &Identity;
- ff_state->transform = REALLOC(ff_state->transform,
- n * sizeof(D3DMATRIX),
- N * sizeof(D3DMATRIX));
- for (; n < N; ++n)
- ff_state->transform[n] = Identity;
- ff_state->num_transforms = N;
+ return &nine_state_identity;
+ nine_state_resize_transform(ff_state, index + 1);
}
return &ff_state->transform[index];
}
void nine_state_after_draw_sw(struct NineDevice9 *device);
void nine_state_destroy_sw(struct NineDevice9 *device);
+void
+nine_state_resize_transform(struct nine_ff_state *ff_state, unsigned N);
+
/* If @alloc is FALSE, the return value may be a const identity matrix.
* Therefore, do not modify if you set alloc to FALSE !
*/
if (!(mask->ff.changed.transform[i] & (1 << (s % 32))))
continue;
*nine_state_access_transform(&dst->ff, s, TRUE) =
- *nine_state_access_transform( /* const because !alloc */
- (struct nine_ff_state *)&src->ff, s, FALSE);
+ *nine_state_access_transform(&src->ff, s, FALSE);
}
if (apply)
dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];
static void
nine_state_copy_common_all(struct NineDevice9 *device,
struct nine_state *dst,
- const struct nine_state *src,
+ struct nine_state *src,
struct nine_state *help,
const boolean apply,
struct nine_range_pool *pool,
/* Transforms. */
if (1) {
- if (dst->ff.num_transforms < src->ff.num_transforms) {
- dst->ff.transform = REALLOC(dst->ff.transform,
- dst->ff.num_transforms * sizeof(dst->ff.transform[0]),
- src->ff.num_transforms * sizeof(src->ff.transform[0]));
- dst->ff.num_transforms = src->ff.num_transforms;
+ /* Increase dst size if required (to copy the new states).
+ * Increase src size if required (to initialize missing transforms).
+ */
+ if (dst->ff.num_transforms != src->ff.num_transforms) {
+ int num_transforms = MAX2(src->ff.num_transforms, dst->ff.num_transforms);
+ nine_state_resize_transform(&src->ff, num_transforms);
+ nine_state_resize_transform(&dst->ff, num_transforms);
}
memcpy(dst->ff.transform,
- src->ff.transform, src->ff.num_transforms * sizeof(D3DMATRIX));
- if (apply) /* TODO: memset */
+ src->ff.transform, dst->ff.num_transforms * sizeof(D3DMATRIX));
+ /* Apply is always used on device state.
+ * src is then the D3DSBT_ALL stateblock which
+ * ff.changed.transform indicates all matrices are dirty.
+ */
+ if (apply)
memcpy(dst->ff.changed.transform,
src->ff.changed.transform, sizeof(dst->ff.changed.transform));
}