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 * Jrme Glisse <jglisse (at) 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 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 */ 50 enum 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 90 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man, 91 struct radeon_surface *surf); 92 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man, 93 struct radeon_surface *surf); 94 95 struct 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 109 struct 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 */ 119 static 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 132 static 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 144 static 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 152 static 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 162 static 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 uint64_t 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 = (uint64_t)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 */ 195 static 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 261 static 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 295 static 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 323 static 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 356 static 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 399 static 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 469 static 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 */ 480 static 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 565 static 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 uint64_t 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 = (uint64_t)mtile_ps * mtileb * slice_pt; 602 603 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 604 } 605 606 static 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 647 static 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 700 static 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 783 static 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_macros.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 805 static 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_macros.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 828 static 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 885 static 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 */ 903 static 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 1065 static 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 1192 static 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 1279 static 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 1414 static 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, uint64_t 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((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y, 1457 (uint64_t)slice_align); 1458 1459 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 1460 } 1461 1462 static void si_surf_minify_2d(struct radeon_surface *surf, 1463 struct radeon_surface_level *surflevel, 1464 unsigned bpe, unsigned level, unsigned slice_pt, 1465 uint32_t xalign, uint32_t yalign, uint32_t zalign, 1466 unsigned mtileb, uint64_t offset) 1467 { 1468 unsigned mtile_pr, mtile_ps; 1469 1470 if (level == 0) { 1471 surflevel->npix_x = surf->npix_x; 1472 } else { 1473 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level); 1474 } 1475 surflevel->npix_y = mip_minify(surf->npix_y, level); 1476 surflevel->npix_z = mip_minify(surf->npix_z, level); 1477 1478 if (level == 0 && surf->last_level > 0) { 1479 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w; 1480 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h; 1481 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d; 1482 } else { 1483 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w; 1484 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h; 1485 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d; 1486 } 1487 1488 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D && 1489 !(surf->flags & RADEON_SURF_FMASK)) { 1490 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) { 1491 surflevel->mode = RADEON_SURF_MODE_1D; 1492 return; 1493 } 1494 } 1495 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign); 1496 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign); 1497 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign); 1498 1499 /* macro tile per row */ 1500 mtile_pr = surflevel->nblk_x / xalign; 1501 /* macro tile per slice */ 1502 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign; 1503 surflevel->offset = offset; 1504 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples; 1505 surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt; 1506 1507 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size; 1508 } 1509 1510 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man, 1511 struct radeon_surface *surf, 1512 unsigned tile_mode, 1513 uint64_t offset, unsigned start_level) 1514 { 1515 uint32_t xalign, yalign, zalign, slice_align; 1516 unsigned i; 1517 1518 /* compute alignment */ 1519 if (!start_level) { 1520 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes); 1521 } 1522 xalign = MAX2(8, 64 / surf->bpe); 1523 yalign = 1; 1524 zalign = 1; 1525 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes); 1526 1527 /* build mipmap tree */ 1528 for (i = start_level; i <= surf->last_level; i++) { 1529 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED; 1530 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset); 1531 /* level0 and first mipmap need to have alignment */ 1532 offset = surf->bo_size; 1533 if (i == 0) { 1534 offset = ALIGN(offset, surf->bo_alignment); 1535 } 1536 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1537 surf->tiling_index[i] = tile_mode; 1538 } 1539 } 1540 return 0; 1541 } 1542 1543 static int si_surface_init_1d(struct radeon_surface_manager *surf_man, 1544 struct radeon_surface *surf, 1545 struct radeon_surface_level *level, 1546 unsigned bpe, unsigned tile_mode, 1547 uint64_t offset, unsigned start_level) 1548 { 1549 uint32_t xalign, yalign, zalign, slice_align; 1550 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes); 1551 unsigned i; 1552 1553 /* compute alignment */ 1554 xalign = 8; 1555 yalign = 8; 1556 zalign = 1; 1557 slice_align = surf_man->hw_info.group_bytes; 1558 if (surf->flags & RADEON_SURF_SCANOUT) { 1559 xalign = MAX2((bpe == 1) ? 64 : 32, xalign); 1560 } 1561 1562 if (start_level <= 1) { 1563 surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 1564 1565 if (offset) { 1566 offset = ALIGN(offset, alignment); 1567 } 1568 } 1569 1570 /* build mipmap tree */ 1571 for (i = start_level; i <= surf->last_level; i++) { 1572 level[i].mode = RADEON_SURF_MODE_1D; 1573 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset); 1574 /* level0 and first mipmap need to have alignment */ 1575 offset = surf->bo_size; 1576 if (i == 0) { 1577 offset = ALIGN(offset, alignment); 1578 } 1579 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1580 if (surf->level == level) { 1581 surf->tiling_index[i] = tile_mode; 1582 /* it's ok because stencil is done after */ 1583 surf->stencil_tiling_index[i] = tile_mode; 1584 } else { 1585 surf->stencil_tiling_index[i] = tile_mode; 1586 } 1587 } 1588 } 1589 return 0; 1590 } 1591 1592 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man, 1593 struct radeon_surface *surf, 1594 unsigned tile_mode, unsigned stencil_tile_mode) 1595 { 1596 int r; 1597 1598 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0); 1599 if (r) { 1600 return r; 1601 } 1602 1603 if (surf->flags & RADEON_SURF_SBUFFER) { 1604 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0); 1605 surf->stencil_offset = surf->stencil_level[0].offset; 1606 } 1607 return r; 1608 } 1609 1610 static int si_surface_init_2d(struct radeon_surface_manager *surf_man, 1611 struct radeon_surface *surf, 1612 struct radeon_surface_level *level, 1613 unsigned bpe, unsigned tile_mode, 1614 unsigned num_pipes, unsigned num_banks, 1615 unsigned tile_split, 1616 uint64_t offset, 1617 unsigned start_level) 1618 { 1619 uint64_t aligned_offset = offset; 1620 unsigned tilew, tileh, tileb; 1621 unsigned mtilew, mtileh, mtileb; 1622 unsigned slice_pt; 1623 unsigned i; 1624 1625 /* compute tile values */ 1626 tilew = 8; 1627 tileh = 8; 1628 tileb = tilew * tileh * bpe * surf->nsamples; 1629 /* slices per tile */ 1630 slice_pt = 1; 1631 if (tileb > tile_split && tile_split) { 1632 slice_pt = tileb / tile_split; 1633 } 1634 tileb = tileb / slice_pt; 1635 1636 /* macro tile width & height */ 1637 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; 1638 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; 1639 1640 /* macro tile bytes */ 1641 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; 1642 1643 if (start_level <= 1) { 1644 unsigned alignment = MAX2(256, mtileb); 1645 surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 1646 1647 if (aligned_offset) { 1648 aligned_offset = ALIGN(aligned_offset, alignment); 1649 } 1650 } 1651 1652 /* build mipmap tree */ 1653 for (i = start_level; i <= surf->last_level; i++) { 1654 level[i].mode = RADEON_SURF_MODE_2D; 1655 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset); 1656 if (level[i].mode == RADEON_SURF_MODE_1D) { 1657 switch (tile_mode) { 1658 case SI_TILE_MODE_COLOR_2D_8BPP: 1659 case SI_TILE_MODE_COLOR_2D_16BPP: 1660 case SI_TILE_MODE_COLOR_2D_32BPP: 1661 case SI_TILE_MODE_COLOR_2D_64BPP: 1662 tile_mode = SI_TILE_MODE_COLOR_1D; 1663 break; 1664 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP: 1665 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP: 1666 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 1667 break; 1668 case SI_TILE_MODE_DEPTH_STENCIL_2D: 1669 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D; 1670 break; 1671 default: 1672 return -EINVAL; 1673 } 1674 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); 1675 } 1676 /* level0 and first mipmap need to have alignment */ 1677 aligned_offset = offset = surf->bo_size; 1678 if (i == 0) { 1679 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment); 1680 } 1681 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 1682 if (surf->level == level) { 1683 surf->tiling_index[i] = tile_mode; 1684 /* it's ok because stencil is done after */ 1685 surf->stencil_tiling_index[i] = tile_mode; 1686 } else { 1687 surf->stencil_tiling_index[i] = tile_mode; 1688 } 1689 } 1690 } 1691 return 0; 1692 } 1693 1694 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, 1695 struct radeon_surface *surf, 1696 unsigned tile_mode, unsigned stencil_tile_mode) 1697 { 1698 unsigned num_pipes, num_banks; 1699 uint32_t gb_tile_mode; 1700 int r; 1701 1702 /* retrieve tiling mode value */ 1703 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; 1704 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL); 1705 1706 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0); 1707 if (r) { 1708 return r; 1709 } 1710 1711 if (surf->flags & RADEON_SURF_SBUFFER) { 1712 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); 1713 surf->stencil_offset = surf->stencil_level[0].offset; 1714 } 1715 return r; 1716 } 1717 1718 static int si_surface_init(struct radeon_surface_manager *surf_man, 1719 struct radeon_surface *surf) 1720 { 1721 unsigned mode, tile_mode, stencil_tile_mode; 1722 int r; 1723 1724 /* MSAA surfaces support the 2D mode only. */ 1725 if (surf->nsamples > 1) { 1726 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1727 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 1728 } 1729 1730 /* tiling mode */ 1731 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 1732 1733 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 1734 /* zbuffer only support 1D or 2D tiled surface */ 1735 switch (mode) { 1736 case RADEON_SURF_MODE_1D: 1737 case RADEON_SURF_MODE_2D: 1738 break; 1739 default: 1740 mode = RADEON_SURF_MODE_1D; 1741 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1742 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1743 break; 1744 } 1745 } 1746 1747 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 1748 if (r) { 1749 return r; 1750 } 1751 1752 surf->stencil_offset = 0; 1753 surf->bo_alignment = 0; 1754 1755 /* check tiling mode */ 1756 switch (mode) { 1757 case RADEON_SURF_MODE_LINEAR: 1758 r = r6_surface_init_linear(surf_man, surf, 0, 0); 1759 break; 1760 case RADEON_SURF_MODE_LINEAR_ALIGNED: 1761 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); 1762 break; 1763 case RADEON_SURF_MODE_1D: 1764 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 1765 break; 1766 case RADEON_SURF_MODE_2D: 1767 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 1768 break; 1769 default: 1770 return -EINVAL; 1771 } 1772 return r; 1773 } 1774 1775 /* 1776 * depending on surface 1777 */ 1778 static int si_surface_best(struct radeon_surface_manager *surf_man, 1779 struct radeon_surface *surf) 1780 { 1781 unsigned mode, tile_mode, stencil_tile_mode; 1782 1783 /* tiling mode */ 1784 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 1785 1786 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && 1787 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { 1788 /* depth/stencil force 1d tiling for old mesa */ 1789 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 1790 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 1791 } 1792 1793 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 1794 } 1795 1796 1797 /* =========================================================================== 1798 * Sea Islands family 1799 */ 1800 #define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f) 1801 #define CIK__PIPE_CONFIG__ADDR_SURF_P2 0 1802 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4 1803 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5 1804 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6 1805 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7 1806 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8 1807 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9 1808 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10 1809 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11 1810 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12 1811 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13 1812 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14 1813 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16 1814 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17 1815 #define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7) 1816 #define CIK__TILE_SPLIT__64B 0 1817 #define CIK__TILE_SPLIT__128B 1 1818 #define CIK__TILE_SPLIT__256B 2 1819 #define CIK__TILE_SPLIT__512B 3 1820 #define CIK__TILE_SPLIT__1024B 4 1821 #define CIK__TILE_SPLIT__2048B 5 1822 #define CIK__TILE_SPLIT__4096B 6 1823 #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3) 1824 #define CIK__SAMPLE_SPLIT__1 0 1825 #define CIK__SAMPLE_SPLIT__2 1 1826 #define CIK__SAMPLE_SPLIT__4 2 1827 #define CIK__SAMPLE_SPLIT__8 3 1828 #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3) 1829 #define CIK__BANK_WIDTH__1 0 1830 #define CIK__BANK_WIDTH__2 1 1831 #define CIK__BANK_WIDTH__4 2 1832 #define CIK__BANK_WIDTH__8 3 1833 #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3) 1834 #define CIK__BANK_HEIGHT__1 0 1835 #define CIK__BANK_HEIGHT__2 1 1836 #define CIK__BANK_HEIGHT__4 2 1837 #define CIK__BANK_HEIGHT__8 3 1838 #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3) 1839 #define CIK__MACRO_TILE_ASPECT__1 0 1840 #define CIK__MACRO_TILE_ASPECT__2 1 1841 #define CIK__MACRO_TILE_ASPECT__4 2 1842 #define CIK__MACRO_TILE_ASPECT__8 3 1843 #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3) 1844 #define CIK__NUM_BANKS__2_BANK 0 1845 #define CIK__NUM_BANKS__4_BANK 1 1846 #define CIK__NUM_BANKS__8_BANK 2 1847 #define CIK__NUM_BANKS__16_BANK 3 1848 1849 1850 static void cik_get_2d_params(struct radeon_surface_manager *surf_man, 1851 unsigned bpe, unsigned nsamples, bool is_color, 1852 unsigned tile_mode, 1853 uint32_t *num_pipes, 1854 uint32_t *tile_split_ptr, 1855 uint32_t *num_banks, 1856 uint32_t *macro_tile_aspect, 1857 uint32_t *bank_w, 1858 uint32_t *bank_h) 1859 { 1860 uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode]; 1861 unsigned tileb_1x, tileb; 1862 unsigned gb_macrotile_mode; 1863 unsigned macrotile_index; 1864 unsigned tile_split, sample_split; 1865 1866 if (num_pipes) { 1867 switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) { 1868 case CIK__PIPE_CONFIG__ADDR_SURF_P2: 1869 default: 1870 *num_pipes = 2; 1871 break; 1872 case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16: 1873 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16: 1874 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32: 1875 case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32: 1876 *num_pipes = 4; 1877 break; 1878 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16: 1879 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16: 1880 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16: 1881 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16: 1882 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16: 1883 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32: 1884 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32: 1885 *num_pipes = 8; 1886 break; 1887 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16: 1888 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16: 1889 *num_pipes = 16; 1890 break; 1891 } 1892 } 1893 switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) { 1894 default: 1895 case CIK__TILE_SPLIT__64B: 1896 tile_split = 64; 1897 break; 1898 case CIK__TILE_SPLIT__128B: 1899 tile_split = 128; 1900 break; 1901 case CIK__TILE_SPLIT__256B: 1902 tile_split = 256; 1903 break; 1904 case CIK__TILE_SPLIT__512B: 1905 tile_split = 512; 1906 break; 1907 case CIK__TILE_SPLIT__1024B: 1908 tile_split = 1024; 1909 break; 1910 case CIK__TILE_SPLIT__2048B: 1911 tile_split = 2048; 1912 break; 1913 case CIK__TILE_SPLIT__4096B: 1914 tile_split = 4096; 1915 break; 1916 } 1917 switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) { 1918 default: 1919 case CIK__SAMPLE_SPLIT__1: 1920 sample_split = 1; 1921 break; 1922 case CIK__SAMPLE_SPLIT__2: 1923 sample_split = 2; 1924 break; 1925 case CIK__SAMPLE_SPLIT__4: 1926 sample_split = 4; 1927 break; 1928 case CIK__SAMPLE_SPLIT__8: 1929 sample_split = 8; 1930 break; 1931 } 1932 1933 /* Adjust the tile split. */ 1934 tileb_1x = 8 * 8 * bpe; 1935 if (is_color) { 1936 tile_split = MAX2(256, sample_split * tileb_1x); 1937 } 1938 tile_split = MIN2(surf_man->hw_info.row_size, tile_split); 1939 1940 /* Determine the macrotile index. */ 1941 tileb = MIN2(tile_split, nsamples * tileb_1x); 1942 1943 for (macrotile_index = 0; tileb > 64; macrotile_index++) { 1944 tileb >>= 1; 1945 } 1946 gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index]; 1947 1948 if (tile_split_ptr) { 1949 *tile_split_ptr = tile_split; 1950 } 1951 if (num_banks) { 1952 switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) { 1953 default: 1954 case CIK__NUM_BANKS__2_BANK: 1955 *num_banks = 2; 1956 break; 1957 case CIK__NUM_BANKS__4_BANK: 1958 *num_banks = 4; 1959 break; 1960 case CIK__NUM_BANKS__8_BANK: 1961 *num_banks = 8; 1962 break; 1963 case CIK__NUM_BANKS__16_BANK: 1964 *num_banks = 16; 1965 break; 1966 } 1967 } 1968 if (macro_tile_aspect) { 1969 switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) { 1970 default: 1971 case CIK__MACRO_TILE_ASPECT__1: 1972 *macro_tile_aspect = 1; 1973 break; 1974 case CIK__MACRO_TILE_ASPECT__2: 1975 *macro_tile_aspect = 2; 1976 break; 1977 case CIK__MACRO_TILE_ASPECT__4: 1978 *macro_tile_aspect = 4; 1979 break; 1980 case CIK__MACRO_TILE_ASPECT__8: 1981 *macro_tile_aspect = 8; 1982 break; 1983 } 1984 } 1985 if (bank_w) { 1986 switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) { 1987 default: 1988 case CIK__BANK_WIDTH__1: 1989 *bank_w = 1; 1990 break; 1991 case CIK__BANK_WIDTH__2: 1992 *bank_w = 2; 1993 break; 1994 case CIK__BANK_WIDTH__4: 1995 *bank_w = 4; 1996 break; 1997 case CIK__BANK_WIDTH__8: 1998 *bank_w = 8; 1999 break; 2000 } 2001 } 2002 if (bank_h) { 2003 switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) { 2004 default: 2005 case CIK__BANK_HEIGHT__1: 2006 *bank_h = 1; 2007 break; 2008 case CIK__BANK_HEIGHT__2: 2009 *bank_h = 2; 2010 break; 2011 case CIK__BANK_HEIGHT__4: 2012 *bank_h = 4; 2013 break; 2014 case CIK__BANK_HEIGHT__8: 2015 *bank_h = 8; 2016 break; 2017 } 2018 } 2019 } 2020 2021 static int cik_init_hw_info(struct radeon_surface_manager *surf_man) 2022 { 2023 uint32_t tiling_config; 2024 drmVersionPtr version; 2025 int r; 2026 2027 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG, 2028 &tiling_config); 2029 if (r) { 2030 return r; 2031 } 2032 2033 surf_man->hw_info.allow_2d = 0; 2034 version = drmGetVersion(surf_man->fd); 2035 if (version && version->version_minor >= 35) { 2036 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) && 2037 !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) { 2038 surf_man->hw_info.allow_2d = 1; 2039 } 2040 } 2041 drmFreeVersion(version); 2042 2043 switch (tiling_config & 0xf) { 2044 case 0: 2045 surf_man->hw_info.num_pipes = 1; 2046 break; 2047 case 1: 2048 surf_man->hw_info.num_pipes = 2; 2049 break; 2050 case 2: 2051 surf_man->hw_info.num_pipes = 4; 2052 break; 2053 case 3: 2054 surf_man->hw_info.num_pipes = 8; 2055 break; 2056 default: 2057 surf_man->hw_info.num_pipes = 8; 2058 surf_man->hw_info.allow_2d = 0; 2059 break; 2060 } 2061 2062 switch ((tiling_config & 0xf0) >> 4) { 2063 case 0: 2064 surf_man->hw_info.num_banks = 4; 2065 break; 2066 case 1: 2067 surf_man->hw_info.num_banks = 8; 2068 break; 2069 case 2: 2070 surf_man->hw_info.num_banks = 16; 2071 break; 2072 default: 2073 surf_man->hw_info.num_banks = 8; 2074 surf_man->hw_info.allow_2d = 0; 2075 break; 2076 } 2077 2078 switch ((tiling_config & 0xf00) >> 8) { 2079 case 0: 2080 surf_man->hw_info.group_bytes = 256; 2081 break; 2082 case 1: 2083 surf_man->hw_info.group_bytes = 512; 2084 break; 2085 default: 2086 surf_man->hw_info.group_bytes = 256; 2087 surf_man->hw_info.allow_2d = 0; 2088 break; 2089 } 2090 2091 switch ((tiling_config & 0xf000) >> 12) { 2092 case 0: 2093 surf_man->hw_info.row_size = 1024; 2094 break; 2095 case 1: 2096 surf_man->hw_info.row_size = 2048; 2097 break; 2098 case 2: 2099 surf_man->hw_info.row_size = 4096; 2100 break; 2101 default: 2102 surf_man->hw_info.row_size = 4096; 2103 surf_man->hw_info.allow_2d = 0; 2104 break; 2105 } 2106 return 0; 2107 } 2108 2109 static int cik_surface_sanity(struct radeon_surface_manager *surf_man, 2110 struct radeon_surface *surf, 2111 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode) 2112 { 2113 /* check surface dimension */ 2114 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) { 2115 return -EINVAL; 2116 } 2117 2118 /* check mipmap last_level */ 2119 if (surf->last_level > 15) { 2120 return -EINVAL; 2121 } 2122 2123 /* force 1d on kernel that can't do 2d */ 2124 if (mode > RADEON_SURF_MODE_1D && 2125 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) { 2126 if (surf->nsamples > 1) { 2127 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__); 2128 return -EFAULT; 2129 } 2130 mode = RADEON_SURF_MODE_1D; 2131 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2132 surf->flags |= RADEON_SURF_SET(mode, MODE); 2133 } 2134 2135 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) { 2136 return -EINVAL; 2137 } 2138 2139 if (!surf->tile_split) { 2140 /* default value */ 2141 surf->mtilea = 1; 2142 surf->bankw = 1; 2143 surf->bankh = 1; 2144 surf->tile_split = 64; 2145 surf->stencil_tile_split = 64; 2146 } 2147 2148 switch (mode) { 2149 case RADEON_SURF_MODE_2D: { 2150 if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) { 2151 switch (surf->nsamples) { 2152 case 1: 2153 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64; 2154 break; 2155 case 2: 2156 case 4: 2157 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128; 2158 break; 2159 case 8: 2160 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256; 2161 break; 2162 default: 2163 return -EINVAL; 2164 } 2165 2166 if (surf->flags & RADEON_SURF_SBUFFER) { 2167 *stencil_tile_mode = *tile_mode; 2168 2169 cik_get_2d_params(surf_man, 1, surf->nsamples, false, 2170 *stencil_tile_mode, NULL, 2171 &surf->stencil_tile_split, 2172 NULL, NULL, NULL, NULL); 2173 } 2174 } else if (surf->flags & RADEON_SURF_SCANOUT) { 2175 *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT; 2176 } else { 2177 *tile_mode = CIK_TILE_MODE_COLOR_2D; 2178 } 2179 2180 /* retrieve tiling mode values */ 2181 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples, 2182 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode, 2183 NULL, &surf->tile_split, NULL, &surf->mtilea, 2184 &surf->bankw, &surf->bankh); 2185 break; 2186 } 2187 case RADEON_SURF_MODE_1D: 2188 if (surf->flags & RADEON_SURF_SBUFFER) { 2189 *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2190 } 2191 if (surf->flags & RADEON_SURF_ZBUFFER) { 2192 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2193 } else if (surf->flags & RADEON_SURF_SCANOUT) { 2194 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 2195 } else { 2196 *tile_mode = SI_TILE_MODE_COLOR_1D; 2197 } 2198 break; 2199 case RADEON_SURF_MODE_LINEAR_ALIGNED: 2200 default: 2201 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED; 2202 } 2203 2204 return 0; 2205 } 2206 2207 static int cik_surface_init_2d(struct radeon_surface_manager *surf_man, 2208 struct radeon_surface *surf, 2209 struct radeon_surface_level *level, 2210 unsigned bpe, unsigned tile_mode, 2211 unsigned tile_split, 2212 unsigned num_pipes, unsigned num_banks, 2213 uint64_t offset, 2214 unsigned start_level) 2215 { 2216 uint64_t aligned_offset = offset; 2217 unsigned tilew, tileh, tileb_1x, tileb; 2218 unsigned mtilew, mtileh, mtileb; 2219 unsigned slice_pt; 2220 unsigned i; 2221 2222 /* compute tile values */ 2223 tilew = 8; 2224 tileh = 8; 2225 tileb_1x = tilew * tileh * bpe; 2226 2227 tile_split = MIN2(surf_man->hw_info.row_size, tile_split); 2228 2229 tileb = surf->nsamples * tileb_1x; 2230 2231 /* slices per tile */ 2232 slice_pt = 1; 2233 if (tileb > tile_split && tile_split) { 2234 slice_pt = tileb / tile_split; 2235 tileb = tileb / slice_pt; 2236 } 2237 2238 /* macro tile width & height */ 2239 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea; 2240 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea; 2241 2242 /* macro tile bytes */ 2243 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb; 2244 2245 if (start_level <= 1) { 2246 unsigned alignment = MAX2(256, mtileb); 2247 surf->bo_alignment = MAX2(surf->bo_alignment, alignment); 2248 2249 if (aligned_offset) { 2250 aligned_offset = ALIGN(aligned_offset, alignment); 2251 } 2252 } 2253 2254 /* build mipmap tree */ 2255 for (i = start_level; i <= surf->last_level; i++) { 2256 level[i].mode = RADEON_SURF_MODE_2D; 2257 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset); 2258 if (level[i].mode == RADEON_SURF_MODE_1D) { 2259 switch (tile_mode) { 2260 case CIK_TILE_MODE_COLOR_2D: 2261 tile_mode = SI_TILE_MODE_COLOR_1D; 2262 break; 2263 case CIK_TILE_MODE_COLOR_2D_SCANOUT: 2264 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT; 2265 break; 2266 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64: 2267 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128: 2268 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256: 2269 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512: 2270 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE: 2271 tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D; 2272 break; 2273 default: 2274 return -EINVAL; 2275 } 2276 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i); 2277 } 2278 /* level0 and first mipmap need to have alignment */ 2279 aligned_offset = offset = surf->bo_size; 2280 if (i == 0) { 2281 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment); 2282 } 2283 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) { 2284 if (surf->level == level) { 2285 surf->tiling_index[i] = tile_mode; 2286 /* it's ok because stencil is done after */ 2287 surf->stencil_tiling_index[i] = tile_mode; 2288 } else { 2289 surf->stencil_tiling_index[i] = tile_mode; 2290 } 2291 } 2292 } 2293 return 0; 2294 } 2295 2296 static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man, 2297 struct radeon_surface *surf, 2298 unsigned tile_mode, unsigned stencil_tile_mode) 2299 { 2300 int r; 2301 uint32_t num_pipes, num_banks; 2302 2303 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples, 2304 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode, 2305 &num_pipes, NULL, &num_banks, NULL, NULL, NULL); 2306 2307 r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, 2308 surf->tile_split, num_pipes, num_banks, 0, 0); 2309 if (r) { 2310 return r; 2311 } 2312 2313 if (surf->flags & RADEON_SURF_SBUFFER) { 2314 r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, 2315 surf->stencil_tile_split, num_pipes, num_banks, 2316 surf->bo_size, 0); 2317 surf->stencil_offset = surf->stencil_level[0].offset; 2318 } 2319 return r; 2320 } 2321 2322 static int cik_surface_init(struct radeon_surface_manager *surf_man, 2323 struct radeon_surface *surf) 2324 { 2325 unsigned mode, tile_mode, stencil_tile_mode; 2326 int r; 2327 2328 /* MSAA surfaces support the 2D mode only. */ 2329 if (surf->nsamples > 1) { 2330 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2331 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); 2332 } 2333 2334 /* tiling mode */ 2335 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 2336 2337 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) { 2338 /* zbuffer only support 1D or 2D tiled surface */ 2339 switch (mode) { 2340 case RADEON_SURF_MODE_1D: 2341 case RADEON_SURF_MODE_2D: 2342 break; 2343 default: 2344 mode = RADEON_SURF_MODE_1D; 2345 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2346 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 2347 break; 2348 } 2349 } 2350 2351 r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 2352 if (r) { 2353 return r; 2354 } 2355 2356 surf->stencil_offset = 0; 2357 surf->bo_alignment = 0; 2358 2359 /* check tiling mode */ 2360 switch (mode) { 2361 case RADEON_SURF_MODE_LINEAR: 2362 r = r6_surface_init_linear(surf_man, surf, 0, 0); 2363 break; 2364 case RADEON_SURF_MODE_LINEAR_ALIGNED: 2365 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0); 2366 break; 2367 case RADEON_SURF_MODE_1D: 2368 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 2369 break; 2370 case RADEON_SURF_MODE_2D: 2371 r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode); 2372 break; 2373 default: 2374 return -EINVAL; 2375 } 2376 return r; 2377 } 2378 2379 /* 2380 * depending on surface 2381 */ 2382 static int cik_surface_best(struct radeon_surface_manager *surf_man, 2383 struct radeon_surface *surf) 2384 { 2385 unsigned mode, tile_mode, stencil_tile_mode; 2386 2387 /* tiling mode */ 2388 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK; 2389 2390 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) && 2391 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) { 2392 /* depth/stencil force 1d tiling for old mesa */ 2393 surf->flags = RADEON_SURF_CLR(surf->flags, MODE); 2394 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); 2395 } 2396 2397 return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode); 2398 } 2399 2400 2401 /* =========================================================================== 2402 * public API 2403 */ 2404 struct radeon_surface_manager * 2405 radeon_surface_manager_new(int fd) 2406 { 2407 struct radeon_surface_manager *surf_man; 2408 2409 surf_man = calloc(1, sizeof(struct radeon_surface_manager)); 2410 if (surf_man == NULL) { 2411 return NULL; 2412 } 2413 surf_man->fd = fd; 2414 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) { 2415 goto out_err; 2416 } 2417 if (radeon_get_family(surf_man)) { 2418 goto out_err; 2419 } 2420 2421 if (surf_man->family <= CHIP_RV740) { 2422 if (r6_init_hw_info(surf_man)) { 2423 goto out_err; 2424 } 2425 surf_man->surface_init = &r6_surface_init; 2426 surf_man->surface_best = &r6_surface_best; 2427 } else if (surf_man->family <= CHIP_ARUBA) { 2428 if (eg_init_hw_info(surf_man)) { 2429 goto out_err; 2430 } 2431 surf_man->surface_init = &eg_surface_init; 2432 surf_man->surface_best = &eg_surface_best; 2433 } else if (surf_man->family < CHIP_BONAIRE) { 2434 if (si_init_hw_info(surf_man)) { 2435 goto out_err; 2436 } 2437 surf_man->surface_init = &si_surface_init; 2438 surf_man->surface_best = &si_surface_best; 2439 } else { 2440 if (cik_init_hw_info(surf_man)) { 2441 goto out_err; 2442 } 2443 surf_man->surface_init = &cik_surface_init; 2444 surf_man->surface_best = &cik_surface_best; 2445 } 2446 2447 return surf_man; 2448 out_err: 2449 free(surf_man); 2450 return NULL; 2451 } 2452 2453 void 2454 radeon_surface_manager_free(struct radeon_surface_manager *surf_man) 2455 { 2456 free(surf_man); 2457 } 2458 2459 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man, 2460 struct radeon_surface *surf, 2461 unsigned type, 2462 unsigned mode) 2463 { 2464 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) { 2465 return -EINVAL; 2466 } 2467 2468 /* all dimension must be at least 1 ! */ 2469 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) { 2470 return -EINVAL; 2471 } 2472 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) { 2473 return -EINVAL; 2474 } 2475 if (!surf->array_size) { 2476 return -EINVAL; 2477 } 2478 /* array size must be a power of 2 */ 2479 surf->array_size = next_power_of_two(surf->array_size); 2480 2481 switch (surf->nsamples) { 2482 case 1: 2483 case 2: 2484 case 4: 2485 case 8: 2486 break; 2487 default: 2488 return -EINVAL; 2489 } 2490 /* check type */ 2491 switch (type) { 2492 case RADEON_SURF_TYPE_1D: 2493 if (surf->npix_y > 1) { 2494 return -EINVAL; 2495 } 2496 case RADEON_SURF_TYPE_2D: 2497 if (surf->npix_z > 1) { 2498 return -EINVAL; 2499 } 2500 break; 2501 case RADEON_SURF_TYPE_CUBEMAP: 2502 if (surf->npix_z > 1) { 2503 return -EINVAL; 2504 } 2505 /* deal with cubemap as they were texture array */ 2506 if (surf_man->family >= CHIP_RV770) { 2507 surf->array_size = 8; 2508 } else { 2509 surf->array_size = 6; 2510 } 2511 break; 2512 case RADEON_SURF_TYPE_3D: 2513 break; 2514 case RADEON_SURF_TYPE_1D_ARRAY: 2515 if (surf->npix_y > 1) { 2516 return -EINVAL; 2517 } 2518 case RADEON_SURF_TYPE_2D_ARRAY: 2519 break; 2520 default: 2521 return -EINVAL; 2522 } 2523 return 0; 2524 } 2525 2526 int 2527 radeon_surface_init(struct radeon_surface_manager *surf_man, 2528 struct radeon_surface *surf) 2529 { 2530 unsigned mode, type; 2531 int r; 2532 2533 type = RADEON_SURF_GET(surf->flags, TYPE); 2534 mode = RADEON_SURF_GET(surf->flags, MODE); 2535 2536 r = radeon_surface_sanity(surf_man, surf, type, mode); 2537 if (r) { 2538 return r; 2539 } 2540 return surf_man->surface_init(surf_man, surf); 2541 } 2542 2543 int 2544 radeon_surface_best(struct radeon_surface_manager *surf_man, 2545 struct radeon_surface *surf) 2546 { 2547 unsigned mode, type; 2548 int r; 2549 2550 type = RADEON_SURF_GET(surf->flags, TYPE); 2551 mode = RADEON_SURF_GET(surf->flags, MODE); 2552 2553 r = radeon_surface_sanity(surf_man, surf, type, mode); 2554 if (r) { 2555 return r; 2556 } 2557 return surf_man->surface_best(surf_man, surf); 2558 } 2559