1/* 2 * Copyright (c) 2012-2017 Etnaviv Project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sub license, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Wladimir J. van der Laan <laanwj@gmail.com> 25 */ 26 27#include "etnaviv_rs.h" 28 29#include "etnaviv_clear_blit.h" 30#include "etnaviv_context.h" 31#include "etnaviv_emit.h" 32#include "etnaviv_format.h" 33#include "etnaviv_resource.h" 34#include "etnaviv_screen.h" 35#include "etnaviv_surface.h" 36#include "etnaviv_tiling.h" 37#include "etnaviv_translate.h" 38#include "etnaviv_util.h" 39 40#include "pipe/p_defines.h" 41#include "pipe/p_state.h" 42#include "util/compiler.h" 43#include "util/u_blitter.h" 44#include "util/u_inlines.h" 45#include "util/u_memory.h" 46#include "util/u_surface.h" 47 48#include "hw/common.xml.h" 49#include "hw/state.xml.h" 50#include "hw/state_3d.xml.h" 51 52#include <assert.h> 53 54/* return a RS "compatible" format for use when copying */ 55static uint32_t 56etna_compatible_rs_format(enum pipe_format fmt) 57{ 58 /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */ 59 if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY) 60 return RS_FORMAT_A4R4G4B4; 61 62 switch (util_format_get_blocksize(fmt)) { 63 case 2: return RS_FORMAT_A4R4G4B4; 64 case 4: return RS_FORMAT_A8R8G8B8; 65 default: return ETNA_NO_MATCH; 66 } 67} 68 69void 70etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs, 71 const struct rs_state *rs) 72{ 73 struct etna_screen *screen = ctx->screen; 74 75 memset(cs, 0, sizeof(*cs)); 76 77 /* TILED and SUPERTILED layout have their strides multiplied with 4 in RS */ 78 unsigned source_stride_shift = COND(rs->source_tiling != ETNA_LAYOUT_LINEAR, 2); 79 unsigned dest_stride_shift = COND(rs->dest_tiling != ETNA_LAYOUT_LINEAR, 2); 80 81 bool src_tiled = rs->source_tiling & ETNA_LAYOUT_BIT_TILE; 82 bool dst_tiled = rs->dest_tiling & ETNA_LAYOUT_BIT_TILE; 83 bool src_super = rs->source_tiling & ETNA_LAYOUT_BIT_SUPER; 84 bool dst_super = rs->dest_tiling & ETNA_LAYOUT_BIT_SUPER; 85 bool src_multi = rs->source_tiling & ETNA_LAYOUT_BIT_MULTI; 86 bool dst_multi = rs->dest_tiling & ETNA_LAYOUT_BIT_MULTI; 87 88 /* Vivante RS needs widths to be a multiple of 16 or bad things 89 * happen, such as scribbing over memory, or the GPU hanging, 90 * even for non-tiled formats. As this is serious, use abort(). 91 */ 92 if (rs->width & ETNA_RS_WIDTH_MASK) 93 abort(); 94 95 /* TODO could just pre-generate command buffer, would simply submit to one memcpy */ 96 cs->RS_CONFIG = VIVS_RS_CONFIG_SOURCE_FORMAT(rs->source_format) | 97 COND(rs->downsample_x, VIVS_RS_CONFIG_DOWNSAMPLE_X) | 98 COND(rs->downsample_y, VIVS_RS_CONFIG_DOWNSAMPLE_Y) | 99 COND(src_tiled, VIVS_RS_CONFIG_SOURCE_TILED) | 100 VIVS_RS_CONFIG_DEST_FORMAT(rs->dest_format) | 101 COND(dst_tiled, VIVS_RS_CONFIG_DEST_TILED) | 102 COND(rs->swap_rb, VIVS_RS_CONFIG_SWAP_RB) | 103 COND(rs->flip, VIVS_RS_CONFIG_FLIP); 104 105 cs->RS_SOURCE_STRIDE = (rs->source_stride << source_stride_shift) | 106 COND(src_super, VIVS_RS_SOURCE_STRIDE_TILING) | 107 COND(src_multi, VIVS_RS_SOURCE_STRIDE_MULTI); 108 109 if (VIV_FEATURE(ctx->screen, chipMinorFeatures6, CACHE128B256BPERLINE)) 110 cs->RS_SOURCE_STRIDE |= VIVS_RS_SOURCE_STRIDE_TS_MODE(rs->source_ts_mode) | 111 COND(src_super, VIVS_RS_SOURCE_STRIDE_SUPER_TILED_NEW); 112 113 /* Initially all pipes are set to the base address of the source and 114 * destination buffer respectively. This will be overridden below as 115 * necessary for the multi-pipe, multi-tiled case. 116 */ 117 for (unsigned pipe = 0; pipe < screen->specs.pixel_pipes; ++pipe) { 118 cs->source[pipe].bo = rs->source; 119 cs->source[pipe].offset = rs->source_offset; 120 cs->source[pipe].flags = ETNA_RELOC_READ; 121 122 cs->dest[pipe].bo = rs->dest; 123 cs->dest[pipe].offset = rs->dest_offset; 124 cs->dest[pipe].flags = ETNA_RELOC_WRITE; 125 126 cs->RS_PIPE_OFFSET[pipe] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0); 127 } 128 129 cs->RS_DEST_STRIDE = (rs->dest_stride << dest_stride_shift) | 130 COND(dst_super, VIVS_RS_DEST_STRIDE_TILING) | 131 COND(dst_multi, VIVS_RS_DEST_STRIDE_MULTI); 132 133 if (VIV_FEATURE(ctx->screen, chipMinorFeatures6, CACHE128B256BPERLINE)) 134 cs->RS_DEST_STRIDE |= COND(dst_super, VIVS_RS_DEST_STRIDE_SUPER_TILED_NEW); 135 136 if (src_multi) 137 cs->source[1].offset = rs->source_offset + rs->source_stride * rs->source_padded_height / 2; 138 139 if (dst_multi) 140 cs->dest[1].offset = rs->dest_offset + rs->dest_stride * rs->dest_padded_height / 2; 141 142 cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) | 143 VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height); 144 145 /* use dual pipe mode when required */ 146 if (!screen->specs.single_buffer && screen->specs.pixel_pipes == 2 && !(rs->height & 7)) { 147 cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) | 148 VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height / 2); 149 cs->RS_PIPE_OFFSET[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs->height / 2); 150 } 151 152 cs->RS_DITHER[0] = rs->dither[0]; 153 cs->RS_DITHER[1] = rs->dither[1]; 154 cs->RS_CLEAR_CONTROL = VIVS_RS_CLEAR_CONTROL_BITS(rs->clear_bits) | rs->clear_mode; 155 cs->RS_FILL_VALUE[0] = rs->clear_value[0]; 156 cs->RS_FILL_VALUE[1] = rs->clear_value[1]; 157 cs->RS_FILL_VALUE[2] = rs->clear_value[2]; 158 cs->RS_FILL_VALUE[3] = rs->clear_value[3]; 159 cs->RS_EXTRA_CONFIG = VIVS_RS_EXTRA_CONFIG_AA(rs->aa) | 160 VIVS_RS_EXTRA_CONFIG_ENDIAN(rs->endian_mode); 161 162 /* If source the same as destination, and the hardware supports this, 163 * do an in-place resolve to fill in unrendered tiles. 164 */ 165 if (screen->specs.single_buffer && rs->source == rs->dest && 166 rs->source_offset == rs->dest_offset && 167 rs->source_format == rs->dest_format && 168 rs->source_tiling == rs->dest_tiling && 169 src_super && 170 rs->source_stride == rs->dest_stride && 171 !rs->downsample_x && !rs->downsample_y && 172 !rs->swap_rb && !rs->flip && 173 !rs->clear_mode && rs->source_padded_width && 174 !rs->source_ts_compressed) { 175 /* Total number of tiles (same as for autodisable) */ 176 cs->RS_KICKER_INPLACE = rs->tile_count; 177 } 178 cs->source_ts_valid = rs->source_ts_valid; 179} 180 181/* modify the clear bits value in the compiled RS state */ 182static void 183etna_modify_rs_clearbits(struct compiled_rs_state *cs, uint32_t clear_bits) 184{ 185 cs->RS_CLEAR_CONTROL &= ~VIVS_RS_CLEAR_CONTROL_BITS__MASK; 186 cs->RS_CLEAR_CONTROL |= VIVS_RS_CLEAR_CONTROL_BITS(clear_bits); 187} 188 189#define EMIT_STATE(state_name, src_value) \ 190 etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value) 191 192#define EMIT_STATE_FIXP(state_name, src_value) \ 193 etna_coalsence_emit_fixp(stream, &coalesce, VIVS_##state_name, src_value) 194 195#define EMIT_STATE_RELOC(state_name, src_value) \ 196 etna_coalsence_emit_reloc(stream, &coalesce, VIVS_##state_name, src_value) 197 198/* submit RS state, without any processing and no dependence on context 199 * except TS if this is a source-to-destination blit. */ 200static void 201etna_submit_rs_state(struct etna_context *ctx, 202 const struct compiled_rs_state *cs) 203{ 204 struct etna_screen *screen = etna_screen(ctx->base.screen); 205 struct etna_cmd_stream *stream = ctx->stream; 206 struct etna_coalesce coalesce; 207 208 if (cs->RS_KICKER_INPLACE && !cs->source_ts_valid) 209 /* Inplace resolve is no-op if TS is not configured */ 210 return; 211 212 ctx->stats.rs_operations++; 213 214 if (cs->RS_KICKER_INPLACE) { 215 etna_cmd_stream_reserve(stream, 6); 216 etna_coalesce_start(stream, &coalesce); 217 /* 0/1 */ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); 218 /* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); 219 /* 4/5 */ EMIT_STATE(RS_KICKER_INPLACE, cs->RS_KICKER_INPLACE); 220 etna_coalesce_end(stream, &coalesce); 221 } else if (screen->specs.pixel_pipes > 1 || 222 VIV_FEATURE(screen, chipMinorFeatures7, RS_NEW_BASEADDR)) { 223 etna_cmd_stream_reserve(stream, 34); /* worst case - both pipes multi=1 */ 224 etna_coalesce_start(stream, &coalesce); 225 /* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG); 226 /* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); 227 /* 4/5 */ EMIT_STATE(RS_DEST_STRIDE, cs->RS_DEST_STRIDE); 228 /* 6/7 */ EMIT_STATE_RELOC(RS_PIPE_SOURCE_ADDR(0), &cs->source[0]); 229 if (cs->RS_SOURCE_STRIDE & VIVS_RS_SOURCE_STRIDE_MULTI) { 230 /*8 */ EMIT_STATE_RELOC(RS_PIPE_SOURCE_ADDR(1), &cs->source[1]); 231 /*9 - pad */ 232 } 233 /*10/11*/ EMIT_STATE_RELOC(RS_PIPE_DEST_ADDR(0), &cs->dest[0]); 234 if (cs->RS_DEST_STRIDE & VIVS_RS_DEST_STRIDE_MULTI) { 235 /*12*/ EMIT_STATE_RELOC(RS_PIPE_DEST_ADDR(1), &cs->dest[1]); 236 /*13 - pad */ 237 } 238 /*14/15*/ EMIT_STATE(RS_PIPE_OFFSET(0), cs->RS_PIPE_OFFSET[0]); 239 /*16 */ EMIT_STATE(RS_PIPE_OFFSET(1), cs->RS_PIPE_OFFSET[1]); 240 /*17 - pad */ 241 /*18/19*/ EMIT_STATE(RS_WINDOW_SIZE, cs->RS_WINDOW_SIZE); 242 /*20/21*/ EMIT_STATE(RS_DITHER(0), cs->RS_DITHER[0]); 243 /*22 */ EMIT_STATE(RS_DITHER(1), cs->RS_DITHER[1]); 244 /*23 - pad */ 245 /*24/25*/ EMIT_STATE(RS_CLEAR_CONTROL, cs->RS_CLEAR_CONTROL); 246 /*26 */ EMIT_STATE(RS_FILL_VALUE(0), cs->RS_FILL_VALUE[0]); 247 /*27 */ EMIT_STATE(RS_FILL_VALUE(1), cs->RS_FILL_VALUE[1]); 248 /*28 */ EMIT_STATE(RS_FILL_VALUE(2), cs->RS_FILL_VALUE[2]); 249 /*29 */ EMIT_STATE(RS_FILL_VALUE(3), cs->RS_FILL_VALUE[3]); 250 /*30/31*/ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); 251 /*32/33*/ EMIT_STATE(RS_KICKER, 0xbeebbeeb); 252 etna_coalesce_end(stream, &coalesce); 253 } else { 254 etna_cmd_stream_reserve(stream, 22); 255 etna_coalesce_start(stream, &coalesce); 256 /* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG); 257 /* 2 */ EMIT_STATE_RELOC(RS_SOURCE_ADDR, &cs->source[0]); 258 /* 3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE); 259 /* 4 */ EMIT_STATE_RELOC(RS_DEST_ADDR, &cs->dest[0]); 260 /* 5 */ EMIT_STATE(RS_DEST_STRIDE, cs->RS_DEST_STRIDE); 261 /* 6/7 */ EMIT_STATE(RS_WINDOW_SIZE, cs->RS_WINDOW_SIZE); 262 /* 8/9 */ EMIT_STATE(RS_DITHER(0), cs->RS_DITHER[0]); 263 /*10 */ EMIT_STATE(RS_DITHER(1), cs->RS_DITHER[1]); 264 /*11 - pad */ 265 /*12/13*/ EMIT_STATE(RS_CLEAR_CONTROL, cs->RS_CLEAR_CONTROL); 266 /*14 */ EMIT_STATE(RS_FILL_VALUE(0), cs->RS_FILL_VALUE[0]); 267 /*15 */ EMIT_STATE(RS_FILL_VALUE(1), cs->RS_FILL_VALUE[1]); 268 /*16 */ EMIT_STATE(RS_FILL_VALUE(2), cs->RS_FILL_VALUE[2]); 269 /*17 */ EMIT_STATE(RS_FILL_VALUE(3), cs->RS_FILL_VALUE[3]); 270 /*18/19*/ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG); 271 /*20/21*/ EMIT_STATE(RS_KICKER, 0xbeebbeeb); 272 etna_coalesce_end(stream, &coalesce); 273 } 274} 275 276/* Generate clear command for a surface (non-fast clear case) */ 277void 278etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf, 279 uint64_t clear_value) 280{ 281 ASSERTED struct etna_screen *screen = ctx->screen; 282 struct etna_resource *dst = etna_resource(surf->base.texture); 283 uint32_t format; 284 285 switch (util_format_get_blocksizebits(surf->base.format)) { 286 case 16: 287 format = RS_FORMAT_A4R4G4B4; 288 break; 289 case 32: 290 format = RS_FORMAT_A8R8G8B8; 291 break; 292 case 64: 293 assert(screen->specs.halti >= 2); 294 format = RS_FORMAT_64BPP_CLEAR; 295 break; 296 default: 297 unreachable("bpp not supported for clear by RS"); 298 break; 299 } 300 301 /* use tiled clear if width is multiple of 16 */ 302 bool tiled_clear = (surf->surf.padded_width & ETNA_RS_WIDTH_MASK) == 0 && 303 (surf->surf.padded_height & ETNA_RS_HEIGHT_MASK) == 0; 304 305 etna_compile_rs_state( ctx, &surf->clear_command, &(struct rs_state) { 306 .source_format = format, 307 .dest_format = format, 308 .dest = dst->bo, 309 .dest_offset = surf->surf.offset, 310 .dest_stride = surf->surf.stride, 311 .dest_padded_height = surf->surf.padded_height, 312 .dest_tiling = tiled_clear ? dst->layout : ETNA_LAYOUT_LINEAR, 313 .dither = {0xffffffff, 0xffffffff}, 314 .width = surf->surf.padded_width, /* These must be padded to 16x4 if !LINEAR, otherwise RS will hang */ 315 .height = surf->surf.padded_height, 316 .clear_value = {clear_value, clear_value >> 32, clear_value, clear_value >> 32}, 317 .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1, 318 .clear_bits = 0xffff 319 }); 320} 321 322static void 323etna_blit_clear_color_rs(struct pipe_context *pctx, struct pipe_surface *dst, 324 const union pipe_color_union *color) 325{ 326 struct etna_context *ctx = etna_context(pctx); 327 struct etna_surface *surf = etna_surface(dst); 328 uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color); 329 330 if (surf->surf.ts_size) { /* TS: use precompiled clear command */ 331 ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value; 332 ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32; 333 334 if (VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) { 335 /* Set number of color tiles to be filled */ 336 etna_set_state(ctx->stream, VIVS_TS_COLOR_AUTO_DISABLE_COUNT, 337 surf->surf.padded_width * surf->surf.padded_height / 16); 338 ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_COLOR_AUTO_DISABLE; 339 } 340 341 surf->level->ts_valid = true; 342 ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; 343 } else if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */ 344 /* If clear color changed, re-generate stored command */ 345 etna_rs_gen_clear_surface(ctx, surf, new_clear_value); 346 } 347 348 etna_submit_rs_state(ctx, &surf->clear_command); 349 350 surf->level->clear_value = new_clear_value; 351 resource_written(ctx, surf->base.texture); 352 etna_resource(surf->base.texture)->seqno++; 353} 354 355static void 356etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst, 357 unsigned buffers, double depth, unsigned stencil) 358{ 359 struct etna_context *ctx = etna_context(pctx); 360 struct etna_surface *surf = etna_surface(dst); 361 uint32_t new_clear_value = translate_clear_depth_stencil(surf->base.format, depth, stencil); 362 uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil; 363 364 /* Get the channels to clear */ 365 switch (surf->base.format) { 366 case PIPE_FORMAT_Z16_UNORM: 367 clear_bits_depth = 0xffff; 368 clear_bits_stencil = 0; 369 break; 370 case PIPE_FORMAT_X8Z24_UNORM: 371 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 372 clear_bits_depth = 0xeeee; 373 clear_bits_stencil = 0x1111; 374 break; 375 default: 376 clear_bits_depth = clear_bits_stencil = 0xffff; 377 break; 378 } 379 380 if (buffers & PIPE_CLEAR_DEPTH) 381 new_clear_bits |= clear_bits_depth; 382 if (buffers & PIPE_CLEAR_STENCIL) 383 new_clear_bits |= clear_bits_stencil; 384 /* FIXME: when tile status is enabled, this becomes more complex as 385 * we may separately clear the depth from the stencil. In this case, 386 * we want to resolve the surface, and avoid using the tile status. 387 * We may be better off recording the pending clear operation, 388 * delaying the actual clear to the first use. This way, we can merge 389 * consecutive clears together. */ 390 if (surf->surf.ts_size) { /* TS: use precompiled clear command */ 391 /* Set new clear depth value */ 392 ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value; 393 if (VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) { 394 /* Set number of depth tiles to be filled */ 395 etna_set_state(ctx->stream, VIVS_TS_DEPTH_AUTO_DISABLE_COUNT, 396 surf->surf.padded_width * surf->surf.padded_height / 16); 397 ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_DEPTH_AUTO_DISABLE; 398 } 399 400 surf->level->ts_valid = true; 401 ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; 402 } else { 403 if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */ 404 /* If clear depth value changed, re-generate stored command */ 405 etna_rs_gen_clear_surface(ctx, surf, new_clear_value); 406 } 407 /* Update the channels to be cleared */ 408 etna_modify_rs_clearbits(&surf->clear_command, new_clear_bits); 409 } 410 411 etna_submit_rs_state(ctx, &surf->clear_command); 412 413 surf->level->clear_value = new_clear_value; 414 resource_written(ctx, surf->base.texture); 415 etna_resource(surf->base.texture)->seqno++; 416} 417 418static void 419etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state, 420 const union pipe_color_union *color, double depth, unsigned stencil) 421{ 422 struct etna_context *ctx = etna_context(pctx); 423 424 /* Flush color and depth cache before clearing anything. 425 * This is especially important when coming from another surface, as 426 * otherwise it may clear part of the old surface instead. */ 427 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); 428 etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); 429 430 /* Preparation: Flush the TS if needed. This must be done after flushing 431 * color and depth, otherwise it can result in crashes */ 432 bool need_ts_flush = false; 433 if ((buffers & PIPE_CLEAR_COLOR) && ctx->framebuffer_s.nr_cbufs) { 434 struct etna_surface *surf = etna_surface(ctx->framebuffer_s.cbufs[0]); 435 if (surf->surf.ts_size) 436 need_ts_flush = true; 437 } 438 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) { 439 struct etna_surface *surf = etna_surface(ctx->framebuffer_s.zsbuf); 440 441 if (surf->surf.ts_size) 442 need_ts_flush = true; 443 } 444 445 if (need_ts_flush) 446 etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); 447 448 /* No need to set up the TS here as RS clear operations (in contrast to 449 * resolve and copy) do not require the TS state. 450 */ 451 if (buffers & PIPE_CLEAR_COLOR) { 452 for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) { 453 etna_blit_clear_color_rs(pctx, ctx->framebuffer_s.cbufs[idx], 454 &color[idx]); 455 } 456 } 457 458 /* Flush the color and depth caches before each RS clear operation 459 * This fixes a hang on GC600. */ 460 if (buffers & PIPE_CLEAR_DEPTHSTENCIL && buffers & PIPE_CLEAR_COLOR) 461 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 462 VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); 463 464 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) 465 etna_blit_clear_zs_rs(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil); 466 467 etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); 468} 469 470static bool 471etna_manual_blit(struct etna_resource *dst, struct etna_resource_level *dst_lev, 472 unsigned int dst_offset, struct etna_resource *src, 473 struct etna_resource_level *src_lev, unsigned int src_offset, 474 const struct pipe_blit_info *blit_info) 475{ 476 void *smap, *srow, *dmap, *drow; 477 size_t tile_size; 478 479 assert(src->layout == ETNA_LAYOUT_TILED); 480 assert(dst->layout == ETNA_LAYOUT_TILED); 481 assert(src->base.nr_samples == 0); 482 assert(dst->base.nr_samples == 0); 483 484 tile_size = util_format_get_blocksize(blit_info->src.format) * 4 * 4; 485 486 smap = etna_bo_map(src->bo); 487 if (!smap) 488 return false; 489 490 dmap = etna_bo_map(dst->bo); 491 if (!dmap) 492 return false; 493 494 srow = smap + src_offset; 495 drow = dmap + dst_offset; 496 497 etna_bo_cpu_prep(src->bo, DRM_ETNA_PREP_READ); 498 etna_bo_cpu_prep(dst->bo, DRM_ETNA_PREP_WRITE); 499 500 for (int y = 0; y < blit_info->src.box.height; y += 4) { 501 memcpy(drow, srow, tile_size * blit_info->src.box.width); 502 srow += src_lev->stride * 4; 503 drow += dst_lev->stride * 4; 504 } 505 506 etna_bo_cpu_fini(dst->bo); 507 etna_bo_cpu_fini(src->bo); 508 509 return true; 510} 511 512static inline size_t 513etna_compute_tileoffset(const struct pipe_box *box, enum pipe_format format, 514 size_t stride, enum etna_surface_layout layout) 515{ 516 size_t offset; 517 unsigned int x = box->x, y = box->y; 518 unsigned int blocksize = util_format_get_blocksize(format); 519 520 switch (layout) { 521 case ETNA_LAYOUT_LINEAR: 522 offset = y * stride + x * blocksize; 523 break; 524 case ETNA_LAYOUT_MULTI_TILED: 525 y >>= 1; 526 FALLTHROUGH; 527 case ETNA_LAYOUT_TILED: 528 assert(!(x & 0x03) && !(y & 0x03)); 529 offset = (y & ~0x03) * stride + blocksize * ((x & ~0x03) << 2); 530 break; 531 case ETNA_LAYOUT_MULTI_SUPERTILED: 532 y >>= 1; 533 FALLTHROUGH; 534 case ETNA_LAYOUT_SUPER_TILED: 535 assert(!(x & 0x3f) && !(y & 0x3f)); 536 offset = (y & ~0x3f) * stride + blocksize * ((x & ~0x3f) << 6); 537 break; 538 default: 539 unreachable("invalid resource layout"); 540 } 541 542 return offset; 543} 544 545static inline void 546etna_get_rs_alignment_mask(const struct etna_context *ctx, 547 const enum etna_surface_layout layout, 548 unsigned int *width_mask, unsigned int *height_mask) 549{ 550 struct etna_screen *screen = ctx->screen; 551 unsigned int h_align, w_align; 552 553 if (layout & ETNA_LAYOUT_BIT_SUPER) { 554 w_align = 64; 555 h_align = 64 * screen->specs.pixel_pipes; 556 } else { 557 w_align = ETNA_RS_WIDTH_MASK + 1; 558 h_align = ETNA_RS_HEIGHT_MASK + 1; 559 } 560 561 *width_mask = w_align - 1; 562 *height_mask = h_align -1; 563} 564 565static bool msaa_config(const struct pipe_resource *src, 566 const struct pipe_resource *dst, 567 int *msaa_xscale, 568 int *msaa_yscale) 569{ 570 int src_xscale = 1, src_yscale = 1; 571 int dst_xscale = 1, dst_yscale = 1; 572 573 assert(src->nr_samples <= 4); 574 assert(dst->nr_samples <= 4); 575 576 translate_samples_to_xyscale(src->nr_samples, &src_xscale, &src_yscale); 577 translate_samples_to_xyscale(dst->nr_samples, &dst_xscale, &dst_yscale); 578 579 /* RS does not support upscaling */ 580 if ((src_xscale < dst_xscale) || (src_yscale < dst_yscale)) 581 return false; 582 583 *msaa_xscale = src_xscale - dst_xscale + 1; 584 *msaa_yscale = src_yscale - dst_yscale + 1; 585 586 return true; 587} 588 589static bool 590etna_try_rs_blit(struct pipe_context *pctx, 591 const struct pipe_blit_info *blit_info) 592{ 593 struct etna_context *ctx = etna_context(pctx); 594 struct etna_resource *src = etna_resource(blit_info->src.resource); 595 struct etna_resource *dst = etna_resource(blit_info->dst.resource); 596 struct compiled_rs_state copy_to_screen; 597 int msaa_xscale = 1, msaa_yscale = 1; 598 599 /* Ensure that the level is valid */ 600 assert(blit_info->src.level <= src->base.last_level); 601 assert(blit_info->dst.level <= dst->base.last_level); 602 603 if (!msaa_config(&src->base, &dst->base, &msaa_xscale, &msaa_yscale)) { 604 DBG("upsampling not supported"); 605 return false; 606 } 607 608 /* The width/height are in pixels; they do not change as a result of 609 * multi-sampling. So, when blitting from a 4x multisampled surface 610 * to a non-multisampled surface, the width and height will be 611 * identical. As we do not support scaling, reject different sizes. */ 612 if (blit_info->dst.box.width != blit_info->src.box.width || 613 blit_info->dst.box.height != blit_info->src.box.height) { 614 DBG("scaling requested: source %dx%d destination %dx%d", 615 blit_info->src.box.width, blit_info->src.box.height, 616 blit_info->dst.box.width, blit_info->dst.box.height); 617 return false; 618 } 619 620 /* No masks - RS can't copy specific channels */ 621 unsigned mask = util_format_get_mask(blit_info->dst.format); 622 if ((blit_info->mask & mask) != mask) { 623 DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info->mask, mask); 624 return false; 625 } 626 627 /* Only support same format (used tiling/detiling) blits for now. 628 * TODO: figure out which different-format blits are possible and test them 629 * - fail if swizzle needed 630 * - avoid trying to convert between float/int formats? 631 */ 632 if (blit_info->src.format != blit_info->dst.format) 633 return false; 634 635 uint32_t format = etna_compatible_rs_format(blit_info->dst.format); 636 if (format == ETNA_NO_MATCH) 637 return false; 638 639 if (blit_info->scissor_enable || 640 blit_info->dst.box.depth != blit_info->src.box.depth || 641 blit_info->dst.box.depth != 1) { 642 return false; 643 } 644 645 unsigned w_mask, h_mask; 646 647 etna_get_rs_alignment_mask(ctx, src->layout, &w_mask, &h_mask); 648 if ((blit_info->src.box.x & w_mask) || (blit_info->src.box.y & h_mask)) 649 return false; 650 651 etna_get_rs_alignment_mask(ctx, dst->layout, &w_mask, &h_mask); 652 if ((blit_info->dst.box.x & w_mask) || (blit_info->dst.box.y & h_mask)) 653 return false; 654 655 struct etna_resource_level *src_lev = &src->levels[blit_info->src.level]; 656 struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level]; 657 658 /* we may be given coordinates up to the padded width to avoid 659 * any alignment issues with different tiling formats */ 660 assert((blit_info->src.box.x + blit_info->src.box.width) * msaa_xscale <= src_lev->padded_width); 661 assert((blit_info->src.box.y + blit_info->src.box.height) * msaa_yscale <= src_lev->padded_height); 662 assert(blit_info->dst.box.x + blit_info->dst.box.width <= dst_lev->padded_width); 663 assert(blit_info->dst.box.y + blit_info->dst.box.height <= dst_lev->padded_height); 664 665 unsigned src_offset = src_lev->offset + 666 blit_info->src.box.z * src_lev->layer_stride + 667 etna_compute_tileoffset(&blit_info->src.box, 668 blit_info->src.format, 669 src_lev->stride, 670 src->layout); 671 unsigned dst_offset = dst_lev->offset + 672 blit_info->dst.box.z * dst_lev->layer_stride + 673 etna_compute_tileoffset(&blit_info->dst.box, 674 blit_info->dst.format, 675 dst_lev->stride, 676 dst->layout); 677 678 if (src_lev->padded_width <= ETNA_RS_WIDTH_MASK || 679 dst_lev->padded_width <= ETNA_RS_WIDTH_MASK || 680 src_lev->padded_height <= ETNA_RS_HEIGHT_MASK || 681 dst_lev->padded_height <= ETNA_RS_HEIGHT_MASK) 682 goto manual; 683 684 /* If the width is not aligned to the RS width, but is within our 685 * padding, adjust the width to suite the RS width restriction. 686 * Note: the RS width/height are converted to source samples here. */ 687 unsigned int width = blit_info->src.box.width * msaa_xscale; 688 unsigned int height = blit_info->src.box.height * msaa_yscale; 689 unsigned int w_align = ETNA_RS_WIDTH_MASK + 1; 690 unsigned int h_align = ETNA_RS_HEIGHT_MASK + 1; 691 692 if (width & (w_align - 1) && width >= src_lev->width * msaa_xscale && width >= dst_lev->width) 693 width = align(width, w_align); 694 695 if (height & (h_align - 1) && height >= src_lev->height * msaa_yscale && height >= dst_lev->height) 696 height = align(height, h_align); 697 698 /* The padded dimensions are in samples */ 699 if (width > src_lev->padded_width || 700 width > dst_lev->padded_width * msaa_xscale || 701 height > src_lev->padded_height || 702 height > dst_lev->padded_height * msaa_yscale || 703 width & (w_align - 1) || height & (h_align - 1)) 704 goto manual; 705 706 /* Always flush color and depth cache together before resolving. This works 707 * around artifacts that appear in some cases when scanning out a texture 708 * directly after it has been rendered to, such as rendering an animated web 709 * page in a QtWebEngine based WebView on GC2000. The artifacts look like 710 * the texture sampler samples zeroes instead of texture data in a small, 711 * irregular triangle in the lower right of each browser tile quad. Other 712 * attempts to avoid these artifacts, including a pipeline stall before the 713 * color flush or a TS cache flush afterwards, or flushing multiple times, 714 * with stalls before and after each flush, have shown no effect. */ 715 if (src->base.bind & PIPE_BIND_RENDER_TARGET || 716 src->base.bind & PIPE_BIND_DEPTH_STENCIL) { 717 etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 718 VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH); 719 etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE); 720 721 if (src_lev->ts_size && src_lev->ts_valid) 722 etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); 723 } 724 725 /* Set up color TS to source surface before blit, if needed */ 726 bool source_ts_valid = false; 727 if (src_lev->ts_size && src_lev->ts_valid) { 728 struct etna_reloc reloc; 729 unsigned ts_offset = 730 src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride; 731 uint32_t ts_mem_config = 0; 732 733 if (src_lev->ts_compress_fmt >= 0) { 734 ts_mem_config |= VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION | 735 VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(src_lev->ts_compress_fmt); 736 } 737 738 etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, 739 VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | ts_mem_config); 740 741 memset(&reloc, 0, sizeof(struct etna_reloc)); 742 reloc.bo = src->ts_bo; 743 reloc.offset = ts_offset; 744 reloc.flags = ETNA_RELOC_READ; 745 etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_STATUS_BASE, &reloc); 746 747 memset(&reloc, 0, sizeof(struct etna_reloc)); 748 reloc.bo = src->bo; 749 reloc.offset = src_lev->offset + 750 blit_info->src.box.z * src_lev->layer_stride; 751 reloc.flags = ETNA_RELOC_READ; 752 etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_SURFACE_BASE, &reloc); 753 754 etna_set_state(ctx->stream, VIVS_TS_COLOR_CLEAR_VALUE, src_lev->clear_value); 755 etna_set_state(ctx->stream, VIVS_TS_COLOR_CLEAR_VALUE_EXT, src_lev->clear_value >> 32); 756 757 source_ts_valid = true; 758 } else { 759 etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, 0); 760 } 761 ctx->dirty |= ETNA_DIRTY_TS; 762 763 /* Kick off RS here */ 764 etna_compile_rs_state(ctx, ©_to_screen, &(struct rs_state) { 765 .source_format = format, 766 .source_tiling = src->layout, 767 .source = src->bo, 768 .source_offset = src_offset, 769 .source_stride = src_lev->stride, 770 .source_padded_width = src_lev->padded_width, 771 .source_padded_height = src_lev->padded_height, 772 .source_ts_valid = source_ts_valid, 773 .source_ts_mode = src_lev->ts_mode, 774 .source_ts_compressed = src_lev->ts_compress_fmt >= 0, 775 .dest_format = format, 776 .dest_tiling = dst->layout, 777 .dest = dst->bo, 778 .dest_offset = dst_offset, 779 .dest_stride = dst_lev->stride, 780 .dest_padded_height = dst_lev->padded_height, 781 .downsample_x = msaa_xscale > 1, 782 .downsample_y = msaa_yscale > 1, 783 .swap_rb = translate_rb_src_dst_swap(src->base.format, dst->base.format), 784 .dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit? 785 .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED, 786 .width = width, 787 .height = height, 788 .tile_count = src_lev->layer_stride / 789 etna_screen_get_tile_size(ctx->screen, src_lev->ts_mode), 790 }); 791 792 etna_submit_rs_state(ctx, ©_to_screen); 793 resource_read(ctx, &src->base); 794 resource_written(ctx, &dst->base); 795 dst->seqno++; 796 dst_lev->ts_valid = false; 797 ctx->dirty |= ETNA_DIRTY_DERIVE_TS; 798 799 return true; 800 801manual: 802 if (src->layout == ETNA_LAYOUT_TILED && dst->layout == ETNA_LAYOUT_TILED) { 803 if ((etna_resource_status(ctx, src) & ETNA_PENDING_WRITE) || 804 (etna_resource_status(ctx, dst) & ETNA_PENDING_WRITE)) 805 pctx->flush(pctx, NULL, 0); 806 return etna_manual_blit(dst, dst_lev, dst_offset, src, src_lev, src_offset, blit_info); 807 } 808 809 return false; 810} 811 812static bool 813etna_blit_rs(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 814{ 815 /* This is a more extended version of resource_copy_region */ 816 /* TODO Some cases can be handled by RS; if not, fall back to rendering or 817 * even CPU copy block of pixels from info->src to info->dst 818 * (resource, level, box, format); 819 * function is used for scaling, flipping in x and y direction (negative 820 * width/height), format conversion, mask and filter and even a scissor rectangle 821 * 822 * What can the RS do for us: 823 * convert between tiling formats (layouts) 824 * downsample 2x in x and y 825 * convert between a limited number of pixel formats 826 * 827 * For the rest, fall back to util_blitter 828 * XXX this goes wrong when source surface is supertiled. */ 829 830 if (blit_info->src.resource->nr_samples > 1 && 831 blit_info->dst.resource->nr_samples <= 1 && 832 !util_format_is_depth_or_stencil(blit_info->src.resource->format) && 833 !util_format_is_pure_integer(blit_info->src.resource->format)) { 834 DBG("color resolve unimplemented"); 835 return false; 836 } 837 838 return etna_try_rs_blit(pctx, blit_info); 839} 840 841void 842etna_clear_blit_rs_init(struct pipe_context *pctx) 843{ 844 struct etna_context *ctx = etna_context(pctx); 845 846 DBG("etnaviv: Using RS blit engine"); 847 pctx->clear = etna_clear_rs; 848 ctx->blit = etna_blit_rs; 849} 850