1 /*
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 #ifndef __PAN_TEXTURE_H
29 #define __PAN_TEXTURE_H
30
31 #include "genxml/gen_macros.h"
32
33 #include <stdbool.h>
34 #include "compiler/shader_enums.h"
35 #include "drm-uapi/drm_fourcc.h"
36 #include "genxml/gen_macros.h"
37 #include "util/format/u_format.h"
38 #include "pan_format.h"
39 #include "pan_pool.h"
40 #include "pan_props.h"
41 #include "pan_util.h"
42
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46
47 #define MAX_MIP_LEVELS 17
48 #define MAX_IMAGE_PLANES 3
49
50 #define PAN_MODIFIER_COUNT 14
51 extern uint64_t pan_best_modifiers[PAN_MODIFIER_COUNT];
52
53 struct pan_image_slice_layout {
54 unsigned offset;
55
56 /* For AFBC images, the number of bytes between two rows of AFBC
57 * headers.
58 *
59 * For non-AFBC images, the number of bytes between two rows of texels.
60 * For linear images, this will equal the logical stride. For
61 * images that are compressed or interleaved, this will be greater than
62 * the logical stride.
63 */
64 unsigned row_stride;
65
66 unsigned surface_stride;
67
68 struct {
69 /* Stride in number of superblocks */
70 unsigned stride;
71
72 /* Number of superblocks */
73 unsigned nr_blocks;
74
75 /* Size of the AFBC header preceding each slice */
76 unsigned header_size;
77
78 /* Size of the AFBC body */
79 unsigned body_size;
80
81 /* Stride between AFBC headers of two consecutive surfaces.
82 * For 3D textures, this must be set to header size since
83 * AFBC headers are allocated together, for 2D arrays this
84 * should be set to size0, since AFBC headers are placed at
85 * the beginning of each layer
86 */
87 unsigned surface_stride;
88 } afbc;
89
90 /* If checksumming is enabled following the slice, what
91 * is its offset/stride? */
92 struct {
93 unsigned offset;
94 unsigned stride;
95 unsigned size;
96 } crc;
97
98 unsigned size;
99 };
100
101 struct pan_image_layout {
102 uint64_t modifier;
103 enum pipe_format format;
104 unsigned width, height, depth;
105 unsigned nr_samples;
106 enum mali_texture_dimension dim;
107 unsigned nr_slices;
108 unsigned array_size;
109 bool crc;
110
111 /* The remaining fields may be derived from the above by calling
112 * pan_image_layout_init
113 */
114
115 struct pan_image_slice_layout slices[MAX_MIP_LEVELS];
116
117 uint64_t data_size;
118 uint64_t array_stride;
119 };
120
121 struct pan_image_mem {
122 uint64_t base;
123 unsigned offset;
124 };
125
126 struct pan_image {
127 struct pan_image_mem data;
128 struct pan_image_layout layout;
129 };
130
131 struct pan_image_view {
132 /* Format, dimension and sample count of the view might differ from
133 * those of the image (2D view of a 3D image surface for instance).
134 */
135 enum pipe_format format;
136 enum mali_texture_dimension dim;
137 unsigned first_level, last_level;
138 unsigned first_layer, last_layer;
139 unsigned char swizzle[4];
140
141 /* planes 1 and 2 are NULL for single plane formats */
142 const struct pan_image *planes[MAX_IMAGE_PLANES];
143
144 /* If EXT_multisampled_render_to_texture is used, this may be
145 * greater than image->layout.nr_samples. */
146 unsigned nr_samples;
147
148 /* Only valid if dim == 1D, needed to implement buffer views */
149 struct {
150 unsigned offset;
151 unsigned size;
152 } buf;
153
154 struct {
155 unsigned narrow;
156 } astc;
157 };
158
159 static inline const struct pan_image *
pan_image_view_get_plane(const struct pan_image_view * iview,uint32_t idx)160 pan_image_view_get_plane(const struct pan_image_view *iview, uint32_t idx)
161 {
162 if (idx >= ARRAY_SIZE(iview->planes))
163 return NULL;
164
165 return iview->planes[idx];
166 }
167
168 static inline unsigned
pan_image_view_get_plane_mask(const struct pan_image_view * iview)169 pan_image_view_get_plane_mask(const struct pan_image_view *iview)
170 {
171 unsigned mask = 0;
172
173 for (unsigned i = 0; i < ARRAY_SIZE(iview->planes); i++) {
174 if (iview->planes[i])
175 mask |= BITFIELD_BIT(i);
176 }
177
178 return mask;
179 }
180
181 static inline unsigned
pan_image_view_get_first_plane_idx(const struct pan_image_view * iview)182 pan_image_view_get_first_plane_idx(const struct pan_image_view *iview)
183 {
184 unsigned mask = pan_image_view_get_plane_mask(iview);
185
186 assert(mask);
187 return ffs(mask) - 1;
188 }
189
190 static inline const struct pan_image *
pan_image_view_get_first_plane(const struct pan_image_view * iview)191 pan_image_view_get_first_plane(const struct pan_image_view *iview)
192 {
193 unsigned first_plane_idx = pan_image_view_get_first_plane_idx(iview);
194 return pan_image_view_get_plane(iview, first_plane_idx);
195 }
196
197 static inline uint32_t
pan_image_view_get_nr_samples(const struct pan_image_view * iview)198 pan_image_view_get_nr_samples(const struct pan_image_view *iview)
199 {
200 const struct pan_image *image = pan_image_view_get_first_plane(iview);
201
202 if (!image)
203 return 0;
204
205 return image->layout.nr_samples;
206 }
207
208 static inline const struct pan_image *
pan_image_view_get_color_plane(const struct pan_image_view * iview)209 pan_image_view_get_color_plane(const struct pan_image_view *iview)
210 {
211 /* We only support rendering to plane 0 */
212 assert(pan_image_view_get_plane(iview, 1) == NULL);
213 return pan_image_view_get_plane(iview, 0);
214 }
215
216 static inline bool
pan_image_view_has_crc(const struct pan_image_view * iview)217 pan_image_view_has_crc(const struct pan_image_view *iview)
218 {
219 const struct pan_image *image = pan_image_view_get_color_plane(iview);
220
221 if (!image)
222 return false;
223
224 return image->layout.crc;
225 }
226
227 static inline const struct pan_image *
pan_image_view_get_s_plane(const struct pan_image_view * iview)228 pan_image_view_get_s_plane(const struct pan_image_view *iview)
229 {
230 ASSERTED const struct util_format_description *fdesc =
231 util_format_description(iview->format);
232 assert(util_format_has_stencil(fdesc));
233
234 /* In case of multiplanar depth/stencil, the stencil is always on
235 * plane 1. Combined depth/stencil only has one plane, so depth
236 * will be on plane 0 in either case.
237 */
238 const struct pan_image *plane = iview->planes[1] ?: iview->planes[0];
239
240 assert(plane);
241 fdesc = util_format_description(plane->layout.format);
242 assert(util_format_has_stencil(fdesc));
243 return plane;
244 }
245
246 static inline const struct pan_image *
pan_image_view_get_zs_plane(const struct pan_image_view * iview)247 pan_image_view_get_zs_plane(const struct pan_image_view *iview)
248 {
249 assert(util_format_is_depth_or_stencil(iview->format));
250
251 /* Depth or combined depth-stencil is always on plane 0. */
252 return pan_image_view_get_plane(iview, 0);
253 }
254
255 unsigned panfrost_compute_checksum_size(struct pan_image_slice_layout *slice,
256 unsigned width, unsigned height);
257
258 /* AFBC format mode. The ordering is intended to match the Valhall hardware enum
259 * ("AFBC Compression Mode"), but this enum is required in software on older
260 * hardware for correct handling of texture views. Defining the enum lets us
261 * unify these code paths.
262 */
263 enum pan_afbc_mode {
264 PAN_AFBC_MODE_R8,
265 PAN_AFBC_MODE_R8G8,
266 PAN_AFBC_MODE_R5G6B5,
267 PAN_AFBC_MODE_R4G4B4A4,
268 PAN_AFBC_MODE_R5G5B5A1,
269 PAN_AFBC_MODE_R8G8B8,
270 PAN_AFBC_MODE_R8G8B8A8,
271 PAN_AFBC_MODE_R10G10B10A2,
272 PAN_AFBC_MODE_R11G11B10,
273 PAN_AFBC_MODE_S8,
274
275 /* Sentintel signalling a format that cannot be compressed */
276 PAN_AFBC_MODE_INVALID
277 };
278
279 enum pan_afbc_mode panfrost_afbc_format(unsigned arch, enum pipe_format format);
280
281 /* A format may be compressed as AFBC if it has an AFBC internal format */
282
283 static inline bool
panfrost_format_supports_afbc(unsigned arch,enum pipe_format format)284 panfrost_format_supports_afbc(unsigned arch, enum pipe_format format)
285 {
286 return panfrost_afbc_format(arch, format) != PAN_AFBC_MODE_INVALID;
287 }
288
289 #define AFBC_HEADER_BYTES_PER_TILE 16
290
291 bool panfrost_afbc_can_ytr(enum pipe_format format);
292
293 bool panfrost_afbc_can_split(unsigned arch, enum pipe_format format,
294 uint64_t modifier);
295
296 bool panfrost_afbc_can_pack(enum pipe_format format);
297
298 /*
299 * Check if a gen supports AFBC with tiled headers (and hence also solid
300 * colour blocks).
301 */
panfrost_afbc_can_tile(unsigned arch)302 static inline bool panfrost_afbc_can_tile(unsigned arch)
303 {
304 return arch >= 7;
305 }
306
307 /*
308 * Represents the block size of a single plane. For AFBC, this represents the
309 * superblock size. For u-interleaving, this represents the tile size.
310 */
311 struct pan_block_size {
312 /** Width of block */
313 unsigned width;
314
315 /** Height of blocks */
316 unsigned height;
317 };
318
319 struct pan_block_size panfrost_afbc_superblock_size(uint64_t modifier);
320
321 unsigned panfrost_afbc_superblock_width(uint64_t modifier);
322
323 unsigned panfrost_afbc_superblock_height(uint64_t modifier);
324
325 struct pan_block_size panfrost_afbc_renderblock_size(uint64_t modifier);
326
327 bool panfrost_afbc_is_wide(uint64_t modifier);
328
329 struct pan_block_size panfrost_afbc_subblock_size(uint64_t modifier);
330
331 uint32_t pan_afbc_row_stride(uint64_t modifier, uint32_t width);
332
333 uint32_t pan_afbc_stride_blocks(uint64_t modifier, uint32_t row_stride_bytes);
334
335 uint32_t pan_slice_align(uint64_t modifier);
336
337 uint32_t pan_afbc_body_align(unsigned arch, uint64_t modifier);
338
339 /* AFRC */
340
341 #define AFRC_CLUMPS_PER_TILE 64
342
343 enum pan_afrc_rate {
344 PAN_AFRC_RATE_NONE,
345 PAN_AFRC_RATE_1BPC,
346 PAN_AFRC_RATE_2BPC,
347 PAN_AFRC_RATE_3BPC,
348 PAN_AFRC_RATE_4BPC,
349 PAN_AFRC_RATE_5BPC,
350 PAN_AFRC_RATE_6BPC,
351 PAN_AFRC_RATE_7BPC,
352 PAN_AFRC_RATE_8BPC,
353 PAN_AFRC_RATE_9BPC,
354 PAN_AFRC_RATE_10BPC,
355 PAN_AFRC_RATE_11BPC,
356 PAN_AFRC_RATE_12BPC,
357 PAN_AFRC_RATE_DEFAULT = 0xF
358 };
359
360 enum pan_afrc_interchange_format {
361 PAN_AFRC_ICHANGE_FORMAT_RAW,
362 PAN_AFRC_ICHANGE_FORMAT_YUV444,
363 PAN_AFRC_ICHANGE_FORMAT_YUV422,
364 PAN_AFRC_ICHANGE_FORMAT_YUV420,
365 };
366
367 struct pan_afrc_format_info {
368 unsigned bpc : 4;
369 unsigned num_comps : 3;
370 unsigned ichange_fmt : 2;
371 unsigned num_planes : 2;
372 };
373
374 struct pan_afrc_format_info
375 panfrost_afrc_get_format_info(enum pipe_format format);
376
377 bool panfrost_format_supports_afrc(enum pipe_format format);
378
379 bool panfrost_afrc_is_scan(uint64_t modifier);
380
381 struct pan_block_size panfrost_afrc_clump_size(enum pipe_format format,
382 bool scan);
383
384 struct pan_block_size panfrost_afrc_tile_size(enum pipe_format format,
385 uint64_t modifier);
386
387 unsigned panfrost_afrc_block_size_from_modifier(uint64_t modifier);
388
389 unsigned pan_afrc_row_stride(enum pipe_format format, uint64_t modifier,
390 uint32_t width);
391
392 unsigned panfrost_afrc_query_rates(enum pipe_format format, unsigned max,
393 uint32_t *rates);
394
395 unsigned panfrost_afrc_get_modifiers(enum pipe_format format, uint32_t rate,
396 unsigned max, uint64_t *modifiers);
397
398 uint32_t panfrost_afrc_get_rate(enum pipe_format format, uint64_t modifier);
399
400 struct pan_block_size panfrost_block_size(uint64_t modifier,
401 enum pipe_format format);
402
403 struct pan_block_size panfrost_renderblock_size(uint64_t modifier,
404 enum pipe_format format);
405
406 #ifdef PAN_ARCH
407 unsigned GENX(panfrost_estimate_texture_payload_size)(
408 const struct pan_image_view *iview);
409
410 #if PAN_ARCH >= 7
411 void GENX(panfrost_texture_swizzle_replicate_x)(struct pan_image_view *iview);
412 #endif
413
414 #if PAN_ARCH == 7
415 void GENX(panfrost_texture_afbc_reswizzle)(struct pan_image_view *iview);
416 #endif
417
418 void GENX(panfrost_new_texture)(const struct pan_image_view *iview,
419 struct mali_texture_packed *out,
420 const struct panfrost_ptr *payload);
421 #endif
422
423 unsigned panfrost_get_layer_stride(const struct pan_image_layout *layout,
424 unsigned level);
425
426 unsigned panfrost_texture_offset(const struct pan_image_layout *layout,
427 unsigned level, unsigned array_idx,
428 unsigned surface_idx);
429
430 /* DRM modifier helper */
431
432 #define drm_is_afbc(mod) \
433 ((mod >> 52) == \
434 (DRM_FORMAT_MOD_ARM_TYPE_AFBC | (DRM_FORMAT_MOD_VENDOR_ARM << 4)))
435
436 #define drm_is_afrc(mod) \
437 ((mod >> 52) == \
438 (DRM_FORMAT_MOD_ARM_TYPE_AFRC | (DRM_FORMAT_MOD_VENDOR_ARM << 4)))
439
440 struct pan_image_explicit_layout {
441 unsigned offset;
442 unsigned row_stride;
443 };
444
445 bool
446 pan_image_layout_init(unsigned arch, struct pan_image_layout *layout,
447 const struct pan_image_explicit_layout *explicit_layout);
448
449 unsigned panfrost_get_legacy_stride(const struct pan_image_layout *layout,
450 unsigned level);
451
452 unsigned panfrost_from_legacy_stride(unsigned legacy_stride,
453 enum pipe_format format,
454 uint64_t modifier);
455
456 struct pan_surface {
457 union {
458 uint64_t data;
459 struct {
460 uint64_t header;
461 uint64_t body;
462 } afbc;
463 };
464 };
465
466 void pan_iview_get_surface(const struct pan_image_view *iview, unsigned level,
467 unsigned layer, unsigned sample,
468 struct pan_surface *surf);
469
470 #if PAN_ARCH >= 9
471 enum mali_afbc_compression_mode
472 GENX(pan_afbc_compression_mode)(enum pipe_format format);
473 #endif
474
475 #if PAN_ARCH >= 10
476 enum mali_afrc_format
477 GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier,
478 unsigned plane);
479 enum mali_afrc_block_size GENX(pan_afrc_block_size)(uint64_t modifier,
480 unsigned index);
481 #endif
482
483 #ifdef __cplusplus
484 } /* extern C */
485 #endif
486
487 #endif
488