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