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