1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright (C) 2021 Collabora, Ltd.
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker *
23*61046927SAndroid Build Coastguard Worker * Authors:
24*61046927SAndroid Build Coastguard Worker * Alyssa Rosenzweig <[email protected]>
25*61046927SAndroid Build Coastguard Worker * Boris Brezillon <[email protected]>
26*61046927SAndroid Build Coastguard Worker */
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker #include "genxml/gen_macros.h"
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker #include "pan_desc.h"
33*61046927SAndroid Build Coastguard Worker #include "pan_encoder.h"
34*61046927SAndroid Build Coastguard Worker #include "pan_texture.h"
35*61046927SAndroid Build Coastguard Worker
36*61046927SAndroid Build Coastguard Worker static unsigned
mod_to_block_fmt(uint64_t mod)37*61046927SAndroid Build Coastguard Worker mod_to_block_fmt(uint64_t mod)
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker switch (mod) {
40*61046927SAndroid Build Coastguard Worker case DRM_FORMAT_MOD_LINEAR:
41*61046927SAndroid Build Coastguard Worker return MALI_BLOCK_FORMAT_LINEAR;
42*61046927SAndroid Build Coastguard Worker case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED:
43*61046927SAndroid Build Coastguard Worker return MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
44*61046927SAndroid Build Coastguard Worker default:
45*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5
46*61046927SAndroid Build Coastguard Worker if (drm_is_afbc(mod) && !(mod & AFBC_FORMAT_MOD_TILED))
47*61046927SAndroid Build Coastguard Worker return MALI_BLOCK_FORMAT_AFBC;
48*61046927SAndroid Build Coastguard Worker #endif
49*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 7
50*61046927SAndroid Build Coastguard Worker if (drm_is_afbc(mod) && (mod & AFBC_FORMAT_MOD_TILED))
51*61046927SAndroid Build Coastguard Worker return MALI_BLOCK_FORMAT_AFBC_TILED;
52*61046927SAndroid Build Coastguard Worker #endif
53*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 10
54*61046927SAndroid Build Coastguard Worker if (drm_is_afrc(mod))
55*61046927SAndroid Build Coastguard Worker return 0; /* Reserved field for AFRC state */
56*61046927SAndroid Build Coastguard Worker #endif
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker unreachable("Unsupported modifer");
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker }
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker static enum mali_msaa
mali_sampling_mode(const struct pan_image_view * view)63*61046927SAndroid Build Coastguard Worker mali_sampling_mode(const struct pan_image_view *view)
64*61046927SAndroid Build Coastguard Worker {
65*61046927SAndroid Build Coastguard Worker unsigned nr_samples = pan_image_view_get_nr_samples(view);
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker if (nr_samples > 1) {
68*61046927SAndroid Build Coastguard Worker assert(view->nr_samples == nr_samples);
69*61046927SAndroid Build Coastguard Worker assert(view->planes[0]->layout.slices[0].surface_stride != 0);
70*61046927SAndroid Build Coastguard Worker return MALI_MSAA_LAYERED;
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker
73*61046927SAndroid Build Coastguard Worker if (view->nr_samples > nr_samples) {
74*61046927SAndroid Build Coastguard Worker assert(nr_samples == 1);
75*61046927SAndroid Build Coastguard Worker return MALI_MSAA_AVERAGE;
76*61046927SAndroid Build Coastguard Worker }
77*61046927SAndroid Build Coastguard Worker
78*61046927SAndroid Build Coastguard Worker assert(view->nr_samples == nr_samples);
79*61046927SAndroid Build Coastguard Worker assert(view->nr_samples == 1);
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker return MALI_MSAA_SINGLE;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker int
GENX(pan_select_crc_rt)85*61046927SAndroid Build Coastguard Worker GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker /* Disable CRC when the tile size is not 16x16. In the hardware, CRC
88*61046927SAndroid Build Coastguard Worker * tiles are the same size as the tiles of the framebuffer. However,
89*61046927SAndroid Build Coastguard Worker * our code only handles 16x16 tiles. Therefore under the current
90*61046927SAndroid Build Coastguard Worker * implementation, we must disable CRC when 16x16 tiles are not used.
91*61046927SAndroid Build Coastguard Worker *
92*61046927SAndroid Build Coastguard Worker * This may hurt performance. However, smaller tile sizes are rare, and
93*61046927SAndroid Build Coastguard Worker * CRCs are more expensive at smaller tile sizes, reducing the benefit.
94*61046927SAndroid Build Coastguard Worker * Restricting CRC to 16x16 should work in practice.
95*61046927SAndroid Build Coastguard Worker */
96*61046927SAndroid Build Coastguard Worker if (tile_size != 16 * 16) {
97*61046927SAndroid Build Coastguard Worker assert(tile_size < 16 * 16);
98*61046927SAndroid Build Coastguard Worker return -1;
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker
101*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 6
102*61046927SAndroid Build Coastguard Worker if (fb->rt_count == 1 && fb->rts[0].view && !fb->rts[0].discard &&
103*61046927SAndroid Build Coastguard Worker pan_image_view_has_crc(fb->rts[0].view))
104*61046927SAndroid Build Coastguard Worker return 0;
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker return -1;
107*61046927SAndroid Build Coastguard Worker #else
108*61046927SAndroid Build Coastguard Worker bool best_rt_valid = false;
109*61046927SAndroid Build Coastguard Worker int best_rt = -1;
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < fb->rt_count; i++) {
112*61046927SAndroid Build Coastguard Worker if (!fb->rts[i].view || fb->rts[0].discard ||
113*61046927SAndroid Build Coastguard Worker !pan_image_view_has_crc(fb->rts[i].view))
114*61046927SAndroid Build Coastguard Worker continue;
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker bool valid = *(fb->rts[i].crc_valid);
117*61046927SAndroid Build Coastguard Worker bool full = !fb->extent.minx && !fb->extent.miny &&
118*61046927SAndroid Build Coastguard Worker fb->extent.maxx == (fb->width - 1) &&
119*61046927SAndroid Build Coastguard Worker fb->extent.maxy == (fb->height - 1);
120*61046927SAndroid Build Coastguard Worker if (!full && !valid)
121*61046927SAndroid Build Coastguard Worker continue;
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker if (best_rt < 0 || (valid && !best_rt_valid)) {
124*61046927SAndroid Build Coastguard Worker best_rt = i;
125*61046927SAndroid Build Coastguard Worker best_rt_valid = valid;
126*61046927SAndroid Build Coastguard Worker }
127*61046927SAndroid Build Coastguard Worker
128*61046927SAndroid Build Coastguard Worker if (valid)
129*61046927SAndroid Build Coastguard Worker break;
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker
132*61046927SAndroid Build Coastguard Worker return best_rt;
133*61046927SAndroid Build Coastguard Worker #endif
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker static enum mali_zs_format
translate_zs_format(enum pipe_format in)137*61046927SAndroid Build Coastguard Worker translate_zs_format(enum pipe_format in)
138*61046927SAndroid Build Coastguard Worker {
139*61046927SAndroid Build Coastguard Worker switch (in) {
140*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z16_UNORM:
141*61046927SAndroid Build Coastguard Worker return MALI_ZS_FORMAT_D16;
142*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z24_UNORM_S8_UINT:
143*61046927SAndroid Build Coastguard Worker return MALI_ZS_FORMAT_D24S8;
144*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z24X8_UNORM:
145*61046927SAndroid Build Coastguard Worker return MALI_ZS_FORMAT_D24X8;
146*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z32_FLOAT:
147*61046927SAndroid Build Coastguard Worker return MALI_ZS_FORMAT_D32;
148*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 7
149*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
150*61046927SAndroid Build Coastguard Worker return MALI_ZS_FORMAT_D32_S8X24;
151*61046927SAndroid Build Coastguard Worker #endif
152*61046927SAndroid Build Coastguard Worker default:
153*61046927SAndroid Build Coastguard Worker unreachable("Unsupported depth/stencil format.");
154*61046927SAndroid Build Coastguard Worker }
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5
158*61046927SAndroid Build Coastguard Worker static enum mali_s_format
translate_s_format(enum pipe_format in)159*61046927SAndroid Build Coastguard Worker translate_s_format(enum pipe_format in)
160*61046927SAndroid Build Coastguard Worker {
161*61046927SAndroid Build Coastguard Worker switch (in) {
162*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_S8_UINT:
163*61046927SAndroid Build Coastguard Worker return MALI_S_FORMAT_S8;
164*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z24_UNORM_S8_UINT:
165*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_X24S8_UINT:
166*61046927SAndroid Build Coastguard Worker return MALI_S_FORMAT_X24S8;
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 7
169*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_S8_UINT_Z24_UNORM:
170*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_S8X24_UINT:
171*61046927SAndroid Build Coastguard Worker return MALI_S_FORMAT_S8X24;
172*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
173*61046927SAndroid Build Coastguard Worker case PIPE_FORMAT_X32_S8X24_UINT:
174*61046927SAndroid Build Coastguard Worker return MALI_S_FORMAT_X32_S8X24;
175*61046927SAndroid Build Coastguard Worker #endif
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker default:
178*61046927SAndroid Build Coastguard Worker unreachable("Unsupported stencil format.");
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker static void
pan_prepare_s(const struct pan_fb_info * fb,unsigned layer_idx,struct MALI_ZS_CRC_EXTENSION * ext)183*61046927SAndroid Build Coastguard Worker pan_prepare_s(const struct pan_fb_info *fb, unsigned layer_idx,
184*61046927SAndroid Build Coastguard Worker struct MALI_ZS_CRC_EXTENSION *ext)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker const struct pan_image_view *s = fb->zs.view.s;
187*61046927SAndroid Build Coastguard Worker
188*61046927SAndroid Build Coastguard Worker if (!s)
189*61046927SAndroid Build Coastguard Worker return;
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_zs_image(s);
192*61046927SAndroid Build Coastguard Worker unsigned level = s->first_level;
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker ext->s_msaa = mali_sampling_mode(s);
195*61046927SAndroid Build Coastguard Worker
196*61046927SAndroid Build Coastguard Worker struct pan_surface surf;
197*61046927SAndroid Build Coastguard Worker pan_iview_get_surface(s, 0, layer_idx, 0, &surf);
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker assert(image->layout.modifier ==
200*61046927SAndroid Build Coastguard Worker DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
201*61046927SAndroid Build Coastguard Worker image->layout.modifier == DRM_FORMAT_MOD_LINEAR);
202*61046927SAndroid Build Coastguard Worker ext->s_writeback_base = surf.data;
203*61046927SAndroid Build Coastguard Worker ext->s_writeback_row_stride = image->layout.slices[level].row_stride;
204*61046927SAndroid Build Coastguard Worker ext->s_writeback_surface_stride =
205*61046927SAndroid Build Coastguard Worker (pan_image_view_get_nr_samples(s) > 1)
206*61046927SAndroid Build Coastguard Worker ? image->layout.slices[level].surface_stride
207*61046927SAndroid Build Coastguard Worker : 0;
208*61046927SAndroid Build Coastguard Worker ext->s_block_format = mod_to_block_fmt(image->layout.modifier);
209*61046927SAndroid Build Coastguard Worker ext->s_write_format = translate_s_format(s->format);
210*61046927SAndroid Build Coastguard Worker }
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker static void
pan_prepare_zs(const struct pan_fb_info * fb,unsigned layer_idx,struct MALI_ZS_CRC_EXTENSION * ext)213*61046927SAndroid Build Coastguard Worker pan_prepare_zs(const struct pan_fb_info *fb, unsigned layer_idx,
214*61046927SAndroid Build Coastguard Worker struct MALI_ZS_CRC_EXTENSION *ext)
215*61046927SAndroid Build Coastguard Worker {
216*61046927SAndroid Build Coastguard Worker const struct pan_image_view *zs = fb->zs.view.zs;
217*61046927SAndroid Build Coastguard Worker
218*61046927SAndroid Build Coastguard Worker if (!zs)
219*61046927SAndroid Build Coastguard Worker return;
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_zs_image(zs);
222*61046927SAndroid Build Coastguard Worker unsigned level = zs->first_level;
223*61046927SAndroid Build Coastguard Worker
224*61046927SAndroid Build Coastguard Worker ext->zs_msaa = mali_sampling_mode(zs);
225*61046927SAndroid Build Coastguard Worker
226*61046927SAndroid Build Coastguard Worker struct pan_surface surf;
227*61046927SAndroid Build Coastguard Worker pan_iview_get_surface(zs, 0, layer_idx, 0, &surf);
228*61046927SAndroid Build Coastguard Worker UNUSED const struct pan_image_slice_layout *slice =
229*61046927SAndroid Build Coastguard Worker &image->layout.slices[level];
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker if (drm_is_afbc(image->layout.modifier)) {
232*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
233*61046927SAndroid Build Coastguard Worker ext->zs_writeback_base = surf.afbc.header;
234*61046927SAndroid Build Coastguard Worker ext->zs_writeback_row_stride = slice->row_stride;
235*61046927SAndroid Build Coastguard Worker /* TODO: surface stride? */
236*61046927SAndroid Build Coastguard Worker ext->zs_afbc_body_offset = surf.afbc.body - surf.afbc.header;
237*61046927SAndroid Build Coastguard Worker
238*61046927SAndroid Build Coastguard Worker /* TODO: stencil AFBC? */
239*61046927SAndroid Build Coastguard Worker #else
240*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
241*61046927SAndroid Build Coastguard Worker ext->zs_afbc_row_stride =
242*61046927SAndroid Build Coastguard Worker pan_afbc_stride_blocks(image->layout.modifier, slice->row_stride);
243*61046927SAndroid Build Coastguard Worker #else
244*61046927SAndroid Build Coastguard Worker ext->zs_block_format = MALI_BLOCK_FORMAT_AFBC;
245*61046927SAndroid Build Coastguard Worker ext->zs_afbc_body_size = 0x1000;
246*61046927SAndroid Build Coastguard Worker ext->zs_afbc_chunk_size = 9;
247*61046927SAndroid Build Coastguard Worker ext->zs_afbc_sparse = true;
248*61046927SAndroid Build Coastguard Worker #endif
249*61046927SAndroid Build Coastguard Worker
250*61046927SAndroid Build Coastguard Worker ext->zs_afbc_header = surf.afbc.header;
251*61046927SAndroid Build Coastguard Worker ext->zs_afbc_body = surf.afbc.body;
252*61046927SAndroid Build Coastguard Worker #endif
253*61046927SAndroid Build Coastguard Worker } else {
254*61046927SAndroid Build Coastguard Worker assert(image->layout.modifier ==
255*61046927SAndroid Build Coastguard Worker DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
256*61046927SAndroid Build Coastguard Worker image->layout.modifier == DRM_FORMAT_MOD_LINEAR);
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker /* TODO: Z32F(S8) support, which is always linear */
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker ext->zs_writeback_base = surf.data;
261*61046927SAndroid Build Coastguard Worker ext->zs_writeback_row_stride = image->layout.slices[level].row_stride;
262*61046927SAndroid Build Coastguard Worker ext->zs_writeback_surface_stride =
263*61046927SAndroid Build Coastguard Worker (pan_image_view_get_nr_samples(zs) > 1)
264*61046927SAndroid Build Coastguard Worker ? image->layout.slices[level].surface_stride
265*61046927SAndroid Build Coastguard Worker : 0;
266*61046927SAndroid Build Coastguard Worker }
267*61046927SAndroid Build Coastguard Worker
268*61046927SAndroid Build Coastguard Worker ext->zs_block_format = mod_to_block_fmt(image->layout.modifier);
269*61046927SAndroid Build Coastguard Worker ext->zs_write_format = translate_zs_format(zs->format);
270*61046927SAndroid Build Coastguard Worker if (ext->zs_write_format == MALI_ZS_FORMAT_D24S8)
271*61046927SAndroid Build Coastguard Worker ext->s_writeback_base = ext->zs_writeback_base;
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker
274*61046927SAndroid Build Coastguard Worker static void
pan_prepare_crc(const struct pan_fb_info * fb,int rt_crc,struct MALI_ZS_CRC_EXTENSION * ext)275*61046927SAndroid Build Coastguard Worker pan_prepare_crc(const struct pan_fb_info *fb, int rt_crc,
276*61046927SAndroid Build Coastguard Worker struct MALI_ZS_CRC_EXTENSION *ext)
277*61046927SAndroid Build Coastguard Worker {
278*61046927SAndroid Build Coastguard Worker if (rt_crc < 0)
279*61046927SAndroid Build Coastguard Worker return;
280*61046927SAndroid Build Coastguard Worker
281*61046927SAndroid Build Coastguard Worker assert(rt_crc < fb->rt_count);
282*61046927SAndroid Build Coastguard Worker
283*61046927SAndroid Build Coastguard Worker const struct pan_image_view *rt = fb->rts[rt_crc].view;
284*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_rt_image(rt);
285*61046927SAndroid Build Coastguard Worker const struct pan_image_slice_layout *slice =
286*61046927SAndroid Build Coastguard Worker &image->layout.slices[rt->first_level];
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker ext->crc_base =
289*61046927SAndroid Build Coastguard Worker image->data.base + image->data.offset + slice->crc.offset;
290*61046927SAndroid Build Coastguard Worker ext->crc_row_stride = slice->crc.stride;
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 7
293*61046927SAndroid Build Coastguard Worker ext->crc_render_target = rt_crc;
294*61046927SAndroid Build Coastguard Worker
295*61046927SAndroid Build Coastguard Worker if (fb->rts[rt_crc].clear) {
296*61046927SAndroid Build Coastguard Worker uint32_t clear_val = fb->rts[rt_crc].clear_value[0];
297*61046927SAndroid Build Coastguard Worker ext->crc_clear_color = clear_val | 0xc000000000000000 |
298*61046927SAndroid Build Coastguard Worker (((uint64_t)clear_val & 0xffff) << 32);
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker #endif
301*61046927SAndroid Build Coastguard Worker }
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker static void
pan_emit_zs_crc_ext(const struct pan_fb_info * fb,unsigned layer_idx,int rt_crc,void * zs_crc_ext)304*61046927SAndroid Build Coastguard Worker pan_emit_zs_crc_ext(const struct pan_fb_info *fb, unsigned layer_idx,
305*61046927SAndroid Build Coastguard Worker int rt_crc, void *zs_crc_ext)
306*61046927SAndroid Build Coastguard Worker {
307*61046927SAndroid Build Coastguard Worker pan_pack(zs_crc_ext, ZS_CRC_EXTENSION, cfg) {
308*61046927SAndroid Build Coastguard Worker pan_prepare_crc(fb, rt_crc, &cfg);
309*61046927SAndroid Build Coastguard Worker cfg.zs_clean_pixel_write_enable = fb->zs.clear.z || fb->zs.clear.s;
310*61046927SAndroid Build Coastguard Worker pan_prepare_zs(fb, layer_idx, &cfg);
311*61046927SAndroid Build Coastguard Worker pan_prepare_s(fb, layer_idx, &cfg);
312*61046927SAndroid Build Coastguard Worker }
313*61046927SAndroid Build Coastguard Worker }
314*61046927SAndroid Build Coastguard Worker
315*61046927SAndroid Build Coastguard Worker /* Measure format as it appears in the tile buffer */
316*61046927SAndroid Build Coastguard Worker
317*61046927SAndroid Build Coastguard Worker static unsigned
pan_bytes_per_pixel_tib(enum pipe_format format)318*61046927SAndroid Build Coastguard Worker pan_bytes_per_pixel_tib(enum pipe_format format)
319*61046927SAndroid Build Coastguard Worker {
320*61046927SAndroid Build Coastguard Worker const struct pan_blendable_format *bf =
321*61046927SAndroid Build Coastguard Worker GENX(panfrost_blendable_format_from_pipe_format)(format);
322*61046927SAndroid Build Coastguard Worker
323*61046927SAndroid Build Coastguard Worker if (bf->internal) {
324*61046927SAndroid Build Coastguard Worker /* Blendable formats are always 32-bits in the tile buffer,
325*61046927SAndroid Build Coastguard Worker * extra bits are used as padding or to dither */
326*61046927SAndroid Build Coastguard Worker return 4;
327*61046927SAndroid Build Coastguard Worker } else {
328*61046927SAndroid Build Coastguard Worker /* Non-blendable formats are raw, rounded up to the nearest
329*61046927SAndroid Build Coastguard Worker * power-of-two size */
330*61046927SAndroid Build Coastguard Worker unsigned bytes = util_format_get_blocksize(format);
331*61046927SAndroid Build Coastguard Worker return util_next_power_of_two(bytes);
332*61046927SAndroid Build Coastguard Worker }
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker
335*61046927SAndroid Build Coastguard Worker static unsigned
pan_cbuf_bytes_per_pixel(const struct pan_fb_info * fb)336*61046927SAndroid Build Coastguard Worker pan_cbuf_bytes_per_pixel(const struct pan_fb_info *fb)
337*61046927SAndroid Build Coastguard Worker {
338*61046927SAndroid Build Coastguard Worker unsigned sum = 0;
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker for (int cb = 0; cb < fb->rt_count; ++cb) {
341*61046927SAndroid Build Coastguard Worker const struct pan_image_view *rt = fb->rts[cb].view;
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker if (!rt)
344*61046927SAndroid Build Coastguard Worker continue;
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker sum += pan_bytes_per_pixel_tib(rt->format) * rt->nr_samples;
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker
349*61046927SAndroid Build Coastguard Worker return sum;
350*61046927SAndroid Build Coastguard Worker }
351*61046927SAndroid Build Coastguard Worker
352*61046927SAndroid Build Coastguard Worker /*
353*61046927SAndroid Build Coastguard Worker * Select the largest tile size that fits within the tilebuffer budget.
354*61046927SAndroid Build Coastguard Worker * Formally, maximize (pixels per tile) such that it is a power of two and
355*61046927SAndroid Build Coastguard Worker *
356*61046927SAndroid Build Coastguard Worker * (bytes per pixel) (pixels per tile) <= (max bytes per tile)
357*61046927SAndroid Build Coastguard Worker *
358*61046927SAndroid Build Coastguard Worker * A bit of algebra gives the following formula.
359*61046927SAndroid Build Coastguard Worker */
360*61046927SAndroid Build Coastguard Worker static unsigned
pan_select_max_tile_size(unsigned tile_buffer_bytes,unsigned bytes_per_pixel)361*61046927SAndroid Build Coastguard Worker pan_select_max_tile_size(unsigned tile_buffer_bytes, unsigned bytes_per_pixel)
362*61046927SAndroid Build Coastguard Worker {
363*61046927SAndroid Build Coastguard Worker assert(util_is_power_of_two_nonzero(tile_buffer_bytes));
364*61046927SAndroid Build Coastguard Worker assert(tile_buffer_bytes >= 1024);
365*61046927SAndroid Build Coastguard Worker
366*61046927SAndroid Build Coastguard Worker return tile_buffer_bytes >> util_logbase2_ceil(bytes_per_pixel);
367*61046927SAndroid Build Coastguard Worker }
368*61046927SAndroid Build Coastguard Worker
369*61046927SAndroid Build Coastguard Worker static enum mali_color_format
pan_mfbd_raw_format(unsigned bits)370*61046927SAndroid Build Coastguard Worker pan_mfbd_raw_format(unsigned bits)
371*61046927SAndroid Build Coastguard Worker {
372*61046927SAndroid Build Coastguard Worker /* clang-format off */
373*61046927SAndroid Build Coastguard Worker switch (bits) {
374*61046927SAndroid Build Coastguard Worker case 8: return MALI_COLOR_FORMAT_RAW8;
375*61046927SAndroid Build Coastguard Worker case 16: return MALI_COLOR_FORMAT_RAW16;
376*61046927SAndroid Build Coastguard Worker case 24: return MALI_COLOR_FORMAT_RAW24;
377*61046927SAndroid Build Coastguard Worker case 32: return MALI_COLOR_FORMAT_RAW32;
378*61046927SAndroid Build Coastguard Worker case 48: return MALI_COLOR_FORMAT_RAW48;
379*61046927SAndroid Build Coastguard Worker case 64: return MALI_COLOR_FORMAT_RAW64;
380*61046927SAndroid Build Coastguard Worker case 96: return MALI_COLOR_FORMAT_RAW96;
381*61046927SAndroid Build Coastguard Worker case 128: return MALI_COLOR_FORMAT_RAW128;
382*61046927SAndroid Build Coastguard Worker case 192: return MALI_COLOR_FORMAT_RAW192;
383*61046927SAndroid Build Coastguard Worker case 256: return MALI_COLOR_FORMAT_RAW256;
384*61046927SAndroid Build Coastguard Worker case 384: return MALI_COLOR_FORMAT_RAW384;
385*61046927SAndroid Build Coastguard Worker case 512: return MALI_COLOR_FORMAT_RAW512;
386*61046927SAndroid Build Coastguard Worker case 768: return MALI_COLOR_FORMAT_RAW768;
387*61046927SAndroid Build Coastguard Worker case 1024: return MALI_COLOR_FORMAT_RAW1024;
388*61046927SAndroid Build Coastguard Worker case 1536: return MALI_COLOR_FORMAT_RAW1536;
389*61046927SAndroid Build Coastguard Worker case 2048: return MALI_COLOR_FORMAT_RAW2048;
390*61046927SAndroid Build Coastguard Worker default: unreachable("invalid raw bpp");
391*61046927SAndroid Build Coastguard Worker }
392*61046927SAndroid Build Coastguard Worker /* clang-format on */
393*61046927SAndroid Build Coastguard Worker }
394*61046927SAndroid Build Coastguard Worker
395*61046927SAndroid Build Coastguard Worker static void
pan_rt_init_format(const struct pan_image_view * rt,struct MALI_RENDER_TARGET * cfg)396*61046927SAndroid Build Coastguard Worker pan_rt_init_format(const struct pan_image_view *rt,
397*61046927SAndroid Build Coastguard Worker struct MALI_RENDER_TARGET *cfg)
398*61046927SAndroid Build Coastguard Worker {
399*61046927SAndroid Build Coastguard Worker /* Explode details on the format */
400*61046927SAndroid Build Coastguard Worker
401*61046927SAndroid Build Coastguard Worker const struct util_format_description *desc =
402*61046927SAndroid Build Coastguard Worker util_format_description(rt->format);
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker /* The swizzle for rendering is inverted from texturing */
405*61046927SAndroid Build Coastguard Worker
406*61046927SAndroid Build Coastguard Worker unsigned char swizzle[4] = {
407*61046927SAndroid Build Coastguard Worker PIPE_SWIZZLE_X,
408*61046927SAndroid Build Coastguard Worker PIPE_SWIZZLE_Y,
409*61046927SAndroid Build Coastguard Worker PIPE_SWIZZLE_Z,
410*61046927SAndroid Build Coastguard Worker PIPE_SWIZZLE_W,
411*61046927SAndroid Build Coastguard Worker };
412*61046927SAndroid Build Coastguard Worker
413*61046927SAndroid Build Coastguard Worker /* Fill in accordingly, defaulting to 8-bit UNORM */
414*61046927SAndroid Build Coastguard Worker
415*61046927SAndroid Build Coastguard Worker if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
416*61046927SAndroid Build Coastguard Worker cfg->srgb = true;
417*61046927SAndroid Build Coastguard Worker
418*61046927SAndroid Build Coastguard Worker struct pan_blendable_format fmt =
419*61046927SAndroid Build Coastguard Worker *GENX(panfrost_blendable_format_from_pipe_format)(rt->format);
420*61046927SAndroid Build Coastguard Worker enum mali_color_format writeback_format;
421*61046927SAndroid Build Coastguard Worker
422*61046927SAndroid Build Coastguard Worker if (fmt.internal) {
423*61046927SAndroid Build Coastguard Worker cfg->internal_format = fmt.internal;
424*61046927SAndroid Build Coastguard Worker writeback_format = fmt.writeback;
425*61046927SAndroid Build Coastguard Worker panfrost_invert_swizzle(desc->swizzle, swizzle);
426*61046927SAndroid Build Coastguard Worker } else {
427*61046927SAndroid Build Coastguard Worker /* Construct RAW internal/writeback, where internal is
428*61046927SAndroid Build Coastguard Worker * specified logarithmically (round to next power-of-two).
429*61046927SAndroid Build Coastguard Worker * Offset specified from RAW8, where 8 = 2^3 */
430*61046927SAndroid Build Coastguard Worker
431*61046927SAndroid Build Coastguard Worker unsigned bits = desc->block.bits;
432*61046927SAndroid Build Coastguard Worker unsigned offset = util_logbase2_ceil(bits) - 3;
433*61046927SAndroid Build Coastguard Worker assert(offset <= 4);
434*61046927SAndroid Build Coastguard Worker
435*61046927SAndroid Build Coastguard Worker cfg->internal_format = MALI_COLOR_BUFFER_INTERNAL_FORMAT_RAW8 + offset;
436*61046927SAndroid Build Coastguard Worker writeback_format = pan_mfbd_raw_format(bits);
437*61046927SAndroid Build Coastguard Worker }
438*61046927SAndroid Build Coastguard Worker
439*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 10
440*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_rt_image(rt);
441*61046927SAndroid Build Coastguard Worker
442*61046927SAndroid Build Coastguard Worker if (drm_is_afrc(image->layout.modifier))
443*61046927SAndroid Build Coastguard Worker cfg->afrc.writeback_format = writeback_format;
444*61046927SAndroid Build Coastguard Worker else
445*61046927SAndroid Build Coastguard Worker cfg->writeback_format = writeback_format;
446*61046927SAndroid Build Coastguard Worker #else
447*61046927SAndroid Build Coastguard Worker cfg->writeback_format = writeback_format;
448*61046927SAndroid Build Coastguard Worker #endif
449*61046927SAndroid Build Coastguard Worker
450*61046927SAndroid Build Coastguard Worker cfg->swizzle = panfrost_translate_swizzle_4(swizzle);
451*61046927SAndroid Build Coastguard Worker }
452*61046927SAndroid Build Coastguard Worker
453*61046927SAndroid Build Coastguard Worker static void
pan_prepare_rt(const struct pan_fb_info * fb,unsigned layer_idx,unsigned rt_idx,unsigned cbuf_offset,struct MALI_RENDER_TARGET * cfg)454*61046927SAndroid Build Coastguard Worker pan_prepare_rt(const struct pan_fb_info *fb, unsigned layer_idx,
455*61046927SAndroid Build Coastguard Worker unsigned rt_idx, unsigned cbuf_offset,
456*61046927SAndroid Build Coastguard Worker struct MALI_RENDER_TARGET *cfg)
457*61046927SAndroid Build Coastguard Worker {
458*61046927SAndroid Build Coastguard Worker cfg->clean_pixel_write_enable = fb->rts[rt_idx].clear;
459*61046927SAndroid Build Coastguard Worker cfg->internal_buffer_offset = cbuf_offset;
460*61046927SAndroid Build Coastguard Worker if (fb->rts[rt_idx].clear) {
461*61046927SAndroid Build Coastguard Worker cfg->clear.color_0 = fb->rts[rt_idx].clear_value[0];
462*61046927SAndroid Build Coastguard Worker cfg->clear.color_1 = fb->rts[rt_idx].clear_value[1];
463*61046927SAndroid Build Coastguard Worker cfg->clear.color_2 = fb->rts[rt_idx].clear_value[2];
464*61046927SAndroid Build Coastguard Worker cfg->clear.color_3 = fb->rts[rt_idx].clear_value[3];
465*61046927SAndroid Build Coastguard Worker }
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker const struct pan_image_view *rt = fb->rts[rt_idx].view;
468*61046927SAndroid Build Coastguard Worker if (!rt || fb->rts[rt_idx].discard) {
469*61046927SAndroid Build Coastguard Worker cfg->internal_format = MALI_COLOR_BUFFER_INTERNAL_FORMAT_R8G8B8A8;
470*61046927SAndroid Build Coastguard Worker cfg->internal_buffer_offset = cbuf_offset;
471*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 7
472*61046927SAndroid Build Coastguard Worker cfg->writeback_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
473*61046927SAndroid Build Coastguard Worker cfg->dithering_enable = true;
474*61046927SAndroid Build Coastguard Worker #endif
475*61046927SAndroid Build Coastguard Worker return;
476*61046927SAndroid Build Coastguard Worker }
477*61046927SAndroid Build Coastguard Worker
478*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_rt_image(rt);
479*61046927SAndroid Build Coastguard Worker
480*61046927SAndroid Build Coastguard Worker if (!drm_is_afrc(image->layout.modifier))
481*61046927SAndroid Build Coastguard Worker cfg->write_enable = true;
482*61046927SAndroid Build Coastguard Worker
483*61046927SAndroid Build Coastguard Worker cfg->dithering_enable = true;
484*61046927SAndroid Build Coastguard Worker
485*61046927SAndroid Build Coastguard Worker unsigned level = rt->first_level;
486*61046927SAndroid Build Coastguard Worker ASSERTED unsigned layer_count = rt->dim == MALI_TEXTURE_DIMENSION_3D
487*61046927SAndroid Build Coastguard Worker ? rt->planes[0]->layout.depth
488*61046927SAndroid Build Coastguard Worker : rt->last_layer - rt->first_layer + 1;
489*61046927SAndroid Build Coastguard Worker
490*61046927SAndroid Build Coastguard Worker assert(rt->last_level == rt->first_level);
491*61046927SAndroid Build Coastguard Worker assert(layer_idx < layer_count);
492*61046927SAndroid Build Coastguard Worker
493*61046927SAndroid Build Coastguard Worker int row_stride = image->layout.slices[level].row_stride;
494*61046927SAndroid Build Coastguard Worker
495*61046927SAndroid Build Coastguard Worker /* Only set layer_stride for layered MSAA rendering */
496*61046927SAndroid Build Coastguard Worker
497*61046927SAndroid Build Coastguard Worker unsigned layer_stride = (pan_image_view_get_nr_samples(rt) > 1)
498*61046927SAndroid Build Coastguard Worker ? image->layout.slices[level].surface_stride
499*61046927SAndroid Build Coastguard Worker : 0;
500*61046927SAndroid Build Coastguard Worker
501*61046927SAndroid Build Coastguard Worker cfg->writeback_msaa = mali_sampling_mode(rt);
502*61046927SAndroid Build Coastguard Worker
503*61046927SAndroid Build Coastguard Worker pan_rt_init_format(rt, cfg);
504*61046927SAndroid Build Coastguard Worker
505*61046927SAndroid Build Coastguard Worker cfg->writeback_block_format = mod_to_block_fmt(image->layout.modifier);
506*61046927SAndroid Build Coastguard Worker
507*61046927SAndroid Build Coastguard Worker struct pan_surface surf;
508*61046927SAndroid Build Coastguard Worker pan_iview_get_surface(rt, 0, layer_idx, 0, &surf);
509*61046927SAndroid Build Coastguard Worker
510*61046927SAndroid Build Coastguard Worker if (drm_is_afbc(image->layout.modifier)) {
511*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
512*61046927SAndroid Build Coastguard Worker if (image->layout.modifier & AFBC_FORMAT_MOD_YTR)
513*61046927SAndroid Build Coastguard Worker cfg->afbc.yuv_transform = true;
514*61046927SAndroid Build Coastguard Worker
515*61046927SAndroid Build Coastguard Worker cfg->afbc.wide_block = panfrost_afbc_is_wide(image->layout.modifier);
516*61046927SAndroid Build Coastguard Worker cfg->afbc.header = surf.afbc.header;
517*61046927SAndroid Build Coastguard Worker cfg->afbc.body_offset = surf.afbc.body - surf.afbc.header;
518*61046927SAndroid Build Coastguard Worker assert(surf.afbc.body >= surf.afbc.header);
519*61046927SAndroid Build Coastguard Worker
520*61046927SAndroid Build Coastguard Worker cfg->afbc.compression_mode = GENX(pan_afbc_compression_mode)(rt->format);
521*61046927SAndroid Build Coastguard Worker cfg->afbc.row_stride = row_stride;
522*61046927SAndroid Build Coastguard Worker #else
523*61046927SAndroid Build Coastguard Worker const struct pan_image_slice_layout *slice = &image->layout.slices[level];
524*61046927SAndroid Build Coastguard Worker
525*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
526*61046927SAndroid Build Coastguard Worker cfg->afbc.row_stride =
527*61046927SAndroid Build Coastguard Worker pan_afbc_stride_blocks(image->layout.modifier, slice->row_stride);
528*61046927SAndroid Build Coastguard Worker cfg->afbc.afbc_wide_block_enable =
529*61046927SAndroid Build Coastguard Worker panfrost_afbc_is_wide(image->layout.modifier);
530*61046927SAndroid Build Coastguard Worker #else
531*61046927SAndroid Build Coastguard Worker cfg->afbc.chunk_size = 9;
532*61046927SAndroid Build Coastguard Worker cfg->afbc.sparse = true;
533*61046927SAndroid Build Coastguard Worker cfg->afbc.body_size = slice->afbc.body_size;
534*61046927SAndroid Build Coastguard Worker #endif
535*61046927SAndroid Build Coastguard Worker
536*61046927SAndroid Build Coastguard Worker cfg->afbc.header = surf.afbc.header;
537*61046927SAndroid Build Coastguard Worker cfg->afbc.body = surf.afbc.body;
538*61046927SAndroid Build Coastguard Worker
539*61046927SAndroid Build Coastguard Worker if (image->layout.modifier & AFBC_FORMAT_MOD_YTR)
540*61046927SAndroid Build Coastguard Worker cfg->afbc.yuv_transform_enable = true;
541*61046927SAndroid Build Coastguard Worker #endif
542*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 10
543*61046927SAndroid Build Coastguard Worker } else if (drm_is_afrc(image->layout.modifier)) {
544*61046927SAndroid Build Coastguard Worker struct pan_afrc_format_info finfo =
545*61046927SAndroid Build Coastguard Worker panfrost_afrc_get_format_info(image->layout.format);
546*61046927SAndroid Build Coastguard Worker
547*61046927SAndroid Build Coastguard Worker cfg->writeback_mode = MALI_WRITEBACK_MODE_AFRC_RGB;
548*61046927SAndroid Build Coastguard Worker cfg->afrc.block_size =
549*61046927SAndroid Build Coastguard Worker GENX(pan_afrc_block_size)(image->layout.modifier, 0);
550*61046927SAndroid Build Coastguard Worker cfg->afrc.format =
551*61046927SAndroid Build Coastguard Worker GENX(pan_afrc_format)(finfo, image->layout.modifier, 0);
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker cfg->rgb.base = surf.data;
554*61046927SAndroid Build Coastguard Worker cfg->rgb.row_stride = row_stride;
555*61046927SAndroid Build Coastguard Worker cfg->rgb.surface_stride = layer_stride;
556*61046927SAndroid Build Coastguard Worker #endif
557*61046927SAndroid Build Coastguard Worker } else {
558*61046927SAndroid Build Coastguard Worker assert(image->layout.modifier == DRM_FORMAT_MOD_LINEAR ||
559*61046927SAndroid Build Coastguard Worker image->layout.modifier ==
560*61046927SAndroid Build Coastguard Worker DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED);
561*61046927SAndroid Build Coastguard Worker cfg->rgb.base = surf.data;
562*61046927SAndroid Build Coastguard Worker cfg->rgb.row_stride = row_stride;
563*61046927SAndroid Build Coastguard Worker cfg->rgb.surface_stride = layer_stride;
564*61046927SAndroid Build Coastguard Worker }
565*61046927SAndroid Build Coastguard Worker }
566*61046927SAndroid Build Coastguard Worker #endif
567*61046927SAndroid Build Coastguard Worker
568*61046927SAndroid Build Coastguard Worker void
GENX(pan_emit_tls)569*61046927SAndroid Build Coastguard Worker GENX(pan_emit_tls)(const struct pan_tls_info *info, void *out)
570*61046927SAndroid Build Coastguard Worker {
571*61046927SAndroid Build Coastguard Worker pan_pack(out, LOCAL_STORAGE, cfg) {
572*61046927SAndroid Build Coastguard Worker if (info->tls.size) {
573*61046927SAndroid Build Coastguard Worker unsigned shift = panfrost_get_stack_shift(info->tls.size);
574*61046927SAndroid Build Coastguard Worker
575*61046927SAndroid Build Coastguard Worker cfg.tls_size = shift;
576*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
577*61046927SAndroid Build Coastguard Worker /* For now, always use packed TLS addressing. This is
578*61046927SAndroid Build Coastguard Worker * better for the cache and requires no fix up code in
579*61046927SAndroid Build Coastguard Worker * the shader. We may need to revisit this someday for
580*61046927SAndroid Build Coastguard Worker * OpenCL generic pointer support.
581*61046927SAndroid Build Coastguard Worker */
582*61046927SAndroid Build Coastguard Worker cfg.tls_address_mode = MALI_ADDRESS_MODE_PACKED;
583*61046927SAndroid Build Coastguard Worker
584*61046927SAndroid Build Coastguard Worker assert((info->tls.ptr & 4095) == 0);
585*61046927SAndroid Build Coastguard Worker cfg.tls_base_pointer = info->tls.ptr >> 8;
586*61046927SAndroid Build Coastguard Worker #else
587*61046927SAndroid Build Coastguard Worker cfg.tls_base_pointer = info->tls.ptr;
588*61046927SAndroid Build Coastguard Worker #endif
589*61046927SAndroid Build Coastguard Worker }
590*61046927SAndroid Build Coastguard Worker
591*61046927SAndroid Build Coastguard Worker if (info->wls.size) {
592*61046927SAndroid Build Coastguard Worker assert(!(info->wls.ptr & 4095));
593*61046927SAndroid Build Coastguard Worker assert((info->wls.ptr & 0xffffffff00000000ULL) ==
594*61046927SAndroid Build Coastguard Worker ((info->wls.ptr + info->wls.size - 1) & 0xffffffff00000000ULL));
595*61046927SAndroid Build Coastguard Worker cfg.wls_base_pointer = info->wls.ptr;
596*61046927SAndroid Build Coastguard Worker unsigned wls_size = pan_wls_adjust_size(info->wls.size);
597*61046927SAndroid Build Coastguard Worker cfg.wls_instances = info->wls.instances;
598*61046927SAndroid Build Coastguard Worker cfg.wls_size_scale = util_logbase2(wls_size) + 1;
599*61046927SAndroid Build Coastguard Worker } else {
600*61046927SAndroid Build Coastguard Worker cfg.wls_instances = MALI_LOCAL_STORAGE_NO_WORKGROUP_MEM;
601*61046927SAndroid Build Coastguard Worker }
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker }
604*61046927SAndroid Build Coastguard Worker
605*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 5
606*61046927SAndroid Build Coastguard Worker static void
pan_emit_midgard_tiler(const struct pan_fb_info * fb,const struct pan_tiler_context * tiler_ctx,void * out)607*61046927SAndroid Build Coastguard Worker pan_emit_midgard_tiler(const struct pan_fb_info *fb,
608*61046927SAndroid Build Coastguard Worker const struct pan_tiler_context *tiler_ctx, void *out)
609*61046927SAndroid Build Coastguard Worker {
610*61046927SAndroid Build Coastguard Worker bool hierarchy = !tiler_ctx->midgard.no_hierarchical_tiling;
611*61046927SAndroid Build Coastguard Worker
612*61046927SAndroid Build Coastguard Worker assert(tiler_ctx->midgard.polygon_list);
613*61046927SAndroid Build Coastguard Worker
614*61046927SAndroid Build Coastguard Worker pan_pack(out, TILER_CONTEXT, cfg) {
615*61046927SAndroid Build Coastguard Worker unsigned header_size;
616*61046927SAndroid Build Coastguard Worker
617*61046927SAndroid Build Coastguard Worker if (tiler_ctx->midgard.disable) {
618*61046927SAndroid Build Coastguard Worker cfg.hierarchy_mask =
619*61046927SAndroid Build Coastguard Worker hierarchy ? MALI_MIDGARD_TILER_DISABLED : MALI_MIDGARD_TILER_USER;
620*61046927SAndroid Build Coastguard Worker header_size = MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE;
621*61046927SAndroid Build Coastguard Worker cfg.polygon_list_size = header_size + (hierarchy ? 0 : 4);
622*61046927SAndroid Build Coastguard Worker cfg.heap_start = tiler_ctx->midgard.polygon_list;
623*61046927SAndroid Build Coastguard Worker cfg.heap_end = tiler_ctx->midgard.polygon_list;
624*61046927SAndroid Build Coastguard Worker } else {
625*61046927SAndroid Build Coastguard Worker cfg.hierarchy_mask = panfrost_choose_hierarchy_mask(
626*61046927SAndroid Build Coastguard Worker fb->width, fb->height, tiler_ctx->midgard.vertex_count, hierarchy);
627*61046927SAndroid Build Coastguard Worker header_size = panfrost_tiler_header_size(
628*61046927SAndroid Build Coastguard Worker fb->width, fb->height, cfg.hierarchy_mask, hierarchy);
629*61046927SAndroid Build Coastguard Worker cfg.polygon_list_size = panfrost_tiler_full_size(
630*61046927SAndroid Build Coastguard Worker fb->width, fb->height, cfg.hierarchy_mask, hierarchy);
631*61046927SAndroid Build Coastguard Worker cfg.heap_start = tiler_ctx->midgard.heap.start;
632*61046927SAndroid Build Coastguard Worker cfg.heap_end = cfg.heap_start + tiler_ctx->midgard.heap.size;
633*61046927SAndroid Build Coastguard Worker }
634*61046927SAndroid Build Coastguard Worker
635*61046927SAndroid Build Coastguard Worker cfg.polygon_list = tiler_ctx->midgard.polygon_list;
636*61046927SAndroid Build Coastguard Worker cfg.polygon_list_body = cfg.polygon_list + header_size;
637*61046927SAndroid Build Coastguard Worker }
638*61046927SAndroid Build Coastguard Worker }
639*61046927SAndroid Build Coastguard Worker #endif
640*61046927SAndroid Build Coastguard Worker
641*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5
642*61046927SAndroid Build Coastguard Worker static void
pan_emit_rt(const struct pan_fb_info * fb,unsigned layer_idx,unsigned idx,unsigned cbuf_offset,void * out)643*61046927SAndroid Build Coastguard Worker pan_emit_rt(const struct pan_fb_info *fb, unsigned layer_idx,
644*61046927SAndroid Build Coastguard Worker unsigned idx, unsigned cbuf_offset, void *out)
645*61046927SAndroid Build Coastguard Worker {
646*61046927SAndroid Build Coastguard Worker pan_pack(out, RENDER_TARGET, cfg) {
647*61046927SAndroid Build Coastguard Worker pan_prepare_rt(fb, layer_idx, idx, cbuf_offset, &cfg);
648*61046927SAndroid Build Coastguard Worker }
649*61046927SAndroid Build Coastguard Worker }
650*61046927SAndroid Build Coastguard Worker
651*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
652*61046927SAndroid Build Coastguard Worker /* All Bifrost and Valhall GPUs are affected by issue TSIX-2033:
653*61046927SAndroid Build Coastguard Worker *
654*61046927SAndroid Build Coastguard Worker * Forcing clean_tile_writes breaks INTERSECT readbacks
655*61046927SAndroid Build Coastguard Worker *
656*61046927SAndroid Build Coastguard Worker * To workaround, use the frame shader mode ALWAYS instead of INTERSECT if
657*61046927SAndroid Build Coastguard Worker * clean tile writes is forced. Since INTERSECT is a hint that the hardware may
658*61046927SAndroid Build Coastguard Worker * ignore, this cannot affect correctness, only performance */
659*61046927SAndroid Build Coastguard Worker
660*61046927SAndroid Build Coastguard Worker static enum mali_pre_post_frame_shader_mode
pan_fix_frame_shader_mode(enum mali_pre_post_frame_shader_mode mode,bool force_clean_tile)661*61046927SAndroid Build Coastguard Worker pan_fix_frame_shader_mode(enum mali_pre_post_frame_shader_mode mode,
662*61046927SAndroid Build Coastguard Worker bool force_clean_tile)
663*61046927SAndroid Build Coastguard Worker {
664*61046927SAndroid Build Coastguard Worker if (force_clean_tile && mode == MALI_PRE_POST_FRAME_SHADER_MODE_INTERSECT)
665*61046927SAndroid Build Coastguard Worker return MALI_PRE_POST_FRAME_SHADER_MODE_ALWAYS;
666*61046927SAndroid Build Coastguard Worker else
667*61046927SAndroid Build Coastguard Worker return mode;
668*61046927SAndroid Build Coastguard Worker }
669*61046927SAndroid Build Coastguard Worker
670*61046927SAndroid Build Coastguard Worker /* Regardless of clean_tile_write_enable, the hardware writes clean tiles if
671*61046927SAndroid Build Coastguard Worker * the effective tile size differs from the superblock size of any enabled AFBC
672*61046927SAndroid Build Coastguard Worker * render target. Check this condition. */
673*61046927SAndroid Build Coastguard Worker
674*61046927SAndroid Build Coastguard Worker static bool
pan_force_clean_write_rt(const struct pan_image_view * rt,unsigned tile_size)675*61046927SAndroid Build Coastguard Worker pan_force_clean_write_rt(const struct pan_image_view *rt, unsigned tile_size)
676*61046927SAndroid Build Coastguard Worker {
677*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_rt_image(rt);
678*61046927SAndroid Build Coastguard Worker if (!drm_is_afbc(image->layout.modifier))
679*61046927SAndroid Build Coastguard Worker return false;
680*61046927SAndroid Build Coastguard Worker
681*61046927SAndroid Build Coastguard Worker unsigned superblock = panfrost_afbc_superblock_width(image->layout.modifier);
682*61046927SAndroid Build Coastguard Worker
683*61046927SAndroid Build Coastguard Worker assert(superblock >= 16);
684*61046927SAndroid Build Coastguard Worker assert(tile_size <= 16 * 16);
685*61046927SAndroid Build Coastguard Worker
686*61046927SAndroid Build Coastguard Worker /* Tile size and superblock differ unless they are both 16x16 */
687*61046927SAndroid Build Coastguard Worker return !(superblock == 16 && tile_size == 16 * 16);
688*61046927SAndroid Build Coastguard Worker }
689*61046927SAndroid Build Coastguard Worker
690*61046927SAndroid Build Coastguard Worker static bool
pan_force_clean_write(const struct pan_fb_info * fb,unsigned tile_size)691*61046927SAndroid Build Coastguard Worker pan_force_clean_write(const struct pan_fb_info *fb, unsigned tile_size)
692*61046927SAndroid Build Coastguard Worker {
693*61046927SAndroid Build Coastguard Worker /* Maximum tile size */
694*61046927SAndroid Build Coastguard Worker assert(tile_size <= 16 * 16);
695*61046927SAndroid Build Coastguard Worker
696*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < fb->rt_count; ++i) {
697*61046927SAndroid Build Coastguard Worker if (fb->rts[i].view && !fb->rts[i].discard &&
698*61046927SAndroid Build Coastguard Worker pan_force_clean_write_rt(fb->rts[i].view, tile_size))
699*61046927SAndroid Build Coastguard Worker return true;
700*61046927SAndroid Build Coastguard Worker }
701*61046927SAndroid Build Coastguard Worker
702*61046927SAndroid Build Coastguard Worker if (fb->zs.view.zs && !fb->zs.discard.z &&
703*61046927SAndroid Build Coastguard Worker pan_force_clean_write_rt(fb->zs.view.zs, tile_size))
704*61046927SAndroid Build Coastguard Worker return true;
705*61046927SAndroid Build Coastguard Worker
706*61046927SAndroid Build Coastguard Worker if (fb->zs.view.s && !fb->zs.discard.s &&
707*61046927SAndroid Build Coastguard Worker pan_force_clean_write_rt(fb->zs.view.s, tile_size))
708*61046927SAndroid Build Coastguard Worker return true;
709*61046927SAndroid Build Coastguard Worker
710*61046927SAndroid Build Coastguard Worker return false;
711*61046927SAndroid Build Coastguard Worker }
712*61046927SAndroid Build Coastguard Worker
713*61046927SAndroid Build Coastguard Worker #endif
714*61046927SAndroid Build Coastguard Worker
715*61046927SAndroid Build Coastguard Worker unsigned
GENX(pan_emit_fbd)716*61046927SAndroid Build Coastguard Worker GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
717*61046927SAndroid Build Coastguard Worker const struct pan_tls_info *tls,
718*61046927SAndroid Build Coastguard Worker const struct pan_tiler_context *tiler_ctx, void *out)
719*61046927SAndroid Build Coastguard Worker {
720*61046927SAndroid Build Coastguard Worker void *fbd = out;
721*61046927SAndroid Build Coastguard Worker void *rtd = out + pan_size(FRAMEBUFFER);
722*61046927SAndroid Build Coastguard Worker
723*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 5
724*61046927SAndroid Build Coastguard Worker GENX(pan_emit_tls)(tls, pan_section_ptr(fbd, FRAMEBUFFER, LOCAL_STORAGE));
725*61046927SAndroid Build Coastguard Worker #endif
726*61046927SAndroid Build Coastguard Worker
727*61046927SAndroid Build Coastguard Worker unsigned bytes_per_pixel = pan_cbuf_bytes_per_pixel(fb);
728*61046927SAndroid Build Coastguard Worker unsigned tile_size =
729*61046927SAndroid Build Coastguard Worker pan_select_max_tile_size(fb->tile_buf_budget, bytes_per_pixel);
730*61046927SAndroid Build Coastguard Worker
731*61046927SAndroid Build Coastguard Worker /* Clamp tile size to hardware limits */
732*61046927SAndroid Build Coastguard Worker tile_size = MIN2(tile_size, 16 * 16);
733*61046927SAndroid Build Coastguard Worker assert(tile_size >= 4 * 4);
734*61046927SAndroid Build Coastguard Worker
735*61046927SAndroid Build Coastguard Worker /* Colour buffer allocations must be 1K aligned. */
736*61046927SAndroid Build Coastguard Worker unsigned cbuf_allocation = ALIGN_POT(bytes_per_pixel * tile_size, 1024);
737*61046927SAndroid Build Coastguard Worker assert(cbuf_allocation <= fb->tile_buf_budget && "tile too big");
738*61046927SAndroid Build Coastguard Worker
739*61046927SAndroid Build Coastguard Worker int crc_rt = GENX(pan_select_crc_rt)(fb, tile_size);
740*61046927SAndroid Build Coastguard Worker bool has_zs_crc_ext = (fb->zs.view.zs || fb->zs.view.s || crc_rt >= 0);
741*61046927SAndroid Build Coastguard Worker
742*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, PARAMETERS, cfg) {
743*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
744*61046927SAndroid Build Coastguard Worker bool force_clean_write = pan_force_clean_write(fb, tile_size);
745*61046927SAndroid Build Coastguard Worker
746*61046927SAndroid Build Coastguard Worker cfg.sample_locations = fb->sample_positions;
747*61046927SAndroid Build Coastguard Worker cfg.pre_frame_0 = pan_fix_frame_shader_mode(fb->bifrost.pre_post.modes[0],
748*61046927SAndroid Build Coastguard Worker force_clean_write);
749*61046927SAndroid Build Coastguard Worker cfg.pre_frame_1 = pan_fix_frame_shader_mode(fb->bifrost.pre_post.modes[1],
750*61046927SAndroid Build Coastguard Worker force_clean_write);
751*61046927SAndroid Build Coastguard Worker cfg.post_frame = pan_fix_frame_shader_mode(fb->bifrost.pre_post.modes[2],
752*61046927SAndroid Build Coastguard Worker force_clean_write);
753*61046927SAndroid Build Coastguard Worker cfg.frame_shader_dcds = fb->bifrost.pre_post.dcds.gpu;
754*61046927SAndroid Build Coastguard Worker cfg.tiler =
755*61046927SAndroid Build Coastguard Worker PAN_ARCH >= 9 ? tiler_ctx->valhall.desc : tiler_ctx->bifrost.desc;
756*61046927SAndroid Build Coastguard Worker #endif
757*61046927SAndroid Build Coastguard Worker cfg.width = fb->width;
758*61046927SAndroid Build Coastguard Worker cfg.height = fb->height;
759*61046927SAndroid Build Coastguard Worker cfg.bound_max_x = fb->width - 1;
760*61046927SAndroid Build Coastguard Worker cfg.bound_max_y = fb->height - 1;
761*61046927SAndroid Build Coastguard Worker
762*61046927SAndroid Build Coastguard Worker cfg.effective_tile_size = tile_size;
763*61046927SAndroid Build Coastguard Worker cfg.tie_break_rule = MALI_TIE_BREAK_RULE_MINUS_180_IN_0_OUT;
764*61046927SAndroid Build Coastguard Worker cfg.render_target_count = MAX2(fb->rt_count, 1);
765*61046927SAndroid Build Coastguard Worker
766*61046927SAndroid Build Coastguard Worker /* Default to 24 bit depth if there's no surface. */
767*61046927SAndroid Build Coastguard Worker cfg.z_internal_format =
768*61046927SAndroid Build Coastguard Worker fb->zs.view.zs ? panfrost_get_z_internal_format(fb->zs.view.zs->format)
769*61046927SAndroid Build Coastguard Worker : MALI_Z_INTERNAL_FORMAT_D24;
770*61046927SAndroid Build Coastguard Worker
771*61046927SAndroid Build Coastguard Worker cfg.z_clear = fb->zs.clear_value.depth;
772*61046927SAndroid Build Coastguard Worker cfg.s_clear = fb->zs.clear_value.stencil;
773*61046927SAndroid Build Coastguard Worker cfg.color_buffer_allocation = cbuf_allocation;
774*61046927SAndroid Build Coastguard Worker
775*61046927SAndroid Build Coastguard Worker /* The force_samples setting dictates the sample-count that is used
776*61046927SAndroid Build Coastguard Worker * for rasterization, and works like D3D11's ForcedSampleCount feature:
777*61046927SAndroid Build Coastguard Worker *
778*61046927SAndroid Build Coastguard Worker * - If force_samples == 0: Let nr_samples dictate sample count
779*61046927SAndroid Build Coastguard Worker * - If force_samples == 1: force single-sampled rasterization
780*61046927SAndroid Build Coastguard Worker * - If force_samples >= 1: force multi-sampled rasterization
781*61046927SAndroid Build Coastguard Worker *
782*61046927SAndroid Build Coastguard Worker * This can be used to read SYSTEM_VALUE_SAMPLE_MASK_IN from the
783*61046927SAndroid Build Coastguard Worker * fragment shader, even when performing single-sampled rendering.
784*61046927SAndroid Build Coastguard Worker */
785*61046927SAndroid Build Coastguard Worker if (!fb->force_samples) {
786*61046927SAndroid Build Coastguard Worker cfg.sample_count = fb->nr_samples;
787*61046927SAndroid Build Coastguard Worker cfg.sample_pattern = pan_sample_pattern(fb->nr_samples);
788*61046927SAndroid Build Coastguard Worker } else if (fb->force_samples == 1) {
789*61046927SAndroid Build Coastguard Worker cfg.sample_count = fb->nr_samples;
790*61046927SAndroid Build Coastguard Worker cfg.sample_pattern = pan_sample_pattern(1);
791*61046927SAndroid Build Coastguard Worker } else {
792*61046927SAndroid Build Coastguard Worker cfg.sample_count = 1;
793*61046927SAndroid Build Coastguard Worker cfg.sample_pattern = pan_sample_pattern(fb->force_samples);
794*61046927SAndroid Build Coastguard Worker }
795*61046927SAndroid Build Coastguard Worker
796*61046927SAndroid Build Coastguard Worker cfg.z_write_enable = (fb->zs.view.zs && !fb->zs.discard.z);
797*61046927SAndroid Build Coastguard Worker cfg.s_write_enable = (fb->zs.view.s && !fb->zs.discard.s);
798*61046927SAndroid Build Coastguard Worker cfg.has_zs_crc_extension = has_zs_crc_ext;
799*61046927SAndroid Build Coastguard Worker
800*61046927SAndroid Build Coastguard Worker if (crc_rt >= 0) {
801*61046927SAndroid Build Coastguard Worker bool *valid = fb->rts[crc_rt].crc_valid;
802*61046927SAndroid Build Coastguard Worker bool full = !fb->extent.minx && !fb->extent.miny &&
803*61046927SAndroid Build Coastguard Worker fb->extent.maxx == (fb->width - 1) &&
804*61046927SAndroid Build Coastguard Worker fb->extent.maxy == (fb->height - 1);
805*61046927SAndroid Build Coastguard Worker
806*61046927SAndroid Build Coastguard Worker cfg.crc_read_enable = *valid;
807*61046927SAndroid Build Coastguard Worker
808*61046927SAndroid Build Coastguard Worker /* If the data is currently invalid, still write CRC
809*61046927SAndroid Build Coastguard Worker * data if we are doing a full write, so that it is
810*61046927SAndroid Build Coastguard Worker * valid for next time. */
811*61046927SAndroid Build Coastguard Worker cfg.crc_write_enable = *valid || full;
812*61046927SAndroid Build Coastguard Worker
813*61046927SAndroid Build Coastguard Worker *valid |= full;
814*61046927SAndroid Build Coastguard Worker }
815*61046927SAndroid Build Coastguard Worker
816*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 9
817*61046927SAndroid Build Coastguard Worker cfg.point_sprite_coord_origin_max_y = fb->sprite_coord_origin;
818*61046927SAndroid Build Coastguard Worker cfg.first_provoking_vertex = fb->first_provoking_vertex;
819*61046927SAndroid Build Coastguard Worker
820*61046927SAndroid Build Coastguard Worker /* internal_layer_index is used to select the right primitive list in the
821*61046927SAndroid Build Coastguard Worker * tiler context, and frame_arg is the value that's passed to the fragment
822*61046927SAndroid Build Coastguard Worker * shader through r62-r63, which we use to pass gl_Layer. Since the
823*61046927SAndroid Build Coastguard Worker * layer_idx only takes 8-bits, we might use the extra 56-bits we have
824*61046927SAndroid Build Coastguard Worker * in frame_argument to pass other information to the fragment shader at
825*61046927SAndroid Build Coastguard Worker * some point. */
826*61046927SAndroid Build Coastguard Worker cfg.internal_layer_index = layer_idx;
827*61046927SAndroid Build Coastguard Worker cfg.frame_argument = layer_idx;
828*61046927SAndroid Build Coastguard Worker #endif
829*61046927SAndroid Build Coastguard Worker }
830*61046927SAndroid Build Coastguard Worker
831*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 6
832*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, PADDING, padding)
833*61046927SAndroid Build Coastguard Worker ;
834*61046927SAndroid Build Coastguard Worker #else
835*61046927SAndroid Build Coastguard Worker pan_emit_midgard_tiler(fb, tiler_ctx,
836*61046927SAndroid Build Coastguard Worker pan_section_ptr(fbd, FRAMEBUFFER, TILER));
837*61046927SAndroid Build Coastguard Worker
838*61046927SAndroid Build Coastguard Worker /* All weights set to 0, nothing to do here */
839*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, TILER_WEIGHTS, w)
840*61046927SAndroid Build Coastguard Worker ;
841*61046927SAndroid Build Coastguard Worker #endif
842*61046927SAndroid Build Coastguard Worker
843*61046927SAndroid Build Coastguard Worker if (has_zs_crc_ext) {
844*61046927SAndroid Build Coastguard Worker pan_emit_zs_crc_ext(fb, layer_idx, crc_rt, out + pan_size(FRAMEBUFFER));
845*61046927SAndroid Build Coastguard Worker rtd += pan_size(ZS_CRC_EXTENSION);
846*61046927SAndroid Build Coastguard Worker }
847*61046927SAndroid Build Coastguard Worker
848*61046927SAndroid Build Coastguard Worker unsigned rt_count = MAX2(fb->rt_count, 1);
849*61046927SAndroid Build Coastguard Worker unsigned cbuf_offset = 0;
850*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < rt_count; i++) {
851*61046927SAndroid Build Coastguard Worker pan_emit_rt(fb, layer_idx, i, cbuf_offset, rtd);
852*61046927SAndroid Build Coastguard Worker rtd += pan_size(RENDER_TARGET);
853*61046927SAndroid Build Coastguard Worker if (!fb->rts[i].view)
854*61046927SAndroid Build Coastguard Worker continue;
855*61046927SAndroid Build Coastguard Worker
856*61046927SAndroid Build Coastguard Worker cbuf_offset += pan_bytes_per_pixel_tib(fb->rts[i].view->format) *
857*61046927SAndroid Build Coastguard Worker tile_size * pan_image_view_get_nr_samples(fb->rts[i].view);
858*61046927SAndroid Build Coastguard Worker
859*61046927SAndroid Build Coastguard Worker if (i != crc_rt)
860*61046927SAndroid Build Coastguard Worker *(fb->rts[i].crc_valid) = false;
861*61046927SAndroid Build Coastguard Worker }
862*61046927SAndroid Build Coastguard Worker
863*61046927SAndroid Build Coastguard Worker struct mali_framebuffer_pointer_packed tag;
864*61046927SAndroid Build Coastguard Worker pan_pack(tag.opaque, FRAMEBUFFER_POINTER, cfg) {
865*61046927SAndroid Build Coastguard Worker cfg.zs_crc_extension_present = has_zs_crc_ext;
866*61046927SAndroid Build Coastguard Worker cfg.render_target_count = MAX2(fb->rt_count, 1);
867*61046927SAndroid Build Coastguard Worker }
868*61046927SAndroid Build Coastguard Worker return tag.opaque[0];
869*61046927SAndroid Build Coastguard Worker }
870*61046927SAndroid Build Coastguard Worker #else /* PAN_ARCH == 4 */
871*61046927SAndroid Build Coastguard Worker static enum mali_color_format
pan_sfbd_raw_format(unsigned bits)872*61046927SAndroid Build Coastguard Worker pan_sfbd_raw_format(unsigned bits)
873*61046927SAndroid Build Coastguard Worker {
874*61046927SAndroid Build Coastguard Worker /* clang-format off */
875*61046927SAndroid Build Coastguard Worker switch (bits) {
876*61046927SAndroid Build Coastguard Worker case 16: return MALI_COLOR_FORMAT_1_16B_CHANNEL;
877*61046927SAndroid Build Coastguard Worker case 32: return MALI_COLOR_FORMAT_1_32B_CHANNEL;
878*61046927SAndroid Build Coastguard Worker case 48: return MALI_COLOR_FORMAT_3_16B_CHANNELS;
879*61046927SAndroid Build Coastguard Worker case 64: return MALI_COLOR_FORMAT_2_32B_CHANNELS;
880*61046927SAndroid Build Coastguard Worker case 96: return MALI_COLOR_FORMAT_3_32B_CHANNELS;
881*61046927SAndroid Build Coastguard Worker case 128: return MALI_COLOR_FORMAT_4_32B_CHANNELS;
882*61046927SAndroid Build Coastguard Worker default: unreachable("invalid raw bpp");
883*61046927SAndroid Build Coastguard Worker }
884*61046927SAndroid Build Coastguard Worker /* clang-format on */
885*61046927SAndroid Build Coastguard Worker }
886*61046927SAndroid Build Coastguard Worker unsigned
GENX(pan_emit_fbd)887*61046927SAndroid Build Coastguard Worker GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx,
888*61046927SAndroid Build Coastguard Worker const struct pan_tls_info *tls,
889*61046927SAndroid Build Coastguard Worker const struct pan_tiler_context *tiler_ctx, void *fbd)
890*61046927SAndroid Build Coastguard Worker {
891*61046927SAndroid Build Coastguard Worker assert(fb->rt_count <= 1);
892*61046927SAndroid Build Coastguard Worker
893*61046927SAndroid Build Coastguard Worker GENX(pan_emit_tls)(tls, pan_section_ptr(fbd, FRAMEBUFFER, LOCAL_STORAGE));
894*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, PARAMETERS, cfg) {
895*61046927SAndroid Build Coastguard Worker cfg.bound_max_x = fb->width - 1;
896*61046927SAndroid Build Coastguard Worker cfg.bound_max_y = fb->height - 1;
897*61046927SAndroid Build Coastguard Worker cfg.dithering_enable = true;
898*61046927SAndroid Build Coastguard Worker cfg.clean_pixel_write_enable = true;
899*61046927SAndroid Build Coastguard Worker cfg.tie_break_rule = MALI_TIE_BREAK_RULE_MINUS_180_IN_0_OUT;
900*61046927SAndroid Build Coastguard Worker if (fb->rts[0].clear) {
901*61046927SAndroid Build Coastguard Worker cfg.clear_color_0 = fb->rts[0].clear_value[0];
902*61046927SAndroid Build Coastguard Worker cfg.clear_color_1 = fb->rts[0].clear_value[1];
903*61046927SAndroid Build Coastguard Worker cfg.clear_color_2 = fb->rts[0].clear_value[2];
904*61046927SAndroid Build Coastguard Worker cfg.clear_color_3 = fb->rts[0].clear_value[3];
905*61046927SAndroid Build Coastguard Worker }
906*61046927SAndroid Build Coastguard Worker
907*61046927SAndroid Build Coastguard Worker if (fb->zs.clear.z)
908*61046927SAndroid Build Coastguard Worker cfg.z_clear = fb->zs.clear_value.depth;
909*61046927SAndroid Build Coastguard Worker
910*61046927SAndroid Build Coastguard Worker if (fb->zs.clear.s)
911*61046927SAndroid Build Coastguard Worker cfg.s_clear = fb->zs.clear_value.stencil;
912*61046927SAndroid Build Coastguard Worker
913*61046927SAndroid Build Coastguard Worker if (fb->rt_count && fb->rts[0].view) {
914*61046927SAndroid Build Coastguard Worker const struct pan_image_view *rt = fb->rts[0].view;
915*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_rt_image(rt);
916*61046927SAndroid Build Coastguard Worker
917*61046927SAndroid Build Coastguard Worker const struct util_format_description *desc =
918*61046927SAndroid Build Coastguard Worker util_format_description(rt->format);
919*61046927SAndroid Build Coastguard Worker
920*61046927SAndroid Build Coastguard Worker /* The swizzle for rendering is inverted from texturing */
921*61046927SAndroid Build Coastguard Worker unsigned char swizzle[4];
922*61046927SAndroid Build Coastguard Worker panfrost_invert_swizzle(desc->swizzle, swizzle);
923*61046927SAndroid Build Coastguard Worker cfg.swizzle = panfrost_translate_swizzle_4(swizzle);
924*61046927SAndroid Build Coastguard Worker
925*61046927SAndroid Build Coastguard Worker struct pan_blendable_format fmt =
926*61046927SAndroid Build Coastguard Worker *GENX(panfrost_blendable_format_from_pipe_format)(rt->format);
927*61046927SAndroid Build Coastguard Worker
928*61046927SAndroid Build Coastguard Worker if (fmt.internal) {
929*61046927SAndroid Build Coastguard Worker cfg.internal_format = fmt.internal;
930*61046927SAndroid Build Coastguard Worker cfg.color_writeback_format = fmt.writeback;
931*61046927SAndroid Build Coastguard Worker } else {
932*61046927SAndroid Build Coastguard Worker /* Construct RAW internal/writeback */
933*61046927SAndroid Build Coastguard Worker unsigned bits = desc->block.bits;
934*61046927SAndroid Build Coastguard Worker
935*61046927SAndroid Build Coastguard Worker cfg.internal_format = MALI_COLOR_BUFFER_INTERNAL_FORMAT_RAW_VALUE;
936*61046927SAndroid Build Coastguard Worker cfg.color_writeback_format = pan_sfbd_raw_format(bits);
937*61046927SAndroid Build Coastguard Worker }
938*61046927SAndroid Build Coastguard Worker
939*61046927SAndroid Build Coastguard Worker unsigned level = rt->first_level;
940*61046927SAndroid Build Coastguard Worker struct pan_surface surf;
941*61046927SAndroid Build Coastguard Worker
942*61046927SAndroid Build Coastguard Worker pan_iview_get_surface(rt, 0, 0, 0, &surf);
943*61046927SAndroid Build Coastguard Worker
944*61046927SAndroid Build Coastguard Worker cfg.color_write_enable = !fb->rts[0].discard;
945*61046927SAndroid Build Coastguard Worker cfg.color_writeback.base = surf.data;
946*61046927SAndroid Build Coastguard Worker cfg.color_writeback.row_stride =
947*61046927SAndroid Build Coastguard Worker image->layout.slices[level].row_stride;
948*61046927SAndroid Build Coastguard Worker
949*61046927SAndroid Build Coastguard Worker cfg.color_block_format = mod_to_block_fmt(image->layout.modifier);
950*61046927SAndroid Build Coastguard Worker assert(cfg.color_block_format == MALI_BLOCK_FORMAT_LINEAR ||
951*61046927SAndroid Build Coastguard Worker cfg.color_block_format ==
952*61046927SAndroid Build Coastguard Worker MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED);
953*61046927SAndroid Build Coastguard Worker
954*61046927SAndroid Build Coastguard Worker if (pan_image_view_has_crc(rt)) {
955*61046927SAndroid Build Coastguard Worker const struct pan_image_slice_layout *slice =
956*61046927SAndroid Build Coastguard Worker &image->layout.slices[level];
957*61046927SAndroid Build Coastguard Worker
958*61046927SAndroid Build Coastguard Worker cfg.crc_buffer.row_stride = slice->crc.stride;
959*61046927SAndroid Build Coastguard Worker cfg.crc_buffer.base =
960*61046927SAndroid Build Coastguard Worker image->data.base + image->data.offset + slice->crc.offset;
961*61046927SAndroid Build Coastguard Worker }
962*61046927SAndroid Build Coastguard Worker }
963*61046927SAndroid Build Coastguard Worker
964*61046927SAndroid Build Coastguard Worker if (fb->zs.view.zs) {
965*61046927SAndroid Build Coastguard Worker const struct pan_image_view *zs = fb->zs.view.zs;
966*61046927SAndroid Build Coastguard Worker const struct pan_image *image = pan_image_view_get_zs_image(zs);
967*61046927SAndroid Build Coastguard Worker unsigned level = zs->first_level;
968*61046927SAndroid Build Coastguard Worker struct pan_surface surf;
969*61046927SAndroid Build Coastguard Worker
970*61046927SAndroid Build Coastguard Worker pan_iview_get_surface(zs, 0, 0, 0, &surf);
971*61046927SAndroid Build Coastguard Worker
972*61046927SAndroid Build Coastguard Worker cfg.zs_write_enable = !fb->zs.discard.z;
973*61046927SAndroid Build Coastguard Worker cfg.zs_writeback.base = surf.data;
974*61046927SAndroid Build Coastguard Worker cfg.zs_writeback.row_stride = image->layout.slices[level].row_stride;
975*61046927SAndroid Build Coastguard Worker cfg.zs_block_format = mod_to_block_fmt(image->layout.modifier);
976*61046927SAndroid Build Coastguard Worker assert(cfg.zs_block_format == MALI_BLOCK_FORMAT_LINEAR ||
977*61046927SAndroid Build Coastguard Worker cfg.zs_block_format == MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED);
978*61046927SAndroid Build Coastguard Worker
979*61046927SAndroid Build Coastguard Worker cfg.zs_format = translate_zs_format(zs->format);
980*61046927SAndroid Build Coastguard Worker }
981*61046927SAndroid Build Coastguard Worker
982*61046927SAndroid Build Coastguard Worker cfg.sample_count = fb->nr_samples;
983*61046927SAndroid Build Coastguard Worker
984*61046927SAndroid Build Coastguard Worker if (fb->rt_count)
985*61046927SAndroid Build Coastguard Worker cfg.msaa = mali_sampling_mode(fb->rts[0].view);
986*61046927SAndroid Build Coastguard Worker }
987*61046927SAndroid Build Coastguard Worker
988*61046927SAndroid Build Coastguard Worker pan_emit_midgard_tiler(fb, tiler_ctx,
989*61046927SAndroid Build Coastguard Worker pan_section_ptr(fbd, FRAMEBUFFER, TILER));
990*61046927SAndroid Build Coastguard Worker
991*61046927SAndroid Build Coastguard Worker /* All weights set to 0, nothing to do here */
992*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, TILER_WEIGHTS, w)
993*61046927SAndroid Build Coastguard Worker ;
994*61046927SAndroid Build Coastguard Worker
995*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, PADDING_1, padding)
996*61046927SAndroid Build Coastguard Worker ;
997*61046927SAndroid Build Coastguard Worker pan_section_pack(fbd, FRAMEBUFFER, PADDING_2, padding)
998*61046927SAndroid Build Coastguard Worker ;
999*61046927SAndroid Build Coastguard Worker return 0;
1000*61046927SAndroid Build Coastguard Worker }
1001*61046927SAndroid Build Coastguard Worker #endif
1002*61046927SAndroid Build Coastguard Worker
1003*61046927SAndroid Build Coastguard Worker #if PAN_ARCH <= 9
1004*61046927SAndroid Build Coastguard Worker void
GENX(pan_emit_fragment_job_payload)1005*61046927SAndroid Build Coastguard Worker GENX(pan_emit_fragment_job_payload)(const struct pan_fb_info *fb, mali_ptr fbd,
1006*61046927SAndroid Build Coastguard Worker void *out)
1007*61046927SAndroid Build Coastguard Worker {
1008*61046927SAndroid Build Coastguard Worker pan_section_pack(out, FRAGMENT_JOB, PAYLOAD, payload) {
1009*61046927SAndroid Build Coastguard Worker payload.bound_min_x = fb->extent.minx >> MALI_TILE_SHIFT;
1010*61046927SAndroid Build Coastguard Worker payload.bound_min_y = fb->extent.miny >> MALI_TILE_SHIFT;
1011*61046927SAndroid Build Coastguard Worker payload.bound_max_x = fb->extent.maxx >> MALI_TILE_SHIFT;
1012*61046927SAndroid Build Coastguard Worker payload.bound_max_y = fb->extent.maxy >> MALI_TILE_SHIFT;
1013*61046927SAndroid Build Coastguard Worker payload.framebuffer = fbd;
1014*61046927SAndroid Build Coastguard Worker
1015*61046927SAndroid Build Coastguard Worker #if PAN_ARCH >= 5
1016*61046927SAndroid Build Coastguard Worker if (fb->tile_map.base) {
1017*61046927SAndroid Build Coastguard Worker payload.has_tile_enable_map = true;
1018*61046927SAndroid Build Coastguard Worker payload.tile_enable_map = fb->tile_map.base;
1019*61046927SAndroid Build Coastguard Worker payload.tile_enable_map_row_stride = fb->tile_map.stride;
1020*61046927SAndroid Build Coastguard Worker }
1021*61046927SAndroid Build Coastguard Worker #endif
1022*61046927SAndroid Build Coastguard Worker }
1023*61046927SAndroid Build Coastguard Worker }
1024*61046927SAndroid Build Coastguard Worker #endif
1025