diff options
Diffstat (limited to 'lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c')
-rw-r--r-- | lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c | 210 |
1 files changed, 156 insertions, 54 deletions
diff --git a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c index 5de34a887..44b1c4f8f 100644 --- a/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -33,10 +33,13 @@ #include "etnaviv_clear_blit.h" #include "etnaviv_context.h" #include "etnaviv_format.h" +#include "etnaviv_rasterizer.h" +#include "etnaviv_screen.h" #include "etnaviv_shader.h" #include "etnaviv_surface.h" #include "etnaviv_translate.h" #include "etnaviv_util.h" +#include "etnaviv_zsa.h" #include "util/u_framebuffer.h" #include "util/u_helpers.h" #include "util/u_inlines.h" @@ -45,18 +48,18 @@ #include "util/u_upload_mgr.h" static void -etna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref *sr) +etna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref sr) { struct etna_context *ctx = etna_context(pctx); struct compiled_stencil_ref *cs = &ctx->stencil_ref; - ctx->stencil_ref_s = *sr; + ctx->stencil_ref_s = sr; for (unsigned i = 0; i < 2; i++) { cs->PE_STENCIL_CONFIG[i] = - VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr->ref_value[i]); + VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr.ref_value[i]); cs->PE_STENCIL_CONFIG_EXT[i] = - VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr->ref_value[!i]); + VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr.ref_value[!i]); } ctx->dirty |= ETNA_DIRTY_STENCIL_REF; } @@ -78,27 +81,31 @@ etna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) static void etna_set_constant_buffer(struct pipe_context *pctx, - enum pipe_shader_type shader, uint index, + enum pipe_shader_type shader, uint index, bool take_ownership, const struct pipe_constant_buffer *cb) { struct etna_context *ctx = etna_context(pctx); + struct etna_constbuf_state *so = &ctx->constant_buffer[shader]; assert(index < ETNA_MAX_CONST_BUF); - util_copy_constant_buffer(&ctx->constant_buffer[shader][index], cb); + util_copy_constant_buffer(&so->cb[index], cb, take_ownership); - /* Note that the state tracker can unbind constant buffers by + /* Note that the gallium frontends can unbind constant buffers by * passing NULL here. */ - if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) + if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) { + so->enabled_mask &= ~(1 << index); return; + } assert(index != 0 || cb->user_buffer != NULL); if (!cb->buffer) { - struct pipe_constant_buffer *cb = &ctx->constant_buffer[shader][index]; + struct pipe_constant_buffer *cb = &so->cb[index]; u_upload_data(pctx->const_uploader, 0, cb->buffer_size, 16, cb->user_buffer, &cb->buffer_offset, &cb->buffer); } + so->enabled_mask |= 1 << index; ctx->dirty |= ETNA_DIRTY_CONSTBUF; } @@ -124,6 +131,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, const struct pipe_framebuffer_state *fb) { struct etna_context *ctx = etna_context(pctx); + struct etna_screen *screen = ctx->screen; struct compiled_framebuffer_state *cs = &ctx->framebuffer; int nr_samples_color = -1; int nr_samples_depth = -1; @@ -152,7 +160,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | VIVS_PE_COLOR_FORMAT_OVERWRITE | COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED) | - COND(color_supertiled && ctx->specs.halti >= 5, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW); + COND(color_supertiled && screen->specs.halti >= 5, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW); /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state * but only if we set the bits above. */ @@ -168,13 +176,13 @@ etna_set_framebuffer_state(struct pipe_context *pctx, cbuf->surf.offset, cbuf->surf.stride * 4); } - if (ctx->specs.pixel_pipes == 1) { + if (screen->specs.pixel_pipes == 1) { cs->PE_COLOR_ADDR = cbuf->reloc[0]; cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } else { /* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */ - assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || ctx->specs.single_buffer); - for (int i = 0; i < ctx->specs.pixel_pipes; i++) { + assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer); + for (int i = 0; i < screen->specs.pixel_pipes; i++) { cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i]; cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } @@ -195,7 +203,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, if (cbuf->level->ts_compress_fmt >= 0) { /* overwrite bit breaks v1/v2 compression */ - if (!ctx->specs.v4_compression) + if (!screen->specs.v4_compression) cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE; ts_mem_config |= @@ -211,7 +219,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, cs->PS_CONTROL = COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0); cs->PS_CONTROL_EXT = - VIVS_PS_CONTROL_EXT_OUTPUT_MODE0(translate_output_mode(cbuf->base.format, ctx->specs.halti >= 5)); + VIVS_PS_CONTROL_EXT_OUTPUT_MODE0(translate_output_mode(cbuf->base.format, screen->specs.halti >= 5)); } else { /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the @@ -222,7 +230,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, cs->TS_COLOR_SURFACE_BASE.bo = NULL; cs->PE_COLOR_ADDR = ctx->dummy_rt_reloc; - for (int i = 0; i < ctx->specs.pixel_pipes; i++) + for (int i = 0; i < screen->specs.pixel_pipes; i++) cs->PE_PIPE_COLOR_ADDR[i] = ctx->dummy_rt_reloc; } @@ -243,17 +251,15 @@ etna_set_framebuffer_state(struct pipe_context *pctx, depth_format | COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) | VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z | - VIVS_PE_DEPTH_CONFIG_UNK18 | /* something to do with clipping? */ - COND(ctx->specs.halti >= 5, VIVS_PE_DEPTH_CONFIG_DISABLE_ZS) /* Needs to be enabled on GC7000, otherwise depth writes hang w/ TS - apparently it does something else now */ - ; + VIVS_PE_DEPTH_CONFIG_UNK18; /* something to do with clipping? */ /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ /* merged with depth_stencil_alpha */ - if (ctx->specs.pixel_pipes == 1) { + if (screen->specs.pixel_pipes == 1) { cs->PE_DEPTH_ADDR = zsbuf->reloc[0]; cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } else { - for (int i = 0; i < ctx->specs.pixel_pipes; i++) { + for (int i = 0; i < screen->specs.pixel_pipes; i++) { cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i]; cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } @@ -342,14 +348,6 @@ etna_set_framebuffer_state(struct pipe_context *pctx, break; } - /* Scissor setup */ - cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */ - cs->SE_SCISSOR_TOP = 0; - cs->SE_SCISSOR_RIGHT = (fb->width << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT; - cs->SE_SCISSOR_BOTTOM = (fb->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; - cs->SE_CLIP_RIGHT = (fb->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; - cs->SE_CLIP_BOTTOM = (fb->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; - cs->TS_MEM_CONFIG = ts_mem_config; cs->PE_MEM_CONFIG = pe_mem_config; @@ -358,7 +356,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, * single buffer when this feature is available. * note: the blob will use 2 in some situations, figure out why? */ - pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(ctx->specs.single_buffer ? 3 : 0); + pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(screen->specs.single_buffer ? 3 : 0); cs->PE_LOGIC_OP = pe_logic_op; /* keep copy of original structure */ @@ -378,19 +376,10 @@ etna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, unsigned num_scissors, const struct pipe_scissor_state *ss) { struct etna_context *ctx = etna_context(pctx); - struct compiled_scissor_state *cs = &ctx->scissor; assert(ss->minx <= ss->maxx); assert(ss->miny <= ss->maxy); - /* note that this state is only used when rasterizer_state->scissor is on */ - ctx->scissor_s = *ss; - cs->SE_SCISSOR_LEFT = (ss->minx << 16); - cs->SE_SCISSOR_TOP = (ss->miny << 16); - cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT; - cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; - cs->SE_CLIP_RIGHT = (ss->maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; - cs->SE_CLIP_BOTTOM = (ss->maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; - + ctx->scissor = *ss; ctx->dirty |= ETNA_DIRTY_SCISSOR; } @@ -425,14 +414,10 @@ etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, /* Compute scissor rectangle (fixp) from viewport. * Make sure left is always < right and top always < bottom. */ - cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f)); - cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f)); - uint32_t right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); - uint32_t bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); - cs->SE_SCISSOR_RIGHT = right_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT; - cs->SE_SCISSOR_BOTTOM = bottom_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM; - cs->SE_CLIP_RIGHT = right_fixp + ETNA_SE_CLIP_MARGIN_RIGHT; - cs->SE_CLIP_BOTTOM = bottom_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM; + cs->SE_SCISSOR_LEFT = MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f); + cs->SE_SCISSOR_TOP = MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f); + cs->SE_SCISSOR_RIGHT = ceilf(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); + cs->SE_SCISSOR_BOTTOM = ceilf(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */ cs->PE_DEPTH_FAR = fui(1.0); @@ -441,12 +426,15 @@ etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, static void etna_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, - unsigned num_buffers, const struct pipe_vertex_buffer *vb) + unsigned num_buffers, unsigned unbind_num_trailing_slots, bool take_ownership, + const struct pipe_vertex_buffer *vb) { struct etna_context *ctx = etna_context(pctx); struct etna_vertexbuf_state *so = &ctx->vertex_buffer; - util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, num_buffers); + util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, + num_buffers, unbind_num_trailing_slots, + take_ownership); so->count = util_last_bit(so->enabled_mask); for (unsigned idx = start_slot; idx < start_slot + num_buffers; ++idx) { @@ -524,14 +512,16 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, unsigned num_elements, const struct pipe_vertex_element *elements) { struct etna_context *ctx = etna_context(pctx); + struct etna_screen *screen = ctx->screen; struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state); if (!cs) return NULL; - if (num_elements > ctx->specs.vertex_max_elements) { + if (num_elements > screen->specs.vertex_max_elements) { BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements, - ctx->specs.vertex_max_elements); + screen->specs.vertex_max_elements); + FREE(cs); return NULL; } @@ -554,7 +544,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, start_offset = elements[idx].src_offset; /* guaranteed by PIPE_CAP_MAX_VERTEX_BUFFERS */ - assert(buffer_idx < ctx->specs.stream_count); + assert(buffer_idx < screen->specs.stream_count); /* maximum vertex size is 256 bytes */ assert(element_size != 0 && (end_offset - start_offset) < 256); @@ -570,7 +560,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, assert(format_type != ETNA_NO_MATCH); assert(normalize != ETNA_NO_MATCH); - if (ctx->specs.halti < 5) { + if (screen->specs.halti < 5) { cs->FE_VERTEX_ELEMENT_CONFIG[idx] = COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) | format_type | @@ -624,6 +614,14 @@ etna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve) ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS; } +static void +etna_set_stream_output_targets(struct pipe_context *pctx, + unsigned num_targets, struct pipe_stream_output_target **targets, + const unsigned *offsets) +{ + /* stub */ +} + static bool etna_update_ts_config(struct etna_context *ctx) { @@ -660,6 +658,101 @@ etna_update_ts_config(struct etna_context *ctx) return true; } +static bool +etna_update_clipping(struct etna_context *ctx) +{ + const struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); + const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; + + /* clip framebuffer against viewport */ + uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT; + uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP; + uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT); + uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM); + + /* clip against scissor */ + if (rasterizer->scissor) { + scissor_left = MAX2(ctx->scissor.minx, scissor_left); + scissor_top = MAX2(ctx->scissor.miny, scissor_top); + scissor_right = MIN2(ctx->scissor.maxx, scissor_right); + scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom); + } + + ctx->clipping.minx = scissor_left; + ctx->clipping.miny = scissor_top; + ctx->clipping.maxx = scissor_right; + ctx->clipping.maxy = scissor_bottom; + + ctx->dirty |= ETNA_DIRTY_SCISSOR_CLIP; + + return true; +} + +static bool +etna_update_zsa(struct etna_context *ctx) +{ + struct compiled_shader_state *shader_state = &ctx->shader_state; + struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa; + struct etna_zsa_state *zsa = etna_zsa_state(zsa_state); + struct etna_screen *screen = ctx->screen; + uint32_t new_pe_depth, new_ra_depth; + bool late_z_write = false, early_z_write = false, + late_z_test = false, early_z_test = false; + + if (zsa->z_write_enabled) { + if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) && + !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) && + !zsa->stencil_enabled && + !zsa_state->alpha_enabled && + !shader_state->writes_z && + !shader_state->uses_discard) + early_z_write = true; + else + late_z_write = true; + } + + if (zsa->z_test_enabled) { + if (!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) && + !zsa->stencil_modified && + !shader_state->writes_z) + early_z_test = true; + else + late_z_test = true; + } + + new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ? + /* compare funcs have 1 to 1 mapping */ + zsa_state->depth_func : PIPE_FUNC_ALWAYS) | + COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) | + COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) | + COND(!late_z_write && !late_z_test && !zsa->stencil_enabled, + VIVS_PE_DEPTH_CONFIG_DISABLE_ZS); + + /* blob sets this to 0x40000031 on GC7000, seems to make no difference, + * but keep it in mind if depth behaves strangely. */ + new_ra_depth = 0x0000030 | + COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE); + + if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)) { + if (!early_z_write) + new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE; + /* The new early hierarchical test seems to only work properly if depth + * is also written from the early stage. + */ + if (late_z_test || (early_z_test && late_z_write)) + new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE; + } + + if (new_pe_depth != zsa->PE_DEPTH_CONFIG || + new_ra_depth != zsa->RA_DEPTH_CONFIG) + ctx->dirty |= ETNA_DIRTY_ZSA; + + zsa->PE_DEPTH_CONFIG = new_pe_depth; + zsa->RA_DEPTH_CONFIG = new_ra_depth; + + return true; +} + struct etna_state_updater { bool (*update)(struct etna_context *ctx); uint32_t dirty; @@ -680,6 +773,13 @@ static const struct etna_state_updater etna_state_updates[] = { }, { etna_update_ts_config, ETNA_DIRTY_DERIVE_TS, + }, + { + etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | + ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT, + }, + { + etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER, } }; @@ -721,4 +821,6 @@ etna_state_init(struct pipe_context *pctx) pctx->create_vertex_elements_state = etna_vertex_elements_state_create; pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete; pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind; + + pctx->set_stream_output_targets = etna_set_stream_output_targets; } |