024ec41da44bd6ed59d2bf7a62854e8f7473b017
[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/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 res->levels[level].layer_stride = util_format_get_stride(pres->format, align(width, 16)) * align(height, 16);
120
121 /* The start address of each level <= 10 must be 64-aligned
122 * in order to be able to pass the addresses
123 * to the hardware.
124 * The start addresses of level 11 and level 12 are passed
125 * implicitely: they start at an offset of respectively
126 * 0x0400 and 0x0800 from the start address of level 10 */
127 if (level < 10)
128 size += align(actual_level_size, 64);
129 else if (level != pres->last_level)
130 size += 0x0400;
131 else
132 size += actual_level_size; /* Save some memory */
133
134 width = u_minify(width, 1);
135 height = u_minify(height, 1);
136 depth = u_minify(depth, 1);
137 }
138
139 return size;
140 }
141
142 static struct pipe_resource *
143 lima_resource_create_bo(struct pipe_screen *pscreen,
144 const struct pipe_resource *templat,
145 unsigned width, unsigned height,
146 bool should_align_dimensions)
147 {
148 struct lima_screen *screen = lima_screen(pscreen);
149 struct lima_resource *res;
150 struct pipe_resource *pres;
151
152 res = CALLOC_STRUCT(lima_resource);
153 if (!res)
154 return NULL;
155
156 res->base = *templat;
157 res->base.screen = pscreen;
158 pipe_reference_init(&res->base.reference, 1);
159
160 pres = &res->base;
161
162 uint32_t size = setup_miptree(res, width, height, should_align_dimensions);
163 size = align(size, LIMA_PAGE_SIZE);
164
165 res->bo = lima_bo_create(screen, size, 0);
166 if (!res->bo) {
167 FREE(res);
168 return NULL;
169 }
170
171 return pres;
172 }
173
174 static struct pipe_resource *
175 _lima_resource_create_with_modifiers(struct pipe_screen *pscreen,
176 const struct pipe_resource *templat,
177 const uint64_t *modifiers,
178 int count)
179 {
180 struct lima_screen *screen = lima_screen(pscreen);
181 bool should_tile = false;
182 unsigned width, height;
183 bool should_align_dimensions;
184
185 /* VBOs/PBOs are untiled (and 1 height). */
186 if (templat->target == PIPE_BUFFER)
187 should_tile = false;
188
189 if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT))
190 should_tile = false;
191
192 /* if linear buffer is not allowed, alloc fail */
193 if (!should_tile && !drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
194 return NULL;
195
196 if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) ||
197 (templat->bind & PIPE_BIND_DEPTH_STENCIL)) {
198 should_align_dimensions = true;
199 width = align(templat->width0, 16);
200 height = align(templat->height0, 16);
201 }
202 else {
203 should_align_dimensions = false;
204 width = templat->width0;
205 height = templat->height0;
206 }
207
208 struct pipe_resource *pres;
209 if (screen->ro && (templat->bind & PIPE_BIND_SCANOUT))
210 pres = lima_resource_create_scanout(pscreen, templat, width, height);
211 else
212 pres = lima_resource_create_bo(pscreen, templat, width, height,
213 should_align_dimensions);
214
215 if (pres) {
216 struct lima_resource *res = lima_resource(pres);
217 res->tiled = should_tile;
218
219 debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d "
220 "bind=%x usage=%d tile=%d last_level=%d\n", __func__,
221 pres, pres->width0, pres->height0, pres->depth0,
222 pres->target, pres->bind, pres->usage, should_tile, templat->last_level);
223 }
224 return pres;
225 }
226
227 static struct pipe_resource *
228 lima_resource_create(struct pipe_screen *pscreen,
229 const struct pipe_resource *templat)
230 {
231 static const uint64_t modifiers[] = {
232 DRM_FORMAT_MOD_LINEAR,
233 };
234 return _lima_resource_create_with_modifiers(pscreen, templat, modifiers, ARRAY_SIZE(modifiers));
235 }
236
237 static struct pipe_resource *
238 lima_resource_create_with_modifiers(struct pipe_screen *pscreen,
239 const struct pipe_resource *templat,
240 const uint64_t *modifiers,
241 int count)
242 {
243 struct pipe_resource tmpl = *templat;
244
245 /* gbm_bo_create_with_modifiers & gbm_surface_create_with_modifiers
246 * don't have usage parameter, but buffer created by these functions
247 * may be used for scanout. So we assume buffer created by this
248 * function always enable scanout if linear modifier is permitted.
249 */
250 if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
251 tmpl.bind |= PIPE_BIND_SCANOUT;
252
253 return _lima_resource_create_with_modifiers(pscreen, &tmpl, modifiers, count);
254 }
255
256 static void
257 lima_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pres)
258 {
259 struct lima_screen *screen = lima_screen(pscreen);
260 struct lima_resource *res = lima_resource(pres);
261
262 if (res->bo)
263 lima_bo_unreference(res->bo);
264
265 if (res->scanout)
266 renderonly_scanout_destroy(res->scanout, screen->ro);
267
268 if (res->damage.region)
269 FREE(res->damage.region);
270
271 FREE(res);
272 }
273
274 static struct pipe_resource *
275 lima_resource_from_handle(struct pipe_screen *pscreen,
276 const struct pipe_resource *templat,
277 struct winsys_handle *handle, unsigned usage)
278 {
279 struct lima_resource *res;
280 struct lima_screen *screen = lima_screen(pscreen);
281
282 res = CALLOC_STRUCT(lima_resource);
283 if (!res)
284 return NULL;
285
286 struct pipe_resource *pres = &res->base;
287 *pres = *templat;
288 pres->screen = pscreen;
289 pipe_reference_init(&pres->reference, 1);
290 res->levels[0].offset = 0;
291 res->levels[0].stride = handle->stride;
292
293 res->bo = lima_bo_import(screen, handle);
294 if (!res->bo) {
295 FREE(res);
296 return NULL;
297 }
298
299 /* check alignment for the buffer */
300 if (pres->bind & PIPE_BIND_RENDER_TARGET) {
301 unsigned width, height, stride, size;
302
303 width = align(pres->width0, 16);
304 height = align(pres->height0, 16);
305 stride = util_format_get_stride(pres->format, width);
306 size = util_format_get_2d_size(pres->format, stride, height);
307
308 if (res->levels[0].stride != stride || res->bo->size < size) {
309 debug_error("import buffer not properly aligned\n");
310 goto err_out;
311 }
312
313 res->levels[0].width = width;
314 }
315 else
316 res->levels[0].width = pres->width0;
317
318 handle->modifier = DRM_FORMAT_MOD_LINEAR;
319 res->tiled = false;
320
321 return pres;
322
323 err_out:
324 lima_resource_destroy(pscreen, pres);
325 return NULL;
326 }
327
328 static bool
329 lima_resource_get_handle(struct pipe_screen *pscreen,
330 struct pipe_context *pctx,
331 struct pipe_resource *pres,
332 struct winsys_handle *handle, unsigned usage)
333 {
334 struct lima_screen *screen = lima_screen(pscreen);
335 struct lima_resource *res = lima_resource(pres);
336
337 handle->modifier = DRM_FORMAT_MOD_LINEAR;
338
339 if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
340 renderonly_get_handle(res->scanout, handle))
341 return true;
342
343 if (!lima_bo_export(res->bo, handle))
344 return false;
345
346 handle->stride = res->levels[0].stride;
347 return true;
348 }
349
350 static void
351 get_scissor_from_box(struct pipe_scissor_state *s,
352 const struct pipe_box *b, int h)
353 {
354 int y = h - (b->y + b->height);
355 /* region in tile unit */
356 s->minx = b->x >> 4;
357 s->miny = y >> 4;
358 s->maxx = (b->x + b->width + 0xf) >> 4;
359 s->maxy = (y + b->height + 0xf) >> 4;
360 }
361
362 static void
363 get_damage_bound_box(struct pipe_resource *pres,
364 const struct pipe_box *rects,
365 unsigned int nrects,
366 struct pipe_scissor_state *bound)
367 {
368 struct pipe_box b = rects[0];
369
370 for (int i = 1; i < nrects; i++)
371 u_box_union_2d(&b, &b, rects + i);
372
373 int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0);
374 if (ret < 0)
375 memset(bound, 0, sizeof(*bound));
376 else
377 get_scissor_from_box(bound, &b, pres->height0);
378 }
379
380 static void
381 lima_resource_set_damage_region(struct pipe_screen *pscreen,
382 struct pipe_resource *pres,
383 unsigned int nrects,
384 const struct pipe_box *rects)
385 {
386 struct lima_resource *res = lima_resource(pres);
387 struct lima_damage_region *damage = &res->damage;
388 int i;
389
390 if (damage->region) {
391 FREE(damage->region);
392 damage->region = NULL;
393 damage->num_region = 0;
394 }
395
396 if (!nrects)
397 return;
398
399 /* check full damage
400 *
401 * TODO: currently only check if there is any single damage
402 * region that can cover the full render target; there may
403 * be some accurate way, but a single window size damage
404 * region is most of the case from weston
405 */
406 for (i = 0; i < nrects; i++) {
407 if (rects[i].x <= 0 && rects[i].y <= 0 &&
408 rects[i].x + rects[i].width >= pres->width0 &&
409 rects[i].y + rects[i].height >= pres->height0)
410 return;
411 }
412
413 struct pipe_scissor_state *bound = &damage->bound;
414 get_damage_bound_box(pres, rects, nrects, bound);
415
416 damage->region = CALLOC(nrects, sizeof(*damage->region));
417 if (!damage->region)
418 return;
419
420 for (i = 0; i < nrects; i++)
421 get_scissor_from_box(damage->region + i, rects + i,
422 pres->height0);
423
424 /* is region aligned to tiles? */
425 damage->aligned = true;
426 for (i = 0; i < nrects; i++) {
427 if (rects[i].x & 0xf || rects[i].y & 0xf ||
428 rects[i].width & 0xf || rects[i].height & 0xf) {
429 damage->aligned = false;
430 break;
431 }
432 }
433
434 damage->num_region = nrects;
435 }
436
437 void
438 lima_resource_screen_init(struct lima_screen *screen)
439 {
440 screen->base.resource_create = lima_resource_create;
441 screen->base.resource_create_with_modifiers = lima_resource_create_with_modifiers;
442 screen->base.resource_from_handle = lima_resource_from_handle;
443 screen->base.resource_destroy = lima_resource_destroy;
444 screen->base.resource_get_handle = lima_resource_get_handle;
445 screen->base.set_damage_region = lima_resource_set_damage_region;
446 }
447
448 static struct pipe_surface *
449 lima_surface_create(struct pipe_context *pctx,
450 struct pipe_resource *pres,
451 const struct pipe_surface *surf_tmpl)
452 {
453 struct lima_surface *surf = CALLOC_STRUCT(lima_surface);
454
455 if (!surf)
456 return NULL;
457
458 assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
459
460 struct pipe_surface *psurf = &surf->base;
461 unsigned level = surf_tmpl->u.tex.level;
462
463 pipe_reference_init(&psurf->reference, 1);
464 pipe_resource_reference(&psurf->texture, pres);
465
466 psurf->context = pctx;
467 psurf->format = surf_tmpl->format;
468 psurf->width = u_minify(pres->width0, level);
469 psurf->height = u_minify(pres->height0, level);
470 psurf->u.tex.level = level;
471 psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
472 psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
473
474 surf->tiled_w = align(psurf->width, 16) >> 4;
475 surf->tiled_h = align(psurf->height, 16) >> 4;
476
477 surf->reload = true;
478
479 struct lima_context *ctx = lima_context(pctx);
480 if (ctx->plb_pp_stream) {
481 struct lima_ctx_plb_pp_stream_key key = {
482 .tiled_w = surf->tiled_w,
483 .tiled_h = surf->tiled_h,
484 };
485
486 for (int i = 0; i < lima_ctx_num_plb; i++) {
487 key.plb_index = i;
488
489 struct hash_entry *entry =
490 _mesa_hash_table_search(ctx->plb_pp_stream, &key);
491 if (entry) {
492 struct lima_ctx_plb_pp_stream *s = entry->data;
493 s->refcnt++;
494 }
495 else {
496 struct lima_ctx_plb_pp_stream *s =
497 ralloc(ctx->plb_pp_stream, struct lima_ctx_plb_pp_stream);
498 s->key.plb_index = i;
499 s->key.tiled_w = surf->tiled_w;
500 s->key.tiled_h = surf->tiled_h;
501 s->refcnt = 1;
502 s->bo = NULL;
503 _mesa_hash_table_insert(ctx->plb_pp_stream, &s->key, s);
504 }
505 }
506 }
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 /* psurf->context may be not equal with pctx (i.e. glxinfo) */
516 struct lima_context *ctx = lima_context(psurf->context);
517
518 if (ctx->plb_pp_stream) {
519 struct lima_ctx_plb_pp_stream_key key = {
520 .tiled_w = surf->tiled_w,
521 .tiled_h = surf->tiled_h,
522 };
523
524 for (int i = 0; i < lima_ctx_num_plb; i++) {
525 key.plb_index = i;
526
527 struct hash_entry *entry =
528 _mesa_hash_table_search(ctx->plb_pp_stream, &key);
529 struct lima_ctx_plb_pp_stream *s = entry->data;
530 if (--s->refcnt == 0) {
531 if (s->bo)
532 lima_bo_unreference(s->bo);
533 _mesa_hash_table_remove(ctx->plb_pp_stream, entry);
534 ralloc_free(s);
535 }
536 }
537 }
538
539 pipe_resource_reference(&psurf->texture, NULL);
540 FREE(surf);
541 }
542
543 static void *
544 lima_transfer_map(struct pipe_context *pctx,
545 struct pipe_resource *pres,
546 unsigned level,
547 unsigned usage,
548 const struct pipe_box *box,
549 struct pipe_transfer **pptrans)
550 {
551 struct lima_context *ctx = lima_context(pctx);
552 struct lima_resource *res = lima_resource(pres);
553 struct lima_bo *bo = res->bo;
554 struct lima_transfer *trans;
555 struct pipe_transfer *ptrans;
556
557 /* No direct mappings of tiled, since we need to manually
558 * tile/untile.
559 */
560 if (res->tiled && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
561 return NULL;
562
563 /* use once buffers are made sure to not read/write overlapped
564 * range, so no need to sync */
565 if (pres->usage != PIPE_USAGE_STREAM) {
566 if (usage & PIPE_TRANSFER_READ_WRITE) {
567 if (lima_need_flush(ctx, bo, usage & PIPE_TRANSFER_WRITE))
568 lima_flush(ctx);
569
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);
573 }
574 }
575
576 if (!lima_bo_map(bo))
577 return NULL;
578
579 trans = slab_alloc(&ctx->transfer_pool);
580 if (!trans)
581 return NULL;
582
583 memset(trans, 0, sizeof(*trans));
584 ptrans = &trans->base;
585
586 pipe_resource_reference(&ptrans->resource, pres);
587 ptrans->level = level;
588 ptrans->usage = usage;
589 ptrans->box = *box;
590
591 *pptrans = ptrans;
592
593 if (res->tiled) {
594 ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width);
595 ptrans->layer_stride = ptrans->stride * ptrans->box.height;
596
597 trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth);
598
599 if (usage & PIPE_TRANSFER_READ) {
600 unsigned i;
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,
606 ptrans->stride,
607 res->levels[level].stride,
608 util_format_get_blocksize(pres->format));
609 }
610
611 return trans->staging;
612 } else {
613 ptrans->stride = res->levels[level].stride;
614 ptrans->layer_stride = res->levels[level].layer_stride;
615
616 return bo->map + res->levels[level].offset +
617 box->z * res->levels[level].layer_stride +
618 box->y / util_format_get_blockheight(pres->format) * ptrans->stride +
619 box->x / util_format_get_blockwidth(pres->format) *
620 util_format_get_blocksize(pres->format);
621 }
622 }
623
624 static void
625 lima_transfer_flush_region(struct pipe_context *pctx,
626 struct pipe_transfer *ptrans,
627 const struct pipe_box *box)
628 {
629
630 }
631
632 static void
633 lima_transfer_unmap(struct pipe_context *pctx,
634 struct pipe_transfer *ptrans)
635 {
636 struct lima_context *ctx = lima_context(pctx);
637 struct lima_transfer *trans = lima_transfer(ptrans);
638 struct lima_resource *res = lima_resource(ptrans->resource);
639 struct lima_bo *bo = res->bo;
640 struct pipe_resource *pres;
641
642 if (trans->staging) {
643 pres = &res->base;
644 if (ptrans->usage & PIPE_TRANSFER_WRITE) {
645 unsigned i;
646 for (i = 0; i < ptrans->box.depth; i++)
647 panfrost_store_tiled_image(
648 bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->level].layer_stride,
649 trans->staging + i * ptrans->stride * ptrans->box.height,
650 &ptrans->box,
651 res->levels[ptrans->level].stride,
652 ptrans->stride,
653 util_format_get_blocksize(pres->format));
654 }
655 free(trans->staging);
656 }
657
658 pipe_resource_reference(&ptrans->resource, NULL);
659 slab_free(&ctx->transfer_pool, trans);
660 }
661
662 static void
663 lima_util_blitter_save_states(struct lima_context *ctx)
664 {
665 util_blitter_save_blend(ctx->blitter, (void *)ctx->blend);
666 util_blitter_save_depth_stencil_alpha(ctx->blitter, (void *)ctx->zsa);
667 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
668 util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer);
669 util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
670 util_blitter_save_vertex_shader(ctx->blitter, ctx->vs);
671 util_blitter_save_viewport(ctx->blitter,
672 &ctx->viewport.transform);
673 util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
674 util_blitter_save_vertex_elements(ctx->blitter,
675 ctx->vertex_elements);
676 util_blitter_save_vertex_buffer_slot(ctx->blitter,
677 ctx->vertex_buffers.vb);
678
679 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base);
680
681 util_blitter_save_fragment_sampler_states(ctx->blitter,
682 ctx->tex_stateobj.num_samplers,
683 (void**)ctx->tex_stateobj.samplers);
684 util_blitter_save_fragment_sampler_views(ctx->blitter,
685 ctx->tex_stateobj.num_textures,
686 ctx->tex_stateobj.textures);
687 }
688
689 static void
690 lima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
691 {
692 struct lima_context *ctx = lima_context(pctx);
693 struct pipe_blit_info info = *blit_info;
694
695 if (util_try_blit_via_copy_region(pctx, &info)) {
696 return; /* done */
697 }
698
699 if (info.mask & PIPE_MASK_S) {
700 debug_printf("lima: cannot blit stencil, skipping\n");
701 info.mask &= ~PIPE_MASK_S;
702 }
703
704 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
705 debug_printf("lima: blit unsupported %s -> %s\n",
706 util_format_short_name(info.src.resource->format),
707 util_format_short_name(info.dst.resource->format));
708 return;
709 }
710
711 lima_util_blitter_save_states(ctx);
712
713 util_blitter_blit(ctx->blitter, &info);
714 }
715
716 static void
717 lima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
718 {
719
720 }
721
722 void
723 lima_resource_context_init(struct lima_context *ctx)
724 {
725 ctx->base.create_surface = lima_surface_create;
726 ctx->base.surface_destroy = lima_surface_destroy;
727
728 /* TODO: optimize these functions to read/write data directly
729 * from/to target instead of creating a staging memory for tiled
730 * buffer indirectly
731 */
732 ctx->base.buffer_subdata = u_default_buffer_subdata;
733 ctx->base.texture_subdata = u_default_texture_subdata;
734 ctx->base.resource_copy_region = util_resource_copy_region;
735
736 ctx->base.blit = lima_blit;
737
738 ctx->base.transfer_map = lima_transfer_map;
739 ctx->base.transfer_flush_region = lima_transfer_flush_region;
740 ctx->base.transfer_unmap = lima_transfer_unmap;
741
742 ctx->base.flush_resource = lima_flush_resource;
743 }