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