blob: 8f3e4e981194d48c01f1705c1ba4c81de647c1f4 [file] [log] [blame]
Alyssa Rosenzweig5ddf7ad2020-02-18 12:07:47 -05001/*
2 * Copyright (C) 2008 VMware, Inc.
3 * Copyright (C) 2014 Broadcom
4 * Copyright (C) 2018-2019 Alyssa Rosenzweig
5 * Copyright (C) 2019-2020 Collabora, Ltd.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 */
27
28#include "util/macros.h"
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -050029#include "util/u_math.h"
Alyssa Rosenzweig5ddf7ad2020-02-18 12:07:47 -050030#include "pan_texture.h"
Boris Brezillonfefb3e92020-09-23 11:08:02 +020031#include "panfrost-quirks.h"
Alyssa Rosenzweig5ddf7ad2020-02-18 12:07:47 -050032
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -050033/* Generates a texture descriptor. Ideally, descriptors are immutable after the
34 * texture is created, so we can keep these hanging around in GPU memory in a
35 * dedicated BO and not have to worry. In practice there are some minor gotchas
36 * with this (the driver sometimes will change the format of a texture on the
37 * fly for compression) but it's fast enough to just regenerate the descriptor
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -040038 * in those cases, rather than monkeypatching at drawtime. A texture descriptor
39 * consists of a 32-byte header followed by pointers.
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -050040 */
41
Alyssa Rosenzweig348d3742020-07-20 18:03:56 -040042/* List of supported modifiers, in descending order of preference. AFBC is
43 * faster than u-interleaved tiling which is faster than linear. Within AFBC,
44 * enabling the YUV-like transform is typically a win where possible. */
45
46uint64_t pan_best_modifiers[PAN_MODIFIER_COUNT] = {
47 DRM_FORMAT_MOD_ARM_AFBC(
48 AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
49 AFBC_FORMAT_MOD_SPARSE |
50 AFBC_FORMAT_MOD_YTR),
51
52 DRM_FORMAT_MOD_ARM_AFBC(
53 AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
54 AFBC_FORMAT_MOD_SPARSE),
55
56 DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
57 DRM_FORMAT_MOD_LINEAR
58};
59
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -040060/* Map modifiers to mali_texture_layout for packing in a texture descriptor */
61
62static enum mali_texture_layout
63panfrost_modifier_to_layout(uint64_t modifier)
64{
65 if (drm_is_afbc(modifier))
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -040066 return MALI_TEXTURE_LAYOUT_AFBC;
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -040067 else if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -040068 return MALI_TEXTURE_LAYOUT_TILED;
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -040069 else if (modifier == DRM_FORMAT_MOD_LINEAR)
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -040070 return MALI_TEXTURE_LAYOUT_LINEAR;
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -040071 else
72 unreachable("Invalid modifer");
73}
74
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -050075/* Check if we need to set a custom stride by computing the "expected"
76 * stride and comparing it to what the user actually wants. Only applies
77 * to linear textures, since tiled/compressed textures have strict
78 * alignment requirements for their strides as it is */
79
80static bool
81panfrost_needs_explicit_stride(
82 struct panfrost_slice *slices,
83 uint16_t width,
84 unsigned first_level, unsigned last_level,
85 unsigned bytes_per_pixel)
86{
87 for (unsigned l = first_level; l <= last_level; ++l) {
88 unsigned actual = slices[l].stride;
89 unsigned expected = u_minify(width, l) * bytes_per_pixel;
90
91 if (actual != expected)
92 return true;
93 }
94
95 return false;
96}
97
98/* A Scalable Texture Compression (ASTC) corresponds to just a few texture type
99 * in the hardware, but in fact can be parametrized to have various widths and
100 * heights for the so-called "stretch factor". It turns out these parameters
101 * are stuffed in the bottom bits of the payload pointers. This functions
102 * computes these magic stuffing constants based on the ASTC format in use. The
103 * constant in a given dimension is 3-bits, and two are stored side-by-side for
104 * each active dimension.
105 */
106
107static unsigned
108panfrost_astc_stretch(unsigned dim)
109{
110 assert(dim >= 4 && dim <= 12);
111 return MIN2(dim, 11) - 4;
112}
113
Icecream9599446c92020-06-02 14:14:12 +1200114/* Texture addresses are tagged with information about compressed formats.
115 * AFBC uses a bit for whether the colorspace transform is enabled (RGB and
116 * RGBA only).
117 * For ASTC, this is a "stretch factor" encoding the block size. */
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500118
119static unsigned
120panfrost_compression_tag(
121 const struct util_format_description *desc,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400122 enum mali_format format, uint64_t modifier)
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500123{
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400124 if (drm_is_afbc(modifier))
125 return (modifier & AFBC_FORMAT_MOD_YTR) ? 1 : 0;
Alyssa Rosenzweigd5a9cd12020-07-10 10:17:44 -0400126 else if (format == MALI_ASTC_2D_LDR || format == MALI_ASTC_2D_HDR)
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500127 return (panfrost_astc_stretch(desc->block.height) << 3) |
128 panfrost_astc_stretch(desc->block.width);
129 else
130 return 0;
131}
132
133
134/* Cubemaps have 6 faces as "layers" in between each actual layer. We
135 * need to fix this up. TODO: logic wrong in the asserted out cases ...
136 * can they happen, perhaps from cubemap arrays? */
137
138static void
139panfrost_adjust_cube_dimensions(
140 unsigned *first_face, unsigned *last_face,
141 unsigned *first_layer, unsigned *last_layer)
142{
143 *first_face = *first_layer % 6;
144 *last_face = *last_layer % 6;
145 *first_layer /= 6;
146 *last_layer /= 6;
147
148 assert((*first_layer == *last_layer) || (*first_face == 0 && *last_face == 5));
149}
150
151/* Following the texture descriptor is a number of pointers. How many? */
152
153static unsigned
154panfrost_texture_num_elements(
155 unsigned first_level, unsigned last_level,
156 unsigned first_layer, unsigned last_layer,
Alyssa Rosenzweig60888912020-07-15 11:39:08 -0400157 unsigned nr_samples,
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500158 bool is_cube, bool manual_stride)
159{
160 unsigned first_face = 0, last_face = 0;
161
162 if (is_cube) {
163 panfrost_adjust_cube_dimensions(&first_face, &last_face,
164 &first_layer, &last_layer);
165 }
166
167 unsigned levels = 1 + last_level - first_level;
168 unsigned layers = 1 + last_layer - first_layer;
169 unsigned faces = 1 + last_face - first_face;
Alyssa Rosenzweig60888912020-07-15 11:39:08 -0400170 unsigned num_elements = levels * layers * faces * MAX2(nr_samples, 1);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500171
172 if (manual_stride)
173 num_elements *= 2;
174
175 return num_elements;
176}
177
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400178/* Conservative estimate of the size of the texture payload a priori.
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500179 * Average case, size equal to the actual size. Worst case, off by 2x (if
180 * a manual stride is not needed on a linear texture). Returned value
181 * must be greater than or equal to the actual size, so it's safe to use
182 * as an allocation amount */
183
184unsigned
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400185panfrost_estimate_texture_payload_size(
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500186 unsigned first_level, unsigned last_level,
187 unsigned first_layer, unsigned last_layer,
Alyssa Rosenzweig60888912020-07-15 11:39:08 -0400188 unsigned nr_samples,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400189 enum mali_texture_dimension dim, uint64_t modifier)
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500190{
191 /* Assume worst case */
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400192 unsigned manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500193
194 unsigned elements = panfrost_texture_num_elements(
195 first_level, last_level,
196 first_layer, last_layer,
Alyssa Rosenzweig60888912020-07-15 11:39:08 -0400197 nr_samples,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400198 dim == MALI_TEXTURE_DIMENSION_CUBE, manual_stride);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500199
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400200 return sizeof(mali_ptr) * elements;
201}
202
Alyssa Rosenzweig53637192020-10-08 18:35:17 -0400203/* If not explicitly, line stride is calculated for block-based formats as
204 * (ceil(width / block_width) * block_size). As a special case, this is left
205 * zero if there is only a single block vertically. So, we have a helper to
206 * extract the dimensions of a block-based format and use that to calculate the
207 * line stride as such.
Alyssa Rosenzweigbde19c02020-04-30 18:48:53 -0400208 */
209
210static unsigned
Alyssa Rosenzweig8bb1d612020-10-08 18:34:48 -0400211panfrost_block_dim(uint64_t modifier, bool width, unsigned plane)
212{
213 if (!drm_is_afbc(modifier)) {
214 assert(modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED);
215 return 16;
216 }
217
218 switch (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
219 case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
220 return 16;
221 case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8:
Vinson Lee85053c02020-10-15 16:14:16 -0700222 return width ? 32 : 8;
Alyssa Rosenzweig8bb1d612020-10-08 18:34:48 -0400223 case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4:
224 return width ? 64 : 4;
225 case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4:
226 return plane ? (width ? 64 : 4) : (width ? 32 : 8);
227 default:
228 unreachable("Invalid AFBC block size");
229 }
230}
231
232static unsigned
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400233panfrost_nonlinear_stride(uint64_t modifier,
Alyssa Rosenzweigf42eb332020-10-08 18:51:43 -0400234 unsigned bytes_per_block,
235 unsigned pixels_per_block,
Alyssa Rosenzweig92553b62020-06-15 12:42:40 -0400236 unsigned width,
Alyssa Rosenzweig53637192020-10-08 18:35:17 -0400237 unsigned height,
238 bool plane)
Alyssa Rosenzweigbde19c02020-04-30 18:48:53 -0400239{
Alyssa Rosenzweig53637192020-10-08 18:35:17 -0400240 unsigned block_w = panfrost_block_dim(modifier, true, plane);
241 unsigned block_h = panfrost_block_dim(modifier, false, plane);
Alyssa Rosenzweigf42eb332020-10-08 18:51:43 -0400242
243 /* Calculate block size. Ensure the division happens only at the end to
244 * avoid rounding errors if bytes per block < pixels per block */
245
246 unsigned block_size = (block_w * block_h * bytes_per_block)
247 / pixels_per_block;
Alyssa Rosenzweig53637192020-10-08 18:35:17 -0400248
249 if (height <= block_h)
250 return 0;
251 else
252 return DIV_ROUND_UP(width, block_w) * block_size;
Alyssa Rosenzweigbde19c02020-04-30 18:48:53 -0400253}
254
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400255static void
256panfrost_emit_texture_payload(
257 mali_ptr *payload,
258 const struct util_format_description *desc,
259 enum mali_format mali_format,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400260 enum mali_texture_dimension dim,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400261 uint64_t modifier,
Alyssa Rosenzweig92553b62020-06-15 12:42:40 -0400262 unsigned width, unsigned height,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400263 unsigned first_level, unsigned last_level,
264 unsigned first_layer, unsigned last_layer,
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400265 unsigned nr_samples,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400266 unsigned cube_stride,
267 bool manual_stride,
268 mali_ptr base,
269 struct panfrost_slice *slices)
270{
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400271 base |= panfrost_compression_tag(desc, mali_format, modifier);
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400272
273 /* Inject the addresses in, interleaving array indices, mip levels,
274 * cube faces, and strides in that order */
275
276 unsigned first_face = 0, last_face = 0, face_mult = 1;
277
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400278 if (dim == MALI_TEXTURE_DIMENSION_CUBE) {
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400279 face_mult = 6;
280 panfrost_adjust_cube_dimensions(&first_face, &last_face, &first_layer, &last_layer);
281 }
282
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400283 nr_samples = MAX2(nr_samples, 1);
284
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400285 unsigned idx = 0;
286
287 for (unsigned w = first_layer; w <= last_layer; ++w) {
288 for (unsigned l = first_level; l <= last_level; ++l) {
289 for (unsigned f = first_face; f <= last_face; ++f) {
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400290 for (unsigned s = 0; s < nr_samples; ++s) {
291 payload[idx++] = base + panfrost_texture_offset(
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400292 slices, dim == MALI_TEXTURE_DIMENSION_3D,
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400293 cube_stride, l, w * face_mult + f, s);
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400294
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400295 if (manual_stride) {
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400296 payload[idx++] = (modifier == DRM_FORMAT_MOD_LINEAR) ?
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400297 slices[l].stride :
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400298 panfrost_nonlinear_stride(modifier,
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400299 MAX2(desc->block.bits / 8, 1),
Alyssa Rosenzweigf42eb332020-10-08 18:51:43 -0400300 desc->block.width * desc->block.height,
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400301 u_minify(width, l),
Alyssa Rosenzweig53637192020-10-08 18:35:17 -0400302 u_minify(height, l), false);
Alyssa Rosenzweig937d3682020-06-30 16:43:47 -0400303 }
Alyssa Rosenzweigbde19c02020-04-30 18:48:53 -0400304 }
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400305 }
306 }
307 }
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500308}
309
Alyssa Rosenzweig816af262020-07-08 16:37:00 -0400310#define MALI_SWIZZLE_R001 \
Alyssa Rosenzweigcdc32762020-08-12 16:46:07 -0400311 (MALI_CHANNEL_R << 0) | \
312 (MALI_CHANNEL_0 << 3) | \
313 (MALI_CHANNEL_0 << 6) | \
314 (MALI_CHANNEL_1 << 9)
Alyssa Rosenzweig816af262020-07-08 16:37:00 -0400315
Alyssa Rosenzweig4c891482020-07-03 13:01:16 -0400316#define MALI_SWIZZLE_A001 \
Alyssa Rosenzweigcdc32762020-08-12 16:46:07 -0400317 (MALI_CHANNEL_A << 0) | \
318 (MALI_CHANNEL_0 << 3) | \
319 (MALI_CHANNEL_0 << 6) | \
320 (MALI_CHANNEL_1 << 9)
Alyssa Rosenzweig4c891482020-07-03 13:01:16 -0400321
Alyssa Rosenzweig816af262020-07-08 16:37:00 -0400322
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500323void
324panfrost_new_texture(
325 void *out,
326 uint16_t width, uint16_t height,
327 uint16_t depth, uint16_t array_size,
328 enum pipe_format format,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400329 enum mali_texture_dimension dim,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400330 uint64_t modifier,
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500331 unsigned first_level, unsigned last_level,
332 unsigned first_layer, unsigned last_layer,
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400333 unsigned nr_samples,
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500334 unsigned cube_stride,
335 unsigned swizzle,
336 mali_ptr base,
337 struct panfrost_slice *slices)
338{
339 const struct util_format_description *desc =
340 util_format_description(format);
341
342 unsigned bytes_per_pixel = util_format_get_blocksize(format);
343
Alyssa Rosenzweig861e7dc2020-05-15 18:43:41 -0400344 enum mali_format mali_format = panfrost_pipe_format_table[desc->format].hw;
345 assert(mali_format);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500346
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400347 bool manual_stride = (modifier == DRM_FORMAT_MOD_LINEAR)
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500348 && panfrost_needs_explicit_stride(slices, width,
349 first_level, last_level, bytes_per_pixel);
350
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400351 unsigned format_swizzle = (format == PIPE_FORMAT_X24S8_UINT) ?
Alyssa Rosenzweig4c891482020-07-03 13:01:16 -0400352 MALI_SWIZZLE_A001 :
Alyssa Rosenzweig816af262020-07-08 16:37:00 -0400353 (format == PIPE_FORMAT_S8_UINT) ?
354 MALI_SWIZZLE_R001 :
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400355 panfrost_translate_swizzle_4(desc->swizzle);
356
357 bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
358
359 pan_pack(out, MIDGARD_TEXTURE, cfg) {
360 cfg.width = u_minify(width, first_level);
361 cfg.height = u_minify(height, first_level);
362 cfg.depth = u_minify(depth, first_level);
363 cfg.array_size = array_size;
364 cfg.format = format_swizzle | (mali_format << 12) | (srgb << 20);
365 cfg.dimension = dim;
366 cfg.texel_ordering = panfrost_modifier_to_layout(modifier);
367 cfg.manual_stride = manual_stride;
368 cfg.levels = last_level - first_level;
369 cfg.swizzle = swizzle;
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500370 };
371
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400372 panfrost_emit_texture_payload(
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400373 (mali_ptr *) (out + MALI_MIDGARD_TEXTURE_LENGTH),
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400374 desc,
375 mali_format,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400376 dim,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400377 modifier,
Alyssa Rosenzweig92553b62020-06-15 12:42:40 -0400378 width, height,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400379 first_level, last_level,
380 first_layer, last_layer,
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400381 nr_samples,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400382 cube_stride,
383 manual_stride,
384 base,
385 slices);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500386}
387
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200388void
389panfrost_new_texture_bifrost(
Boris Brezillonfefb3e92020-09-23 11:08:02 +0200390 const struct panfrost_device *dev,
Alyssa Rosenzweigad0b32c2020-08-06 18:12:28 -0400391 struct mali_bifrost_texture_packed *out,
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200392 uint16_t width, uint16_t height,
393 uint16_t depth, uint16_t array_size,
394 enum pipe_format format,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400395 enum mali_texture_dimension dim,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400396 uint64_t modifier,
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200397 unsigned first_level, unsigned last_level,
398 unsigned first_layer, unsigned last_layer,
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400399 unsigned nr_samples,
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200400 unsigned cube_stride,
401 unsigned swizzle,
402 mali_ptr base,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400403 struct panfrost_slice *slices,
Boris Brezillon8892c9c2020-10-18 10:27:48 +0200404 const struct panfrost_ptr *payload)
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200405{
406 const struct util_format_description *desc =
407 util_format_description(format);
408
Alyssa Rosenzweig861e7dc2020-05-15 18:43:41 -0400409 enum mali_format mali_format = panfrost_pipe_format_table[desc->format].hw;
410 assert(mali_format);
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200411
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400412 panfrost_emit_texture_payload(
Boris Brezillon8892c9c2020-10-18 10:27:48 +0200413 payload->cpu,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400414 desc,
415 mali_format,
Alyssa Rosenzweigf008a632020-08-11 17:27:36 -0400416 dim,
Alyssa Rosenzweig965537df2020-07-22 10:23:50 -0400417 modifier,
Alyssa Rosenzweig92553b62020-06-15 12:42:40 -0400418 width, height,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400419 first_level, last_level,
420 first_layer, last_layer,
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400421 nr_samples,
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400422 cube_stride,
Alyssa Rosenzweigbde19c02020-04-30 18:48:53 -0400423 true, /* Stride explicit on Bifrost */
Alyssa Rosenzweiga3d29362020-04-21 16:08:07 -0400424 base,
425 slices);
426
Alyssa Rosenzweigad0b32c2020-08-06 18:12:28 -0400427 bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
428
429 pan_pack(out, BIFROST_TEXTURE, cfg) {
430 cfg.dimension = dim;
431 cfg.format = (mali_format << 12) | (srgb << 20);
Boris Brezillonfefb3e92020-09-23 11:08:02 +0200432 if (dev->quirks & HAS_SWIZZLES)
433 cfg.format |= panfrost_get_default_swizzle(desc->nr_channels);
434
Alyssa Rosenzweigad0b32c2020-08-06 18:12:28 -0400435 cfg.width = u_minify(width, first_level);
436 cfg.height = u_minify(height, first_level);
437 cfg.swizzle = swizzle;
438 cfg.texel_ordering = panfrost_modifier_to_layout(modifier);
439 cfg.levels = last_level - first_level;
Boris Brezillon8892c9c2020-10-18 10:27:48 +0200440 cfg.surfaces = payload->gpu;
Alyssa Rosenzweigad0b32c2020-08-06 18:12:28 -0400441
Alyssa Rosenzweig239e4e82020-10-06 21:46:56 -0400442 /* We specify API-level LOD clamps in the sampler descriptor
443 * and use these clamps simply for bounds checking */
444 cfg.minimum_lod = FIXED_16(0, false);
445 cfg.maximum_lod = FIXED_16(cfg.levels, false);
Alyssa Rosenzweigad0b32c2020-08-06 18:12:28 -0400446 }
Tomeu Vizosoe41894b2020-04-17 14:23:49 +0200447}
448
Alyssa Rosenzweig5ddf7ad2020-02-18 12:07:47 -0500449/* Computes sizes for checksumming, which is 8 bytes per 16x16 tile.
450 * Checksumming is believed to be a CRC variant (CRC64 based on the size?).
451 * This feature is also known as "transaction elimination". */
452
453#define CHECKSUM_TILE_WIDTH 16
454#define CHECKSUM_TILE_HEIGHT 16
455#define CHECKSUM_BYTES_PER_TILE 8
456
457unsigned
458panfrost_compute_checksum_size(
459 struct panfrost_slice *slice,
460 unsigned width,
461 unsigned height)
462{
463 unsigned aligned_width = ALIGN_POT(width, CHECKSUM_TILE_WIDTH);
464 unsigned aligned_height = ALIGN_POT(height, CHECKSUM_TILE_HEIGHT);
465
466 unsigned tile_count_x = aligned_width / CHECKSUM_TILE_WIDTH;
467 unsigned tile_count_y = aligned_height / CHECKSUM_TILE_HEIGHT;
468
469 slice->checksum_stride = tile_count_x * CHECKSUM_BYTES_PER_TILE;
470
471 return slice->checksum_stride * tile_count_y;
472}
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500473
474unsigned
475panfrost_get_layer_stride(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level)
476{
477 return is_3d ? slices[level].size0 : cube_stride;
478}
479
480/* Computes the offset into a texture at a particular level/face. Add to
481 * the base address of a texture to get the address to that level/face */
482
483unsigned
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400484panfrost_texture_offset(struct panfrost_slice *slices, bool is_3d, unsigned cube_stride, unsigned level, unsigned face, unsigned sample)
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500485{
486 unsigned layer_stride = panfrost_get_layer_stride(slices, is_3d, cube_stride, level);
Alyssa Rosenzweig41c06de2020-06-30 16:43:32 -0400487 return slices[level].offset + (face * layer_stride) + (sample * slices[level].size0);
Alyssa Rosenzweigb9295652020-02-18 14:20:16 -0500488}