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