19f464c52Smaya/* 29f464c52Smaya * Copyright (c) 2017-2019 Lima Project 39f464c52Smaya * 49f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a 59f464c52Smaya * copy of this software and associated documentation files (the "Software"), 69f464c52Smaya * to deal in the Software without restriction, including without limitation 79f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sub license, 89f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the 99f464c52Smaya * Software is furnished to do so, subject to the following conditions: 109f464c52Smaya * 119f464c52Smaya * The above copyright notice and this permission notice (including the 129f464c52Smaya * next paragraph) shall be included in all copies or substantial portions 139f464c52Smaya * of the Software. 149f464c52Smaya * 159f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 169f464c52Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 179f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 189f464c52Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 199f464c52Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 209f464c52Smaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 219f464c52Smaya * DEALINGS IN THE SOFTWARE. 229f464c52Smaya * 239f464c52Smaya */ 249f464c52Smaya 259f464c52Smaya#include "util/u_memory.h" 269f464c52Smaya#include "util/u_blitter.h" 277ec681f3Smrg#include "util/format/u_format.h" 289f464c52Smaya#include "util/u_inlines.h" 299f464c52Smaya#include "util/u_math.h" 309f464c52Smaya#include "util/u_debug.h" 319f464c52Smaya#include "util/u_transfer.h" 329f464c52Smaya#include "util/u_surface.h" 339f464c52Smaya#include "util/hash_table.h" 347ec681f3Smrg#include "util/ralloc.h" 359f464c52Smaya#include "util/u_drm.h" 369f464c52Smaya#include "renderonly/renderonly.h" 379f464c52Smaya 387ec681f3Smrg#include "frontend/drm_driver.h" 399f464c52Smaya 409f464c52Smaya#include "drm-uapi/drm_fourcc.h" 419f464c52Smaya#include "drm-uapi/lima_drm.h" 429f464c52Smaya 439f464c52Smaya#include "lima_screen.h" 449f464c52Smaya#include "lima_context.h" 459f464c52Smaya#include "lima_resource.h" 469f464c52Smaya#include "lima_bo.h" 479f464c52Smaya#include "lima_util.h" 487ec681f3Smrg 497ec681f3Smrg#include "pan_minmax_cache.h" 507ec681f3Smrg#include "pan_tiling.h" 519f464c52Smaya 529f464c52Smayastatic struct pipe_resource * 539f464c52Smayalima_resource_create_scanout(struct pipe_screen *pscreen, 549f464c52Smaya const struct pipe_resource *templat, 559f464c52Smaya unsigned width, unsigned height) 569f464c52Smaya{ 579f464c52Smaya struct lima_screen *screen = lima_screen(pscreen); 589f464c52Smaya struct renderonly_scanout *scanout; 599f464c52Smaya struct winsys_handle handle; 609f464c52Smaya struct pipe_resource *pres; 619f464c52Smaya 629f464c52Smaya struct pipe_resource scanout_templat = *templat; 639f464c52Smaya scanout_templat.width0 = width; 649f464c52Smaya scanout_templat.height0 = height; 659f464c52Smaya scanout_templat.screen = pscreen; 669f464c52Smaya 679f464c52Smaya scanout = renderonly_scanout_for_resource(&scanout_templat, 689f464c52Smaya screen->ro, &handle); 699f464c52Smaya if (!scanout) 709f464c52Smaya return NULL; 719f464c52Smaya 729f464c52Smaya assert(handle.type == WINSYS_HANDLE_TYPE_FD); 739f464c52Smaya pres = pscreen->resource_from_handle(pscreen, templat, &handle, 749f464c52Smaya PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 759f464c52Smaya 769f464c52Smaya close(handle.handle); 779f464c52Smaya if (!pres) { 789f464c52Smaya renderonly_scanout_destroy(scanout, screen->ro); 799f464c52Smaya return NULL; 809f464c52Smaya } 819f464c52Smaya 829f464c52Smaya struct lima_resource *res = lima_resource(pres); 839f464c52Smaya res->scanout = scanout; 849f464c52Smaya 859f464c52Smaya return pres; 869f464c52Smaya} 879f464c52Smaya 889f464c52Smayastatic uint32_t 899f464c52Smayasetup_miptree(struct lima_resource *res, 909f464c52Smaya unsigned width0, unsigned height0, 919f464c52Smaya bool should_align_dimensions) 929f464c52Smaya{ 939f464c52Smaya struct pipe_resource *pres = &res->base; 949f464c52Smaya unsigned level; 959f464c52Smaya unsigned width = width0; 969f464c52Smaya unsigned height = height0; 979f464c52Smaya unsigned depth = pres->depth0; 989f464c52Smaya uint32_t size = 0; 999f464c52Smaya 1009f464c52Smaya for (level = 0; level <= pres->last_level; level++) { 1019f464c52Smaya uint32_t actual_level_size; 1029f464c52Smaya uint32_t stride; 1039f464c52Smaya unsigned aligned_width; 1049f464c52Smaya unsigned aligned_height; 1059f464c52Smaya 1069f464c52Smaya if (should_align_dimensions) { 1079f464c52Smaya aligned_width = align(width, 16); 1089f464c52Smaya aligned_height = align(height, 16); 1099f464c52Smaya } else { 1109f464c52Smaya aligned_width = width; 1119f464c52Smaya aligned_height = height; 1129f464c52Smaya } 1139f464c52Smaya 1149f464c52Smaya stride = util_format_get_stride(pres->format, aligned_width); 1159f464c52Smaya actual_level_size = stride * 1169f464c52Smaya util_format_get_nblocksy(pres->format, aligned_height) * 1179f464c52Smaya pres->array_size * depth; 1189f464c52Smaya 1199f464c52Smaya res->levels[level].width = aligned_width; 1209f464c52Smaya res->levels[level].stride = stride; 1219f464c52Smaya res->levels[level].offset = size; 1227ec681f3Smrg res->levels[level].layer_stride = util_format_get_stride(pres->format, align(width, 16)) * align(height, 16); 1237ec681f3Smrg 1247ec681f3Smrg if (util_format_is_compressed(pres->format)) 1257ec681f3Smrg res->levels[level].layer_stride /= 4; 1269f464c52Smaya 1277ec681f3Smrg /* The start address of each level except the last level 1287ec681f3Smrg * must be 64-aligned in order to be able to pass the 1297ec681f3Smrg * addresses to the hardware. */ 1307ec681f3Smrg if (level != pres->last_level) 1319f464c52Smaya size += align(actual_level_size, 64); 1329f464c52Smaya else 1339f464c52Smaya size += actual_level_size; /* Save some memory */ 1349f464c52Smaya 1359f464c52Smaya width = u_minify(width, 1); 1369f464c52Smaya height = u_minify(height, 1); 1379f464c52Smaya depth = u_minify(depth, 1); 1389f464c52Smaya } 1399f464c52Smaya 1409f464c52Smaya return size; 1419f464c52Smaya} 1429f464c52Smaya 1439f464c52Smayastatic struct pipe_resource * 1449f464c52Smayalima_resource_create_bo(struct pipe_screen *pscreen, 1459f464c52Smaya const struct pipe_resource *templat, 1469f464c52Smaya unsigned width, unsigned height, 1479f464c52Smaya bool should_align_dimensions) 1489f464c52Smaya{ 1499f464c52Smaya struct lima_screen *screen = lima_screen(pscreen); 1509f464c52Smaya struct lima_resource *res; 1519f464c52Smaya struct pipe_resource *pres; 1529f464c52Smaya 1539f464c52Smaya res = CALLOC_STRUCT(lima_resource); 1549f464c52Smaya if (!res) 1559f464c52Smaya return NULL; 1569f464c52Smaya 1579f464c52Smaya res->base = *templat; 1589f464c52Smaya res->base.screen = pscreen; 1599f464c52Smaya pipe_reference_init(&res->base.reference, 1); 1609f464c52Smaya 1619f464c52Smaya pres = &res->base; 1629f464c52Smaya 1639f464c52Smaya uint32_t size = setup_miptree(res, width, height, should_align_dimensions); 1649f464c52Smaya size = align(size, LIMA_PAGE_SIZE); 1659f464c52Smaya 1669f464c52Smaya res->bo = lima_bo_create(screen, size, 0); 1679f464c52Smaya if (!res->bo) { 1689f464c52Smaya FREE(res); 1699f464c52Smaya return NULL; 1709f464c52Smaya } 1719f464c52Smaya 1729f464c52Smaya return pres; 1739f464c52Smaya} 1749f464c52Smaya 1759f464c52Smayastatic struct pipe_resource * 1769f464c52Smaya_lima_resource_create_with_modifiers(struct pipe_screen *pscreen, 1779f464c52Smaya const struct pipe_resource *templat, 1789f464c52Smaya const uint64_t *modifiers, 1799f464c52Smaya int count) 1809f464c52Smaya{ 1819f464c52Smaya struct lima_screen *screen = lima_screen(pscreen); 1827ec681f3Smrg bool should_tile = lima_debug & LIMA_DEBUG_NO_TILING ? false : true; 1839f464c52Smaya unsigned width, height; 1849f464c52Smaya bool should_align_dimensions; 1857ec681f3Smrg bool has_user_modifiers = true; 1867ec681f3Smrg 1877ec681f3Smrg if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) 1887ec681f3Smrg has_user_modifiers = false; 1899f464c52Smaya 1909f464c52Smaya /* VBOs/PBOs are untiled (and 1 height). */ 1919f464c52Smaya if (templat->target == PIPE_BUFFER) 1929f464c52Smaya should_tile = false; 1939f464c52Smaya 1949f464c52Smaya if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT)) 1959f464c52Smaya should_tile = false; 1969f464c52Smaya 1977ec681f3Smrg /* If there's no user modifiers and buffer is shared we use linear */ 1987ec681f3Smrg if (!has_user_modifiers && (templat->bind & PIPE_BIND_SHARED)) 1997ec681f3Smrg should_tile = false; 2007ec681f3Smrg 2017ec681f3Smrg if (has_user_modifiers && 2027ec681f3Smrg !drm_find_modifier(DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, 2037ec681f3Smrg modifiers, count)) 2047ec681f3Smrg should_tile = false; 2059f464c52Smaya 2069f464c52Smaya if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) || 2079f464c52Smaya (templat->bind & PIPE_BIND_DEPTH_STENCIL)) { 2089f464c52Smaya should_align_dimensions = true; 2099f464c52Smaya width = align(templat->width0, 16); 2109f464c52Smaya height = align(templat->height0, 16); 2119f464c52Smaya } 2129f464c52Smaya else { 2139f464c52Smaya should_align_dimensions = false; 2149f464c52Smaya width = templat->width0; 2159f464c52Smaya height = templat->height0; 2169f464c52Smaya } 2179f464c52Smaya 2189f464c52Smaya struct pipe_resource *pres; 2199f464c52Smaya if (screen->ro && (templat->bind & PIPE_BIND_SCANOUT)) 2209f464c52Smaya pres = lima_resource_create_scanout(pscreen, templat, width, height); 2219f464c52Smaya else 2229f464c52Smaya pres = lima_resource_create_bo(pscreen, templat, width, height, 2239f464c52Smaya should_align_dimensions); 2249f464c52Smaya 2259f464c52Smaya if (pres) { 2269f464c52Smaya struct lima_resource *res = lima_resource(pres); 2279f464c52Smaya res->tiled = should_tile; 2289f464c52Smaya 2297ec681f3Smrg if (templat->bind & PIPE_BIND_INDEX_BUFFER) 2307ec681f3Smrg res->index_cache = CALLOC_STRUCT(panfrost_minmax_cache); 2317ec681f3Smrg 2329f464c52Smaya debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d " 2339f464c52Smaya "bind=%x usage=%d tile=%d last_level=%d\n", __func__, 2349f464c52Smaya pres, pres->width0, pres->height0, pres->depth0, 2359f464c52Smaya pres->target, pres->bind, pres->usage, should_tile, templat->last_level); 2369f464c52Smaya } 2379f464c52Smaya return pres; 2389f464c52Smaya} 2399f464c52Smaya 2409f464c52Smayastatic struct pipe_resource * 2419f464c52Smayalima_resource_create(struct pipe_screen *pscreen, 2429f464c52Smaya const struct pipe_resource *templat) 2439f464c52Smaya{ 2447ec681f3Smrg const uint64_t mod = DRM_FORMAT_MOD_INVALID; 2457ec681f3Smrg 2467ec681f3Smrg return _lima_resource_create_with_modifiers(pscreen, templat, &mod, 1); 2479f464c52Smaya} 2489f464c52Smaya 2499f464c52Smayastatic struct pipe_resource * 2509f464c52Smayalima_resource_create_with_modifiers(struct pipe_screen *pscreen, 2519f464c52Smaya const struct pipe_resource *templat, 2529f464c52Smaya const uint64_t *modifiers, 2539f464c52Smaya int count) 2549f464c52Smaya{ 2559f464c52Smaya struct pipe_resource tmpl = *templat; 2569f464c52Smaya 2579f464c52Smaya /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers 2589f464c52Smaya * don't have usage parameter, but buffer created by these functions 2599f464c52Smaya * may be used for scanout. So we assume buffer created by this 2609f464c52Smaya * function always enable scanout if linear modifier is permitted. 2619f464c52Smaya */ 2629f464c52Smaya if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count)) 2639f464c52Smaya tmpl.bind |= PIPE_BIND_SCANOUT; 2649f464c52Smaya 2659f464c52Smaya return _lima_resource_create_with_modifiers(pscreen, &tmpl, modifiers, count); 2669f464c52Smaya} 2679f464c52Smaya 2689f464c52Smayastatic void 2699f464c52Smayalima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres) 2709f464c52Smaya{ 2719f464c52Smaya struct lima_screen *screen = lima_screen(pscreen); 2729f464c52Smaya struct lima_resource *res = lima_resource(pres); 2739f464c52Smaya 2749f464c52Smaya if (res->bo) 2757ec681f3Smrg lima_bo_unreference(res->bo); 2769f464c52Smaya 2779f464c52Smaya if (res->scanout) 2789f464c52Smaya renderonly_scanout_destroy(res->scanout, screen->ro); 2799f464c52Smaya 2807ec681f3Smrg if (res->damage.region) 2817ec681f3Smrg FREE(res->damage.region); 2827ec681f3Smrg 2837ec681f3Smrg if (res->index_cache) 2847ec681f3Smrg FREE(res->index_cache); 2857ec681f3Smrg 2869f464c52Smaya FREE(res); 2879f464c52Smaya} 2889f464c52Smaya 2899f464c52Smayastatic struct pipe_resource * 2909f464c52Smayalima_resource_from_handle(struct pipe_screen *pscreen, 2919f464c52Smaya const struct pipe_resource *templat, 2929f464c52Smaya struct winsys_handle *handle, unsigned usage) 2939f464c52Smaya{ 2947ec681f3Smrg if (templat->bind & (PIPE_BIND_SAMPLER_VIEW | 2957ec681f3Smrg PIPE_BIND_RENDER_TARGET | 2967ec681f3Smrg PIPE_BIND_DEPTH_STENCIL)) { 2977ec681f3Smrg /* sampler hardware need offset alignment 64, while render hardware 2987ec681f3Smrg * need offset alignment 8, but due to render target may be reloaded 2997ec681f3Smrg * which uses the sampler, set alignment requrement to 64 for all 3007ec681f3Smrg */ 3017ec681f3Smrg if (handle->offset & 0x3f) { 3027ec681f3Smrg debug_error("import buffer offset not properly aligned\n"); 3037ec681f3Smrg return NULL; 3047ec681f3Smrg } 3057ec681f3Smrg } 3069f464c52Smaya 3077ec681f3Smrg struct lima_resource *res = CALLOC_STRUCT(lima_resource); 3089f464c52Smaya if (!res) 3099f464c52Smaya return NULL; 3109f464c52Smaya 3119f464c52Smaya struct pipe_resource *pres = &res->base; 3129f464c52Smaya *pres = *templat; 3139f464c52Smaya pres->screen = pscreen; 3149f464c52Smaya pipe_reference_init(&pres->reference, 1); 3157ec681f3Smrg res->levels[0].offset = handle->offset; 3169f464c52Smaya res->levels[0].stride = handle->stride; 3179f464c52Smaya 3187ec681f3Smrg struct lima_screen *screen = lima_screen(pscreen); 3199f464c52Smaya res->bo = lima_bo_import(screen, handle); 3209f464c52Smaya if (!res->bo) { 3219f464c52Smaya FREE(res); 3229f464c52Smaya return NULL; 3239f464c52Smaya } 3249f464c52Smaya 3257ec681f3Smrg res->modifier_constant = true; 3267ec681f3Smrg 3277ec681f3Smrg switch (handle->modifier) { 3287ec681f3Smrg case DRM_FORMAT_MOD_LINEAR: 3297ec681f3Smrg res->tiled = false; 3307ec681f3Smrg break; 3317ec681f3Smrg case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED: 3327ec681f3Smrg res->tiled = true; 3337ec681f3Smrg break; 3347ec681f3Smrg case DRM_FORMAT_MOD_INVALID: 3357ec681f3Smrg /* Modifier wasn't specified and it's shared buffer. We create these 3367ec681f3Smrg * as linear, so disable tiling. 3377ec681f3Smrg */ 3387ec681f3Smrg res->tiled = false; 3397ec681f3Smrg break; 3407ec681f3Smrg default: 3417ec681f3Smrg fprintf(stderr, "Attempted to import unsupported modifier 0x%llx\n", 3427ec681f3Smrg (long long)handle->modifier); 3437ec681f3Smrg goto err_out; 3447ec681f3Smrg } 3457ec681f3Smrg 3469f464c52Smaya /* check alignment for the buffer */ 3477ec681f3Smrg if (res->tiled || 3487ec681f3Smrg (pres->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL))) { 3499f464c52Smaya unsigned width, height, stride, size; 3509f464c52Smaya 3519f464c52Smaya width = align(pres->width0, 16); 3529f464c52Smaya height = align(pres->height0, 16); 3539f464c52Smaya stride = util_format_get_stride(pres->format, width); 3549f464c52Smaya size = util_format_get_2d_size(pres->format, stride, height); 3559f464c52Smaya 3567ec681f3Smrg if (res->tiled && res->levels[0].stride != stride) { 3577ec681f3Smrg fprintf(stderr, "tiled imported buffer has mismatching stride: %d (BO) != %d (expected)", 3587ec681f3Smrg res->levels[0].stride, stride); 3597ec681f3Smrg goto err_out; 3607ec681f3Smrg } 3617ec681f3Smrg 3627ec681f3Smrg if (!res->tiled && (res->levels[0].stride % 8)) { 3637ec681f3Smrg fprintf(stderr, "linear imported buffer stride is not aligned to 8 bytes: %d\n", 3647ec681f3Smrg res->levels[0].stride); 3657ec681f3Smrg } 3667ec681f3Smrg 3677ec681f3Smrg if (!res->tiled && res->levels[0].stride < stride) { 3687ec681f3Smrg fprintf(stderr, "linear imported buffer stride is smaller than minimal: %d (BO) < %d (min)", 3697ec681f3Smrg res->levels[0].stride, stride); 3707ec681f3Smrg goto err_out; 3717ec681f3Smrg } 3727ec681f3Smrg 3737ec681f3Smrg if ((res->bo->size - res->levels[0].offset) < size) { 3747ec681f3Smrg fprintf(stderr, "imported bo size is smaller than expected: %d (BO) < %d (expected)\n", 3757ec681f3Smrg (res->bo->size - res->levels[0].offset), size); 3769f464c52Smaya goto err_out; 3779f464c52Smaya } 3789f464c52Smaya 3799f464c52Smaya res->levels[0].width = width; 3809f464c52Smaya } 3819f464c52Smaya else 3829f464c52Smaya res->levels[0].width = pres->width0; 3839f464c52Smaya 3847ec681f3Smrg if (screen->ro) { 3857ec681f3Smrg /* Make sure that renderonly has a handle to our buffer in the 3867ec681f3Smrg * display's fd, so that a later renderonly_get_handle() 3877ec681f3Smrg * returns correct handles or GEM names. 3887ec681f3Smrg */ 3897ec681f3Smrg res->scanout = 3907ec681f3Smrg renderonly_create_gpu_import_for_resource(pres, 3917ec681f3Smrg screen->ro, 3927ec681f3Smrg NULL); 3937ec681f3Smrg /* ignore failiure to allow importing non-displayable buffer */ 3947ec681f3Smrg } 3959f464c52Smaya 3969f464c52Smaya return pres; 3979f464c52Smaya 3989f464c52Smayaerr_out: 3999f464c52Smaya lima_resource_destroy(pscreen, pres); 4009f464c52Smaya return NULL; 4019f464c52Smaya} 4029f464c52Smaya 4037ec681f3Smrgstatic bool 4049f464c52Smayalima_resource_get_handle(struct pipe_screen *pscreen, 4059f464c52Smaya struct pipe_context *pctx, 4069f464c52Smaya struct pipe_resource *pres, 4079f464c52Smaya struct winsys_handle *handle, unsigned usage) 4089f464c52Smaya{ 4099f464c52Smaya struct lima_screen *screen = lima_screen(pscreen); 4109f464c52Smaya struct lima_resource *res = lima_resource(pres); 4119f464c52Smaya 4127ec681f3Smrg if (res->tiled) 4137ec681f3Smrg handle->modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 4147ec681f3Smrg else 4157ec681f3Smrg handle->modifier = DRM_FORMAT_MOD_LINEAR; 4167ec681f3Smrg 4177ec681f3Smrg res->modifier_constant = true; 4189f464c52Smaya 4197ec681f3Smrg if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro) 4207ec681f3Smrg return renderonly_get_handle(res->scanout, handle); 4219f464c52Smaya 4229f464c52Smaya if (!lima_bo_export(res->bo, handle)) 4237ec681f3Smrg return false; 4249f464c52Smaya 4257ec681f3Smrg handle->offset = res->levels[0].offset; 4269f464c52Smaya handle->stride = res->levels[0].stride; 4277ec681f3Smrg return true; 4287ec681f3Smrg} 4297ec681f3Smrg 4307ec681f3Smrgstatic bool 4317ec681f3Smrglima_resource_get_param(struct pipe_screen *pscreen, 4327ec681f3Smrg struct pipe_context *pctx, 4337ec681f3Smrg struct pipe_resource *pres, 4347ec681f3Smrg unsigned plane, unsigned layer, unsigned level, 4357ec681f3Smrg enum pipe_resource_param param, 4367ec681f3Smrg unsigned usage, uint64_t *value) 4377ec681f3Smrg{ 4387ec681f3Smrg struct lima_resource *res = lima_resource(pres); 4397ec681f3Smrg 4407ec681f3Smrg switch (param) { 4417ec681f3Smrg case PIPE_RESOURCE_PARAM_STRIDE: 4427ec681f3Smrg *value = res->levels[level].stride; 4437ec681f3Smrg return true; 4447ec681f3Smrg case PIPE_RESOURCE_PARAM_OFFSET: 4457ec681f3Smrg *value = res->levels[level].offset; 4467ec681f3Smrg return true; 4477ec681f3Smrg case PIPE_RESOURCE_PARAM_MODIFIER: 4487ec681f3Smrg if (res->tiled) 4497ec681f3Smrg *value = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED; 4507ec681f3Smrg else 4517ec681f3Smrg *value = DRM_FORMAT_MOD_LINEAR; 4527ec681f3Smrg 4537ec681f3Smrg return true; 4547ec681f3Smrg default: 4557ec681f3Smrg return false; 4567ec681f3Smrg } 4577ec681f3Smrg} 4587ec681f3Smrg 4597ec681f3Smrgstatic void 4607ec681f3Smrgget_scissor_from_box(struct pipe_scissor_state *s, 4617ec681f3Smrg const struct pipe_box *b, int h) 4627ec681f3Smrg{ 4637ec681f3Smrg int y = h - (b->y + b->height); 4647ec681f3Smrg /* region in tile unit */ 4657ec681f3Smrg s->minx = b->x >> 4; 4667ec681f3Smrg s->miny = y >> 4; 4677ec681f3Smrg s->maxx = (b->x + b->width + 0xf) >> 4; 4687ec681f3Smrg s->maxy = (y + b->height + 0xf) >> 4; 4697ec681f3Smrg} 4707ec681f3Smrg 4717ec681f3Smrgstatic void 4727ec681f3Smrgget_damage_bound_box(struct pipe_resource *pres, 4737ec681f3Smrg const struct pipe_box *rects, 4747ec681f3Smrg unsigned int nrects, 4757ec681f3Smrg struct pipe_scissor_state *bound) 4767ec681f3Smrg{ 4777ec681f3Smrg struct pipe_box b = rects[0]; 4787ec681f3Smrg 4797ec681f3Smrg for (int i = 1; i < nrects; i++) 4807ec681f3Smrg u_box_union_2d(&b, &b, rects + i); 4817ec681f3Smrg 4827ec681f3Smrg int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0); 4837ec681f3Smrg if (ret < 0) 4847ec681f3Smrg memset(bound, 0, sizeof(*bound)); 4857ec681f3Smrg else 4867ec681f3Smrg get_scissor_from_box(bound, &b, pres->height0); 4877ec681f3Smrg} 4887ec681f3Smrg 4897ec681f3Smrgstatic void 4907ec681f3Smrglima_resource_set_damage_region(struct pipe_screen *pscreen, 4917ec681f3Smrg struct pipe_resource *pres, 4927ec681f3Smrg unsigned int nrects, 4937ec681f3Smrg const struct pipe_box *rects) 4947ec681f3Smrg{ 4957ec681f3Smrg struct lima_resource *res = lima_resource(pres); 4967ec681f3Smrg struct lima_damage_region *damage = &res->damage; 4977ec681f3Smrg int i; 4987ec681f3Smrg 4997ec681f3Smrg if (damage->region) { 5007ec681f3Smrg FREE(damage->region); 5017ec681f3Smrg damage->region = NULL; 5027ec681f3Smrg damage->num_region = 0; 5037ec681f3Smrg } 5047ec681f3Smrg 5057ec681f3Smrg if (!nrects) 5067ec681f3Smrg return; 5077ec681f3Smrg 5087ec681f3Smrg /* check full damage 5097ec681f3Smrg * 5107ec681f3Smrg * TODO: currently only check if there is any single damage 5117ec681f3Smrg * region that can cover the full render target; there may 5127ec681f3Smrg * be some accurate way, but a single window size damage 5137ec681f3Smrg * region is most of the case from weston 5147ec681f3Smrg */ 5157ec681f3Smrg for (i = 0; i < nrects; i++) { 5167ec681f3Smrg if (rects[i].x <= 0 && rects[i].y <= 0 && 5177ec681f3Smrg rects[i].x + rects[i].width >= pres->width0 && 5187ec681f3Smrg rects[i].y + rects[i].height >= pres->height0) 5197ec681f3Smrg return; 5207ec681f3Smrg } 5217ec681f3Smrg 5227ec681f3Smrg struct pipe_scissor_state *bound = &damage->bound; 5237ec681f3Smrg get_damage_bound_box(pres, rects, nrects, bound); 5247ec681f3Smrg 5257ec681f3Smrg damage->region = CALLOC(nrects, sizeof(*damage->region)); 5267ec681f3Smrg if (!damage->region) 5277ec681f3Smrg return; 5287ec681f3Smrg 5297ec681f3Smrg for (i = 0; i < nrects; i++) 5307ec681f3Smrg get_scissor_from_box(damage->region + i, rects + i, 5317ec681f3Smrg pres->height0); 5327ec681f3Smrg 5337ec681f3Smrg /* is region aligned to tiles? */ 5347ec681f3Smrg damage->aligned = true; 5357ec681f3Smrg for (i = 0; i < nrects; i++) { 5367ec681f3Smrg if (rects[i].x & 0xf || rects[i].y & 0xf || 5377ec681f3Smrg rects[i].width & 0xf || rects[i].height & 0xf) { 5387ec681f3Smrg damage->aligned = false; 5397ec681f3Smrg break; 5407ec681f3Smrg } 5417ec681f3Smrg } 5427ec681f3Smrg 5437ec681f3Smrg damage->num_region = nrects; 5449f464c52Smaya} 5459f464c52Smaya 5469f464c52Smayavoid 5479f464c52Smayalima_resource_screen_init(struct lima_screen *screen) 5489f464c52Smaya{ 5499f464c52Smaya screen->base.resource_create = lima_resource_create; 5509f464c52Smaya screen->base.resource_create_with_modifiers = lima_resource_create_with_modifiers; 5519f464c52Smaya screen->base.resource_from_handle = lima_resource_from_handle; 5529f464c52Smaya screen->base.resource_destroy = lima_resource_destroy; 5539f464c52Smaya screen->base.resource_get_handle = lima_resource_get_handle; 5547ec681f3Smrg screen->base.resource_get_param = lima_resource_get_param; 5557ec681f3Smrg screen->base.set_damage_region = lima_resource_set_damage_region; 5569f464c52Smaya} 5579f464c52Smaya 5589f464c52Smayastatic struct pipe_surface * 5599f464c52Smayalima_surface_create(struct pipe_context *pctx, 5609f464c52Smaya struct pipe_resource *pres, 5619f464c52Smaya const struct pipe_surface *surf_tmpl) 5629f464c52Smaya{ 5639f464c52Smaya struct lima_surface *surf = CALLOC_STRUCT(lima_surface); 5649f464c52Smaya 5659f464c52Smaya if (!surf) 5669f464c52Smaya return NULL; 5679f464c52Smaya 5689f464c52Smaya assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); 5699f464c52Smaya 5709f464c52Smaya struct pipe_surface *psurf = &surf->base; 5719f464c52Smaya unsigned level = surf_tmpl->u.tex.level; 5729f464c52Smaya 5739f464c52Smaya pipe_reference_init(&psurf->reference, 1); 5749f464c52Smaya pipe_resource_reference(&psurf->texture, pres); 5759f464c52Smaya 5769f464c52Smaya psurf->context = pctx; 5779f464c52Smaya psurf->format = surf_tmpl->format; 5789f464c52Smaya psurf->width = u_minify(pres->width0, level); 5799f464c52Smaya psurf->height = u_minify(pres->height0, level); 5809f464c52Smaya psurf->u.tex.level = level; 5819f464c52Smaya psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 5829f464c52Smaya psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 5839f464c52Smaya 5849f464c52Smaya surf->tiled_w = align(psurf->width, 16) >> 4; 5859f464c52Smaya surf->tiled_h = align(psurf->height, 16) >> 4; 5869f464c52Smaya 5877ec681f3Smrg surf->reload = 0; 5887ec681f3Smrg if (util_format_has_stencil(util_format_description(psurf->format))) 5897ec681f3Smrg surf->reload |= PIPE_CLEAR_STENCIL; 5907ec681f3Smrg if (util_format_has_depth(util_format_description(psurf->format))) 5917ec681f3Smrg surf->reload |= PIPE_CLEAR_DEPTH; 5927ec681f3Smrg if (!util_format_is_depth_or_stencil(psurf->format)) 5937ec681f3Smrg surf->reload |= PIPE_CLEAR_COLOR0; 5949f464c52Smaya 5959f464c52Smaya return &surf->base; 5969f464c52Smaya} 5979f464c52Smaya 5989f464c52Smayastatic void 5999f464c52Smayalima_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) 6009f464c52Smaya{ 6019f464c52Smaya struct lima_surface *surf = lima_surface(psurf); 6029f464c52Smaya 6039f464c52Smaya pipe_resource_reference(&psurf->texture, NULL); 6049f464c52Smaya FREE(surf); 6059f464c52Smaya} 6069f464c52Smaya 6079f464c52Smayastatic void * 6089f464c52Smayalima_transfer_map(struct pipe_context *pctx, 6099f464c52Smaya struct pipe_resource *pres, 6109f464c52Smaya unsigned level, 6119f464c52Smaya unsigned usage, 6129f464c52Smaya const struct pipe_box *box, 6139f464c52Smaya struct pipe_transfer **pptrans) 6149f464c52Smaya{ 6157ec681f3Smrg struct lima_screen *screen = lima_screen(pres->screen); 6169f464c52Smaya struct lima_context *ctx = lima_context(pctx); 6179f464c52Smaya struct lima_resource *res = lima_resource(pres); 6189f464c52Smaya struct lima_bo *bo = res->bo; 6199f464c52Smaya struct lima_transfer *trans; 6209f464c52Smaya struct pipe_transfer *ptrans; 6219f464c52Smaya 6229f464c52Smaya /* No direct mappings of tiled, since we need to manually 6239f464c52Smaya * tile/untile. 6249f464c52Smaya */ 6257ec681f3Smrg if (res->tiled && (usage & PIPE_MAP_DIRECTLY)) 6269f464c52Smaya return NULL; 6279f464c52Smaya 6287ec681f3Smrg /* bo might be in use in a previous stream draw. Allocate a new 6297ec681f3Smrg * one for the resource to avoid overwriting data in use. */ 6307ec681f3Smrg if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 6317ec681f3Smrg struct lima_bo *new_bo; 6327ec681f3Smrg assert(res->bo && res->bo->size); 6339f464c52Smaya 6347ec681f3Smrg new_bo = lima_bo_create(screen, res->bo->size, res->bo->flags); 6357ec681f3Smrg if (!new_bo) 6367ec681f3Smrg return NULL; 6377ec681f3Smrg 6387ec681f3Smrg lima_bo_unreference(res->bo); 6397ec681f3Smrg res->bo = new_bo; 6407ec681f3Smrg 6417ec681f3Smrg if (pres->bind & PIPE_BIND_VERTEX_BUFFER) 6427ec681f3Smrg ctx->dirty |= LIMA_CONTEXT_DIRTY_VERTEX_BUFF; 6437ec681f3Smrg 6447ec681f3Smrg bo = res->bo; 6457ec681f3Smrg } 6467ec681f3Smrg else if (!(usage & PIPE_MAP_UNSYNCHRONIZED) && 6477ec681f3Smrg (usage & PIPE_MAP_READ_WRITE)) { 6487ec681f3Smrg /* use once buffers are made sure to not read/write overlapped 6497ec681f3Smrg * range, so no need to sync */ 6507ec681f3Smrg lima_flush_job_accessing_bo(ctx, bo, usage & PIPE_MAP_WRITE); 6517ec681f3Smrg 6527ec681f3Smrg unsigned op = usage & PIPE_MAP_WRITE ? 6537ec681f3Smrg LIMA_GEM_WAIT_WRITE : LIMA_GEM_WAIT_READ; 6547ec681f3Smrg lima_bo_wait(bo, op, PIPE_TIMEOUT_INFINITE); 6559f464c52Smaya } 6569f464c52Smaya 6579f464c52Smaya if (!lima_bo_map(bo)) 6589f464c52Smaya return NULL; 6599f464c52Smaya 6609f464c52Smaya trans = slab_alloc(&ctx->transfer_pool); 6619f464c52Smaya if (!trans) 6629f464c52Smaya return NULL; 6639f464c52Smaya 6649f464c52Smaya memset(trans, 0, sizeof(*trans)); 6659f464c52Smaya ptrans = &trans->base; 6669f464c52Smaya 6679f464c52Smaya pipe_resource_reference(&ptrans->resource, pres); 6689f464c52Smaya ptrans->level = level; 6699f464c52Smaya ptrans->usage = usage; 6709f464c52Smaya ptrans->box = *box; 6719f464c52Smaya 6729f464c52Smaya *pptrans = ptrans; 6739f464c52Smaya 6749f464c52Smaya if (res->tiled) { 6759f464c52Smaya ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width); 6769f464c52Smaya ptrans->layer_stride = ptrans->stride * ptrans->box.height; 6779f464c52Smaya 6789f464c52Smaya trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth); 6799f464c52Smaya 6807ec681f3Smrg if (usage & PIPE_MAP_READ) { 6817ec681f3Smrg unsigned i; 6827ec681f3Smrg for (i = 0; i < ptrans->box.depth; i++) 6837ec681f3Smrg panfrost_load_tiled_image( 6847ec681f3Smrg trans->staging + i * ptrans->stride * ptrans->box.height, 6857ec681f3Smrg bo->map + res->levels[level].offset + (i + box->z) * res->levels[level].layer_stride, 6867ec681f3Smrg ptrans->box.x, ptrans->box.y, 6877ec681f3Smrg ptrans->box.width, ptrans->box.height, 6887ec681f3Smrg ptrans->stride, 6897ec681f3Smrg res->levels[level].stride, 6907ec681f3Smrg pres->format); 6917ec681f3Smrg } 6929f464c52Smaya 6939f464c52Smaya return trans->staging; 6949f464c52Smaya } else { 6957ec681f3Smrg unsigned dpw = PIPE_MAP_DIRECTLY | PIPE_MAP_WRITE | 6967ec681f3Smrg PIPE_MAP_PERSISTENT; 6977ec681f3Smrg if ((usage & dpw) == dpw && res->index_cache) 6987ec681f3Smrg return NULL; 6997ec681f3Smrg 7009f464c52Smaya ptrans->stride = res->levels[level].stride; 7017ec681f3Smrg ptrans->layer_stride = res->levels[level].layer_stride; 7027ec681f3Smrg 7037ec681f3Smrg if ((usage & PIPE_MAP_WRITE) && (usage & PIPE_MAP_DIRECTLY)) 7047ec681f3Smrg panfrost_minmax_cache_invalidate(res->index_cache, ptrans); 7059f464c52Smaya 7069f464c52Smaya return bo->map + res->levels[level].offset + 7077ec681f3Smrg box->z * res->levels[level].layer_stride + 7089f464c52Smaya box->y / util_format_get_blockheight(pres->format) * ptrans->stride + 7099f464c52Smaya box->x / util_format_get_blockwidth(pres->format) * 7109f464c52Smaya util_format_get_blocksize(pres->format); 7119f464c52Smaya } 7129f464c52Smaya} 7139f464c52Smaya 7149f464c52Smayastatic void 7159f464c52Smayalima_transfer_flush_region(struct pipe_context *pctx, 7169f464c52Smaya struct pipe_transfer *ptrans, 7179f464c52Smaya const struct pipe_box *box) 7189f464c52Smaya{ 7199f464c52Smaya 7209f464c52Smaya} 7219f464c52Smaya 7227ec681f3Smrgstatic bool 7237ec681f3Smrglima_should_convert_linear(struct lima_resource *res, 7247ec681f3Smrg struct pipe_transfer *ptrans) 7257ec681f3Smrg{ 7267ec681f3Smrg if (res->modifier_constant) 7277ec681f3Smrg return false; 7287ec681f3Smrg 7297ec681f3Smrg /* Overwriting the entire resource indicates streaming, for which 7307ec681f3Smrg * linear layout is most efficient due to the lack of expensive 7317ec681f3Smrg * conversion. 7327ec681f3Smrg * 7337ec681f3Smrg * For now we just switch to linear after a number of complete 7347ec681f3Smrg * overwrites to keep things simple, but we could do better. 7357ec681f3Smrg */ 7367ec681f3Smrg 7377ec681f3Smrg unsigned depth = res->base.target == PIPE_TEXTURE_3D ? 7387ec681f3Smrg res->base.depth0 : res->base.array_size; 7397ec681f3Smrg bool entire_overwrite = 7407ec681f3Smrg res->base.last_level == 0 && 7417ec681f3Smrg ptrans->box.width == res->base.width0 && 7427ec681f3Smrg ptrans->box.height == res->base.height0 && 7437ec681f3Smrg ptrans->box.depth == depth && 7447ec681f3Smrg ptrans->box.x == 0 && 7457ec681f3Smrg ptrans->box.y == 0 && 7467ec681f3Smrg ptrans->box.z == 0; 7477ec681f3Smrg 7487ec681f3Smrg if (entire_overwrite) 7497ec681f3Smrg ++res->full_updates; 7507ec681f3Smrg 7517ec681f3Smrg return res->full_updates >= LAYOUT_CONVERT_THRESHOLD; 7527ec681f3Smrg} 7537ec681f3Smrg 7549f464c52Smayastatic void 7557ec681f3Smrglima_transfer_unmap_inner(struct lima_context *ctx, 7567ec681f3Smrg struct pipe_transfer *ptrans) 7579f464c52Smaya{ 7589f464c52Smaya struct lima_resource *res = lima_resource(ptrans->resource); 7597ec681f3Smrg struct lima_transfer *trans = lima_transfer(ptrans); 7609f464c52Smaya struct lima_bo *bo = res->bo; 7619f464c52Smaya struct pipe_resource *pres; 7629f464c52Smaya 7639f464c52Smaya if (trans->staging) { 7649f464c52Smaya pres = &res->base; 7657ec681f3Smrg if (trans->base.usage & PIPE_MAP_WRITE) { 7667ec681f3Smrg unsigned i; 7677ec681f3Smrg if (lima_should_convert_linear(res, ptrans)) { 7687ec681f3Smrg /* It's safe to re-use the same BO since tiled BO always has 7697ec681f3Smrg * aligned dimensions */ 7707ec681f3Smrg for (i = 0; i < trans->base.box.depth; i++) { 7717ec681f3Smrg util_copy_rect(bo->map + res->levels[0].offset + 7727ec681f3Smrg (i + trans->base.box.z) * res->levels[0].stride, 7737ec681f3Smrg res->base.format, 7747ec681f3Smrg res->levels[0].stride, 7757ec681f3Smrg 0, 0, 7767ec681f3Smrg ptrans->box.width, 7777ec681f3Smrg ptrans->box.height, 7787ec681f3Smrg trans->staging + i * ptrans->stride * ptrans->box.height, 7799f464c52Smaya ptrans->stride, 7807ec681f3Smrg 0, 0); 7817ec681f3Smrg } 7827ec681f3Smrg res->tiled = false; 7837ec681f3Smrg res->modifier_constant = true; 7847ec681f3Smrg /* Update texture descriptor */ 7857ec681f3Smrg ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES; 7867ec681f3Smrg } else { 7877ec681f3Smrg for (i = 0; i < trans->base.box.depth; i++) 7887ec681f3Smrg panfrost_store_tiled_image( 7897ec681f3Smrg bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride, 7907ec681f3Smrg trans->staging + i * ptrans->stride * ptrans->box.height, 7917ec681f3Smrg ptrans->box.x, ptrans->box.y, 7927ec681f3Smrg ptrans->box.width, ptrans->box.height, 7937ec681f3Smrg res->levels[ptrans->level].stride, 7947ec681f3Smrg ptrans->stride, 7957ec681f3Smrg pres->format); 7967ec681f3Smrg } 7977ec681f3Smrg } 7989f464c52Smaya } 7997ec681f3Smrg} 8007ec681f3Smrg 8017ec681f3Smrgstatic void 8027ec681f3Smrglima_transfer_unmap(struct pipe_context *pctx, 8037ec681f3Smrg struct pipe_transfer *ptrans) 8047ec681f3Smrg{ 8057ec681f3Smrg struct lima_context *ctx = lima_context(pctx); 8067ec681f3Smrg struct lima_transfer *trans = lima_transfer(ptrans); 8077ec681f3Smrg struct lima_resource *res = lima_resource(ptrans->resource); 8087ec681f3Smrg 8097ec681f3Smrg lima_transfer_unmap_inner(ctx, ptrans); 8107ec681f3Smrg if (trans->staging) 8117ec681f3Smrg free(trans->staging); 8127ec681f3Smrg panfrost_minmax_cache_invalidate(res->index_cache, ptrans); 8139f464c52Smaya 8149f464c52Smaya pipe_resource_reference(&ptrans->resource, NULL); 8159f464c52Smaya slab_free(&ctx->transfer_pool, trans); 8169f464c52Smaya} 8179f464c52Smaya 8189f464c52Smayastatic void 8199f464c52Smayalima_util_blitter_save_states(struct lima_context *ctx) 8209f464c52Smaya{ 8219f464c52Smaya util_blitter_save_blend(ctx->blitter, (void *)ctx->blend); 8229f464c52Smaya util_blitter_save_depth_stencil_alpha(ctx->blitter, (void *)ctx->zsa); 8239f464c52Smaya util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); 8249f464c52Smaya util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer); 8257ec681f3Smrg util_blitter_save_fragment_shader(ctx->blitter, ctx->uncomp_fs); 8267ec681f3Smrg util_blitter_save_vertex_shader(ctx->blitter, ctx->uncomp_vs); 8279f464c52Smaya util_blitter_save_viewport(ctx->blitter, 8289f464c52Smaya &ctx->viewport.transform); 8299f464c52Smaya util_blitter_save_scissor(ctx->blitter, &ctx->scissor); 8309f464c52Smaya util_blitter_save_vertex_elements(ctx->blitter, 8319f464c52Smaya ctx->vertex_elements); 8329f464c52Smaya util_blitter_save_vertex_buffer_slot(ctx->blitter, 8339f464c52Smaya ctx->vertex_buffers.vb); 8349f464c52Smaya 8359f464c52Smaya util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base); 8369f464c52Smaya 8379f464c52Smaya util_blitter_save_fragment_sampler_states(ctx->blitter, 8389f464c52Smaya ctx->tex_stateobj.num_samplers, 8399f464c52Smaya (void**)ctx->tex_stateobj.samplers); 8409f464c52Smaya util_blitter_save_fragment_sampler_views(ctx->blitter, 8419f464c52Smaya ctx->tex_stateobj.num_textures, 8429f464c52Smaya ctx->tex_stateobj.textures); 8439f464c52Smaya} 8449f464c52Smaya 8459f464c52Smayastatic void 8469f464c52Smayalima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 8479f464c52Smaya{ 8489f464c52Smaya struct lima_context *ctx = lima_context(pctx); 8499f464c52Smaya struct pipe_blit_info info = *blit_info; 8509f464c52Smaya 8519f464c52Smaya if (util_try_blit_via_copy_region(pctx, &info)) { 8529f464c52Smaya return; /* done */ 8539f464c52Smaya } 8549f464c52Smaya 8559f464c52Smaya if (info.mask & PIPE_MASK_S) { 8569f464c52Smaya debug_printf("lima: cannot blit stencil, skipping\n"); 8579f464c52Smaya info.mask &= ~PIPE_MASK_S; 8589f464c52Smaya } 8599f464c52Smaya 8609f464c52Smaya if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { 8619f464c52Smaya debug_printf("lima: blit unsupported %s -> %s\n", 8629f464c52Smaya util_format_short_name(info.src.resource->format), 8639f464c52Smaya util_format_short_name(info.dst.resource->format)); 8649f464c52Smaya return; 8659f464c52Smaya } 8669f464c52Smaya 8679f464c52Smaya lima_util_blitter_save_states(ctx); 8689f464c52Smaya 8699f464c52Smaya util_blitter_blit(ctx->blitter, &info); 8709f464c52Smaya} 8719f464c52Smaya 8729f464c52Smayastatic void 8739f464c52Smayalima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource) 8749f464c52Smaya{ 8759f464c52Smaya 8769f464c52Smaya} 8779f464c52Smaya 8787ec681f3Smrgstatic void 8797ec681f3Smrglima_texture_subdata(struct pipe_context *pctx, 8807ec681f3Smrg struct pipe_resource *prsc, 8817ec681f3Smrg unsigned level, 8827ec681f3Smrg unsigned usage, 8837ec681f3Smrg const struct pipe_box *box, 8847ec681f3Smrg const void *data, 8857ec681f3Smrg unsigned stride, 8867ec681f3Smrg unsigned layer_stride) 8877ec681f3Smrg{ 8887ec681f3Smrg struct lima_context *ctx = lima_context(pctx); 8897ec681f3Smrg struct lima_resource *res = lima_resource(prsc); 8907ec681f3Smrg 8917ec681f3Smrg if (!res->tiled) { 8927ec681f3Smrg u_default_texture_subdata(pctx, prsc, level, usage, box, 8937ec681f3Smrg data, stride, layer_stride); 8947ec681f3Smrg return; 8957ec681f3Smrg } 8967ec681f3Smrg 8977ec681f3Smrg assert(!(usage & PIPE_MAP_READ)); 8987ec681f3Smrg 8997ec681f3Smrg struct lima_transfer t = { 9007ec681f3Smrg .base = { 9017ec681f3Smrg .resource = prsc, 9027ec681f3Smrg .usage = PIPE_MAP_WRITE, 9037ec681f3Smrg .level = level, 9047ec681f3Smrg .box = *box, 9057ec681f3Smrg .stride = stride, 9067ec681f3Smrg .layer_stride = layer_stride, 9077ec681f3Smrg }, 9087ec681f3Smrg .staging = (void *)data, 9097ec681f3Smrg }; 9107ec681f3Smrg 9117ec681f3Smrg lima_flush_job_accessing_bo(ctx, res->bo, true); 9127ec681f3Smrg lima_bo_wait(res->bo, LIMA_GEM_WAIT_WRITE, PIPE_TIMEOUT_INFINITE); 9137ec681f3Smrg if (!lima_bo_map(res->bo)) 9147ec681f3Smrg return; 9157ec681f3Smrg 9167ec681f3Smrg lima_transfer_unmap_inner(ctx, &t.base); 9177ec681f3Smrg} 9187ec681f3Smrg 9199f464c52Smayavoid 9209f464c52Smayalima_resource_context_init(struct lima_context *ctx) 9219f464c52Smaya{ 9229f464c52Smaya ctx->base.create_surface = lima_surface_create; 9239f464c52Smaya ctx->base.surface_destroy = lima_surface_destroy; 9249f464c52Smaya 9259f464c52Smaya ctx->base.buffer_subdata = u_default_buffer_subdata; 9267ec681f3Smrg ctx->base.texture_subdata = lima_texture_subdata; 9277ec681f3Smrg /* TODO: optimize resource_copy_region to do copy directly 9287ec681f3Smrg * between 2 tiled or tiled and linear resources instead of 9297ec681f3Smrg * using staging buffer. 9307ec681f3Smrg */ 9319f464c52Smaya ctx->base.resource_copy_region = util_resource_copy_region; 9329f464c52Smaya 9339f464c52Smaya ctx->base.blit = lima_blit; 9349f464c52Smaya 9357ec681f3Smrg ctx->base.buffer_map = lima_transfer_map; 9367ec681f3Smrg ctx->base.texture_map = lima_transfer_map; 9379f464c52Smaya ctx->base.transfer_flush_region = lima_transfer_flush_region; 9387ec681f3Smrg ctx->base.buffer_unmap = lima_transfer_unmap; 9397ec681f3Smrg ctx->base.texture_unmap = lima_transfer_unmap; 9409f464c52Smaya 9419f464c52Smaya ctx->base.flush_resource = lima_flush_resource; 9429f464c52Smaya} 943