1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2012-2015 Etnaviv Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 13bf215546Sopenharmony_ci * of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Wladimir J. van der Laan <laanwj@gmail.com> 25bf215546Sopenharmony_ci * Christian Gmeiner <christian.gmeiner@gmail.com> 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "etnaviv_state.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "hw/common.xml.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "etnaviv_blend.h" 33bf215546Sopenharmony_ci#include "etnaviv_clear_blit.h" 34bf215546Sopenharmony_ci#include "etnaviv_context.h" 35bf215546Sopenharmony_ci#include "etnaviv_format.h" 36bf215546Sopenharmony_ci#include "etnaviv_rasterizer.h" 37bf215546Sopenharmony_ci#include "etnaviv_screen.h" 38bf215546Sopenharmony_ci#include "etnaviv_shader.h" 39bf215546Sopenharmony_ci#include "etnaviv_surface.h" 40bf215546Sopenharmony_ci#include "etnaviv_translate.h" 41bf215546Sopenharmony_ci#include "etnaviv_util.h" 42bf215546Sopenharmony_ci#include "etnaviv_zsa.h" 43bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 44bf215546Sopenharmony_ci#include "util/u_helpers.h" 45bf215546Sopenharmony_ci#include "util/u_inlines.h" 46bf215546Sopenharmony_ci#include "util/u_math.h" 47bf215546Sopenharmony_ci#include "util/u_memory.h" 48bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistatic void 51bf215546Sopenharmony_cietna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref sr) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 54bf215546Sopenharmony_ci struct compiled_stencil_ref *cs = &ctx->stencil_ref; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci ctx->stencil_ref_s = sr; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci for (unsigned i = 0; i < 2; i++) { 59bf215546Sopenharmony_ci cs->PE_STENCIL_CONFIG[i] = 60bf215546Sopenharmony_ci VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr.ref_value[i]); 61bf215546Sopenharmony_ci cs->PE_STENCIL_CONFIG_EXT[i] = 62bf215546Sopenharmony_ci VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr.ref_value[!i]); 63bf215546Sopenharmony_ci } 64bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_STENCIL_REF; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic void 68bf215546Sopenharmony_cietna_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *pcs) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci /* NOOP */ 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cistatic void 74bf215546Sopenharmony_cietna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci ctx->sample_mask = sample_mask; 79bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_SAMPLE_MASK; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistatic void 83bf215546Sopenharmony_cietna_set_constant_buffer(struct pipe_context *pctx, 84bf215546Sopenharmony_ci enum pipe_shader_type shader, uint index, bool take_ownership, 85bf215546Sopenharmony_ci const struct pipe_constant_buffer *cb) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 88bf215546Sopenharmony_ci struct etna_constbuf_state *so = &ctx->constant_buffer[shader]; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci assert(index < ETNA_MAX_CONST_BUF); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci /* Note that the gallium frontends can unbind constant buffers by 95bf215546Sopenharmony_ci * passing NULL here. */ 96bf215546Sopenharmony_ci if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) { 97bf215546Sopenharmony_ci so->enabled_mask &= ~(1 << index); 98bf215546Sopenharmony_ci return; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci assert(index != 0 || cb->user_buffer != NULL); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (!cb->buffer) { 104bf215546Sopenharmony_ci struct pipe_constant_buffer *cb = &so->cb[index]; 105bf215546Sopenharmony_ci u_upload_data(pctx->const_uploader, 0, cb->buffer_size, 16, cb->user_buffer, &cb->buffer_offset, &cb->buffer); 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci so->enabled_mask |= 1 << index; 109bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_CONSTBUF; 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void 113bf215546Sopenharmony_cietna_update_render_resource(struct pipe_context *pctx, struct etna_resource *base) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct etna_resource *to = base, *from = base; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (base->texture && etna_resource_newer(etna_resource(base->texture), base)) 118bf215546Sopenharmony_ci from = etna_resource(base->texture); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci if (base->render) 121bf215546Sopenharmony_ci to = etna_resource(base->render); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if ((to != from) && etna_resource_older(to, from)) { 124bf215546Sopenharmony_ci etna_copy_resource(pctx, &to->base, &from->base, 0, base->base.last_level); 125bf215546Sopenharmony_ci to->seqno = from->seqno; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_cistatic void 130bf215546Sopenharmony_cietna_set_framebuffer_state(struct pipe_context *pctx, 131bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 134bf215546Sopenharmony_ci struct etna_screen *screen = ctx->screen; 135bf215546Sopenharmony_ci struct compiled_framebuffer_state *cs = &ctx->framebuffer; 136bf215546Sopenharmony_ci int nr_samples_color = -1; 137bf215546Sopenharmony_ci int nr_samples_depth = -1; 138bf215546Sopenharmony_ci bool target_16bpp = false; 139bf215546Sopenharmony_ci bool target_linear = false; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci /* Set up TS as well. Warning: this state is used by both the RS and PE */ 142bf215546Sopenharmony_ci uint32_t ts_mem_config = 0; 143bf215546Sopenharmony_ci uint32_t pe_mem_config = 0; 144bf215546Sopenharmony_ci uint32_t pe_logic_op = 0; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (fb->nr_cbufs > 0) { /* at least one color buffer? */ 147bf215546Sopenharmony_ci struct etna_surface *cbuf = etna_surface(fb->cbufs[0]); 148bf215546Sopenharmony_ci struct etna_resource *res = etna_resource(cbuf->base.texture); 149bf215546Sopenharmony_ci bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; 150bf215546Sopenharmony_ci uint32_t fmt = translate_pe_format(cbuf->base.format); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci assert((res->layout & ETNA_LAYOUT_BIT_TILE) || 153bf215546Sopenharmony_ci VIV_FEATURE(screen, chipMinorFeatures2, LINEAR_PE)); 154bf215546Sopenharmony_ci etna_update_render_resource(pctx, etna_resource(cbuf->prsc)); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci if (res->layout == ETNA_LAYOUT_LINEAR) 157bf215546Sopenharmony_ci target_linear = true; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci if (fmt >= PE_FORMAT_R16F) 160bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT(fmt) | 161bf215546Sopenharmony_ci VIVS_PE_COLOR_FORMAT_FORMAT_MASK; 162bf215546Sopenharmony_ci else 163bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(fmt); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci if (util_format_get_blocksize(cbuf->base.format) <= 2) 166bf215546Sopenharmony_ci target_16bpp = true; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT |= 169bf215546Sopenharmony_ci VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | 170bf215546Sopenharmony_ci VIVS_PE_COLOR_FORMAT_OVERWRITE | 171bf215546Sopenharmony_ci COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED); 172bf215546Sopenharmony_ci if (VIV_FEATURE(screen, chipMinorFeatures6, CACHE128B256BPERLINE)) 173bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT |= COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW); 174bf215546Sopenharmony_ci /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and 175bf215546Sopenharmony_ci * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state 176bf215546Sopenharmony_ci * but only if we set the bits above. */ 177bf215546Sopenharmony_ci /* merged with depth_stencil_alpha */ 178bf215546Sopenharmony_ci if ((cbuf->surf.offset & 63) || 179bf215546Sopenharmony_ci (((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) { 180bf215546Sopenharmony_ci /* XXX Must make temporary surface here. 181bf215546Sopenharmony_ci * Need the same mechanism on gc2000 when we want to do mipmap 182bf215546Sopenharmony_ci * generation by 183bf215546Sopenharmony_ci * rendering to levels > 1 due to multitiled / tiled conversion. */ 184bf215546Sopenharmony_ci BUG("Alignment error, trying to render to offset %08x with tile " 185bf215546Sopenharmony_ci "stride %i", 186bf215546Sopenharmony_ci cbuf->surf.offset, cbuf->surf.stride * 4); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci if (screen->specs.halti >= 0 && screen->model != 0x880) { 190bf215546Sopenharmony_ci /* Rendertargets on GPUs with more than a single pixel pipe must always 191bf215546Sopenharmony_ci * be multi-tiled, or single-buffer mode must be supported */ 192bf215546Sopenharmony_ci assert(screen->specs.pixel_pipes == 1 || 193bf215546Sopenharmony_ci (res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer); 194bf215546Sopenharmony_ci for (int i = 0; i < screen->specs.pixel_pipes; i++) { 195bf215546Sopenharmony_ci cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i]; 196bf215546Sopenharmony_ci cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci } else { 199bf215546Sopenharmony_ci cs->PE_COLOR_ADDR = cbuf->reloc[0]; 200bf215546Sopenharmony_ci cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci cs->PE_COLOR_STRIDE = cbuf->surf.stride; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci if (cbuf->surf.ts_size) { 206bf215546Sopenharmony_ci cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value; 207bf215546Sopenharmony_ci cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc; 210bf215546Sopenharmony_ci cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0]; 213bf215546Sopenharmony_ci cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci pe_mem_config |= VIVS_PE_MEM_CONFIG_COLOR_TS_MODE(cbuf->level->ts_mode); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci if (cbuf->level->ts_compress_fmt >= 0) { 218bf215546Sopenharmony_ci /* overwrite bit breaks v1/v2 compression */ 219bf215546Sopenharmony_ci if (!screen->specs.v4_compression) 220bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci ts_mem_config |= 223bf215546Sopenharmony_ci VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION | 224bf215546Sopenharmony_ci VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci nr_samples_color = cbuf->base.texture->nr_samples; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci if (util_format_is_srgb(cbuf->base.format)) 231bf215546Sopenharmony_ci pe_logic_op |= VIVS_PE_LOGIC_OP_SRGB; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci cs->PS_CONTROL = COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0); 234bf215546Sopenharmony_ci cs->PS_CONTROL_EXT = 235bf215546Sopenharmony_ci VIVS_PS_CONTROL_EXT_OUTPUT_MODE0(translate_output_mode(cbuf->base.format, screen->specs.halti >= 5)); 236bf215546Sopenharmony_ci } else { 237bf215546Sopenharmony_ci /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and 238bf215546Sopenharmony_ci * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the 239bf215546Sopenharmony_ci * color target */ 240bf215546Sopenharmony_ci cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE; 241bf215546Sopenharmony_ci cs->PE_COLOR_STRIDE = 0; 242bf215546Sopenharmony_ci cs->TS_COLOR_STATUS_BASE.bo = NULL; 243bf215546Sopenharmony_ci cs->TS_COLOR_SURFACE_BASE.bo = NULL; 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci cs->PE_COLOR_ADDR = screen->dummy_rt_reloc; 246bf215546Sopenharmony_ci for (int i = 0; i < screen->specs.pixel_pipes; i++) 247bf215546Sopenharmony_ci cs->PE_PIPE_COLOR_ADDR[i] = screen->dummy_rt_reloc; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if (fb->zsbuf != NULL) { 251bf215546Sopenharmony_ci struct etna_surface *zsbuf = etna_surface(fb->zsbuf); 252bf215546Sopenharmony_ci struct etna_resource *res = etna_resource(zsbuf->base.texture); 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci etna_update_render_resource(pctx, etna_resource(zsbuf->prsc)); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci uint32_t depth_format = translate_depth_format(zsbuf->base.format); 259bf215546Sopenharmony_ci unsigned depth_bits = 260bf215546Sopenharmony_ci depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24; 261bf215546Sopenharmony_ci bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if (depth_bits == 16) 264bf215546Sopenharmony_ci target_16bpp = true; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci cs->PE_DEPTH_CONFIG = 267bf215546Sopenharmony_ci depth_format | 268bf215546Sopenharmony_ci COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) | 269bf215546Sopenharmony_ci VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z | 270bf215546Sopenharmony_ci VIVS_PE_DEPTH_CONFIG_UNK18; /* something to do with clipping? */ 271bf215546Sopenharmony_ci /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ 272bf215546Sopenharmony_ci /* merged with depth_stencil_alpha */ 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci if (screen->specs.halti >= 0 && screen->model != 0x880) { 275bf215546Sopenharmony_ci for (int i = 0; i < screen->specs.pixel_pipes; i++) { 276bf215546Sopenharmony_ci cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i]; 277bf215546Sopenharmony_ci cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci } else { 280bf215546Sopenharmony_ci cs->PE_DEPTH_ADDR = zsbuf->reloc[0]; 281bf215546Sopenharmony_ci cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci cs->PE_DEPTH_STRIDE = zsbuf->surf.stride; 285bf215546Sopenharmony_ci cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED; 286bf215546Sopenharmony_ci cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f); 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci if (zsbuf->surf.ts_size) { 289bf215546Sopenharmony_ci cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc; 292bf215546Sopenharmony_ci cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0]; 295bf215546Sopenharmony_ci cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci pe_mem_config |= VIVS_PE_MEM_CONFIG_DEPTH_TS_MODE(zsbuf->level->ts_mode); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (zsbuf->level->ts_compress_fmt >= 0) { 300bf215546Sopenharmony_ci ts_mem_config |= 301bf215546Sopenharmony_ci VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION | 302bf215546Sopenharmony_ci COND(zsbuf->level->ts_compress_fmt == COMPRESSION_FORMAT_D24S8, 303bf215546Sopenharmony_ci VIVS_TS_MEM_CONFIG_STENCIL_ENABLE); 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP); 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci nr_samples_depth = zsbuf->base.texture->nr_samples; 310bf215546Sopenharmony_ci } else { 311bf215546Sopenharmony_ci cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE; 312bf215546Sopenharmony_ci cs->PE_DEPTH_ADDR.bo = NULL; 313bf215546Sopenharmony_ci cs->PE_DEPTH_STRIDE = 0; 314bf215546Sopenharmony_ci cs->TS_DEPTH_STATUS_BASE.bo = NULL; 315bf215546Sopenharmony_ci cs->TS_DEPTH_SURFACE_BASE.bo = NULL; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) 318bf215546Sopenharmony_ci cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL; 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci /* MSAA setup */ 322bf215546Sopenharmony_ci if (nr_samples_depth != -1 && nr_samples_color != -1 && 323bf215546Sopenharmony_ci nr_samples_depth != nr_samples_color) { 324bf215546Sopenharmony_ci BUG("Number of samples in color and depth texture must match (%i and %i respectively)", 325bf215546Sopenharmony_ci nr_samples_color, nr_samples_depth); 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci switch (MAX2(nr_samples_depth, nr_samples_color)) { 329bf215546Sopenharmony_ci case 0: 330bf215546Sopenharmony_ci case 1: /* Are 0 and 1 samples allowed? */ 331bf215546Sopenharmony_ci cs->GL_MULTI_SAMPLE_CONFIG = 332bf215546Sopenharmony_ci VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; 333bf215546Sopenharmony_ci cs->msaa_mode = false; 334bf215546Sopenharmony_ci break; 335bf215546Sopenharmony_ci case 2: 336bf215546Sopenharmony_ci cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; 337bf215546Sopenharmony_ci cs->msaa_mode = true; /* Add input to PS */ 338bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E04 = 0x0; 339bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22; 340bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[0] = 0x66aa2288; 341bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[1] = 0x88558800; 342bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[2] = 0x88881100; 343bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[3] = 0x33888800; 344bf215546Sopenharmony_ci break; 345bf215546Sopenharmony_ci case 4: 346bf215546Sopenharmony_ci cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; 347bf215546Sopenharmony_ci cs->msaa_mode = true; /* Add input to PS */ 348bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E04 = 0x0; 349bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26; 350bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a; 351bf215546Sopenharmony_ci cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22; 352bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[0] = 0x4a6e2688; 353bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[1] = 0x888888a2; 354bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[2] = 0x888888ea; 355bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[3] = 0x888888c6; 356bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[4] = 0x46622a88; 357bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[5] = 0x888888ae; 358bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[6] = 0x888888e6; 359bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[7] = 0x888888ca; 360bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[8] = 0x262a2288; 361bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[9] = 0x886688a2; 362bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[10] = 0x888866aa; 363bf215546Sopenharmony_ci cs->RA_CENTROID_TABLE[11] = 0x668888a6; 364bf215546Sopenharmony_ci break; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci cs->TS_MEM_CONFIG = ts_mem_config; 368bf215546Sopenharmony_ci cs->PE_MEM_CONFIG = pe_mem_config; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* Single buffer setup. There is only one switch for this, not a separate 371bf215546Sopenharmony_ci * one per color buffer / depth buffer. To keep the logic simple always use 372bf215546Sopenharmony_ci * single buffer when this feature is available. 373bf215546Sopenharmony_ci */ 374bf215546Sopenharmony_ci if (unlikely(target_linear)) 375bf215546Sopenharmony_ci pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(1); 376bf215546Sopenharmony_ci else if (screen->specs.single_buffer) 377bf215546Sopenharmony_ci pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(target_16bpp ? 3 : 2); 378bf215546Sopenharmony_ci cs->PE_LOGIC_OP = pe_logic_op; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci /* keep copy of original structure */ 381bf215546Sopenharmony_ci util_copy_framebuffer_state(&ctx->framebuffer_s, fb); 382bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS; 383bf215546Sopenharmony_ci} 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_cistatic void 386bf215546Sopenharmony_cietna_set_polygon_stipple(struct pipe_context *pctx, 387bf215546Sopenharmony_ci const struct pipe_poly_stipple *stipple) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci /* NOP */ 390bf215546Sopenharmony_ci} 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_cistatic void 393bf215546Sopenharmony_cietna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot, 394bf215546Sopenharmony_ci unsigned num_scissors, const struct pipe_scissor_state *ss) 395bf215546Sopenharmony_ci{ 396bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 397bf215546Sopenharmony_ci assert(ss->minx <= ss->maxx); 398bf215546Sopenharmony_ci assert(ss->miny <= ss->maxy); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci ctx->scissor = *ss; 401bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_SCISSOR; 402bf215546Sopenharmony_ci} 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_cistatic void 405bf215546Sopenharmony_cietna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot, 406bf215546Sopenharmony_ci unsigned num_scissors, const struct pipe_viewport_state *vs) 407bf215546Sopenharmony_ci{ 408bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 409bf215546Sopenharmony_ci struct compiled_viewport_state *cs = &ctx->viewport; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci ctx->viewport_s = *vs; 412bf215546Sopenharmony_ci /** 413bf215546Sopenharmony_ci * For Vivante GPU, viewport z transformation is 0..1 to 0..1 instead of 414bf215546Sopenharmony_ci * -1..1 to 0..1. 415bf215546Sopenharmony_ci * scaling and translation to 0..1 already happened, so remove that 416bf215546Sopenharmony_ci * 417bf215546Sopenharmony_ci * z' = (z * 2 - 1) * scale + translate 418bf215546Sopenharmony_ci * = z * (2 * scale) + (translate - scale) 419bf215546Sopenharmony_ci * 420bf215546Sopenharmony_ci * scale' = 2 * scale 421bf215546Sopenharmony_ci * translate' = translate - scale 422bf215546Sopenharmony_ci */ 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci /* must be fixp as v4 state deltas assume it is */ 425bf215546Sopenharmony_ci cs->PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16(vs->scale[0]); 426bf215546Sopenharmony_ci cs->PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16(vs->scale[1]); 427bf215546Sopenharmony_ci cs->PA_VIEWPORT_SCALE_Z = fui(vs->scale[2] * 2.0f); 428bf215546Sopenharmony_ci cs->PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16(vs->translate[0]); 429bf215546Sopenharmony_ci cs->PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16(vs->translate[1]); 430bf215546Sopenharmony_ci cs->PA_VIEWPORT_OFFSET_Z = fui(vs->translate[2] - vs->scale[2]); 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci /* Compute scissor rectangle (fixp) from viewport. 433bf215546Sopenharmony_ci * Make sure left is always < right and top always < bottom. 434bf215546Sopenharmony_ci */ 435bf215546Sopenharmony_ci cs->SE_SCISSOR_LEFT = MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f); 436bf215546Sopenharmony_ci cs->SE_SCISSOR_TOP = MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f); 437bf215546Sopenharmony_ci cs->SE_SCISSOR_RIGHT = ceilf(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f)); 438bf215546Sopenharmony_ci cs->SE_SCISSOR_BOTTOM = ceilf(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f)); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */ 441bf215546Sopenharmony_ci cs->PE_DEPTH_FAR = fui(1.0); 442bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_VIEWPORT; 443bf215546Sopenharmony_ci} 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_cistatic void 446bf215546Sopenharmony_cietna_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot, 447bf215546Sopenharmony_ci unsigned num_buffers, unsigned unbind_num_trailing_slots, bool take_ownership, 448bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vb) 449bf215546Sopenharmony_ci{ 450bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 451bf215546Sopenharmony_ci struct etna_vertexbuf_state *so = &ctx->vertex_buffer; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, 454bf215546Sopenharmony_ci num_buffers, unbind_num_trailing_slots, 455bf215546Sopenharmony_ci take_ownership); 456bf215546Sopenharmony_ci so->count = util_last_bit(so->enabled_mask); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci for (unsigned idx = start_slot; idx < start_slot + num_buffers; ++idx) { 459bf215546Sopenharmony_ci struct compiled_set_vertex_buffer *cs = &so->cvb[idx]; 460bf215546Sopenharmony_ci struct pipe_vertex_buffer *vbi = &so->vb[idx]; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci assert(!vbi->is_user_buffer); /* XXX support user_buffer using 463bf215546Sopenharmony_ci etna_usermem_map */ 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci if (vbi->buffer.resource) { /* GPU buffer */ 466bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer.resource)->bo; 467bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_BASE_ADDR.offset = vbi->buffer_offset; 468bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ; 469bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_CONTROL = 470bf215546Sopenharmony_ci FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(vbi->stride); 471bf215546Sopenharmony_ci } else { 472bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_BASE_ADDR.bo = NULL; 473bf215546Sopenharmony_ci cs->FE_VERTEX_STREAM_CONTROL = 0; 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_VERTEX_BUFFERS; 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic void 481bf215546Sopenharmony_cietna_blend_state_bind(struct pipe_context *pctx, void *bs) 482bf215546Sopenharmony_ci{ 483bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci ctx->blend = bs; 486bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_BLEND; 487bf215546Sopenharmony_ci} 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_cistatic void 490bf215546Sopenharmony_cietna_blend_state_delete(struct pipe_context *pctx, void *bs) 491bf215546Sopenharmony_ci{ 492bf215546Sopenharmony_ci FREE(bs); 493bf215546Sopenharmony_ci} 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_cistatic void 496bf215546Sopenharmony_cietna_rasterizer_state_bind(struct pipe_context *pctx, void *rs) 497bf215546Sopenharmony_ci{ 498bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci ctx->rasterizer = rs; 501bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_RASTERIZER; 502bf215546Sopenharmony_ci} 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_cistatic void 505bf215546Sopenharmony_cietna_rasterizer_state_delete(struct pipe_context *pctx, void *rs) 506bf215546Sopenharmony_ci{ 507bf215546Sopenharmony_ci FREE(rs); 508bf215546Sopenharmony_ci} 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_cistatic void 511bf215546Sopenharmony_cietna_zsa_state_bind(struct pipe_context *pctx, void *zs) 512bf215546Sopenharmony_ci{ 513bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci ctx->zsa = zs; 516bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_ZSA; 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_cistatic void 520bf215546Sopenharmony_cietna_zsa_state_delete(struct pipe_context *pctx, void *zs) 521bf215546Sopenharmony_ci{ 522bf215546Sopenharmony_ci FREE(zs); 523bf215546Sopenharmony_ci} 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci/** Create vertex element states, which define a layout for fetching 526bf215546Sopenharmony_ci * vertices for rendering. 527bf215546Sopenharmony_ci */ 528bf215546Sopenharmony_cistatic void * 529bf215546Sopenharmony_cietna_vertex_elements_state_create(struct pipe_context *pctx, 530bf215546Sopenharmony_ci unsigned num_elements, const struct pipe_vertex_element *elements) 531bf215546Sopenharmony_ci{ 532bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 533bf215546Sopenharmony_ci struct etna_screen *screen = ctx->screen; 534bf215546Sopenharmony_ci struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state); 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci if (!cs) 537bf215546Sopenharmony_ci return NULL; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci if (num_elements > screen->specs.vertex_max_elements) { 540bf215546Sopenharmony_ci BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements, 541bf215546Sopenharmony_ci screen->specs.vertex_max_elements); 542bf215546Sopenharmony_ci FREE(cs); 543bf215546Sopenharmony_ci return NULL; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci /* XXX could minimize number of consecutive stretches here by sorting, and 547bf215546Sopenharmony_ci * permuting the inputs in shader or does Mesa do this already? */ 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci cs->num_elements = num_elements; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci unsigned start_offset = 0; /* start of current consecutive stretch */ 552bf215546Sopenharmony_ci bool nonconsecutive = true; /* previous value of nonconsecutive */ 553bf215546Sopenharmony_ci uint32_t buffer_mask = 0; /* mask of buffer_idx already seen */ 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci for (unsigned idx = 0; idx < num_elements; ++idx) { 556bf215546Sopenharmony_ci unsigned buffer_idx = elements[idx].vertex_buffer_index; 557bf215546Sopenharmony_ci unsigned element_size = util_format_get_blocksize(elements[idx].src_format); 558bf215546Sopenharmony_ci unsigned end_offset = elements[idx].src_offset + element_size; 559bf215546Sopenharmony_ci uint32_t format_type, normalize; 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci if (nonconsecutive) 562bf215546Sopenharmony_ci start_offset = elements[idx].src_offset; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci /* guaranteed by PIPE_CAP_MAX_VERTEX_BUFFERS */ 565bf215546Sopenharmony_ci assert(buffer_idx < screen->specs.stream_count); 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci /* maximum vertex size is 256 bytes */ 568bf215546Sopenharmony_ci assert(element_size != 0 && (end_offset - start_offset) < 256); 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci /* check whether next element is consecutive to this one */ 571bf215546Sopenharmony_ci nonconsecutive = (idx == (num_elements - 1)) || 572bf215546Sopenharmony_ci elements[idx + 1].vertex_buffer_index != buffer_idx || 573bf215546Sopenharmony_ci end_offset != elements[idx + 1].src_offset; 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci format_type = translate_vertex_format_type(elements[idx].src_format); 576bf215546Sopenharmony_ci normalize = translate_vertex_format_normalize(elements[idx].src_format); 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci assert(format_type != ETNA_NO_MATCH); 579bf215546Sopenharmony_ci assert(normalize != ETNA_NO_MATCH); 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci if (screen->specs.halti < 5) { 582bf215546Sopenharmony_ci cs->FE_VERTEX_ELEMENT_CONFIG[idx] = 583bf215546Sopenharmony_ci COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) | 584bf215546Sopenharmony_ci format_type | 585bf215546Sopenharmony_ci VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) | 586bf215546Sopenharmony_ci normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | 587bf215546Sopenharmony_ci VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(buffer_idx) | 588bf215546Sopenharmony_ci VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) | 589bf215546Sopenharmony_ci VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset); 590bf215546Sopenharmony_ci } else { /* HALTI5 spread vertex attrib config over two registers */ 591bf215546Sopenharmony_ci cs->NFE_GENERIC_ATTRIB_CONFIG0[idx] = 592bf215546Sopenharmony_ci format_type | 593bf215546Sopenharmony_ci VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM(util_format_get_nr_components(elements[idx].src_format)) | 594bf215546Sopenharmony_ci normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN(ENDIAN_MODE_NO_SWAP) | 595bf215546Sopenharmony_ci VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(buffer_idx) | 596bf215546Sopenharmony_ci VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START(elements[idx].src_offset); 597bf215546Sopenharmony_ci cs->NFE_GENERIC_ATTRIB_CONFIG1[idx] = 598bf215546Sopenharmony_ci COND(nonconsecutive, VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE) | 599bf215546Sopenharmony_ci VIVS_NFE_GENERIC_ATTRIB_CONFIG1_END(end_offset - start_offset); 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci if (util_format_is_pure_integer(elements[idx].src_format)) 603bf215546Sopenharmony_ci cs->NFE_GENERIC_ATTRIB_SCALE[idx] = 1; 604bf215546Sopenharmony_ci else 605bf215546Sopenharmony_ci cs->NFE_GENERIC_ATTRIB_SCALE[idx] = fui(1.0f); 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci /* instance_divisor is part of elements state but should be the same for all buffers */ 608bf215546Sopenharmony_ci if (buffer_mask & 1 << buffer_idx) 609bf215546Sopenharmony_ci assert(cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] == elements[idx].instance_divisor); 610bf215546Sopenharmony_ci else 611bf215546Sopenharmony_ci cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] = elements[idx].instance_divisor; 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci buffer_mask |= 1 << buffer_idx; 614bf215546Sopenharmony_ci cs->num_buffers = MAX2(cs->num_buffers, buffer_idx + 1); 615bf215546Sopenharmony_ci } 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci return cs; 618bf215546Sopenharmony_ci} 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_cistatic void 621bf215546Sopenharmony_cietna_vertex_elements_state_delete(struct pipe_context *pctx, void *ve) 622bf215546Sopenharmony_ci{ 623bf215546Sopenharmony_ci FREE(ve); 624bf215546Sopenharmony_ci} 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_cistatic void 627bf215546Sopenharmony_cietna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve) 628bf215546Sopenharmony_ci{ 629bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci ctx->vertex_elements = ve; 632bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS; 633bf215546Sopenharmony_ci} 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_cistatic void 636bf215546Sopenharmony_cietna_set_stream_output_targets(struct pipe_context *pctx, 637bf215546Sopenharmony_ci unsigned num_targets, struct pipe_stream_output_target **targets, 638bf215546Sopenharmony_ci const unsigned *offsets) 639bf215546Sopenharmony_ci{ 640bf215546Sopenharmony_ci /* stub */ 641bf215546Sopenharmony_ci} 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_cistatic bool 644bf215546Sopenharmony_cietna_update_ts_config(struct etna_context *ctx) 645bf215546Sopenharmony_ci{ 646bf215546Sopenharmony_ci uint32_t new_ts_config = ctx->framebuffer.TS_MEM_CONFIG; 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci if (ctx->framebuffer_s.nr_cbufs > 0) { 649bf215546Sopenharmony_ci struct etna_surface *c_surf = etna_surface(ctx->framebuffer_s.cbufs[0]); 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci if(c_surf->level->ts_size && c_surf->level->ts_valid) { 652bf215546Sopenharmony_ci new_ts_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; 653bf215546Sopenharmony_ci } else { 654bf215546Sopenharmony_ci new_ts_config &= ~VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR; 655bf215546Sopenharmony_ci } 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci if (ctx->framebuffer_s.zsbuf) { 659bf215546Sopenharmony_ci struct etna_surface *zs_surf = etna_surface(ctx->framebuffer_s.zsbuf); 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci if(zs_surf->level->ts_size && zs_surf->level->ts_valid) { 662bf215546Sopenharmony_ci new_ts_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; 663bf215546Sopenharmony_ci } else { 664bf215546Sopenharmony_ci new_ts_config &= ~VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR; 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci if (new_ts_config != ctx->framebuffer.TS_MEM_CONFIG || 669bf215546Sopenharmony_ci (ctx->dirty & ETNA_DIRTY_FRAMEBUFFER)) { 670bf215546Sopenharmony_ci ctx->framebuffer.TS_MEM_CONFIG = new_ts_config; 671bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_TS; 672bf215546Sopenharmony_ci } 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci ctx->dirty &= ~ETNA_DIRTY_DERIVE_TS; 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci return true; 677bf215546Sopenharmony_ci} 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_cistatic bool 680bf215546Sopenharmony_cietna_update_clipping(struct etna_context *ctx) 681bf215546Sopenharmony_ci{ 682bf215546Sopenharmony_ci const struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer); 683bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci /* clip framebuffer against viewport */ 686bf215546Sopenharmony_ci uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT; 687bf215546Sopenharmony_ci uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP; 688bf215546Sopenharmony_ci uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT); 689bf215546Sopenharmony_ci uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM); 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci /* clip against scissor */ 692bf215546Sopenharmony_ci if (rasterizer->scissor) { 693bf215546Sopenharmony_ci scissor_left = MAX2(ctx->scissor.minx, scissor_left); 694bf215546Sopenharmony_ci scissor_top = MAX2(ctx->scissor.miny, scissor_top); 695bf215546Sopenharmony_ci scissor_right = MIN2(ctx->scissor.maxx, scissor_right); 696bf215546Sopenharmony_ci scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom); 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci ctx->clipping.minx = scissor_left; 700bf215546Sopenharmony_ci ctx->clipping.miny = scissor_top; 701bf215546Sopenharmony_ci ctx->clipping.maxx = scissor_right; 702bf215546Sopenharmony_ci ctx->clipping.maxy = scissor_bottom; 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_SCISSOR_CLIP; 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci return true; 707bf215546Sopenharmony_ci} 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_cistatic bool 710bf215546Sopenharmony_cietna_update_zsa(struct etna_context *ctx) 711bf215546Sopenharmony_ci{ 712bf215546Sopenharmony_ci struct compiled_shader_state *shader_state = &ctx->shader_state; 713bf215546Sopenharmony_ci struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa; 714bf215546Sopenharmony_ci struct etna_zsa_state *zsa = etna_zsa_state(zsa_state); 715bf215546Sopenharmony_ci struct etna_screen *screen = ctx->screen; 716bf215546Sopenharmony_ci uint32_t new_pe_depth, new_ra_depth; 717bf215546Sopenharmony_ci bool early_z_allowed = !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z); 718bf215546Sopenharmony_ci bool late_z_write = false, early_z_write = false, 719bf215546Sopenharmony_ci late_z_test = false, early_z_test = false; 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci /* Linear PE breaks the combination of early test with late write, as it 722bf215546Sopenharmony_ci * seems RA and PE disagree about the buffer layout in this mode. Fall back 723bf215546Sopenharmony_ci * to late Z always even though early Z write might be possible, as we don't 724bf215546Sopenharmony_ci * know if any other draws to the same surface require late Z write. 725bf215546Sopenharmony_ci */ 726bf215546Sopenharmony_ci if (ctx->framebuffer_s.nr_cbufs > 0) { 727bf215546Sopenharmony_ci struct etna_surface *cbuf = etna_surface(ctx->framebuffer_s.cbufs[0]); 728bf215546Sopenharmony_ci struct etna_resource *res = etna_resource(cbuf->base.texture); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci if (res->layout == ETNA_LAYOUT_LINEAR) 731bf215546Sopenharmony_ci early_z_allowed = false; 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci if (zsa->z_write_enabled) { 735bf215546Sopenharmony_ci if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) && 736bf215546Sopenharmony_ci early_z_allowed && 737bf215546Sopenharmony_ci !zsa->stencil_enabled && 738bf215546Sopenharmony_ci !zsa_state->alpha_enabled && 739bf215546Sopenharmony_ci !shader_state->writes_z && 740bf215546Sopenharmony_ci !shader_state->uses_discard) 741bf215546Sopenharmony_ci early_z_write = true; 742bf215546Sopenharmony_ci else 743bf215546Sopenharmony_ci late_z_write = true; 744bf215546Sopenharmony_ci } 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci if (zsa->z_test_enabled) { 747bf215546Sopenharmony_ci if (early_z_allowed && 748bf215546Sopenharmony_ci !zsa->stencil_modified && 749bf215546Sopenharmony_ci !shader_state->writes_z) 750bf215546Sopenharmony_ci early_z_test = true; 751bf215546Sopenharmony_ci else 752bf215546Sopenharmony_ci late_z_test = true; 753bf215546Sopenharmony_ci } 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ? 756bf215546Sopenharmony_ci /* compare funcs have 1 to 1 mapping */ 757bf215546Sopenharmony_ci zsa_state->depth_func : PIPE_FUNC_ALWAYS) | 758bf215546Sopenharmony_ci COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) | 759bf215546Sopenharmony_ci COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) | 760bf215546Sopenharmony_ci COND(!late_z_write && !late_z_test && !zsa->stencil_enabled, 761bf215546Sopenharmony_ci VIVS_PE_DEPTH_CONFIG_DISABLE_ZS); 762bf215546Sopenharmony_ci 763bf215546Sopenharmony_ci /* blob sets this to 0x40000031 on GC7000, seems to make no difference, 764bf215546Sopenharmony_ci * but keep it in mind if depth behaves strangely. */ 765bf215546Sopenharmony_ci new_ra_depth = 0x0000030 | 766bf215546Sopenharmony_ci COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE); 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)) { 769bf215546Sopenharmony_ci if (!early_z_write) 770bf215546Sopenharmony_ci new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE; 771bf215546Sopenharmony_ci /* The new early hierarchical test seems to only work properly if depth 772bf215546Sopenharmony_ci * is also written from the early stage. 773bf215546Sopenharmony_ci */ 774bf215546Sopenharmony_ci if (late_z_test || (early_z_test && late_z_write)) 775bf215546Sopenharmony_ci new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE; 776bf215546Sopenharmony_ci } 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci if (new_pe_depth != zsa->PE_DEPTH_CONFIG || 779bf215546Sopenharmony_ci new_ra_depth != zsa->RA_DEPTH_CONFIG) 780bf215546Sopenharmony_ci ctx->dirty |= ETNA_DIRTY_ZSA; 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci zsa->PE_DEPTH_CONFIG = new_pe_depth; 783bf215546Sopenharmony_ci zsa->RA_DEPTH_CONFIG = new_ra_depth; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci return true; 786bf215546Sopenharmony_ci} 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_cistatic bool 789bf215546Sopenharmony_cietna_record_flush_resources(struct etna_context *ctx) 790bf215546Sopenharmony_ci{ 791bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &ctx->framebuffer_s; 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci if (fb->nr_cbufs > 0) { 794bf215546Sopenharmony_ci struct etna_surface *surf = etna_surface(fb->cbufs[0]); 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_ci if (!etna_resource(surf->prsc)->explicit_flush) { 797bf215546Sopenharmony_ci bool found; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci _mesa_set_search_or_add(ctx->flush_resources, surf->prsc, &found); 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci if (!found) 802bf215546Sopenharmony_ci pipe_reference(NULL, &surf->prsc->reference); 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci } 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci return true; 807bf215546Sopenharmony_ci} 808bf215546Sopenharmony_ci 809bf215546Sopenharmony_cistruct etna_state_updater { 810bf215546Sopenharmony_ci bool (*update)(struct etna_context *ctx); 811bf215546Sopenharmony_ci uint32_t dirty; 812bf215546Sopenharmony_ci}; 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_cistatic const struct etna_state_updater etna_state_updates[] = { 815bf215546Sopenharmony_ci { 816bf215546Sopenharmony_ci etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS, 817bf215546Sopenharmony_ci }, 818bf215546Sopenharmony_ci { 819bf215546Sopenharmony_ci etna_shader_link, ETNA_DIRTY_SHADER, 820bf215546Sopenharmony_ci }, 821bf215546Sopenharmony_ci { 822bf215546Sopenharmony_ci etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER 823bf215546Sopenharmony_ci }, 824bf215546Sopenharmony_ci { 825bf215546Sopenharmony_ci etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER, 826bf215546Sopenharmony_ci }, 827bf215546Sopenharmony_ci { 828bf215546Sopenharmony_ci etna_update_ts_config, ETNA_DIRTY_DERIVE_TS, 829bf215546Sopenharmony_ci }, 830bf215546Sopenharmony_ci { 831bf215546Sopenharmony_ci etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | 832bf215546Sopenharmony_ci ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT, 833bf215546Sopenharmony_ci }, 834bf215546Sopenharmony_ci { 835bf215546Sopenharmony_ci etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER | 836bf215546Sopenharmony_ci ETNA_DIRTY_FRAMEBUFFER, 837bf215546Sopenharmony_ci }, 838bf215546Sopenharmony_ci { 839bf215546Sopenharmony_ci etna_record_flush_resources, ETNA_DIRTY_FRAMEBUFFER, 840bf215546Sopenharmony_ci } 841bf215546Sopenharmony_ci}; 842bf215546Sopenharmony_ci 843bf215546Sopenharmony_cibool 844bf215546Sopenharmony_cietna_state_update(struct etna_context *ctx) 845bf215546Sopenharmony_ci{ 846bf215546Sopenharmony_ci for (unsigned int i = 0; i < ARRAY_SIZE(etna_state_updates); i++) 847bf215546Sopenharmony_ci if (ctx->dirty & etna_state_updates[i].dirty) 848bf215546Sopenharmony_ci if (!etna_state_updates[i].update(ctx)) 849bf215546Sopenharmony_ci return false; 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci return true; 852bf215546Sopenharmony_ci} 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_civoid 855bf215546Sopenharmony_cietna_state_init(struct pipe_context *pctx) 856bf215546Sopenharmony_ci{ 857bf215546Sopenharmony_ci pctx->set_blend_color = etna_set_blend_color; 858bf215546Sopenharmony_ci pctx->set_stencil_ref = etna_set_stencil_ref; 859bf215546Sopenharmony_ci pctx->set_clip_state = etna_set_clip_state; 860bf215546Sopenharmony_ci pctx->set_sample_mask = etna_set_sample_mask; 861bf215546Sopenharmony_ci pctx->set_constant_buffer = etna_set_constant_buffer; 862bf215546Sopenharmony_ci pctx->set_framebuffer_state = etna_set_framebuffer_state; 863bf215546Sopenharmony_ci pctx->set_polygon_stipple = etna_set_polygon_stipple; 864bf215546Sopenharmony_ci pctx->set_scissor_states = etna_set_scissor_states; 865bf215546Sopenharmony_ci pctx->set_viewport_states = etna_set_viewport_states; 866bf215546Sopenharmony_ci 867bf215546Sopenharmony_ci pctx->set_vertex_buffers = etna_set_vertex_buffers; 868bf215546Sopenharmony_ci 869bf215546Sopenharmony_ci pctx->bind_blend_state = etna_blend_state_bind; 870bf215546Sopenharmony_ci pctx->delete_blend_state = etna_blend_state_delete; 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_ci pctx->bind_rasterizer_state = etna_rasterizer_state_bind; 873bf215546Sopenharmony_ci pctx->delete_rasterizer_state = etna_rasterizer_state_delete; 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci pctx->bind_depth_stencil_alpha_state = etna_zsa_state_bind; 876bf215546Sopenharmony_ci pctx->delete_depth_stencil_alpha_state = etna_zsa_state_delete; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci pctx->create_vertex_elements_state = etna_vertex_elements_state_create; 879bf215546Sopenharmony_ci pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete; 880bf215546Sopenharmony_ci pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind; 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci pctx->set_stream_output_targets = etna_set_stream_output_targets; 883bf215546Sopenharmony_ci} 884