101e04c3fSmrg/* 201e04c3fSmrg * Copyright (c) 2012-2015 Etnaviv Project 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the 1201e04c3fSmrg * next paragraph) shall be included in all copies or substantial portions 1301e04c3fSmrg * of the Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2101e04c3fSmrg * DEALINGS IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Wladimir J. van der Laan <laanwj@gmail.com> 2501e04c3fSmrg * Christian Gmeiner <christian.gmeiner@gmail.com> 2601e04c3fSmrg */ 2701e04c3fSmrg 2801e04c3fSmrg#include "etnaviv_state.h" 2901e04c3fSmrg 3001e04c3fSmrg#include "hw/common.xml.h" 3101e04c3fSmrg 3201e04c3fSmrg#include "etnaviv_blend.h" 3301e04c3fSmrg#include "etnaviv_clear_blit.h" 3401e04c3fSmrg#include "etnaviv_context.h" 3501e04c3fSmrg#include "etnaviv_format.h" 367ec681f3Smrg#include "etnaviv_rasterizer.h" 377ec681f3Smrg#include "etnaviv_screen.h" 3801e04c3fSmrg#include "etnaviv_shader.h" 3901e04c3fSmrg#include "etnaviv_surface.h" 4001e04c3fSmrg#include "etnaviv_translate.h" 4101e04c3fSmrg#include "etnaviv_util.h" 427ec681f3Smrg#include "etnaviv_zsa.h" 4301e04c3fSmrg#include "util/u_framebuffer.h" 4401e04c3fSmrg#include "util/u_helpers.h" 4501e04c3fSmrg#include "util/u_inlines.h" 4601e04c3fSmrg#include "util/u_math.h" 4701e04c3fSmrg#include "util/u_memory.h" 487ec681f3Smrg#include "util/u_upload_mgr.h" 4901e04c3fSmrg 5001e04c3fSmrgstatic void 517ec681f3Smrgetna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref sr) 5201e04c3fSmrg{ 5301e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 5401e04c3fSmrg struct compiled_stencil_ref *cs = &ctx->stencil_ref; 5501e04c3fSmrg 567ec681f3Smrg ctx->stencil_ref_s = sr; 5701e04c3fSmrg 587ec681f3Smrg for (unsigned i = 0; i < 2; i++) { 597ec681f3Smrg cs->PE_STENCIL_CONFIG[i] = 607ec681f3Smrg VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr.ref_value[i]); 617ec681f3Smrg cs->PE_STENCIL_CONFIG_EXT[i] = 627ec681f3Smrg VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr.ref_value[!i]); 637ec681f3Smrg } 6401e04c3fSmrg ctx->dirty |= ETNA_DIRTY_STENCIL_REF; 6501e04c3fSmrg} 6601e04c3fSmrg 6701e04c3fSmrgstatic void 6801e04c3fSmrgetna_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *pcs) 6901e04c3fSmrg{ 7001e04c3fSmrg /* NOOP */ 7101e04c3fSmrg} 7201e04c3fSmrg 7301e04c3fSmrgstatic void 7401e04c3fSmrgetna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 7501e04c3fSmrg{ 7601e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 7701e04c3fSmrg 7801e04c3fSmrg ctx->sample_mask = sample_mask; 7901e04c3fSmrg ctx->dirty |= ETNA_DIRTY_SAMPLE_MASK; 8001e04c3fSmrg} 8101e04c3fSmrg 8201e04c3fSmrgstatic void 8301e04c3fSmrgetna_set_constant_buffer(struct pipe_context *pctx, 847ec681f3Smrg enum pipe_shader_type shader, uint index, bool take_ownership, 8501e04c3fSmrg const struct pipe_constant_buffer *cb) 8601e04c3fSmrg{ 8701e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 887ec681f3Smrg struct etna_constbuf_state *so = &ctx->constant_buffer[shader]; 8901e04c3fSmrg 907ec681f3Smrg assert(index < ETNA_MAX_CONST_BUF); 9101e04c3fSmrg 927ec681f3Smrg util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 9301e04c3fSmrg 947ec681f3Smrg /* Note that the gallium frontends can unbind constant buffers by 9501e04c3fSmrg * passing NULL here. */ 967ec681f3Smrg if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) { 977ec681f3Smrg so->enabled_mask &= ~(1 << index); 9801e04c3fSmrg return; 997ec681f3Smrg } 10001e04c3fSmrg 1017ec681f3Smrg assert(index != 0 || cb->user_buffer != NULL); 10201e04c3fSmrg 1037ec681f3Smrg if (!cb->buffer) { 1047ec681f3Smrg struct pipe_constant_buffer *cb = &so->cb[index]; 1057ec681f3Smrg u_upload_data(pctx->const_uploader, 0, cb->buffer_size, 16, cb->user_buffer, &cb->buffer_offset, &cb->buffer); 1067ec681f3Smrg } 1077ec681f3Smrg 1087ec681f3Smrg so->enabled_mask |= 1 << index; 10901e04c3fSmrg ctx->dirty |= ETNA_DIRTY_CONSTBUF; 11001e04c3fSmrg} 11101e04c3fSmrg 11201e04c3fSmrgstatic void 1137ec681f3Smrgetna_update_render_resource(struct pipe_context *pctx, struct etna_resource *base) 11401e04c3fSmrg{ 1157ec681f3Smrg struct etna_resource *to = base, *from = base; 1167ec681f3Smrg 1177ec681f3Smrg if (base->texture && etna_resource_newer(etna_resource(base->texture), base)) 1187ec681f3Smrg from = etna_resource(base->texture); 11901e04c3fSmrg 1207ec681f3Smrg if (base->render) 1217ec681f3Smrg to = etna_resource(base->render); 1227ec681f3Smrg 1237ec681f3Smrg if ((to != from) && etna_resource_older(to, from)) { 1247ec681f3Smrg etna_copy_resource(pctx, &to->base, &from->base, 0, base->base.last_level); 1257ec681f3Smrg to->seqno = from->seqno; 12601e04c3fSmrg } 12701e04c3fSmrg} 12801e04c3fSmrg 12901e04c3fSmrgstatic void 13001e04c3fSmrgetna_set_framebuffer_state(struct pipe_context *pctx, 1317ec681f3Smrg const struct pipe_framebuffer_state *fb) 13201e04c3fSmrg{ 13301e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 1347ec681f3Smrg struct etna_screen *screen = ctx->screen; 13501e04c3fSmrg struct compiled_framebuffer_state *cs = &ctx->framebuffer; 13601e04c3fSmrg int nr_samples_color = -1; 13701e04c3fSmrg int nr_samples_depth = -1; 13801e04c3fSmrg 13901e04c3fSmrg /* Set up TS as well. Warning: this state is used by both the RS and PE */ 14001e04c3fSmrg uint32_t ts_mem_config = 0; 1417ec681f3Smrg uint32_t pe_mem_config = 0; 1427ec681f3Smrg uint32_t pe_logic_op = 0; 14301e04c3fSmrg 1447ec681f3Smrg if (fb->nr_cbufs > 0) { /* at least one color buffer? */ 1457ec681f3Smrg struct etna_surface *cbuf = etna_surface(fb->cbufs[0]); 14601e04c3fSmrg struct etna_resource *res = etna_resource(cbuf->base.texture); 14701e04c3fSmrg bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; 1487ec681f3Smrg uint32_t fmt = translate_pe_format(cbuf->base.format); 14901e04c3fSmrg 15001e04c3fSmrg assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ 1517ec681f3Smrg etna_update_render_resource(pctx, etna_resource(cbuf->prsc)); 1527ec681f3Smrg 1537ec681f3Smrg if (fmt >= PE_FORMAT_R16F) 1547ec681f3Smrg cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT(fmt) | 1557ec681f3Smrg VIVS_PE_COLOR_FORMAT_FORMAT_MASK; 1567ec681f3Smrg else 1577ec681f3Smrg cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(fmt); 15801e04c3fSmrg 1597ec681f3Smrg cs->PE_COLOR_FORMAT |= 16001e04c3fSmrg VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | 16101e04c3fSmrg VIVS_PE_COLOR_FORMAT_OVERWRITE | 16201e04c3fSmrg COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED) | 1637ec681f3Smrg COND(color_supertiled && screen->specs.halti >= 5, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW); 16401e04c3fSmrg /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and 16501e04c3fSmrg * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state 16601e04c3fSmrg * but only if we set the bits above. */ 16701e04c3fSmrg /* merged with depth_stencil_alpha */ 16801e04c3fSmrg if ((cbuf->surf.offset & 63) || 16901e04c3fSmrg (((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) { 17001e04c3fSmrg /* XXX Must make temporary surface here. 17101e04c3fSmrg * Need the same mechanism on gc2000 when we want to do mipmap 17201e04c3fSmrg * generation by 17301e04c3fSmrg * rendering to levels > 1 due to multitiled / tiled conversion. */ 17401e04c3fSmrg BUG("Alignment error, trying to render to offset %08x with tile " 17501e04c3fSmrg "stride %i", 17601e04c3fSmrg cbuf->surf.offset, cbuf->surf.stride * 4); 17701e04c3fSmrg } 17801e04c3fSmrg 1797ec681f3Smrg if (screen->specs.pixel_pipes == 1) { 18001e04c3fSmrg cs->PE_COLOR_ADDR = cbuf->reloc[0]; 18101e04c3fSmrg cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 18201e04c3fSmrg } else { 18301e04c3fSmrg /* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */ 1847ec681f3Smrg assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer); 1857ec681f3Smrg for (int i = 0; i < screen->specs.pixel_pipes; i++) { 18601e04c3fSmrg cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i]; 18701e04c3fSmrg cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 18801e04c3fSmrg } 18901e04c3fSmrg } 19001e04c3fSmrg cs->PE_COLOR_STRIDE = cbuf->surf.stride; 19101e04c3fSmrg 19201e04c3fSmrg if (cbuf->surf.ts_size) { 19301e04c3fSmrg cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value; 1947ec681f3Smrg cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32; 19501e04c3fSmrg 19601e04c3fSmrg cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc; 19701e04c3fSmrg cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 19801e04c3fSmrg 19901e04c3fSmrg cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0]; 20001e04c3fSmrg cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 20101e04c3fSmrg 2027ec681f3Smrg pe_mem_config |= VIVS_PE_MEM_CONFIG_COLOR_TS_MODE(cbuf->level->ts_mode); 2037ec681f3Smrg 2047ec681f3Smrg if (cbuf->level->ts_compress_fmt >= 0) { 2057ec681f3Smrg /* overwrite bit breaks v1/v2 compression */ 2067ec681f3Smrg if (!screen->specs.v4_compression) 2077ec681f3Smrg cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE; 2087ec681f3Smrg 2097ec681f3Smrg ts_mem_config |= 2107ec681f3Smrg VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION | 2117ec681f3Smrg VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt); 2127ec681f3Smrg } 2137ec681f3Smrg } 21401e04c3fSmrg 21501e04c3fSmrg nr_samples_color = cbuf->base.texture->nr_samples; 2167ec681f3Smrg 2177ec681f3Smrg if (util_format_is_srgb(cbuf->base.format)) 2187ec681f3Smrg pe_logic_op |= VIVS_PE_LOGIC_OP_SRGB; 2197ec681f3Smrg 2207ec681f3Smrg cs->PS_CONTROL = COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0); 2217ec681f3Smrg cs->PS_CONTROL_EXT = 2227ec681f3Smrg VIVS_PS_CONTROL_EXT_OUTPUT_MODE0(translate_output_mode(cbuf->base.format, screen->specs.halti >= 5)); 22301e04c3fSmrg } else { 22401e04c3fSmrg /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and 22501e04c3fSmrg * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the 22601e04c3fSmrg * color target */ 22701e04c3fSmrg cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE; 22801e04c3fSmrg cs->PE_COLOR_STRIDE = 0; 22901e04c3fSmrg cs->TS_COLOR_STATUS_BASE.bo = NULL; 23001e04c3fSmrg cs->TS_COLOR_SURFACE_BASE.bo = NULL; 23101e04c3fSmrg 2329f464c52Smaya cs->PE_COLOR_ADDR = ctx->dummy_rt_reloc; 2337ec681f3Smrg for (int i = 0; i < screen->specs.pixel_pipes; i++) 2349f464c52Smaya cs->PE_PIPE_COLOR_ADDR[i] = ctx->dummy_rt_reloc; 23501e04c3fSmrg } 23601e04c3fSmrg 2377ec681f3Smrg if (fb->zsbuf != NULL) { 2387ec681f3Smrg struct etna_surface *zsbuf = etna_surface(fb->zsbuf); 23901e04c3fSmrg struct etna_resource *res = etna_resource(zsbuf->base.texture); 24001e04c3fSmrg 2417ec681f3Smrg etna_update_render_resource(pctx, etna_resource(zsbuf->prsc)); 24201e04c3fSmrg 24301e04c3fSmrg assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ 24401e04c3fSmrg 24501e04c3fSmrg uint32_t depth_format = translate_depth_format(zsbuf->base.format); 24601e04c3fSmrg unsigned depth_bits = 24701e04c3fSmrg depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24; 24801e04c3fSmrg bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; 24901e04c3fSmrg 25001e04c3fSmrg cs->PE_DEPTH_CONFIG = 25101e04c3fSmrg depth_format | 25201e04c3fSmrg COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) | 25301e04c3fSmrg VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z | 2547ec681f3Smrg VIVS_PE_DEPTH_CONFIG_UNK18; /* something to do with clipping? */ 25501e04c3fSmrg /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ 25601e04c3fSmrg /* merged with depth_stencil_alpha */ 25701e04c3fSmrg 2587ec681f3Smrg if (screen->specs.pixel_pipes == 1) { 25901e04c3fSmrg cs->PE_DEPTH_ADDR = zsbuf->reloc[0]; 26001e04c3fSmrg cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 26101e04c3fSmrg } else { 2627ec681f3Smrg for (int i = 0; i < screen->specs.pixel_pipes; i++) { 26301e04c3fSmrg cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i]; 26401e04c3fSmrg cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 26501e04c3fSmrg } 26601e04c3fSmrg } 26701e04c3fSmrg 26801e04c3fSmrg cs->PE_DEPTH_STRIDE = zsbuf->surf.stride; 26901e04c3fSmrg cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED; 27001e04c3fSmrg cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f); 27101e04c3fSmrg 27201e04c3fSmrg if (zsbuf->surf.ts_size) { 27301e04c3fSmrg cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value; 27401e04c3fSmrg 27501e04c3fSmrg cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc; 27601e04c3fSmrg cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 27701e04c3fSmrg 27801e04c3fSmrg cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0]; 27901e04c3fSmrg cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 2807ec681f3Smrg 2817ec681f3Smrg pe_mem_config |= VIVS_PE_MEM_CONFIG_DEPTH_TS_MODE(zsbuf->level->ts_mode); 2827ec681f3Smrg 2837ec681f3Smrg if (zsbuf->level->ts_compress_fmt >= 0) { 2847ec681f3Smrg ts_mem_config |= 2857ec681f3Smrg VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION | 2867ec681f3Smrg COND(zsbuf->level->ts_compress_fmt == COMPRESSION_FORMAT_D24S8, 2877ec681f3Smrg VIVS_TS_MEM_CONFIG_STENCIL_ENABLE); 2887ec681f3Smrg } 28901e04c3fSmrg } 29001e04c3fSmrg 29101e04c3fSmrg ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP); 29201e04c3fSmrg 29301e04c3fSmrg nr_samples_depth = zsbuf->base.texture->nr_samples; 29401e04c3fSmrg } else { 29501e04c3fSmrg cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE; 29601e04c3fSmrg cs->PE_DEPTH_ADDR.bo = NULL; 29701e04c3fSmrg cs->PE_DEPTH_STRIDE = 0; 29801e04c3fSmrg cs->TS_DEPTH_STATUS_BASE.bo = NULL; 29901e04c3fSmrg cs->TS_DEPTH_SURFACE_BASE.bo = NULL; 30001e04c3fSmrg 30101e04c3fSmrg for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) 30201e04c3fSmrg cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL; 30301e04c3fSmrg } 30401e04c3fSmrg 30501e04c3fSmrg /* MSAA setup */ 30601e04c3fSmrg if (nr_samples_depth != -1 && nr_samples_color != -1 && 30701e04c3fSmrg nr_samples_depth != nr_samples_color) { 30801e04c3fSmrg BUG("Number of samples in color and depth texture must match (%i and %i respectively)", 30901e04c3fSmrg nr_samples_color, nr_samples_depth); 31001e04c3fSmrg } 31101e04c3fSmrg 31201e04c3fSmrg switch (MAX2(nr_samples_depth, nr_samples_color)) { 31301e04c3fSmrg case 0: 31401e04c3fSmrg case 1: /* Are 0 and 1 samples allowed? */ 31501e04c3fSmrg cs->GL_MULTI_SAMPLE_CONFIG = 31601e04c3fSmrg VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; 31701e04c3fSmrg cs->msaa_mode = false; 31801e04c3fSmrg break; 31901e04c3fSmrg case 2: 32001e04c3fSmrg cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; 32101e04c3fSmrg cs->msaa_mode = true; /* Add input to PS */ 32201e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E04 = 0x0; 32301e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22; 32401e04c3fSmrg cs->RA_CENTROID_TABLE[0] = 0x66aa2288; 32501e04c3fSmrg cs->RA_CENTROID_TABLE[1] = 0x88558800; 32601e04c3fSmrg cs->RA_CENTROID_TABLE[2] = 0x88881100; 32701e04c3fSmrg cs->RA_CENTROID_TABLE[3] = 0x33888800; 32801e04c3fSmrg break; 32901e04c3fSmrg case 4: 33001e04c3fSmrg cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; 33101e04c3fSmrg cs->msaa_mode = true; /* Add input to PS */ 33201e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E04 = 0x0; 33301e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26; 33401e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a; 33501e04c3fSmrg cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22; 33601e04c3fSmrg cs->RA_CENTROID_TABLE[0] = 0x4a6e2688; 33701e04c3fSmrg cs->RA_CENTROID_TABLE[1] = 0x888888a2; 33801e04c3fSmrg cs->RA_CENTROID_TABLE[2] = 0x888888ea; 33901e04c3fSmrg cs->RA_CENTROID_TABLE[3] = 0x888888c6; 34001e04c3fSmrg cs->RA_CENTROID_TABLE[4] = 0x46622a88; 34101e04c3fSmrg cs->RA_CENTROID_TABLE[5] = 0x888888ae; 34201e04c3fSmrg cs->RA_CENTROID_TABLE[6] = 0x888888e6; 34301e04c3fSmrg cs->RA_CENTROID_TABLE[7] = 0x888888ca; 34401e04c3fSmrg cs->RA_CENTROID_TABLE[8] = 0x262a2288; 34501e04c3fSmrg cs->RA_CENTROID_TABLE[9] = 0x886688a2; 34601e04c3fSmrg cs->RA_CENTROID_TABLE[10] = 0x888866aa; 34701e04c3fSmrg cs->RA_CENTROID_TABLE[11] = 0x668888a6; 34801e04c3fSmrg break; 34901e04c3fSmrg } 35001e04c3fSmrg 35101e04c3fSmrg cs->TS_MEM_CONFIG = ts_mem_config; 3527ec681f3Smrg cs->PE_MEM_CONFIG = pe_mem_config; 35301e04c3fSmrg 35401e04c3fSmrg /* Single buffer setup. There is only one switch for this, not a separate 35501e04c3fSmrg * one per color buffer / depth buffer. To keep the logic simple always use 35601e04c3fSmrg * single buffer when this feature is available. 3577ec681f3Smrg * note: the blob will use 2 in some situations, figure out why? 35801e04c3fSmrg */ 3597ec681f3Smrg pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(screen->specs.single_buffer ? 3 : 0); 3607ec681f3Smrg cs->PE_LOGIC_OP = pe_logic_op; 36101e04c3fSmrg 36201e04c3fSmrg /* keep copy of original structure */ 3637ec681f3Smrg util_copy_framebuffer_state(&ctx->framebuffer_s, fb); 36401e04c3fSmrg ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS; 36501e04c3fSmrg} 36601e04c3fSmrg 36701e04c3fSmrgstatic void 36801e04c3fSmrgetna_set_polygon_stipple(struct pipe_context *pctx, 36901e04c3fSmrg const struct pipe_poly_stipple *stipple) 37001e04c3fSmrg{ 37101e04c3fSmrg /* NOP */ 37201e04c3fSmrg} 37301e04c3fSmrg 37401e04c3fSmrgstatic void 37501e04c3fSmrgetna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, 37601e04c3fSmrg unsigned num_scissors, const struct pipe_scissor_state *ss) 37701e04c3fSmrg{ 37801e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 37901e04c3fSmrg assert(ss->minx <= ss->maxx); 38001e04c3fSmrg assert(ss->miny <= ss->maxy); 38101e04c3fSmrg 3827ec681f3Smrg ctx->scissor = *ss; 38301e04c3fSmrg ctx->dirty |= ETNA_DIRTY_SCISSOR; 38401e04c3fSmrg} 38501e04c3fSmrg 38601e04c3fSmrgstatic void 38701e04c3fSmrgetna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, 38801e04c3fSmrg unsigned num_scissors, const struct pipe_viewport_state *vs) 38901e04c3fSmrg{ 39001e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 39101e04c3fSmrg struct compiled_viewport_state *cs = &ctx->viewport; 39201e04c3fSmrg 39301e04c3fSmrg ctx->viewport_s = *vs; 39401e04c3fSmrg /** 39501e04c3fSmrg * For Vivante GPU, viewport z transformation is 0..1 to 0..1 instead of 39601e04c3fSmrg * -1..1 to 0..1. 39701e04c3fSmrg * scaling and translation to 0..1 already happened, so remove that 39801e04c3fSmrg * 39901e04c3fSmrg * z' = (z * 2 - 1) * scale + translate 40001e04c3fSmrg * = z * (2 * scale) + (translate - scale) 40101e04c3fSmrg * 40201e04c3fSmrg * scale' = 2 * scale 40301e04c3fSmrg * translate' = translate - scale 40401e04c3fSmrg */ 40501e04c3fSmrg 40601e04c3fSmrg /* must be fixp as v4 state deltas assume it is */ 40701e04c3fSmrg cs->PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16(vs->scale[0]); 40801e04c3fSmrg cs->PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16(vs->scale[1]); 40901e04c3fSmrg cs->PA_VIEWPORT_SCALE_Z = fui(vs->scale[2] * 2.0f); 41001e04c3fSmrg cs->PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16(vs->translate[0]); 41101e04c3fSmrg cs->PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16(vs->translate[1]); 41201e04c3fSmrg cs->PA_VIEWPORT_OFFSET_Z = fui(vs->translate[2] - vs->scale[2]); 41301e04c3fSmrg 41401e04c3fSmrg /* Compute scissor rectangle (fixp) from viewport. 41501e04c3fSmrg * Make sure left is always < right and top always < bottom. 41601e04c3fSmrg */ 4177ec681f3Smrg cs->SE_SCISSOR_LEFT = MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f); 4187ec681f3Smrg cs->SE_SCISSOR_TOP = MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f); 4197ec681f3Smrg cs->SE_SCISSOR_RIGHT = ceilf(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); 4207ec681f3Smrg cs->SE_SCISSOR_BOTTOM = ceilf(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); 42101e04c3fSmrg 42201e04c3fSmrg cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */ 42301e04c3fSmrg cs->PE_DEPTH_FAR = fui(1.0); 42401e04c3fSmrg ctx->dirty |= ETNA_DIRTY_VIEWPORT; 42501e04c3fSmrg} 42601e04c3fSmrg 42701e04c3fSmrgstatic void 42801e04c3fSmrgetna_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, 4297ec681f3Smrg unsigned num_buffers, unsigned unbind_num_trailing_slots, bool take_ownership, 4307ec681f3Smrg const struct pipe_vertex_buffer *vb) 43101e04c3fSmrg{ 43201e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 43301e04c3fSmrg struct etna_vertexbuf_state *so = &ctx->vertex_buffer; 43401e04c3fSmrg 4357ec681f3Smrg util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, 4367ec681f3Smrg num_buffers, unbind_num_trailing_slots, 4377ec681f3Smrg take_ownership); 43801e04c3fSmrg so->count = util_last_bit(so->enabled_mask); 43901e04c3fSmrg 44001e04c3fSmrg for (unsigned idx = start_slot; idx < start_slot + num_buffers; ++idx) { 44101e04c3fSmrg struct compiled_set_vertex_buffer *cs = &so->cvb[idx]; 44201e04c3fSmrg struct pipe_vertex_buffer *vbi = &so->vb[idx]; 44301e04c3fSmrg 44401e04c3fSmrg assert(!vbi->is_user_buffer); /* XXX support user_buffer using 44501e04c3fSmrg etna_usermem_map */ 44601e04c3fSmrg 44701e04c3fSmrg if (vbi->buffer.resource) { /* GPU buffer */ 44801e04c3fSmrg cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer.resource)->bo; 44901e04c3fSmrg cs->FE_VERTEX_STREAM_BASE_ADDR.offset = vbi->buffer_offset; 45001e04c3fSmrg cs->FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ; 45101e04c3fSmrg cs->FE_VERTEX_STREAM_CONTROL = 45201e04c3fSmrg FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(vbi->stride); 45301e04c3fSmrg } else { 45401e04c3fSmrg cs->FE_VERTEX_STREAM_BASE_ADDR.bo = NULL; 45501e04c3fSmrg cs->FE_VERTEX_STREAM_CONTROL = 0; 45601e04c3fSmrg } 45701e04c3fSmrg } 45801e04c3fSmrg 45901e04c3fSmrg ctx->dirty |= ETNA_DIRTY_VERTEX_BUFFERS; 46001e04c3fSmrg} 46101e04c3fSmrg 46201e04c3fSmrgstatic void 46301e04c3fSmrgetna_blend_state_bind(struct pipe_context *pctx, void *bs) 46401e04c3fSmrg{ 46501e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 46601e04c3fSmrg 46701e04c3fSmrg ctx->blend = bs; 46801e04c3fSmrg ctx->dirty |= ETNA_DIRTY_BLEND; 46901e04c3fSmrg} 47001e04c3fSmrg 47101e04c3fSmrgstatic void 47201e04c3fSmrgetna_blend_state_delete(struct pipe_context *pctx, void *bs) 47301e04c3fSmrg{ 47401e04c3fSmrg FREE(bs); 47501e04c3fSmrg} 47601e04c3fSmrg 47701e04c3fSmrgstatic void 47801e04c3fSmrgetna_rasterizer_state_bind(struct pipe_context *pctx, void *rs) 47901e04c3fSmrg{ 48001e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 48101e04c3fSmrg 48201e04c3fSmrg ctx->rasterizer = rs; 48301e04c3fSmrg ctx->dirty |= ETNA_DIRTY_RASTERIZER; 48401e04c3fSmrg} 48501e04c3fSmrg 48601e04c3fSmrgstatic void 48701e04c3fSmrgetna_rasterizer_state_delete(struct pipe_context *pctx, void *rs) 48801e04c3fSmrg{ 48901e04c3fSmrg FREE(rs); 49001e04c3fSmrg} 49101e04c3fSmrg 49201e04c3fSmrgstatic void 49301e04c3fSmrgetna_zsa_state_bind(struct pipe_context *pctx, void *zs) 49401e04c3fSmrg{ 49501e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 49601e04c3fSmrg 49701e04c3fSmrg ctx->zsa = zs; 49801e04c3fSmrg ctx->dirty |= ETNA_DIRTY_ZSA; 49901e04c3fSmrg} 50001e04c3fSmrg 50101e04c3fSmrgstatic void 50201e04c3fSmrgetna_zsa_state_delete(struct pipe_context *pctx, void *zs) 50301e04c3fSmrg{ 50401e04c3fSmrg FREE(zs); 50501e04c3fSmrg} 50601e04c3fSmrg 50701e04c3fSmrg/** Create vertex element states, which define a layout for fetching 50801e04c3fSmrg * vertices for rendering. 50901e04c3fSmrg */ 51001e04c3fSmrgstatic void * 51101e04c3fSmrgetna_vertex_elements_state_create(struct pipe_context *pctx, 51201e04c3fSmrg unsigned num_elements, const struct pipe_vertex_element *elements) 51301e04c3fSmrg{ 51401e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 5157ec681f3Smrg struct etna_screen *screen = ctx->screen; 51601e04c3fSmrg struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state); 51701e04c3fSmrg 51801e04c3fSmrg if (!cs) 51901e04c3fSmrg return NULL; 52001e04c3fSmrg 5217ec681f3Smrg if (num_elements > screen->specs.vertex_max_elements) { 52201e04c3fSmrg BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements, 5237ec681f3Smrg screen->specs.vertex_max_elements); 5247ec681f3Smrg FREE(cs); 52501e04c3fSmrg return NULL; 52601e04c3fSmrg } 52701e04c3fSmrg 52801e04c3fSmrg /* XXX could minimize number of consecutive stretches here by sorting, and 52901e04c3fSmrg * permuting the inputs in shader or does Mesa do this already? */ 53001e04c3fSmrg 53101e04c3fSmrg cs->num_elements = num_elements; 53201e04c3fSmrg 53301e04c3fSmrg unsigned start_offset = 0; /* start of current consecutive stretch */ 53401e04c3fSmrg bool nonconsecutive = true; /* previous value of nonconsecutive */ 5357ec681f3Smrg uint32_t buffer_mask = 0; /* mask of buffer_idx already seen */ 53601e04c3fSmrg 53701e04c3fSmrg for (unsigned idx = 0; idx < num_elements; ++idx) { 5387ec681f3Smrg unsigned buffer_idx = elements[idx].vertex_buffer_index; 53901e04c3fSmrg unsigned element_size = util_format_get_blocksize(elements[idx].src_format); 54001e04c3fSmrg unsigned end_offset = elements[idx].src_offset + element_size; 54101e04c3fSmrg uint32_t format_type, normalize; 54201e04c3fSmrg 54301e04c3fSmrg if (nonconsecutive) 54401e04c3fSmrg start_offset = elements[idx].src_offset; 54501e04c3fSmrg 5467ec681f3Smrg /* guaranteed by PIPE_CAP_MAX_VERTEX_BUFFERS */ 5477ec681f3Smrg assert(buffer_idx < screen->specs.stream_count); 5487ec681f3Smrg 54901e04c3fSmrg /* maximum vertex size is 256 bytes */ 5507ec681f3Smrg assert(element_size != 0 && (end_offset - start_offset) < 256); 55101e04c3fSmrg 55201e04c3fSmrg /* check whether next element is consecutive to this one */ 55301e04c3fSmrg nonconsecutive = (idx == (num_elements - 1)) || 5547ec681f3Smrg elements[idx + 1].vertex_buffer_index != buffer_idx || 55501e04c3fSmrg end_offset != elements[idx + 1].src_offset; 55601e04c3fSmrg 55701e04c3fSmrg format_type = translate_vertex_format_type(elements[idx].src_format); 55801e04c3fSmrg normalize = translate_vertex_format_normalize(elements[idx].src_format); 55901e04c3fSmrg 56001e04c3fSmrg assert(format_type != ETNA_NO_MATCH); 56101e04c3fSmrg assert(normalize != ETNA_NO_MATCH); 56201e04c3fSmrg 5637ec681f3Smrg if (screen->specs.halti < 5) { 56401e04c3fSmrg cs->FE_VERTEX_ELEMENT_CONFIG[idx] = 56501e04c3fSmrg COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) | 56601e04c3fSmrg format_type | 56701e04c3fSmrg VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) | 56801e04c3fSmrg normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | 5697ec681f3Smrg VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(buffer_idx) | 57001e04c3fSmrg VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) | 57101e04c3fSmrg VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset); 57201e04c3fSmrg } else { /* HALTI5 spread vertex attrib config over two registers */ 57301e04c3fSmrg cs->NFE_GENERIC_ATTRIB_CONFIG0[idx] = 57401e04c3fSmrg format_type | 57501e04c3fSmrg VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM(util_format_get_nr_components(elements[idx].src_format)) | 57601e04c3fSmrg normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN(ENDIAN_MODE_NO_SWAP) | 5777ec681f3Smrg VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(buffer_idx) | 57801e04c3fSmrg VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START(elements[idx].src_offset); 57901e04c3fSmrg cs->NFE_GENERIC_ATTRIB_CONFIG1[idx] = 58001e04c3fSmrg COND(nonconsecutive, VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE) | 58101e04c3fSmrg VIVS_NFE_GENERIC_ATTRIB_CONFIG1_END(end_offset - start_offset); 58201e04c3fSmrg } 5837ec681f3Smrg 5847ec681f3Smrg if (util_format_is_pure_integer(elements[idx].src_format)) 5857ec681f3Smrg cs->NFE_GENERIC_ATTRIB_SCALE[idx] = 1; 5867ec681f3Smrg else 5877ec681f3Smrg cs->NFE_GENERIC_ATTRIB_SCALE[idx] = fui(1.0f); 5887ec681f3Smrg 5897ec681f3Smrg /* instance_divisor is part of elements state but should be the same for all buffers */ 5907ec681f3Smrg if (buffer_mask & 1 << buffer_idx) 5917ec681f3Smrg assert(cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] == elements[idx].instance_divisor); 5927ec681f3Smrg else 5937ec681f3Smrg cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] = elements[idx].instance_divisor; 5947ec681f3Smrg 5957ec681f3Smrg buffer_mask |= 1 << buffer_idx; 5967ec681f3Smrg cs->num_buffers = MAX2(cs->num_buffers, buffer_idx + 1); 59701e04c3fSmrg } 59801e04c3fSmrg 59901e04c3fSmrg return cs; 60001e04c3fSmrg} 60101e04c3fSmrg 60201e04c3fSmrgstatic void 60301e04c3fSmrgetna_vertex_elements_state_delete(struct pipe_context *pctx, void *ve) 60401e04c3fSmrg{ 60501e04c3fSmrg FREE(ve); 60601e04c3fSmrg} 60701e04c3fSmrg 60801e04c3fSmrgstatic void 60901e04c3fSmrgetna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve) 61001e04c3fSmrg{ 61101e04c3fSmrg struct etna_context *ctx = etna_context(pctx); 61201e04c3fSmrg 61301e04c3fSmrg ctx->vertex_elements = ve; 61401e04c3fSmrg ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS; 61501e04c3fSmrg} 61601e04c3fSmrg 6177ec681f3Smrgstatic void 6187ec681f3Smrgetna_set_stream_output_targets(struct pipe_context *pctx, 6197ec681f3Smrg unsigned num_targets, struct pipe_stream_output_target **targets, 6207ec681f3Smrg const unsigned *offsets) 6217ec681f3Smrg{ 6227ec681f3Smrg /* stub */ 6237ec681f3Smrg} 6247ec681f3Smrg 62501e04c3fSmrgstatic bool 62601e04c3fSmrgetna_update_ts_config(struct etna_context *ctx) 62701e04c3fSmrg{ 62801e04c3fSmrg uint32_t new_ts_config = ctx->framebuffer.TS_MEM_CONFIG; 62901e04c3fSmrg 63001e04c3fSmrg if (ctx->framebuffer_s.nr_cbufs > 0) { 63101e04c3fSmrg struct etna_surface *c_surf = etna_surface(ctx->framebuffer_s.cbufs[0]); 63201e04c3fSmrg 63301e04c3fSmrg if(c_surf->level->ts_size && c_surf->level->ts_valid) { 63401e04c3fSmrg new_ts_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; 63501e04c3fSmrg } else { 63601e04c3fSmrg new_ts_config &= ~VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; 63701e04c3fSmrg } 63801e04c3fSmrg } 63901e04c3fSmrg 64001e04c3fSmrg if (ctx->framebuffer_s.zsbuf) { 64101e04c3fSmrg struct etna_surface *zs_surf = etna_surface(ctx->framebuffer_s.zsbuf); 64201e04c3fSmrg 64301e04c3fSmrg if(zs_surf->level->ts_size && zs_surf->level->ts_valid) { 64401e04c3fSmrg new_ts_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; 64501e04c3fSmrg } else { 64601e04c3fSmrg new_ts_config &= ~VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; 64701e04c3fSmrg } 64801e04c3fSmrg } 64901e04c3fSmrg 65001e04c3fSmrg if (new_ts_config != ctx->framebuffer.TS_MEM_CONFIG || 65101e04c3fSmrg (ctx->dirty & ETNA_DIRTY_FRAMEBUFFER)) { 65201e04c3fSmrg ctx->framebuffer.TS_MEM_CONFIG = new_ts_config; 65301e04c3fSmrg ctx->dirty |= ETNA_DIRTY_TS; 65401e04c3fSmrg } 65501e04c3fSmrg 65601e04c3fSmrg ctx->dirty &= ~ETNA_DIRTY_DERIVE_TS; 65701e04c3fSmrg 65801e04c3fSmrg return true; 65901e04c3fSmrg} 66001e04c3fSmrg 6617ec681f3Smrgstatic bool 6627ec681f3Smrgetna_update_clipping(struct etna_context *ctx) 6637ec681f3Smrg{ 6647ec681f3Smrg const struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); 6657ec681f3Smrg const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; 6667ec681f3Smrg 6677ec681f3Smrg /* clip framebuffer against viewport */ 6687ec681f3Smrg uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT; 6697ec681f3Smrg uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP; 6707ec681f3Smrg uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT); 6717ec681f3Smrg uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM); 6727ec681f3Smrg 6737ec681f3Smrg /* clip against scissor */ 6747ec681f3Smrg if (rasterizer->scissor) { 6757ec681f3Smrg scissor_left = MAX2(ctx->scissor.minx, scissor_left); 6767ec681f3Smrg scissor_top = MAX2(ctx->scissor.miny, scissor_top); 6777ec681f3Smrg scissor_right = MIN2(ctx->scissor.maxx, scissor_right); 6787ec681f3Smrg scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom); 6797ec681f3Smrg } 6807ec681f3Smrg 6817ec681f3Smrg ctx->clipping.minx = scissor_left; 6827ec681f3Smrg ctx->clipping.miny = scissor_top; 6837ec681f3Smrg ctx->clipping.maxx = scissor_right; 6847ec681f3Smrg ctx->clipping.maxy = scissor_bottom; 6857ec681f3Smrg 6867ec681f3Smrg ctx->dirty |= ETNA_DIRTY_SCISSOR_CLIP; 6877ec681f3Smrg 6887ec681f3Smrg return true; 6897ec681f3Smrg} 6907ec681f3Smrg 6917ec681f3Smrgstatic bool 6927ec681f3Smrgetna_update_zsa(struct etna_context *ctx) 6937ec681f3Smrg{ 6947ec681f3Smrg struct compiled_shader_state *shader_state = &ctx->shader_state; 6957ec681f3Smrg struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa; 6967ec681f3Smrg struct etna_zsa_state *zsa = etna_zsa_state(zsa_state); 6977ec681f3Smrg struct etna_screen *screen = ctx->screen; 6987ec681f3Smrg uint32_t new_pe_depth, new_ra_depth; 6997ec681f3Smrg bool late_z_write = false, early_z_write = false, 7007ec681f3Smrg late_z_test = false, early_z_test = false; 7017ec681f3Smrg 7027ec681f3Smrg if (zsa->z_write_enabled) { 7037ec681f3Smrg if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) && 7047ec681f3Smrg !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) && 7057ec681f3Smrg !zsa->stencil_enabled && 7067ec681f3Smrg !zsa_state->alpha_enabled && 7077ec681f3Smrg !shader_state->writes_z && 7087ec681f3Smrg !shader_state->uses_discard) 7097ec681f3Smrg early_z_write = true; 7107ec681f3Smrg else 7117ec681f3Smrg late_z_write = true; 7127ec681f3Smrg } 7137ec681f3Smrg 7147ec681f3Smrg if (zsa->z_test_enabled) { 7157ec681f3Smrg if (!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) && 7167ec681f3Smrg !zsa->stencil_modified && 7177ec681f3Smrg !shader_state->writes_z) 7187ec681f3Smrg early_z_test = true; 7197ec681f3Smrg else 7207ec681f3Smrg late_z_test = true; 7217ec681f3Smrg } 7227ec681f3Smrg 7237ec681f3Smrg new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ? 7247ec681f3Smrg /* compare funcs have 1 to 1 mapping */ 7257ec681f3Smrg zsa_state->depth_func : PIPE_FUNC_ALWAYS) | 7267ec681f3Smrg COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) | 7277ec681f3Smrg COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) | 7287ec681f3Smrg COND(!late_z_write && !late_z_test && !zsa->stencil_enabled, 7297ec681f3Smrg VIVS_PE_DEPTH_CONFIG_DISABLE_ZS); 7307ec681f3Smrg 7317ec681f3Smrg /* blob sets this to 0x40000031 on GC7000, seems to make no difference, 7327ec681f3Smrg * but keep it in mind if depth behaves strangely. */ 7337ec681f3Smrg new_ra_depth = 0x0000030 | 7347ec681f3Smrg COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE); 7357ec681f3Smrg 7367ec681f3Smrg if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)) { 7377ec681f3Smrg if (!early_z_write) 7387ec681f3Smrg new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE; 7397ec681f3Smrg /* The new early hierarchical test seems to only work properly if depth 7407ec681f3Smrg * is also written from the early stage. 7417ec681f3Smrg */ 7427ec681f3Smrg if (late_z_test || (early_z_test && late_z_write)) 7437ec681f3Smrg new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE; 7447ec681f3Smrg } 7457ec681f3Smrg 7467ec681f3Smrg if (new_pe_depth != zsa->PE_DEPTH_CONFIG || 7477ec681f3Smrg new_ra_depth != zsa->RA_DEPTH_CONFIG) 7487ec681f3Smrg ctx->dirty |= ETNA_DIRTY_ZSA; 7497ec681f3Smrg 7507ec681f3Smrg zsa->PE_DEPTH_CONFIG = new_pe_depth; 7517ec681f3Smrg zsa->RA_DEPTH_CONFIG = new_ra_depth; 7527ec681f3Smrg 7537ec681f3Smrg return true; 7547ec681f3Smrg} 7557ec681f3Smrg 7567ec681f3Smrgstatic bool 7577ec681f3Smrgetna_record_flush_resources(struct etna_context *ctx) 7587ec681f3Smrg{ 7597ec681f3Smrg struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; 7607ec681f3Smrg 7617ec681f3Smrg if (fb->nr_cbufs > 0) { 7627ec681f3Smrg struct etna_surface *surf = etna_surface(fb->cbufs[0]); 7637ec681f3Smrg 7647ec681f3Smrg if (!etna_resource(surf->prsc)->explicit_flush) 7657ec681f3Smrg _mesa_set_add(ctx->flush_resources, surf->prsc); 7667ec681f3Smrg } 7677ec681f3Smrg 7687ec681f3Smrg return true; 7697ec681f3Smrg} 7707ec681f3Smrg 77101e04c3fSmrgstruct etna_state_updater { 77201e04c3fSmrg bool (*update)(struct etna_context *ctx); 77301e04c3fSmrg uint32_t dirty; 77401e04c3fSmrg}; 77501e04c3fSmrg 77601e04c3fSmrgstatic const struct etna_state_updater etna_state_updates[] = { 77701e04c3fSmrg { 77801e04c3fSmrg etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS, 77901e04c3fSmrg }, 78001e04c3fSmrg { 78101e04c3fSmrg etna_shader_link, ETNA_DIRTY_SHADER, 78201e04c3fSmrg }, 78301e04c3fSmrg { 78401e04c3fSmrg etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER 78501e04c3fSmrg }, 78601e04c3fSmrg { 78701e04c3fSmrg etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER, 78801e04c3fSmrg }, 78901e04c3fSmrg { 79001e04c3fSmrg etna_update_ts_config, ETNA_DIRTY_DERIVE_TS, 7917ec681f3Smrg }, 7927ec681f3Smrg { 7937ec681f3Smrg etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | 7947ec681f3Smrg ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT, 7957ec681f3Smrg }, 7967ec681f3Smrg { 7977ec681f3Smrg etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER, 7987ec681f3Smrg }, 7997ec681f3Smrg { 8007ec681f3Smrg etna_record_flush_resources, ETNA_DIRTY_FRAMEBUFFER, 80101e04c3fSmrg } 80201e04c3fSmrg}; 80301e04c3fSmrg 80401e04c3fSmrgbool 80501e04c3fSmrgetna_state_update(struct etna_context *ctx) 80601e04c3fSmrg{ 80701e04c3fSmrg for (unsigned int i = 0; i < ARRAY_SIZE(etna_state_updates); i++) 80801e04c3fSmrg if (ctx->dirty & etna_state_updates[i].dirty) 80901e04c3fSmrg if (!etna_state_updates[i].update(ctx)) 81001e04c3fSmrg return false; 81101e04c3fSmrg 81201e04c3fSmrg return true; 81301e04c3fSmrg} 81401e04c3fSmrg 81501e04c3fSmrgvoid 81601e04c3fSmrgetna_state_init(struct pipe_context *pctx) 81701e04c3fSmrg{ 81801e04c3fSmrg pctx->set_blend_color = etna_set_blend_color; 81901e04c3fSmrg pctx->set_stencil_ref = etna_set_stencil_ref; 82001e04c3fSmrg pctx->set_clip_state = etna_set_clip_state; 82101e04c3fSmrg pctx->set_sample_mask = etna_set_sample_mask; 82201e04c3fSmrg pctx->set_constant_buffer = etna_set_constant_buffer; 82301e04c3fSmrg pctx->set_framebuffer_state = etna_set_framebuffer_state; 82401e04c3fSmrg pctx->set_polygon_stipple = etna_set_polygon_stipple; 82501e04c3fSmrg pctx->set_scissor_states = etna_set_scissor_states; 82601e04c3fSmrg pctx->set_viewport_states = etna_set_viewport_states; 82701e04c3fSmrg 82801e04c3fSmrg pctx->set_vertex_buffers = etna_set_vertex_buffers; 82901e04c3fSmrg 83001e04c3fSmrg pctx->bind_blend_state = etna_blend_state_bind; 83101e04c3fSmrg pctx->delete_blend_state = etna_blend_state_delete; 83201e04c3fSmrg 83301e04c3fSmrg pctx->bind_rasterizer_state = etna_rasterizer_state_bind; 83401e04c3fSmrg pctx->delete_rasterizer_state = etna_rasterizer_state_delete; 83501e04c3fSmrg 83601e04c3fSmrg pctx->bind_depth_stencil_alpha_state = etna_zsa_state_bind; 83701e04c3fSmrg pctx->delete_depth_stencil_alpha_state = etna_zsa_state_delete; 83801e04c3fSmrg 83901e04c3fSmrg pctx->create_vertex_elements_state = etna_vertex_elements_state_create; 84001e04c3fSmrg pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete; 84101e04c3fSmrg pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind; 8427ec681f3Smrg 8437ec681f3Smrg pctx->set_stream_output_targets = etna_set_stream_output_targets; 84401e04c3fSmrg} 845