X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_state.c;h=51c47770fe04edbc808c96aea19b769ad36e540e;hb=6eae8e4482b6d5e3d46e10473b05f16381736a5a;hp=bd4c2766cb1426859c0fe11a538ef78ee8759a01;hpb=fc1dd5ce1de8b9c0a02b9fb08aaeac0c38372e65;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index bd4c2766cb1..51c47770fe0 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -34,11 +34,12 @@ #include "r300_context.h" #include "r300_reg.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" #include "r300_state_inlines.h" #include "r300_fs.h" +#include "r300_texture.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. */ @@ -219,7 +220,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* Enable reading from the colorbuffer. */ blend->blend_control |= R300_READ_ENABLE; - if (r300_screen(r300_context(pipe)->context.screen)->caps->is_r500) { + if (r300screen->caps.is_r500) { /* Optimization: Depending on incoming pixels, we can * conditionally disable the reading in hardware... */ if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN && @@ -308,7 +309,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* Color channel masks for all MRTs. */ blend->color_channel_mask = bgra_cmask(state->rt[0].colormask); - if (r300screen->caps->is_r500 && state->independent_blend_enable) { + if (r300screen->caps.is_r500 && state->independent_blend_enable) { if (state->rt[1].blend_enable) { blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4; } @@ -320,10 +321,17 @@ static void* r300_create_blend_state(struct pipe_context* pipe, } } + /* Neither fglrx nor classic r300 ever set this, regardless of dithering + * state. Since it's an optional implementation detail, we can leave it + * out and never dither. + * + * This could be revisited if we ever get quality or conformance hints. + * if (state->dither) { blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT | - R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; + R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; } + */ return (void*)blend; } @@ -356,7 +364,6 @@ static void r300_set_blend_color(struct pipe_context* pipe, const struct pipe_blend_color* color) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_color_state* state = (struct r300_blend_color_state*)r300->blend_color_state.state; union util_color uc; @@ -372,7 +379,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, float_to_fixed10(color->color[2]) | (float_to_fixed10(color->color[1]) << 16); - r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2; + r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2; r300->blend_color_state.dirty = TRUE; } @@ -383,7 +390,7 @@ static void r300_set_clip_state(struct pipe_context* pipe, r300->clip = *state; - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); r300->clip_state.size = 29; } else { @@ -404,8 +411,7 @@ static void* r300_create_dsa_state(struct pipe_context* pipe, const struct pipe_depth_stencil_alpha_state* state) { - struct r300_capabilities *caps = - r300_screen(r300_context(pipe)->context.screen)->caps; + struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps; struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state); /* Depth test setup. */ @@ -439,6 +445,8 @@ static void* (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT); if (state->stencil[1].enabled) { + dsa->two_sided = TRUE; + dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK; dsa->z_stencil_control |= (r300_translate_depth_stencil_function(state->stencil[1].func) << @@ -450,14 +458,16 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - if (caps->is_r500) - { + dsa->stencil_ref_bf = + (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | + (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT); + + if (caps->is_r500) { dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; - dsa->stencil_ref_bf = - (state->stencil[1].valuemask << - R300_STENCILMASK_SHIFT) | - (state->stencil[1].writemask << - R300_STENCILWRITEMASK_SHIFT); + } else { + dsa->stencil_ref_bf_fallback = + (state->stencil[0].valuemask != state->stencil[1].valuemask || + state->stencil[0].writemask != state->stencil[1].writemask); } } } @@ -478,13 +488,33 @@ static void* return (void*)dsa; } +static void r300_update_stencil_ref_fallback_status(struct r300_context *r300) +{ + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + if (r300->screen->caps.is_r500) { + return; + } + + r300->stencil_ref_bf_fallback = + dsa->stencil_ref_bf_fallback || + (dsa->two_sided && + r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]); +} + /* Bind DSA state. */ static void r300_bind_dsa_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); + if (!state) { + return; + } + UPDATE_STATE(state, r300->dsa_state); + + r300_update_stencil_ref_fallback_status(r300); } /* Free DSA state. */ @@ -498,8 +528,11 @@ 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; + + r300_update_stencil_ref_fallback_status(r300); } /* This switcheroo is needed just because of goddamned MACRO_SWITCH. */ @@ -522,46 +555,46 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, continue; } - tex = (struct r300_texture*)old_state->cbufs[i]->texture; + tex = r300_texture(old_state->cbufs[i]->texture); if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + 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 && (!new_state->zsbuf || old_state->zsbuf->texture != new_state->zsbuf->texture)) { - tex = (struct r300_texture*)old_state->zsbuf->texture; + tex = r300_texture(old_state->zsbuf->texture); if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], - tex->microtile != 0, - tex->macrotile != 0); + tex->microtile, + tex->macrotile); } } /* Set tiling flags for new surfaces. */ for (i = 0; i < new_state->nr_cbufs; i++) { - tex = (struct r300_texture*)new_state->cbufs[i]->texture; + tex = r300_texture(new_state->cbufs[i]->texture); level = new_state->cbufs[i]->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + 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; + tex = r300_texture(new_state->zsbuf->texture); level = new_state->zsbuf->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + 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]); } } @@ -570,28 +603,26 @@ static void const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(pipe->screen); struct pipe_framebuffer_state *old_state = r300->fb_state.state; 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; } - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { max_width = max_height = 4096; - } else if (r300screen->caps->is_r400) { + } else if (r300->screen->caps.is_r400) { max_width = max_height = 4021; } else { max_width = max_height = 2560; } 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; } @@ -610,16 +641,13 @@ static void if (!!old_state->zsbuf != !!state->zsbuf) { r300->dsa_state.dirty = TRUE; } - if (!r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; - } r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 8; + (state->zsbuf ? 10 : 0) + 11; /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -651,9 +679,6 @@ static void* r300_create_fs_state(struct pipe_context* pipe, fs->state = *shader; fs->state.tokens = tgsi_dup_tokens(shader->tokens); - tgsi_scan_shader(shader->tokens, &fs->info); - r300_shader_read_fs_inputs(&fs->info, &fs->inputs); - return (void*)fs; } @@ -712,7 +737,6 @@ static void r300_set_polygon_stipple(struct pipe_context* pipe, static void* r300_create_rs_state(struct pipe_context* pipe, const struct pipe_rasterizer_state* state) { - struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); /* Copy rasterizer state for Draw. */ @@ -725,7 +749,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, #endif /* If no TCL engine is present, turn off the HW TCL. */ - if (!r300screen->caps->has_tcl) { + if (!r300_screen(pipe->screen)->caps.has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; } @@ -806,6 +830,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } + rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF; + return (void*)rs; } @@ -814,7 +840,6 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; - boolean scissor_was_enabled = r300->scissor_enabled; if (r300->draw) { draw_flush(r300->draw); @@ -823,18 +848,12 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; - r300->scissor_enabled = rs->rs.scissor; } else { r300->polygon_offset_enabled = FALSE; - r300->scissor_enabled = FALSE; } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); - - if (scissor_was_enabled != r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; - } + r300->rs_state.size = 19 + (r300->polygon_offset_enabled ? 5 : 0); } /* Free rasterizer state. */ @@ -849,6 +868,7 @@ static void* { struct r300_context* r300 = r300_context(pipe); struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state); + boolean is_r500 = r300->screen->caps.is_r500; int lod_bias; union util_color uc; @@ -864,6 +884,8 @@ static void* state->min_mip_filter, state->max_anisotropy > 0); + sampler->filter0 |= r300_anisotropy(state->max_anisotropy); + /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */ /* We must pass these to the merge function to clamp them properly. */ sampler->min_lod = MAX2((unsigned)state->min_lod, 0); @@ -873,13 +895,19 @@ static void* sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT; - sampler->filter1 |= r300_anisotropy(state->max_anisotropy); + /* This is very high quality anisotropic filtering for R5xx. + * It's good for benchmarking the performance of texturing but + * in practice we don't want to slow down the driver because it's + * a pretty good performance killer. Feel free to play with it. */ + if (DBG_ON(r300, DBG_ANISOHQ) && is_r500) { + sampler->filter1 |= r500_anisotropy(state->max_anisotropy); + } util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); sampler->border_color = uc.ui; /* R500-specific fixups and optimizations */ - if (r300_screen(r300->context.screen)->caps->is_r500) { + if (r300->screen->caps.is_r500) { sampler->filter1 |= R500_BORDER_FIX; } @@ -893,13 +921,14 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; + unsigned tex_units = r300->screen->caps.num_tex_units; - if (count > 8) { + if (count > tex_units) { return; } memcpy(state->sampler_states, states, sizeof(void*) * count); - state->sampler_count = count; + state->sampler_state_count = count; r300->textures_state.dirty = TRUE; @@ -923,30 +952,39 @@ 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; + unsigned tex_units = r300->screen->caps.num_tex_units; + boolean is_r500 = r300->screen->caps.is_r500; boolean dirty_tex = FALSE; - /* XXX magic num */ - if (count > 8) { + if (count > tex_units) { return; } 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->sampler_views[i]->base != views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->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 = r300_texture(views[i]->texture); + if (!is_r500 && texture->uses_pitch) { /* XXX It would be nice to re-emit just 1 constant, * XXX not all of them */ r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -954,14 +992,15 @@ 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); + for (i = count; i < tex_units; i++) { + if (state->sampler_views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + NULL); } } - state->texture_count = count; + state->sampler_view_count = count; r300->textures_state.dirty = TRUE; @@ -970,6 +1009,48 @@ 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_resource *texture, + const struct pipe_sampler_view *templ) +{ + struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); + struct r300_texture *tex = r300_texture(texture); + unsigned char swizzle[4]; + + if (view) { + view->base = *templ; + view->base.reference.count = 1; + view->base.context = pipe; + view->base.texture = NULL; + pipe_resource_reference(&view->base.texture, texture); + + swizzle[0] = templ->swizzle_r; + swizzle[1] = templ->swizzle_g; + swizzle[2] = templ->swizzle_b; + swizzle[3] = templ->swizzle_a; + + /* XXX Enable swizzles when they become supported. Now we get RGBA + * everywhere. And do testing! */ + view->format = tex->tx_format; + view->format.format1 |= r300_translate_texformat(templ->format, + 0); /*swizzle);*/ + if (r300_screen(pipe->screen)->caps.is_r500) { + view->format.format2 |= r500_tx_format_msb_bit(templ->format); + } + } + + return (struct pipe_sampler_view*)view; +} + +static void +r300_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_resource_reference(&view->texture, NULL); + FREE(view); +} + static void r300_set_scissor_state(struct pipe_context* pipe, const struct pipe_scissor_state* state) { @@ -978,9 +1059,7 @@ static void r300_set_scissor_state(struct pipe_context* pipe, memcpy(r300->scissor_state.state, state, sizeof(struct pipe_scissor_state)); - if (r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; - } + r300->scissor_state.dirty = TRUE; } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -1021,7 +1100,7 @@ static void r300_set_viewport_state(struct pipe_context* pipe, } r300->viewport_state.dirty = TRUE; - if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { + if (r300->fs && r300->fs->shader->inputs.wpos != ATTR_UNUSED) { r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; } } @@ -1031,104 +1110,75 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - unsigned i, max_index = ~0; + struct pipe_vertex_buffer *vbo; + unsigned i, max_index = (1 << 24) - 1; + boolean any_user_buffer = FALSE; - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); + if (count == r300->vertex_buffer_count && + 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++) { - 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); + abort(); + } + } } - r300->vertex_buffer_count = count; - r300->vertex_buffer_max_index = max_index; + for (i = 0; i < count; i++) { + /* Why, yes, I AM casting away constness. How did you know? */ + vbo = (struct pipe_vertex_buffer*)&buffers[i]; - if (r300->draw) { - draw_flush(r300->draw); - draw_set_vertex_buffers(r300->draw, count, buffers); - } -} + /* Reference our buffer. */ + pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); -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. */ + /* TODO - more hax - fixes doom3 from almos on irc */ + if (!vbo->stride) { + fprintf(stderr, "r300: got a VBO with stride 0 fixing up to stide 4\n"); + vbo->stride = 4; + } + vbo->max_index = + (vbo->buffer->width0 - 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_resource_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. */ @@ -1139,7 +1189,11 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) enum pipe_format format; unsigned i; - assert(velems->count <= 16); + if (velems->count > 16) { + fprintf(stderr, "r300: More than 16 vertex elements are not supported," + " requested %i, using 16.\n", velems->count); + velems->count = 16; + } /* Vertex shaders have no semantics on their inputs, * so PSC should just route stuff based on the vertex elements, @@ -1170,70 +1224,12 @@ 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); @@ -1241,13 +1237,22 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, velems->count = count; memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); - if (r300screen->caps->has_tcl) { + if (r300_screen(pipe->screen)->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; @@ -1270,12 +1275,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; } @@ -1291,10 +1290,13 @@ static void* r300_create_vs_state(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); - r300_vertex_shader_common_init(vs, shader); - if (r300_screen(pipe->screen)->caps->has_tcl) { - r300_translate_vertex_shader(r300, vs); + /* Copy state directly into shader. */ + vs->state = *shader; + vs->state.tokens = tgsi_dup_tokens(shader->tokens); + + if (r300->screen->caps.has_tcl) { + r300_translate_vertex_shader(r300, vs, vs->state.tokens); } else { vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } @@ -1327,7 +1329,7 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) /* The majority of the RS block bits is dependent on the vertex shader. */ r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { r300->vs_state.dirty = TRUE; r300->vs_state.size = vs->code.length + 9; @@ -1346,7 +1348,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) struct r300_context* r300 = r300_context(pipe); struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { rc_constants_destroy(&vs->code.constants); } else { draw_delete_vertex_shader(r300->draw, @@ -1359,21 +1361,21 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) static void r300_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_resource *buf) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen *r300screen = r300_screen(pipe->screen); + struct pipe_transfer *tr; 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) + if (buf == NULL || buf->width0 == 0 || + (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL) { r300->shader_constants[shader].count = 0; return; } - assert((buf->size % 4 * sizeof(float)) == 0); + assert((buf->width0 % 4 * sizeof(float)) == 0); /* Check the size of the constant buffer. */ switch (shader) { @@ -1381,10 +1383,10 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, max_size = 256; break; case PIPE_SHADER_FRAGMENT: - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { max_size = 256; /* XXX Implement emission of r400's extended constant buffer. */ - /*} else if (r300screen->caps->is_r400) { + /*} else if (r300->screen->caps.is_r400) { max_size = 64;*/ } else { max_size = 32; @@ -1395,24 +1397,28 @@ 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 " + if (buf->width0 > (sizeof(float) * 4 * max_size)) { + fprintf(stderr, "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); + memcpy(r300->shader_constants[shader].constants, mapped, buf->width0); + r300->shader_constants[shader].count = buf->width0 / (4 * sizeof(float)); + pipe_buffer_unmap(pipe, buf, tr); if (shader == PIPE_SHADER_VERTEX) { - if (r300screen->caps->has_tcl) { + if (r300->screen->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->width0); } - } - 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) @@ -1450,7 +1456,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;