diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_state.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 312 |
1 files changed, 125 insertions, 187 deletions
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 712e9280e3..39e05583dd 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -38,8 +38,7 @@ #include "r300_state_inlines.h" #include "r300_fs.h" #include "r300_vs.h" - -#include "radeon_winsys.h" +#include "r300_winsys.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -528,8 +527,8 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, if (tex) { r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], - tex->microtile != 0, - tex->macrotile != 0); + tex->microtile, + tex->macrotile); } } if (old_state->zsbuf && @@ -540,8 +539,8 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, if (tex) { r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], - tex->microtile != 0, - tex->macrotile != 0); + tex->microtile, + tex->macrotile); } } @@ -552,8 +551,8 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], - tex->microtile != 0, - tex->mip_macrotile[level] != 0); + tex->microtile, + tex->mip_macrotile[level]); } if (new_state->zsbuf) { tex = (struct r300_texture*)new_state->zsbuf->texture; @@ -561,8 +560,8 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], - tex->microtile != 0, - tex->mip_macrotile[level] != 0); + tex->microtile, + tex->mip_macrotile[level]); } } @@ -576,9 +575,8 @@ static void unsigned max_width, max_height; uint32_t zbuffer_bpp = 0; - if (state->nr_cbufs > 4) { - debug_printf("r300: Implementation error: Too many MRTs in %s, " + fprintf(stderr, "r300: Implementation error: Too many MRTs in %s, " "refusing to bind framebuffer state!\n", __FUNCTION__); return; } @@ -592,7 +590,7 @@ static void } if (state->width > max_width || state->height > max_height) { - debug_printf("r300: Implementation error: Render targets are too " + fprintf(stderr, "r300: Implementation error: Render targets are too " "big in %s, refusing to bind framebuffer state!\n", __FUNCTION__); return; } @@ -933,13 +931,14 @@ static void r300_delete_sampler_state(struct pipe_context* pipe, void* state) FREE(state); } -static void r300_set_sampler_textures(struct pipe_context* pipe, - unsigned count, - struct pipe_texture** texture) +static void r300_set_fragment_sampler_views(struct pipe_context* pipe, + unsigned count, + struct pipe_sampler_view** views) { struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; + struct r300_texture *texture; unsigned i; boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; boolean dirty_tex = FALSE; @@ -950,13 +949,20 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } for (i = 0; i < count; i++) { - if (state->textures[i] != (struct r300_texture*)texture[i]) { - pipe_texture_reference((struct pipe_texture**)&state->textures[i], - texture[i]); + if (state->fragment_sampler_views[i] != views[i]) { + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + views[i]); + + if (!views[i]) { + continue; + } + + /* A new sampler view (= texture)... */ dirty_tex = TRUE; /* R300-specific - set the texrect factor in the fragment shader */ - if (!is_r500 && state->textures[i]->is_npot) { + texture = (struct r300_texture *)views[i]->texture; + if (!is_r500 && texture->is_npot) { /* XXX It would be nice to re-emit just 1 constant, * XXX not all of them */ r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -965,9 +971,9 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } for (i = count; i < 8; i++) { - if (state->textures[i]) { - pipe_texture_reference((struct pipe_texture**)&state->textures[i], - NULL); + if (state->fragment_sampler_views[i]) { + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + NULL); } } @@ -980,6 +986,32 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } } +static struct pipe_sampler_view * +r300_create_sampler_view(struct pipe_context *pipe, + struct pipe_texture *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_texture_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + +static void +r300_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_texture_reference(&view->texture, NULL); + FREE(view); +} + static void r300_set_scissor_state(struct pipe_context* pipe, const struct pipe_scissor_state* state) { @@ -1041,117 +1073,71 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - int i; - unsigned max_index = (1 << 24) - 1; - boolean any_user_buffer = false; + struct pipe_vertex_buffer *vbo; + unsigned i, max_index = (1 << 24) - 1; + boolean any_user_buffer = FALSE; if (count == r300->vertex_buffer_count && - memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0) + memcmp(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count) == 0) { return; + } + /* Check if the stride is aligned to the size of DWORD. */ for (i = 0; i < count; i++) { - pipe_buffer_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer); - if (r300_buffer_is_user_buffer(buffers[i].buffer)) - any_user_buffer = true; - max_index = MIN2(buffers[i].max_index, max_index); + if (buffers[i].buffer) { + if (buffers[i].stride % 4 != 0) { + // XXX Shouldn't we align the buffer? + fprintf(stderr, "r300_set_vertex_buffers: " + "Unaligned buffer stride %i isn't supported.\n", + buffers[i].stride); + assert(0); + abort(); + } + } } - for ( ; i < r300->vertex_buffer_count; i++) - pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); - - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); + for (i = 0; i < count; i++) { + /* Why, yes, I AM casting away constness. How did you know? */ + vbo = (struct pipe_vertex_buffer*)&buffers[i]; - r300->vertex_buffer_count = count; - r300->vertex_buffer_max_index = max_index; - r300->any_user_vbs = any_user_buffer; + /* Reference our buffer. */ + pipe_buffer_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); - if (r300->draw) { - draw_flush(r300->draw); - draw_set_vertex_buffers(r300->draw, count, buffers); - } -} - -static boolean r300_validate_aos(struct r300_context *r300) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->velems->velem; - int i; - - /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->velems->count; i++) { - if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || - util_format_get_blocksize(velem[i].src_format) % 4 != 0) { - return FALSE; + /* Skip NULL buffers */ + if (!buffers[i].buffer) { + continue; } - } - return TRUE; -} -static void r300_draw_emit_attrib(struct r300_context* r300, - enum attrib_emit emit, - enum interp_mode interp, - int index) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct tgsi_shader_info* info = &vs->info; - int output; - - output = draw_find_shader_output(r300->draw, - info->output_semantic_name[index], - info->output_semantic_index[index]); - draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); -} + if (r300_buffer_is_user_buffer(vbo->buffer)) { + any_user_buffer = TRUE; + } -static void r300_draw_emit_all_attribs(struct r300_context* r300) -{ - struct r300_vertex_shader* vs = r300->vs_state.state; - struct r300_shader_semantics* vs_outputs = &vs->outputs; - int i, gen_count; - - /* Position. */ - if (vs_outputs->pos != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->pos); - } else { - assert(0); - } + if (vbo->max_index == ~0) { + /* Bogus value from broken state tracker; hax it. */ + vbo->max_index = + (vbo->buffer->size - vbo->buffer_offset) / vbo->stride; + } - /* Point size. */ - if (vs_outputs->psize != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, - vs_outputs->psize); + max_index = MIN2(vbo->max_index, max_index); } - /* Colors. */ - for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, - vs_outputs->color[i]); - } + for (; i < r300->vertex_buffer_count; i++) { + /* Dereference any old buffers. */ + pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); } - /* XXX Back-face colors. */ + memcpy(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count); - /* Texture coordinates. */ - gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->generic[i]); - gen_count++; - } - } + r300->vertex_buffer_count = count; + r300->vertex_buffer_max_index = max_index; + r300->any_user_vbs = any_user_buffer; - /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { - r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, - vs_outputs->fog); - gen_count++; + if (r300->draw) { + draw_flush(r300->draw); + draw_set_vertex_buffers(r300->draw, count, buffers); } - - /* XXX magic */ - assert(gen_count <= 8); } /* Update the PSC tables. */ @@ -1193,70 +1179,13 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) vstream->count = (i >> 1) + 1; } -/* Update the PSC tables for SW TCL, using Draw. */ -static void r300_swtcl_vertex_psc(struct r300_context *r300, - struct r300_vertex_element_state *velems) -{ - struct r300_vertex_stream_state *vstream = &velems->vertex_stream; - struct r300_vertex_shader* vs = r300->vs_state.state; - struct vertex_info* vinfo = &r300->vertex_info; - uint16_t type, swizzle; - enum pipe_format format; - unsigned i, attrib_count; - int* vs_output_tab = vs->stream_loc_notcl; - - /* For each Draw attribute, route it to the fragment shader according - * to the vs_output_tab. */ - attrib_count = vinfo->num_attribs; - DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); - for (i = 0; i < attrib_count; i++) { - DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," - " vs_output_tab %d\n", vinfo->attrib[i].src_index, - vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, - vs_output_tab[i]); - } - - for (i = 0; i < attrib_count; i++) { - /* Make sure we have a proper destination for our attribute. */ - assert(vs_output_tab[i] != -1); - - format = draw_translate_vinfo_format(vinfo->attrib[i].emit); - - /* Obtain the type of data in this attribute. */ - type = r300_translate_vertex_data_type(format) | - vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; - - /* Obtain the swizzle for this attribute. Note that the default - * swizzle in the hardware is not XYZW! */ - swizzle = r300_translate_vertex_data_swizzle(format); - - /* Add the attribute to the PSC table. */ - if (i & 1) { - vstream->vap_prog_stream_cntl[i >> 1] |= type << 16; - vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; - } else { - vstream->vap_prog_stream_cntl[i >> 1] |= type; - vstream->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; - } - } - - /* Set the last vector in the PSC. */ - if (i) { - i -= 1; - } - vstream->vap_prog_stream_cntl[i >> 1] |= - (R300_LAST_VEC << (i & 1 ? 16 : 0)); - - vstream->count = (i >> 1) + 1; -} - static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { - struct r300_context *r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_vertex_element_state *velems; + unsigned i, size; assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); @@ -1265,12 +1194,21 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); if (r300screen->caps->has_tcl) { + /* Check if the format is aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + size = util_format_get_blocksize(attribs[i].src_format); + + if (size % 4 != 0) { + /* XXX Shouldn't we align the format? */ + fprintf(stderr, "r300_create_vertex_elements_state: " + "Unaligned format %s:%i isn't supported\n", + util_format_name(attribs[i].src_format), size); + assert(0); + abort(); + } + } + r300_vertex_psc(velems); - } else { - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300, velems); } } return velems; @@ -1293,12 +1231,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, draw_set_vertex_elements(r300->draw, velems->count, velems->velem); } - if (!r300_validate_aos(r300)) { - /* XXX We should fallback using draw. */ - assert(0); - abort(); - } - UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; } @@ -1419,7 +1351,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, /* 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 " + fprintf(stderr, "r300: Max size of the constant buffer is " "%i*4 floats.\n", max_size); abort(); } @@ -1432,10 +1364,14 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, if (r300screen->caps->has_tcl) { r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; r300->pvs_flush.dirty = TRUE; + } else if (r300->draw) { + draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, + 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, + buf->size); } - } - else if (shader == PIPE_SHADER_FRAGMENT) + } else if (shader == PIPE_SHADER_FRAGMENT) { r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } } void r300_init_state_functions(struct r300_context* r300) @@ -1473,7 +1409,9 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.bind_vertex_sampler_states = r300_lacks_vertex_textures; r300->context.delete_sampler_state = r300_delete_sampler_state; - r300->context.set_fragment_sampler_textures = r300_set_sampler_textures; + r300->context.set_fragment_sampler_views = r300_set_fragment_sampler_views; + r300->context.create_sampler_view = r300_create_sampler_view; + r300->context.sampler_view_destroy = r300_sampler_view_destroy; r300->context.set_scissor_state = r300_set_scissor_state; |