18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2014-2015 Broadcom 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218c2ecf20Sopenharmony_ci * IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/** 258c2ecf20Sopenharmony_ci * DOC: Render command list generation 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * In the V3D hardware, render command lists are what load and store 288c2ecf20Sopenharmony_ci * tiles of a framebuffer and optionally call out to binner-generated 298c2ecf20Sopenharmony_ci * command lists to do the 3D drawing for that tile. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * In the VC4 driver, render command list generation is performed by the 328c2ecf20Sopenharmony_ci * kernel instead of userspace. We do this because validating a 338c2ecf20Sopenharmony_ci * user-submitted command list is hard to get right and has high CPU overhead, 348c2ecf20Sopenharmony_ci * while the number of valid configurations for render command lists is 358c2ecf20Sopenharmony_ci * actually fairly low. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include "uapi/drm/vc4_drm.h" 398c2ecf20Sopenharmony_ci#include "vc4_drv.h" 408c2ecf20Sopenharmony_ci#include "vc4_packet.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct vc4_rcl_setup { 438c2ecf20Sopenharmony_ci struct drm_gem_cma_object *color_read; 448c2ecf20Sopenharmony_ci struct drm_gem_cma_object *color_write; 458c2ecf20Sopenharmony_ci struct drm_gem_cma_object *zs_read; 468c2ecf20Sopenharmony_ci struct drm_gem_cma_object *zs_write; 478c2ecf20Sopenharmony_ci struct drm_gem_cma_object *msaa_color_write; 488c2ecf20Sopenharmony_ci struct drm_gem_cma_object *msaa_zs_write; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci struct drm_gem_cma_object *rcl; 518c2ecf20Sopenharmony_ci u32 next_offset; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci u32 next_write_bo_index; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic inline void rcl_u8(struct vc4_rcl_setup *setup, u8 val) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci *(u8 *)(setup->rcl->vaddr + setup->next_offset) = val; 598c2ecf20Sopenharmony_ci setup->next_offset += 1; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic inline void rcl_u16(struct vc4_rcl_setup *setup, u16 val) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci *(u16 *)(setup->rcl->vaddr + setup->next_offset) = val; 658c2ecf20Sopenharmony_ci setup->next_offset += 2; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic inline void rcl_u32(struct vc4_rcl_setup *setup, u32 val) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci *(u32 *)(setup->rcl->vaddr + setup->next_offset) = val; 718c2ecf20Sopenharmony_ci setup->next_offset += 4; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* 758c2ecf20Sopenharmony_ci * Emits a no-op STORE_TILE_BUFFER_GENERAL. 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * If we emit a PACKET_TILE_COORDINATES, it must be followed by a store of 788c2ecf20Sopenharmony_ci * some sort before another load is triggered. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_cistatic void vc4_store_before_load(struct vc4_rcl_setup *setup) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL); 838c2ecf20Sopenharmony_ci rcl_u16(setup, 848c2ecf20Sopenharmony_ci VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_NONE, 858c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_BUFFER) | 868c2ecf20Sopenharmony_ci VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR | 878c2ecf20Sopenharmony_ci VC4_STORE_TILE_BUFFER_DISABLE_ZS_CLEAR | 888c2ecf20Sopenharmony_ci VC4_STORE_TILE_BUFFER_DISABLE_VG_MASK_CLEAR); 898c2ecf20Sopenharmony_ci rcl_u32(setup, 0); /* no address, since we're in None mode */ 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* 938c2ecf20Sopenharmony_ci * Calculates the physical address of the start of a tile in a RCL surface. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * Unlike the other load/store packets, 968c2ecf20Sopenharmony_ci * VC4_PACKET_LOAD/STORE_FULL_RES_TILE_BUFFER don't look at the tile 978c2ecf20Sopenharmony_ci * coordinates packet, and instead just store to the address given. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_cistatic uint32_t vc4_full_res_offset(struct vc4_exec_info *exec, 1008c2ecf20Sopenharmony_ci struct drm_gem_cma_object *bo, 1018c2ecf20Sopenharmony_ci struct drm_vc4_submit_rcl_surface *surf, 1028c2ecf20Sopenharmony_ci uint8_t x, uint8_t y) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return bo->paddr + surf->offset + VC4_TILE_BUFFER_SIZE * 1058c2ecf20Sopenharmony_ci (DIV_ROUND_UP(exec->args->width, 32) * y + x); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * Emits a PACKET_TILE_COORDINATES if one isn't already pending. 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * The tile coordinates packet triggers a pending load if there is one, are 1128c2ecf20Sopenharmony_ci * used for clipping during rendering, and determine where loads/stores happen 1138c2ecf20Sopenharmony_ci * relative to their base address. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_cistatic void vc4_tile_coordinates(struct vc4_rcl_setup *setup, 1168c2ecf20Sopenharmony_ci uint32_t x, uint32_t y) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_TILE_COORDINATES); 1198c2ecf20Sopenharmony_ci rcl_u8(setup, x); 1208c2ecf20Sopenharmony_ci rcl_u8(setup, y); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic void emit_tile(struct vc4_exec_info *exec, 1248c2ecf20Sopenharmony_ci struct vc4_rcl_setup *setup, 1258c2ecf20Sopenharmony_ci uint8_t x, uint8_t y, bool first, bool last) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct drm_vc4_submit_cl *args = exec->args; 1288c2ecf20Sopenharmony_ci bool has_bin = args->bin_cl_size != 0; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Note that the load doesn't actually occur until the 1318c2ecf20Sopenharmony_ci * tile coords packet is processed, and only one load 1328c2ecf20Sopenharmony_ci * may be outstanding at a time. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci if (setup->color_read) { 1358c2ecf20Sopenharmony_ci if (args->color_read.flags & 1368c2ecf20Sopenharmony_ci VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 1378c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER); 1388c2ecf20Sopenharmony_ci rcl_u32(setup, 1398c2ecf20Sopenharmony_ci vc4_full_res_offset(exec, setup->color_read, 1408c2ecf20Sopenharmony_ci &args->color_read, x, y) | 1418c2ecf20Sopenharmony_ci VC4_LOADSTORE_FULL_RES_DISABLE_ZS); 1428c2ecf20Sopenharmony_ci } else { 1438c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL); 1448c2ecf20Sopenharmony_ci rcl_u16(setup, args->color_read.bits); 1458c2ecf20Sopenharmony_ci rcl_u32(setup, setup->color_read->paddr + 1468c2ecf20Sopenharmony_ci args->color_read.offset); 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (setup->zs_read) { 1518c2ecf20Sopenharmony_ci if (setup->color_read) { 1528c2ecf20Sopenharmony_ci /* Exec previous load. */ 1538c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, x, y); 1548c2ecf20Sopenharmony_ci vc4_store_before_load(setup); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (args->zs_read.flags & 1588c2ecf20Sopenharmony_ci VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 1598c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER); 1608c2ecf20Sopenharmony_ci rcl_u32(setup, 1618c2ecf20Sopenharmony_ci vc4_full_res_offset(exec, setup->zs_read, 1628c2ecf20Sopenharmony_ci &args->zs_read, x, y) | 1638c2ecf20Sopenharmony_ci VC4_LOADSTORE_FULL_RES_DISABLE_COLOR); 1648c2ecf20Sopenharmony_ci } else { 1658c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL); 1668c2ecf20Sopenharmony_ci rcl_u16(setup, args->zs_read.bits); 1678c2ecf20Sopenharmony_ci rcl_u32(setup, setup->zs_read->paddr + 1688c2ecf20Sopenharmony_ci args->zs_read.offset); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* Clipping depends on tile coordinates having been 1738c2ecf20Sopenharmony_ci * emitted, so we always need one here. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, x, y); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* Wait for the binner before jumping to the first 1788c2ecf20Sopenharmony_ci * tile's lists. 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci if (first && has_bin) 1818c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_WAIT_ON_SEMAPHORE); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (has_bin) { 1848c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_BRANCH_TO_SUB_LIST); 1858c2ecf20Sopenharmony_ci rcl_u32(setup, (exec->tile_alloc_offset + 1868c2ecf20Sopenharmony_ci (y * exec->bin_tiles_x + x) * 32)); 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (setup->msaa_color_write) { 1908c2ecf20Sopenharmony_ci bool last_tile_write = (!setup->msaa_zs_write && 1918c2ecf20Sopenharmony_ci !setup->zs_write && 1928c2ecf20Sopenharmony_ci !setup->color_write); 1938c2ecf20Sopenharmony_ci uint32_t bits = VC4_LOADSTORE_FULL_RES_DISABLE_ZS; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (!last_tile_write) 1968c2ecf20Sopenharmony_ci bits |= VC4_LOADSTORE_FULL_RES_DISABLE_CLEAR_ALL; 1978c2ecf20Sopenharmony_ci else if (last) 1988c2ecf20Sopenharmony_ci bits |= VC4_LOADSTORE_FULL_RES_EOF; 1998c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_FULL_RES_TILE_BUFFER); 2008c2ecf20Sopenharmony_ci rcl_u32(setup, 2018c2ecf20Sopenharmony_ci vc4_full_res_offset(exec, setup->msaa_color_write, 2028c2ecf20Sopenharmony_ci &args->msaa_color_write, x, y) | 2038c2ecf20Sopenharmony_ci bits); 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (setup->msaa_zs_write) { 2078c2ecf20Sopenharmony_ci bool last_tile_write = (!setup->zs_write && 2088c2ecf20Sopenharmony_ci !setup->color_write); 2098c2ecf20Sopenharmony_ci uint32_t bits = VC4_LOADSTORE_FULL_RES_DISABLE_COLOR; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (setup->msaa_color_write) 2128c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, x, y); 2138c2ecf20Sopenharmony_ci if (!last_tile_write) 2148c2ecf20Sopenharmony_ci bits |= VC4_LOADSTORE_FULL_RES_DISABLE_CLEAR_ALL; 2158c2ecf20Sopenharmony_ci else if (last) 2168c2ecf20Sopenharmony_ci bits |= VC4_LOADSTORE_FULL_RES_EOF; 2178c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_FULL_RES_TILE_BUFFER); 2188c2ecf20Sopenharmony_ci rcl_u32(setup, 2198c2ecf20Sopenharmony_ci vc4_full_res_offset(exec, setup->msaa_zs_write, 2208c2ecf20Sopenharmony_ci &args->msaa_zs_write, x, y) | 2218c2ecf20Sopenharmony_ci bits); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (setup->zs_write) { 2258c2ecf20Sopenharmony_ci bool last_tile_write = !setup->color_write; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (setup->msaa_color_write || setup->msaa_zs_write) 2288c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, x, y); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL); 2318c2ecf20Sopenharmony_ci rcl_u16(setup, args->zs_write.bits | 2328c2ecf20Sopenharmony_ci (last_tile_write ? 2338c2ecf20Sopenharmony_ci 0 : VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR)); 2348c2ecf20Sopenharmony_ci rcl_u32(setup, 2358c2ecf20Sopenharmony_ci (setup->zs_write->paddr + args->zs_write.offset) | 2368c2ecf20Sopenharmony_ci ((last && last_tile_write) ? 2378c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_EOF : 0)); 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (setup->color_write) { 2418c2ecf20Sopenharmony_ci if (setup->msaa_color_write || setup->msaa_zs_write || 2428c2ecf20Sopenharmony_ci setup->zs_write) { 2438c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, x, y); 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci if (last) 2478c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF); 2488c2ecf20Sopenharmony_ci else 2498c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_MS_TILE_BUFFER); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec, 2548c2ecf20Sopenharmony_ci struct vc4_rcl_setup *setup) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct drm_vc4_submit_cl *args = exec->args; 2578c2ecf20Sopenharmony_ci bool has_bin = args->bin_cl_size != 0; 2588c2ecf20Sopenharmony_ci uint8_t min_x_tile = args->min_x_tile; 2598c2ecf20Sopenharmony_ci uint8_t min_y_tile = args->min_y_tile; 2608c2ecf20Sopenharmony_ci uint8_t max_x_tile = args->max_x_tile; 2618c2ecf20Sopenharmony_ci uint8_t max_y_tile = args->max_y_tile; 2628c2ecf20Sopenharmony_ci uint8_t xtiles = max_x_tile - min_x_tile + 1; 2638c2ecf20Sopenharmony_ci uint8_t ytiles = max_y_tile - min_y_tile + 1; 2648c2ecf20Sopenharmony_ci uint8_t xi, yi; 2658c2ecf20Sopenharmony_ci uint32_t size, loop_body_size; 2668c2ecf20Sopenharmony_ci bool positive_x = true; 2678c2ecf20Sopenharmony_ci bool positive_y = true; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (args->flags & VC4_SUBMIT_CL_FIXED_RCL_ORDER) { 2708c2ecf20Sopenharmony_ci if (!(args->flags & VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X)) 2718c2ecf20Sopenharmony_ci positive_x = false; 2728c2ecf20Sopenharmony_ci if (!(args->flags & VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y)) 2738c2ecf20Sopenharmony_ci positive_y = false; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci size = VC4_PACKET_TILE_RENDERING_MODE_CONFIG_SIZE; 2778c2ecf20Sopenharmony_ci loop_body_size = VC4_PACKET_TILE_COORDINATES_SIZE; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (args->flags & VC4_SUBMIT_CL_USE_CLEAR_COLOR) { 2808c2ecf20Sopenharmony_ci size += VC4_PACKET_CLEAR_COLORS_SIZE + 2818c2ecf20Sopenharmony_ci VC4_PACKET_TILE_COORDINATES_SIZE + 2828c2ecf20Sopenharmony_ci VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (setup->color_read) { 2868c2ecf20Sopenharmony_ci if (args->color_read.flags & 2878c2ecf20Sopenharmony_ci VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 2888c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE; 2898c2ecf20Sopenharmony_ci } else { 2908c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci if (setup->zs_read) { 2948c2ecf20Sopenharmony_ci if (setup->color_read) { 2958c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE; 2968c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (args->zs_read.flags & 3008c2ecf20Sopenharmony_ci VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 3018c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_LOAD_FULL_RES_TILE_BUFFER_SIZE; 3028c2ecf20Sopenharmony_ci } else { 3038c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_LOAD_TILE_BUFFER_GENERAL_SIZE; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci if (has_bin) { 3088c2ecf20Sopenharmony_ci size += VC4_PACKET_WAIT_ON_SEMAPHORE_SIZE; 3098c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_BRANCH_TO_SUB_LIST_SIZE; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (setup->msaa_color_write) 3138c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_STORE_FULL_RES_TILE_BUFFER_SIZE; 3148c2ecf20Sopenharmony_ci if (setup->msaa_zs_write) 3158c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_STORE_FULL_RES_TILE_BUFFER_SIZE; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (setup->zs_write) 3188c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_STORE_TILE_BUFFER_GENERAL_SIZE; 3198c2ecf20Sopenharmony_ci if (setup->color_write) 3208c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_STORE_MS_TILE_BUFFER_SIZE; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* We need a VC4_PACKET_TILE_COORDINATES in between each store. */ 3238c2ecf20Sopenharmony_ci loop_body_size += VC4_PACKET_TILE_COORDINATES_SIZE * 3248c2ecf20Sopenharmony_ci ((setup->msaa_color_write != NULL) + 3258c2ecf20Sopenharmony_ci (setup->msaa_zs_write != NULL) + 3268c2ecf20Sopenharmony_ci (setup->color_write != NULL) + 3278c2ecf20Sopenharmony_ci (setup->zs_write != NULL) - 1); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci size += xtiles * ytiles * loop_body_size; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci setup->rcl = &vc4_bo_create(dev, size, true, VC4_BO_TYPE_RCL)->base; 3328c2ecf20Sopenharmony_ci if (IS_ERR(setup->rcl)) 3338c2ecf20Sopenharmony_ci return PTR_ERR(setup->rcl); 3348c2ecf20Sopenharmony_ci list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head, 3358c2ecf20Sopenharmony_ci &exec->unref_list); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* The tile buffer gets cleared when the previous tile is stored. If 3388c2ecf20Sopenharmony_ci * the clear values changed between frames, then the tile buffer has 3398c2ecf20Sopenharmony_ci * stale clear values in it, so we have to do a store in None mode (no 3408c2ecf20Sopenharmony_ci * writes) so that we trigger the tile buffer clear. 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci if (args->flags & VC4_SUBMIT_CL_USE_CLEAR_COLOR) { 3438c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_CLEAR_COLORS); 3448c2ecf20Sopenharmony_ci rcl_u32(setup, args->clear_color[0]); 3458c2ecf20Sopenharmony_ci rcl_u32(setup, args->clear_color[1]); 3468c2ecf20Sopenharmony_ci rcl_u32(setup, args->clear_z); 3478c2ecf20Sopenharmony_ci rcl_u8(setup, args->clear_s); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci vc4_tile_coordinates(setup, 0, 0); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_STORE_TILE_BUFFER_GENERAL); 3528c2ecf20Sopenharmony_ci rcl_u16(setup, VC4_LOADSTORE_TILE_BUFFER_NONE); 3538c2ecf20Sopenharmony_ci rcl_u32(setup, 0); /* no address, since we're in None mode */ 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); 3578c2ecf20Sopenharmony_ci rcl_u32(setup, 3588c2ecf20Sopenharmony_ci (setup->color_write ? (setup->color_write->paddr + 3598c2ecf20Sopenharmony_ci args->color_write.offset) : 3608c2ecf20Sopenharmony_ci 0)); 3618c2ecf20Sopenharmony_ci rcl_u16(setup, args->width); 3628c2ecf20Sopenharmony_ci rcl_u16(setup, args->height); 3638c2ecf20Sopenharmony_ci rcl_u16(setup, args->color_write.bits); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci for (yi = 0; yi < ytiles; yi++) { 3668c2ecf20Sopenharmony_ci int y = positive_y ? min_y_tile + yi : max_y_tile - yi; 3678c2ecf20Sopenharmony_ci for (xi = 0; xi < xtiles; xi++) { 3688c2ecf20Sopenharmony_ci int x = positive_x ? min_x_tile + xi : max_x_tile - xi; 3698c2ecf20Sopenharmony_ci bool first = (xi == 0 && yi == 0); 3708c2ecf20Sopenharmony_ci bool last = (xi == xtiles - 1 && yi == ytiles - 1); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci emit_tile(exec, setup, x, y, first, last); 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci BUG_ON(setup->next_offset != size); 3778c2ecf20Sopenharmony_ci exec->ct1ca = setup->rcl->paddr; 3788c2ecf20Sopenharmony_ci exec->ct1ea = setup->rcl->paddr + setup->next_offset; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci return 0; 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic int vc4_full_res_bounds_check(struct vc4_exec_info *exec, 3848c2ecf20Sopenharmony_ci struct drm_gem_cma_object *obj, 3858c2ecf20Sopenharmony_ci struct drm_vc4_submit_rcl_surface *surf) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci struct drm_vc4_submit_cl *args = exec->args; 3888c2ecf20Sopenharmony_ci u32 render_tiles_stride = DIV_ROUND_UP(exec->args->width, 32); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (surf->offset > obj->base.size) { 3918c2ecf20Sopenharmony_ci DRM_DEBUG("surface offset %d > BO size %zd\n", 3928c2ecf20Sopenharmony_ci surf->offset, obj->base.size); 3938c2ecf20Sopenharmony_ci return -EINVAL; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci if ((obj->base.size - surf->offset) / VC4_TILE_BUFFER_SIZE < 3978c2ecf20Sopenharmony_ci render_tiles_stride * args->max_y_tile + args->max_x_tile) { 3988c2ecf20Sopenharmony_ci DRM_DEBUG("MSAA tile %d, %d out of bounds " 3998c2ecf20Sopenharmony_ci "(bo size %zd, offset %d).\n", 4008c2ecf20Sopenharmony_ci args->max_x_tile, args->max_y_tile, 4018c2ecf20Sopenharmony_ci obj->base.size, 4028c2ecf20Sopenharmony_ci surf->offset); 4038c2ecf20Sopenharmony_ci return -EINVAL; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci return 0; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec, 4108c2ecf20Sopenharmony_ci struct drm_gem_cma_object **obj, 4118c2ecf20Sopenharmony_ci struct drm_vc4_submit_rcl_surface *surf) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci if (surf->flags != 0 || surf->bits != 0) { 4148c2ecf20Sopenharmony_ci DRM_DEBUG("MSAA surface had nonzero flags/bits\n"); 4158c2ecf20Sopenharmony_ci return -EINVAL; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (surf->hindex == ~0) 4198c2ecf20Sopenharmony_ci return 0; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci *obj = vc4_use_bo(exec, surf->hindex); 4228c2ecf20Sopenharmony_ci if (!*obj) 4238c2ecf20Sopenharmony_ci return -EINVAL; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci if (surf->offset & 0xf) { 4288c2ecf20Sopenharmony_ci DRM_DEBUG("MSAA write must be 16b aligned.\n"); 4298c2ecf20Sopenharmony_ci return -EINVAL; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci return vc4_full_res_bounds_check(exec, *obj, surf); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic int vc4_rcl_surface_setup(struct vc4_exec_info *exec, 4368c2ecf20Sopenharmony_ci struct drm_gem_cma_object **obj, 4378c2ecf20Sopenharmony_ci struct drm_vc4_submit_rcl_surface *surf, 4388c2ecf20Sopenharmony_ci bool is_write) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci uint8_t tiling = VC4_GET_FIELD(surf->bits, 4418c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_TILING); 4428c2ecf20Sopenharmony_ci uint8_t buffer = VC4_GET_FIELD(surf->bits, 4438c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_BUFFER); 4448c2ecf20Sopenharmony_ci uint8_t format = VC4_GET_FIELD(surf->bits, 4458c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_FORMAT); 4468c2ecf20Sopenharmony_ci int cpp; 4478c2ecf20Sopenharmony_ci int ret; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (surf->flags & ~VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 4508c2ecf20Sopenharmony_ci DRM_DEBUG("Extra flags set\n"); 4518c2ecf20Sopenharmony_ci return -EINVAL; 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (surf->hindex == ~0) 4558c2ecf20Sopenharmony_ci return 0; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci *obj = vc4_use_bo(exec, surf->hindex); 4588c2ecf20Sopenharmony_ci if (!*obj) 4598c2ecf20Sopenharmony_ci return -EINVAL; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (is_write) 4628c2ecf20Sopenharmony_ci exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci if (surf->flags & VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { 4658c2ecf20Sopenharmony_ci if (surf == &exec->args->zs_write) { 4668c2ecf20Sopenharmony_ci DRM_DEBUG("general zs write may not be a full-res.\n"); 4678c2ecf20Sopenharmony_ci return -EINVAL; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (surf->bits != 0) { 4718c2ecf20Sopenharmony_ci DRM_DEBUG("load/store general bits set with " 4728c2ecf20Sopenharmony_ci "full res load/store.\n"); 4738c2ecf20Sopenharmony_ci return -EINVAL; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci ret = vc4_full_res_bounds_check(exec, *obj, surf); 4778c2ecf20Sopenharmony_ci if (ret) 4788c2ecf20Sopenharmony_ci return ret; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return 0; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (surf->bits & ~(VC4_LOADSTORE_TILE_BUFFER_TILING_MASK | 4848c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_BUFFER_MASK | 4858c2ecf20Sopenharmony_ci VC4_LOADSTORE_TILE_BUFFER_FORMAT_MASK)) { 4868c2ecf20Sopenharmony_ci DRM_DEBUG("Unknown bits in load/store: 0x%04x\n", 4878c2ecf20Sopenharmony_ci surf->bits); 4888c2ecf20Sopenharmony_ci return -EINVAL; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (tiling > VC4_TILING_FORMAT_LT) { 4928c2ecf20Sopenharmony_ci DRM_DEBUG("Bad tiling format\n"); 4938c2ecf20Sopenharmony_ci return -EINVAL; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (buffer == VC4_LOADSTORE_TILE_BUFFER_ZS) { 4978c2ecf20Sopenharmony_ci if (format != 0) { 4988c2ecf20Sopenharmony_ci DRM_DEBUG("No color format should be set for ZS\n"); 4998c2ecf20Sopenharmony_ci return -EINVAL; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci cpp = 4; 5028c2ecf20Sopenharmony_ci } else if (buffer == VC4_LOADSTORE_TILE_BUFFER_COLOR) { 5038c2ecf20Sopenharmony_ci switch (format) { 5048c2ecf20Sopenharmony_ci case VC4_LOADSTORE_TILE_BUFFER_BGR565: 5058c2ecf20Sopenharmony_ci case VC4_LOADSTORE_TILE_BUFFER_BGR565_DITHER: 5068c2ecf20Sopenharmony_ci cpp = 2; 5078c2ecf20Sopenharmony_ci break; 5088c2ecf20Sopenharmony_ci case VC4_LOADSTORE_TILE_BUFFER_RGBA8888: 5098c2ecf20Sopenharmony_ci cpp = 4; 5108c2ecf20Sopenharmony_ci break; 5118c2ecf20Sopenharmony_ci default: 5128c2ecf20Sopenharmony_ci DRM_DEBUG("Bad tile buffer format\n"); 5138c2ecf20Sopenharmony_ci return -EINVAL; 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci } else { 5168c2ecf20Sopenharmony_ci DRM_DEBUG("Bad load/store buffer %d.\n", buffer); 5178c2ecf20Sopenharmony_ci return -EINVAL; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (surf->offset & 0xf) { 5218c2ecf20Sopenharmony_ci DRM_DEBUG("load/store buffer must be 16b aligned.\n"); 5228c2ecf20Sopenharmony_ci return -EINVAL; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci if (!vc4_check_tex_size(exec, *obj, surf->offset, tiling, 5268c2ecf20Sopenharmony_ci exec->args->width, exec->args->height, cpp)) { 5278c2ecf20Sopenharmony_ci return -EINVAL; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci return 0; 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic int 5348c2ecf20Sopenharmony_civc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec, 5358c2ecf20Sopenharmony_ci struct vc4_rcl_setup *setup, 5368c2ecf20Sopenharmony_ci struct drm_gem_cma_object **obj, 5378c2ecf20Sopenharmony_ci struct drm_vc4_submit_rcl_surface *surf) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci uint8_t tiling = VC4_GET_FIELD(surf->bits, 5408c2ecf20Sopenharmony_ci VC4_RENDER_CONFIG_MEMORY_FORMAT); 5418c2ecf20Sopenharmony_ci uint8_t format = VC4_GET_FIELD(surf->bits, 5428c2ecf20Sopenharmony_ci VC4_RENDER_CONFIG_FORMAT); 5438c2ecf20Sopenharmony_ci int cpp; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci if (surf->flags != 0) { 5468c2ecf20Sopenharmony_ci DRM_DEBUG("No flags supported on render config.\n"); 5478c2ecf20Sopenharmony_ci return -EINVAL; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (surf->bits & ~(VC4_RENDER_CONFIG_MEMORY_FORMAT_MASK | 5518c2ecf20Sopenharmony_ci VC4_RENDER_CONFIG_FORMAT_MASK | 5528c2ecf20Sopenharmony_ci VC4_RENDER_CONFIG_MS_MODE_4X | 5538c2ecf20Sopenharmony_ci VC4_RENDER_CONFIG_DECIMATE_MODE_4X)) { 5548c2ecf20Sopenharmony_ci DRM_DEBUG("Unknown bits in render config: 0x%04x\n", 5558c2ecf20Sopenharmony_ci surf->bits); 5568c2ecf20Sopenharmony_ci return -EINVAL; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci if (surf->hindex == ~0) 5608c2ecf20Sopenharmony_ci return 0; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci *obj = vc4_use_bo(exec, surf->hindex); 5638c2ecf20Sopenharmony_ci if (!*obj) 5648c2ecf20Sopenharmony_ci return -EINVAL; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (tiling > VC4_TILING_FORMAT_LT) { 5698c2ecf20Sopenharmony_ci DRM_DEBUG("Bad tiling format\n"); 5708c2ecf20Sopenharmony_ci return -EINVAL; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci switch (format) { 5748c2ecf20Sopenharmony_ci case VC4_RENDER_CONFIG_FORMAT_BGR565_DITHERED: 5758c2ecf20Sopenharmony_ci case VC4_RENDER_CONFIG_FORMAT_BGR565: 5768c2ecf20Sopenharmony_ci cpp = 2; 5778c2ecf20Sopenharmony_ci break; 5788c2ecf20Sopenharmony_ci case VC4_RENDER_CONFIG_FORMAT_RGBA8888: 5798c2ecf20Sopenharmony_ci cpp = 4; 5808c2ecf20Sopenharmony_ci break; 5818c2ecf20Sopenharmony_ci default: 5828c2ecf20Sopenharmony_ci DRM_DEBUG("Bad tile buffer format\n"); 5838c2ecf20Sopenharmony_ci return -EINVAL; 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (!vc4_check_tex_size(exec, *obj, surf->offset, tiling, 5878c2ecf20Sopenharmony_ci exec->args->width, exec->args->height, cpp)) { 5888c2ecf20Sopenharmony_ci return -EINVAL; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci return 0; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ciint vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci struct vc4_rcl_setup setup = {0}; 5978c2ecf20Sopenharmony_ci struct drm_vc4_submit_cl *args = exec->args; 5988c2ecf20Sopenharmony_ci bool has_bin = args->bin_cl_size != 0; 5998c2ecf20Sopenharmony_ci int ret; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (args->min_x_tile > args->max_x_tile || 6028c2ecf20Sopenharmony_ci args->min_y_tile > args->max_y_tile) { 6038c2ecf20Sopenharmony_ci DRM_DEBUG("Bad render tile set (%d,%d)-(%d,%d)\n", 6048c2ecf20Sopenharmony_ci args->min_x_tile, args->min_y_tile, 6058c2ecf20Sopenharmony_ci args->max_x_tile, args->max_y_tile); 6068c2ecf20Sopenharmony_ci return -EINVAL; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (has_bin && 6108c2ecf20Sopenharmony_ci (args->max_x_tile > exec->bin_tiles_x || 6118c2ecf20Sopenharmony_ci args->max_y_tile > exec->bin_tiles_y)) { 6128c2ecf20Sopenharmony_ci DRM_DEBUG("Render tiles (%d,%d) outside of bin config " 6138c2ecf20Sopenharmony_ci "(%d,%d)\n", 6148c2ecf20Sopenharmony_ci args->max_x_tile, args->max_y_tile, 6158c2ecf20Sopenharmony_ci exec->bin_tiles_x, exec->bin_tiles_y); 6168c2ecf20Sopenharmony_ci return -EINVAL; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci ret = vc4_rcl_render_config_surface_setup(exec, &setup, 6208c2ecf20Sopenharmony_ci &setup.color_write, 6218c2ecf20Sopenharmony_ci &args->color_write); 6228c2ecf20Sopenharmony_ci if (ret) 6238c2ecf20Sopenharmony_ci return ret; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci ret = vc4_rcl_surface_setup(exec, &setup.color_read, &args->color_read, 6268c2ecf20Sopenharmony_ci false); 6278c2ecf20Sopenharmony_ci if (ret) 6288c2ecf20Sopenharmony_ci return ret; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci ret = vc4_rcl_surface_setup(exec, &setup.zs_read, &args->zs_read, 6318c2ecf20Sopenharmony_ci false); 6328c2ecf20Sopenharmony_ci if (ret) 6338c2ecf20Sopenharmony_ci return ret; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci ret = vc4_rcl_surface_setup(exec, &setup.zs_write, &args->zs_write, 6368c2ecf20Sopenharmony_ci true); 6378c2ecf20Sopenharmony_ci if (ret) 6388c2ecf20Sopenharmony_ci return ret; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci ret = vc4_rcl_msaa_surface_setup(exec, &setup.msaa_color_write, 6418c2ecf20Sopenharmony_ci &args->msaa_color_write); 6428c2ecf20Sopenharmony_ci if (ret) 6438c2ecf20Sopenharmony_ci return ret; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci ret = vc4_rcl_msaa_surface_setup(exec, &setup.msaa_zs_write, 6468c2ecf20Sopenharmony_ci &args->msaa_zs_write); 6478c2ecf20Sopenharmony_ci if (ret) 6488c2ecf20Sopenharmony_ci return ret; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci /* We shouldn't even have the job submitted to us if there's no 6518c2ecf20Sopenharmony_ci * surface to write out. 6528c2ecf20Sopenharmony_ci */ 6538c2ecf20Sopenharmony_ci if (!setup.color_write && !setup.zs_write && 6548c2ecf20Sopenharmony_ci !setup.msaa_color_write && !setup.msaa_zs_write) { 6558c2ecf20Sopenharmony_ci DRM_DEBUG("RCL requires color or Z/S write\n"); 6568c2ecf20Sopenharmony_ci return -EINVAL; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci return vc4_create_rcl_bo(dev, exec, &setup); 6608c2ecf20Sopenharmony_ci} 661