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