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