1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2012-2013 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 */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "etnaviv_surface.h" 28bf215546Sopenharmony_ci#include "etnaviv_screen.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "etnaviv_clear_blit.h" 31bf215546Sopenharmony_ci#include "etnaviv_context.h" 32bf215546Sopenharmony_ci#include "etnaviv_translate.h" 33bf215546Sopenharmony_ci#include "pipe/p_defines.h" 34bf215546Sopenharmony_ci#include "pipe/p_state.h" 35bf215546Sopenharmony_ci#include "util/u_inlines.h" 36bf215546Sopenharmony_ci#include "util/u_math.h" 37bf215546Sopenharmony_ci#include "util/u_memory.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "hw/common.xml.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic struct etna_resource * 44bf215546Sopenharmony_cietna_render_handle_incompatible(struct pipe_context *pctx, 45bf215546Sopenharmony_ci struct pipe_resource *prsc, 46bf215546Sopenharmony_ci unsigned int level) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 49bf215546Sopenharmony_ci struct etna_screen *screen = ctx->screen; 50bf215546Sopenharmony_ci struct etna_resource *res = etna_resource(prsc); 51bf215546Sopenharmony_ci bool need_multitiled = screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer; 52bf215546Sopenharmony_ci bool want_supertiled = screen->specs.can_supertile; 53bf215546Sopenharmony_ci unsigned int min_tilesize = etna_screen_get_tile_size(screen, TS_MODE_128B); 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci /* Resource is compatible if it is tiled or PE is able to render to linear 56bf215546Sopenharmony_ci * and has multi tiling when required. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_ci if ((res->layout != ETNA_LAYOUT_LINEAR || 59bf215546Sopenharmony_ci (VIV_FEATURE(screen, chipMinorFeatures2, LINEAR_PE) && 60bf215546Sopenharmony_ci (!VIV_FEATURE(screen, chipFeatures, FAST_CLEAR) || 61bf215546Sopenharmony_ci res->levels[level].stride % min_tilesize == 0))) && 62bf215546Sopenharmony_ci (!need_multitiled || (res->layout & ETNA_LAYOUT_BIT_MULTI))) 63bf215546Sopenharmony_ci return res; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci if (!res->render) { 66bf215546Sopenharmony_ci struct pipe_resource templat = *prsc; 67bf215546Sopenharmony_ci unsigned layout = ETNA_LAYOUT_TILED; 68bf215546Sopenharmony_ci if (need_multitiled) 69bf215546Sopenharmony_ci layout |= ETNA_LAYOUT_BIT_MULTI; 70bf215546Sopenharmony_ci if (want_supertiled) 71bf215546Sopenharmony_ci layout |= ETNA_LAYOUT_BIT_SUPER; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci templat.bind &= (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | 74bf215546Sopenharmony_ci PIPE_BIND_BLENDABLE); 75bf215546Sopenharmony_ci res->render = 76bf215546Sopenharmony_ci etna_resource_alloc(pctx->screen, layout, 77bf215546Sopenharmony_ci DRM_FORMAT_MOD_LINEAR, &templat); 78bf215546Sopenharmony_ci assert(res->render); 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci return etna_resource(res->render); 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic struct pipe_surface * 84bf215546Sopenharmony_cietna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc, 85bf215546Sopenharmony_ci const struct pipe_surface *templat) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci struct etna_context *ctx = etna_context(pctx); 88bf215546Sopenharmony_ci struct etna_screen *screen = ctx->screen; 89bf215546Sopenharmony_ci unsigned layer = templat->u.tex.first_layer; 90bf215546Sopenharmony_ci unsigned level = templat->u.tex.level; 91bf215546Sopenharmony_ci struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc, level); 92bf215546Sopenharmony_ci struct etna_surface *surf = CALLOC_STRUCT(etna_surface); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (!surf) 95bf215546Sopenharmony_ci return NULL; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci assert(templat->u.tex.first_layer == templat->u.tex.last_layer); 98bf215546Sopenharmony_ci assert(layer <= util_max_layer(prsc, level)); 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci surf->base.context = pctx; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci pipe_reference_init(&surf->base.reference, 1); 103bf215546Sopenharmony_ci pipe_resource_reference(&surf->base.texture, &rsc->base); 104bf215546Sopenharmony_ci pipe_resource_reference(&surf->prsc, prsc); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci /* Allocate a TS for the resource if there isn't one yet, 107bf215546Sopenharmony_ci * and it is allowed by the hw (width is a multiple of 16). 108bf215546Sopenharmony_ci * Avoid doing this for GPUs with MC1.0, as kernel sources 109bf215546Sopenharmony_ci * indicate the tile status module bypasses the memory 110bf215546Sopenharmony_ci * offset and MMU. */ 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (VIV_FEATURE(screen, chipFeatures, FAST_CLEAR) && 113bf215546Sopenharmony_ci !rsc->ts_bo && 114bf215546Sopenharmony_ci /* needs to be RS/BLT compatible for transfer_map/unmap */ 115bf215546Sopenharmony_ci (rsc->levels[level].padded_width & ETNA_RS_WIDTH_MASK) == 0 && 116bf215546Sopenharmony_ci (rsc->levels[level].padded_height & ETNA_RS_HEIGHT_MASK) == 0 && 117bf215546Sopenharmony_ci etna_resource_hw_tileable(screen->specs.use_blt, prsc)) { 118bf215546Sopenharmony_ci etna_screen_resource_alloc_ts(pctx->screen, rsc); 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci surf->base.format = templat->format; 122bf215546Sopenharmony_ci surf->base.width = rsc->levels[level].width; 123bf215546Sopenharmony_ci surf->base.height = rsc->levels[level].height; 124bf215546Sopenharmony_ci surf->base.writable = templat->writable; /* what is this for anyway */ 125bf215546Sopenharmony_ci surf->base.u = templat->u; 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci surf->level = &rsc->levels[level]; /* Keep pointer to actual level to set 128bf215546Sopenharmony_ci * clear color on underlying resource 129bf215546Sopenharmony_ci * instead of surface */ 130bf215546Sopenharmony_ci surf->surf = rsc->levels [level]; /* Make copy of level to narrow down 131bf215546Sopenharmony_ci * address to layer */ 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* XXX we don't really need a copy but it's convenient */ 134bf215546Sopenharmony_ci surf->surf.offset += layer * surf->surf.layer_stride; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci struct etna_resource_level *lev = &rsc->levels[level]; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* Setup template relocations for this surface */ 139bf215546Sopenharmony_ci for (unsigned pipe = 0; pipe < screen->specs.pixel_pipes; ++pipe) { 140bf215546Sopenharmony_ci surf->reloc[pipe].bo = rsc->bo; 141bf215546Sopenharmony_ci surf->reloc[pipe].offset = surf->surf.offset; 142bf215546Sopenharmony_ci surf->reloc[pipe].flags = 0; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci /* In single buffer mode, both pixel pipes must point to the same address, 146bf215546Sopenharmony_ci * for multi-tiled surfaces on the other hand the second pipe is expected to 147bf215546Sopenharmony_ci * point halfway the image vertically. 148bf215546Sopenharmony_ci */ 149bf215546Sopenharmony_ci if (rsc->layout & ETNA_LAYOUT_BIT_MULTI) 150bf215546Sopenharmony_ci surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (surf->surf.ts_size) { 153bf215546Sopenharmony_ci unsigned int layer_offset = layer * surf->surf.ts_layer_stride; 154bf215546Sopenharmony_ci assert(layer_offset < surf->surf.ts_size); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci surf->surf.ts_offset += layer_offset; 157bf215546Sopenharmony_ci surf->surf.ts_size -= layer_offset; 158bf215546Sopenharmony_ci surf->surf.ts_valid = false; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci surf->ts_reloc.bo = rsc->ts_bo; 161bf215546Sopenharmony_ci surf->ts_reloc.offset = surf->surf.ts_offset; 162bf215546Sopenharmony_ci surf->ts_reloc.flags = 0; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci if (!screen->specs.use_blt) { 165bf215546Sopenharmony_ci /* This (ab)uses the RS as a plain buffer memset(). 166bf215546Sopenharmony_ci * Currently uses a fixed row size of 64 bytes. Some benchmarking with 167bf215546Sopenharmony_ci * different sizes may be in order. */ 168bf215546Sopenharmony_ci struct etna_bo *ts_bo = etna_resource(surf->base.texture)->ts_bo; 169bf215546Sopenharmony_ci etna_compile_rs_state(ctx, &surf->clear_command, &(struct rs_state) { 170bf215546Sopenharmony_ci .source_format = RS_FORMAT_A8R8G8B8, 171bf215546Sopenharmony_ci .dest_format = RS_FORMAT_A8R8G8B8, 172bf215546Sopenharmony_ci .dest = ts_bo, 173bf215546Sopenharmony_ci .dest_offset = surf->surf.ts_offset, 174bf215546Sopenharmony_ci .dest_stride = 0x40, 175bf215546Sopenharmony_ci .dest_tiling = ETNA_LAYOUT_TILED, 176bf215546Sopenharmony_ci .dither = {0xffffffff, 0xffffffff}, 177bf215546Sopenharmony_ci .width = 16, 178bf215546Sopenharmony_ci .height = align(surf->surf.ts_size / 0x40, 4), 179bf215546Sopenharmony_ci .clear_value = {screen->specs.ts_clear_value}, 180bf215546Sopenharmony_ci .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1, 181bf215546Sopenharmony_ci .clear_bits = 0xffff 182bf215546Sopenharmony_ci }); 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci } else { 185bf215546Sopenharmony_ci if (!screen->specs.use_blt) 186bf215546Sopenharmony_ci etna_rs_gen_clear_surface(ctx, surf, surf->level->clear_value); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci return &surf->base; 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_cistatic void 193bf215546Sopenharmony_cietna_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci pipe_resource_reference(&psurf->texture, NULL); 196bf215546Sopenharmony_ci pipe_resource_reference(&etna_surface(psurf)->prsc, NULL); 197bf215546Sopenharmony_ci FREE(psurf); 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_civoid 201bf215546Sopenharmony_cietna_surface_init(struct pipe_context *pctx) 202bf215546Sopenharmony_ci{ 203bf215546Sopenharmony_ci pctx->create_surface = etna_create_surface; 204bf215546Sopenharmony_ci pctx->surface_destroy = etna_surface_destroy; 205bf215546Sopenharmony_ci} 206