st/nine: Reimplement nine_context_apply_stateblock

The new version uses nine_context functions instead of
applying the changes directly to nine_context.
This will enable it to work with CSMT.

v2: Fix nine_context_light_enable_stateblock
The memcpy arguments were wrong, and the state
wasn't set dirty.

Signed-off-by: Axel Davy <axel.davy@ens.fr>
This commit is contained in:
Axel Davy 2016-11-01 18:00:02 +01:00
parent 8d967abb98
commit 97e4b65e7f
1 changed files with 206 additions and 0 deletions

View File

@ -1446,6 +1446,23 @@ nine_context_set_pixel_shader_constant_f(struct NineDevice9 *device,
context->changed.group |= NINE_STATE_PS_CONST;
}
/* For stateblocks */
static void
nine_context_set_pixel_shader_constant_i_transformed(struct NineDevice9 *device,
UINT StartRegister,
const int *pConstantData,
UINT Vector4iCount)
{
struct nine_context *context = &device->context;
memcpy(&context->ps_const_i[StartRegister][0],
pConstantData,
Vector4iCount * sizeof(context->ps_const_i[0]));
context->changed.ps_const_i = TRUE;
context->changed.group |= NINE_STATE_PS_CONST;
}
void
nine_context_set_pixel_shader_constant_i(struct NineDevice9 *device,
UINT StartRegister,
@ -1587,6 +1604,20 @@ nine_context_set_light(struct NineDevice9 *device,
context->changed.group |= NINE_STATE_FF_LIGHTING;
}
/* For stateblocks */
static void
nine_context_light_enable_stateblock(struct NineDevice9 *device,
const uint16_t active_light[NINE_MAX_LIGHTS_ACTIVE], /* TODO: use pointer that convey size for csmt */
unsigned int num_lights_active)
{
struct nine_context *context = &device->context;
memcpy(context->ff.active_light, active_light, NINE_MAX_LIGHTS_ACTIVE * sizeof(context->ff.active_light[0]));
context->ff.num_lights_active = num_lights_active;
context->changed.group |= NINE_STATE_FF_LIGHTING;
}
void
nine_context_light_enable(struct NineDevice9 *device,
DWORD Index,
@ -1653,6 +1684,8 @@ nine_context_set_clip_plane(struct NineDevice9 *device,
context->changed.ucp = TRUE;
}
#if 0
void
nine_context_apply_stateblock(struct NineDevice9 *device,
const struct nine_state *src)
@ -1878,6 +1911,179 @@ nine_context_apply_stateblock(struct NineDevice9 *device,
}
}
#endif
/* Do not write to nine_context directly. Slower,
* but works with csmt. TODO: write a special csmt version that
* would record the list of commands as much as possible,
* and use the version above else.
*/
void
nine_context_apply_stateblock(struct NineDevice9 *device,
const struct nine_state *src)
{
int i;
/* No need to apply src->changed.group, since all calls do
* set context->changed.group */
for (i = 0; i < ARRAY_SIZE(src->changed.rs); ++i) {
uint32_t m = src->changed.rs[i];
while (m) {
const int r = ffs(m) - 1;
m &= ~(1 << r);
nine_context_set_render_state(device, i * 32 + r, src->rs_advertised[i * 32 + r]);
}
}
/* Textures */
if (src->changed.texture) {
uint32_t m = src->changed.texture;
unsigned s;
for (s = 0; m; ++s, m >>= 1) {
struct NineBaseTexture9 *tex = src->texture[s];
if (!(m & 1))
continue;
nine_context_set_texture(device, s, tex);
}
}
/* Sampler state */
if (src->changed.group & NINE_STATE_SAMPLER) {
unsigned s;
for (s = 0; s < NINE_MAX_SAMPLERS; ++s) {
uint32_t m = src->changed.sampler[s];
while (m) {
const int i = ffs(m) - 1;
m &= ~(1 << i);
nine_context_set_sampler_state(device, s, i, src->samp_advertised[s][i]);
}
}
}
/* Vertex buffers */
if (src->changed.vtxbuf | src->changed.stream_freq) {
uint32_t m = src->changed.vtxbuf | src->changed.stream_freq;
for (i = 0; m; ++i, m >>= 1) {
if (src->changed.vtxbuf & (1 << i))
nine_context_set_stream_source(device, i, src->stream[i], src->vtxbuf[i].buffer_offset, src->vtxbuf[i].stride);
if (src->changed.stream_freq & (1 << i))
nine_context_set_stream_source_freq(device, i, src->stream_freq[i]);
}
}
/* Index buffer */
if (src->changed.group & NINE_STATE_IDXBUF)
nine_context_set_indices(device, src->idxbuf);
/* Vertex declaration */
if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl)
nine_context_set_vertex_declaration(device, src->vdecl);
/* Vertex shader */
if (src->changed.group & NINE_STATE_VS)
nine_context_set_vertex_shader(device, src->vs);
/* Pixel shader */
if (src->changed.group & NINE_STATE_PS)
nine_context_set_pixel_shader(device, src->ps);
/* Vertex constants */
if (src->changed.group & NINE_STATE_VS_CONST) {
struct nine_range *r;
for (r = src->changed.vs_const_f; r; r = r->next)
nine_context_set_vertex_shader_constant_f(device, r->bgn,
&src->vs_const_f[r->bgn * 4],
r->end - r->bgn);
for (r = src->changed.vs_const_i; r; r = r->next)
nine_context_set_vertex_shader_constant_i(device, r->bgn,
&src->vs_const_i[r->bgn * 4],
r->end - r->bgn);
for (r = src->changed.vs_const_b; r; r = r->next)
nine_context_set_vertex_shader_constant_b(device, r->bgn,
&src->vs_const_b[r->bgn * 4],
r->end - r->bgn);
}
/* Pixel constants */
if (src->changed.group & NINE_STATE_PS_CONST) {
struct nine_range *r;
for (r = src->changed.ps_const_f; r; r = r->next)
nine_context_set_pixel_shader_constant_f(device, r->bgn,
&src->ps_const_f[r->bgn * 4],
r->end - r->bgn);
if (src->changed.ps_const_i) {
uint16_t m = src->changed.ps_const_i;
for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
if (m & 1)
nine_context_set_pixel_shader_constant_i_transformed(device, i,
src->ps_const_i[i], 1);
}
if (src->changed.ps_const_b) {
uint16_t m = src->changed.ps_const_b;
for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
if (m & 1)
nine_context_set_pixel_shader_constant_b(device, i,
&src->ps_const_b[i], 1);
}
}
/* Viewport */
if (src->changed.group & NINE_STATE_VIEWPORT)
nine_context_set_viewport(device, &src->viewport);
/* Scissor */
if (src->changed.group & NINE_STATE_SCISSOR)
nine_context_set_scissor(device, &src->scissor);
/* User Clip Planes */
if (src->changed.ucp)
for (i = 0; i < PIPE_MAX_CLIP_PLANES; ++i)
if (src->changed.ucp & (1 << i))
nine_context_set_clip_plane(device, i, &src->clip.ucp[i][0]);
if (!(src->changed.group & NINE_STATE_FF))
return;
/* Fixed function state. */
if (src->changed.group & NINE_STATE_FF_MATERIAL)
nine_context_set_material(device, &src->ff.material);
if (src->changed.group & NINE_STATE_FF_PSSTAGES) {
unsigned s;
for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) {
for (i = 0; i < NINED3DTSS_COUNT; ++i)
if (src->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32)))
nine_context_set_texture_stage_state(device, s, i, src->ff.tex_stage[s][i]);
}
}
if (src->changed.group & NINE_STATE_FF_LIGHTING) {
for (i = 0; i < src->ff.num_lights; ++i)
if (src->ff.light[i].Type != NINED3DLIGHT_INVALID)
nine_context_set_light(device, i, &src->ff.light[i]);
nine_context_light_enable_stateblock(device, src->ff.active_light, src->ff.num_lights_active);
}
if (src->changed.group & NINE_STATE_FF_VSTRANSF) {
for (i = 0; i < ARRAY_SIZE(src->ff.changed.transform); ++i) {
unsigned s;
if (!src->ff.changed.transform[i])
continue;
for (s = i * 32; s < (i * 32 + 32); ++s) {
if (!(src->ff.changed.transform[i] & (1 << (s % 32))))
continue;
nine_context_set_transform(device, s,
nine_state_access_transform(
(struct nine_ff_state *)&src->ff,
s, FALSE));
}
}
}
}
static void
nine_update_state_framebuffer_clear(struct NineDevice9 *device)
{