lima: handle DRM_FORMAT_MOD_INVALID in resource_from_handle()
[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 case DRM_FORMAT_MOD_INVALID:
333 res->tiled = screen->ro == NULL;
334 break;
335 default:
336 fprintf(stderr, "Attempted to import unsupported modifier 0x%llx\n",
337 (long long)handle->modifier);
338 goto err_out;
339 }
340
341 return pres;
342
343 err_out:
344 lima_resource_destroy(pscreen, pres);
345 return NULL;
346 }
347
348 static bool
349 lima_resource_get_handle(struct pipe_screen *pscreen,
350 struct pipe_context *pctx,
351 struct pipe_resource *pres,
352 struct winsys_handle *handle, unsigned usage)
353 {
354 struct lima_screen *screen = lima_screen(pscreen);
355 struct lima_resource *res = lima_resource(pres);
356
357 if (res->tiled)
358 handle->modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
359 else
360 handle->modifier = DRM_FORMAT_MOD_LINEAR;
361
362 if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
363 renderonly_get_handle(res->scanout, handle))
364 return true;
365
366 if (!lima_bo_export(res->bo, handle))
367 return false;
368
369 handle->stride = res->levels[0].stride;
370 return true;
371 }
372
373 static void
374 get_scissor_from_box(struct pipe_scissor_state *s,
375 const struct pipe_box *b, int h)
376 {
377 int y = h - (b->y + b->height);
378 /* region in tile unit */
379 s->minx = b->x >> 4;
380 s->miny = y >> 4;
381 s->maxx = (b->x + b->width + 0xf) >> 4;
382 s->maxy = (y + b->height + 0xf) >> 4;
383 }
384
385 static void
386 get_damage_bound_box(struct pipe_resource *pres,
387 const struct pipe_box *rects,
388 unsigned int nrects,
389 struct pipe_scissor_state *bound)
390 {
391 struct pipe_box b = rects[0];
392
393 for (int i = 1; i < nrects; i++)
394 u_box_union_2d(&b, &b, rects + i);
395
396 int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0);
397 if (ret < 0)
398 memset(bound, 0, sizeof(*bound));
399 else
400 get_scissor_from_box(bound, &b, pres->height0);
401 }
402
403 static void
404 lima_resource_set_damage_region(struct pipe_screen *pscreen,
405 struct pipe_resource *pres,
406 unsigned int nrects,
407 const struct pipe_box *rects)
408 {
409 struct lima_resource *res = lima_resource(pres);
410 struct lima_damage_region *damage = &res->damage;
411 int i;
412
413 if (damage->region) {
414 FREE(damage->region);
415 damage->region = NULL;
416 damage->num_region = 0;
417 }
418
419 if (!nrects)
420 return;
421
422 /* check full damage
423 *
424 * TODO: currently only check if there is any single damage
425 * region that can cover the full render target; there may
426 * be some accurate way, but a single window size damage
427 * region is most of the case from weston
428 */
429 for (i = 0; i < nrects; i++) {
430 if (rects[i].x <= 0 && rects[i].y <= 0 &&
431 rects[i].x + rects[i].width >= pres->width0 &&
432 rects[i].y + rects[i].height >= pres->height0)
433 return;
434 }
435
436 struct pipe_scissor_state *bound = &damage->bound;
437 get_damage_bound_box(pres, rects, nrects, bound);
438
439 damage->region = CALLOC(nrects, sizeof(*damage->region));
440 if (!damage->region)
441 return;
442
443 for (i = 0; i < nrects; i++)
444 get_scissor_from_box(damage->region + i, rects + i,
445 pres->height0);
446
447 /* is region aligned to tiles? */
448 damage->aligned = true;
449 for (i = 0; i < nrects; i++) {
450 if (rects[i].x & 0xf || rects[i].y & 0xf ||
451 rects[i].width & 0xf || rects[i].height & 0xf) {
452 damage->aligned = false;
453 break;
454 }
455 }
456
457 damage->num_region = nrects;
458 }
459
460 void
461 lima_resource_screen_init(struct lima_screen *screen)
462 {
463 screen->base.resource_create = lima_resource_create;
464 screen->base.resource_create_with_modifiers = lima_resource_create_with_modifiers;
465 screen->base.resource_from_handle = lima_resource_from_handle;
466 screen->base.resource_destroy = lima_resource_destroy;
467 screen->base.resource_get_handle = lima_resource_get_handle;
468 screen->base.set_damage_region = lima_resource_set_damage_region;
469 }
470
471 static struct pipe_surface *
472 lima_surface_create(struct pipe_context *pctx,
473 struct pipe_resource *pres,
474 const struct pipe_surface *surf_tmpl)
475 {
476 struct lima_surface *surf = CALLOC_STRUCT(lima_surface);
477
478 if (!surf)
479 return NULL;
480
481 assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
482
483 struct pipe_surface *psurf = &surf->base;
484 unsigned level = surf_tmpl->u.tex.level;
485
486 pipe_reference_init(&psurf->reference, 1);
487 pipe_resource_reference(&psurf->texture, pres);
488
489 psurf->context = pctx;
490 psurf->format = surf_tmpl->format;
491 psurf->width = u_minify(pres->width0, level);
492 psurf->height = u_minify(pres->height0, level);
493 psurf->u.tex.level = level;
494 psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
495 psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
496
497 surf->tiled_w = align(psurf->width, 16) >> 4;
498 surf->tiled_h = align(psurf->height, 16) >> 4;
499
500 surf->reload = true;
501
502 struct lima_context *ctx = lima_context(pctx);
503 if (ctx->plb_pp_stream) {
504 struct lima_ctx_plb_pp_stream_key key = {
505 .tiled_w = surf->tiled_w,
506 .tiled_h = surf->tiled_h,
507 };
508
509 for (int i = 0; i < lima_ctx_num_plb; i++) {
510 key.plb_index = i;
511
512 struct hash_entry *entry =
513 _mesa_hash_table_search(ctx->plb_pp_stream, &key);
514 if (entry) {
515 struct lima_ctx_plb_pp_stream *s = entry->data;
516 s->refcnt++;
517 }
518 else {
519 struct lima_ctx_plb_pp_stream *s =
520 ralloc(ctx->plb_pp_stream, struct lima_ctx_plb_pp_stream);
521 s->key.plb_index = i;
522 s->key.tiled_w = surf->tiled_w;
523 s->key.tiled_h = surf->tiled_h;
524 s->refcnt = 1;
525 s->bo = NULL;
526 _mesa_hash_table_insert(ctx->plb_pp_stream, &s->key, s);
527 }
528 }
529 }
530
531 return &surf->base;
532 }
533
534 static void
535 lima_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
536 {
537 struct lima_surface *surf = lima_surface(psurf);
538 /* psurf->context may be not equal with pctx (i.e. glxinfo) */
539 struct lima_context *ctx = lima_context(psurf->context);
540
541 if (ctx->plb_pp_stream) {
542 struct lima_ctx_plb_pp_stream_key key = {
543 .tiled_w = surf->tiled_w,
544 .tiled_h = surf->tiled_h,
545 };
546
547 for (int i = 0; i < lima_ctx_num_plb; i++) {
548 key.plb_index = i;
549
550 struct hash_entry *entry =
551 _mesa_hash_table_search(ctx->plb_pp_stream, &key);
552 struct lima_ctx_plb_pp_stream *s = entry->data;
553 if (--s->refcnt == 0) {
554 if (s->bo)
555 lima_bo_unreference(s->bo);
556 _mesa_hash_table_remove(ctx->plb_pp_stream, entry);
557 ralloc_free(s);
558 }
559 }
560 }
561
562 pipe_resource_reference(&psurf->texture, NULL);
563 FREE(surf);
564 }
565
566 static void *
567 lima_transfer_map(struct pipe_context *pctx,
568 struct pipe_resource *pres,
569 unsigned level,
570 unsigned usage,
571 const struct pipe_box *box,
572 struct pipe_transfer **pptrans)
573 {
574 struct lima_context *ctx = lima_context(pctx);
575 struct lima_resource *res = lima_resource(pres);
576 struct lima_bo *bo = res->bo;
577 struct lima_transfer *trans;
578 struct pipe_transfer *ptrans;
579
580 /* No direct mappings of tiled, since we need to manually
581 * tile/untile.
582 */
583 if (res->tiled && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
584 return NULL;
585
586 /* use once buffers are made sure to not read/write overlapped
587 * range, so no need to sync */
588 if (pres->usage != PIPE_USAGE_STREAM) {
589 if (usage & PIPE_TRANSFER_READ_WRITE) {
590 if (lima_need_flush(ctx, bo, usage & PIPE_TRANSFER_WRITE))
591 lima_flush(ctx);
592
593 unsigned op = usage & PIPE_TRANSFER_WRITE ?
594 LIMA_GEM_WAIT_WRITE : LIMA_GEM_WAIT_READ;
595 lima_bo_wait(bo, op, PIPE_TIMEOUT_INFINITE);
596 }
597 }
598
599 if (!lima_bo_map(bo))
600 return NULL;
601
602 trans = slab_alloc(&ctx->transfer_pool);
603 if (!trans)
604 return NULL;
605
606 memset(trans, 0, sizeof(*trans));
607 ptrans = &trans->base;
608
609 pipe_resource_reference(&ptrans->resource, pres);
610 ptrans->level = level;
611 ptrans->usage = usage;
612 ptrans->box = *box;
613
614 *pptrans = ptrans;
615
616 if (res->tiled) {
617 ptrans->stride = util_format_get_stride(pres->format, ptrans->box.width);
618 ptrans->layer_stride = ptrans->stride * ptrans->box.height;
619
620 trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth);
621
622 if (usage & PIPE_TRANSFER_READ) {
623 unsigned i;
624 for (i = 0; i < ptrans->box.depth; i++)
625 panfrost_load_tiled_image(
626 trans->staging + i * ptrans->stride * ptrans->box.height,
627 bo->map + res->levels[level].offset + (i + box->z) * res->levels[level].layer_stride,
628 &ptrans->box,
629 ptrans->stride,
630 res->levels[level].stride,
631 util_format_get_blocksize(pres->format));
632 }
633
634 return trans->staging;
635 } else {
636 ptrans->stride = res->levels[level].stride;
637 ptrans->layer_stride = res->levels[level].layer_stride;
638
639 return bo->map + res->levels[level].offset +
640 box->z * res->levels[level].layer_stride +
641 box->y / util_format_get_blockheight(pres->format) * ptrans->stride +
642 box->x / util_format_get_blockwidth(pres->format) *
643 util_format_get_blocksize(pres->format);
644 }
645 }
646
647 static void
648 lima_transfer_flush_region(struct pipe_context *pctx,
649 struct pipe_transfer *ptrans,
650 const struct pipe_box *box)
651 {
652
653 }
654
655 static void
656 lima_transfer_unmap(struct pipe_context *pctx,
657 struct pipe_transfer *ptrans)
658 {
659 struct lima_context *ctx = lima_context(pctx);
660 struct lima_transfer *trans = lima_transfer(ptrans);
661 struct lima_resource *res = lima_resource(ptrans->resource);
662 struct lima_bo *bo = res->bo;
663 struct pipe_resource *pres;
664
665 if (trans->staging) {
666 pres = &res->base;
667 if (ptrans->usage & PIPE_TRANSFER_WRITE) {
668 unsigned i;
669 for (i = 0; i < ptrans->box.depth; i++)
670 panfrost_store_tiled_image(
671 bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->level].layer_stride,
672 trans->staging + i * ptrans->stride * ptrans->box.height,
673 &ptrans->box,
674 res->levels[ptrans->level].stride,
675 ptrans->stride,
676 util_format_get_blocksize(pres->format));
677 }
678 free(trans->staging);
679 }
680
681 pipe_resource_reference(&ptrans->resource, NULL);
682 slab_free(&ctx->transfer_pool, trans);
683 }
684
685 static void
686 lima_util_blitter_save_states(struct lima_context *ctx)
687 {
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);
701
702 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base);
703
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);
710 }
711
712 static void
713 lima_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
714 {
715 struct lima_context *ctx = lima_context(pctx);
716 struct pipe_blit_info info = *blit_info;
717
718 if (util_try_blit_via_copy_region(pctx, &info)) {
719 return; /* done */
720 }
721
722 if (info.mask & PIPE_MASK_S) {
723 debug_printf("lima: cannot blit stencil, skipping\n");
724 info.mask &= ~PIPE_MASK_S;
725 }
726
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));
731 return;
732 }
733
734 lima_util_blitter_save_states(ctx);
735
736 util_blitter_blit(ctx->blitter, &info);
737 }
738
739 static void
740 lima_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource)
741 {
742
743 }
744
745 void
746 lima_resource_context_init(struct lima_context *ctx)
747 {
748 ctx->base.create_surface = lima_surface_create;
749 ctx->base.surface_destroy = lima_surface_destroy;
750
751 /* TODO: optimize these functions to read/write data directly
752 * from/to target instead of creating a staging memory for tiled
753 * buffer indirectly
754 */
755 ctx->base.buffer_subdata = u_default_buffer_subdata;
756 ctx->base.texture_subdata = u_default_texture_subdata;
757 ctx->base.resource_copy_region = util_resource_copy_region;
758
759 ctx->base.blit = lima_blit;
760
761 ctx->base.transfer_map = lima_transfer_map;
762 ctx->base.transfer_flush_region = lima_transfer_flush_region;
763 ctx->base.transfer_unmap = lima_transfer_unmap;
764
765 ctx->base.flush_resource = lima_flush_resource;
766 }