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