lima: add RGBA5551 and RGBA4444 formats
[mesa.git] / src / gallium / drivers / lima / lima_resource.c
1 /*
2 * Copyright (c) 2017-2019 Lima Project
3 *
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:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
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.
22 *
23 */
24
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"
37
38 #include "state_tracker/drm_driver.h"
39
40 #include "drm-uapi/drm_fourcc.h"
41 #include "drm-uapi/lima_drm.h"
42
43 #include "lima_screen.h"
44 #include "lima_context.h"
45 #include "lima_resource.h"
46 #include "lima_bo.h"
47 #include "lima_util.h"
48 #include "pan_tiling.h"
49
50 static struct pipe_resource *
51 lima_resource_create_scanout(struct pipe_screen *pscreen,
52 const struct pipe_resource *templat,
53 unsigned width, unsigned height)
54 {
55 struct lima_screen *screen = lima_screen(pscreen);
56 struct renderonly_scanout *scanout;
57 struct winsys_handle handle;
58 struct pipe_resource *pres;
59
60 struct pipe_resource scanout_templat = *templat;
61 scanout_templat.width0 = width;
62 scanout_templat.height0 = height;
63 scanout_templat.screen = pscreen;
64
65 scanout = renderonly_scanout_for_resource(&scanout_templat,
66 screen->ro, &handle);
67 if (!scanout)
68 return NULL;
69
70 assert(handle.type == WINSYS_HANDLE_TYPE_FD);
71 pres = pscreen->resource_from_handle(pscreen, templat, &handle,
72 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
73
74 close(handle.handle);
75 if (!pres) {
76 renderonly_scanout_destroy(scanout, screen->ro);
77 return NULL;
78 }
79
80 struct lima_resource *res = lima_resource(pres);
81 res->scanout = scanout;
82
83 return pres;
84 }
85
86 static uint32_t
87 setup_miptree(struct lima_resource *res,
88 unsigned width0, unsigned height0,
89 bool should_align_dimensions)
90 {
91 struct pipe_resource *pres = &res->base;
92 unsigned level;
93 unsigned width = width0;
94 unsigned height = height0;
95 unsigned depth = pres->depth0;
96 uint32_t size = 0;
97
98 for (level = 0; level <= pres->last_level; level++) {
99 uint32_t actual_level_size;
100 uint32_t stride;
101 unsigned aligned_width;
102 unsigned aligned_height;
103
104 if (should_align_dimensions) {
105 aligned_width = align(width, 16);
106 aligned_height = align(height, 16);
107 } else {
108 aligned_width = width;
109 aligned_height = height;
110 }
111
112 stride = util_format_get_stride(pres->format, aligned_width);
113 actual_level_size = stride *
114 util_format_get_nblocksy(pres->format, aligned_height) *
115 pres->array_size * depth;
116
117 res->levels[level].width = aligned_width;
118 res->levels[level].stride = stride;
119 res->levels[level].offset = size;
120 res->levels[level].layer_stride = util_format_get_stride(pres->format, align(width, 16)) * align(height, 16);
121
122 if (util_format_is_compressed(pres->format))
123 res->levels[level].layer_stride /= 4;
124
125 /* The start address of each level except the last level
126 * must be 64-aligned in order to be able to pass the
127 * addresses to the hardware. */
128 if (level != pres->last_level)
129 size += align(actual_level_size, 64);
130 else
131 size += actual_level_size; /* Save some memory */
132
133 width = u_minify(width, 1);
134 height = u_minify(height, 1);
135 depth = u_minify(depth, 1);
136 }
137
138 return size;
139 }
140
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)
146 {
147 struct lima_screen *screen = lima_screen(pscreen);
148 struct lima_resource *res;
149 struct pipe_resource *pres;
150
151 res = CALLOC_STRUCT(lima_resource);
152 if (!res)
153 return NULL;
154
155 res->base = *templat;
156 res->base.screen = pscreen;
157 pipe_reference_init(&res->base.reference, 1);
158
159 pres = &res->base;
160
161 uint32_t size = setup_miptree(res, width, height, should_align_dimensions);
162 size = align(size, LIMA_PAGE_SIZE);
163
164 res->bo = lima_bo_create(screen, size, 0);
165 if (!res->bo) {
166 FREE(res);
167 return NULL;
168 }
169
170 return pres;
171 }
172
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,
177 int count)
178 {
179 struct lima_screen *screen = lima_screen(pscreen);
180 bool should_tile = lima_debug & LIMA_DEBUG_NO_TILING ? false : true;
181 unsigned width, height;
182 bool should_align_dimensions;
183 bool has_user_modifiers = true;
184
185 if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)
186 has_user_modifiers = false;
187
188 /* VBOs/PBOs are untiled (and 1 height). */
189 if (templat->target == PIPE_BUFFER)
190 should_tile = false;
191
192 if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT))
193 should_tile = false;
194
195 /* If there's no user modifiers and buffer is shared we use linear */
196 if (!has_user_modifiers && (templat->bind & PIPE_BIND_SHARED))
197 should_tile = false;
198
199 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
200 should_tile = false;
201
202 if (has_user_modifiers &&
203 !drm_find_modifier(DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
204 modifiers, count))
205 should_tile = false;
206
207 if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) ||
208 (templat->bind & PIPE_BIND_DEPTH_STENCIL)) {
209 should_align_dimensions = true;
210 width = align(templat->width0, 16);
211 height = align(templat->height0, 16);
212 }
213 else {
214 should_align_dimensions = false;
215 width = templat->width0;
216 height = templat->height0;
217 }
218
219 struct pipe_resource *pres;
220 if (screen->ro && (templat->bind & PIPE_BIND_SCANOUT))
221 pres = lima_resource_create_scanout(pscreen, templat, width, height);
222 else
223 pres = lima_resource_create_bo(pscreen, templat, width, height,
224 should_align_dimensions);
225
226 if (pres) {
227 struct lima_resource *res = lima_resource(pres);
228 res->tiled = should_tile;
229
230 debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d "
231 "bind=%x usage=%d tile=%d last_level=%d\n", __func__,
232 pres, pres->width0, pres->height0, pres->depth0,
233 pres->target, pres->bind, pres->usage, should_tile, templat->last_level);
234 }
235 return pres;
236 }
237
238 static struct pipe_resource *
239 lima_resource_create(struct pipe_screen *pscreen,
240 const struct pipe_resource *templat)
241 {
242 const uint64_t mod = DRM_FORMAT_MOD_INVALID;
243
244 return _lima_resource_create_with_modifiers(pscreen, templat, &mod, 1);
245 }
246
247 static struct pipe_resource *
248 lima_resource_create_with_modifiers(struct pipe_screen *pscreen,
249 const struct pipe_resource *templat,
250 const uint64_t *modifiers,
251 int count)
252 {
253 struct pipe_resource tmpl = *templat;
254
255 /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers
256 * don't have usage parameter, but buffer created by these functions
257 * may be used for scanout. So we assume buffer created by this
258 * function always enable scanout if linear modifier is permitted.
259 */
260 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
261 tmpl.bind |= PIPE_BIND_SCANOUT;
262
263 return _lima_resource_create_with_modifiers(pscreen, &tmpl, modifiers, count);
264 }
265
266 static void
267 lima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres)
268 {
269 struct lima_screen *screen = lima_screen(pscreen);
270 struct lima_resource *res = lima_resource(pres);
271
272 if (res->bo)
273 lima_bo_unreference(res->bo);
274
275 if (res->scanout)
276 renderonly_scanout_destroy(res->scanout, screen->ro);
277
278 if (res->damage.region)
279 FREE(res->damage.region);
280
281 FREE(res);
282 }
283
284 static struct pipe_resource *
285 lima_resource_from_handle(struct pipe_screen *pscreen,
286 const struct pipe_resource *templat,
287 struct winsys_handle *handle, unsigned usage)
288 {
289 struct lima_resource *res;
290 struct lima_screen *screen = lima_screen(pscreen);
291
292 res = CALLOC_STRUCT(lima_resource);
293 if (!res)
294 return NULL;
295
296 struct pipe_resource *pres = &res->base;
297 *pres = *templat;
298 pres->screen = pscreen;
299 pipe_reference_init(&pres->reference, 1);
300 res->levels[0].offset = 0;
301 res->levels[0].stride = handle->stride;
302
303 res->bo = lima_bo_import(screen, handle);
304 if (!res->bo) {
305 FREE(res);
306 return NULL;
307 }
308
309 /* check alignment for the buffer */
310 if (pres->bind & PIPE_BIND_RENDER_TARGET) {
311 unsigned width, height, stride, size;
312
313 width = align(pres->width0, 16);
314 height = align(pres->height0, 16);
315 stride = util_format_get_stride(pres->format, width);
316 size = util_format_get_2d_size(pres->format, stride, height);
317
318 if (res->levels[0].stride != stride || res->bo->size < size) {
319 debug_error("import buffer not properly aligned\n");
320 goto err_out;
321 }
322
323 res->levels[0].width = width;
324 }
325 else
326 res->levels[0].width = pres->width0;
327
328 switch (handle->modifier) {
329 case DRM_FORMAT_MOD_LINEAR:
330 res->tiled = false;
331 break;
332 case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED:
333 res->tiled = true;
334 break;
335 case DRM_FORMAT_MOD_INVALID:
336 /* Modifier wasn't specified and it's shared buffer. We create these
337 * as linear, so disable tiling.
338 */
339 res->tiled = false;
340 break;
341 default:
342 fprintf(stderr, "Attempted to import unsupported modifier 0x%llx\n",
343 (long long)handle->modifier);
344 goto err_out;
345 }
346
347 return pres;
348
349 err_out:
350 lima_resource_destroy(pscreen, pres);
351 return NULL;
352 }
353
354 static bool
355 lima_resource_get_handle(struct pipe_screen *pscreen,
356 struct pipe_context *pctx,
357 struct pipe_resource *pres,
358 struct winsys_handle *handle, unsigned usage)
359 {
360 struct lima_screen *screen = lima_screen(pscreen);
361 struct lima_resource *res = lima_resource(pres);
362
363 if (res->tiled)
364 handle->modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
365 else
366 handle->modifier = DRM_FORMAT_MOD_LINEAR;
367
368 if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
369 renderonly_get_handle(res->scanout, handle))
370 return true;
371
372 if (!lima_bo_export(res->bo, handle))
373 return false;
374
375 handle->stride = res->levels[0].stride;
376 return true;
377 }
378
379 static void
380 get_scissor_from_box(struct pipe_scissor_state *s,
381 const struct pipe_box *b, int h)
382 {
383 int y = h - (b->y + b->height);
384 /* region in tile unit */
385 s->minx = b->x >> 4;
386 s->miny = y >> 4;
387 s->maxx = (b->x + b->width + 0xf) >> 4;
388 s->maxy = (y + b->height + 0xf) >> 4;
389 }
390
391 static void
392 get_damage_bound_box(struct pipe_resource *pres,
393 const struct pipe_box *rects,
394 unsigned int nrects,
395 struct pipe_scissor_state *bound)
396 {
397 struct pipe_box b = rects[0];
398
399 for (int i = 1; i < nrects; i++)
400 u_box_union_2d(&b, &b, rects + i);
401
402 int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0);
403 if (ret < 0)
404 memset(bound, 0, sizeof(*bound));
405 else
406 get_scissor_from_box(bound, &b, pres->height0);
407 }
408
409 static void
410 lima_resource_set_damage_region(struct pipe_screen *pscreen,
411 struct pipe_resource *pres,
412 unsigned int nrects,
413 const struct pipe_box *rects)
414 {
415 struct lima_resource *res = lima_resource(pres);
416 struct lima_damage_region *damage = &res->damage;
417 int i;
418
419 if (damage->region) {
420 FREE(damage->region);
421 damage->region = NULL;
422 damage->num_region = 0;
423 }
424
425 if (!nrects)
426 return;
427
428 /* check full damage
429 *
430 * TODO: currently only check if there is any single damage
431 * region that can cover the full render target; there may
432 * be some accurate way, but a single window size damage
433 * region is most of the case from weston
434 */
435 for (i = 0; i < nrects; i++) {
436 if (rects[i].x <= 0 && rects[i].y <= 0 &&
437 rects[i].x + rects[i].width >= pres->width0 &&
438 rects[i].y + rects[i].height >= pres->height0)
439 return;
440 }
441
442 struct pipe_scissor_state *bound = &damage->bound;
443 get_damage_bound_box(pres, rects, nrects, bound);
444
445 damage->region = CALLOC(nrects, sizeof(*damage->region));
446 if (!damage->region)
447 return;
448
449 for (i = 0; i < nrects; i++)
450 get_scissor_from_box(damage->region + i, rects + i,
451 pres->height0);
452
453 /* is region aligned to tiles? */
454 damage->aligned = true;
455 for (i = 0; i < nrects; i++) {
456 if (rects[i].x & 0xf || rects[i].y & 0xf ||
457 rects[i].width & 0xf || rects[i].height & 0xf) {
458 damage->aligned = false;
459 break;
460 }
461 }
462
463 damage->num_region = nrects;
464 }
465
466 void
467 lima_resource_screen_init(struct lima_screen *screen)
468 {
469 screen->base.resource_create = lima_resource_create;
470 screen->base.resource_create_with_modifiers = lima_resource_create_with_modifiers;
471 screen->base.resource_from_handle = lima_resource_from_handle;
472 screen->base.resource_destroy = lima_resource_destroy;
473 screen->base.resource_get_handle = lima_resource_get_handle;
474 screen->base.set_damage_region = lima_resource_set_damage_region;
475 }
476
477 static struct pipe_surface *
478 lima_surface_create(struct pipe_context *pctx,
479 struct pipe_resource *pres,
480 const struct pipe_surface *surf_tmpl)
481 {
482 struct lima_surface *surf = CALLOC_STRUCT(lima_surface);
483
484 if (!surf)
485 return NULL;
486
487 assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
488
489 struct pipe_surface *psurf = &surf->base;
490 unsigned level = surf_tmpl->u.tex.level;
491
492 pipe_reference_init(&psurf->reference, 1);
493 pipe_resource_reference(&psurf->texture, pres);
494
495 psurf->context = pctx;
496 psurf->format = surf_tmpl->format;
497 psurf->width = u_minify(pres->width0, level);
498 psurf->height = u_minify(pres->height0, level);
499 psurf->u.tex.level = level;
500 psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
501 psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
502
503 surf->tiled_w = align(psurf->width, 16) >> 4;
504 surf->tiled_h = align(psurf->height, 16) >> 4;
505
506 surf->reload = true;
507
508 return &surf->base;
509 }
510
511 static void
512 lima_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
513 {
514 struct lima_surface *surf = lima_surface(psurf);
515
516 pipe_resource_reference(&psurf->texture, NULL);
517 FREE(surf);
518 }
519
520 static void *
521 lima_transfer_map(struct pipe_context *pctx,
522 struct pipe_resource *pres,
523 unsigned level,
524 unsigned usage,
525 const struct pipe_box *box,
526 struct pipe_transfer **pptrans)
527 {
528 struct lima_context *ctx = lima_context(pctx);
529 struct lima_resource *res = lima_resource(pres);
530 struct lima_bo *bo = res->bo;
531 struct lima_transfer *trans;
532 struct pipe_transfer *ptrans;
533
534 /* No direct mappings of tiled, since we need to manually
535 * tile/untile.
536 */
537 if (res->tiled && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
538 return NULL;
539
540 /* use once buffers are made sure to not read/write overlapped
541 * range, so no need to sync */
542 if (pres->usage != PIPE_USAGE_STREAM) {
543 if (usage & PIPE_TRANSFER_READ_WRITE) {
544 lima_flush_job_accessing_bo(ctx, bo, usage & PIPE_TRANSFER_WRITE);
545
546 unsigned op = usage & PIPE_TRANSFER_WRITE ?
547 LIMA_GEM_WAIT_WRITE : LIMA_GEM_WAIT_READ;
548 lima_bo_wait(bo, op, PIPE_TIMEOUT_INFINITE);
549 }
550 }
551
552 if (!lima_bo_map(bo))
553 return NULL;
554
555 trans = slab_alloc(&ctx->transfer_pool);
556 if (!trans)
557 return NULL;
558
559 memset(trans, 0, sizeof(*trans));
560 ptrans = &trans->base;
561
562 pipe_resource_reference(&ptrans->resource, pres);
563 ptrans->level = level;
564 ptrans->usage = usage;
565 ptrans->box = *box;
566
567 *pptrans = ptrans;
568
569 if (res->tiled) {
570 ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width);
571 ptrans->layer_stride = ptrans->stride * ptrans->box.height;
572
573 trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth);
574
575 if (usage & PIPE_TRANSFER_READ) {
576 unsigned i;
577 for (i = 0; i < ptrans->box.depth; i++)
578 panfrost_load_tiled_image(
579 trans->staging + i * ptrans->stride * ptrans->box.height,
580 bo->map + res->levels[level].offset + (i + box->z) * res->levels[level].layer_stride,
581 ptrans->box.x, ptrans->box.y,
582 ptrans->box.width, ptrans->box.height,
583 ptrans->stride,
584 res->levels[level].stride,
585 pres->format);
586 }
587
588 return trans->staging;
589 } else {
590 ptrans->stride = res->levels[level].stride;
591 ptrans->layer_stride = res->levels[level].layer_stride;
592
593 return bo->map + res->levels[level].offset +
594 box->z * res->levels[level].layer_stride +
595 box->y / util_format_get_blockheight(pres->format) * ptrans->stride +
596 box->x / util_format_get_blockwidth(pres->format) *
597 util_format_get_blocksize(pres->format);
598 }
599 }
600
601 static void
602 lima_transfer_flush_region(struct pipe_context *pctx,
603 struct pipe_transfer *ptrans,
604 const struct pipe_box *box)
605 {
606
607 }
608
609 static void
610 lima_transfer_unmap(struct pipe_context *pctx,
611 struct pipe_transfer *ptrans)
612 {
613 struct lima_context *ctx = lima_context(pctx);
614 struct lima_transfer *trans = lima_transfer(ptrans);
615 struct lima_resource *res = lima_resource(ptrans->resource);
616 struct lima_bo *bo = res->bo;
617 struct pipe_resource *pres;
618
619 if (trans->staging) {
620 pres = &res->base;
621 if (ptrans->usage & PIPE_TRANSFER_WRITE) {
622 unsigned i;
623 for (i = 0; i < ptrans->box.depth; i++)
624 panfrost_store_tiled_image(
625 bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->level].layer_stride,
626 trans->staging + i * ptrans->stride * ptrans->box.height,
627 ptrans->box.x, ptrans->box.y,
628 ptrans->box.width, ptrans->box.height,
629 res->levels[ptrans->level].stride,
630 ptrans->stride,
631 pres->format);
632 }
633 free(trans->staging);
634 }
635
636 pipe_resource_reference(&ptrans->resource, NULL);
637 slab_free(&ctx->transfer_pool, trans);
638 }
639
640 static void
641 lima_util_blitter_save_states(struct lima_context *ctx)
642 {
643 util_blitter_save_blend(ctx->blitter, (void *)ctx->blend);
644 util_blitter_save_depth_stencil_alpha(ctx->blitter, (void *)ctx->zsa);
645 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
646 util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer);
647 util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
648 util_blitter_save_vertex_shader(ctx->blitter, ctx->vs);
649 util_blitter_save_viewport(ctx->blitter,
650 &ctx->viewport.transform);
651 util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
652 util_blitter_save_vertex_elements(ctx->blitter,
653 ctx->vertex_elements);
654 util_blitter_save_vertex_buffer_slot(ctx->blitter,
655 ctx->vertex_buffers.vb);
656
657 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base);
658
659 util_blitter_save_fragment_sampler_states(ctx->blitter,
660 ctx->tex_stateobj.num_samplers,
661 (void**)ctx->tex_stateobj.samplers);
662 util_blitter_save_fragment_sampler_views(ctx->blitter,
663 ctx->tex_stateobj.num_textures,
664 ctx->tex_stateobj.textures);
665 }
666
667 static void
668 lima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
669 {
670 struct lima_context *ctx = lima_context(pctx);
671 struct pipe_blit_info info = *blit_info;
672
673 if (util_try_blit_via_copy_region(pctx, &info)) {
674 return; /* done */
675 }
676
677 if (info.mask & PIPE_MASK_S) {
678 debug_printf("lima: cannot blit stencil, skipping\n");
679 info.mask &= ~PIPE_MASK_S;
680 }
681
682 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
683 debug_printf("lima: blit unsupported %s -> %s\n",
684 util_format_short_name(info.src.resource->format),
685 util_format_short_name(info.dst.resource->format));
686 return;
687 }
688
689 lima_util_blitter_save_states(ctx);
690
691 util_blitter_blit(ctx->blitter, &info);
692 }
693
694 static void
695 lima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
696 {
697
698 }
699
700 void
701 lima_resource_context_init(struct lima_context *ctx)
702 {
703 ctx->base.create_surface = lima_surface_create;
704 ctx->base.surface_destroy = lima_surface_destroy;
705
706 /* TODO: optimize these functions to read/write data directly
707 * from/to target instead of creating a staging memory for tiled
708 * buffer indirectly
709 */
710 ctx->base.buffer_subdata = u_default_buffer_subdata;
711 ctx->base.texture_subdata = u_default_texture_subdata;
712 ctx->base.resource_copy_region = util_resource_copy_region;
713
714 ctx->base.blit = lima_blit;
715
716 ctx->base.transfer_map = lima_transfer_map;
717 ctx->base.transfer_flush_region = lima_transfer_flush_region;
718 ctx->base.transfer_unmap = lima_transfer_unmap;
719
720 ctx->base.flush_resource = lima_flush_resource;
721 }