diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_state.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 119 |
1 files changed, 112 insertions, 7 deletions
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 99ecae9f5f..34bf81c193 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -38,6 +38,8 @@ #include "r300_fs.h" #include "r300_vs.h" +#include "radeon_winsys.h" + /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -425,7 +427,7 @@ static void* (r300_translate_stencil_op(state->stencil[0].zfail_op) << R300_S_FRONT_ZFAIL_OP_SHIFT); - dsa->stencil_ref_mask = (state->stencil[0].ref_value) | + dsa->stencil_ref_mask = (state->stencil[0].valuemask << R300_STENCILMASK_SHIFT) | (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT); @@ -444,7 +446,7 @@ static void* if (caps->is_r500) { dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; - dsa->stencil_ref_bf = (state->stencil[1].ref_value) | + dsa->stencil_ref_bf = (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | (state->stencil[1].writemask << @@ -488,6 +490,77 @@ static void r300_delete_dsa_state(struct pipe_context* pipe, FREE(state); } +static void r300_set_stencil_ref(struct pipe_context* pipe, + const struct pipe_stencil_ref* sr) +{ + struct r300_context* r300 = r300_context(pipe); + r300->stencil_ref = *sr; + r300->dsa_state.dirty = TRUE; +} + +/* This switcheroo is needed just because of goddamned MACRO_SWITCH. */ +static void r300_fb_update_tiling_flags(struct r300_context *r300, + const struct pipe_framebuffer_state *old_state, + const struct pipe_framebuffer_state *new_state) +{ + struct r300_texture *tex; + unsigned i, j, level; + + /* Reset tiling flags for old surfaces to default values. */ + for (i = 0; i < old_state->nr_cbufs; i++) { + for (j = 0; j < new_state->nr_cbufs; j++) { + if (old_state->cbufs[i]->texture == new_state->cbufs[j]->texture) { + break; + } + } + /* If not binding the surface again... */ + if (j != new_state->nr_cbufs) { + continue; + } + + tex = (struct r300_texture*)old_state->cbufs[i]->texture; + + if (tex) { + r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + tex->pitch[0], + tex->microtile != 0, + tex->macrotile != 0); + } + } + if (old_state->zsbuf && + (!new_state->zsbuf || + old_state->zsbuf->texture != new_state->zsbuf->texture)) { + tex = (struct r300_texture*)old_state->zsbuf->texture; + + if (tex) { + r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + tex->pitch[0], + tex->microtile != 0, + tex->macrotile != 0); + } + } + + /* Set tiling flags for new surfaces. */ + for (i = 0; i < new_state->nr_cbufs; i++) { + tex = (struct r300_texture*)new_state->cbufs[i]->texture; + level = new_state->cbufs[i]->level; + + r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + tex->pitch[level], + tex->microtile != 0, + tex->mip_macrotile[level] != 0); + } + if (new_state->zsbuf) { + tex = (struct r300_texture*)new_state->zsbuf->texture; + level = new_state->zsbuf->level; + + r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + tex->pitch[level], + tex->microtile != 0, + tex->mip_macrotile[level] != 0); + } +} + static void r300_set_framebuffer_state(struct pipe_context* pipe, const struct pipe_framebuffer_state* state) @@ -497,9 +570,6 @@ static void unsigned max_width, max_height; uint32_t zbuffer_bpp = 0; - r300->fb_state.size = (10 * state->nr_cbufs) + - (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 6; if (state->nr_cbufs > 4) { debug_printf("r300: Implementation error: Too many MRTs in %s, " @@ -521,13 +591,17 @@ static void return; } + if (r300->draw) { draw_flush(r300->draw); } memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); - /* Don't rely on the order of states being set for the first time. */ + r300->fb_state.size = (10 * state->nr_cbufs) + (state->zsbuf ? 10 : 0) + 6; + + r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); + /* XXX wait what */ r300->blend_state.dirty = TRUE; r300->dsa_state.dirty = TRUE; @@ -794,7 +868,7 @@ static void* sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter, state->mag_img_filter, state->min_mip_filter, - state->max_anisotropy > 1.0); + state->max_anisotropy > 0); /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */ /* We must pass these to the emit function to clamp them properly. */ @@ -1076,7 +1150,9 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, struct pipe_buffer *buf) { struct r300_context* r300 = r300_context(pipe); + struct r300_screen *r300screen = r300_screen(pipe->screen); void *mapped; + int max_size = 0; if (buf == NULL || buf->size == 0 || (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) @@ -1086,6 +1162,33 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, } assert((buf->size % 4 * sizeof(float)) == 0); + + /* Check the size of the constant buffer. */ + switch (shader) { + case PIPE_SHADER_VERTEX: + max_size = 256; + break; + case PIPE_SHADER_FRAGMENT: + if (r300screen->caps->is_r500) { + max_size = 256; + /* XXX Implement emission of r400's extended constant buffer. */ + /*} else if (r300screen->caps->is_r400) { + max_size = 64;*/ + } else { + max_size = 32; + } + break; + default: + assert(0); + } + + /* XXX Subtract immediates and RC_STATE_* variables. */ + if (buf->size > (sizeof(float) * 4 * max_size)) { + debug_printf("r300: Max size of the constant buffer is " + "%i*4 floats.\n", max_size); + abort(); + } + memcpy(r300->shader_constants[shader].constants, mapped, buf->size); r300->shader_constants[shader].count = buf->size / (4 * sizeof(float)); pipe_buffer_unmap(pipe->screen, buf); @@ -1112,6 +1215,8 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state; r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state; + r300->context.set_stencil_ref = r300_set_stencil_ref; + r300->context.set_framebuffer_state = r300_set_framebuffer_state; r300->context.create_fs_state = r300_create_fs_state; |