lima/ppir: add NIR pass to split varying loads
[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/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"
36
37 #include "state_tracker/drm_driver.h"
38
39 #include "drm-uapi/drm_fourcc.h"
40 #include "drm-uapi/lima_drm.h"
41
42 #include "lima_screen.h"
43 #include "lima_context.h"
44 #include "lima_resource.h"
45 #include "lima_bo.h"
46 #include "lima_util.h"
47 #include "pan_tiling.h"
48
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)
53 {
54 struct lima_screen *screen = lima_screen(pscreen);
55 struct renderonly_scanout *scanout;
56 struct winsys_handle handle;
57 struct pipe_resource *pres;
58
59 struct pipe_resource scanout_templat = *templat;
60 scanout_templat.width0 = width;
61 scanout_templat.height0 = height;
62 scanout_templat.screen = pscreen;
63
64 scanout = renderonly_scanout_for_resource(&scanout_templat,
65 screen->ro, &handle);
66 if (!scanout)
67 return NULL;
68
69 assert(handle.type == WINSYS_HANDLE_TYPE_FD);
70 pres = pscreen->resource_from_handle(pscreen, templat, &handle,
71 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
72
73 close(handle.handle);
74 if (!pres) {
75 renderonly_scanout_destroy(scanout, screen->ro);
76 return NULL;
77 }
78
79 struct lima_resource *res = lima_resource(pres);
80 res->scanout = scanout;
81
82 return pres;
83 }
84
85 static uint32_t
86 setup_miptree(struct lima_resource *res,
87 unsigned width0, unsigned height0,
88 bool should_align_dimensions)
89 {
90 struct pipe_resource *pres = &res->base;
91 unsigned level;
92 unsigned width = width0;
93 unsigned height = height0;
94 unsigned depth = pres->depth0;
95 uint32_t size = 0;
96
97 for (level = 0; level <= pres->last_level; level++) {
98 uint32_t actual_level_size;
99 uint32_t stride;
100 unsigned aligned_width;
101 unsigned aligned_height;
102
103 if (should_align_dimensions) {
104 aligned_width = align(width, 16);
105 aligned_height = align(height, 16);
106 } else {
107 aligned_width = width;
108 aligned_height = height;
109 }
110
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;
115
116 res->levels[level].width = aligned_width;
117 res->levels[level].stride = stride;
118 res->levels[level].offset = size;
119
120 /* The start address of each level <= 10 must be 64-aligned
121 * in order to be able to pass the addresses
122 * to the hardware.
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 */
126 if (level < 10)
127 size += align(actual_level_size, 64);
128 else if (level != pres->last_level)
129 size += 0x0400;
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 = false;
181 unsigned width, height;
182 bool should_align_dimensions;
183
184 /* VBOs/PBOs are untiled (and 1 height). */
185 if (templat->target == PIPE_BUFFER)
186 should_tile = false;
187
188 if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT))
189 should_tile = false;
190
191 /* if linear buffer is not allowed, alloc fail */
192 if (!should_tile && !drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
193 return NULL;
194
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);
200 }
201 else {
202 should_align_dimensions = false;
203 width = templat->width0;
204 height = templat->height0;
205 }
206
207 struct pipe_resource *pres;
208 if (screen->ro && (templat->bind & PIPE_BIND_SCANOUT))
209 pres = lima_resource_create_scanout(pscreen, templat, width, height);
210 else
211 pres = lima_resource_create_bo(pscreen, templat, width, height,
212 should_align_dimensions);
213
214 if (pres) {
215 struct lima_resource *res = lima_resource(pres);
216 res->tiled = should_tile;
217
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);
222 }
223 return pres;
224 }
225
226 static struct pipe_resource *
227 lima_resource_create(struct pipe_screen *pscreen,
228 const struct pipe_resource *templat)
229 {
230 static const uint64_t modifiers[] = {
231 DRM_FORMAT_MOD_LINEAR,
232 };
233 return _lima_resource_create_with_modifiers(pscreen, templat, modifiers, ARRAY_SIZE(modifiers));
234 }
235
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,
240 int count)
241 {
242 struct pipe_resource tmpl = *templat;
243
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.
248 */
249 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
250 tmpl.bind |= PIPE_BIND_SCANOUT;
251
252 return _lima_resource_create_with_modifiers(pscreen, &tmpl, modifiers, count);
253 }
254
255 static void
256 lima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres)
257 {
258 struct lima_screen *screen = lima_screen(pscreen);
259 struct lima_resource *res = lima_resource(pres);
260
261 if (res->bo)
262 lima_bo_unreference(res->bo);
263
264 if (res->scanout)
265 renderonly_scanout_destroy(res->scanout, screen->ro);
266
267 if (res->damage.region)
268 FREE(res->damage.region);
269
270 FREE(res);
271 }
272
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)
277 {
278 struct lima_resource *res;
279 struct lima_screen *screen = lima_screen(pscreen);
280
281 res = CALLOC_STRUCT(lima_resource);
282 if (!res)
283 return NULL;
284
285 struct pipe_resource *pres = &res->base;
286 *pres = *templat;
287 pres->screen = pscreen;
288 pipe_reference_init(&pres->reference, 1);
289 res->levels[0].offset = 0;
290 res->levels[0].stride = handle->stride;
291
292 res->bo = lima_bo_import(screen, handle);
293 if (!res->bo) {
294 FREE(res);
295 return NULL;
296 }
297
298 /* check alignment for the buffer */
299 if (pres->bind & PIPE_BIND_RENDER_TARGET) {
300 unsigned width, height, stride, size;
301
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);
306
307 if (res->levels[0].stride != stride || res->bo->size < size) {
308 debug_error("import buffer not properly aligned\n");
309 goto err_out;
310 }
311
312 res->levels[0].width = width;
313 }
314 else
315 res->levels[0].width = pres->width0;
316
317 handle->modifier = DRM_FORMAT_MOD_LINEAR;
318 res->tiled = false;
319
320 return pres;
321
322 err_out:
323 lima_resource_destroy(pscreen, pres);
324 return NULL;
325 }
326
327 static bool
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)
332 {
333 struct lima_screen *screen = lima_screen(pscreen);
334 struct lima_resource *res = lima_resource(pres);
335
336 handle->modifier = DRM_FORMAT_MOD_LINEAR;
337
338 if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
339 renderonly_get_handle(res->scanout, handle))
340 return true;
341
342 if (!lima_bo_export(res->bo, handle))
343 return false;
344
345 handle->stride = res->levels[0].stride;
346 return true;
347 }
348
349 static void
350 get_scissor_from_box(struct pipe_scissor_state *s,
351 const struct pipe_box *b, int h)
352 {
353 int y = h - (b->y + b->height);
354 /* region in tile unit */
355 s->minx = b->x >> 4;
356 s->miny = y >> 4;
357 s->maxx = (b->x + b->width + 0xf) >> 4;
358 s->maxy = (y + b->height + 0xf) >> 4;
359 }
360
361 static void
362 get_damage_bound_box(struct pipe_resource *pres,
363 const struct pipe_box *rects,
364 unsigned int nrects,
365 struct pipe_scissor_state *bound)
366 {
367 struct pipe_box b = rects[0];
368
369 for (int i = 1; i < nrects; i++)
370 u_box_union_2d(&b, &b, rects + i);
371
372 int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0);
373 if (ret < 0)
374 memset(bound, 0, sizeof(*bound));
375 else
376 get_scissor_from_box(bound, &b, pres->height0);
377 }
378
379 static void
380 lima_resource_set_damage_region(struct pipe_screen *pscreen,
381 struct pipe_resource *pres,
382 unsigned int nrects,
383 const struct pipe_box *rects)
384 {
385 struct lima_resource *res = lima_resource(pres);
386 struct lima_damage_region *damage = &res->damage;
387 int i;
388
389 if (damage->region) {
390 FREE(damage->region);
391 damage->region = NULL;
392 damage->num_region = 0;
393 }
394
395 if (!nrects)
396 return;
397
398 /* check full damage
399 *
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
404 */
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)
409 return;
410 }
411
412 struct pipe_scissor_state *bound = &damage->bound;
413 get_damage_bound_box(pres, rects, nrects, bound);
414
415 damage->region = CALLOC(nrects, sizeof(*damage->region));
416 if (!damage->region)
417 return;
418
419 for (i = 0; i < nrects; i++)
420 get_scissor_from_box(damage->region + i, rects + i,
421 pres->height0);
422
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;
429 break;
430 }
431 }
432
433 damage->num_region = nrects;
434 }
435
436 void
437 lima_resource_screen_init(struct lima_screen *screen)
438 {
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;
445 }
446
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)
451 {
452 struct lima_surface *surf = CALLOC_STRUCT(lima_surface);
453
454 if (!surf)
455 return NULL;
456
457 assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
458
459 struct pipe_surface *psurf = &surf->base;
460 unsigned level = surf_tmpl->u.tex.level;
461
462 pipe_reference_init(&psurf->reference, 1);
463 pipe_resource_reference(&psurf->texture, pres);
464
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;
472
473 surf->tiled_w = align(psurf->width, 16) >> 4;
474 surf->tiled_h = align(psurf->height, 16) >> 4;
475
476 surf->reload = true;
477
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,
483 };
484
485 for (int i = 0; i < lima_ctx_num_plb; i++) {
486 key.plb_index = i;
487
488 struct hash_entry *entry =
489 _mesa_hash_table_search(ctx->plb_pp_stream, &key);
490 if (entry) {
491 struct lima_ctx_plb_pp_stream *s = entry->data;
492 s->refcnt++;
493 }
494 else {
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;
500 s->refcnt = 1;
501 s->bo = NULL;
502 _mesa_hash_table_insert(ctx->plb_pp_stream, &s->key, s);
503 }
504 }
505 }
506
507 return &surf->base;
508 }
509
510 static void
511 lima_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
512 {
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);
516
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,
521 };
522
523 for (int i = 0; i < lima_ctx_num_plb; i++) {
524 key.plb_index = i;
525
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) {
530 if (s->bo)
531 lima_bo_unreference(s->bo);
532 _mesa_hash_table_remove(ctx->plb_pp_stream, entry);
533 ralloc_free(s);
534 }
535 }
536 }
537
538 pipe_resource_reference(&psurf->texture, NULL);
539 FREE(surf);
540 }
541
542 static void *
543 lima_transfer_map(struct pipe_context *pctx,
544 struct pipe_resource *pres,
545 unsigned level,
546 unsigned usage,
547 const struct pipe_box *box,
548 struct pipe_transfer **pptrans)
549 {
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;
555
556 /* No direct mappings of tiled, since we need to manually
557 * tile/untile.
558 */
559 if (res->tiled && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
560 return NULL;
561
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))
567 lima_flush(ctx);
568
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);
572 }
573 }
574
575 if (!lima_bo_map(bo))
576 return NULL;
577
578 trans = slab_alloc(&ctx->transfer_pool);
579 if (!trans)
580 return NULL;
581
582 memset(trans, 0, sizeof(*trans));
583 ptrans = &trans->base;
584
585 pipe_resource_reference(&ptrans->resource, pres);
586 ptrans->level = level;
587 ptrans->usage = usage;
588 ptrans->box = *box;
589
590 *pptrans = ptrans;
591
592 if (res->tiled) {
593 ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width);
594 ptrans->layer_stride = ptrans->stride * ptrans->box.height;
595
596 trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth);
597
598 if (usage & PIPE_TRANSFER_READ)
599 panfrost_load_tiled_image(trans->staging, bo->map + res->levels[level].offset,
600 &ptrans->box,
601 ptrans->stride,
602 res->levels[level].stride,
603 util_format_get_blocksize(pres->format));
604
605 return trans->staging;
606 } else {
607 ptrans->stride = res->levels[level].stride;
608 ptrans->layer_stride = ptrans->stride * box->height;
609
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);
615 }
616 }
617
618 static void
619 lima_transfer_flush_region(struct pipe_context *pctx,
620 struct pipe_transfer *ptrans,
621 const struct pipe_box *box)
622 {
623
624 }
625
626 static void
627 lima_transfer_unmap(struct pipe_context *pctx,
628 struct pipe_transfer *ptrans)
629 {
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;
635
636 if (trans->staging) {
637 pres = &res->base;
638 if (ptrans->usage & PIPE_TRANSFER_WRITE)
639 panfrost_store_tiled_image(bo->map + res->levels[ptrans->level].offset, trans->staging,
640 &ptrans->box,
641 res->levels[ptrans->level].stride,
642 ptrans->stride,
643 util_format_get_blocksize(pres->format));
644 free(trans->staging);
645 }
646
647 pipe_resource_reference(&ptrans->resource, NULL);
648 slab_free(&ctx->transfer_pool, trans);
649 }
650
651 static void
652 lima_util_blitter_save_states(struct lima_context *ctx)
653 {
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);
667
668 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base);
669
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);
676 }
677
678 static void
679 lima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
680 {
681 struct lima_context *ctx = lima_context(pctx);
682 struct pipe_blit_info info = *blit_info;
683
684 if (util_try_blit_via_copy_region(pctx, &info)) {
685 return; /* done */
686 }
687
688 if (info.mask & PIPE_MASK_S) {
689 debug_printf("lima: cannot blit stencil, skipping\n");
690 info.mask &= ~PIPE_MASK_S;
691 }
692
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));
697 return;
698 }
699
700 lima_util_blitter_save_states(ctx);
701
702 util_blitter_blit(ctx->blitter, &info);
703 }
704
705 static void
706 lima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
707 {
708
709 }
710
711 void
712 lima_resource_context_init(struct lima_context *ctx)
713 {
714 ctx->base.create_surface = lima_surface_create;
715 ctx->base.surface_destroy = lima_surface_destroy;
716
717 /* TODO: optimize these functions to read/write data directly
718 * from/to target instead of creating a staging memory for tiled
719 * buffer indirectly
720 */
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;
724
725 ctx->base.blit = lima_blit;
726
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;
730
731 ctx->base.flush_resource = lima_flush_resource;
732 }