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