2 * Copyright (c) 2017-2019 Lima Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "util/u_memory.h"
26 #include "util/u_blitter.h"
27 #include "util/u_format.h"
28 #include "util/u_inlines.h"
29 #include "util/u_math.h"
30 #include "util/u_debug.h"
31 #include "util/u_transfer.h"
32 #include "util/u_surface.h"
33 #include "util/hash_table.h"
34 #include "util/u_drm.h"
35 #include "renderonly/renderonly.h"
37 #include "state_tracker/drm_driver.h"
39 #include "drm-uapi/drm_fourcc.h"
40 #include "drm-uapi/lima_drm.h"
42 #include "lima_screen.h"
43 #include "lima_context.h"
44 #include "lima_resource.h"
46 #include "lima_util.h"
47 #include "pan_tiling.h"
49 static struct pipe_resource
*
50 lima_resource_create_scanout(struct pipe_screen
*pscreen
,
51 const struct pipe_resource
*templat
,
52 unsigned width
, unsigned height
)
54 struct lima_screen
*screen
= lima_screen(pscreen
);
55 struct renderonly_scanout
*scanout
;
56 struct winsys_handle handle
;
57 struct pipe_resource
*pres
;
59 struct pipe_resource scanout_templat
= *templat
;
60 scanout_templat
.width0
= width
;
61 scanout_templat
.height0
= height
;
62 scanout_templat
.screen
= pscreen
;
64 scanout
= renderonly_scanout_for_resource(&scanout_templat
,
69 assert(handle
.type
== WINSYS_HANDLE_TYPE_FD
);
70 pres
= pscreen
->resource_from_handle(pscreen
, templat
, &handle
,
71 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
);
75 renderonly_scanout_destroy(scanout
, screen
->ro
);
79 struct lima_resource
*res
= lima_resource(pres
);
80 res
->scanout
= scanout
;
86 setup_miptree(struct lima_resource
*res
,
87 unsigned width0
, unsigned height0
,
88 bool should_align_dimensions
)
90 struct pipe_resource
*pres
= &res
->base
;
92 unsigned width
= width0
;
93 unsigned height
= height0
;
94 unsigned depth
= pres
->depth0
;
97 for (level
= 0; level
<= pres
->last_level
; level
++) {
98 uint32_t actual_level_size
;
100 unsigned aligned_width
;
101 unsigned aligned_height
;
103 if (should_align_dimensions
) {
104 aligned_width
= align(width
, 16);
105 aligned_height
= align(height
, 16);
107 aligned_width
= width
;
108 aligned_height
= height
;
111 stride
= util_format_get_stride(pres
->format
, aligned_width
);
112 actual_level_size
= stride
*
113 util_format_get_nblocksy(pres
->format
, aligned_height
) *
114 pres
->array_size
* depth
;
116 res
->levels
[level
].width
= aligned_width
;
117 res
->levels
[level
].stride
= stride
;
118 res
->levels
[level
].offset
= size
;
120 /* The start address of each level <= 10 must be 64-aligned
121 * in order to be able to pass the addresses
123 * The start addresses of level 11 and level 12 are passed
124 * implicitely: they start at an offset of respectively
125 * 0x0400 and 0x0800 from the start address of level 10 */
127 size
+= align(actual_level_size
, 64);
128 else if (level
!= pres
->last_level
)
131 size
+= actual_level_size
; /* Save some memory */
133 width
= u_minify(width
, 1);
134 height
= u_minify(height
, 1);
135 depth
= u_minify(depth
, 1);
141 static struct pipe_resource
*
142 lima_resource_create_bo(struct pipe_screen
*pscreen
,
143 const struct pipe_resource
*templat
,
144 unsigned width
, unsigned height
,
145 bool should_align_dimensions
)
147 struct lima_screen
*screen
= lima_screen(pscreen
);
148 struct lima_resource
*res
;
149 struct pipe_resource
*pres
;
151 res
= CALLOC_STRUCT(lima_resource
);
155 res
->base
= *templat
;
156 res
->base
.screen
= pscreen
;
157 pipe_reference_init(&res
->base
.reference
, 1);
161 uint32_t size
= setup_miptree(res
, width
, height
, should_align_dimensions
);
162 size
= align(size
, LIMA_PAGE_SIZE
);
164 res
->bo
= lima_bo_create(screen
, size
, 0);
173 static struct pipe_resource
*
174 _lima_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
175 const struct pipe_resource
*templat
,
176 const uint64_t *modifiers
,
179 struct lima_screen
*screen
= lima_screen(pscreen
);
180 bool should_tile
= false;
181 unsigned width
, height
;
182 bool should_align_dimensions
;
184 /* VBOs/PBOs are untiled (and 1 height). */
185 if (templat
->target
== PIPE_BUFFER
)
188 if (templat
->bind
& (PIPE_BIND_LINEAR
| PIPE_BIND_SCANOUT
))
191 /* if linear buffer is not allowed, alloc fail */
192 if (!should_tile
&& !drm_find_modifier(DRM_FORMAT_MOD_LINEAR
, modifiers
, count
))
195 if (should_tile
|| (templat
->bind
& PIPE_BIND_RENDER_TARGET
) ||
196 (templat
->bind
& PIPE_BIND_DEPTH_STENCIL
)) {
197 should_align_dimensions
= true;
198 width
= align(templat
->width0
, 16);
199 height
= align(templat
->height0
, 16);
202 should_align_dimensions
= false;
203 width
= templat
->width0
;
204 height
= templat
->height0
;
207 struct pipe_resource
*pres
;
208 if (screen
->ro
&& (templat
->bind
& PIPE_BIND_SCANOUT
))
209 pres
= lima_resource_create_scanout(pscreen
, templat
, width
, height
);
211 pres
= lima_resource_create_bo(pscreen
, templat
, width
, height
,
212 should_align_dimensions
);
215 struct lima_resource
*res
= lima_resource(pres
);
216 res
->tiled
= should_tile
;
218 debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d "
219 "bind=%x usage=%d tile=%d last_level=%d\n", __func__
,
220 pres
, pres
->width0
, pres
->height0
, pres
->depth0
,
221 pres
->target
, pres
->bind
, pres
->usage
, should_tile
, templat
->last_level
);
226 static struct pipe_resource
*
227 lima_resource_create(struct pipe_screen
*pscreen
,
228 const struct pipe_resource
*templat
)
230 static const uint64_t modifiers
[] = {
231 DRM_FORMAT_MOD_LINEAR
,
233 return _lima_resource_create_with_modifiers(pscreen
, templat
, modifiers
, ARRAY_SIZE(modifiers
));
236 static struct pipe_resource
*
237 lima_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
238 const struct pipe_resource
*templat
,
239 const uint64_t *modifiers
,
242 struct pipe_resource tmpl
= *templat
;
244 /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers
245 * don't have usage parameter, but buffer created by these functions
246 * may be used for scanout. So we assume buffer created by this
247 * function always enable scanout if linear modifier is permitted.
249 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR
, modifiers
, count
))
250 tmpl
.bind
|= PIPE_BIND_SCANOUT
;
252 return _lima_resource_create_with_modifiers(pscreen
, &tmpl
, modifiers
, count
);
256 lima_resource_destroy(struct pipe_screen
*pscreen
, struct pipe_resource
*pres
)
258 struct lima_screen
*screen
= lima_screen(pscreen
);
259 struct lima_resource
*res
= lima_resource(pres
);
262 lima_bo_unreference(res
->bo
);
265 renderonly_scanout_destroy(res
->scanout
, screen
->ro
);
267 if (res
->damage
.region
)
268 FREE(res
->damage
.region
);
273 static struct pipe_resource
*
274 lima_resource_from_handle(struct pipe_screen
*pscreen
,
275 const struct pipe_resource
*templat
,
276 struct winsys_handle
*handle
, unsigned usage
)
278 struct lima_resource
*res
;
279 struct lima_screen
*screen
= lima_screen(pscreen
);
281 res
= CALLOC_STRUCT(lima_resource
);
285 struct pipe_resource
*pres
= &res
->base
;
287 pres
->screen
= pscreen
;
288 pipe_reference_init(&pres
->reference
, 1);
289 res
->levels
[0].offset
= 0;
290 res
->levels
[0].stride
= handle
->stride
;
292 res
->bo
= lima_bo_import(screen
, handle
);
298 /* check alignment for the buffer */
299 if (pres
->bind
& PIPE_BIND_RENDER_TARGET
) {
300 unsigned width
, height
, stride
, size
;
302 width
= align(pres
->width0
, 16);
303 height
= align(pres
->height0
, 16);
304 stride
= util_format_get_stride(pres
->format
, width
);
305 size
= util_format_get_2d_size(pres
->format
, stride
, height
);
307 if (res
->levels
[0].stride
!= stride
|| res
->bo
->size
< size
) {
308 debug_error("import buffer not properly aligned\n");
312 res
->levels
[0].width
= width
;
315 res
->levels
[0].width
= pres
->width0
;
317 handle
->modifier
= DRM_FORMAT_MOD_LINEAR
;
323 lima_resource_destroy(pscreen
, pres
);
328 lima_resource_get_handle(struct pipe_screen
*pscreen
,
329 struct pipe_context
*pctx
,
330 struct pipe_resource
*pres
,
331 struct winsys_handle
*handle
, unsigned usage
)
333 struct lima_screen
*screen
= lima_screen(pscreen
);
334 struct lima_resource
*res
= lima_resource(pres
);
336 handle
->modifier
= DRM_FORMAT_MOD_LINEAR
;
338 if (handle
->type
== WINSYS_HANDLE_TYPE_KMS
&& screen
->ro
&&
339 renderonly_get_handle(res
->scanout
, handle
))
342 if (!lima_bo_export(res
->bo
, handle
))
345 handle
->stride
= res
->levels
[0].stride
;
350 get_scissor_from_box(struct pipe_scissor_state
*s
,
351 const struct pipe_box
*b
, int h
)
353 int y
= h
- (b
->y
+ b
->height
);
354 /* region in tile unit */
357 s
->maxx
= (b
->x
+ b
->width
+ 0xf) >> 4;
358 s
->maxy
= (y
+ b
->height
+ 0xf) >> 4;
362 get_damage_bound_box(struct pipe_resource
*pres
,
363 const struct pipe_box
*rects
,
365 struct pipe_scissor_state
*bound
)
367 struct pipe_box b
= rects
[0];
369 for (int i
= 1; i
< nrects
; i
++)
370 u_box_union_2d(&b
, &b
, rects
+ i
);
372 int ret
= u_box_clip_2d(&b
, &b
, pres
->width0
, pres
->height0
);
374 memset(bound
, 0, sizeof(*bound
));
376 get_scissor_from_box(bound
, &b
, pres
->height0
);
380 lima_resource_set_damage_region(struct pipe_screen
*pscreen
,
381 struct pipe_resource
*pres
,
383 const struct pipe_box
*rects
)
385 struct lima_resource
*res
= lima_resource(pres
);
386 struct lima_damage_region
*damage
= &res
->damage
;
389 if (damage
->region
) {
390 FREE(damage
->region
);
391 damage
->region
= NULL
;
392 damage
->num_region
= 0;
400 * TODO: currently only check if there is any single damage
401 * region that can cover the full render target; there may
402 * be some accurate way, but a single window size damage
403 * region is most of the case from weston
405 for (i
= 0; i
< nrects
; i
++) {
406 if (rects
[i
].x
<= 0 && rects
[i
].y
<= 0 &&
407 rects
[i
].x
+ rects
[i
].width
>= pres
->width0
&&
408 rects
[i
].y
+ rects
[i
].height
>= pres
->height0
)
412 struct pipe_scissor_state
*bound
= &damage
->bound
;
413 get_damage_bound_box(pres
, rects
, nrects
, bound
);
415 damage
->region
= CALLOC(nrects
, sizeof(*damage
->region
));
419 for (i
= 0; i
< nrects
; i
++)
420 get_scissor_from_box(damage
->region
+ i
, rects
+ i
,
423 /* is region aligned to tiles? */
424 damage
->aligned
= true;
425 for (i
= 0; i
< nrects
; i
++) {
426 if (rects
[i
].x
& 0xf || rects
[i
].y
& 0xf ||
427 rects
[i
].width
& 0xf || rects
[i
].height
& 0xf) {
428 damage
->aligned
= false;
433 damage
->num_region
= nrects
;
437 lima_resource_screen_init(struct lima_screen
*screen
)
439 screen
->base
.resource_create
= lima_resource_create
;
440 screen
->base
.resource_create_with_modifiers
= lima_resource_create_with_modifiers
;
441 screen
->base
.resource_from_handle
= lima_resource_from_handle
;
442 screen
->base
.resource_destroy
= lima_resource_destroy
;
443 screen
->base
.resource_get_handle
= lima_resource_get_handle
;
444 screen
->base
.set_damage_region
= lima_resource_set_damage_region
;
447 static struct pipe_surface
*
448 lima_surface_create(struct pipe_context
*pctx
,
449 struct pipe_resource
*pres
,
450 const struct pipe_surface
*surf_tmpl
)
452 struct lima_surface
*surf
= CALLOC_STRUCT(lima_surface
);
457 assert(surf_tmpl
->u
.tex
.first_layer
== surf_tmpl
->u
.tex
.last_layer
);
459 struct pipe_surface
*psurf
= &surf
->base
;
460 unsigned level
= surf_tmpl
->u
.tex
.level
;
462 pipe_reference_init(&psurf
->reference
, 1);
463 pipe_resource_reference(&psurf
->texture
, pres
);
465 psurf
->context
= pctx
;
466 psurf
->format
= surf_tmpl
->format
;
467 psurf
->width
= u_minify(pres
->width0
, level
);
468 psurf
->height
= u_minify(pres
->height0
, level
);
469 psurf
->u
.tex
.level
= level
;
470 psurf
->u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
471 psurf
->u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
473 surf
->tiled_w
= align(psurf
->width
, 16) >> 4;
474 surf
->tiled_h
= align(psurf
->height
, 16) >> 4;
478 struct lima_context
*ctx
= lima_context(pctx
);
479 if (ctx
->plb_pp_stream
) {
480 struct lima_ctx_plb_pp_stream_key key
= {
481 .tiled_w
= surf
->tiled_w
,
482 .tiled_h
= surf
->tiled_h
,
485 for (int i
= 0; i
< lima_ctx_num_plb
; i
++) {
488 struct hash_entry
*entry
=
489 _mesa_hash_table_search(ctx
->plb_pp_stream
, &key
);
491 struct lima_ctx_plb_pp_stream
*s
= entry
->data
;
495 struct lima_ctx_plb_pp_stream
*s
=
496 ralloc(ctx
->plb_pp_stream
, struct lima_ctx_plb_pp_stream
);
497 s
->key
.plb_index
= i
;
498 s
->key
.tiled_w
= surf
->tiled_w
;
499 s
->key
.tiled_h
= surf
->tiled_h
;
502 _mesa_hash_table_insert(ctx
->plb_pp_stream
, &s
->key
, s
);
511 lima_surface_destroy(struct pipe_context
*pctx
, struct pipe_surface
*psurf
)
513 struct lima_surface
*surf
= lima_surface(psurf
);
514 /* psurf->context may be not equal with pctx (i.e. glxinfo) */
515 struct lima_context
*ctx
= lima_context(psurf
->context
);
517 if (ctx
->plb_pp_stream
) {
518 struct lima_ctx_plb_pp_stream_key key
= {
519 .tiled_w
= surf
->tiled_w
,
520 .tiled_h
= surf
->tiled_h
,
523 for (int i
= 0; i
< lima_ctx_num_plb
; i
++) {
526 struct hash_entry
*entry
=
527 _mesa_hash_table_search(ctx
->plb_pp_stream
, &key
);
528 struct lima_ctx_plb_pp_stream
*s
= entry
->data
;
529 if (--s
->refcnt
== 0) {
531 lima_bo_unreference(s
->bo
);
532 _mesa_hash_table_remove(ctx
->plb_pp_stream
, entry
);
538 pipe_resource_reference(&psurf
->texture
, NULL
);
543 lima_transfer_map(struct pipe_context
*pctx
,
544 struct pipe_resource
*pres
,
547 const struct pipe_box
*box
,
548 struct pipe_transfer
**pptrans
)
550 struct lima_context
*ctx
= lima_context(pctx
);
551 struct lima_resource
*res
= lima_resource(pres
);
552 struct lima_bo
*bo
= res
->bo
;
553 struct lima_transfer
*trans
;
554 struct pipe_transfer
*ptrans
;
556 /* No direct mappings of tiled, since we need to manually
559 if (res
->tiled
&& (usage
& PIPE_TRANSFER_MAP_DIRECTLY
))
562 /* use once buffers are made sure to not read/write overlapped
563 * range, so no need to sync */
564 if (pres
->usage
!= PIPE_USAGE_STREAM
) {
565 if (usage
& PIPE_TRANSFER_READ_WRITE
) {
566 if (lima_need_flush(ctx
, bo
, usage
& PIPE_TRANSFER_WRITE
))
569 unsigned op
= usage
& PIPE_TRANSFER_WRITE
?
570 LIMA_GEM_WAIT_WRITE
: LIMA_GEM_WAIT_READ
;
571 lima_bo_wait(bo
, op
, PIPE_TIMEOUT_INFINITE
);
575 if (!lima_bo_map(bo
))
578 trans
= slab_alloc(&ctx
->transfer_pool
);
582 memset(trans
, 0, sizeof(*trans
));
583 ptrans
= &trans
->base
;
585 pipe_resource_reference(&ptrans
->resource
, pres
);
586 ptrans
->level
= level
;
587 ptrans
->usage
= usage
;
593 ptrans
->stride
= util_format_get_stride(pres
->format
, ptrans
->box
.width
);
594 ptrans
->layer_stride
= ptrans
->stride
* ptrans
->box
.height
;
596 trans
->staging
= malloc(ptrans
->stride
* ptrans
->box
.height
* ptrans
->box
.depth
);
598 if (usage
& PIPE_TRANSFER_READ
)
599 panfrost_load_tiled_image(trans
->staging
, bo
->map
+ res
->levels
[level
].offset
,
602 res
->levels
[level
].stride
,
603 util_format_get_blocksize(pres
->format
));
605 return trans
->staging
;
607 ptrans
->stride
= res
->levels
[level
].stride
;
608 ptrans
->layer_stride
= ptrans
->stride
* box
->height
;
610 return bo
->map
+ res
->levels
[level
].offset
+
611 box
->z
* ptrans
->layer_stride
+
612 box
->y
/ util_format_get_blockheight(pres
->format
) * ptrans
->stride
+
613 box
->x
/ util_format_get_blockwidth(pres
->format
) *
614 util_format_get_blocksize(pres
->format
);
619 lima_transfer_flush_region(struct pipe_context
*pctx
,
620 struct pipe_transfer
*ptrans
,
621 const struct pipe_box
*box
)
627 lima_transfer_unmap(struct pipe_context
*pctx
,
628 struct pipe_transfer
*ptrans
)
630 struct lima_context
*ctx
= lima_context(pctx
);
631 struct lima_transfer
*trans
= lima_transfer(ptrans
);
632 struct lima_resource
*res
= lima_resource(ptrans
->resource
);
633 struct lima_bo
*bo
= res
->bo
;
634 struct pipe_resource
*pres
;
636 if (trans
->staging
) {
638 if (ptrans
->usage
& PIPE_TRANSFER_WRITE
)
639 panfrost_store_tiled_image(bo
->map
+ res
->levels
[ptrans
->level
].offset
, trans
->staging
,
641 res
->levels
[ptrans
->level
].stride
,
643 util_format_get_blocksize(pres
->format
));
644 free(trans
->staging
);
647 pipe_resource_reference(&ptrans
->resource
, NULL
);
648 slab_free(&ctx
->transfer_pool
, trans
);
652 lima_util_blitter_save_states(struct lima_context
*ctx
)
654 util_blitter_save_blend(ctx
->blitter
, (void *)ctx
->blend
);
655 util_blitter_save_depth_stencil_alpha(ctx
->blitter
, (void *)ctx
->zsa
);
656 util_blitter_save_stencil_ref(ctx
->blitter
, &ctx
->stencil_ref
);
657 util_blitter_save_rasterizer(ctx
->blitter
, (void *)ctx
->rasterizer
);
658 util_blitter_save_fragment_shader(ctx
->blitter
, ctx
->fs
);
659 util_blitter_save_vertex_shader(ctx
->blitter
, ctx
->vs
);
660 util_blitter_save_viewport(ctx
->blitter
,
661 &ctx
->viewport
.transform
);
662 util_blitter_save_scissor(ctx
->blitter
, &ctx
->scissor
);
663 util_blitter_save_vertex_elements(ctx
->blitter
,
664 ctx
->vertex_elements
);
665 util_blitter_save_vertex_buffer_slot(ctx
->blitter
,
666 ctx
->vertex_buffers
.vb
);
668 util_blitter_save_framebuffer(ctx
->blitter
, &ctx
->framebuffer
.base
);
670 util_blitter_save_fragment_sampler_states(ctx
->blitter
,
671 ctx
->tex_stateobj
.num_samplers
,
672 (void**)ctx
->tex_stateobj
.samplers
);
673 util_blitter_save_fragment_sampler_views(ctx
->blitter
,
674 ctx
->tex_stateobj
.num_textures
,
675 ctx
->tex_stateobj
.textures
);
679 lima_blit(struct pipe_context
*pctx
, const struct pipe_blit_info
*blit_info
)
681 struct lima_context
*ctx
= lima_context(pctx
);
682 struct pipe_blit_info info
= *blit_info
;
684 if (util_try_blit_via_copy_region(pctx
, &info
)) {
688 if (info
.mask
& PIPE_MASK_S
) {
689 debug_printf("lima: cannot blit stencil, skipping\n");
690 info
.mask
&= ~PIPE_MASK_S
;
693 if (!util_blitter_is_blit_supported(ctx
->blitter
, &info
)) {
694 debug_printf("lima: blit unsupported %s -> %s\n",
695 util_format_short_name(info
.src
.resource
->format
),
696 util_format_short_name(info
.dst
.resource
->format
));
700 lima_util_blitter_save_states(ctx
);
702 util_blitter_blit(ctx
->blitter
, &info
);
706 lima_flush_resource(struct pipe_context
*pctx
, struct pipe_resource
*resource
)
712 lima_resource_context_init(struct lima_context
*ctx
)
714 ctx
->base
.create_surface
= lima_surface_create
;
715 ctx
->base
.surface_destroy
= lima_surface_destroy
;
717 /* TODO: optimize these functions to read/write data directly
718 * from/to target instead of creating a staging memory for tiled
721 ctx
->base
.buffer_subdata
= u_default_buffer_subdata
;
722 ctx
->base
.texture_subdata
= u_default_texture_subdata
;
723 ctx
->base
.resource_copy_region
= util_resource_copy_region
;
725 ctx
->base
.blit
= lima_blit
;
727 ctx
->base
.transfer_map
= lima_transfer_map
;
728 ctx
->base
.transfer_flush_region
= lima_transfer_flush_region
;
729 ctx
->base
.transfer_unmap
= lima_transfer_unmap
;
731 ctx
->base
.flush_resource
= lima_flush_resource
;