1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2012-2015 Etnaviv Project
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
13bf215546Sopenharmony_ci * of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Wladimir J. van der Laan <laanwj@gmail.com>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "etnaviv_resource.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "hw/common.xml.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "etnaviv_context.h"
32bf215546Sopenharmony_ci#include "etnaviv_debug.h"
33bf215546Sopenharmony_ci#include "etnaviv_screen.h"
34bf215546Sopenharmony_ci#include "etnaviv_translate.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "util/hash_table.h"
37bf215546Sopenharmony_ci#include "util/u_inlines.h"
38bf215546Sopenharmony_ci#include "util/u_memory.h"
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic enum etna_surface_layout modifier_to_layout(uint64_t modifier)
43bf215546Sopenharmony_ci{
44bf215546Sopenharmony_ci   switch (modifier) {
45bf215546Sopenharmony_ci   case DRM_FORMAT_MOD_VIVANTE_TILED:
46bf215546Sopenharmony_ci      return ETNA_LAYOUT_TILED;
47bf215546Sopenharmony_ci   case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
48bf215546Sopenharmony_ci      return ETNA_LAYOUT_SUPER_TILED;
49bf215546Sopenharmony_ci   case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
50bf215546Sopenharmony_ci      return ETNA_LAYOUT_MULTI_TILED;
51bf215546Sopenharmony_ci   case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
52bf215546Sopenharmony_ci      return ETNA_LAYOUT_MULTI_SUPERTILED;
53bf215546Sopenharmony_ci   case DRM_FORMAT_MOD_LINEAR:
54bf215546Sopenharmony_ci   default:
55bf215546Sopenharmony_ci      return ETNA_LAYOUT_LINEAR;
56bf215546Sopenharmony_ci   }
57bf215546Sopenharmony_ci}
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_cistatic uint64_t layout_to_modifier(enum etna_surface_layout layout)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   switch (layout) {
62bf215546Sopenharmony_ci   case ETNA_LAYOUT_TILED:
63bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_VIVANTE_TILED;
64bf215546Sopenharmony_ci   case ETNA_LAYOUT_SUPER_TILED:
65bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_VIVANTE_SUPER_TILED;
66bf215546Sopenharmony_ci   case ETNA_LAYOUT_MULTI_TILED:
67bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED;
68bf215546Sopenharmony_ci   case ETNA_LAYOUT_MULTI_SUPERTILED:
69bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED;
70bf215546Sopenharmony_ci   case ETNA_LAYOUT_LINEAR:
71bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_LINEAR;
72bf215546Sopenharmony_ci   default:
73bf215546Sopenharmony_ci      return DRM_FORMAT_MOD_INVALID;
74bf215546Sopenharmony_ci   }
75bf215546Sopenharmony_ci}
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci/* A tile is 4x4 pixels, having 'screen->specs.bits_per_tile' of tile status.
78bf215546Sopenharmony_ci * So, in a buffer of N pixels, there are N / (4 * 4) tiles.
79bf215546Sopenharmony_ci * We need N * screen->specs.bits_per_tile / (4 * 4) bits of tile status, or
80bf215546Sopenharmony_ci * N * screen->specs.bits_per_tile / (4 * 4 * 8) bytes.
81bf215546Sopenharmony_ci */
82bf215546Sopenharmony_cibool
83bf215546Sopenharmony_cietna_screen_resource_alloc_ts(struct pipe_screen *pscreen,
84bf215546Sopenharmony_ci                              struct etna_resource *rsc)
85bf215546Sopenharmony_ci{
86bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
87bf215546Sopenharmony_ci   size_t rt_ts_size, ts_layer_stride;
88bf215546Sopenharmony_ci   uint8_t ts_mode = TS_MODE_128B;
89bf215546Sopenharmony_ci   int8_t ts_compress_fmt;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   assert(!rsc->ts_bo);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   /* pre-v4 compression is largely useless, so disable it when not wanted for MSAA
94bf215546Sopenharmony_ci    * v4 compression can be enabled everywhere without any known drawback,
95bf215546Sopenharmony_ci    * except that in-place resolve must go through a slower path
96bf215546Sopenharmony_ci    */
97bf215546Sopenharmony_ci   ts_compress_fmt = (screen->specs.v4_compression || rsc->base.nr_samples > 1) ?
98bf215546Sopenharmony_ci                      translate_ts_format(rsc->base.format) : -1;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   /* enable 256B ts mode with compression, as it improves performance
101bf215546Sopenharmony_ci    * the size of the resource might also determine if we want to use it or not
102bf215546Sopenharmony_ci    */
103bf215546Sopenharmony_ci   if (VIV_FEATURE(screen, chipMinorFeatures6, CACHE128B256BPERLINE) &&
104bf215546Sopenharmony_ci       ts_compress_fmt >= 0 &&
105bf215546Sopenharmony_ci       (rsc->layout != ETNA_LAYOUT_LINEAR ||
106bf215546Sopenharmony_ci        rsc->levels[0].stride % 256 == 0) )
107bf215546Sopenharmony_ci         ts_mode = TS_MODE_256B;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   ts_layer_stride = align(DIV_ROUND_UP(rsc->levels[0].layer_stride,
110bf215546Sopenharmony_ci                                        etna_screen_get_tile_size(screen, ts_mode) *
111bf215546Sopenharmony_ci                                        8 / screen->specs.bits_per_tile),
112bf215546Sopenharmony_ci                           0x100 * screen->specs.pixel_pipes);
113bf215546Sopenharmony_ci   rt_ts_size = ts_layer_stride * rsc->base.array_size;
114bf215546Sopenharmony_ci   if (rt_ts_size == 0)
115bf215546Sopenharmony_ci      return true;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   DBG_F(ETNA_DBG_RESOURCE_MSGS, "%p: Allocating tile status of size %zu",
118bf215546Sopenharmony_ci         rsc, rt_ts_size);
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   struct etna_bo *rt_ts;
121bf215546Sopenharmony_ci   rt_ts = etna_bo_new(screen->dev, rt_ts_size, DRM_ETNA_GEM_CACHE_WC);
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   if (unlikely(!rt_ts)) {
124bf215546Sopenharmony_ci      BUG("Problem allocating tile status for resource");
125bf215546Sopenharmony_ci      return false;
126bf215546Sopenharmony_ci   }
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   rsc->ts_bo = rt_ts;
129bf215546Sopenharmony_ci   rsc->levels[0].ts_offset = 0;
130bf215546Sopenharmony_ci   rsc->levels[0].ts_layer_stride = ts_layer_stride;
131bf215546Sopenharmony_ci   rsc->levels[0].ts_size = rt_ts_size;
132bf215546Sopenharmony_ci   rsc->levels[0].ts_mode = ts_mode;
133bf215546Sopenharmony_ci   rsc->levels[0].ts_compress_fmt = ts_compress_fmt;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   return true;
136bf215546Sopenharmony_ci}
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_cistatic bool
139bf215546Sopenharmony_cietna_screen_can_create_resource(struct pipe_screen *pscreen,
140bf215546Sopenharmony_ci                                const struct pipe_resource *templat)
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
143bf215546Sopenharmony_ci   if (!translate_samples_to_xyscale(templat->nr_samples, NULL, NULL))
144bf215546Sopenharmony_ci      return false;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   /* templat->bind is not set here, so we must use the minimum sizes */
147bf215546Sopenharmony_ci   uint max_size =
148bf215546Sopenharmony_ci      MIN2(screen->specs.max_rendertarget_size, screen->specs.max_texture_size);
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   if (templat->width0 > max_size || templat->height0 > max_size)
151bf215546Sopenharmony_ci      return false;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   return true;
154bf215546Sopenharmony_ci}
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_cistatic unsigned
157bf215546Sopenharmony_cisetup_miptree(struct etna_resource *rsc, unsigned paddingX, unsigned paddingY,
158bf215546Sopenharmony_ci              unsigned msaa_xscale, unsigned msaa_yscale)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct pipe_resource *prsc = &rsc->base;
161bf215546Sopenharmony_ci   unsigned level, size = 0;
162bf215546Sopenharmony_ci   unsigned width = prsc->width0;
163bf215546Sopenharmony_ci   unsigned height = prsc->height0;
164bf215546Sopenharmony_ci   unsigned depth = prsc->depth0;
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   for (level = 0; level <= prsc->last_level; level++) {
167bf215546Sopenharmony_ci      struct etna_resource_level *mip = &rsc->levels[level];
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci      mip->width = width;
170bf215546Sopenharmony_ci      mip->height = height;
171bf215546Sopenharmony_ci      mip->depth = depth;
172bf215546Sopenharmony_ci      mip->padded_width = align(width * msaa_xscale, paddingX);
173bf215546Sopenharmony_ci      mip->padded_height = align(height * msaa_yscale, paddingY);
174bf215546Sopenharmony_ci      mip->stride = util_format_get_stride(prsc->format, mip->padded_width);
175bf215546Sopenharmony_ci      mip->offset = size;
176bf215546Sopenharmony_ci      mip->layer_stride = mip->stride * util_format_get_nblocksy(prsc->format, mip->padded_height);
177bf215546Sopenharmony_ci      mip->size = prsc->array_size * mip->layer_stride;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci      /* align levels to 64 bytes to be able to render to them */
180bf215546Sopenharmony_ci      size += align(mip->size, ETNA_PE_ALIGNMENT) * depth;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci      width = u_minify(width, 1);
183bf215546Sopenharmony_ci      height = u_minify(height, 1);
184bf215546Sopenharmony_ci      depth = u_minify(depth, 1);
185bf215546Sopenharmony_ci   }
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   return size;
188bf215546Sopenharmony_ci}
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci/* Is rs alignment needed? */
191bf215546Sopenharmony_cistatic bool is_rs_align(struct etna_screen *screen,
192bf215546Sopenharmony_ci                        const struct pipe_resource *tmpl)
193bf215546Sopenharmony_ci{
194bf215546Sopenharmony_ci   return screen->specs.use_blt ? false : (
195bf215546Sopenharmony_ci      VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN) ||
196bf215546Sopenharmony_ci      !etna_resource_sampler_only(tmpl));
197bf215546Sopenharmony_ci}
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci/* Create a new resource object, using the given template info */
200bf215546Sopenharmony_cistruct pipe_resource *
201bf215546Sopenharmony_cietna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
202bf215546Sopenharmony_ci                    uint64_t modifier, const struct pipe_resource *templat)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
205bf215546Sopenharmony_ci   struct etna_resource *rsc;
206bf215546Sopenharmony_ci   unsigned size;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   DBG_F(ETNA_DBG_RESOURCE_MSGS,
209bf215546Sopenharmony_ci         "target=%d, format=%s, %ux%ux%u, array_size=%u, "
210bf215546Sopenharmony_ci         "last_level=%u, nr_samples=%u, usage=%u, bind=%x, flags=%x",
211bf215546Sopenharmony_ci         templat->target, util_format_name(templat->format), templat->width0,
212bf215546Sopenharmony_ci         templat->height0, templat->depth0, templat->array_size,
213bf215546Sopenharmony_ci         templat->last_level, templat->nr_samples, templat->usage,
214bf215546Sopenharmony_ci         templat->bind, templat->flags);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   /* Determine scaling for antialiasing, allow override using debug flag */
217bf215546Sopenharmony_ci   int nr_samples = templat->nr_samples;
218bf215546Sopenharmony_ci   if ((templat->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) &&
219bf215546Sopenharmony_ci       !(templat->bind & PIPE_BIND_SAMPLER_VIEW)) {
220bf215546Sopenharmony_ci      if (DBG_ENABLED(ETNA_DBG_MSAA_2X))
221bf215546Sopenharmony_ci         nr_samples = 2;
222bf215546Sopenharmony_ci      if (DBG_ENABLED(ETNA_DBG_MSAA_4X))
223bf215546Sopenharmony_ci         nr_samples = 4;
224bf215546Sopenharmony_ci   }
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   int msaa_xscale = 1, msaa_yscale = 1;
227bf215546Sopenharmony_ci   if (!translate_samples_to_xyscale(nr_samples, &msaa_xscale, &msaa_yscale)) {
228bf215546Sopenharmony_ci      /* Number of samples not supported */
229bf215546Sopenharmony_ci      return NULL;
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   /* Determine needed padding (alignment of height/width) */
233bf215546Sopenharmony_ci   unsigned paddingX = 0, paddingY = 0;
234bf215546Sopenharmony_ci   unsigned halign = TEXTURE_HALIGN_FOUR;
235bf215546Sopenharmony_ci   if (!util_format_is_compressed(templat->format)) {
236bf215546Sopenharmony_ci      /* If we have the TEXTURE_HALIGN feature, we can always align to the
237bf215546Sopenharmony_ci       * resolve engine's width.  If not, we must not align resources used
238bf215546Sopenharmony_ci       * only for textures. If this GPU uses the BLT engine, never do RS align.
239bf215546Sopenharmony_ci       */
240bf215546Sopenharmony_ci      etna_layout_multiple(layout, screen->specs.pixel_pipes,
241bf215546Sopenharmony_ci                           is_rs_align (screen, templat),
242bf215546Sopenharmony_ci                           &paddingX, &paddingY, &halign);
243bf215546Sopenharmony_ci      assert(paddingX && paddingY);
244bf215546Sopenharmony_ci   } else {
245bf215546Sopenharmony_ci      /* Compressed textures are padded to their block size, but we don't have
246bf215546Sopenharmony_ci       * to do anything special for that. */
247bf215546Sopenharmony_ci      paddingX = 1;
248bf215546Sopenharmony_ci      paddingY = 1;
249bf215546Sopenharmony_ci   }
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   if (!screen->specs.use_blt && templat->target != PIPE_BUFFER && layout == ETNA_LAYOUT_LINEAR)
252bf215546Sopenharmony_ci      paddingY = align(paddingY, ETNA_RS_HEIGHT_MASK + 1);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   rsc = CALLOC_STRUCT(etna_resource);
255bf215546Sopenharmony_ci   if (!rsc)
256bf215546Sopenharmony_ci      return NULL;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   rsc->base = *templat;
259bf215546Sopenharmony_ci   rsc->base.screen = pscreen;
260bf215546Sopenharmony_ci   rsc->base.nr_samples = nr_samples;
261bf215546Sopenharmony_ci   rsc->layout = layout;
262bf215546Sopenharmony_ci   rsc->halign = halign;
263bf215546Sopenharmony_ci   rsc->explicit_flush = true;
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci   pipe_reference_init(&rsc->base.reference, 1);
266bf215546Sopenharmony_ci   util_range_init(&rsc->valid_buffer_range);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   if (unlikely(templat->bind & PIPE_BIND_SCANOUT) && screen->ro) {
271bf215546Sopenharmony_ci      struct pipe_resource scanout_templat = *templat;
272bf215546Sopenharmony_ci      struct winsys_handle handle;
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci      scanout_templat.width0 = align(scanout_templat.width0, paddingX);
275bf215546Sopenharmony_ci      scanout_templat.height0 = align(scanout_templat.height0, paddingY);
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci      rsc->scanout = renderonly_scanout_for_resource(&scanout_templat,
278bf215546Sopenharmony_ci                                                     screen->ro, &handle);
279bf215546Sopenharmony_ci      if (!rsc->scanout) {
280bf215546Sopenharmony_ci         BUG("Problem allocating kms memory for resource");
281bf215546Sopenharmony_ci         goto free_rsc;
282bf215546Sopenharmony_ci      }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci      assert(handle.type == WINSYS_HANDLE_TYPE_FD);
285bf215546Sopenharmony_ci      rsc->levels[0].stride = handle.stride;
286bf215546Sopenharmony_ci      rsc->bo = etna_screen_bo_from_handle(pscreen, &handle);
287bf215546Sopenharmony_ci      close(handle.handle);
288bf215546Sopenharmony_ci      if (unlikely(!rsc->bo))
289bf215546Sopenharmony_ci         goto free_rsc;
290bf215546Sopenharmony_ci   } else {
291bf215546Sopenharmony_ci      uint32_t flags = DRM_ETNA_GEM_CACHE_WC;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci      if (templat->bind & PIPE_BIND_VERTEX_BUFFER)
294bf215546Sopenharmony_ci         flags |= DRM_ETNA_GEM_FORCE_MMU;
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci      rsc->bo = etna_bo_new(screen->dev, size, flags);
297bf215546Sopenharmony_ci      if (unlikely(!rsc->bo)) {
298bf215546Sopenharmony_ci         BUG("Problem allocating video memory for resource");
299bf215546Sopenharmony_ci         goto free_rsc;
300bf215546Sopenharmony_ci      }
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   if (DBG_ENABLED(ETNA_DBG_ZERO)) {
304bf215546Sopenharmony_ci      void *map = etna_bo_map(rsc->bo);
305bf215546Sopenharmony_ci      etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_WRITE);
306bf215546Sopenharmony_ci      memset(map, 0, size);
307bf215546Sopenharmony_ci      etna_bo_cpu_fini(rsc->bo);
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   return &rsc->base;
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_cifree_rsc:
313bf215546Sopenharmony_ci   FREE(rsc);
314bf215546Sopenharmony_ci   return NULL;
315bf215546Sopenharmony_ci}
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_cistatic struct pipe_resource *
318bf215546Sopenharmony_cietna_resource_create(struct pipe_screen *pscreen,
319bf215546Sopenharmony_ci                     const struct pipe_resource *templat)
320bf215546Sopenharmony_ci{
321bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
322bf215546Sopenharmony_ci   unsigned layout = ETNA_LAYOUT_TILED;
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   /* At this point we don't know if the resource will be used as a texture,
325bf215546Sopenharmony_ci    * render target, or both, because gallium sets the bits whenever possible
326bf215546Sopenharmony_ci    * This matters because on some GPUs (GC2000) there is no tiling that is
327bf215546Sopenharmony_ci    * compatible with both TE and PE.
328bf215546Sopenharmony_ci    *
329bf215546Sopenharmony_ci    * We expect that depth/stencil buffers will always be used by PE (rendering),
330bf215546Sopenharmony_ci    * and any other non-scanout resource will be used as a texture at some point,
331bf215546Sopenharmony_ci    * So allocate a render-compatible base buffer for scanout/depthstencil buffers,
332bf215546Sopenharmony_ci    * and a texture-compatible base buffer in other cases
333bf215546Sopenharmony_ci    *
334bf215546Sopenharmony_ci    */
335bf215546Sopenharmony_ci   if (templat->bind & PIPE_BIND_DEPTH_STENCIL) {
336bf215546Sopenharmony_ci      if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer)
337bf215546Sopenharmony_ci         layout |= ETNA_LAYOUT_BIT_MULTI;
338bf215546Sopenharmony_ci      if (screen->specs.can_supertile)
339bf215546Sopenharmony_ci         layout |= ETNA_LAYOUT_BIT_SUPER;
340bf215546Sopenharmony_ci   } else if (screen->specs.can_supertile &&
341bf215546Sopenharmony_ci              VIV_FEATURE(screen, chipMinorFeatures2, SUPERTILED_TEXTURE) &&
342bf215546Sopenharmony_ci              etna_resource_hw_tileable(screen->specs.use_blt, templat)) {
343bf215546Sopenharmony_ci      layout |= ETNA_LAYOUT_BIT_SUPER;
344bf215546Sopenharmony_ci   }
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   if (/* linear base or scanout without modifier requested */
347bf215546Sopenharmony_ci       (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT)) ||
348bf215546Sopenharmony_ci       templat->target == PIPE_BUFFER || /* buffer always linear */
349bf215546Sopenharmony_ci       /* compressed textures don't use tiling, they have their own "tiles" */
350bf215546Sopenharmony_ci       util_format_is_compressed(templat->format)) {
351bf215546Sopenharmony_ci      layout = ETNA_LAYOUT_LINEAR;
352bf215546Sopenharmony_ci   }
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   /* modifier is only used for scanout surfaces, so safe to use LINEAR here */
355bf215546Sopenharmony_ci   return etna_resource_alloc(pscreen, layout, DRM_FORMAT_MOD_LINEAR, templat);
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_cienum modifier_priority {
359bf215546Sopenharmony_ci   MODIFIER_PRIORITY_INVALID = 0,
360bf215546Sopenharmony_ci   MODIFIER_PRIORITY_LINEAR,
361bf215546Sopenharmony_ci   MODIFIER_PRIORITY_SPLIT_TILED,
362bf215546Sopenharmony_ci   MODIFIER_PRIORITY_SPLIT_SUPER_TILED,
363bf215546Sopenharmony_ci   MODIFIER_PRIORITY_TILED,
364bf215546Sopenharmony_ci   MODIFIER_PRIORITY_SUPER_TILED,
365bf215546Sopenharmony_ci};
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_cistatic const uint64_t priority_to_modifier[] = {
368bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID,
369bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR,
370bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_SPLIT_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED,
371bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_SPLIT_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED,
372bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_TILED] = DRM_FORMAT_MOD_VIVANTE_TILED,
373bf215546Sopenharmony_ci   [MODIFIER_PRIORITY_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SUPER_TILED,
374bf215546Sopenharmony_ci};
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_cistatic uint64_t
377bf215546Sopenharmony_ciselect_best_modifier(const struct etna_screen * screen,
378bf215546Sopenharmony_ci                     const uint64_t *modifiers, const unsigned count)
379bf215546Sopenharmony_ci{
380bf215546Sopenharmony_ci   enum modifier_priority prio = MODIFIER_PRIORITY_INVALID;
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci   for (int i = 0; i < count; i++) {
383bf215546Sopenharmony_ci      switch (modifiers[i]) {
384bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
385bf215546Sopenharmony_ci         if ((screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer) ||
386bf215546Sopenharmony_ci             !screen->specs.can_supertile)
387bf215546Sopenharmony_ci            break;
388bf215546Sopenharmony_ci         prio = MAX2(prio, MODIFIER_PRIORITY_SUPER_TILED);
389bf215546Sopenharmony_ci         break;
390bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_VIVANTE_TILED:
391bf215546Sopenharmony_ci         if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer)
392bf215546Sopenharmony_ci            break;
393bf215546Sopenharmony_ci         prio = MAX2(prio, MODIFIER_PRIORITY_TILED);
394bf215546Sopenharmony_ci         break;
395bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
396bf215546Sopenharmony_ci         if ((screen->specs.pixel_pipes < 2) || !screen->specs.can_supertile)
397bf215546Sopenharmony_ci            break;
398bf215546Sopenharmony_ci         prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_SUPER_TILED);
399bf215546Sopenharmony_ci         break;
400bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
401bf215546Sopenharmony_ci         if (screen->specs.pixel_pipes < 2)
402bf215546Sopenharmony_ci            break;
403bf215546Sopenharmony_ci         prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_TILED);
404bf215546Sopenharmony_ci         break;
405bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_LINEAR:
406bf215546Sopenharmony_ci         prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR);
407bf215546Sopenharmony_ci         break;
408bf215546Sopenharmony_ci      case DRM_FORMAT_MOD_INVALID:
409bf215546Sopenharmony_ci      default:
410bf215546Sopenharmony_ci         break;
411bf215546Sopenharmony_ci      }
412bf215546Sopenharmony_ci   }
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   return priority_to_modifier[prio];
415bf215546Sopenharmony_ci}
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_cistatic struct pipe_resource *
418bf215546Sopenharmony_cietna_resource_create_modifiers(struct pipe_screen *pscreen,
419bf215546Sopenharmony_ci                               const struct pipe_resource *templat,
420bf215546Sopenharmony_ci                               const uint64_t *modifiers, int count)
421bf215546Sopenharmony_ci{
422bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
423bf215546Sopenharmony_ci   struct pipe_resource tmpl = *templat;
424bf215546Sopenharmony_ci   uint64_t modifier = select_best_modifier(screen, modifiers, count);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   if (modifier == DRM_FORMAT_MOD_INVALID)
427bf215546Sopenharmony_ci      return NULL;
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   return etna_resource_alloc(pscreen, modifier_to_layout(modifier), modifier, &tmpl);
430bf215546Sopenharmony_ci}
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_cistatic void
433bf215546Sopenharmony_cietna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc)
434bf215546Sopenharmony_ci{
435bf215546Sopenharmony_ci   etna_resource(prsc)->seqno++;
436bf215546Sopenharmony_ci}
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_cistatic void
439bf215546Sopenharmony_cietna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
440bf215546Sopenharmony_ci{
441bf215546Sopenharmony_ci   struct etna_resource *rsc = etna_resource(prsc);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   if (rsc->bo)
444bf215546Sopenharmony_ci      etna_bo_del(rsc->bo);
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   if (rsc->ts_bo)
447bf215546Sopenharmony_ci      etna_bo_del(rsc->ts_bo);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   if (rsc->scanout)
450bf215546Sopenharmony_ci      renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   util_range_destroy(&rsc->valid_buffer_range);
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   pipe_resource_reference(&rsc->texture, NULL);
455bf215546Sopenharmony_ci   pipe_resource_reference(&rsc->render, NULL);
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci   for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
458bf215546Sopenharmony_ci      FREE(rsc->levels[i].patch_offsets);
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   FREE(rsc);
461bf215546Sopenharmony_ci}
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_cistatic struct pipe_resource *
464bf215546Sopenharmony_cietna_resource_from_handle(struct pipe_screen *pscreen,
465bf215546Sopenharmony_ci                          const struct pipe_resource *tmpl,
466bf215546Sopenharmony_ci                          struct winsys_handle *handle, unsigned usage)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
469bf215546Sopenharmony_ci   struct etna_resource *rsc;
470bf215546Sopenharmony_ci   struct etna_resource_level *level;
471bf215546Sopenharmony_ci   struct pipe_resource *prsc;
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
474bf215546Sopenharmony_ci       "nr_samples=%u, usage=%u, bind=%x, flags=%x",
475bf215546Sopenharmony_ci       tmpl->target, util_format_name(tmpl->format), tmpl->width0,
476bf215546Sopenharmony_ci       tmpl->height0, tmpl->depth0, tmpl->array_size, tmpl->last_level,
477bf215546Sopenharmony_ci       tmpl->nr_samples, tmpl->usage, tmpl->bind, tmpl->flags);
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   rsc = CALLOC_STRUCT(etna_resource);
480bf215546Sopenharmony_ci   if (!rsc)
481bf215546Sopenharmony_ci      return NULL;
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   level = &rsc->levels[0];
484bf215546Sopenharmony_ci   prsc = &rsc->base;
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   *prsc = *tmpl;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   pipe_reference_init(&prsc->reference, 1);
489bf215546Sopenharmony_ci   util_range_init(&rsc->valid_buffer_range);
490bf215546Sopenharmony_ci   prsc->screen = pscreen;
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci   rsc->bo = etna_screen_bo_from_handle(pscreen, handle);
493bf215546Sopenharmony_ci   if (!rsc->bo)
494bf215546Sopenharmony_ci      goto fail;
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci   rsc->seqno = 1;
497bf215546Sopenharmony_ci   rsc->layout = modifier_to_layout(handle->modifier);
498bf215546Sopenharmony_ci   rsc->halign = TEXTURE_HALIGN_FOUR;
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci   if (usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)
501bf215546Sopenharmony_ci      rsc->explicit_flush = true;
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   level->width = tmpl->width0;
504bf215546Sopenharmony_ci   level->height = tmpl->height0;
505bf215546Sopenharmony_ci   level->depth = tmpl->depth0;
506bf215546Sopenharmony_ci   level->stride = handle->stride;
507bf215546Sopenharmony_ci   level->offset = handle->offset;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   /* Determine padding of the imported resource. */
510bf215546Sopenharmony_ci   unsigned paddingX = 0, paddingY = 0;
511bf215546Sopenharmony_ci   etna_layout_multiple(rsc->layout, screen->specs.pixel_pipes,
512bf215546Sopenharmony_ci                        is_rs_align(screen, tmpl),
513bf215546Sopenharmony_ci                        &paddingX, &paddingY, &rsc->halign);
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   if (!screen->specs.use_blt && rsc->layout == ETNA_LAYOUT_LINEAR)
516bf215546Sopenharmony_ci      paddingY = align(paddingY, ETNA_RS_HEIGHT_MASK + 1);
517bf215546Sopenharmony_ci   level->padded_width = align(level->width, paddingX);
518bf215546Sopenharmony_ci   level->padded_height = align(level->height, paddingY);
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci   level->layer_stride = level->stride * util_format_get_nblocksy(prsc->format,
521bf215546Sopenharmony_ci                                                                  level->padded_height);
522bf215546Sopenharmony_ci   level->size = level->layer_stride;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   /* The DDX must give us a BO which conforms to our padding size.
525bf215546Sopenharmony_ci    * The stride of the BO must be greater or equal to our padded
526bf215546Sopenharmony_ci    * stride. The size of the BO must accomodate the padded height. */
527bf215546Sopenharmony_ci   if (level->stride < util_format_get_stride(tmpl->format, level->padded_width)) {
528bf215546Sopenharmony_ci      BUG("BO stride %u is too small for RS engine width padding (%zu, format %s)",
529bf215546Sopenharmony_ci          level->stride, util_format_get_stride(tmpl->format, level->padded_width),
530bf215546Sopenharmony_ci          util_format_name(tmpl->format));
531bf215546Sopenharmony_ci      goto fail;
532bf215546Sopenharmony_ci   }
533bf215546Sopenharmony_ci   if (etna_bo_size(rsc->bo) < level->stride * level->padded_height) {
534bf215546Sopenharmony_ci      BUG("BO size %u is too small for RS engine height padding (%u, format %s)",
535bf215546Sopenharmony_ci          etna_bo_size(rsc->bo), level->stride * level->padded_height,
536bf215546Sopenharmony_ci          util_format_name(tmpl->format));
537bf215546Sopenharmony_ci      goto fail;
538bf215546Sopenharmony_ci   }
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci   if (screen->ro) {
541bf215546Sopenharmony_ci      struct pipe_resource *imp_prsc = prsc;
542bf215546Sopenharmony_ci      do {
543bf215546Sopenharmony_ci         etna_resource(imp_prsc)->scanout =
544bf215546Sopenharmony_ci               renderonly_create_gpu_import_for_resource(imp_prsc, screen->ro,
545bf215546Sopenharmony_ci                                                         NULL);
546bf215546Sopenharmony_ci         /* failure is expected for scanout incompatible buffers */
547bf215546Sopenharmony_ci      } while ((imp_prsc = imp_prsc->next));
548bf215546Sopenharmony_ci   }
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   return prsc;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_cifail:
553bf215546Sopenharmony_ci   etna_resource_destroy(pscreen, prsc);
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   return NULL;
556bf215546Sopenharmony_ci}
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_cistatic bool
559bf215546Sopenharmony_cietna_resource_get_handle(struct pipe_screen *pscreen,
560bf215546Sopenharmony_ci                         struct pipe_context *pctx,
561bf215546Sopenharmony_ci                         struct pipe_resource *prsc,
562bf215546Sopenharmony_ci                         struct winsys_handle *handle, unsigned usage)
563bf215546Sopenharmony_ci{
564bf215546Sopenharmony_ci   struct etna_screen *screen = etna_screen(pscreen);
565bf215546Sopenharmony_ci   struct etna_resource *rsc = etna_resource(prsc);
566bf215546Sopenharmony_ci   struct renderonly_scanout *scanout;
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci   if (handle->plane) {
569bf215546Sopenharmony_ci      struct pipe_resource *cur = prsc;
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci      for (int i = 0; i < handle->plane; i++) {
572bf215546Sopenharmony_ci         cur = cur->next;
573bf215546Sopenharmony_ci         if (!cur)
574bf215546Sopenharmony_ci            return false;
575bf215546Sopenharmony_ci      }
576bf215546Sopenharmony_ci      rsc = etna_resource(cur);
577bf215546Sopenharmony_ci   }
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   /* Scanout is always attached to the base resource */
580bf215546Sopenharmony_ci   scanout = rsc->scanout;
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   handle->stride = rsc->levels[0].stride;
583bf215546Sopenharmony_ci   handle->offset = rsc->levels[0].offset;
584bf215546Sopenharmony_ci   handle->modifier = layout_to_modifier(rsc->layout);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci   if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH))
587bf215546Sopenharmony_ci      rsc->explicit_flush = false;
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci   if (handle->type == WINSYS_HANDLE_TYPE_SHARED) {
590bf215546Sopenharmony_ci      return etna_bo_get_name(rsc->bo, &handle->handle) == 0;
591bf215546Sopenharmony_ci   } else if (handle->type == WINSYS_HANDLE_TYPE_KMS) {
592bf215546Sopenharmony_ci      if (screen->ro) {
593bf215546Sopenharmony_ci         return renderonly_get_handle(scanout, handle);
594bf215546Sopenharmony_ci      } else {
595bf215546Sopenharmony_ci         handle->handle = etna_bo_handle(rsc->bo);
596bf215546Sopenharmony_ci         return true;
597bf215546Sopenharmony_ci      }
598bf215546Sopenharmony_ci   } else if (handle->type == WINSYS_HANDLE_TYPE_FD) {
599bf215546Sopenharmony_ci      handle->handle = etna_bo_dmabuf(rsc->bo);
600bf215546Sopenharmony_ci      return true;
601bf215546Sopenharmony_ci   } else {
602bf215546Sopenharmony_ci      return false;
603bf215546Sopenharmony_ci   }
604bf215546Sopenharmony_ci}
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_cistatic bool
607bf215546Sopenharmony_cietna_resource_get_param(struct pipe_screen *pscreen,
608bf215546Sopenharmony_ci                        struct pipe_context *pctx, struct pipe_resource *prsc,
609bf215546Sopenharmony_ci                        unsigned plane, unsigned layer, unsigned level,
610bf215546Sopenharmony_ci                        enum pipe_resource_param param,
611bf215546Sopenharmony_ci                        unsigned usage, uint64_t *value)
612bf215546Sopenharmony_ci{
613bf215546Sopenharmony_ci   if (param == PIPE_RESOURCE_PARAM_NPLANES) {
614bf215546Sopenharmony_ci      unsigned count = 0;
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci      for (struct pipe_resource *cur = prsc; cur; cur = cur->next)
617bf215546Sopenharmony_ci         count++;
618bf215546Sopenharmony_ci      *value = count;
619bf215546Sopenharmony_ci      return true;
620bf215546Sopenharmony_ci   }
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci   struct pipe_resource *cur = prsc;
623bf215546Sopenharmony_ci   for (int i = 0; i < plane; i++) {
624bf215546Sopenharmony_ci      cur = cur->next;
625bf215546Sopenharmony_ci      if (!cur)
626bf215546Sopenharmony_ci         return false;
627bf215546Sopenharmony_ci   }
628bf215546Sopenharmony_ci   struct etna_resource *rsc = etna_resource(cur);
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   switch (param) {
631bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_STRIDE:
632bf215546Sopenharmony_ci      *value = rsc->levels[level].stride;
633bf215546Sopenharmony_ci      return true;
634bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_OFFSET:
635bf215546Sopenharmony_ci      *value = rsc->levels[level].offset;
636bf215546Sopenharmony_ci      return true;
637bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_MODIFIER:
638bf215546Sopenharmony_ci      *value = layout_to_modifier(rsc->layout);
639bf215546Sopenharmony_ci      return true;
640bf215546Sopenharmony_ci   default:
641bf215546Sopenharmony_ci      return false;
642bf215546Sopenharmony_ci   }
643bf215546Sopenharmony_ci}
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_civoid
646bf215546Sopenharmony_cietna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc,
647bf215546Sopenharmony_ci                   enum etna_resource_status status)
648bf215546Sopenharmony_ci{
649bf215546Sopenharmony_ci   struct etna_resource *rsc;
650bf215546Sopenharmony_ci   struct hash_entry *entry;
651bf215546Sopenharmony_ci   uint32_t hash;
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci   if (!prsc)
654bf215546Sopenharmony_ci      return;
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   rsc = etna_resource(prsc);
657bf215546Sopenharmony_ci   hash = _mesa_hash_pointer(rsc);
658bf215546Sopenharmony_ci   entry = _mesa_hash_table_search_pre_hashed(ctx->pending_resources,
659bf215546Sopenharmony_ci                                              hash, rsc);
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci   if (entry) {
662bf215546Sopenharmony_ci      enum etna_resource_status tmp = (uintptr_t)entry->data;
663bf215546Sopenharmony_ci      tmp |= status;
664bf215546Sopenharmony_ci      entry->data = (void *)(uintptr_t)tmp;
665bf215546Sopenharmony_ci   } else {
666bf215546Sopenharmony_ci      _mesa_hash_table_insert_pre_hashed(ctx->pending_resources, hash, rsc,
667bf215546Sopenharmony_ci                                         (void *)(uintptr_t)status);
668bf215546Sopenharmony_ci   }
669bf215546Sopenharmony_ci}
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_cienum etna_resource_status
672bf215546Sopenharmony_cietna_resource_status(struct etna_context *ctx, struct etna_resource *res)
673bf215546Sopenharmony_ci{
674bf215546Sopenharmony_ci   struct hash_entry *entry = _mesa_hash_table_search(ctx->pending_resources, res);
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci   if (entry)
677bf215546Sopenharmony_ci      return (enum etna_resource_status)(uintptr_t)entry->data;
678bf215546Sopenharmony_ci   else
679bf215546Sopenharmony_ci      return 0;
680bf215546Sopenharmony_ci}
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_cibool
683bf215546Sopenharmony_cietna_resource_has_valid_ts(struct etna_resource *rsc)
684bf215546Sopenharmony_ci{
685bf215546Sopenharmony_ci   if (!rsc->ts_bo)
686bf215546Sopenharmony_ci      return false;
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   for (int level = 0; level <= rsc->base.last_level; level++)
689bf215546Sopenharmony_ci      if (rsc->levels[level].ts_valid)
690bf215546Sopenharmony_ci         return true;
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci   return false;
693bf215546Sopenharmony_ci}
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_civoid
696bf215546Sopenharmony_cietna_resource_screen_init(struct pipe_screen *pscreen)
697bf215546Sopenharmony_ci{
698bf215546Sopenharmony_ci   pscreen->can_create_resource = etna_screen_can_create_resource;
699bf215546Sopenharmony_ci   pscreen->resource_create = etna_resource_create;
700bf215546Sopenharmony_ci   pscreen->resource_create_with_modifiers = etna_resource_create_modifiers;
701bf215546Sopenharmony_ci   pscreen->resource_from_handle = etna_resource_from_handle;
702bf215546Sopenharmony_ci   pscreen->resource_get_handle = etna_resource_get_handle;
703bf215546Sopenharmony_ci   pscreen->resource_get_param = etna_resource_get_param;
704bf215546Sopenharmony_ci   pscreen->resource_changed = etna_resource_changed;
705bf215546Sopenharmony_ci   pscreen->resource_destroy = etna_resource_destroy;
706bf215546Sopenharmony_ci}
707