1/*
2 * Copyright © 2021 Collabora Ltd.
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, sublicense,
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 next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * 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 NONINFRINGEMENT.  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#include "gen_macros.h"
25
26#include "pan_blitter.h"
27
28#include "panvk_private.h"
29
30static void
31panvk_meta_blit(struct panvk_cmd_buffer *cmdbuf,
32                const struct pan_blit_info *blitinfo)
33{
34   struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
35   struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
36   struct pan_blit_context ctx;
37   struct pan_image_view views[2] = {
38      {
39         .format = blitinfo->dst.planes[0].format,
40         .dim = MALI_TEXTURE_DIMENSION_2D,
41         .image = blitinfo->dst.planes[0].image,
42         .nr_samples = blitinfo->dst.planes[0].image->layout.nr_samples,
43         .first_level = blitinfo->dst.level,
44         .last_level = blitinfo->dst.level,
45         .swizzle = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W },
46      },
47   };
48
49   *fbinfo = (struct pan_fb_info){
50      .width = u_minify(blitinfo->dst.planes[0].image->layout.width, blitinfo->dst.level),
51      .height = u_minify(blitinfo->dst.planes[0].image->layout.height, blitinfo->dst.level),
52      .extent = {
53         .minx = MAX2(MIN2(blitinfo->dst.start.x, blitinfo->dst.end.x), 0),
54         .miny = MAX2(MIN2(blitinfo->dst.start.y, blitinfo->dst.end.y), 0),
55         .maxx = MAX2(blitinfo->dst.start.x, blitinfo->dst.end.x),
56         .maxy = MAX2(blitinfo->dst.start.y, blitinfo->dst.end.y),
57      },
58      .nr_samples = blitinfo->dst.planes[0].image->layout.nr_samples,
59   };
60
61   fbinfo->extent.maxx = MIN2(fbinfo->extent.maxx, fbinfo->width - 1);
62   fbinfo->extent.maxy = MIN2(fbinfo->extent.maxy, fbinfo->height - 1);
63
64   /* TODO: don't force preloads of dst resources if unneeded */
65
66   const struct util_format_description *fdesc =
67      util_format_description(blitinfo->dst.planes[0].image->layout.format);
68
69   if (util_format_has_depth(fdesc)) {
70      /* We want the image format here, otherwise we might lose one of the
71       * component.
72       */
73      views[0].format = blitinfo->dst.planes[0].image->layout.format;
74      fbinfo->zs.view.zs = &views[0];
75      fbinfo->zs.preload.z = true;
76      fbinfo->zs.preload.s = util_format_has_stencil(fdesc);
77   } else if (util_format_has_stencil(fdesc)) {
78      fbinfo->zs.view.s = &views[0];
79      fbinfo->zs.preload.s = true;
80   } else {
81      fbinfo->rt_count = 1;
82      fbinfo->rts[0].view = &views[0];
83      fbinfo->rts[0].preload = true;
84      cmdbuf->state.fb.crc_valid[0] = false;
85      fbinfo->rts[0].crc_valid = &cmdbuf->state.fb.crc_valid[0];
86   }
87
88   if (blitinfo->dst.planes[1].format != PIPE_FORMAT_NONE) {
89      /* TODO: don't force preloads of dst resources if unneeded */
90      views[1].format = blitinfo->dst.planes[1].format;
91      views[1].dim = MALI_TEXTURE_DIMENSION_2D;
92      views[1].image = blitinfo->dst.planes[1].image;
93      views[1].nr_samples = blitinfo->dst.planes[1].image->layout.nr_samples;
94      views[1].first_level = blitinfo->dst.level;
95      views[1].last_level = blitinfo->dst.level;
96      views[1].swizzle[0] = PIPE_SWIZZLE_X;
97      views[1].swizzle[1] = PIPE_SWIZZLE_Y;
98      views[1].swizzle[2] = PIPE_SWIZZLE_Z;
99      views[1].swizzle[3] = PIPE_SWIZZLE_W;
100      fbinfo->zs.view.s = &views[1];
101   }
102
103   panvk_per_arch(cmd_close_batch)(cmdbuf);
104
105   GENX(pan_blit_ctx_init)(pdev, blitinfo, &cmdbuf->desc_pool.base, &ctx);
106   do {
107      if (ctx.dst.cur_layer < 0)
108         continue;
109
110      struct panvk_batch *batch = panvk_cmd_open_batch(cmdbuf);
111      mali_ptr tsd, tiler;
112
113      views[0].first_layer = views[0].last_layer = ctx.dst.cur_layer;
114      views[1].first_layer = views[1].last_layer = views[0].first_layer;
115      batch->blit.src = blitinfo->src.planes[0].image->data.bo;
116      batch->blit.dst = blitinfo->dst.planes[0].image->data.bo;
117      panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true);
118      panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
119      panvk_per_arch(cmd_prepare_tiler_context)(cmdbuf);
120
121      tsd = batch->tls.gpu;
122      tiler = batch->tiler.descs.gpu;
123
124      struct panfrost_ptr job =
125         GENX(pan_blit)(&ctx, &cmdbuf->desc_pool.base, &batch->scoreboard, tsd, tiler);
126      util_dynarray_append(&batch->jobs, void *, job.cpu);
127      panvk_per_arch(cmd_close_batch)(cmdbuf);
128   } while (pan_blit_next_surface(&ctx));
129}
130
131void
132panvk_per_arch(CmdBlitImage2)(VkCommandBuffer commandBuffer,
133                              const VkBlitImageInfo2 *pBlitImageInfo)
134{
135   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
136   VK_FROM_HANDLE(panvk_image, src, pBlitImageInfo->srcImage);
137   VK_FROM_HANDLE(panvk_image, dst, pBlitImageInfo->dstImage);
138
139   for (unsigned i = 0; i < pBlitImageInfo->regionCount; i++) {
140      const VkImageBlit2 *region = &pBlitImageInfo->pRegions[i];
141      struct pan_blit_info info = {
142         .src = {
143            .planes[0].image = &src->pimage,
144            .planes[0].format = src->pimage.layout.format,
145            .level = region->srcSubresource.mipLevel,
146            .start = {
147               region->srcOffsets[0].x,
148               region->srcOffsets[0].y,
149               region->srcOffsets[0].z,
150               region->srcSubresource.baseArrayLayer,
151            },
152            .end = {
153               region->srcOffsets[1].x,
154               region->srcOffsets[1].y,
155               region->srcOffsets[1].z,
156               region->srcSubresource.baseArrayLayer + region->srcSubresource.layerCount - 1,
157            },
158         },
159         .dst = {
160            .planes[0].image = &dst->pimage,
161            .planes[0].format = dst->pimage.layout.format,
162            .level = region->dstSubresource.mipLevel,
163            .start = {
164               region->dstOffsets[0].x,
165               region->dstOffsets[0].y,
166               region->dstOffsets[0].z,
167               region->dstSubresource.baseArrayLayer,
168            },
169            .end = {
170               region->dstOffsets[1].x,
171               region->dstOffsets[1].y,
172               region->dstOffsets[1].z,
173               region->dstSubresource.baseArrayLayer + region->dstSubresource.layerCount - 1,
174            },
175         },
176         .nearest = pBlitImageInfo->filter == VK_FILTER_NEAREST,
177      };
178
179      if (region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
180         info.src.planes[0].format = util_format_stencil_only(info.src.planes[0].format);
181      else if (region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)
182         info.src.planes[0].format = util_format_get_depth_only(info.src.planes[0].format);
183
184      if (region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
185         info.dst.planes[0].format = util_format_stencil_only(info.dst.planes[0].format);
186      else if (region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT)
187         info.dst.planes[0].format = util_format_get_depth_only(info.dst.planes[0].format);
188
189      panvk_meta_blit(cmdbuf, &info);
190   }
191}
192
193void
194panvk_per_arch(CmdResolveImage2)(VkCommandBuffer commandBuffer,
195                                 const VkResolveImageInfo2* pResolveImageInfo)
196{
197   panvk_stub();
198}
199
200void
201panvk_per_arch(meta_blit_init)(struct panvk_physical_device *dev)
202{
203   panvk_pool_init(&dev->meta.blitter.bin_pool, &dev->pdev, NULL,
204                   PAN_BO_EXECUTE, 16 * 1024,
205                   "panvk_meta blitter binary pool", false);
206   panvk_pool_init(&dev->meta.blitter.desc_pool, &dev->pdev, NULL,
207                   0, 16 * 1024, "panvk_meta blitter descriptor pool",
208                   false);
209   pan_blend_shaders_init(&dev->pdev);
210   GENX(pan_blitter_init)(&dev->pdev, &dev->meta.blitter.bin_pool.base,
211                          &dev->meta.blitter.desc_pool.base);
212}
213
214void
215panvk_per_arch(meta_blit_cleanup)(struct panvk_physical_device *dev)
216{
217   GENX(pan_blitter_cleanup)(&dev->pdev);
218   pan_blend_shaders_cleanup(&dev->pdev);
219   panvk_pool_cleanup(&dev->meta.blitter.desc_pool);
220   panvk_pool_cleanup(&dev->meta.blitter.bin_pool);
221}
222