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/format/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/ralloc.h"
35 #include "util/u_drm.h"
36 #include "renderonly/renderonly.h"
38 #include "frontend/drm_driver.h"
40 #include "drm-uapi/drm_fourcc.h"
41 #include "drm-uapi/lima_drm.h"
43 #include "lima_screen.h"
44 #include "lima_context.h"
45 #include "lima_resource.h"
47 #include "lima_util.h"
49 #include "pan_minmax_cache.h"
50 #include "pan_tiling.h"
52 static struct pipe_resource
*
53 lima_resource_create_scanout(struct pipe_screen
*pscreen
,
54 const struct pipe_resource
*templat
,
55 unsigned width
, unsigned height
)
57 struct lima_screen
*screen
= lima_screen(pscreen
);
58 struct renderonly_scanout
*scanout
;
59 struct winsys_handle handle
;
60 struct pipe_resource
*pres
;
62 struct pipe_resource scanout_templat
= *templat
;
63 scanout_templat
.width0
= width
;
64 scanout_templat
.height0
= height
;
65 scanout_templat
.screen
= pscreen
;
67 scanout
= renderonly_scanout_for_resource(&scanout_templat
,
72 assert(handle
.type
== WINSYS_HANDLE_TYPE_FD
);
73 pres
= pscreen
->resource_from_handle(pscreen
, templat
, &handle
,
74 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE
);
78 renderonly_scanout_destroy(scanout
, screen
->ro
);
82 struct lima_resource
*res
= lima_resource(pres
);
83 res
->scanout
= scanout
;
89 setup_miptree(struct lima_resource
*res
,
90 unsigned width0
, unsigned height0
,
91 bool should_align_dimensions
)
93 struct pipe_resource
*pres
= &res
->base
;
95 unsigned width
= width0
;
96 unsigned height
= height0
;
97 unsigned depth
= pres
->depth0
;
100 for (level
= 0; level
<= pres
->last_level
; level
++) {
101 uint32_t actual_level_size
;
103 unsigned aligned_width
;
104 unsigned aligned_height
;
106 if (should_align_dimensions
) {
107 aligned_width
= align(width
, 16);
108 aligned_height
= align(height
, 16);
110 aligned_width
= width
;
111 aligned_height
= height
;
114 stride
= util_format_get_stride(pres
->format
, aligned_width
);
115 actual_level_size
= stride
*
116 util_format_get_nblocksy(pres
->format
, aligned_height
) *
117 pres
->array_size
* depth
;
119 res
->levels
[level
].width
= aligned_width
;
120 res
->levels
[level
].stride
= stride
;
121 res
->levels
[level
].offset
= size
;
122 res
->levels
[level
].layer_stride
= util_format_get_stride(pres
->format
, align(width
, 16)) * align(height
, 16);
124 if (util_format_is_compressed(pres
->format
))
125 res
->levels
[level
].layer_stride
/= 4;
127 /* The start address of each level except the last level
128 * must be 64-aligned in order to be able to pass the
129 * addresses to the hardware. */
130 if (level
!= pres
->last_level
)
131 size
+= align(actual_level_size
, 64);
133 size
+= actual_level_size
; /* Save some memory */
135 width
= u_minify(width
, 1);
136 height
= u_minify(height
, 1);
137 depth
= u_minify(depth
, 1);
143 static struct pipe_resource
*
144 lima_resource_create_bo(struct pipe_screen
*pscreen
,
145 const struct pipe_resource
*templat
,
146 unsigned width
, unsigned height
,
147 bool should_align_dimensions
)
149 struct lima_screen
*screen
= lima_screen(pscreen
);
150 struct lima_resource
*res
;
151 struct pipe_resource
*pres
;
153 res
= CALLOC_STRUCT(lima_resource
);
157 res
->base
= *templat
;
158 res
->base
.screen
= pscreen
;
159 pipe_reference_init(&res
->base
.reference
, 1);
163 uint32_t size
= setup_miptree(res
, width
, height
, should_align_dimensions
);
164 size
= align(size
, LIMA_PAGE_SIZE
);
166 res
->bo
= lima_bo_create(screen
, size
, 0);
175 static struct pipe_resource
*
176 _lima_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
177 const struct pipe_resource
*templat
,
178 const uint64_t *modifiers
,
181 struct lima_screen
*screen
= lima_screen(pscreen
);
182 bool should_tile
= lima_debug
& LIMA_DEBUG_NO_TILING
? false : true;
183 unsigned width
, height
;
184 bool should_align_dimensions
;
185 bool has_user_modifiers
= true;
187 if (count
== 1 && modifiers
[0] == DRM_FORMAT_MOD_INVALID
)
188 has_user_modifiers
= false;
190 /* VBOs/PBOs are untiled (and 1 height). */
191 if (templat
->target
== PIPE_BUFFER
)
194 if (templat
->bind
& (PIPE_BIND_LINEAR
| PIPE_BIND_SCANOUT
))
197 /* If there's no user modifiers and buffer is shared we use linear */
198 if (!has_user_modifiers
&& (templat
->bind
& PIPE_BIND_SHARED
))
201 if (has_user_modifiers
&&
202 !drm_find_modifier(DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED
,
206 if (should_tile
|| (templat
->bind
& PIPE_BIND_RENDER_TARGET
) ||
207 (templat
->bind
& PIPE_BIND_DEPTH_STENCIL
)) {
208 should_align_dimensions
= true;
209 width
= align(templat
->width0
, 16);
210 height
= align(templat
->height0
, 16);
213 should_align_dimensions
= false;
214 width
= templat
->width0
;
215 height
= templat
->height0
;
218 struct pipe_resource
*pres
;
219 if (screen
->ro
&& (templat
->bind
& PIPE_BIND_SCANOUT
))
220 pres
= lima_resource_create_scanout(pscreen
, templat
, width
, height
);
222 pres
= lima_resource_create_bo(pscreen
, templat
, width
, height
,
223 should_align_dimensions
);
226 struct lima_resource
*res
= lima_resource(pres
);
227 res
->tiled
= should_tile
;
229 if (templat
->bind
& PIPE_BIND_INDEX_BUFFER
)
230 res
->index_cache
= CALLOC_STRUCT(panfrost_minmax_cache
);
232 debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d "
233 "bind=%x usage=%d tile=%d last_level=%d\n", __func__
,
234 pres
, pres
->width0
, pres
->height0
, pres
->depth0
,
235 pres
->target
, pres
->bind
, pres
->usage
, should_tile
, templat
->last_level
);
240 static struct pipe_resource
*
241 lima_resource_create(struct pipe_screen
*pscreen
,
242 const struct pipe_resource
*templat
)
244 const uint64_t mod
= DRM_FORMAT_MOD_INVALID
;
246 return _lima_resource_create_with_modifiers(pscreen
, templat
, &mod
, 1);
249 static struct pipe_resource
*
250 lima_resource_create_with_modifiers(struct pipe_screen
*pscreen
,
251 const struct pipe_resource
*templat
,
252 const uint64_t *modifiers
,
255 struct pipe_resource tmpl
= *templat
;
257 /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers
258 * don't have usage parameter, but buffer created by these functions
259 * may be used for scanout. So we assume buffer created by this
260 * function always enable scanout if linear modifier is permitted.
262 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR
, modifiers
, count
))
263 tmpl
.bind
|= PIPE_BIND_SCANOUT
;
265 return _lima_resource_create_with_modifiers(pscreen
, &tmpl
, modifiers
, count
);
269 lima_resource_destroy(struct pipe_screen
*pscreen
, struct pipe_resource
*pres
)
271 struct lima_screen
*screen
= lima_screen(pscreen
);
272 struct lima_resource
*res
= lima_resource(pres
);
275 lima_bo_unreference(res
->bo
);
278 renderonly_scanout_destroy(res
->scanout
, screen
->ro
);
280 if (res
->damage
.region
)
281 FREE(res
->damage
.region
);
283 if (res
->index_cache
)
284 FREE(res
->index_cache
);
289 static struct pipe_resource
*
290 lima_resource_from_handle(struct pipe_screen
*pscreen
,
291 const struct pipe_resource
*templat
,
292 struct winsys_handle
*handle
, unsigned usage
)
294 if (templat
->bind
& (PIPE_BIND_SAMPLER_VIEW
|
295 PIPE_BIND_RENDER_TARGET
|
296 PIPE_BIND_DEPTH_STENCIL
)) {
297 /* sampler hardware need offset alignment 64, while render hardware
298 * need offset alignment 8, but due to render target may be reloaded
299 * which uses the sampler, set alignment requrement to 64 for all
301 if (handle
->offset
& 0x3f) {
302 debug_error("import buffer offset not properly aligned\n");
307 struct lima_resource
*res
= CALLOC_STRUCT(lima_resource
);
311 struct pipe_resource
*pres
= &res
->base
;
313 pres
->screen
= pscreen
;
314 pipe_reference_init(&pres
->reference
, 1);
315 res
->levels
[0].offset
= handle
->offset
;
316 res
->levels
[0].stride
= handle
->stride
;
318 struct lima_screen
*screen
= lima_screen(pscreen
);
319 res
->bo
= lima_bo_import(screen
, handle
);
325 switch (handle
->modifier
) {
326 case DRM_FORMAT_MOD_LINEAR
:
329 case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED
:
332 case DRM_FORMAT_MOD_INVALID
:
333 /* Modifier wasn't specified and it's shared buffer. We create these
334 * as linear, so disable tiling.
339 fprintf(stderr
, "Attempted to import unsupported modifier 0x%llx\n",
340 (long long)handle
->modifier
);
344 /* check alignment for the buffer */
346 (pres
->bind
& (PIPE_BIND_RENDER_TARGET
| PIPE_BIND_DEPTH_STENCIL
))) {
347 unsigned width
, height
, stride
, size
;
349 width
= align(pres
->width0
, 16);
350 height
= align(pres
->height0
, 16);
351 stride
= util_format_get_stride(pres
->format
, width
);
352 size
= util_format_get_2d_size(pres
->format
, stride
, height
);
354 if (res
->levels
[0].stride
!= stride
|| res
->bo
->size
< size
) {
355 debug_error("import buffer not properly aligned\n");
359 res
->levels
[0].width
= width
;
362 res
->levels
[0].width
= pres
->width0
;
367 lima_resource_destroy(pscreen
, pres
);
372 lima_resource_get_handle(struct pipe_screen
*pscreen
,
373 struct pipe_context
*pctx
,
374 struct pipe_resource
*pres
,
375 struct winsys_handle
*handle
, unsigned usage
)
377 struct lima_screen
*screen
= lima_screen(pscreen
);
378 struct lima_resource
*res
= lima_resource(pres
);
381 handle
->modifier
= DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED
;
383 handle
->modifier
= DRM_FORMAT_MOD_LINEAR
;
385 if (handle
->type
== WINSYS_HANDLE_TYPE_KMS
&& screen
->ro
&&
386 renderonly_get_handle(res
->scanout
, handle
))
389 if (!lima_bo_export(res
->bo
, handle
))
392 handle
->offset
= res
->levels
[0].offset
;
393 handle
->stride
= res
->levels
[0].stride
;
398 get_scissor_from_box(struct pipe_scissor_state
*s
,
399 const struct pipe_box
*b
, int h
)
401 int y
= h
- (b
->y
+ b
->height
);
402 /* region in tile unit */
405 s
->maxx
= (b
->x
+ b
->width
+ 0xf) >> 4;
406 s
->maxy
= (y
+ b
->height
+ 0xf) >> 4;
410 get_damage_bound_box(struct pipe_resource
*pres
,
411 const struct pipe_box
*rects
,
413 struct pipe_scissor_state
*bound
)
415 struct pipe_box b
= rects
[0];
417 for (int i
= 1; i
< nrects
; i
++)
418 u_box_union_2d(&b
, &b
, rects
+ i
);
420 int ret
= u_box_clip_2d(&b
, &b
, pres
->width0
, pres
->height0
);
422 memset(bound
, 0, sizeof(*bound
));
424 get_scissor_from_box(bound
, &b
, pres
->height0
);
428 lima_resource_set_damage_region(struct pipe_screen
*pscreen
,
429 struct pipe_resource
*pres
,
431 const struct pipe_box
*rects
)
433 struct lima_resource
*res
= lima_resource(pres
);
434 struct lima_damage_region
*damage
= &res
->damage
;
437 if (damage
->region
) {
438 FREE(damage
->region
);
439 damage
->region
= NULL
;
440 damage
->num_region
= 0;
448 * TODO: currently only check if there is any single damage
449 * region that can cover the full render target; there may
450 * be some accurate way, but a single window size damage
451 * region is most of the case from weston
453 for (i
= 0; i
< nrects
; i
++) {
454 if (rects
[i
].x
<= 0 && rects
[i
].y
<= 0 &&
455 rects
[i
].x
+ rects
[i
].width
>= pres
->width0
&&
456 rects
[i
].y
+ rects
[i
].height
>= pres
->height0
)
460 struct pipe_scissor_state
*bound
= &damage
->bound
;
461 get_damage_bound_box(pres
, rects
, nrects
, bound
);
463 damage
->region
= CALLOC(nrects
, sizeof(*damage
->region
));
467 for (i
= 0; i
< nrects
; i
++)
468 get_scissor_from_box(damage
->region
+ i
, rects
+ i
,
471 /* is region aligned to tiles? */
472 damage
->aligned
= true;
473 for (i
= 0; i
< nrects
; i
++) {
474 if (rects
[i
].x
& 0xf || rects
[i
].y
& 0xf ||
475 rects
[i
].width
& 0xf || rects
[i
].height
& 0xf) {
476 damage
->aligned
= false;
481 damage
->num_region
= nrects
;
485 lima_resource_screen_init(struct lima_screen
*screen
)
487 screen
->base
.resource_create
= lima_resource_create
;
488 screen
->base
.resource_create_with_modifiers
= lima_resource_create_with_modifiers
;
489 screen
->base
.resource_from_handle
= lima_resource_from_handle
;
490 screen
->base
.resource_destroy
= lima_resource_destroy
;
491 screen
->base
.resource_get_handle
= lima_resource_get_handle
;
492 screen
->base
.set_damage_region
= lima_resource_set_damage_region
;
495 static struct pipe_surface
*
496 lima_surface_create(struct pipe_context
*pctx
,
497 struct pipe_resource
*pres
,
498 const struct pipe_surface
*surf_tmpl
)
500 struct lima_surface
*surf
= CALLOC_STRUCT(lima_surface
);
505 assert(surf_tmpl
->u
.tex
.first_layer
== surf_tmpl
->u
.tex
.last_layer
);
507 struct pipe_surface
*psurf
= &surf
->base
;
508 unsigned level
= surf_tmpl
->u
.tex
.level
;
510 pipe_reference_init(&psurf
->reference
, 1);
511 pipe_resource_reference(&psurf
->texture
, pres
);
513 psurf
->context
= pctx
;
514 psurf
->format
= surf_tmpl
->format
;
515 psurf
->width
= u_minify(pres
->width0
, level
);
516 psurf
->height
= u_minify(pres
->height0
, level
);
517 psurf
->u
.tex
.level
= level
;
518 psurf
->u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
519 psurf
->u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
521 surf
->tiled_w
= align(psurf
->width
, 16) >> 4;
522 surf
->tiled_h
= align(psurf
->height
, 16) >> 4;
525 if (util_format_has_stencil(util_format_description(psurf
->format
)))
526 surf
->reload
|= PIPE_CLEAR_STENCIL
;
527 if (util_format_has_depth(util_format_description(psurf
->format
)))
528 surf
->reload
|= PIPE_CLEAR_DEPTH
;
529 if (!util_format_is_depth_or_stencil(psurf
->format
))
530 surf
->reload
|= PIPE_CLEAR_COLOR0
;
536 lima_surface_destroy(struct pipe_context
*pctx
, struct pipe_surface
*psurf
)
538 struct lima_surface
*surf
= lima_surface(psurf
);
540 pipe_resource_reference(&psurf
->texture
, NULL
);
545 lima_transfer_map(struct pipe_context
*pctx
,
546 struct pipe_resource
*pres
,
549 const struct pipe_box
*box
,
550 struct pipe_transfer
**pptrans
)
552 struct lima_context
*ctx
= lima_context(pctx
);
553 struct lima_resource
*res
= lima_resource(pres
);
554 struct lima_bo
*bo
= res
->bo
;
555 struct lima_transfer
*trans
;
556 struct pipe_transfer
*ptrans
;
558 /* No direct mappings of tiled, since we need to manually
561 if (res
->tiled
&& (usage
& PIPE_TRANSFER_MAP_DIRECTLY
))
564 /* use once buffers are made sure to not read/write overlapped
565 * range, so no need to sync */
566 if (pres
->usage
!= PIPE_USAGE_STREAM
) {
567 if (usage
& PIPE_TRANSFER_READ_WRITE
) {
568 lima_flush_job_accessing_bo(ctx
, bo
, usage
& PIPE_TRANSFER_WRITE
);
570 unsigned op
= usage
& PIPE_TRANSFER_WRITE
?
571 LIMA_GEM_WAIT_WRITE
: LIMA_GEM_WAIT_READ
;
572 lima_bo_wait(bo
, op
, PIPE_TIMEOUT_INFINITE
);
576 if (!lima_bo_map(bo
))
579 trans
= slab_alloc(&ctx
->transfer_pool
);
583 memset(trans
, 0, sizeof(*trans
));
584 ptrans
= &trans
->base
;
586 pipe_resource_reference(&ptrans
->resource
, pres
);
587 ptrans
->level
= level
;
588 ptrans
->usage
= usage
;
594 ptrans
->stride
= util_format_get_stride(pres
->format
, ptrans
->box
.width
);
595 ptrans
->layer_stride
= ptrans
->stride
* ptrans
->box
.height
;
597 trans
->staging
= malloc(ptrans
->stride
* ptrans
->box
.height
* ptrans
->box
.depth
);
599 if (usage
& PIPE_TRANSFER_READ
) {
601 for (i
= 0; i
< ptrans
->box
.depth
; i
++)
602 panfrost_load_tiled_image(
603 trans
->staging
+ i
* ptrans
->stride
* ptrans
->box
.height
,
604 bo
->map
+ res
->levels
[level
].offset
+ (i
+ box
->z
) * res
->levels
[level
].layer_stride
,
605 ptrans
->box
.x
, ptrans
->box
.y
,
606 ptrans
->box
.width
, ptrans
->box
.height
,
608 res
->levels
[level
].stride
,
612 return trans
->staging
;
614 unsigned dpw
= PIPE_TRANSFER_MAP_DIRECTLY
| PIPE_TRANSFER_WRITE
|
615 PIPE_TRANSFER_PERSISTENT
;
616 if ((usage
& dpw
) == dpw
&& res
->index_cache
)
619 ptrans
->stride
= res
->levels
[level
].stride
;
620 ptrans
->layer_stride
= res
->levels
[level
].layer_stride
;
622 if ((usage
& PIPE_TRANSFER_WRITE
) && (usage
& PIPE_TRANSFER_MAP_DIRECTLY
))
623 panfrost_minmax_cache_invalidate(res
->index_cache
, ptrans
);
625 return bo
->map
+ res
->levels
[level
].offset
+
626 box
->z
* res
->levels
[level
].layer_stride
+
627 box
->y
/ util_format_get_blockheight(pres
->format
) * ptrans
->stride
+
628 box
->x
/ util_format_get_blockwidth(pres
->format
) *
629 util_format_get_blocksize(pres
->format
);
634 lima_transfer_flush_region(struct pipe_context
*pctx
,
635 struct pipe_transfer
*ptrans
,
636 const struct pipe_box
*box
)
642 lima_transfer_unmap_inner(struct lima_context
*ctx
,
643 struct pipe_transfer
*ptrans
)
646 struct lima_resource
*res
= lima_resource(ptrans
->resource
);
647 struct lima_transfer
*trans
= lima_transfer(ptrans
);
648 struct lima_bo
*bo
= res
->bo
;
649 struct pipe_resource
*pres
;
651 if (trans
->staging
) {
653 if (trans
->base
.usage
& PIPE_TRANSFER_WRITE
) {
655 for (i
= 0; i
< trans
->base
.box
.depth
; i
++)
656 panfrost_store_tiled_image(
657 bo
->map
+ res
->levels
[trans
->base
.level
].offset
+ (i
+ trans
->base
.box
.z
) * res
->levels
[trans
->base
.level
].layer_stride
,
658 trans
->staging
+ i
* ptrans
->stride
* ptrans
->box
.height
,
659 ptrans
->box
.x
, ptrans
->box
.y
,
660 ptrans
->box
.width
, ptrans
->box
.height
,
661 res
->levels
[ptrans
->level
].stride
,
669 lima_transfer_unmap(struct pipe_context
*pctx
,
670 struct pipe_transfer
*ptrans
)
672 struct lima_context
*ctx
= lima_context(pctx
);
673 struct lima_transfer
*trans
= lima_transfer(ptrans
);
674 struct lima_resource
*res
= lima_resource(ptrans
->resource
);
676 lima_transfer_unmap_inner(ctx
, ptrans
);
678 free(trans
->staging
);
679 panfrost_minmax_cache_invalidate(res
->index_cache
, ptrans
);
681 pipe_resource_reference(&ptrans
->resource
, NULL
);
682 slab_free(&ctx
->transfer_pool
, trans
);
686 lima_util_blitter_save_states(struct lima_context
*ctx
)
688 util_blitter_save_blend(ctx
->blitter
, (void *)ctx
->blend
);
689 util_blitter_save_depth_stencil_alpha(ctx
->blitter
, (void *)ctx
->zsa
);
690 util_blitter_save_stencil_ref(ctx
->blitter
, &ctx
->stencil_ref
);
691 util_blitter_save_rasterizer(ctx
->blitter
, (void *)ctx
->rasterizer
);
692 util_blitter_save_fragment_shader(ctx
->blitter
, ctx
->fs
);
693 util_blitter_save_vertex_shader(ctx
->blitter
, ctx
->vs
);
694 util_blitter_save_viewport(ctx
->blitter
,
695 &ctx
->viewport
.transform
);
696 util_blitter_save_scissor(ctx
->blitter
, &ctx
->scissor
);
697 util_blitter_save_vertex_elements(ctx
->blitter
,
698 ctx
->vertex_elements
);
699 util_blitter_save_vertex_buffer_slot(ctx
->blitter
,
700 ctx
->vertex_buffers
.vb
);
702 util_blitter_save_framebuffer(ctx
->blitter
, &ctx
->framebuffer
.base
);
704 util_blitter_save_fragment_sampler_states(ctx
->blitter
,
705 ctx
->tex_stateobj
.num_samplers
,
706 (void**)ctx
->tex_stateobj
.samplers
);
707 util_blitter_save_fragment_sampler_views(ctx
->blitter
,
708 ctx
->tex_stateobj
.num_textures
,
709 ctx
->tex_stateobj
.textures
);
713 lima_blit(struct pipe_context
*pctx
, const struct pipe_blit_info
*blit_info
)
715 struct lima_context
*ctx
= lima_context(pctx
);
716 struct pipe_blit_info info
= *blit_info
;
718 if (util_try_blit_via_copy_region(pctx
, &info
)) {
722 if (info
.mask
& PIPE_MASK_S
) {
723 debug_printf("lima: cannot blit stencil, skipping\n");
724 info
.mask
&= ~PIPE_MASK_S
;
727 if (!util_blitter_is_blit_supported(ctx
->blitter
, &info
)) {
728 debug_printf("lima: blit unsupported %s -> %s\n",
729 util_format_short_name(info
.src
.resource
->format
),
730 util_format_short_name(info
.dst
.resource
->format
));
734 lima_util_blitter_save_states(ctx
);
736 util_blitter_blit(ctx
->blitter
, &info
);
740 lima_flush_resource(struct pipe_context
*pctx
, struct pipe_resource
*resource
)
746 lima_texture_subdata(struct pipe_context
*pctx
,
747 struct pipe_resource
*prsc
,
750 const struct pipe_box
*box
,
753 unsigned layer_stride
)
755 struct lima_context
*ctx
= lima_context(pctx
);
756 struct lima_resource
*res
= lima_resource(prsc
);
759 u_default_texture_subdata(pctx
, prsc
, level
, usage
, box
,
760 data
, stride
, layer_stride
);
764 assert(!(usage
& PIPE_TRANSFER_READ
));
766 struct lima_transfer t
= {
769 .usage
= PIPE_TRANSFER_WRITE
,
773 .layer_stride
= layer_stride
,
775 .staging
= (void *)data
,
778 lima_flush_job_accessing_bo(ctx
, res
->bo
, true);
779 lima_bo_wait(res
->bo
, LIMA_GEM_WAIT_WRITE
, PIPE_TIMEOUT_INFINITE
);
780 if (!lima_bo_map(res
->bo
))
783 lima_transfer_unmap_inner(ctx
, &t
.base
);
787 lima_resource_context_init(struct lima_context
*ctx
)
789 ctx
->base
.create_surface
= lima_surface_create
;
790 ctx
->base
.surface_destroy
= lima_surface_destroy
;
792 ctx
->base
.buffer_subdata
= u_default_buffer_subdata
;
793 ctx
->base
.texture_subdata
= lima_texture_subdata
;
794 /* TODO: optimize resource_copy_region to do copy directly
795 * between 2 tiled or tiled and linear resources instead of
796 * using staging buffer.
798 ctx
->base
.resource_copy_region
= util_resource_copy_region
;
800 ctx
->base
.blit
= lima_blit
;
802 ctx
->base
.transfer_map
= lima_transfer_map
;
803 ctx
->base
.transfer_flush_region
= lima_transfer_flush_region
;
804 ctx
->base
.transfer_unmap
= lima_transfer_unmap
;
806 ctx
->base
.flush_resource
= lima_flush_resource
;