summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c')
-rw-r--r--lib/mesa/src/gallium/drivers/etnaviv/etnaviv_state.c210
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;
}