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