xref: /aosp_15_r20/external/mesa3d/src/panfrost/lib/pan_texture.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2008 VMware, Inc.
3*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2014 Broadcom
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2018-2019 Alyssa Rosenzweig
5*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2019-2020 Collabora, Ltd.
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
15*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
16*61046927SAndroid Build Coastguard Worker  * Software.
17*61046927SAndroid Build Coastguard Worker  *
18*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  */
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker #include "pan_texture.h"
29*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
30*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5
33*61046927SAndroid Build Coastguard Worker /*
34*61046927SAndroid Build Coastguard Worker  * Arm Scalable Texture Compression (ASTC) corresponds to just a few formats.
35*61046927SAndroid Build Coastguard Worker  * The block dimension is not part of the format. Instead, it is encoded as a
36*61046927SAndroid Build Coastguard Worker  * 6-bit tag on the payload pointer. Map the block size for a single dimension.
37*61046927SAndroid Build Coastguard Worker  */
38*61046927SAndroid Build Coastguard Worker static inline enum mali_astc_2d_dimension
panfrost_astc_dim_2d(unsigned dim)39*61046927SAndroid Build Coastguard Worker panfrost_astc_dim_2d(unsigned dim)
40*61046927SAndroid Build Coastguard Worker {
41*61046927SAndroid Build Coastguard Worker    switch (dim) {
42*61046927SAndroid Build Coastguard Worker    case 4:
43*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_4;
44*61046927SAndroid Build Coastguard Worker    case 5:
45*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_5;
46*61046927SAndroid Build Coastguard Worker    case 6:
47*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_6;
48*61046927SAndroid Build Coastguard Worker    case 8:
49*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_8;
50*61046927SAndroid Build Coastguard Worker    case 10:
51*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_10;
52*61046927SAndroid Build Coastguard Worker    case 12:
53*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_2D_DIMENSION_12;
54*61046927SAndroid Build Coastguard Worker    default:
55*61046927SAndroid Build Coastguard Worker       unreachable("Invalid ASTC dimension");
56*61046927SAndroid Build Coastguard Worker    }
57*61046927SAndroid Build Coastguard Worker }
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker static inline enum mali_astc_3d_dimension
panfrost_astc_dim_3d(unsigned dim)60*61046927SAndroid Build Coastguard Worker panfrost_astc_dim_3d(unsigned dim)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    switch (dim) {
63*61046927SAndroid Build Coastguard Worker    case 3:
64*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_3D_DIMENSION_3;
65*61046927SAndroid Build Coastguard Worker    case 4:
66*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_3D_DIMENSION_4;
67*61046927SAndroid Build Coastguard Worker    case 5:
68*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_3D_DIMENSION_5;
69*61046927SAndroid Build Coastguard Worker    case 6:
70*61046927SAndroid Build Coastguard Worker       return MALI_ASTC_3D_DIMENSION_6;
71*61046927SAndroid Build Coastguard Worker    default:
72*61046927SAndroid Build Coastguard Worker       unreachable("Invalid ASTC dimension");
73*61046927SAndroid Build Coastguard Worker    }
74*61046927SAndroid Build Coastguard Worker }
75*61046927SAndroid Build Coastguard Worker #endif
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker /* Texture addresses are tagged with information about compressed formats.
78*61046927SAndroid Build Coastguard Worker  * AFBC uses a bit for whether the colorspace transform is enabled (RGB and
79*61046927SAndroid Build Coastguard Worker  * RGBA only).
80*61046927SAndroid Build Coastguard Worker  * For ASTC, this is a "stretch factor" encoding the block size. */
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker static unsigned
panfrost_compression_tag(const struct util_format_description * desc,enum mali_texture_dimension dim,uint64_t modifier)83*61046927SAndroid Build Coastguard Worker panfrost_compression_tag(const struct util_format_description *desc,
84*61046927SAndroid Build Coastguard Worker                          enum mali_texture_dimension dim, uint64_t modifier)
85*61046927SAndroid Build Coastguard Worker {
86*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5 && PAN_ARCH <= 8
87*61046927SAndroid Build Coastguard Worker    if (drm_is_afbc(modifier)) {
88*61046927SAndroid Build Coastguard Worker       unsigned flags =
89*61046927SAndroid Build Coastguard Worker          (modifier & AFBC_FORMAT_MOD_YTR) ? MALI_AFBC_SURFACE_FLAG_YTR : 0;
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
92*61046927SAndroid Build Coastguard Worker       /* Prefetch enable */
93*61046927SAndroid Build Coastguard Worker       flags |= MALI_AFBC_SURFACE_FLAG_PREFETCH;
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker       if (panfrost_afbc_is_wide(modifier))
96*61046927SAndroid Build Coastguard Worker          flags |= MALI_AFBC_SURFACE_FLAG_WIDE_BLOCK;
97*61046927SAndroid Build Coastguard Worker #endif
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 7
100*61046927SAndroid Build Coastguard Worker       /* Tiled headers */
101*61046927SAndroid Build Coastguard Worker       if (modifier & AFBC_FORMAT_MOD_TILED)
102*61046927SAndroid Build Coastguard Worker          flags |= MALI_AFBC_SURFACE_FLAG_TILED_HEADER;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker       /* Used to make sure AFBC headers don't point outside the AFBC
105*61046927SAndroid Build Coastguard Worker        * body. HW is using the AFBC surface stride to do this check,
106*61046927SAndroid Build Coastguard Worker        * which doesn't work for 3D textures because the surface
107*61046927SAndroid Build Coastguard Worker        * stride does not cover the body. Only supported on v7+.
108*61046927SAndroid Build Coastguard Worker        */
109*61046927SAndroid Build Coastguard Worker       if (dim != MALI_TEXTURE_DIMENSION_3D)
110*61046927SAndroid Build Coastguard Worker          flags |= MALI_AFBC_SURFACE_FLAG_CHECK_PAYLOAD_RANGE;
111*61046927SAndroid Build Coastguard Worker #endif
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker       return flags;
114*61046927SAndroid Build Coastguard Worker    } else if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
115*61046927SAndroid Build Coastguard Worker       if (desc->block.depth > 1) {
116*61046927SAndroid Build Coastguard Worker          return (panfrost_astc_dim_3d(desc->block.depth) << 4) |
117*61046927SAndroid Build Coastguard Worker                 (panfrost_astc_dim_3d(desc->block.height) << 2) |
118*61046927SAndroid Build Coastguard Worker                 panfrost_astc_dim_3d(desc->block.width);
119*61046927SAndroid Build Coastguard Worker       } else {
120*61046927SAndroid Build Coastguard Worker          return (panfrost_astc_dim_2d(desc->block.height) << 3) |
121*61046927SAndroid Build Coastguard Worker                 panfrost_astc_dim_2d(desc->block.width);
122*61046927SAndroid Build Coastguard Worker       }
123*61046927SAndroid Build Coastguard Worker    }
124*61046927SAndroid Build Coastguard Worker #endif
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker    /* Tags are not otherwise used */
127*61046927SAndroid Build Coastguard Worker    return 0;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker /* Following the texture descriptor is a number of descriptors. How many? */
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker static unsigned
panfrost_texture_num_elements(const struct pan_image_view * iview)133*61046927SAndroid Build Coastguard Worker panfrost_texture_num_elements(const struct pan_image_view *iview)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker    unsigned levels = 1 + iview->last_level - iview->first_level;
136*61046927SAndroid Build Coastguard Worker    unsigned layers = 1 + iview->last_layer - iview->first_layer;
137*61046927SAndroid Build Coastguard Worker    unsigned nr_samples = pan_image_view_get_nr_samples(iview);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    return levels * layers * MAX2(nr_samples, 1);
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker /* Conservative estimate of the size of the texture payload a priori.
143*61046927SAndroid Build Coastguard Worker  * Average case, size equal to the actual size. Worst case, off by 2x (if
144*61046927SAndroid Build Coastguard Worker  * a manual stride is not needed on a linear texture). Returned value
145*61046927SAndroid Build Coastguard Worker  * must be greater than or equal to the actual size, so it's safe to use
146*61046927SAndroid Build Coastguard Worker  * as an allocation amount */
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker unsigned
GENX(panfrost_estimate_texture_payload_size)149*61046927SAndroid Build Coastguard Worker GENX(panfrost_estimate_texture_payload_size)(const struct pan_image_view *iview)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker    size_t element_size;
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
154*61046927SAndroid Build Coastguard Worker    element_size = pan_size(PLANE);
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    /* 2-plane and 3-plane YUV use two plane descriptors. */
157*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(iview->format) && iview->planes[1] != NULL)
158*61046927SAndroid Build Coastguard Worker       element_size *= 2;
159*61046927SAndroid Build Coastguard Worker #elif PAN_ARCH == 7
160*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(iview->format))
161*61046927SAndroid Build Coastguard Worker       element_size = pan_size(MULTIPLANAR_SURFACE);
162*61046927SAndroid Build Coastguard Worker    else
163*61046927SAndroid Build Coastguard Worker       element_size = pan_size(SURFACE_WITH_STRIDE);
164*61046927SAndroid Build Coastguard Worker #else
165*61046927SAndroid Build Coastguard Worker    /* Assume worst case. Overestimates on Midgard, but that's ok. */
166*61046927SAndroid Build Coastguard Worker    element_size = pan_size(SURFACE_WITH_STRIDE);
167*61046927SAndroid Build Coastguard Worker #endif
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    unsigned elements = panfrost_texture_num_elements(iview);
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    return element_size * elements;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker static void
panfrost_get_surface_strides(const struct pan_image_layout * layout,unsigned l,int32_t * row_stride,int32_t * surf_stride)175*61046927SAndroid Build Coastguard Worker panfrost_get_surface_strides(const struct pan_image_layout *layout, unsigned l,
176*61046927SAndroid Build Coastguard Worker                              int32_t *row_stride, int32_t *surf_stride)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker    const struct pan_image_slice_layout *slice = &layout->slices[l];
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    if (drm_is_afbc(layout->modifier)) {
181*61046927SAndroid Build Coastguard Worker       /* Pre v7 don't have a row stride field. This field is
182*61046927SAndroid Build Coastguard Worker        * repurposed as a Y offset which we don't use */
183*61046927SAndroid Build Coastguard Worker       *row_stride = PAN_ARCH < 7 ? 0 : slice->row_stride;
184*61046927SAndroid Build Coastguard Worker       *surf_stride = slice->afbc.surface_stride;
185*61046927SAndroid Build Coastguard Worker    } else {
186*61046927SAndroid Build Coastguard Worker       *row_stride = slice->row_stride;
187*61046927SAndroid Build Coastguard Worker       *surf_stride = slice->surface_stride;
188*61046927SAndroid Build Coastguard Worker    }
189*61046927SAndroid Build Coastguard Worker }
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker static mali_ptr
panfrost_get_surface_pointer(const struct pan_image_layout * layout,enum mali_texture_dimension dim,mali_ptr base,unsigned l,unsigned i,unsigned s)192*61046927SAndroid Build Coastguard Worker panfrost_get_surface_pointer(const struct pan_image_layout *layout,
193*61046927SAndroid Build Coastguard Worker                              enum mali_texture_dimension dim, mali_ptr base,
194*61046927SAndroid Build Coastguard Worker                              unsigned l, unsigned i, unsigned s)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    unsigned offset;
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    if (layout->dim == MALI_TEXTURE_DIMENSION_3D) {
199*61046927SAndroid Build Coastguard Worker       assert(!s);
200*61046927SAndroid Build Coastguard Worker       offset =
201*61046927SAndroid Build Coastguard Worker          layout->slices[l].offset + i * panfrost_get_layer_stride(layout, l);
202*61046927SAndroid Build Coastguard Worker    } else {
203*61046927SAndroid Build Coastguard Worker       offset = panfrost_texture_offset(layout, l, i, s);
204*61046927SAndroid Build Coastguard Worker    }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    return base + offset;
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 7
210*61046927SAndroid Build Coastguard Worker static void
panfrost_emit_surface_with_stride(mali_ptr plane,int32_t row_stride,int32_t surface_stride,void ** payload)211*61046927SAndroid Build Coastguard Worker panfrost_emit_surface_with_stride(mali_ptr plane, int32_t row_stride,
212*61046927SAndroid Build Coastguard Worker                                   int32_t surface_stride, void **payload)
213*61046927SAndroid Build Coastguard Worker {
214*61046927SAndroid Build Coastguard Worker    pan_pack(*payload, SURFACE_WITH_STRIDE, cfg) {
215*61046927SAndroid Build Coastguard Worker       cfg.pointer = plane;
216*61046927SAndroid Build Coastguard Worker       cfg.row_stride = row_stride;
217*61046927SAndroid Build Coastguard Worker       cfg.surface_stride = surface_stride;
218*61046927SAndroid Build Coastguard Worker    }
219*61046927SAndroid Build Coastguard Worker    *payload += pan_size(SURFACE_WITH_STRIDE);
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker #endif
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker #if PAN_ARCH == 7
224*61046927SAndroid Build Coastguard Worker static void
panfrost_emit_multiplanar_surface(mali_ptr planes[MAX_IMAGE_PLANES],int32_t row_strides[MAX_IMAGE_PLANES],void ** payload)225*61046927SAndroid Build Coastguard Worker panfrost_emit_multiplanar_surface(mali_ptr planes[MAX_IMAGE_PLANES],
226*61046927SAndroid Build Coastguard Worker                                   int32_t row_strides[MAX_IMAGE_PLANES],
227*61046927SAndroid Build Coastguard Worker                                   void **payload)
228*61046927SAndroid Build Coastguard Worker {
229*61046927SAndroid Build Coastguard Worker    assert(row_strides[2] == 0 || row_strides[1] == row_strides[2]);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    pan_pack(*payload, MULTIPLANAR_SURFACE, cfg) {
232*61046927SAndroid Build Coastguard Worker       cfg.plane_0_pointer = planes[0];
233*61046927SAndroid Build Coastguard Worker       cfg.plane_0_row_stride = row_strides[0];
234*61046927SAndroid Build Coastguard Worker       cfg.plane_1_2_row_stride = row_strides[1];
235*61046927SAndroid Build Coastguard Worker       cfg.plane_1_pointer = planes[1];
236*61046927SAndroid Build Coastguard Worker       cfg.plane_2_pointer = planes[2];
237*61046927SAndroid Build Coastguard Worker    }
238*61046927SAndroid Build Coastguard Worker    *payload += pan_size(MULTIPLANAR_SURFACE);
239*61046927SAndroid Build Coastguard Worker }
240*61046927SAndroid Build Coastguard Worker #endif
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker /* clang-format off */
245*61046927SAndroid Build Coastguard Worker #define CLUMP_FMT(pipe, mali) [PIPE_FORMAT_ ## pipe] = MALI_CLUMP_FORMAT_ ## mali
246*61046927SAndroid Build Coastguard Worker static enum mali_clump_format special_clump_formats[PIPE_FORMAT_COUNT] = {
247*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(X32_S8X24_UINT,  X32S8X24),
248*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(X24S8_UINT,      X24S8),
249*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(S8X24_UINT,      S8X24),
250*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(S8_UINT,         S8),
251*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(L4A4_UNORM,      L4A4),
252*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(L8A8_UNORM,      L8A8),
253*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(L8A8_UINT,       L8A8),
254*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(L8A8_SINT,       L8A8),
255*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(A8_UNORM,        A8),
256*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(A8_UINT,         A8),
257*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(A8_SINT,         A8),
258*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC1_RGB8,       ETC2_RGB8),
259*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_RGB8,       ETC2_RGB8),
260*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_SRGB8,      ETC2_RGB8),
261*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_RGB8A1,     ETC2_RGB8A1),
262*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_SRGB8A1,    ETC2_RGB8A1),
263*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_RGBA8,      ETC2_RGBA8),
264*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_SRGBA8,     ETC2_RGBA8),
265*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_R11_UNORM,  ETC2_R11_UNORM),
266*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_R11_SNORM,  ETC2_R11_SNORM),
267*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_RG11_UNORM, ETC2_RG11_UNORM),
268*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(ETC2_RG11_SNORM, ETC2_RG11_SNORM),
269*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT1_RGB,        BC1_UNORM),
270*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT1_RGBA,       BC1_UNORM),
271*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT1_SRGB,       BC1_UNORM),
272*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT1_SRGBA,      BC1_UNORM),
273*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT3_RGBA,       BC2_UNORM),
274*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT3_SRGBA,      BC2_UNORM),
275*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT5_RGBA,       BC3_UNORM),
276*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(DXT5_SRGBA,      BC3_UNORM),
277*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(RGTC1_UNORM,     BC4_UNORM),
278*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(RGTC1_SNORM,     BC4_SNORM),
279*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(RGTC2_UNORM,     BC5_UNORM),
280*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(RGTC2_SNORM,     BC5_SNORM),
281*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(BPTC_RGB_FLOAT,  BC6H_SF16),
282*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(BPTC_RGB_UFLOAT, BC6H_UF16),
283*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(BPTC_RGBA_UNORM, BC7_UNORM),
284*61046927SAndroid Build Coastguard Worker    CLUMP_FMT(BPTC_SRGBA,      BC7_UNORM),
285*61046927SAndroid Build Coastguard Worker };
286*61046927SAndroid Build Coastguard Worker #undef CLUMP_FMT
287*61046927SAndroid Build Coastguard Worker /* clang-format on */
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker static enum mali_clump_format
panfrost_clump_format(enum pipe_format format)290*61046927SAndroid Build Coastguard Worker panfrost_clump_format(enum pipe_format format)
291*61046927SAndroid Build Coastguard Worker {
292*61046927SAndroid Build Coastguard Worker    /* First, try a special clump format. Note that the 0 encoding is for a
293*61046927SAndroid Build Coastguard Worker     * raw clump format, which will never be in the special table.
294*61046927SAndroid Build Coastguard Worker     */
295*61046927SAndroid Build Coastguard Worker    if (special_clump_formats[format])
296*61046927SAndroid Build Coastguard Worker       return special_clump_formats[format];
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker    /* Else, it's a raw format. Raw formats must not be compressed. */
299*61046927SAndroid Build Coastguard Worker    assert(!util_format_is_compressed(format));
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    /* YUV-sampling has special cases */
302*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(format)) {
303*61046927SAndroid Build Coastguard Worker       switch (format) {
304*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8G8_R8B8_UNORM:
305*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_G8R8_B8R8_UNORM:
306*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8B8_R8G8_UNORM:
307*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_B8R8_G8R8_UNORM:
308*61046927SAndroid Build Coastguard Worker          return MALI_CLUMP_FORMAT_Y8_UV8_422;
309*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8_G8B8_420_UNORM:
310*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8_B8G8_420_UNORM:
311*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8_G8_B8_420_UNORM:
312*61046927SAndroid Build Coastguard Worker       case PIPE_FORMAT_R8_B8_G8_420_UNORM:
313*61046927SAndroid Build Coastguard Worker          return MALI_CLUMP_FORMAT_Y8_UV8_420;
314*61046927SAndroid Build Coastguard Worker       default:
315*61046927SAndroid Build Coastguard Worker          unreachable("unhandled clump format");
316*61046927SAndroid Build Coastguard Worker       }
317*61046927SAndroid Build Coastguard Worker    }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    /* Select the appropriate raw format. */
320*61046927SAndroid Build Coastguard Worker    switch (util_format_get_blocksize(format)) {
321*61046927SAndroid Build Coastguard Worker    case 1:
322*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW8;
323*61046927SAndroid Build Coastguard Worker    case 2:
324*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW16;
325*61046927SAndroid Build Coastguard Worker    case 3:
326*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW24;
327*61046927SAndroid Build Coastguard Worker    case 4:
328*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW32;
329*61046927SAndroid Build Coastguard Worker    case 6:
330*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW48;
331*61046927SAndroid Build Coastguard Worker    case 8:
332*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW64;
333*61046927SAndroid Build Coastguard Worker    case 12:
334*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW96;
335*61046927SAndroid Build Coastguard Worker    case 16:
336*61046927SAndroid Build Coastguard Worker       return MALI_CLUMP_FORMAT_RAW128;
337*61046927SAndroid Build Coastguard Worker    default:
338*61046927SAndroid Build Coastguard Worker       unreachable("Invalid bpp");
339*61046927SAndroid Build Coastguard Worker    }
340*61046927SAndroid Build Coastguard Worker }
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker static enum mali_afbc_superblock_size
translate_superblock_size(uint64_t modifier)343*61046927SAndroid Build Coastguard Worker translate_superblock_size(uint64_t modifier)
344*61046927SAndroid Build Coastguard Worker {
345*61046927SAndroid Build Coastguard Worker    assert(drm_is_afbc(modifier));
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    switch (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
348*61046927SAndroid Build Coastguard Worker    case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
349*61046927SAndroid Build Coastguard Worker       return MALI_AFBC_SUPERBLOCK_SIZE_16X16;
350*61046927SAndroid Build Coastguard Worker    case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8:
351*61046927SAndroid Build Coastguard Worker       return MALI_AFBC_SUPERBLOCK_SIZE_32X8;
352*61046927SAndroid Build Coastguard Worker    case AFBC_FORMAT_MOD_BLOCK_SIZE_64x4:
353*61046927SAndroid Build Coastguard Worker       return MALI_AFBC_SUPERBLOCK_SIZE_64X4;
354*61046927SAndroid Build Coastguard Worker    default:
355*61046927SAndroid Build Coastguard Worker       unreachable("Invalid superblock size");
356*61046927SAndroid Build Coastguard Worker    }
357*61046927SAndroid Build Coastguard Worker }
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker static void
panfrost_emit_plane(const struct pan_image_view * iview,int index,const struct pan_image_layout * layout,enum pipe_format format,mali_ptr pointer,unsigned level,int32_t row_stride,int32_t surface_stride,mali_ptr plane2_ptr,void ** payload)360*61046927SAndroid Build Coastguard Worker panfrost_emit_plane(const struct pan_image_view *iview, int index,
361*61046927SAndroid Build Coastguard Worker                     const struct pan_image_layout *layout,
362*61046927SAndroid Build Coastguard Worker                     enum pipe_format format, mali_ptr pointer, unsigned level,
363*61046927SAndroid Build Coastguard Worker                     int32_t row_stride, int32_t surface_stride,
364*61046927SAndroid Build Coastguard Worker                     mali_ptr plane2_ptr, void **payload)
365*61046927SAndroid Build Coastguard Worker {
366*61046927SAndroid Build Coastguard Worker    const struct util_format_description *desc =
367*61046927SAndroid Build Coastguard Worker       util_format_description(format);
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    assert(row_stride >= 0 && surface_stride >= 0 && "negative stride");
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker    bool afbc = drm_is_afbc(layout->modifier);
372*61046927SAndroid Build Coastguard Worker    bool afrc = drm_is_afrc(layout->modifier);
373*61046927SAndroid Build Coastguard Worker    // TODO: this isn't technically guaranteed to be YUV, but it is in practice.
374*61046927SAndroid Build Coastguard Worker    bool is_3_planar_yuv = desc->layout == UTIL_FORMAT_LAYOUT_PLANAR3;
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    pan_pack(*payload, PLANE, cfg) {
377*61046927SAndroid Build Coastguard Worker       cfg.pointer = pointer;
378*61046927SAndroid Build Coastguard Worker       cfg.row_stride = row_stride;
379*61046927SAndroid Build Coastguard Worker       cfg.size = layout->data_size - layout->slices[level].offset;
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker       if (is_3_planar_yuv) {
382*61046927SAndroid Build Coastguard Worker          cfg.two_plane_yuv_chroma.secondary_pointer = plane2_ptr;
383*61046927SAndroid Build Coastguard Worker       } else if (!panfrost_format_is_yuv(layout->format)) {
384*61046927SAndroid Build Coastguard Worker          cfg.slice_stride = layout->nr_samples
385*61046927SAndroid Build Coastguard Worker                                ? surface_stride
386*61046927SAndroid Build Coastguard Worker                                : panfrost_get_layer_stride(layout, level);
387*61046927SAndroid Build Coastguard Worker       }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker       if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
390*61046927SAndroid Build Coastguard Worker          assert(!afbc);
391*61046927SAndroid Build Coastguard Worker          assert(!afrc);
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker          if (desc->block.depth > 1) {
394*61046927SAndroid Build Coastguard Worker             cfg.plane_type = MALI_PLANE_TYPE_ASTC_3D;
395*61046927SAndroid Build Coastguard Worker             cfg.astc._3d.block_width = panfrost_astc_dim_3d(desc->block.width);
396*61046927SAndroid Build Coastguard Worker             cfg.astc._3d.block_height =
397*61046927SAndroid Build Coastguard Worker                panfrost_astc_dim_3d(desc->block.height);
398*61046927SAndroid Build Coastguard Worker             cfg.astc._3d.block_depth = panfrost_astc_dim_3d(desc->block.depth);
399*61046927SAndroid Build Coastguard Worker          } else {
400*61046927SAndroid Build Coastguard Worker             cfg.plane_type = MALI_PLANE_TYPE_ASTC_2D;
401*61046927SAndroid Build Coastguard Worker             cfg.astc._2d.block_width = panfrost_astc_dim_2d(desc->block.width);
402*61046927SAndroid Build Coastguard Worker             cfg.astc._2d.block_height =
403*61046927SAndroid Build Coastguard Worker                panfrost_astc_dim_2d(desc->block.height);
404*61046927SAndroid Build Coastguard Worker          }
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker          bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker          /* Mesa does not advertise _HDR formats yet */
409*61046927SAndroid Build Coastguard Worker          cfg.astc.decode_hdr = false;
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker          /* sRGB formats decode to RGBA8 sRGB, which is narrow.
412*61046927SAndroid Build Coastguard Worker           *
413*61046927SAndroid Build Coastguard Worker           * Non-sRGB formats decode to RGBA16F which is wide except if decode
414*61046927SAndroid Build Coastguard Worker           * precision is set to GL_RGBA8 for that texture.
415*61046927SAndroid Build Coastguard Worker           */
416*61046927SAndroid Build Coastguard Worker          cfg.astc.decode_wide = !srgb && !iview->astc.narrow;
417*61046927SAndroid Build Coastguard Worker       } else if (afbc) {
418*61046927SAndroid Build Coastguard Worker          cfg.plane_type = MALI_PLANE_TYPE_AFBC;
419*61046927SAndroid Build Coastguard Worker          cfg.afbc.superblock_size = translate_superblock_size(layout->modifier);
420*61046927SAndroid Build Coastguard Worker          cfg.afbc.ytr = (layout->modifier & AFBC_FORMAT_MOD_YTR);
421*61046927SAndroid Build Coastguard Worker          cfg.afbc.tiled_header = (layout->modifier & AFBC_FORMAT_MOD_TILED);
422*61046927SAndroid Build Coastguard Worker          cfg.afbc.prefetch = true;
423*61046927SAndroid Build Coastguard Worker          cfg.afbc.compression_mode = GENX(pan_afbc_compression_mode)(format);
424*61046927SAndroid Build Coastguard Worker          cfg.afbc.header_stride = layout->slices[level].afbc.header_size;
425*61046927SAndroid Build Coastguard Worker       } else if (afrc) {
426*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 10
427*61046927SAndroid Build Coastguard Worker          struct pan_afrc_format_info finfo =
428*61046927SAndroid Build Coastguard Worker             panfrost_afrc_get_format_info(format);
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker          cfg.plane_type = MALI_PLANE_TYPE_AFRC;
431*61046927SAndroid Build Coastguard Worker          cfg.afrc.block_size =
432*61046927SAndroid Build Coastguard Worker             GENX(pan_afrc_block_size)(layout->modifier, index);
433*61046927SAndroid Build Coastguard Worker          cfg.afrc.format =
434*61046927SAndroid Build Coastguard Worker             GENX(pan_afrc_format)(finfo, layout->modifier, index);
435*61046927SAndroid Build Coastguard Worker #endif
436*61046927SAndroid Build Coastguard Worker       } else {
437*61046927SAndroid Build Coastguard Worker          cfg.plane_type = is_3_planar_yuv ? MALI_PLANE_TYPE_CHROMA_2P
438*61046927SAndroid Build Coastguard Worker                                           : MALI_PLANE_TYPE_GENERIC;
439*61046927SAndroid Build Coastguard Worker          cfg.clump_format = panfrost_clump_format(format);
440*61046927SAndroid Build Coastguard Worker       }
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker       if (!afbc && !afrc) {
443*61046927SAndroid Build Coastguard Worker          if (layout->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
444*61046927SAndroid Build Coastguard Worker             cfg.clump_ordering = MALI_CLUMP_ORDERING_TILED_U_INTERLEAVED;
445*61046927SAndroid Build Coastguard Worker          else
446*61046927SAndroid Build Coastguard Worker             cfg.clump_ordering = MALI_CLUMP_ORDERING_LINEAR;
447*61046927SAndroid Build Coastguard Worker       }
448*61046927SAndroid Build Coastguard Worker    }
449*61046927SAndroid Build Coastguard Worker    *payload += pan_size(PLANE);
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker #endif
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker static void
panfrost_emit_surface(const struct pan_image_view * iview,unsigned level,unsigned index,unsigned sample,enum pipe_format format,void ** payload)454*61046927SAndroid Build Coastguard Worker panfrost_emit_surface(const struct pan_image_view *iview, unsigned level,
455*61046927SAndroid Build Coastguard Worker                       unsigned index, unsigned sample,
456*61046927SAndroid Build Coastguard Worker                       enum pipe_format format, void **payload)
457*61046927SAndroid Build Coastguard Worker {
458*61046927SAndroid Build Coastguard Worker    ASSERTED const struct util_format_description *desc =
459*61046927SAndroid Build Coastguard Worker       util_format_description(format);
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    const struct pan_image_layout *layouts[MAX_IMAGE_PLANES] = {0};
462*61046927SAndroid Build Coastguard Worker    mali_ptr plane_ptrs[MAX_IMAGE_PLANES] = {0};
463*61046927SAndroid Build Coastguard Worker    int32_t row_strides[MAX_IMAGE_PLANES] = {0};
464*61046927SAndroid Build Coastguard Worker    int32_t surface_strides[MAX_IMAGE_PLANES] = {0};
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < MAX_IMAGE_PLANES; i++) {
467*61046927SAndroid Build Coastguard Worker       const struct pan_image *base_image = pan_image_view_get_plane(iview, i);
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker       if (!base_image) {
470*61046927SAndroid Build Coastguard Worker          /* Every texture should have at least one plane. */
471*61046927SAndroid Build Coastguard Worker          assert(i > 0);
472*61046927SAndroid Build Coastguard Worker          break;
473*61046927SAndroid Build Coastguard Worker       }
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker       mali_ptr base = base_image->data.base + base_image->data.offset;
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker       if (iview->buf.size) {
478*61046927SAndroid Build Coastguard Worker          assert(iview->dim == MALI_TEXTURE_DIMENSION_1D);
479*61046927SAndroid Build Coastguard Worker          base += iview->buf.offset;
480*61046927SAndroid Build Coastguard Worker       }
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker       layouts[i] = &pan_image_view_get_plane(iview, i)->layout;
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker       /* v4 does not support compression */
485*61046927SAndroid Build Coastguard Worker       assert(PAN_ARCH >= 5 || !drm_is_afbc(layouts[i]->modifier));
486*61046927SAndroid Build Coastguard Worker       assert(PAN_ARCH >= 5 || desc->layout != UTIL_FORMAT_LAYOUT_ASTC);
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker       /* panfrost_compression_tag() wants the dimension of the resource, not the
489*61046927SAndroid Build Coastguard Worker        * one of the image view (those might differ).
490*61046927SAndroid Build Coastguard Worker        */
491*61046927SAndroid Build Coastguard Worker       unsigned tag =
492*61046927SAndroid Build Coastguard Worker          panfrost_compression_tag(desc, layouts[i]->dim, layouts[i]->modifier);
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker       plane_ptrs[i] = panfrost_get_surface_pointer(
495*61046927SAndroid Build Coastguard Worker          layouts[i], iview->dim, base | tag, level, index, sample);
496*61046927SAndroid Build Coastguard Worker       panfrost_get_surface_strides(layouts[i], level, &row_strides[i],
497*61046927SAndroid Build Coastguard Worker                                    &surface_strides[i]);
498*61046927SAndroid Build Coastguard Worker    }
499*61046927SAndroid Build Coastguard Worker 
500*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
501*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(format)) {
502*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < MAX_IMAGE_PLANES; i++) {
503*61046927SAndroid Build Coastguard Worker          /* 3-plane YUV is submitted using two PLANE descriptors, where the
504*61046927SAndroid Build Coastguard Worker           * second one is of type CHROMA_2P */
505*61046927SAndroid Build Coastguard Worker          if (i > 1)
506*61046927SAndroid Build Coastguard Worker             break;
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker          if (plane_ptrs[i] == 0)
509*61046927SAndroid Build Coastguard Worker             break;
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker          /* 3-plane YUV requires equal stride for both chroma planes */
512*61046927SAndroid Build Coastguard Worker          assert(row_strides[2] == 0 || row_strides[1] == row_strides[2]);
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker          panfrost_emit_plane(iview, i, layouts[i], format, plane_ptrs[i], level,
515*61046927SAndroid Build Coastguard Worker                              row_strides[i], surface_strides[i], plane_ptrs[2],
516*61046927SAndroid Build Coastguard Worker                              payload);
517*61046927SAndroid Build Coastguard Worker       }
518*61046927SAndroid Build Coastguard Worker    } else {
519*61046927SAndroid Build Coastguard Worker       panfrost_emit_plane(iview, 0, layouts[0], format, plane_ptrs[0], level,
520*61046927SAndroid Build Coastguard Worker                           row_strides[0], surface_strides[0], 0, payload);
521*61046927SAndroid Build Coastguard Worker    }
522*61046927SAndroid Build Coastguard Worker    return;
523*61046927SAndroid Build Coastguard Worker #endif
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 7
526*61046927SAndroid Build Coastguard Worker #if PAN_ARCH == 7
527*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(format)) {
528*61046927SAndroid Build Coastguard Worker       panfrost_emit_multiplanar_surface(plane_ptrs, row_strides, payload);
529*61046927SAndroid Build Coastguard Worker       return;
530*61046927SAndroid Build Coastguard Worker    }
531*61046927SAndroid Build Coastguard Worker #endif
532*61046927SAndroid Build Coastguard Worker    panfrost_emit_surface_with_stride(plane_ptrs[0], row_strides[0],
533*61046927SAndroid Build Coastguard Worker                                      surface_strides[0], payload);
534*61046927SAndroid Build Coastguard Worker #endif
535*61046927SAndroid Build Coastguard Worker }
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker static void
panfrost_emit_texture_payload(const struct pan_image_view * iview,enum pipe_format format,void * payload)538*61046927SAndroid Build Coastguard Worker panfrost_emit_texture_payload(const struct pan_image_view *iview,
539*61046927SAndroid Build Coastguard Worker                               enum pipe_format format, void *payload)
540*61046927SAndroid Build Coastguard Worker {
541*61046927SAndroid Build Coastguard Worker    unsigned nr_samples =
542*61046927SAndroid Build Coastguard Worker       PAN_ARCH <= 7 ? pan_image_view_get_nr_samples(iview) : 1;
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker    /* Inject the addresses in, interleaving array indices, mip levels,
545*61046927SAndroid Build Coastguard Worker     * cube faces, and strides in that order. On Bifrost and older, each
546*61046927SAndroid Build Coastguard Worker     * sample had its own surface descriptor; on Valhall, they are fused
547*61046927SAndroid Build Coastguard Worker     * into a single plane descriptor.
548*61046927SAndroid Build Coastguard Worker     */
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 7
551*61046927SAndroid Build Coastguard Worker    /* V7 and later treats faces as extra layers */
552*61046927SAndroid Build Coastguard Worker    for (int layer = iview->first_layer; layer <= iview->last_layer; ++layer) {
553*61046927SAndroid Build Coastguard Worker       for (int sample = 0; sample < nr_samples; ++sample) {
554*61046927SAndroid Build Coastguard Worker          for (int level = iview->first_level; level <= iview->last_level; ++level) {
555*61046927SAndroid Build Coastguard Worker             panfrost_emit_surface(iview, level, layer, sample,
556*61046927SAndroid Build Coastguard Worker                                   format, &payload);
557*61046927SAndroid Build Coastguard Worker          }
558*61046927SAndroid Build Coastguard Worker       }
559*61046927SAndroid Build Coastguard Worker    }
560*61046927SAndroid Build Coastguard Worker #else
561*61046927SAndroid Build Coastguard Worker    unsigned first_layer = iview->first_layer, last_layer = iview->last_layer;
562*61046927SAndroid Build Coastguard Worker    unsigned face_count = 1;
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    if (iview->dim == MALI_TEXTURE_DIMENSION_CUBE) {
565*61046927SAndroid Build Coastguard Worker       first_layer /= 6;
566*61046927SAndroid Build Coastguard Worker       last_layer /= 6;
567*61046927SAndroid Build Coastguard Worker       face_count = 6;
568*61046927SAndroid Build Coastguard Worker    }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker    /* V6 and earlier has a different memory-layout */
571*61046927SAndroid Build Coastguard Worker    for (int layer = first_layer; layer <= last_layer; ++layer) {
572*61046927SAndroid Build Coastguard Worker       for (int level = iview->first_level; level <= iview->last_level; ++level) {
573*61046927SAndroid Build Coastguard Worker          /* order of face and sample doesn't matter; we can only have multiple
574*61046927SAndroid Build Coastguard Worker           * of one or the other (no support for multisampled cubemaps)
575*61046927SAndroid Build Coastguard Worker           */
576*61046927SAndroid Build Coastguard Worker          for (int face = 0; face < face_count; ++face) {
577*61046927SAndroid Build Coastguard Worker             for (int sample = 0; sample < nr_samples; ++sample) {
578*61046927SAndroid Build Coastguard Worker                panfrost_emit_surface(iview, level, (face_count * layer) + face,
579*61046927SAndroid Build Coastguard Worker                                      sample, format, &payload);
580*61046927SAndroid Build Coastguard Worker             }
581*61046927SAndroid Build Coastguard Worker          }
582*61046927SAndroid Build Coastguard Worker       }
583*61046927SAndroid Build Coastguard Worker    }
584*61046927SAndroid Build Coastguard Worker #endif
585*61046927SAndroid Build Coastguard Worker }
586*61046927SAndroid Build Coastguard Worker 
587*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 7
588*61046927SAndroid Build Coastguard Worker /* Map modifiers to mali_texture_layout for packing in a texture descriptor */
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker static enum mali_texture_layout
panfrost_modifier_to_layout(uint64_t modifier)591*61046927SAndroid Build Coastguard Worker panfrost_modifier_to_layout(uint64_t modifier)
592*61046927SAndroid Build Coastguard Worker {
593*61046927SAndroid Build Coastguard Worker    if (drm_is_afbc(modifier))
594*61046927SAndroid Build Coastguard Worker       return MALI_TEXTURE_LAYOUT_AFBC;
595*61046927SAndroid Build Coastguard Worker    else if (modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
596*61046927SAndroid Build Coastguard Worker       return MALI_TEXTURE_LAYOUT_TILED;
597*61046927SAndroid Build Coastguard Worker    else if (modifier == DRM_FORMAT_MOD_LINEAR)
598*61046927SAndroid Build Coastguard Worker       return MALI_TEXTURE_LAYOUT_LINEAR;
599*61046927SAndroid Build Coastguard Worker    else
600*61046927SAndroid Build Coastguard Worker       unreachable("Invalid modifer");
601*61046927SAndroid Build Coastguard Worker }
602*61046927SAndroid Build Coastguard Worker #endif
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker /*
605*61046927SAndroid Build Coastguard Worker  * Generates a texture descriptor. Ideally, descriptors are immutable after the
606*61046927SAndroid Build Coastguard Worker  * texture is created, so we can keep these hanging around in GPU memory in a
607*61046927SAndroid Build Coastguard Worker  * dedicated BO and not have to worry. In practice there are some minor gotchas
608*61046927SAndroid Build Coastguard Worker  * with this (the driver sometimes will change the format of a texture on the
609*61046927SAndroid Build Coastguard Worker  * fly for compression) but it's fast enough to just regenerate the descriptor
610*61046927SAndroid Build Coastguard Worker  * in those cases, rather than monkeypatching at drawtime. A texture descriptor
611*61046927SAndroid Build Coastguard Worker  * consists of a 32-byte header followed by pointers.
612*61046927SAndroid Build Coastguard Worker  */
613*61046927SAndroid Build Coastguard Worker void
GENX(panfrost_new_texture)614*61046927SAndroid Build Coastguard Worker GENX(panfrost_new_texture)(const struct pan_image_view *iview, void *out,
615*61046927SAndroid Build Coastguard Worker                            const struct panfrost_ptr *payload)
616*61046927SAndroid Build Coastguard Worker {
617*61046927SAndroid Build Coastguard Worker    const struct pan_image *base_image = pan_image_view_get_plane(iview, 0);
618*61046927SAndroid Build Coastguard Worker    const struct pan_image_layout *layout = &base_image->layout;
619*61046927SAndroid Build Coastguard Worker    enum pipe_format format = iview->format;
620*61046927SAndroid Build Coastguard Worker    const struct util_format_description *desc = util_format_description(format);
621*61046927SAndroid Build Coastguard Worker    uint32_t mali_format = GENX(panfrost_format_from_pipe_format)(format)->hw;
622*61046927SAndroid Build Coastguard Worker    unsigned char swizzle[4];
623*61046927SAndroid Build Coastguard Worker 
624*61046927SAndroid Build Coastguard Worker    if (desc->layout == UTIL_FORMAT_LAYOUT_ASTC && iview->astc.narrow &&
625*61046927SAndroid Build Coastguard Worker        desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
626*61046927SAndroid Build Coastguard Worker       mali_format = MALI_PACK_FMT(RGBA8_UNORM, RGBA, L);
627*61046927SAndroid Build Coastguard Worker    }
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    if (PAN_ARCH >= 7 && util_format_is_depth_or_stencil(format)) {
630*61046927SAndroid Build Coastguard Worker       /* v7+ doesn't have an _RRRR component order, combine the
631*61046927SAndroid Build Coastguard Worker        * user swizzle with a .XXXX swizzle to emulate that.
632*61046927SAndroid Build Coastguard Worker        */
633*61046927SAndroid Build Coastguard Worker       static const unsigned char replicate_x[4] = {
634*61046927SAndroid Build Coastguard Worker          PIPE_SWIZZLE_X,
635*61046927SAndroid Build Coastguard Worker          PIPE_SWIZZLE_X,
636*61046927SAndroid Build Coastguard Worker          PIPE_SWIZZLE_X,
637*61046927SAndroid Build Coastguard Worker          PIPE_SWIZZLE_X,
638*61046927SAndroid Build Coastguard Worker       };
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker       util_format_compose_swizzles(replicate_x, iview->swizzle, swizzle);
641*61046927SAndroid Build Coastguard Worker    } else if ((PAN_ARCH == 7 || PAN_ARCH == 10) &&
642*61046927SAndroid Build Coastguard Worker               !panfrost_format_is_yuv(format)) {
643*61046927SAndroid Build Coastguard Worker #if PAN_ARCH == 7 || PAN_ARCH >= 10
644*61046927SAndroid Build Coastguard Worker       /* v7 (only) restricts component orders when AFBC is in use.
645*61046927SAndroid Build Coastguard Worker        * Rather than restrict AFBC, we use an allowed component order
646*61046927SAndroid Build Coastguard Worker        * with an invertible swizzle composed.
647*61046927SAndroid Build Coastguard Worker        * v10 has the same restriction, but on AFRC formats.
648*61046927SAndroid Build Coastguard Worker        */
649*61046927SAndroid Build Coastguard Worker       enum mali_rgb_component_order orig = mali_format & BITFIELD_MASK(12);
650*61046927SAndroid Build Coastguard Worker       struct pan_decomposed_swizzle decomposed =
651*61046927SAndroid Build Coastguard Worker          GENX(pan_decompose_swizzle)(orig);
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker       /* Apply the new component order */
654*61046927SAndroid Build Coastguard Worker       mali_format = (mali_format & ~orig) | decomposed.pre;
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker       /* Compose the new swizzle */
657*61046927SAndroid Build Coastguard Worker       util_format_compose_swizzles(decomposed.post, iview->swizzle, swizzle);
658*61046927SAndroid Build Coastguard Worker #endif
659*61046927SAndroid Build Coastguard Worker    } else {
660*61046927SAndroid Build Coastguard Worker       STATIC_ASSERT(sizeof(swizzle) == sizeof(iview->swizzle));
661*61046927SAndroid Build Coastguard Worker       memcpy(swizzle, iview->swizzle, sizeof(swizzle));
662*61046927SAndroid Build Coastguard Worker    }
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker    panfrost_emit_texture_payload(iview, format, payload->cpu);
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker    unsigned array_size = iview->last_layer - iview->first_layer + 1;
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker    /* If this is a cubemap, we expect the number of layers to be a multiple
669*61046927SAndroid Build Coastguard Worker     * of 6.
670*61046927SAndroid Build Coastguard Worker     */
671*61046927SAndroid Build Coastguard Worker    if (iview->dim == MALI_TEXTURE_DIMENSION_CUBE) {
672*61046927SAndroid Build Coastguard Worker       assert(array_size % 6 == 0);
673*61046927SAndroid Build Coastguard Worker       array_size /= 6;
674*61046927SAndroid Build Coastguard Worker    }
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker    /* Multiplanar YUV textures require 2 surface descriptors. */
677*61046927SAndroid Build Coastguard Worker    if (panfrost_format_is_yuv(iview->format) && PAN_ARCH >= 9 &&
678*61046927SAndroid Build Coastguard Worker        pan_image_view_get_plane(iview, 1) != NULL)
679*61046927SAndroid Build Coastguard Worker       array_size *= 2;
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker    unsigned width, height, depth;
682*61046927SAndroid Build Coastguard Worker 
683*61046927SAndroid Build Coastguard Worker    if (iview->buf.size) {
684*61046927SAndroid Build Coastguard Worker       assert(iview->dim == MALI_TEXTURE_DIMENSION_1D);
685*61046927SAndroid Build Coastguard Worker       assert(!iview->first_level && !iview->last_level);
686*61046927SAndroid Build Coastguard Worker       assert(!iview->first_layer && !iview->last_layer);
687*61046927SAndroid Build Coastguard Worker       assert(layout->nr_samples == 1);
688*61046927SAndroid Build Coastguard Worker       assert(layout->height == 1 && layout->depth == 1);
689*61046927SAndroid Build Coastguard Worker       assert(iview->buf.offset + iview->buf.size <= layout->width);
690*61046927SAndroid Build Coastguard Worker       width = iview->buf.size;
691*61046927SAndroid Build Coastguard Worker       height = 1;
692*61046927SAndroid Build Coastguard Worker       depth = 1;
693*61046927SAndroid Build Coastguard Worker    } else {
694*61046927SAndroid Build Coastguard Worker       width = u_minify(layout->width, iview->first_level);
695*61046927SAndroid Build Coastguard Worker       height = u_minify(layout->height, iview->first_level);
696*61046927SAndroid Build Coastguard Worker       depth = u_minify(layout->depth, iview->first_level);
697*61046927SAndroid Build Coastguard Worker       if (util_format_is_compressed(layout->format) &&
698*61046927SAndroid Build Coastguard Worker           !util_format_is_compressed(format)) {
699*61046927SAndroid Build Coastguard Worker          width =
700*61046927SAndroid Build Coastguard Worker             DIV_ROUND_UP(width, util_format_get_blockwidth(layout->format));
701*61046927SAndroid Build Coastguard Worker          height =
702*61046927SAndroid Build Coastguard Worker             DIV_ROUND_UP(height, util_format_get_blockheight(layout->format));
703*61046927SAndroid Build Coastguard Worker          depth =
704*61046927SAndroid Build Coastguard Worker             DIV_ROUND_UP(depth, util_format_get_blockdepth(layout->format));
705*61046927SAndroid Build Coastguard Worker          assert(util_format_get_blockwidth(format) == 1);
706*61046927SAndroid Build Coastguard Worker          assert(util_format_get_blockheight(format) == 1);
707*61046927SAndroid Build Coastguard Worker          assert(util_format_get_blockheight(format) == 1);
708*61046927SAndroid Build Coastguard Worker          assert(iview->last_level == iview->first_level);
709*61046927SAndroid Build Coastguard Worker       }
710*61046927SAndroid Build Coastguard Worker    }
711*61046927SAndroid Build Coastguard Worker 
712*61046927SAndroid Build Coastguard Worker    pan_pack(out, TEXTURE, cfg) {
713*61046927SAndroid Build Coastguard Worker       cfg.dimension = iview->dim;
714*61046927SAndroid Build Coastguard Worker       cfg.format = mali_format;
715*61046927SAndroid Build Coastguard Worker       cfg.width = width;
716*61046927SAndroid Build Coastguard Worker       cfg.height = height;
717*61046927SAndroid Build Coastguard Worker       if (iview->dim == MALI_TEXTURE_DIMENSION_3D)
718*61046927SAndroid Build Coastguard Worker          cfg.depth = depth;
719*61046927SAndroid Build Coastguard Worker       else
720*61046927SAndroid Build Coastguard Worker          cfg.sample_count = layout->nr_samples;
721*61046927SAndroid Build Coastguard Worker       cfg.swizzle = panfrost_translate_swizzle_4(swizzle);
722*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
723*61046927SAndroid Build Coastguard Worker       cfg.texel_interleave = (layout->modifier != DRM_FORMAT_MOD_LINEAR) ||
724*61046927SAndroid Build Coastguard Worker                              util_format_is_compressed(format);
725*61046927SAndroid Build Coastguard Worker #else
726*61046927SAndroid Build Coastguard Worker       cfg.texel_ordering = panfrost_modifier_to_layout(layout->modifier);
727*61046927SAndroid Build Coastguard Worker #endif
728*61046927SAndroid Build Coastguard Worker       cfg.levels = iview->last_level - iview->first_level + 1;
729*61046927SAndroid Build Coastguard Worker       cfg.array_size = array_size;
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
732*61046927SAndroid Build Coastguard Worker       cfg.surfaces = payload->gpu;
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker       /* We specify API-level LOD clamps in the sampler descriptor
735*61046927SAndroid Build Coastguard Worker        * and use these clamps simply for bounds checking.
736*61046927SAndroid Build Coastguard Worker        */
737*61046927SAndroid Build Coastguard Worker       cfg.minimum_lod = 0;
738*61046927SAndroid Build Coastguard Worker       cfg.maximum_lod = cfg.levels - 1;
739*61046927SAndroid Build Coastguard Worker #endif
740*61046927SAndroid Build Coastguard Worker    }
741*61046927SAndroid Build Coastguard Worker }
742*61046927SAndroid Build Coastguard Worker 
743*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
744*61046927SAndroid Build Coastguard Worker enum mali_afbc_compression_mode
GENX(pan_afbc_compression_mode)745*61046927SAndroid Build Coastguard Worker GENX(pan_afbc_compression_mode)(enum pipe_format format)
746*61046927SAndroid Build Coastguard Worker {
747*61046927SAndroid Build Coastguard Worker    /* There's a special case for texturing the stencil part from a combined
748*61046927SAndroid Build Coastguard Worker     * depth/stencil texture, handle it separately.
749*61046927SAndroid Build Coastguard Worker     */
750*61046927SAndroid Build Coastguard Worker    if (format == PIPE_FORMAT_X24S8_UINT)
751*61046927SAndroid Build Coastguard Worker       return MALI_AFBC_COMPRESSION_MODE_X24S8;
752*61046927SAndroid Build Coastguard Worker 
753*61046927SAndroid Build Coastguard Worker    /* Otherwise, map canonical formats to the hardware enum. This only
754*61046927SAndroid Build Coastguard Worker     * needs to handle the subset of formats returned by
755*61046927SAndroid Build Coastguard Worker     * panfrost_afbc_format.
756*61046927SAndroid Build Coastguard Worker     */
757*61046927SAndroid Build Coastguard Worker    /* clang-format off */
758*61046927SAndroid Build Coastguard Worker    switch (panfrost_afbc_format(PAN_ARCH, format)) {
759*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R8:          return MALI_AFBC_COMPRESSION_MODE_R8;
760*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R8G8:        return MALI_AFBC_COMPRESSION_MODE_R8G8;
761*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R5G6B5:      return MALI_AFBC_COMPRESSION_MODE_R5G6B5;
762*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R4G4B4A4:    return MALI_AFBC_COMPRESSION_MODE_R4G4B4A4;
763*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R5G5B5A1:    return MALI_AFBC_COMPRESSION_MODE_R5G5B5A1;
764*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R8G8B8:      return MALI_AFBC_COMPRESSION_MODE_R8G8B8;
765*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R8G8B8A8:    return MALI_AFBC_COMPRESSION_MODE_R8G8B8A8;
766*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R10G10B10A2: return MALI_AFBC_COMPRESSION_MODE_R10G10B10A2;
767*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_R11G11B10:   return MALI_AFBC_COMPRESSION_MODE_R11G11B10;
768*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_S8:          return MALI_AFBC_COMPRESSION_MODE_S8;
769*61046927SAndroid Build Coastguard Worker    case PAN_AFBC_MODE_INVALID:     unreachable("Invalid AFBC format");
770*61046927SAndroid Build Coastguard Worker    }
771*61046927SAndroid Build Coastguard Worker    /* clang-format on */
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker    unreachable("all AFBC formats handled");
774*61046927SAndroid Build Coastguard Worker }
775*61046927SAndroid Build Coastguard Worker #endif
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 10
778*61046927SAndroid Build Coastguard Worker enum mali_afrc_format
GENX(pan_afrc_format)779*61046927SAndroid Build Coastguard Worker GENX(pan_afrc_format)(struct pan_afrc_format_info info, uint64_t modifier,
780*61046927SAndroid Build Coastguard Worker                       unsigned plane)
781*61046927SAndroid Build Coastguard Worker {
782*61046927SAndroid Build Coastguard Worker    bool scan = panfrost_afrc_is_scan(modifier);
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker    assert(info.bpc == 8 || info.bpc == 10);
785*61046927SAndroid Build Coastguard Worker    assert(info.num_comps > 0 && info.num_comps <= 4);
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker    switch (info.ichange_fmt) {
788*61046927SAndroid Build Coastguard Worker    case PAN_AFRC_ICHANGE_FORMAT_RAW:
789*61046927SAndroid Build Coastguard Worker       assert(plane == 0);
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker       if (info.bpc == 8)
792*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R8_SCAN : MALI_AFRC_FORMAT_R8_ROT) +
793*61046927SAndroid Build Coastguard Worker                 (info.num_comps - 1);
794*61046927SAndroid Build Coastguard Worker 
795*61046927SAndroid Build Coastguard Worker       assert(info.num_comps == 4);
796*61046927SAndroid Build Coastguard Worker       return (scan ? MALI_AFRC_FORMAT_R10G10B10A10_SCAN
797*61046927SAndroid Build Coastguard Worker                    : MALI_AFRC_FORMAT_R10G10B10A10_ROT);
798*61046927SAndroid Build Coastguard Worker 
799*61046927SAndroid Build Coastguard Worker    case PAN_AFRC_ICHANGE_FORMAT_YUV444:
800*61046927SAndroid Build Coastguard Worker       if (info.bpc == 8) {
801*61046927SAndroid Build Coastguard Worker          if (plane == 0 || info.num_planes == 3)
802*61046927SAndroid Build Coastguard Worker             return (scan ? MALI_AFRC_FORMAT_R8_444_SCAN
803*61046927SAndroid Build Coastguard Worker                          : MALI_AFRC_FORMAT_R8_444_ROT);
804*61046927SAndroid Build Coastguard Worker 
805*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R8G8_444_SCAN
806*61046927SAndroid Build Coastguard Worker                       : MALI_AFRC_FORMAT_R8G8_444_ROT);
807*61046927SAndroid Build Coastguard Worker       }
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker       assert(info.num_planes == 3);
810*61046927SAndroid Build Coastguard Worker       return (scan ? MALI_AFRC_FORMAT_R10_444_SCAN
811*61046927SAndroid Build Coastguard Worker                    : MALI_AFRC_FORMAT_R10_444_ROT);
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker    case PAN_AFRC_ICHANGE_FORMAT_YUV422:
814*61046927SAndroid Build Coastguard Worker       if (info.bpc == 8) {
815*61046927SAndroid Build Coastguard Worker          if (plane == 0 || info.num_planes == 3)
816*61046927SAndroid Build Coastguard Worker             return (scan ? MALI_AFRC_FORMAT_R8_422_SCAN
817*61046927SAndroid Build Coastguard Worker                          : MALI_AFRC_FORMAT_R8_422_ROT);
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R8G8_422_SCAN
820*61046927SAndroid Build Coastguard Worker                       : MALI_AFRC_FORMAT_R8G8_422_ROT);
821*61046927SAndroid Build Coastguard Worker       }
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker       if (plane == 0 || info.num_planes == 3)
824*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R10_422_SCAN
825*61046927SAndroid Build Coastguard Worker                       : MALI_AFRC_FORMAT_R10_422_ROT);
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker       return (scan ? MALI_AFRC_FORMAT_R10G10_422_SCAN
828*61046927SAndroid Build Coastguard Worker                    : MALI_AFRC_FORMAT_R10G10_422_ROT);
829*61046927SAndroid Build Coastguard Worker 
830*61046927SAndroid Build Coastguard Worker    case PAN_AFRC_ICHANGE_FORMAT_YUV420:
831*61046927SAndroid Build Coastguard Worker       if (info.bpc == 8) {
832*61046927SAndroid Build Coastguard Worker          if (plane == 0 || info.num_planes == 3)
833*61046927SAndroid Build Coastguard Worker             return (scan ? MALI_AFRC_FORMAT_R8_420_SCAN
834*61046927SAndroid Build Coastguard Worker                          : MALI_AFRC_FORMAT_R8_420_ROT);
835*61046927SAndroid Build Coastguard Worker 
836*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R8G8_420_SCAN
837*61046927SAndroid Build Coastguard Worker                       : MALI_AFRC_FORMAT_R8G8_420_ROT);
838*61046927SAndroid Build Coastguard Worker       }
839*61046927SAndroid Build Coastguard Worker 
840*61046927SAndroid Build Coastguard Worker       if (plane == 0 || info.num_planes == 3)
841*61046927SAndroid Build Coastguard Worker          return (scan ? MALI_AFRC_FORMAT_R10_420_SCAN
842*61046927SAndroid Build Coastguard Worker                       : MALI_AFRC_FORMAT_R10_420_ROT);
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker       return (scan ? MALI_AFRC_FORMAT_R10G10_420_SCAN
845*61046927SAndroid Build Coastguard Worker                    : MALI_AFRC_FORMAT_R10G10_420_ROT);
846*61046927SAndroid Build Coastguard Worker 
847*61046927SAndroid Build Coastguard Worker    default:
848*61046927SAndroid Build Coastguard Worker       return MALI_AFRC_FORMAT_INVALID;
849*61046927SAndroid Build Coastguard Worker    }
850*61046927SAndroid Build Coastguard Worker }
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker enum mali_afrc_block_size
GENX(pan_afrc_block_size)853*61046927SAndroid Build Coastguard Worker GENX(pan_afrc_block_size)(uint64_t modifier, unsigned index)
854*61046927SAndroid Build Coastguard Worker {
855*61046927SAndroid Build Coastguard Worker    /* Clump size flag for planes 1 and 2 is shifted by 4 bits */
856*61046927SAndroid Build Coastguard Worker    unsigned shift = index == 0 ? 0 : 4;
857*61046927SAndroid Build Coastguard Worker    uint64_t flag = (modifier >> shift) & AFRC_FORMAT_MOD_CU_SIZE_MASK;
858*61046927SAndroid Build Coastguard Worker 
859*61046927SAndroid Build Coastguard Worker    /* clang-format off */
860*61046927SAndroid Build Coastguard Worker    switch (flag) {
861*61046927SAndroid Build Coastguard Worker    case AFRC_FORMAT_MOD_CU_SIZE_16: return MALI_AFRC_BLOCK_SIZE_16;
862*61046927SAndroid Build Coastguard Worker    case AFRC_FORMAT_MOD_CU_SIZE_24: return MALI_AFRC_BLOCK_SIZE_24;
863*61046927SAndroid Build Coastguard Worker    case AFRC_FORMAT_MOD_CU_SIZE_32: return MALI_AFRC_BLOCK_SIZE_32;
864*61046927SAndroid Build Coastguard Worker    default:                         unreachable("invalid code unit size");
865*61046927SAndroid Build Coastguard Worker    }
866*61046927SAndroid Build Coastguard Worker    /* clang-format on */
867*61046927SAndroid Build Coastguard Worker }
868*61046927SAndroid Build Coastguard Worker #endif
869