radeon_surface.c revision 2ee35494
1e88f27b3Smrg/* 2e88f27b3Smrg * Copyright © 2011 Red Hat All Rights Reserved. 3e88f27b3Smrg * 4e88f27b3Smrg * Permission is hereby granted, free of charge, to any person obtaining 5e88f27b3Smrg * a copy of this software and associated documentation files (the 6e88f27b3Smrg * "Software"), to deal in the Software without restriction, including 7e88f27b3Smrg * without limitation the rights to use, copy, modify, merge, publish, 8e88f27b3Smrg * distribute, sub license, and/or sell copies of the Software, and to 9e88f27b3Smrg * permit persons to whom the Software is furnished to do so, subject to 10e88f27b3Smrg * the following conditions: 11e88f27b3Smrg * 12e88f27b3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 13e88f27b3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 14e88f27b3Smrg * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15e88f27b3Smrg * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 16e88f27b3Smrg * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e88f27b3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18e88f27b3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 19e88f27b3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 20e88f27b3Smrg * 21e88f27b3Smrg * The above copyright notice and this permission notice (including the 22e88f27b3Smrg * next paragraph) shall be included in all copies or substantial portions 23e88f27b3Smrg * of the Software. 24e88f27b3Smrg */ 25e88f27b3Smrg/* 26e88f27b3Smrg * Authors: 27e88f27b3Smrg * Jérôme Glisse <jglisse@redhat.com> 28e88f27b3Smrg */ 29a884aba1Smrg#ifdef HAVE_CONFIG_H 30a884aba1Smrg#include <config.h> 31a884aba1Smrg#endif 32e88f27b3Smrg#include <stdbool.h> 33e88f27b3Smrg#include <assert.h> 34e88f27b3Smrg#include <errno.h> 35e88f27b3Smrg#include <stdio.h> 36e88f27b3Smrg#include <stdlib.h> 37e88f27b3Smrg#include <string.h> 38e88f27b3Smrg#include <sys/ioctl.h> 39e88f27b3Smrg#include "drm.h" 40424e9256Smrg#include "libdrm_macros.h" 41e88f27b3Smrg#include "xf86drm.h" 42e88f27b3Smrg#include "radeon_drm.h" 43e88f27b3Smrg#include "radeon_surface.h" 44e88f27b3Smrg 452ee35494Smrg#define CIK_TILE_MODE_COLOR_2D 14 462ee35494Smrg#define CIK_TILE_MODE_COLOR_2D_SCANOUT 10 472ee35494Smrg#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64 0 482ee35494Smrg#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128 1 492ee35494Smrg#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256 2 502ee35494Smrg#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512 3 512ee35494Smrg#define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4 522ee35494Smrg 53e88f27b3Smrg#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1)) 54e88f27b3Smrg#define MAX2(A, B) ((A) > (B) ? (A) : (B)) 55e88f27b3Smrg#define MIN2(A, B) ((A) < (B) ? (A) : (B)) 56e88f27b3Smrg 57e88f27b3Smrg/* keep this private */ 58e88f27b3Smrgenum radeon_family { 59e88f27b3Smrg CHIP_UNKNOWN, 60e88f27b3Smrg CHIP_R600, 61e88f27b3Smrg CHIP_RV610, 62e88f27b3Smrg CHIP_RV630, 63e88f27b3Smrg CHIP_RV670, 64e88f27b3Smrg CHIP_RV620, 65e88f27b3Smrg CHIP_RV635, 66e88f27b3Smrg CHIP_RS780, 67e88f27b3Smrg CHIP_RS880, 68e88f27b3Smrg CHIP_RV770, 69e88f27b3Smrg CHIP_RV730, 70e88f27b3Smrg CHIP_RV710, 71e88f27b3Smrg CHIP_RV740, 72e88f27b3Smrg CHIP_CEDAR, 73e88f27b3Smrg CHIP_REDWOOD, 74e88f27b3Smrg CHIP_JUNIPER, 75e88f27b3Smrg CHIP_CYPRESS, 76e88f27b3Smrg CHIP_HEMLOCK, 77e88f27b3Smrg CHIP_PALM, 78e88f27b3Smrg CHIP_SUMO, 79e88f27b3Smrg CHIP_SUMO2, 80e88f27b3Smrg CHIP_BARTS, 81e88f27b3Smrg CHIP_TURKS, 82e88f27b3Smrg CHIP_CAICOS, 83e88f27b3Smrg CHIP_CAYMAN, 84e88f27b3Smrg CHIP_ARUBA, 85e88f27b3Smrg CHIP_TAHITI, 86e88f27b3Smrg CHIP_PITCAIRN, 87e88f27b3Smrg CHIP_VERDE, 88e88f27b3Smrg CHIP_OLAND, 89e88f27b3Smrg CHIP_HAINAN, 90e88f27b3Smrg CHIP_BONAIRE, 91e88f27b3Smrg CHIP_KAVERI, 92e88f27b3Smrg CHIP_KABINI, 93e88f27b3Smrg CHIP_HAWAII, 94a7d7de1eSmrg CHIP_MULLINS, 95e88f27b3Smrg CHIP_LAST, 96e88f27b3Smrg}; 97e88f27b3Smrg 98e88f27b3Smrgtypedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man, 99e88f27b3Smrg struct radeon_surface *surf); 100e88f27b3Smrgtypedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man, 101e88f27b3Smrg struct radeon_surface *surf); 102e88f27b3Smrg 103e88f27b3Smrgstruct radeon_hw_info { 104e88f27b3Smrg /* apply to r6, eg */ 105e88f27b3Smrg uint32_t group_bytes; 106e88f27b3Smrg uint32_t num_banks; 107e88f27b3Smrg uint32_t num_pipes; 108e88f27b3Smrg /* apply to eg */ 109e88f27b3Smrg uint32_t row_size; 110e88f27b3Smrg unsigned allow_2d; 111e88f27b3Smrg /* apply to si */ 112e88f27b3Smrg uint32_t tile_mode_array[32]; 113e88f27b3Smrg /* apply to cik */ 114e88f27b3Smrg uint32_t macrotile_mode_array[16]; 115e88f27b3Smrg}; 116e88f27b3Smrg 117e88f27b3Smrgstruct radeon_surface_manager { 118e88f27b3Smrg int fd; 119e88f27b3Smrg uint32_t device_id; 120e88f27b3Smrg struct radeon_hw_info hw_info; 121e88f27b3Smrg unsigned family; 122e88f27b3Smrg hw_init_surface_t surface_init; 123e88f27b3Smrg hw_best_surface_t surface_best; 124e88f27b3Smrg}; 125e88f27b3Smrg 126e88f27b3Smrg/* helper */ 127e88f27b3Smrgstatic int radeon_get_value(int fd, unsigned req, uint32_t *value) 128e88f27b3Smrg{ 129e88f27b3Smrg struct drm_radeon_info info = {}; 130e88f27b3Smrg int r; 131e88f27b3Smrg 132e88f27b3Smrg *value = 0; 133e88f27b3Smrg info.request = req; 134e88f27b3Smrg info.value = (uintptr_t)value; 135e88f27b3Smrg r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, 136e88f27b3Smrg sizeof(struct drm_radeon_info)); 137e88f27b3Smrg return r; 138e88f27b3Smrg} 139e88f27b3Smrg 140e88f27b3Smrgstatic int radeon_get_family(struct radeon_surface_manager *surf_man) 141e88f27b3Smrg{ 142e88f27b3Smrg switch (surf_man->device_id) { 143e88f27b3Smrg#define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break; 144e88f27b3Smrg#include "r600_pci_ids.h" 145e88f27b3Smrg#undef CHIPSET 146e88f27b3Smrg default: 147e88f27b3Smrg return -EINVAL; 148e88f27b3Smrg } 149e88f27b3Smrg return 0; 150e88f27b3Smrg} 151e88f27b3Smrg 152e88f27b3Smrgstatic unsigned next_power_of_two(unsigned x) 153e88f27b3Smrg{ 154e88f27b3Smrg if (x <= 1) 155e88f27b3Smrg return 1; 156e88f27b3Smrg 157e88f27b3Smrg return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1))); 158e88f27b3Smrg} 159e88f27b3Smrg 160e88f27b3Smrgstatic unsigned mip_minify(unsigned size, unsigned level) 161e88f27b3Smrg{ 162e88f27b3Smrg unsigned val; 163e88f27b3Smrg 164e88f27b3Smrg val = MAX2(1, size >> level); 165e88f27b3Smrg if (level > 0) 166e88f27b3Smrg val = next_power_of_two(val); 167e88f27b3Smrg return val; 168e88f27b3Smrg} 169e88f27b3Smrg 170e88f27b3Smrgstatic void surf_minify(struct radeon_surface *surf, 171e88f27b3Smrg struct radeon_surface_level *surflevel, 172e88f27b3Smrg unsigned bpe, unsigned level, 173e88f27b3Smrg uint32_t xalign, uint32_t yalign, uint32_t zalign, 174fe517fc9Smrg uint64_t offset) 175e88f27b3Smrg{ 176e88f27b3Smrg surflevel->npix_x = mip_minify(surf->npix_x, level); 177e88f27b3Smrg surflevel->npix_y = mip_minify(surf->npix_y, level); 178e88f27b3Smrg surflevel->npix_z = mip_minify(surf->npix_z, level); 179e88f27b3Smrg surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; 180e88f27b3Smrg surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; 181e88f27b3Smrg surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; 182e88f27b3Smrg if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && 183e88f27b3Smrg !(surf->flags & RADEON_SURF_FMASK)) { 184e88f27b3Smrg if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { 185e88f27b3Smrg surflevel->mode = RADEON_SURF_MODE_1D; 186e88f27b3Smrg return; 187e88f27b3Smrg } 188e88f27b3Smrg } 189e88f27b3Smrg surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); 190e88f27b3Smrg surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); 191e88f27b3Smrg surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); 192e88f27b3Smrg 193e88f27b3Smrg surflevel->offset = offset; 194e88f27b3Smrg surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples; 195fe517fc9Smrg surflevel->slice_size = (uint64_t)surflevel->pitch_bytes * surflevel->nblk_y; 196e88f27b3Smrg 197e88f27b3Smrg surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 198e88f27b3Smrg} 199e88f27b3Smrg 200e88f27b3Smrg/* =========================================================================== 201e88f27b3Smrg * r600/r700 family 202e88f27b3Smrg */ 203e88f27b3Smrgstatic int r6_init_hw_info(struct radeon_surface_manager *surf_man) 204e88f27b3Smrg{ 205e88f27b3Smrg uint32_t tiling_config; 206e88f27b3Smrg drmVersionPtr version; 207e88f27b3Smrg int r; 208e88f27b3Smrg 209e88f27b3Smrg r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, 210e88f27b3Smrg &tiling_config); 211e88f27b3Smrg if (r) { 212e88f27b3Smrg return r; 213e88f27b3Smrg } 214e88f27b3Smrg 215e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 216e88f27b3Smrg version = drmGetVersion(surf_man->fd); 217e88f27b3Smrg if (version && version->version_minor >= 14) { 218e88f27b3Smrg surf_man->hw_info.allow_2d = 1; 219e88f27b3Smrg } 220e88f27b3Smrg drmFreeVersion(version); 221e88f27b3Smrg 222e88f27b3Smrg switch ((tiling_config & 0xe) >> 1) { 223e88f27b3Smrg case 0: 224e88f27b3Smrg surf_man->hw_info.num_pipes = 1; 225e88f27b3Smrg break; 226e88f27b3Smrg case 1: 227e88f27b3Smrg surf_man->hw_info.num_pipes = 2; 228e88f27b3Smrg break; 229e88f27b3Smrg case 2: 230e88f27b3Smrg surf_man->hw_info.num_pipes = 4; 231e88f27b3Smrg break; 232e88f27b3Smrg case 3: 233e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 234e88f27b3Smrg break; 235e88f27b3Smrg default: 236e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 237e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 238e88f27b3Smrg break; 239e88f27b3Smrg } 240e88f27b3Smrg 241e88f27b3Smrg switch ((tiling_config & 0x30) >> 4) { 242e88f27b3Smrg case 0: 243e88f27b3Smrg surf_man->hw_info.num_banks = 4; 244e88f27b3Smrg break; 245e88f27b3Smrg case 1: 246e88f27b3Smrg surf_man->hw_info.num_banks = 8; 247e88f27b3Smrg break; 248e88f27b3Smrg default: 249e88f27b3Smrg surf_man->hw_info.num_banks = 8; 250e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 251e88f27b3Smrg break; 252e88f27b3Smrg } 253e88f27b3Smrg 254e88f27b3Smrg switch ((tiling_config & 0xc0) >> 6) { 255e88f27b3Smrg case 0: 256e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 257e88f27b3Smrg break; 258e88f27b3Smrg case 1: 259e88f27b3Smrg surf_man->hw_info.group_bytes = 512; 260e88f27b3Smrg break; 261e88f27b3Smrg default: 262e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 263e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 264e88f27b3Smrg break; 265e88f27b3Smrg } 266e88f27b3Smrg return 0; 267e88f27b3Smrg} 268e88f27b3Smrg 269e88f27b3Smrgstatic int r6_surface_init_linear(struct radeon_surface_manager *surf_man, 270e88f27b3Smrg struct radeon_surface *surf, 271e88f27b3Smrg uint64_t offset, unsigned start_level) 272e88f27b3Smrg{ 273e88f27b3Smrg uint32_t xalign, yalign, zalign; 274e88f27b3Smrg unsigned i; 275e88f27b3Smrg 276e88f27b3Smrg /* compute alignment */ 277e88f27b3Smrg if (!start_level) { 278e88f27b3Smrg surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); 279e88f27b3Smrg } 280e88f27b3Smrg /* the 32 alignment is for scanout, cb or db but to allow texture to be 281e88f27b3Smrg * easily bound as such we force this alignment to all surface 282e88f27b3Smrg */ 283e88f27b3Smrg xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe); 284e88f27b3Smrg yalign = 1; 285e88f27b3Smrg zalign = 1; 286e88f27b3Smrg if (surf->flags & RADEON_SURF_SCANOUT) { 287e88f27b3Smrg xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign); 288e88f27b3Smrg } 289e88f27b3Smrg 290e88f27b3Smrg /* build mipmap tree */ 291e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 292e88f27b3Smrg surf->level[i].mode = RADEON_SURF_MODE_LINEAR; 293e88f27b3Smrg surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset); 294e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 295e88f27b3Smrg offset = surf->bo_size; 296a884aba1Smrg if (i == 0) { 297e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 298e88f27b3Smrg } 299e88f27b3Smrg } 300e88f27b3Smrg return 0; 301e88f27b3Smrg} 302e88f27b3Smrg 303e88f27b3Smrgstatic int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, 304e88f27b3Smrg struct radeon_surface *surf, 305e88f27b3Smrg uint64_t offset, unsigned start_level) 306e88f27b3Smrg{ 307e88f27b3Smrg uint32_t xalign, yalign, zalign; 308e88f27b3Smrg unsigned i; 309e88f27b3Smrg 310e88f27b3Smrg /* compute alignment */ 311e88f27b3Smrg if (!start_level) { 312e88f27b3Smrg surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); 313e88f27b3Smrg } 314e88f27b3Smrg xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe); 315e88f27b3Smrg yalign = 1; 316e88f27b3Smrg zalign = 1; 317e88f27b3Smrg 318e88f27b3Smrg /* build mipmap tree */ 319e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 320e88f27b3Smrg surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; 321e88f27b3Smrg surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset); 322e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 323e88f27b3Smrg offset = surf->bo_size; 324a884aba1Smrg if (i == 0) { 325e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 326e88f27b3Smrg } 327e88f27b3Smrg } 328e88f27b3Smrg return 0; 329e88f27b3Smrg} 330e88f27b3Smrg 331e88f27b3Smrgstatic int r6_surface_init_1d(struct radeon_surface_manager *surf_man, 332e88f27b3Smrg struct radeon_surface *surf, 333e88f27b3Smrg uint64_t offset, unsigned start_level) 334e88f27b3Smrg{ 335e88f27b3Smrg uint32_t xalign, yalign, zalign, tilew; 336e88f27b3Smrg unsigned i; 337e88f27b3Smrg 338e88f27b3Smrg /* compute alignment */ 339e88f27b3Smrg tilew = 8; 340e88f27b3Smrg xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples); 341e88f27b3Smrg xalign = MAX2(tilew, xalign); 342e88f27b3Smrg yalign = tilew; 343e88f27b3Smrg zalign = 1; 344e88f27b3Smrg if (surf->flags & RADEON_SURF_SCANOUT) { 345e88f27b3Smrg xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign); 346e88f27b3Smrg } 347e88f27b3Smrg if (!start_level) { 348e88f27b3Smrg surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); 349e88f27b3Smrg } 350e88f27b3Smrg 351e88f27b3Smrg /* build mipmap tree */ 352e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 353e88f27b3Smrg surf->level[i].mode = RADEON_SURF_MODE_1D; 354e88f27b3Smrg surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset); 355e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 356e88f27b3Smrg offset = surf->bo_size; 357a884aba1Smrg if (i == 0) { 358e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 359e88f27b3Smrg } 360e88f27b3Smrg } 361e88f27b3Smrg return 0; 362e88f27b3Smrg} 363e88f27b3Smrg 364e88f27b3Smrgstatic int r6_surface_init_2d(struct radeon_surface_manager *surf_man, 365e88f27b3Smrg struct radeon_surface *surf, 366e88f27b3Smrg uint64_t offset, unsigned start_level) 367e88f27b3Smrg{ 368e88f27b3Smrg uint32_t xalign, yalign, zalign, tilew; 369e88f27b3Smrg unsigned i; 370e88f27b3Smrg 371e88f27b3Smrg /* compute alignment */ 372e88f27b3Smrg tilew = 8; 373e88f27b3Smrg zalign = 1; 374e88f27b3Smrg xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) / 375e88f27b3Smrg (tilew * surf->bpe * surf->nsamples); 376e88f27b3Smrg xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign); 3773c748557Ssnj if (surf->flags & RADEON_SURF_FMASK) 3783c748557Ssnj xalign = MAX2(128, xalign); 379e88f27b3Smrg yalign = tilew * surf_man->hw_info.num_pipes; 380e88f27b3Smrg if (surf->flags & RADEON_SURF_SCANOUT) { 381e88f27b3Smrg xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign); 382e88f27b3Smrg } 383e88f27b3Smrg if (!start_level) { 384e88f27b3Smrg surf->bo_alignment = 385e88f27b3Smrg MAX2(surf_man->hw_info.num_pipes * 386e88f27b3Smrg surf_man->hw_info.num_banks * 387e88f27b3Smrg surf->nsamples * surf->bpe * 64, 388e88f27b3Smrg xalign * yalign * surf->nsamples * surf->bpe); 389e88f27b3Smrg } 390e88f27b3Smrg 391e88f27b3Smrg /* build mipmap tree */ 392e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 393e88f27b3Smrg surf->level[i].mode = RADEON_SURF_MODE_2D; 394e88f27b3Smrg surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset); 395e88f27b3Smrg if (surf->level[i].mode == RADEON_SURF_MODE_1D) { 396e88f27b3Smrg return r6_surface_init_1d(surf_man, surf, offset, i); 397e88f27b3Smrg } 398e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 399e88f27b3Smrg offset = surf->bo_size; 400a884aba1Smrg if (i == 0) { 401e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 402e88f27b3Smrg } 403e88f27b3Smrg } 404e88f27b3Smrg return 0; 405e88f27b3Smrg} 406e88f27b3Smrg 407e88f27b3Smrgstatic int r6_surface_init(struct radeon_surface_manager *surf_man, 408e88f27b3Smrg struct radeon_surface *surf) 409e88f27b3Smrg{ 410e88f27b3Smrg unsigned mode; 411e88f27b3Smrg int r; 412e88f27b3Smrg 413e88f27b3Smrg /* MSAA surfaces support the 2D mode only. */ 414e88f27b3Smrg if (surf->nsamples > 1) { 415e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 416e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 417e88f27b3Smrg } 418e88f27b3Smrg 419e88f27b3Smrg /* tiling mode */ 420e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 421e88f27b3Smrg 422e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 423e88f27b3Smrg /* zbuffer only support 1D or 2D tiled surface */ 424e88f27b3Smrg switch (mode) { 425e88f27b3Smrg case RADEON_SURF_MODE_1D: 426e88f27b3Smrg case RADEON_SURF_MODE_2D: 427e88f27b3Smrg break; 428e88f27b3Smrg default: 429e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 430e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 431e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 432e88f27b3Smrg break; 433e88f27b3Smrg } 434e88f27b3Smrg } 435e88f27b3Smrg 436e88f27b3Smrg /* force 1d on kernel that can't do 2d */ 437e88f27b3Smrg if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) { 438e88f27b3Smrg if (surf->nsamples > 1) { 439e88f27b3Smrg fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__); 440e88f27b3Smrg return -EFAULT; 441e88f27b3Smrg } 442e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 443e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 444e88f27b3Smrg surf->flags |= RADEON_SURF_SET(mode, MODE); 445e88f27b3Smrg } 446e88f27b3Smrg 447e88f27b3Smrg /* check surface dimension */ 448e88f27b3Smrg if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) { 449e88f27b3Smrg return -EINVAL; 450e88f27b3Smrg } 451e88f27b3Smrg 452e88f27b3Smrg /* check mipmap last_level */ 453e88f27b3Smrg if (surf->last_level > 14) { 454e88f27b3Smrg return -EINVAL; 455e88f27b3Smrg } 456e88f27b3Smrg 457e88f27b3Smrg /* check tiling mode */ 458e88f27b3Smrg switch (mode) { 459e88f27b3Smrg case RADEON_SURF_MODE_LINEAR: 460e88f27b3Smrg r = r6_surface_init_linear(surf_man, surf, 0, 0); 461e88f27b3Smrg break; 462e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 463e88f27b3Smrg r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0); 464e88f27b3Smrg break; 465e88f27b3Smrg case RADEON_SURF_MODE_1D: 466e88f27b3Smrg r = r6_surface_init_1d(surf_man, surf, 0, 0); 467e88f27b3Smrg break; 468e88f27b3Smrg case RADEON_SURF_MODE_2D: 469e88f27b3Smrg r = r6_surface_init_2d(surf_man, surf, 0, 0); 470e88f27b3Smrg break; 471e88f27b3Smrg default: 472e88f27b3Smrg return -EINVAL; 473e88f27b3Smrg } 474e88f27b3Smrg return r; 475e88f27b3Smrg} 476e88f27b3Smrg 477e88f27b3Smrgstatic int r6_surface_best(struct radeon_surface_manager *surf_man, 478e88f27b3Smrg struct radeon_surface *surf) 479e88f27b3Smrg{ 480e88f27b3Smrg /* no value to optimize for r6xx/r7xx */ 481e88f27b3Smrg return 0; 482e88f27b3Smrg} 483e88f27b3Smrg 484e88f27b3Smrg 485e88f27b3Smrg/* =========================================================================== 486e88f27b3Smrg * evergreen family 487e88f27b3Smrg */ 488e88f27b3Smrgstatic int eg_init_hw_info(struct radeon_surface_manager *surf_man) 489e88f27b3Smrg{ 490e88f27b3Smrg uint32_t tiling_config; 491e88f27b3Smrg drmVersionPtr version; 492e88f27b3Smrg int r; 493e88f27b3Smrg 494e88f27b3Smrg r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, 495e88f27b3Smrg &tiling_config); 496e88f27b3Smrg if (r) { 497e88f27b3Smrg return r; 498e88f27b3Smrg } 499e88f27b3Smrg 500e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 501e88f27b3Smrg version = drmGetVersion(surf_man->fd); 502e88f27b3Smrg if (version && version->version_minor >= 16) { 503e88f27b3Smrg surf_man->hw_info.allow_2d = 1; 504e88f27b3Smrg } 505e88f27b3Smrg drmFreeVersion(version); 506e88f27b3Smrg 507e88f27b3Smrg switch (tiling_config & 0xf) { 508e88f27b3Smrg case 0: 509e88f27b3Smrg surf_man->hw_info.num_pipes = 1; 510e88f27b3Smrg break; 511e88f27b3Smrg case 1: 512e88f27b3Smrg surf_man->hw_info.num_pipes = 2; 513e88f27b3Smrg break; 514e88f27b3Smrg case 2: 515e88f27b3Smrg surf_man->hw_info.num_pipes = 4; 516e88f27b3Smrg break; 517e88f27b3Smrg case 3: 518e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 519e88f27b3Smrg break; 520e88f27b3Smrg default: 521e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 522e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 523e88f27b3Smrg break; 524e88f27b3Smrg } 525e88f27b3Smrg 526e88f27b3Smrg switch ((tiling_config & 0xf0) >> 4) { 527e88f27b3Smrg case 0: 528e88f27b3Smrg surf_man->hw_info.num_banks = 4; 529e88f27b3Smrg break; 530e88f27b3Smrg case 1: 531e88f27b3Smrg surf_man->hw_info.num_banks = 8; 532e88f27b3Smrg break; 533e88f27b3Smrg case 2: 534e88f27b3Smrg surf_man->hw_info.num_banks = 16; 535e88f27b3Smrg break; 536e88f27b3Smrg default: 537e88f27b3Smrg surf_man->hw_info.num_banks = 8; 538e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 539e88f27b3Smrg break; 540e88f27b3Smrg } 541e88f27b3Smrg 542e88f27b3Smrg switch ((tiling_config & 0xf00) >> 8) { 543e88f27b3Smrg case 0: 544e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 545e88f27b3Smrg break; 546e88f27b3Smrg case 1: 547e88f27b3Smrg surf_man->hw_info.group_bytes = 512; 548e88f27b3Smrg break; 549e88f27b3Smrg default: 550e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 551e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 552e88f27b3Smrg break; 553e88f27b3Smrg } 554e88f27b3Smrg 555e88f27b3Smrg switch ((tiling_config & 0xf000) >> 12) { 556e88f27b3Smrg case 0: 557e88f27b3Smrg surf_man->hw_info.row_size = 1024; 558e88f27b3Smrg break; 559e88f27b3Smrg case 1: 560e88f27b3Smrg surf_man->hw_info.row_size = 2048; 561e88f27b3Smrg break; 562e88f27b3Smrg case 2: 563e88f27b3Smrg surf_man->hw_info.row_size = 4096; 564e88f27b3Smrg break; 565e88f27b3Smrg default: 566e88f27b3Smrg surf_man->hw_info.row_size = 4096; 567e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 568e88f27b3Smrg break; 569e88f27b3Smrg } 570e88f27b3Smrg return 0; 571e88f27b3Smrg} 572e88f27b3Smrg 573e88f27b3Smrgstatic void eg_surf_minify(struct radeon_surface *surf, 574e88f27b3Smrg struct radeon_surface_level *surflevel, 575e88f27b3Smrg unsigned bpe, 576e88f27b3Smrg unsigned level, 577e88f27b3Smrg unsigned slice_pt, 578e88f27b3Smrg unsigned mtilew, 579e88f27b3Smrg unsigned mtileh, 580e88f27b3Smrg unsigned mtileb, 581fe517fc9Smrg uint64_t offset) 582e88f27b3Smrg{ 583e88f27b3Smrg unsigned mtile_pr, mtile_ps; 584e88f27b3Smrg 585e88f27b3Smrg surflevel->npix_x = mip_minify(surf->npix_x, level); 586e88f27b3Smrg surflevel->npix_y = mip_minify(surf->npix_y, level); 587e88f27b3Smrg surflevel->npix_z = mip_minify(surf->npix_z, level); 588e88f27b3Smrg surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; 589e88f27b3Smrg surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; 590e88f27b3Smrg surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; 591e88f27b3Smrg if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && 592e88f27b3Smrg !(surf->flags & RADEON_SURF_FMASK)) { 593e88f27b3Smrg if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) { 594e88f27b3Smrg surflevel->mode = RADEON_SURF_MODE_1D; 595e88f27b3Smrg return; 596e88f27b3Smrg } 597e88f27b3Smrg } 598e88f27b3Smrg surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew); 599e88f27b3Smrg surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh); 600e88f27b3Smrg surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1); 601e88f27b3Smrg 602e88f27b3Smrg /* macro tile per row */ 603e88f27b3Smrg mtile_pr = surflevel->nblk_x / mtilew; 604e88f27b3Smrg /* macro tile per slice */ 605e88f27b3Smrg mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh; 606e88f27b3Smrg 607e88f27b3Smrg surflevel->offset = offset; 6083c748557Ssnj surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples; 609fe517fc9Smrg surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt; 610e88f27b3Smrg 611e88f27b3Smrg surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 612e88f27b3Smrg} 613e88f27b3Smrg 614e88f27b3Smrgstatic int eg_surface_init_1d(struct radeon_surface_manager *surf_man, 615e88f27b3Smrg struct radeon_surface *surf, 616e88f27b3Smrg struct radeon_surface_level *level, 617e88f27b3Smrg unsigned bpe, 618e88f27b3Smrg uint64_t offset, unsigned start_level) 619e88f27b3Smrg{ 620e88f27b3Smrg uint32_t xalign, yalign, zalign, tilew; 621e88f27b3Smrg unsigned i; 622e88f27b3Smrg 623e88f27b3Smrg /* compute alignment */ 624e88f27b3Smrg tilew = 8; 625e88f27b3Smrg xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples); 626e88f27b3Smrg xalign = MAX2(tilew, xalign); 627e88f27b3Smrg yalign = tilew; 628e88f27b3Smrg zalign = 1; 629e88f27b3Smrg if (surf->flags & RADEON_SURF_SCANOUT) { 630e88f27b3Smrg xalign = MAX2((bpe == 1) ? 64 : 32, xalign); 631e88f27b3Smrg } 632e88f27b3Smrg 633e88f27b3Smrg if (!start_level) { 634e88f27b3Smrg unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes); 635e88f27b3Smrg surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 636e88f27b3Smrg 637e88f27b3Smrg if (offset) { 638e88f27b3Smrg offset = ALIGN(offset, alignment); 639e88f27b3Smrg } 640e88f27b3Smrg } 641e88f27b3Smrg 642e88f27b3Smrg /* build mipmap tree */ 643e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 644e88f27b3Smrg level[i].mode = RADEON_SURF_MODE_1D; 645e88f27b3Smrg surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset); 646e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 647e88f27b3Smrg offset = surf->bo_size; 648a884aba1Smrg if (i == 0) { 649e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 650e88f27b3Smrg } 651e88f27b3Smrg } 652e88f27b3Smrg return 0; 653e88f27b3Smrg} 654e88f27b3Smrg 655e88f27b3Smrgstatic int eg_surface_init_2d(struct radeon_surface_manager *surf_man, 656e88f27b3Smrg struct radeon_surface *surf, 657e88f27b3Smrg struct radeon_surface_level *level, 658e88f27b3Smrg unsigned bpe, unsigned tile_split, 659e88f27b3Smrg uint64_t offset, unsigned start_level) 660e88f27b3Smrg{ 661e88f27b3Smrg unsigned tilew, tileh, tileb; 662e88f27b3Smrg unsigned mtilew, mtileh, mtileb; 663e88f27b3Smrg unsigned slice_pt; 664e88f27b3Smrg unsigned i; 665e88f27b3Smrg 666e88f27b3Smrg /* compute tile values */ 667e88f27b3Smrg tilew = 8; 668e88f27b3Smrg tileh = 8; 669e88f27b3Smrg tileb = tilew * tileh * bpe * surf->nsamples; 670e88f27b3Smrg /* slices per tile */ 671e88f27b3Smrg slice_pt = 1; 672e88f27b3Smrg if (tileb > tile_split && tile_split) { 673e88f27b3Smrg slice_pt = tileb / tile_split; 674e88f27b3Smrg } 675e88f27b3Smrg tileb = tileb / slice_pt; 676e88f27b3Smrg 677e88f27b3Smrg /* macro tile width & height */ 678e88f27b3Smrg mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea; 679e88f27b3Smrg mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea; 680e88f27b3Smrg /* macro tile bytes */ 681e88f27b3Smrg mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; 682e88f27b3Smrg 683e88f27b3Smrg if (!start_level) { 684e88f27b3Smrg unsigned alignment = MAX2(256, mtileb); 685e88f27b3Smrg surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 686e88f27b3Smrg 687e88f27b3Smrg if (offset) { 688e88f27b3Smrg offset = ALIGN(offset, alignment); 689e88f27b3Smrg } 690e88f27b3Smrg } 691e88f27b3Smrg 692e88f27b3Smrg /* build mipmap tree */ 693e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 694e88f27b3Smrg level[i].mode = RADEON_SURF_MODE_2D; 695e88f27b3Smrg eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset); 696e88f27b3Smrg if (level[i].mode == RADEON_SURF_MODE_1D) { 697e88f27b3Smrg return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i); 698e88f27b3Smrg } 699e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 700e88f27b3Smrg offset = surf->bo_size; 701a884aba1Smrg if (i == 0) { 702e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 703e88f27b3Smrg } 704e88f27b3Smrg } 705e88f27b3Smrg return 0; 706e88f27b3Smrg} 707e88f27b3Smrg 708e88f27b3Smrgstatic int eg_surface_sanity(struct radeon_surface_manager *surf_man, 709e88f27b3Smrg struct radeon_surface *surf, 710e88f27b3Smrg unsigned mode) 711e88f27b3Smrg{ 712e88f27b3Smrg unsigned tileb; 713e88f27b3Smrg 714e88f27b3Smrg /* check surface dimension */ 715e88f27b3Smrg if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { 716e88f27b3Smrg return -EINVAL; 717e88f27b3Smrg } 718e88f27b3Smrg 719e88f27b3Smrg /* check mipmap last_level */ 720e88f27b3Smrg if (surf->last_level > 15) { 721e88f27b3Smrg return -EINVAL; 722e88f27b3Smrg } 723e88f27b3Smrg 724e88f27b3Smrg /* force 1d on kernel that can't do 2d */ 725e88f27b3Smrg if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) { 726e88f27b3Smrg if (surf->nsamples > 1) { 727e88f27b3Smrg fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__); 728e88f27b3Smrg return -EFAULT; 729e88f27b3Smrg } 730e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 731e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 732e88f27b3Smrg surf->flags |= RADEON_SURF_SET(mode, MODE); 733e88f27b3Smrg } 734e88f27b3Smrg 735e88f27b3Smrg /* check tile split */ 736e88f27b3Smrg if (mode == RADEON_SURF_MODE_2D) { 737e88f27b3Smrg switch (surf->tile_split) { 738e88f27b3Smrg case 64: 739e88f27b3Smrg case 128: 740e88f27b3Smrg case 256: 741e88f27b3Smrg case 512: 742e88f27b3Smrg case 1024: 743e88f27b3Smrg case 2048: 744e88f27b3Smrg case 4096: 745e88f27b3Smrg break; 746e88f27b3Smrg default: 747e88f27b3Smrg return -EINVAL; 748e88f27b3Smrg } 749e88f27b3Smrg switch (surf->mtilea) { 750e88f27b3Smrg case 1: 751e88f27b3Smrg case 2: 752e88f27b3Smrg case 4: 753e88f27b3Smrg case 8: 754e88f27b3Smrg break; 755e88f27b3Smrg default: 756e88f27b3Smrg return -EINVAL; 757e88f27b3Smrg } 758e88f27b3Smrg /* check aspect ratio */ 759e88f27b3Smrg if (surf_man->hw_info.num_banks < surf->mtilea) { 760e88f27b3Smrg return -EINVAL; 761e88f27b3Smrg } 762e88f27b3Smrg /* check bank width */ 763e88f27b3Smrg switch (surf->bankw) { 764e88f27b3Smrg case 1: 765e88f27b3Smrg case 2: 766e88f27b3Smrg case 4: 767e88f27b3Smrg case 8: 768e88f27b3Smrg break; 769e88f27b3Smrg default: 770e88f27b3Smrg return -EINVAL; 771e88f27b3Smrg } 772e88f27b3Smrg /* check bank height */ 773e88f27b3Smrg switch (surf->bankh) { 774e88f27b3Smrg case 1: 775e88f27b3Smrg case 2: 776e88f27b3Smrg case 4: 777e88f27b3Smrg case 8: 778e88f27b3Smrg break; 779e88f27b3Smrg default: 780e88f27b3Smrg return -EINVAL; 781e88f27b3Smrg } 782e88f27b3Smrg tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples); 783e88f27b3Smrg if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) { 784e88f27b3Smrg return -EINVAL; 785e88f27b3Smrg } 786e88f27b3Smrg } 787e88f27b3Smrg 788e88f27b3Smrg return 0; 789e88f27b3Smrg} 790e88f27b3Smrg 791e88f27b3Smrgstatic int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, 792e88f27b3Smrg struct radeon_surface *surf) 793e88f27b3Smrg{ 794e88f27b3Smrg unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER; 795e88f27b3Smrg int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags; 796424e9256Smrg /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */ 797e88f27b3Smrg struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL]; 798e88f27b3Smrg struct radeon_surface_level *stencil_level = 799e88f27b3Smrg (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp; 800e88f27b3Smrg 801e88f27b3Smrg r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0); 802e88f27b3Smrg if (r) 803e88f27b3Smrg return r; 804e88f27b3Smrg 805e88f27b3Smrg if (is_depth_stencil) { 806e88f27b3Smrg r = eg_surface_init_1d(surf_man, surf, stencil_level, 1, 807e88f27b3Smrg surf->bo_size, 0); 808e88f27b3Smrg surf->stencil_offset = stencil_level[0].offset; 809e88f27b3Smrg } 810e88f27b3Smrg return r; 811e88f27b3Smrg} 812e88f27b3Smrg 813e88f27b3Smrgstatic int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, 814e88f27b3Smrg struct radeon_surface *surf) 815e88f27b3Smrg{ 816e88f27b3Smrg unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER; 817e88f27b3Smrg int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags; 818424e9256Smrg /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */ 819e88f27b3Smrg struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL]; 820e88f27b3Smrg struct radeon_surface_level *stencil_level = 821e88f27b3Smrg (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp; 822e88f27b3Smrg 823e88f27b3Smrg r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe, 824e88f27b3Smrg surf->tile_split, 0, 0); 825e88f27b3Smrg if (r) 826e88f27b3Smrg return r; 827e88f27b3Smrg 828e88f27b3Smrg if (is_depth_stencil) { 829e88f27b3Smrg r = eg_surface_init_2d(surf_man, surf, stencil_level, 1, 830e88f27b3Smrg surf->stencil_tile_split, surf->bo_size, 0); 831e88f27b3Smrg surf->stencil_offset = stencil_level[0].offset; 832e88f27b3Smrg } 833e88f27b3Smrg return r; 834e88f27b3Smrg} 835e88f27b3Smrg 836e88f27b3Smrgstatic int eg_surface_init(struct radeon_surface_manager *surf_man, 837e88f27b3Smrg struct radeon_surface *surf) 838e88f27b3Smrg{ 839e88f27b3Smrg unsigned mode; 840e88f27b3Smrg int r; 841e88f27b3Smrg 842e88f27b3Smrg /* MSAA surfaces support the 2D mode only. */ 843e88f27b3Smrg if (surf->nsamples > 1) { 844e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 845e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 846e88f27b3Smrg } 847e88f27b3Smrg 848e88f27b3Smrg /* tiling mode */ 849e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 850e88f27b3Smrg 851e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 852e88f27b3Smrg /* zbuffer only support 1D or 2D tiled surface */ 853e88f27b3Smrg switch (mode) { 854e88f27b3Smrg case RADEON_SURF_MODE_1D: 855e88f27b3Smrg case RADEON_SURF_MODE_2D: 856e88f27b3Smrg break; 857e88f27b3Smrg default: 858e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 859e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 860e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 861e88f27b3Smrg break; 862e88f27b3Smrg } 863e88f27b3Smrg } 864e88f27b3Smrg 865e88f27b3Smrg r = eg_surface_sanity(surf_man, surf, mode); 866e88f27b3Smrg if (r) { 867e88f27b3Smrg return r; 868e88f27b3Smrg } 869e88f27b3Smrg 870e88f27b3Smrg surf->stencil_offset = 0; 871e88f27b3Smrg surf->bo_alignment = 0; 872e88f27b3Smrg 873e88f27b3Smrg /* check tiling mode */ 874e88f27b3Smrg switch (mode) { 875e88f27b3Smrg case RADEON_SURF_MODE_LINEAR: 876e88f27b3Smrg r = r6_surface_init_linear(surf_man, surf, 0, 0); 877e88f27b3Smrg break; 878e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 879e88f27b3Smrg r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0); 880e88f27b3Smrg break; 881e88f27b3Smrg case RADEON_SURF_MODE_1D: 882e88f27b3Smrg r = eg_surface_init_1d_miptrees(surf_man, surf); 883e88f27b3Smrg break; 884e88f27b3Smrg case RADEON_SURF_MODE_2D: 885e88f27b3Smrg r = eg_surface_init_2d_miptrees(surf_man, surf); 886e88f27b3Smrg break; 887e88f27b3Smrg default: 888e88f27b3Smrg return -EINVAL; 889e88f27b3Smrg } 890e88f27b3Smrg return r; 891e88f27b3Smrg} 892e88f27b3Smrg 893e88f27b3Smrgstatic unsigned log2_int(unsigned x) 894e88f27b3Smrg{ 895e88f27b3Smrg unsigned l; 896e88f27b3Smrg 897e88f27b3Smrg if (x < 2) { 898e88f27b3Smrg return 0; 899e88f27b3Smrg } 900e88f27b3Smrg for (l = 2; ; l++) { 901e88f27b3Smrg if ((unsigned)(1 << l) > x) { 902e88f27b3Smrg return l - 1; 903e88f27b3Smrg } 904e88f27b3Smrg } 905e88f27b3Smrg return 0; 906e88f27b3Smrg} 907e88f27b3Smrg 908e88f27b3Smrg/* compute best tile_split, bankw, bankh, mtilea 909e88f27b3Smrg * depending on surface 910e88f27b3Smrg */ 911e88f27b3Smrgstatic int eg_surface_best(struct radeon_surface_manager *surf_man, 912e88f27b3Smrg struct radeon_surface *surf) 913e88f27b3Smrg{ 914e88f27b3Smrg unsigned mode, tileb, h_over_w; 915e88f27b3Smrg int r; 916e88f27b3Smrg 917e88f27b3Smrg /* tiling mode */ 918e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 919e88f27b3Smrg 920e88f27b3Smrg /* set some default value to avoid sanity check choking on them */ 921e88f27b3Smrg surf->tile_split = 1024; 922e88f27b3Smrg surf->bankw = 1; 923e88f27b3Smrg surf->bankh = 1; 924e88f27b3Smrg surf->mtilea = surf_man->hw_info.num_banks; 925e88f27b3Smrg tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples); 926e88f27b3Smrg for (; surf->bankh <= 8; surf->bankh *= 2) { 927e88f27b3Smrg if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) { 928e88f27b3Smrg break; 929e88f27b3Smrg } 930e88f27b3Smrg } 931e88f27b3Smrg if (surf->mtilea > 8) { 932e88f27b3Smrg surf->mtilea = 8; 933e88f27b3Smrg } 934e88f27b3Smrg 935e88f27b3Smrg r = eg_surface_sanity(surf_man, surf, mode); 936e88f27b3Smrg if (r) { 937e88f27b3Smrg return r; 938e88f27b3Smrg } 939e88f27b3Smrg 940e88f27b3Smrg if (mode != RADEON_SURF_MODE_2D) { 941e88f27b3Smrg /* nothing to do for non 2D tiled surface */ 942e88f27b3Smrg return 0; 943e88f27b3Smrg } 944e88f27b3Smrg 945e88f27b3Smrg /* Tweak TILE_SPLIT for performance here. */ 946e88f27b3Smrg if (surf->nsamples > 1) { 947e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 948e88f27b3Smrg switch (surf->nsamples) { 949e88f27b3Smrg case 2: 950e88f27b3Smrg surf->tile_split = 128; 951e88f27b3Smrg break; 952e88f27b3Smrg case 4: 953e88f27b3Smrg surf->tile_split = 128; 954e88f27b3Smrg break; 955e88f27b3Smrg case 8: 956e88f27b3Smrg surf->tile_split = 256; 957e88f27b3Smrg break; 958e88f27b3Smrg case 16: /* cayman only */ 959e88f27b3Smrg surf->tile_split = 512; 960e88f27b3Smrg break; 961e88f27b3Smrg default: 962e88f27b3Smrg fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n", 963e88f27b3Smrg surf->nsamples, __LINE__); 964e88f27b3Smrg return -EINVAL; 965e88f27b3Smrg } 966e88f27b3Smrg surf->stencil_tile_split = 64; 967e88f27b3Smrg } else { 968fe517fc9Smrg /* tile split must be >= 256 for colorbuffer surfaces, 969fe517fc9Smrg * SAMPLE_SPLIT = tile_split / (bpe * 64), the optimal value is 2 970fe517fc9Smrg */ 971fe517fc9Smrg surf->tile_split = MAX2(2 * surf->bpe * 64, 256); 972e88f27b3Smrg if (surf->tile_split > 4096) 973e88f27b3Smrg surf->tile_split = 4096; 974e88f27b3Smrg } 975e88f27b3Smrg } else { 976e88f27b3Smrg /* set tile split to row size */ 977e88f27b3Smrg surf->tile_split = surf_man->hw_info.row_size; 978e88f27b3Smrg surf->stencil_tile_split = surf_man->hw_info.row_size / 2; 979e88f27b3Smrg } 980e88f27b3Smrg 981e88f27b3Smrg /* bankw or bankh greater than 1 increase alignment requirement, not 982e88f27b3Smrg * sure if it's worth using smaller bankw & bankh to stick with 2D 983e88f27b3Smrg * tiling on small surface rather than falling back to 1D tiling. 9842ee35494Smrg * Use recommended value based on tile size for now. 985e88f27b3Smrg * 986e88f27b3Smrg * fmask buffer has different optimal value figure them out once we 987e88f27b3Smrg * use it. 988e88f27b3Smrg */ 989e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 990e88f27b3Smrg /* assume 1 bytes for stencil, we optimize for stencil as stencil 991e88f27b3Smrg * and depth shares surface values 992e88f27b3Smrg */ 993e88f27b3Smrg tileb = MIN2(surf->tile_split, 64 * surf->nsamples); 994e88f27b3Smrg } else { 995e88f27b3Smrg tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples); 996e88f27b3Smrg } 997e88f27b3Smrg 998e88f27b3Smrg /* use bankw of 1 to minimize width alignment, might be interesting to 999e88f27b3Smrg * increase it for large surface 1000e88f27b3Smrg */ 1001e88f27b3Smrg surf->bankw = 1; 1002e88f27b3Smrg switch (tileb) { 1003e88f27b3Smrg case 64: 1004e88f27b3Smrg surf->bankh = 4; 1005e88f27b3Smrg break; 1006e88f27b3Smrg case 128: 1007e88f27b3Smrg case 256: 1008e88f27b3Smrg surf->bankh = 2; 1009e88f27b3Smrg break; 1010e88f27b3Smrg default: 1011e88f27b3Smrg surf->bankh = 1; 1012e88f27b3Smrg break; 1013e88f27b3Smrg } 1014e88f27b3Smrg /* double check the constraint */ 1015e88f27b3Smrg for (; surf->bankh <= 8; surf->bankh *= 2) { 1016e88f27b3Smrg if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) { 1017e88f27b3Smrg break; 1018e88f27b3Smrg } 1019e88f27b3Smrg } 1020e88f27b3Smrg 1021e88f27b3Smrg h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) / 1022e88f27b3Smrg (surf->bankw * surf_man->hw_info.num_pipes)) >> 16; 1023e88f27b3Smrg surf->mtilea = 1 << (log2_int(h_over_w) >> 1); 1024e88f27b3Smrg 1025e88f27b3Smrg return 0; 1026e88f27b3Smrg} 1027e88f27b3Smrg 1028e88f27b3Smrg 1029e88f27b3Smrg/* =========================================================================== 1030e88f27b3Smrg * Southern Islands family 1031e88f27b3Smrg */ 1032e88f27b3Smrg#define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) 1033e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P2 0 1034e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 1035e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 1036e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 1037e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 1038e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 1039e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 1040e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 1041e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 1042e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 1043e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 1044e88f27b3Smrg#define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 1045e88f27b3Smrg#define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7) 1046e88f27b3Smrg#define SI__TILE_SPLIT__64B 0 1047e88f27b3Smrg#define SI__TILE_SPLIT__128B 1 1048e88f27b3Smrg#define SI__TILE_SPLIT__256B 2 1049e88f27b3Smrg#define SI__TILE_SPLIT__512B 3 1050e88f27b3Smrg#define SI__TILE_SPLIT__1024B 4 1051e88f27b3Smrg#define SI__TILE_SPLIT__2048B 5 1052e88f27b3Smrg#define SI__TILE_SPLIT__4096B 6 1053e88f27b3Smrg#define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3) 1054e88f27b3Smrg#define SI__BANK_WIDTH__1 0 1055e88f27b3Smrg#define SI__BANK_WIDTH__2 1 1056e88f27b3Smrg#define SI__BANK_WIDTH__4 2 1057e88f27b3Smrg#define SI__BANK_WIDTH__8 3 1058e88f27b3Smrg#define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3) 1059e88f27b3Smrg#define SI__BANK_HEIGHT__1 0 1060e88f27b3Smrg#define SI__BANK_HEIGHT__2 1 1061e88f27b3Smrg#define SI__BANK_HEIGHT__4 2 1062e88f27b3Smrg#define SI__BANK_HEIGHT__8 3 1063e88f27b3Smrg#define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3) 1064e88f27b3Smrg#define SI__MACRO_TILE_ASPECT__1 0 1065e88f27b3Smrg#define SI__MACRO_TILE_ASPECT__2 1 1066e88f27b3Smrg#define SI__MACRO_TILE_ASPECT__4 2 1067e88f27b3Smrg#define SI__MACRO_TILE_ASPECT__8 3 1068e88f27b3Smrg#define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3) 1069e88f27b3Smrg#define SI__NUM_BANKS__2_BANK 0 1070e88f27b3Smrg#define SI__NUM_BANKS__4_BANK 1 1071e88f27b3Smrg#define SI__NUM_BANKS__8_BANK 2 1072e88f27b3Smrg#define SI__NUM_BANKS__16_BANK 3 1073e88f27b3Smrg 1074e88f27b3Smrg 1075e88f27b3Smrgstatic void si_gb_tile_mode(uint32_t gb_tile_mode, 1076e88f27b3Smrg unsigned *num_pipes, 1077e88f27b3Smrg unsigned *num_banks, 1078e88f27b3Smrg uint32_t *macro_tile_aspect, 1079e88f27b3Smrg uint32_t *bank_w, 1080e88f27b3Smrg uint32_t *bank_h, 1081e88f27b3Smrg uint32_t *tile_split) 1082e88f27b3Smrg{ 1083e88f27b3Smrg if (num_pipes) { 1084e88f27b3Smrg switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) { 1085e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P2: 1086e88f27b3Smrg default: 1087e88f27b3Smrg *num_pipes = 2; 1088e88f27b3Smrg break; 1089e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16: 1090e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16: 1091e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32: 1092e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32: 1093e88f27b3Smrg *num_pipes = 4; 1094e88f27b3Smrg break; 1095e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: 1096e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: 1097e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: 1098e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: 1099e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: 1100e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: 1101e88f27b3Smrg case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: 1102e88f27b3Smrg *num_pipes = 8; 1103e88f27b3Smrg break; 1104e88f27b3Smrg } 1105e88f27b3Smrg } 1106e88f27b3Smrg if (num_banks) { 1107e88f27b3Smrg switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) { 1108e88f27b3Smrg default: 1109e88f27b3Smrg case SI__NUM_BANKS__2_BANK: 1110e88f27b3Smrg *num_banks = 2; 1111e88f27b3Smrg break; 1112e88f27b3Smrg case SI__NUM_BANKS__4_BANK: 1113e88f27b3Smrg *num_banks = 4; 1114e88f27b3Smrg break; 1115e88f27b3Smrg case SI__NUM_BANKS__8_BANK: 1116e88f27b3Smrg *num_banks = 8; 1117e88f27b3Smrg break; 1118e88f27b3Smrg case SI__NUM_BANKS__16_BANK: 1119e88f27b3Smrg *num_banks = 16; 1120e88f27b3Smrg break; 1121e88f27b3Smrg } 1122e88f27b3Smrg } 1123e88f27b3Smrg if (macro_tile_aspect) { 1124e88f27b3Smrg switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) { 1125e88f27b3Smrg default: 1126e88f27b3Smrg case SI__MACRO_TILE_ASPECT__1: 1127e88f27b3Smrg *macro_tile_aspect = 1; 1128e88f27b3Smrg break; 1129e88f27b3Smrg case SI__MACRO_TILE_ASPECT__2: 1130e88f27b3Smrg *macro_tile_aspect = 2; 1131e88f27b3Smrg break; 1132e88f27b3Smrg case SI__MACRO_TILE_ASPECT__4: 1133e88f27b3Smrg *macro_tile_aspect = 4; 1134e88f27b3Smrg break; 1135e88f27b3Smrg case SI__MACRO_TILE_ASPECT__8: 1136e88f27b3Smrg *macro_tile_aspect = 8; 1137e88f27b3Smrg break; 1138e88f27b3Smrg } 1139e88f27b3Smrg } 1140e88f27b3Smrg if (bank_w) { 1141e88f27b3Smrg switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) { 1142e88f27b3Smrg default: 1143e88f27b3Smrg case SI__BANK_WIDTH__1: 1144e88f27b3Smrg *bank_w = 1; 1145e88f27b3Smrg break; 1146e88f27b3Smrg case SI__BANK_WIDTH__2: 1147e88f27b3Smrg *bank_w = 2; 1148e88f27b3Smrg break; 1149e88f27b3Smrg case SI__BANK_WIDTH__4: 1150e88f27b3Smrg *bank_w = 4; 1151e88f27b3Smrg break; 1152e88f27b3Smrg case SI__BANK_WIDTH__8: 1153e88f27b3Smrg *bank_w = 8; 1154e88f27b3Smrg break; 1155e88f27b3Smrg } 1156e88f27b3Smrg } 1157e88f27b3Smrg if (bank_h) { 1158e88f27b3Smrg switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) { 1159e88f27b3Smrg default: 1160e88f27b3Smrg case SI__BANK_HEIGHT__1: 1161e88f27b3Smrg *bank_h = 1; 1162e88f27b3Smrg break; 1163e88f27b3Smrg case SI__BANK_HEIGHT__2: 1164e88f27b3Smrg *bank_h = 2; 1165e88f27b3Smrg break; 1166e88f27b3Smrg case SI__BANK_HEIGHT__4: 1167e88f27b3Smrg *bank_h = 4; 1168e88f27b3Smrg break; 1169e88f27b3Smrg case SI__BANK_HEIGHT__8: 1170e88f27b3Smrg *bank_h = 8; 1171e88f27b3Smrg break; 1172e88f27b3Smrg } 1173e88f27b3Smrg } 1174e88f27b3Smrg if (tile_split) { 1175e88f27b3Smrg switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) { 1176e88f27b3Smrg default: 1177e88f27b3Smrg case SI__TILE_SPLIT__64B: 1178e88f27b3Smrg *tile_split = 64; 1179e88f27b3Smrg break; 1180e88f27b3Smrg case SI__TILE_SPLIT__128B: 1181e88f27b3Smrg *tile_split = 128; 1182e88f27b3Smrg break; 1183e88f27b3Smrg case SI__TILE_SPLIT__256B: 1184e88f27b3Smrg *tile_split = 256; 1185e88f27b3Smrg break; 1186e88f27b3Smrg case SI__TILE_SPLIT__512B: 1187e88f27b3Smrg *tile_split = 512; 1188e88f27b3Smrg break; 1189e88f27b3Smrg case SI__TILE_SPLIT__1024B: 1190e88f27b3Smrg *tile_split = 1024; 1191e88f27b3Smrg break; 1192e88f27b3Smrg case SI__TILE_SPLIT__2048B: 1193e88f27b3Smrg *tile_split = 2048; 1194e88f27b3Smrg break; 1195e88f27b3Smrg case SI__TILE_SPLIT__4096B: 1196e88f27b3Smrg *tile_split = 4096; 1197e88f27b3Smrg break; 1198e88f27b3Smrg } 1199e88f27b3Smrg } 1200e88f27b3Smrg} 1201e88f27b3Smrg 1202e88f27b3Smrgstatic int si_init_hw_info(struct radeon_surface_manager *surf_man) 1203e88f27b3Smrg{ 1204e88f27b3Smrg uint32_t tiling_config; 1205e88f27b3Smrg drmVersionPtr version; 1206e88f27b3Smrg int r; 1207e88f27b3Smrg 1208e88f27b3Smrg r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, 1209e88f27b3Smrg &tiling_config); 1210e88f27b3Smrg if (r) { 1211e88f27b3Smrg return r; 1212e88f27b3Smrg } 1213e88f27b3Smrg 1214e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 1215e88f27b3Smrg version = drmGetVersion(surf_man->fd); 1216e88f27b3Smrg if (version && version->version_minor >= 33) { 1217e88f27b3Smrg if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) { 1218e88f27b3Smrg surf_man->hw_info.allow_2d = 1; 1219e88f27b3Smrg } 1220e88f27b3Smrg } 1221e88f27b3Smrg drmFreeVersion(version); 1222e88f27b3Smrg 1223e88f27b3Smrg switch (tiling_config & 0xf) { 1224e88f27b3Smrg case 0: 1225e88f27b3Smrg surf_man->hw_info.num_pipes = 1; 1226e88f27b3Smrg break; 1227e88f27b3Smrg case 1: 1228e88f27b3Smrg surf_man->hw_info.num_pipes = 2; 1229e88f27b3Smrg break; 1230e88f27b3Smrg case 2: 1231e88f27b3Smrg surf_man->hw_info.num_pipes = 4; 1232e88f27b3Smrg break; 1233e88f27b3Smrg case 3: 1234e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 1235e88f27b3Smrg break; 1236e88f27b3Smrg default: 1237e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 1238e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 1239e88f27b3Smrg break; 1240e88f27b3Smrg } 1241e88f27b3Smrg 1242e88f27b3Smrg switch ((tiling_config & 0xf0) >> 4) { 1243e88f27b3Smrg case 0: 1244e88f27b3Smrg surf_man->hw_info.num_banks = 4; 1245e88f27b3Smrg break; 1246e88f27b3Smrg case 1: 1247e88f27b3Smrg surf_man->hw_info.num_banks = 8; 1248e88f27b3Smrg break; 1249e88f27b3Smrg case 2: 1250e88f27b3Smrg surf_man->hw_info.num_banks = 16; 1251e88f27b3Smrg break; 1252e88f27b3Smrg default: 1253e88f27b3Smrg surf_man->hw_info.num_banks = 8; 1254e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 1255e88f27b3Smrg break; 1256e88f27b3Smrg } 1257e88f27b3Smrg 1258e88f27b3Smrg switch ((tiling_config & 0xf00) >> 8) { 1259e88f27b3Smrg case 0: 1260e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 1261e88f27b3Smrg break; 1262e88f27b3Smrg case 1: 1263e88f27b3Smrg surf_man->hw_info.group_bytes = 512; 1264e88f27b3Smrg break; 1265e88f27b3Smrg default: 1266e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 1267e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 1268e88f27b3Smrg break; 1269e88f27b3Smrg } 1270e88f27b3Smrg 1271e88f27b3Smrg switch ((tiling_config & 0xf000) >> 12) { 1272e88f27b3Smrg case 0: 1273e88f27b3Smrg surf_man->hw_info.row_size = 1024; 1274e88f27b3Smrg break; 1275e88f27b3Smrg case 1: 1276e88f27b3Smrg surf_man->hw_info.row_size = 2048; 1277e88f27b3Smrg break; 1278e88f27b3Smrg case 2: 1279e88f27b3Smrg surf_man->hw_info.row_size = 4096; 1280e88f27b3Smrg break; 1281e88f27b3Smrg default: 1282e88f27b3Smrg surf_man->hw_info.row_size = 4096; 1283e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 1284e88f27b3Smrg break; 1285e88f27b3Smrg } 1286e88f27b3Smrg return 0; 1287e88f27b3Smrg} 1288e88f27b3Smrg 1289e88f27b3Smrgstatic int si_surface_sanity(struct radeon_surface_manager *surf_man, 1290e88f27b3Smrg struct radeon_surface *surf, 1291e88f27b3Smrg unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode) 1292e88f27b3Smrg{ 1293e88f27b3Smrg uint32_t gb_tile_mode; 1294e88f27b3Smrg 1295e88f27b3Smrg /* check surface dimension */ 1296e88f27b3Smrg if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { 1297e88f27b3Smrg return -EINVAL; 1298e88f27b3Smrg } 1299e88f27b3Smrg 1300e88f27b3Smrg /* check mipmap last_level */ 1301e88f27b3Smrg if (surf->last_level > 15) { 1302e88f27b3Smrg return -EINVAL; 1303e88f27b3Smrg } 1304e88f27b3Smrg 1305e88f27b3Smrg /* force 1d on kernel that can't do 2d */ 1306e88f27b3Smrg if (mode > RADEON_SURF_MODE_1D && 1307e88f27b3Smrg (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) { 1308e88f27b3Smrg if (surf->nsamples > 1) { 1309e88f27b3Smrg fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__); 1310e88f27b3Smrg return -EFAULT; 1311e88f27b3Smrg } 1312e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 1313e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1314e88f27b3Smrg surf->flags |= RADEON_SURF_SET(mode, MODE); 1315e88f27b3Smrg } 1316e88f27b3Smrg 1317e88f27b3Smrg if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) { 1318e88f27b3Smrg return -EINVAL; 1319e88f27b3Smrg } 1320e88f27b3Smrg 1321e88f27b3Smrg if (!surf->tile_split) { 1322e88f27b3Smrg /* default value */ 1323e88f27b3Smrg surf->mtilea = 1; 1324e88f27b3Smrg surf->bankw = 1; 1325a884aba1Smrg surf->bankh = 1; 1326e88f27b3Smrg surf->tile_split = 64; 1327e88f27b3Smrg surf->stencil_tile_split = 64; 1328e88f27b3Smrg } 1329e88f27b3Smrg 1330e88f27b3Smrg switch (mode) { 1331e88f27b3Smrg case RADEON_SURF_MODE_2D: 1332e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 1333e88f27b3Smrg switch (surf->nsamples) { 1334e88f27b3Smrg case 1: 1335e88f27b3Smrg *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; 1336e88f27b3Smrg break; 1337e88f27b3Smrg case 2: 1338e88f27b3Smrg *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; 1339e88f27b3Smrg break; 1340e88f27b3Smrg case 4: 1341e88f27b3Smrg *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; 1342e88f27b3Smrg break; 1343e88f27b3Smrg case 8: 1344e88f27b3Smrg *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; 1345e88f27b3Smrg break; 1346e88f27b3Smrg default: 1347e88f27b3Smrg return -EINVAL; 1348e88f27b3Smrg } 1349e88f27b3Smrg /* retrieve tiling mode value */ 1350e88f27b3Smrg gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode]; 1351e88f27b3Smrg si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split); 1352e88f27b3Smrg } 1353e88f27b3Smrg if (surf->flags & RADEON_SURF_ZBUFFER) { 1354e88f27b3Smrg switch (surf->nsamples) { 1355e88f27b3Smrg case 1: 1356e88f27b3Smrg *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D; 1357e88f27b3Smrg break; 1358e88f27b3Smrg case 2: 1359e88f27b3Smrg *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA; 1360e88f27b3Smrg break; 1361e88f27b3Smrg case 4: 1362e88f27b3Smrg *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA; 1363e88f27b3Smrg break; 1364e88f27b3Smrg case 8: 1365e88f27b3Smrg *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA; 1366e88f27b3Smrg break; 1367e88f27b3Smrg default: 1368e88f27b3Smrg return -EINVAL; 1369e88f27b3Smrg } 1370e88f27b3Smrg } else if (surf->flags & RADEON_SURF_SCANOUT) { 1371e88f27b3Smrg switch (surf->bpe) { 1372e88f27b3Smrg case 2: 1373e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP; 1374e88f27b3Smrg break; 1375e88f27b3Smrg case 4: 1376e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP; 1377e88f27b3Smrg break; 1378e88f27b3Smrg default: 1379e88f27b3Smrg return -EINVAL; 1380e88f27b3Smrg } 1381e88f27b3Smrg } else { 1382e88f27b3Smrg switch (surf->bpe) { 1383e88f27b3Smrg case 1: 1384e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP; 1385e88f27b3Smrg break; 1386e88f27b3Smrg case 2: 1387e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP; 1388e88f27b3Smrg break; 1389e88f27b3Smrg case 4: 1390e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP; 1391e88f27b3Smrg break; 1392e88f27b3Smrg case 8: 1393e88f27b3Smrg case 16: 1394e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP; 1395e88f27b3Smrg break; 1396e88f27b3Smrg default: 1397e88f27b3Smrg return -EINVAL; 1398e88f27b3Smrg } 1399e88f27b3Smrg } 1400e88f27b3Smrg /* retrieve tiling mode value */ 1401e88f27b3Smrg gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode]; 1402e88f27b3Smrg si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split); 1403e88f27b3Smrg break; 1404e88f27b3Smrg case RADEON_SURF_MODE_1D: 1405e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 1406e88f27b3Smrg *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; 1407e88f27b3Smrg } 1408e88f27b3Smrg if (surf->flags & RADEON_SURF_ZBUFFER) { 1409e88f27b3Smrg *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; 1410e88f27b3Smrg } else if (surf->flags & RADEON_SURF_SCANOUT) { 1411e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 1412e88f27b3Smrg } else { 1413e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_1D; 1414e88f27b3Smrg } 1415e88f27b3Smrg break; 1416e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 1417e88f27b3Smrg default: 1418e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; 1419e88f27b3Smrg } 1420e88f27b3Smrg 1421e88f27b3Smrg return 0; 1422e88f27b3Smrg} 1423e88f27b3Smrg 1424e88f27b3Smrgstatic void si_surf_minify(struct radeon_surface *surf, 1425e88f27b3Smrg struct radeon_surface_level *surflevel, 1426e88f27b3Smrg unsigned bpe, unsigned level, 1427e88f27b3Smrg uint32_t xalign, uint32_t yalign, uint32_t zalign, 1428fe517fc9Smrg uint32_t slice_align, uint64_t offset) 1429e88f27b3Smrg{ 1430e88f27b3Smrg if (level == 0) { 1431e88f27b3Smrg surflevel->npix_x = surf->npix_x; 1432e88f27b3Smrg } else { 1433e88f27b3Smrg surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level); 1434e88f27b3Smrg } 1435e88f27b3Smrg surflevel->npix_y = mip_minify(surf->npix_y, level); 1436e88f27b3Smrg surflevel->npix_z = mip_minify(surf->npix_z, level); 1437e88f27b3Smrg 1438e88f27b3Smrg if (level == 0 && surf->last_level > 0) { 1439e88f27b3Smrg surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w; 1440e88f27b3Smrg surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h; 1441e88f27b3Smrg surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d; 1442e88f27b3Smrg } else { 1443e88f27b3Smrg surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; 1444e88f27b3Smrg surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; 1445e88f27b3Smrg surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; 1446e88f27b3Smrg } 1447e88f27b3Smrg 1448e88f27b3Smrg surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); 1449e88f27b3Smrg 1450e88f27b3Smrg /* XXX: Texture sampling uses unexpectedly large pitches in some cases, 1451e88f27b3Smrg * these are just guesses for the rules behind those 1452e88f27b3Smrg */ 1453e88f27b3Smrg if (level == 0 && surf->last_level == 0) 1454e88f27b3Smrg /* Non-mipmap pitch padded to slice alignment */ 1455e88f27b3Smrg /* Using just bpe here breaks stencil blitting; surf->bpe works. */ 1456e88f27b3Smrg xalign = MAX2(xalign, slice_align / surf->bpe); 1457e88f27b3Smrg else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED) 1458e88f27b3Smrg /* Small rows evenly distributed across slice */ 1459e88f27b3Smrg xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y); 1460e88f27b3Smrg 1461e88f27b3Smrg surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); 1462e88f27b3Smrg surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); 1463e88f27b3Smrg 1464e88f27b3Smrg surflevel->offset = offset; 1465e88f27b3Smrg surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples; 1466fe517fc9Smrg surflevel->slice_size = ALIGN((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y, 1467fe517fc9Smrg (uint64_t)slice_align); 1468e88f27b3Smrg 1469e88f27b3Smrg surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 1470e88f27b3Smrg} 1471e88f27b3Smrg 1472e88f27b3Smrgstatic void si_surf_minify_2d(struct radeon_surface *surf, 1473e88f27b3Smrg struct radeon_surface_level *surflevel, 1474e88f27b3Smrg unsigned bpe, unsigned level, unsigned slice_pt, 1475e88f27b3Smrg uint32_t xalign, uint32_t yalign, uint32_t zalign, 1476fe517fc9Smrg unsigned mtileb, uint64_t offset) 1477e88f27b3Smrg{ 1478e88f27b3Smrg unsigned mtile_pr, mtile_ps; 1479e88f27b3Smrg 1480e88f27b3Smrg if (level == 0) { 1481e88f27b3Smrg surflevel->npix_x = surf->npix_x; 1482e88f27b3Smrg } else { 1483e88f27b3Smrg surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level); 1484e88f27b3Smrg } 1485e88f27b3Smrg surflevel->npix_y = mip_minify(surf->npix_y, level); 1486e88f27b3Smrg surflevel->npix_z = mip_minify(surf->npix_z, level); 1487e88f27b3Smrg 1488e88f27b3Smrg if (level == 0 && surf->last_level > 0) { 1489e88f27b3Smrg surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w; 1490e88f27b3Smrg surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h; 1491e88f27b3Smrg surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d; 1492e88f27b3Smrg } else { 1493e88f27b3Smrg surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; 1494e88f27b3Smrg surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; 1495e88f27b3Smrg surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; 1496e88f27b3Smrg } 1497e88f27b3Smrg 1498e88f27b3Smrg if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && 1499e88f27b3Smrg !(surf->flags & RADEON_SURF_FMASK)) { 1500e88f27b3Smrg if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { 1501e88f27b3Smrg surflevel->mode = RADEON_SURF_MODE_1D; 1502e88f27b3Smrg return; 1503e88f27b3Smrg } 1504e88f27b3Smrg } 1505e88f27b3Smrg surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); 1506e88f27b3Smrg surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); 1507e88f27b3Smrg surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); 1508e88f27b3Smrg 1509e88f27b3Smrg /* macro tile per row */ 1510e88f27b3Smrg mtile_pr = surflevel->nblk_x / xalign; 1511e88f27b3Smrg /* macro tile per slice */ 1512e88f27b3Smrg mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign; 1513e88f27b3Smrg surflevel->offset = offset; 15143c748557Ssnj surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples; 1515fe517fc9Smrg surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt; 1516e88f27b3Smrg 1517e88f27b3Smrg surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 1518e88f27b3Smrg} 1519e88f27b3Smrg 1520e88f27b3Smrgstatic int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, 1521e88f27b3Smrg struct radeon_surface *surf, 1522e88f27b3Smrg unsigned tile_mode, 1523e88f27b3Smrg uint64_t offset, unsigned start_level) 1524e88f27b3Smrg{ 1525e88f27b3Smrg uint32_t xalign, yalign, zalign, slice_align; 1526e88f27b3Smrg unsigned i; 1527e88f27b3Smrg 1528e88f27b3Smrg /* compute alignment */ 1529e88f27b3Smrg if (!start_level) { 1530e88f27b3Smrg surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); 1531e88f27b3Smrg } 1532e88f27b3Smrg xalign = MAX2(8, 64 / surf->bpe); 1533e88f27b3Smrg yalign = 1; 1534e88f27b3Smrg zalign = 1; 1535e88f27b3Smrg slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes); 1536e88f27b3Smrg 1537e88f27b3Smrg /* build mipmap tree */ 1538e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 1539e88f27b3Smrg surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; 1540e88f27b3Smrg si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset); 1541e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 1542e88f27b3Smrg offset = surf->bo_size; 1543a884aba1Smrg if (i == 0) { 1544e88f27b3Smrg offset = ALIGN(offset, surf->bo_alignment); 1545e88f27b3Smrg } 1546e88f27b3Smrg if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1547e88f27b3Smrg surf->tiling_index[i] = tile_mode; 1548e88f27b3Smrg } 1549e88f27b3Smrg } 1550e88f27b3Smrg return 0; 1551e88f27b3Smrg} 1552e88f27b3Smrg 1553e88f27b3Smrgstatic int si_surface_init_1d(struct radeon_surface_manager *surf_man, 1554e88f27b3Smrg struct radeon_surface *surf, 1555e88f27b3Smrg struct radeon_surface_level *level, 1556e88f27b3Smrg unsigned bpe, unsigned tile_mode, 1557e88f27b3Smrg uint64_t offset, unsigned start_level) 1558e88f27b3Smrg{ 1559e88f27b3Smrg uint32_t xalign, yalign, zalign, slice_align; 1560e88f27b3Smrg unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes); 1561e88f27b3Smrg unsigned i; 1562e88f27b3Smrg 1563e88f27b3Smrg /* compute alignment */ 1564e88f27b3Smrg xalign = 8; 1565e88f27b3Smrg yalign = 8; 1566e88f27b3Smrg zalign = 1; 1567e88f27b3Smrg slice_align = surf_man->hw_info.group_bytes; 1568e88f27b3Smrg if (surf->flags & RADEON_SURF_SCANOUT) { 1569e88f27b3Smrg xalign = MAX2((bpe == 1) ? 64 : 32, xalign); 1570e88f27b3Smrg } 1571e88f27b3Smrg 1572e88f27b3Smrg if (start_level <= 1) { 1573e88f27b3Smrg surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 1574e88f27b3Smrg 1575e88f27b3Smrg if (offset) { 1576e88f27b3Smrg offset = ALIGN(offset, alignment); 1577e88f27b3Smrg } 1578e88f27b3Smrg } 1579e88f27b3Smrg 1580e88f27b3Smrg /* build mipmap tree */ 1581e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 1582e88f27b3Smrg level[i].mode = RADEON_SURF_MODE_1D; 1583e88f27b3Smrg si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset); 1584e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 1585e88f27b3Smrg offset = surf->bo_size; 1586a884aba1Smrg if (i == 0) { 1587e88f27b3Smrg offset = ALIGN(offset, alignment); 1588e88f27b3Smrg } 1589e88f27b3Smrg if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1590e88f27b3Smrg if (surf->level == level) { 1591e88f27b3Smrg surf->tiling_index[i] = tile_mode; 1592e88f27b3Smrg /* it's ok because stencil is done after */ 1593e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 1594e88f27b3Smrg } else { 1595e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 1596e88f27b3Smrg } 1597e88f27b3Smrg } 1598e88f27b3Smrg } 1599e88f27b3Smrg return 0; 1600e88f27b3Smrg} 1601e88f27b3Smrg 1602e88f27b3Smrgstatic int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, 1603e88f27b3Smrg struct radeon_surface *surf, 1604e88f27b3Smrg unsigned tile_mode, unsigned stencil_tile_mode) 1605e88f27b3Smrg{ 1606e88f27b3Smrg int r; 1607e88f27b3Smrg 1608e88f27b3Smrg r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0); 1609e88f27b3Smrg if (r) { 1610e88f27b3Smrg return r; 1611e88f27b3Smrg } 1612e88f27b3Smrg 1613e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 1614e88f27b3Smrg r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0); 1615e88f27b3Smrg surf->stencil_offset = surf->stencil_level[0].offset; 1616e88f27b3Smrg } 1617e88f27b3Smrg return r; 1618e88f27b3Smrg} 1619e88f27b3Smrg 1620e88f27b3Smrgstatic int si_surface_init_2d(struct radeon_surface_manager *surf_man, 1621e88f27b3Smrg struct radeon_surface *surf, 1622e88f27b3Smrg struct radeon_surface_level *level, 1623e88f27b3Smrg unsigned bpe, unsigned tile_mode, 1624e88f27b3Smrg unsigned num_pipes, unsigned num_banks, 1625e88f27b3Smrg unsigned tile_split, 1626e88f27b3Smrg uint64_t offset, 1627e88f27b3Smrg unsigned start_level) 1628e88f27b3Smrg{ 1629e88f27b3Smrg uint64_t aligned_offset = offset; 1630e88f27b3Smrg unsigned tilew, tileh, tileb; 1631e88f27b3Smrg unsigned mtilew, mtileh, mtileb; 1632e88f27b3Smrg unsigned slice_pt; 1633e88f27b3Smrg unsigned i; 1634e88f27b3Smrg 1635e88f27b3Smrg /* compute tile values */ 1636e88f27b3Smrg tilew = 8; 1637e88f27b3Smrg tileh = 8; 1638e88f27b3Smrg tileb = tilew * tileh * bpe * surf->nsamples; 1639e88f27b3Smrg /* slices per tile */ 1640e88f27b3Smrg slice_pt = 1; 1641e88f27b3Smrg if (tileb > tile_split && tile_split) { 1642e88f27b3Smrg slice_pt = tileb / tile_split; 1643e88f27b3Smrg } 1644e88f27b3Smrg tileb = tileb / slice_pt; 1645e88f27b3Smrg 1646e88f27b3Smrg /* macro tile width & height */ 1647e88f27b3Smrg mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; 1648e88f27b3Smrg mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; 1649e88f27b3Smrg 1650e88f27b3Smrg /* macro tile bytes */ 1651e88f27b3Smrg mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; 1652e88f27b3Smrg 1653e88f27b3Smrg if (start_level <= 1) { 1654e88f27b3Smrg unsigned alignment = MAX2(256, mtileb); 1655e88f27b3Smrg surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 1656e88f27b3Smrg 1657e88f27b3Smrg if (aligned_offset) { 1658e88f27b3Smrg aligned_offset = ALIGN(aligned_offset, alignment); 1659e88f27b3Smrg } 1660e88f27b3Smrg } 1661e88f27b3Smrg 1662e88f27b3Smrg /* build mipmap tree */ 1663e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 1664e88f27b3Smrg level[i].mode = RADEON_SURF_MODE_2D; 1665e88f27b3Smrg si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset); 1666e88f27b3Smrg if (level[i].mode == RADEON_SURF_MODE_1D) { 1667e88f27b3Smrg switch (tile_mode) { 1668e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_8BPP: 1669e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_16BPP: 1670e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_32BPP: 1671e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_64BPP: 1672e88f27b3Smrg tile_mode = SI_TILE_MODE_COLOR_1D; 1673e88f27b3Smrg break; 1674e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP: 1675e88f27b3Smrg case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP: 1676e88f27b3Smrg tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 1677e88f27b3Smrg break; 1678e88f27b3Smrg case SI_TILE_MODE_DEPTH_STENCIL_2D: 1679e88f27b3Smrg tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; 1680e88f27b3Smrg break; 1681e88f27b3Smrg default: 1682e88f27b3Smrg return -EINVAL; 1683e88f27b3Smrg } 1684e88f27b3Smrg return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); 1685e88f27b3Smrg } 1686e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 1687e88f27b3Smrg aligned_offset = offset = surf->bo_size; 1688a884aba1Smrg if (i == 0) { 1689e88f27b3Smrg aligned_offset = ALIGN(aligned_offset, surf->bo_alignment); 1690e88f27b3Smrg } 1691e88f27b3Smrg if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1692e88f27b3Smrg if (surf->level == level) { 1693e88f27b3Smrg surf->tiling_index[i] = tile_mode; 1694e88f27b3Smrg /* it's ok because stencil is done after */ 1695e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 1696e88f27b3Smrg } else { 1697e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 1698e88f27b3Smrg } 1699e88f27b3Smrg } 1700e88f27b3Smrg } 1701e88f27b3Smrg return 0; 1702e88f27b3Smrg} 1703e88f27b3Smrg 1704e88f27b3Smrgstatic int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, 1705e88f27b3Smrg struct radeon_surface *surf, 1706e88f27b3Smrg unsigned tile_mode, unsigned stencil_tile_mode) 1707e88f27b3Smrg{ 1708e88f27b3Smrg unsigned num_pipes, num_banks; 1709e88f27b3Smrg uint32_t gb_tile_mode; 1710e88f27b3Smrg int r; 1711e88f27b3Smrg 1712e88f27b3Smrg /* retrieve tiling mode value */ 1713e88f27b3Smrg gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; 1714e88f27b3Smrg si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL); 1715e88f27b3Smrg 1716e88f27b3Smrg r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0); 1717e88f27b3Smrg if (r) { 1718e88f27b3Smrg return r; 1719e88f27b3Smrg } 1720e88f27b3Smrg 1721e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 1722e88f27b3Smrg r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0); 1723e88f27b3Smrg surf->stencil_offset = surf->stencil_level[0].offset; 1724e88f27b3Smrg } 1725e88f27b3Smrg return r; 1726e88f27b3Smrg} 1727e88f27b3Smrg 1728e88f27b3Smrgstatic int si_surface_init(struct radeon_surface_manager *surf_man, 1729e88f27b3Smrg struct radeon_surface *surf) 1730e88f27b3Smrg{ 1731e88f27b3Smrg unsigned mode, tile_mode, stencil_tile_mode; 1732e88f27b3Smrg int r; 1733e88f27b3Smrg 1734e88f27b3Smrg /* MSAA surfaces support the 2D mode only. */ 1735e88f27b3Smrg if (surf->nsamples > 1) { 1736e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1737e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 1738e88f27b3Smrg } 1739e88f27b3Smrg 1740e88f27b3Smrg /* tiling mode */ 1741e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 1742e88f27b3Smrg 1743e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 1744e88f27b3Smrg /* zbuffer only support 1D or 2D tiled surface */ 1745e88f27b3Smrg switch (mode) { 1746e88f27b3Smrg case RADEON_SURF_MODE_1D: 1747e88f27b3Smrg case RADEON_SURF_MODE_2D: 1748e88f27b3Smrg break; 1749e88f27b3Smrg default: 1750e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 1751e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1752e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1753e88f27b3Smrg break; 1754e88f27b3Smrg } 1755e88f27b3Smrg } 1756e88f27b3Smrg 1757e88f27b3Smrg r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 1758e88f27b3Smrg if (r) { 1759e88f27b3Smrg return r; 1760e88f27b3Smrg } 1761e88f27b3Smrg 1762e88f27b3Smrg surf->stencil_offset = 0; 1763e88f27b3Smrg surf->bo_alignment = 0; 1764e88f27b3Smrg 1765e88f27b3Smrg /* check tiling mode */ 1766e88f27b3Smrg switch (mode) { 1767e88f27b3Smrg case RADEON_SURF_MODE_LINEAR: 1768e88f27b3Smrg r = r6_surface_init_linear(surf_man, surf, 0, 0); 1769e88f27b3Smrg break; 1770e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 1771e88f27b3Smrg r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); 1772e88f27b3Smrg break; 1773e88f27b3Smrg case RADEON_SURF_MODE_1D: 1774e88f27b3Smrg r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 1775e88f27b3Smrg break; 1776e88f27b3Smrg case RADEON_SURF_MODE_2D: 1777e88f27b3Smrg r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 1778e88f27b3Smrg break; 1779e88f27b3Smrg default: 1780e88f27b3Smrg return -EINVAL; 1781e88f27b3Smrg } 1782e88f27b3Smrg return r; 1783e88f27b3Smrg} 1784e88f27b3Smrg 1785e88f27b3Smrg/* 1786e88f27b3Smrg * depending on surface 1787e88f27b3Smrg */ 1788e88f27b3Smrgstatic int si_surface_best(struct radeon_surface_manager *surf_man, 1789e88f27b3Smrg struct radeon_surface *surf) 1790e88f27b3Smrg{ 1791e88f27b3Smrg unsigned mode, tile_mode, stencil_tile_mode; 1792e88f27b3Smrg 1793e88f27b3Smrg /* tiling mode */ 1794e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 1795e88f27b3Smrg 1796e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && 1797e88f27b3Smrg !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { 1798e88f27b3Smrg /* depth/stencil force 1d tiling for old mesa */ 1799e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1800e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1801e88f27b3Smrg } 1802e88f27b3Smrg 1803e88f27b3Smrg return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 1804e88f27b3Smrg} 1805e88f27b3Smrg 1806e88f27b3Smrg 1807e88f27b3Smrg/* =========================================================================== 1808e88f27b3Smrg * Sea Islands family 1809e88f27b3Smrg */ 1810e88f27b3Smrg#define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) 1811e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P2 0 1812e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 1813e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 1814e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 1815e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 1816e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 1817e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 1818e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 1819e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 1820e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 1821e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 1822e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 1823e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16 1824e88f27b3Smrg#define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17 1825e88f27b3Smrg#define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7) 1826e88f27b3Smrg#define CIK__TILE_SPLIT__64B 0 1827e88f27b3Smrg#define CIK__TILE_SPLIT__128B 1 1828e88f27b3Smrg#define CIK__TILE_SPLIT__256B 2 1829e88f27b3Smrg#define CIK__TILE_SPLIT__512B 3 1830e88f27b3Smrg#define CIK__TILE_SPLIT__1024B 4 1831e88f27b3Smrg#define CIK__TILE_SPLIT__2048B 5 1832e88f27b3Smrg#define CIK__TILE_SPLIT__4096B 6 1833e88f27b3Smrg#define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3) 1834e88f27b3Smrg#define CIK__SAMPLE_SPLIT__1 0 1835e88f27b3Smrg#define CIK__SAMPLE_SPLIT__2 1 1836e88f27b3Smrg#define CIK__SAMPLE_SPLIT__4 2 1837e88f27b3Smrg#define CIK__SAMPLE_SPLIT__8 3 1838e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3) 1839e88f27b3Smrg#define CIK__BANK_WIDTH__1 0 1840e88f27b3Smrg#define CIK__BANK_WIDTH__2 1 1841e88f27b3Smrg#define CIK__BANK_WIDTH__4 2 1842e88f27b3Smrg#define CIK__BANK_WIDTH__8 3 1843e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3) 1844e88f27b3Smrg#define CIK__BANK_HEIGHT__1 0 1845e88f27b3Smrg#define CIK__BANK_HEIGHT__2 1 1846e88f27b3Smrg#define CIK__BANK_HEIGHT__4 2 1847e88f27b3Smrg#define CIK__BANK_HEIGHT__8 3 1848e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3) 1849e88f27b3Smrg#define CIK__MACRO_TILE_ASPECT__1 0 1850e88f27b3Smrg#define CIK__MACRO_TILE_ASPECT__2 1 1851e88f27b3Smrg#define CIK__MACRO_TILE_ASPECT__4 2 1852e88f27b3Smrg#define CIK__MACRO_TILE_ASPECT__8 3 1853e88f27b3Smrg#define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3) 1854e88f27b3Smrg#define CIK__NUM_BANKS__2_BANK 0 1855e88f27b3Smrg#define CIK__NUM_BANKS__4_BANK 1 1856e88f27b3Smrg#define CIK__NUM_BANKS__8_BANK 2 1857e88f27b3Smrg#define CIK__NUM_BANKS__16_BANK 3 1858e88f27b3Smrg 1859e88f27b3Smrg 1860e88f27b3Smrgstatic void cik_get_2d_params(struct radeon_surface_manager *surf_man, 1861e88f27b3Smrg unsigned bpe, unsigned nsamples, bool is_color, 1862e88f27b3Smrg unsigned tile_mode, 1863e88f27b3Smrg uint32_t *num_pipes, 1864e88f27b3Smrg uint32_t *tile_split_ptr, 1865e88f27b3Smrg uint32_t *num_banks, 1866e88f27b3Smrg uint32_t *macro_tile_aspect, 1867e88f27b3Smrg uint32_t *bank_w, 1868e88f27b3Smrg uint32_t *bank_h) 1869e88f27b3Smrg{ 1870e88f27b3Smrg uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; 1871e88f27b3Smrg unsigned tileb_1x, tileb; 1872e88f27b3Smrg unsigned gb_macrotile_mode; 1873e88f27b3Smrg unsigned macrotile_index; 1874e88f27b3Smrg unsigned tile_split, sample_split; 1875e88f27b3Smrg 1876e88f27b3Smrg if (num_pipes) { 1877e88f27b3Smrg switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) { 1878e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P2: 1879e88f27b3Smrg default: 1880e88f27b3Smrg *num_pipes = 2; 1881e88f27b3Smrg break; 1882e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16: 1883e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16: 1884e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32: 1885e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32: 1886e88f27b3Smrg *num_pipes = 4; 1887e88f27b3Smrg break; 1888e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: 1889e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: 1890e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: 1891e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: 1892e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: 1893e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: 1894e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: 1895e88f27b3Smrg *num_pipes = 8; 1896e88f27b3Smrg break; 1897e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16: 1898e88f27b3Smrg case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16: 1899e88f27b3Smrg *num_pipes = 16; 1900e88f27b3Smrg break; 1901e88f27b3Smrg } 1902e88f27b3Smrg } 1903e88f27b3Smrg switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) { 1904e88f27b3Smrg default: 1905e88f27b3Smrg case CIK__TILE_SPLIT__64B: 1906e88f27b3Smrg tile_split = 64; 1907e88f27b3Smrg break; 1908e88f27b3Smrg case CIK__TILE_SPLIT__128B: 1909e88f27b3Smrg tile_split = 128; 1910e88f27b3Smrg break; 1911e88f27b3Smrg case CIK__TILE_SPLIT__256B: 1912e88f27b3Smrg tile_split = 256; 1913e88f27b3Smrg break; 1914e88f27b3Smrg case CIK__TILE_SPLIT__512B: 1915e88f27b3Smrg tile_split = 512; 1916e88f27b3Smrg break; 1917e88f27b3Smrg case CIK__TILE_SPLIT__1024B: 1918e88f27b3Smrg tile_split = 1024; 1919e88f27b3Smrg break; 1920e88f27b3Smrg case CIK__TILE_SPLIT__2048B: 1921e88f27b3Smrg tile_split = 2048; 1922e88f27b3Smrg break; 1923e88f27b3Smrg case CIK__TILE_SPLIT__4096B: 1924e88f27b3Smrg tile_split = 4096; 1925e88f27b3Smrg break; 1926e88f27b3Smrg } 1927e88f27b3Smrg switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) { 1928e88f27b3Smrg default: 1929e88f27b3Smrg case CIK__SAMPLE_SPLIT__1: 1930e88f27b3Smrg sample_split = 1; 1931e88f27b3Smrg break; 1932e88f27b3Smrg case CIK__SAMPLE_SPLIT__2: 1933a884aba1Smrg sample_split = 2; 1934e88f27b3Smrg break; 1935e88f27b3Smrg case CIK__SAMPLE_SPLIT__4: 1936e88f27b3Smrg sample_split = 4; 1937e88f27b3Smrg break; 1938e88f27b3Smrg case CIK__SAMPLE_SPLIT__8: 1939e88f27b3Smrg sample_split = 8; 1940e88f27b3Smrg break; 1941e88f27b3Smrg } 1942e88f27b3Smrg 1943e88f27b3Smrg /* Adjust the tile split. */ 1944e88f27b3Smrg tileb_1x = 8 * 8 * bpe; 1945e88f27b3Smrg if (is_color) { 1946e88f27b3Smrg tile_split = MAX2(256, sample_split * tileb_1x); 1947e88f27b3Smrg } 1948e88f27b3Smrg tile_split = MIN2(surf_man->hw_info.row_size, tile_split); 1949e88f27b3Smrg 1950e88f27b3Smrg /* Determine the macrotile index. */ 1951e88f27b3Smrg tileb = MIN2(tile_split, nsamples * tileb_1x); 1952e88f27b3Smrg 1953e88f27b3Smrg for (macrotile_index = 0; tileb > 64; macrotile_index++) { 1954e88f27b3Smrg tileb >>= 1; 1955e88f27b3Smrg } 1956e88f27b3Smrg gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index]; 1957e88f27b3Smrg 1958e88f27b3Smrg if (tile_split_ptr) { 1959e88f27b3Smrg *tile_split_ptr = tile_split; 1960e88f27b3Smrg } 1961e88f27b3Smrg if (num_banks) { 1962e88f27b3Smrg switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) { 1963e88f27b3Smrg default: 1964e88f27b3Smrg case CIK__NUM_BANKS__2_BANK: 1965e88f27b3Smrg *num_banks = 2; 1966e88f27b3Smrg break; 1967e88f27b3Smrg case CIK__NUM_BANKS__4_BANK: 1968e88f27b3Smrg *num_banks = 4; 1969e88f27b3Smrg break; 1970e88f27b3Smrg case CIK__NUM_BANKS__8_BANK: 1971e88f27b3Smrg *num_banks = 8; 1972e88f27b3Smrg break; 1973e88f27b3Smrg case CIK__NUM_BANKS__16_BANK: 1974e88f27b3Smrg *num_banks = 16; 1975e88f27b3Smrg break; 1976e88f27b3Smrg } 1977e88f27b3Smrg } 1978e88f27b3Smrg if (macro_tile_aspect) { 1979e88f27b3Smrg switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) { 1980e88f27b3Smrg default: 1981e88f27b3Smrg case CIK__MACRO_TILE_ASPECT__1: 1982e88f27b3Smrg *macro_tile_aspect = 1; 1983e88f27b3Smrg break; 1984e88f27b3Smrg case CIK__MACRO_TILE_ASPECT__2: 1985e88f27b3Smrg *macro_tile_aspect = 2; 1986e88f27b3Smrg break; 1987e88f27b3Smrg case CIK__MACRO_TILE_ASPECT__4: 1988e88f27b3Smrg *macro_tile_aspect = 4; 1989e88f27b3Smrg break; 1990e88f27b3Smrg case CIK__MACRO_TILE_ASPECT__8: 1991e88f27b3Smrg *macro_tile_aspect = 8; 1992e88f27b3Smrg break; 1993e88f27b3Smrg } 1994e88f27b3Smrg } 1995e88f27b3Smrg if (bank_w) { 1996e88f27b3Smrg switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) { 1997e88f27b3Smrg default: 1998e88f27b3Smrg case CIK__BANK_WIDTH__1: 1999e88f27b3Smrg *bank_w = 1; 2000e88f27b3Smrg break; 2001e88f27b3Smrg case CIK__BANK_WIDTH__2: 2002e88f27b3Smrg *bank_w = 2; 2003e88f27b3Smrg break; 2004e88f27b3Smrg case CIK__BANK_WIDTH__4: 2005e88f27b3Smrg *bank_w = 4; 2006e88f27b3Smrg break; 2007e88f27b3Smrg case CIK__BANK_WIDTH__8: 2008e88f27b3Smrg *bank_w = 8; 2009e88f27b3Smrg break; 2010e88f27b3Smrg } 2011e88f27b3Smrg } 2012e88f27b3Smrg if (bank_h) { 2013e88f27b3Smrg switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) { 2014e88f27b3Smrg default: 2015e88f27b3Smrg case CIK__BANK_HEIGHT__1: 2016e88f27b3Smrg *bank_h = 1; 2017e88f27b3Smrg break; 2018e88f27b3Smrg case CIK__BANK_HEIGHT__2: 2019e88f27b3Smrg *bank_h = 2; 2020e88f27b3Smrg break; 2021e88f27b3Smrg case CIK__BANK_HEIGHT__4: 2022e88f27b3Smrg *bank_h = 4; 2023e88f27b3Smrg break; 2024e88f27b3Smrg case CIK__BANK_HEIGHT__8: 2025e88f27b3Smrg *bank_h = 8; 2026e88f27b3Smrg break; 2027e88f27b3Smrg } 2028e88f27b3Smrg } 2029e88f27b3Smrg} 2030e88f27b3Smrg 2031e88f27b3Smrgstatic int cik_init_hw_info(struct radeon_surface_manager *surf_man) 2032e88f27b3Smrg{ 2033e88f27b3Smrg uint32_t tiling_config; 2034e88f27b3Smrg drmVersionPtr version; 2035e88f27b3Smrg int r; 2036e88f27b3Smrg 2037e88f27b3Smrg r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, 2038e88f27b3Smrg &tiling_config); 2039e88f27b3Smrg if (r) { 2040e88f27b3Smrg return r; 2041e88f27b3Smrg } 2042e88f27b3Smrg 2043e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 2044e88f27b3Smrg version = drmGetVersion(surf_man->fd); 2045e88f27b3Smrg if (version && version->version_minor >= 35) { 2046e88f27b3Smrg if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) && 2047e88f27b3Smrg !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) { 2048e88f27b3Smrg surf_man->hw_info.allow_2d = 1; 2049e88f27b3Smrg } 2050e88f27b3Smrg } 2051e88f27b3Smrg drmFreeVersion(version); 2052e88f27b3Smrg 2053e88f27b3Smrg switch (tiling_config & 0xf) { 2054e88f27b3Smrg case 0: 2055e88f27b3Smrg surf_man->hw_info.num_pipes = 1; 2056e88f27b3Smrg break; 2057e88f27b3Smrg case 1: 2058e88f27b3Smrg surf_man->hw_info.num_pipes = 2; 2059e88f27b3Smrg break; 2060e88f27b3Smrg case 2: 2061e88f27b3Smrg surf_man->hw_info.num_pipes = 4; 2062e88f27b3Smrg break; 2063e88f27b3Smrg case 3: 2064e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 2065e88f27b3Smrg break; 2066e88f27b3Smrg default: 2067e88f27b3Smrg surf_man->hw_info.num_pipes = 8; 2068e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 2069e88f27b3Smrg break; 2070e88f27b3Smrg } 2071e88f27b3Smrg 2072e88f27b3Smrg switch ((tiling_config & 0xf0) >> 4) { 2073e88f27b3Smrg case 0: 2074e88f27b3Smrg surf_man->hw_info.num_banks = 4; 2075e88f27b3Smrg break; 2076e88f27b3Smrg case 1: 2077e88f27b3Smrg surf_man->hw_info.num_banks = 8; 2078e88f27b3Smrg break; 2079e88f27b3Smrg case 2: 2080e88f27b3Smrg surf_man->hw_info.num_banks = 16; 2081e88f27b3Smrg break; 2082e88f27b3Smrg default: 2083e88f27b3Smrg surf_man->hw_info.num_banks = 8; 2084e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 2085e88f27b3Smrg break; 2086e88f27b3Smrg } 2087e88f27b3Smrg 2088e88f27b3Smrg switch ((tiling_config & 0xf00) >> 8) { 2089e88f27b3Smrg case 0: 2090e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 2091e88f27b3Smrg break; 2092e88f27b3Smrg case 1: 2093e88f27b3Smrg surf_man->hw_info.group_bytes = 512; 2094e88f27b3Smrg break; 2095e88f27b3Smrg default: 2096e88f27b3Smrg surf_man->hw_info.group_bytes = 256; 2097e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 2098e88f27b3Smrg break; 2099e88f27b3Smrg } 2100e88f27b3Smrg 2101e88f27b3Smrg switch ((tiling_config & 0xf000) >> 12) { 2102e88f27b3Smrg case 0: 2103e88f27b3Smrg surf_man->hw_info.row_size = 1024; 2104e88f27b3Smrg break; 2105e88f27b3Smrg case 1: 2106e88f27b3Smrg surf_man->hw_info.row_size = 2048; 2107e88f27b3Smrg break; 2108e88f27b3Smrg case 2: 2109e88f27b3Smrg surf_man->hw_info.row_size = 4096; 2110e88f27b3Smrg break; 2111e88f27b3Smrg default: 2112e88f27b3Smrg surf_man->hw_info.row_size = 4096; 2113e88f27b3Smrg surf_man->hw_info.allow_2d = 0; 2114e88f27b3Smrg break; 2115e88f27b3Smrg } 2116e88f27b3Smrg return 0; 2117e88f27b3Smrg} 2118e88f27b3Smrg 2119e88f27b3Smrgstatic int cik_surface_sanity(struct radeon_surface_manager *surf_man, 2120e88f27b3Smrg struct radeon_surface *surf, 2121e88f27b3Smrg unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode) 2122e88f27b3Smrg{ 2123e88f27b3Smrg /* check surface dimension */ 2124e88f27b3Smrg if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { 2125e88f27b3Smrg return -EINVAL; 2126e88f27b3Smrg } 2127e88f27b3Smrg 2128e88f27b3Smrg /* check mipmap last_level */ 2129e88f27b3Smrg if (surf->last_level > 15) { 2130e88f27b3Smrg return -EINVAL; 2131e88f27b3Smrg } 2132e88f27b3Smrg 2133e88f27b3Smrg /* force 1d on kernel that can't do 2d */ 2134e88f27b3Smrg if (mode > RADEON_SURF_MODE_1D && 2135e88f27b3Smrg (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) { 2136e88f27b3Smrg if (surf->nsamples > 1) { 2137e88f27b3Smrg fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__); 2138e88f27b3Smrg return -EFAULT; 2139e88f27b3Smrg } 2140e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 2141e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2142e88f27b3Smrg surf->flags |= RADEON_SURF_SET(mode, MODE); 2143e88f27b3Smrg } 2144e88f27b3Smrg 2145e88f27b3Smrg if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) { 2146e88f27b3Smrg return -EINVAL; 2147e88f27b3Smrg } 2148e88f27b3Smrg 2149e88f27b3Smrg if (!surf->tile_split) { 2150e88f27b3Smrg /* default value */ 2151e88f27b3Smrg surf->mtilea = 1; 2152e88f27b3Smrg surf->bankw = 1; 2153a884aba1Smrg surf->bankh = 1; 2154e88f27b3Smrg surf->tile_split = 64; 2155e88f27b3Smrg surf->stencil_tile_split = 64; 2156e88f27b3Smrg } 2157e88f27b3Smrg 2158e88f27b3Smrg switch (mode) { 2159e88f27b3Smrg case RADEON_SURF_MODE_2D: { 2160e88f27b3Smrg if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) { 2161e88f27b3Smrg switch (surf->nsamples) { 2162e88f27b3Smrg case 1: 2163e88f27b3Smrg *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64; 2164e88f27b3Smrg break; 2165e88f27b3Smrg case 2: 2166e88f27b3Smrg case 4: 2167e88f27b3Smrg *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128; 2168e88f27b3Smrg break; 2169e88f27b3Smrg case 8: 2170e88f27b3Smrg *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256; 2171e88f27b3Smrg break; 2172e88f27b3Smrg default: 2173e88f27b3Smrg return -EINVAL; 2174e88f27b3Smrg } 2175e88f27b3Smrg 2176e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 2177e88f27b3Smrg *stencil_tile_mode = *tile_mode; 2178e88f27b3Smrg 2179e88f27b3Smrg cik_get_2d_params(surf_man, 1, surf->nsamples, false, 2180e88f27b3Smrg *stencil_tile_mode, NULL, 2181e88f27b3Smrg &surf->stencil_tile_split, 2182e88f27b3Smrg NULL, NULL, NULL, NULL); 2183e88f27b3Smrg } 2184e88f27b3Smrg } else if (surf->flags & RADEON_SURF_SCANOUT) { 2185e88f27b3Smrg *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT; 2186e88f27b3Smrg } else { 2187e88f27b3Smrg *tile_mode = CIK_TILE_MODE_COLOR_2D; 2188e88f27b3Smrg } 2189e88f27b3Smrg 2190e88f27b3Smrg /* retrieve tiling mode values */ 2191e88f27b3Smrg cik_get_2d_params(surf_man, surf->bpe, surf->nsamples, 2192e88f27b3Smrg !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode, 2193e88f27b3Smrg NULL, &surf->tile_split, NULL, &surf->mtilea, 2194e88f27b3Smrg &surf->bankw, &surf->bankh); 2195e88f27b3Smrg break; 2196e88f27b3Smrg } 2197e88f27b3Smrg case RADEON_SURF_MODE_1D: 2198e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 2199e88f27b3Smrg *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2200e88f27b3Smrg } 2201e88f27b3Smrg if (surf->flags & RADEON_SURF_ZBUFFER) { 2202e88f27b3Smrg *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2203e88f27b3Smrg } else if (surf->flags & RADEON_SURF_SCANOUT) { 2204e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 2205e88f27b3Smrg } else { 2206e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_1D; 2207e88f27b3Smrg } 2208e88f27b3Smrg break; 2209e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 2210e88f27b3Smrg default: 2211e88f27b3Smrg *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; 2212e88f27b3Smrg } 2213e88f27b3Smrg 2214e88f27b3Smrg return 0; 2215e88f27b3Smrg} 2216e88f27b3Smrg 2217e88f27b3Smrgstatic int cik_surface_init_2d(struct radeon_surface_manager *surf_man, 2218e88f27b3Smrg struct radeon_surface *surf, 2219e88f27b3Smrg struct radeon_surface_level *level, 2220e88f27b3Smrg unsigned bpe, unsigned tile_mode, 2221e88f27b3Smrg unsigned tile_split, 2222e88f27b3Smrg unsigned num_pipes, unsigned num_banks, 2223e88f27b3Smrg uint64_t offset, 2224e88f27b3Smrg unsigned start_level) 2225e88f27b3Smrg{ 2226e88f27b3Smrg uint64_t aligned_offset = offset; 2227e88f27b3Smrg unsigned tilew, tileh, tileb_1x, tileb; 2228e88f27b3Smrg unsigned mtilew, mtileh, mtileb; 2229e88f27b3Smrg unsigned slice_pt; 2230e88f27b3Smrg unsigned i; 2231e88f27b3Smrg 2232e88f27b3Smrg /* compute tile values */ 2233e88f27b3Smrg tilew = 8; 2234e88f27b3Smrg tileh = 8; 2235e88f27b3Smrg tileb_1x = tilew * tileh * bpe; 2236e88f27b3Smrg 2237e88f27b3Smrg tile_split = MIN2(surf_man->hw_info.row_size, tile_split); 2238e88f27b3Smrg 2239e88f27b3Smrg tileb = surf->nsamples * tileb_1x; 2240e88f27b3Smrg 2241e88f27b3Smrg /* slices per tile */ 2242e88f27b3Smrg slice_pt = 1; 2243e88f27b3Smrg if (tileb > tile_split && tile_split) { 2244e88f27b3Smrg slice_pt = tileb / tile_split; 2245e88f27b3Smrg tileb = tileb / slice_pt; 2246e88f27b3Smrg } 2247e88f27b3Smrg 2248e88f27b3Smrg /* macro tile width & height */ 2249e88f27b3Smrg mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; 2250e88f27b3Smrg mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; 2251e88f27b3Smrg 2252e88f27b3Smrg /* macro tile bytes */ 2253e88f27b3Smrg mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; 2254e88f27b3Smrg 2255e88f27b3Smrg if (start_level <= 1) { 2256e88f27b3Smrg unsigned alignment = MAX2(256, mtileb); 2257e88f27b3Smrg surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 2258e88f27b3Smrg 2259e88f27b3Smrg if (aligned_offset) { 2260e88f27b3Smrg aligned_offset = ALIGN(aligned_offset, alignment); 2261e88f27b3Smrg } 2262e88f27b3Smrg } 2263e88f27b3Smrg 2264e88f27b3Smrg /* build mipmap tree */ 2265e88f27b3Smrg for (i = start_level; i <= surf->last_level; i++) { 2266e88f27b3Smrg level[i].mode = RADEON_SURF_MODE_2D; 2267e88f27b3Smrg si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset); 2268e88f27b3Smrg if (level[i].mode == RADEON_SURF_MODE_1D) { 2269e88f27b3Smrg switch (tile_mode) { 2270e88f27b3Smrg case CIK_TILE_MODE_COLOR_2D: 2271e88f27b3Smrg tile_mode = SI_TILE_MODE_COLOR_1D; 2272e88f27b3Smrg break; 2273e88f27b3Smrg case CIK_TILE_MODE_COLOR_2D_SCANOUT: 2274e88f27b3Smrg tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 2275e88f27b3Smrg break; 2276e88f27b3Smrg case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64: 2277e88f27b3Smrg case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128: 2278e88f27b3Smrg case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256: 2279e88f27b3Smrg case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512: 2280e88f27b3Smrg case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE: 2281e88f27b3Smrg tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2282e88f27b3Smrg break; 2283e88f27b3Smrg default: 2284e88f27b3Smrg return -EINVAL; 2285e88f27b3Smrg } 2286e88f27b3Smrg return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); 2287e88f27b3Smrg } 2288e88f27b3Smrg /* level0 and first mipmap need to have alignment */ 2289e88f27b3Smrg aligned_offset = offset = surf->bo_size; 2290e88f27b3Smrg if (i == 0) { 2291e88f27b3Smrg aligned_offset = ALIGN(aligned_offset, surf->bo_alignment); 2292e88f27b3Smrg } 2293e88f27b3Smrg if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 2294e88f27b3Smrg if (surf->level == level) { 2295e88f27b3Smrg surf->tiling_index[i] = tile_mode; 2296e88f27b3Smrg /* it's ok because stencil is done after */ 2297e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 2298e88f27b3Smrg } else { 2299e88f27b3Smrg surf->stencil_tiling_index[i] = tile_mode; 2300e88f27b3Smrg } 2301e88f27b3Smrg } 2302e88f27b3Smrg } 2303e88f27b3Smrg return 0; 2304e88f27b3Smrg} 2305e88f27b3Smrg 2306e88f27b3Smrgstatic int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, 2307e88f27b3Smrg struct radeon_surface *surf, 2308e88f27b3Smrg unsigned tile_mode, unsigned stencil_tile_mode) 2309e88f27b3Smrg{ 2310e88f27b3Smrg int r; 2311e88f27b3Smrg uint32_t num_pipes, num_banks; 2312e88f27b3Smrg 2313e88f27b3Smrg cik_get_2d_params(surf_man, surf->bpe, surf->nsamples, 2314e88f27b3Smrg !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode, 2315e88f27b3Smrg &num_pipes, NULL, &num_banks, NULL, NULL, NULL); 2316e88f27b3Smrg 2317e88f27b3Smrg r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, 2318e88f27b3Smrg surf->tile_split, num_pipes, num_banks, 0, 0); 2319e88f27b3Smrg if (r) { 2320e88f27b3Smrg return r; 2321e88f27b3Smrg } 2322e88f27b3Smrg 2323e88f27b3Smrg if (surf->flags & RADEON_SURF_SBUFFER) { 2324e88f27b3Smrg r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, 2325e88f27b3Smrg surf->stencil_tile_split, num_pipes, num_banks, 2326e88f27b3Smrg surf->bo_size, 0); 2327e88f27b3Smrg surf->stencil_offset = surf->stencil_level[0].offset; 2328e88f27b3Smrg } 2329e88f27b3Smrg return r; 2330e88f27b3Smrg} 2331e88f27b3Smrg 2332e88f27b3Smrgstatic int cik_surface_init(struct radeon_surface_manager *surf_man, 2333e88f27b3Smrg struct radeon_surface *surf) 2334e88f27b3Smrg{ 2335e88f27b3Smrg unsigned mode, tile_mode, stencil_tile_mode; 2336e88f27b3Smrg int r; 2337e88f27b3Smrg 2338e88f27b3Smrg /* MSAA surfaces support the 2D mode only. */ 2339e88f27b3Smrg if (surf->nsamples > 1) { 2340e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2341e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 2342e88f27b3Smrg } 2343e88f27b3Smrg 2344e88f27b3Smrg /* tiling mode */ 2345e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 2346e88f27b3Smrg 2347e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 2348e88f27b3Smrg /* zbuffer only support 1D or 2D tiled surface */ 2349e88f27b3Smrg switch (mode) { 2350e88f27b3Smrg case RADEON_SURF_MODE_1D: 2351e88f27b3Smrg case RADEON_SURF_MODE_2D: 2352e88f27b3Smrg break; 2353e88f27b3Smrg default: 2354e88f27b3Smrg mode = RADEON_SURF_MODE_1D; 2355e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2356e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 2357e88f27b3Smrg break; 2358e88f27b3Smrg } 2359e88f27b3Smrg } 2360e88f27b3Smrg 2361e88f27b3Smrg r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 2362e88f27b3Smrg if (r) { 2363e88f27b3Smrg return r; 2364e88f27b3Smrg } 2365e88f27b3Smrg 2366e88f27b3Smrg surf->stencil_offset = 0; 2367e88f27b3Smrg surf->bo_alignment = 0; 2368e88f27b3Smrg 2369e88f27b3Smrg /* check tiling mode */ 2370e88f27b3Smrg switch (mode) { 2371e88f27b3Smrg case RADEON_SURF_MODE_LINEAR: 2372e88f27b3Smrg r = r6_surface_init_linear(surf_man, surf, 0, 0); 2373e88f27b3Smrg break; 2374e88f27b3Smrg case RADEON_SURF_MODE_LINEAR_ALIGNED: 2375e88f27b3Smrg r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); 2376e88f27b3Smrg break; 2377e88f27b3Smrg case RADEON_SURF_MODE_1D: 2378e88f27b3Smrg r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 2379e88f27b3Smrg break; 2380e88f27b3Smrg case RADEON_SURF_MODE_2D: 2381e88f27b3Smrg r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 2382e88f27b3Smrg break; 2383e88f27b3Smrg default: 2384e88f27b3Smrg return -EINVAL; 2385e88f27b3Smrg } 2386e88f27b3Smrg return r; 2387e88f27b3Smrg} 2388e88f27b3Smrg 2389e88f27b3Smrg/* 2390e88f27b3Smrg * depending on surface 2391e88f27b3Smrg */ 2392e88f27b3Smrgstatic int cik_surface_best(struct radeon_surface_manager *surf_man, 2393e88f27b3Smrg struct radeon_surface *surf) 2394e88f27b3Smrg{ 2395e88f27b3Smrg unsigned mode, tile_mode, stencil_tile_mode; 2396e88f27b3Smrg 2397e88f27b3Smrg /* tiling mode */ 2398e88f27b3Smrg mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 2399e88f27b3Smrg 2400e88f27b3Smrg if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && 2401e88f27b3Smrg !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { 2402e88f27b3Smrg /* depth/stencil force 1d tiling for old mesa */ 2403e88f27b3Smrg surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2404e88f27b3Smrg surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 2405e88f27b3Smrg } 2406e88f27b3Smrg 2407e88f27b3Smrg return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 2408e88f27b3Smrg} 2409e88f27b3Smrg 2410e88f27b3Smrg 2411e88f27b3Smrg/* =========================================================================== 2412e88f27b3Smrg * public API 2413e88f27b3Smrg */ 2414424e9256Smrgstruct radeon_surface_manager * 2415a884aba1Smrgradeon_surface_manager_new(int fd) 2416e88f27b3Smrg{ 2417e88f27b3Smrg struct radeon_surface_manager *surf_man; 2418e88f27b3Smrg 2419e88f27b3Smrg surf_man = calloc(1, sizeof(struct radeon_surface_manager)); 2420e88f27b3Smrg if (surf_man == NULL) { 2421e88f27b3Smrg return NULL; 2422e88f27b3Smrg } 2423e88f27b3Smrg surf_man->fd = fd; 2424e88f27b3Smrg if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) { 2425e88f27b3Smrg goto out_err; 2426e88f27b3Smrg } 2427e88f27b3Smrg if (radeon_get_family(surf_man)) { 2428e88f27b3Smrg goto out_err; 2429e88f27b3Smrg } 2430e88f27b3Smrg 2431e88f27b3Smrg if (surf_man->family <= CHIP_RV740) { 2432e88f27b3Smrg if (r6_init_hw_info(surf_man)) { 2433e88f27b3Smrg goto out_err; 2434e88f27b3Smrg } 2435e88f27b3Smrg surf_man->surface_init = &r6_surface_init; 2436e88f27b3Smrg surf_man->surface_best = &r6_surface_best; 2437e88f27b3Smrg } else if (surf_man->family <= CHIP_ARUBA) { 2438e88f27b3Smrg if (eg_init_hw_info(surf_man)) { 2439e88f27b3Smrg goto out_err; 2440e88f27b3Smrg } 2441e88f27b3Smrg surf_man->surface_init = &eg_surface_init; 2442e88f27b3Smrg surf_man->surface_best = &eg_surface_best; 2443e88f27b3Smrg } else if (surf_man->family < CHIP_BONAIRE) { 2444e88f27b3Smrg if (si_init_hw_info(surf_man)) { 2445e88f27b3Smrg goto out_err; 2446e88f27b3Smrg } 2447e88f27b3Smrg surf_man->surface_init = &si_surface_init; 2448e88f27b3Smrg surf_man->surface_best = &si_surface_best; 2449e88f27b3Smrg } else { 2450e88f27b3Smrg if (cik_init_hw_info(surf_man)) { 2451e88f27b3Smrg goto out_err; 2452e88f27b3Smrg } 2453e88f27b3Smrg surf_man->surface_init = &cik_surface_init; 2454e88f27b3Smrg surf_man->surface_best = &cik_surface_best; 2455e88f27b3Smrg } 2456e88f27b3Smrg 2457e88f27b3Smrg return surf_man; 2458e88f27b3Smrgout_err: 2459e88f27b3Smrg free(surf_man); 2460e88f27b3Smrg return NULL; 2461e88f27b3Smrg} 2462e88f27b3Smrg 2463424e9256Smrgvoid 2464a884aba1Smrgradeon_surface_manager_free(struct radeon_surface_manager *surf_man) 2465e88f27b3Smrg{ 2466e88f27b3Smrg free(surf_man); 2467e88f27b3Smrg} 2468e88f27b3Smrg 2469e88f27b3Smrgstatic int radeon_surface_sanity(struct radeon_surface_manager *surf_man, 2470e88f27b3Smrg struct radeon_surface *surf, 2471e88f27b3Smrg unsigned type, 2472e88f27b3Smrg unsigned mode) 2473e88f27b3Smrg{ 2474e88f27b3Smrg if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) { 2475e88f27b3Smrg return -EINVAL; 2476e88f27b3Smrg } 2477e88f27b3Smrg 2478e88f27b3Smrg /* all dimension must be at least 1 ! */ 2479e88f27b3Smrg if (!surf->npix_x || !surf->npix_y || !surf->npix_z) { 2480e88f27b3Smrg return -EINVAL; 2481e88f27b3Smrg } 2482e88f27b3Smrg if (!surf->blk_w || !surf->blk_h || !surf->blk_d) { 2483e88f27b3Smrg return -EINVAL; 2484e88f27b3Smrg } 2485e88f27b3Smrg if (!surf->array_size) { 2486e88f27b3Smrg return -EINVAL; 2487e88f27b3Smrg } 2488e88f27b3Smrg /* array size must be a power of 2 */ 2489e88f27b3Smrg surf->array_size = next_power_of_two(surf->array_size); 2490e88f27b3Smrg 2491e88f27b3Smrg switch (surf->nsamples) { 2492e88f27b3Smrg case 1: 2493e88f27b3Smrg case 2: 2494e88f27b3Smrg case 4: 2495e88f27b3Smrg case 8: 2496e88f27b3Smrg break; 2497e88f27b3Smrg default: 2498e88f27b3Smrg return -EINVAL; 2499e88f27b3Smrg } 2500e88f27b3Smrg /* check type */ 2501e88f27b3Smrg switch (type) { 2502e88f27b3Smrg case RADEON_SURF_TYPE_1D: 2503e88f27b3Smrg if (surf->npix_y > 1) { 2504e88f27b3Smrg return -EINVAL; 2505e88f27b3Smrg } 2506e88f27b3Smrg case RADEON_SURF_TYPE_2D: 2507e88f27b3Smrg if (surf->npix_z > 1) { 2508e88f27b3Smrg return -EINVAL; 2509e88f27b3Smrg } 2510e88f27b3Smrg break; 2511e88f27b3Smrg case RADEON_SURF_TYPE_CUBEMAP: 2512e88f27b3Smrg if (surf->npix_z > 1) { 2513e88f27b3Smrg return -EINVAL; 2514e88f27b3Smrg } 2515e88f27b3Smrg /* deal with cubemap as they were texture array */ 2516e88f27b3Smrg if (surf_man->family >= CHIP_RV770) { 2517e88f27b3Smrg surf->array_size = 8; 2518e88f27b3Smrg } else { 2519e88f27b3Smrg surf->array_size = 6; 2520e88f27b3Smrg } 2521e88f27b3Smrg break; 2522e88f27b3Smrg case RADEON_SURF_TYPE_3D: 2523e88f27b3Smrg break; 2524e88f27b3Smrg case RADEON_SURF_TYPE_1D_ARRAY: 2525e88f27b3Smrg if (surf->npix_y > 1) { 2526e88f27b3Smrg return -EINVAL; 2527e88f27b3Smrg } 2528e88f27b3Smrg case RADEON_SURF_TYPE_2D_ARRAY: 2529e88f27b3Smrg break; 2530e88f27b3Smrg default: 2531e88f27b3Smrg return -EINVAL; 2532e88f27b3Smrg } 2533e88f27b3Smrg return 0; 2534e88f27b3Smrg} 2535e88f27b3Smrg 2536424e9256Smrgint 2537a884aba1Smrgradeon_surface_init(struct radeon_surface_manager *surf_man, 2538a884aba1Smrg struct radeon_surface *surf) 2539e88f27b3Smrg{ 2540e88f27b3Smrg unsigned mode, type; 2541e88f27b3Smrg int r; 2542e88f27b3Smrg 2543e88f27b3Smrg type = RADEON_SURF_GET(surf->flags, TYPE); 2544e88f27b3Smrg mode = RADEON_SURF_GET(surf->flags, MODE); 2545e88f27b3Smrg 2546e88f27b3Smrg r = radeon_surface_sanity(surf_man, surf, type, mode); 2547e88f27b3Smrg if (r) { 2548e88f27b3Smrg return r; 2549e88f27b3Smrg } 2550e88f27b3Smrg return surf_man->surface_init(surf_man, surf); 2551e88f27b3Smrg} 2552e88f27b3Smrg 2553424e9256Smrgint 2554a884aba1Smrgradeon_surface_best(struct radeon_surface_manager *surf_man, 2555a884aba1Smrg struct radeon_surface *surf) 2556e88f27b3Smrg{ 2557e88f27b3Smrg unsigned mode, type; 2558e88f27b3Smrg int r; 2559e88f27b3Smrg 2560e88f27b3Smrg type = RADEON_SURF_GET(surf->flags, TYPE); 2561e88f27b3Smrg mode = RADEON_SURF_GET(surf->flags, MODE); 2562e88f27b3Smrg 2563e88f27b3Smrg r = radeon_surface_sanity(surf_man, surf, type, mode); 2564e88f27b3Smrg if (r) { 2565e88f27b3Smrg return r; 2566e88f27b3Smrg } 2567e88f27b3Smrg return surf_man->surface_best(surf_man, surf); 2568e88f27b3Smrg} 2569