1 /* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 */ 26 27 /** 28 *************************************************************************************************** 29 * @file addrlib.cpp 30 * @brief Contains the implementation for the AddrLib base class.. 31 *************************************************************************************************** 32 */ 33 34 #include "addrinterface.h" 35 #include "addrlib.h" 36 #include "addrcommon.h" 37 38 #if defined(__APPLE__) 39 40 UINT_32 div64_32(UINT_64 n, UINT_32 base) 41 { 42 UINT_64 rem = n; 43 UINT_64 b = base; 44 UINT_64 res, d = 1; 45 UINT_32 high = rem >> 32; 46 47 res = 0; 48 if (high >= base) 49 { 50 high /= base; 51 res = (UINT_64) high << 32; 52 rem -= (UINT_64) (high*base) << 32; 53 } 54 55 while ((INT_64)b > 0 && b < rem) 56 { 57 b = b+b; 58 d = d+d; 59 } 60 61 do 62 { 63 if (rem >= b) 64 { 65 rem -= b; 66 res += d; 67 } 68 b >>= 1; 69 d >>= 1; 70 } while (d); 71 72 n = res; 73 return rem; 74 } 75 76 extern "C" 77 UINT_32 __umoddi3(UINT_64 n, UINT_32 base) 78 { 79 return div64_32(n, base); 80 } 81 82 #endif // __APPLE__ 83 84 /////////////////////////////////////////////////////////////////////////////////////////////////// 85 // Static Const Member 86 /////////////////////////////////////////////////////////////////////////////////////////////////// 87 88 const AddrTileModeFlags AddrLib::m_modeFlags[ADDR_TM_COUNT] = 89 {// T L 1 2 3 P Pr B 90 {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_GENERAL 91 {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_ALIGNED 92 {1, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THIN1 93 {4, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THICK 94 {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN1 95 {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN2 96 {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN4 97 {4, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THICK 98 {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN1 99 {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN2 100 {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN4 101 {4, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THICK 102 {1, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THIN1 103 {4, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THICK 104 {1, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THIN1 105 {4, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THICK 106 {8, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_XTHICK 107 {8, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_XTHICK 108 {1, 0, 0, 0, 0, 0, 0, 0}, // ADDR_TM_POWER_SAVE 109 {1, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THIN1 110 {1, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THIN1 111 {1, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THIN1 112 {4, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THICK 113 {4, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THICK 114 {4, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THICK 115 }; 116 117 /////////////////////////////////////////////////////////////////////////////////////////////////// 118 // Constructor/Destructor 119 /////////////////////////////////////////////////////////////////////////////////////////////////// 120 121 /** 122 *************************************************************************************************** 123 * AddrLib::AddrLib 124 * 125 * @brief 126 * Constructor for the AddrLib class 127 * 128 *************************************************************************************************** 129 */ 130 AddrLib::AddrLib() : 131 m_class(BASE_ADDRLIB), 132 m_chipFamily(ADDR_CHIP_FAMILY_IVLD), 133 m_chipRevision(0), 134 m_version(ADDRLIB_VERSION), 135 m_pipes(0), 136 m_banks(0), 137 m_pipeInterleaveBytes(0), 138 m_rowSize(0), 139 m_minPitchAlignPixels(1), 140 m_maxSamples(8), 141 m_pElemLib(NULL) 142 { 143 m_configFlags.value = 0; 144 } 145 146 /** 147 *************************************************************************************************** 148 * AddrLib::AddrLib 149 * 150 * @brief 151 * Constructor for the AddrLib class with hClient as parameter 152 * 153 *************************************************************************************************** 154 */ 155 AddrLib::AddrLib(const AddrClient* pClient) : 156 AddrObject(pClient), 157 m_class(BASE_ADDRLIB), 158 m_chipFamily(ADDR_CHIP_FAMILY_IVLD), 159 m_chipRevision(0), 160 m_version(ADDRLIB_VERSION), 161 m_pipes(0), 162 m_banks(0), 163 m_pipeInterleaveBytes(0), 164 m_rowSize(0), 165 m_minPitchAlignPixels(1), 166 m_maxSamples(8), 167 m_pElemLib(NULL) 168 { 169 m_configFlags.value = 0; 170 } 171 172 /** 173 *************************************************************************************************** 174 * AddrLib::~AddrLib 175 * 176 * @brief 177 * Destructor for the AddrLib class 178 * 179 *************************************************************************************************** 180 */ 181 AddrLib::~AddrLib() 182 { 183 if (m_pElemLib) 184 { 185 delete m_pElemLib; 186 } 187 } 188 189 190 191 /////////////////////////////////////////////////////////////////////////////////////////////////// 192 // Initialization/Helper 193 /////////////////////////////////////////////////////////////////////////////////////////////////// 194 195 /** 196 *************************************************************************************************** 197 * AddrLib::Create 198 * 199 * @brief 200 * Creates and initializes AddrLib object. 201 * 202 * @return 203 * ADDR_E_RETURNCODE 204 *************************************************************************************************** 205 */ 206 ADDR_E_RETURNCODE AddrLib::Create( 207 const ADDR_CREATE_INPUT* pCreateIn, ///< [in] pointer to ADDR_CREATE_INPUT 208 ADDR_CREATE_OUTPUT* pCreateOut) ///< [out] pointer to ADDR_CREATE_OUTPUT 209 { 210 AddrLib* pLib = NULL; 211 ADDR_E_RETURNCODE returnCode = ADDR_OK; 212 213 if (pCreateIn->createFlags.fillSizeFields == TRUE) 214 { 215 if ((pCreateIn->size != sizeof(ADDR_CREATE_INPUT)) || 216 (pCreateOut->size != sizeof(ADDR_CREATE_OUTPUT))) 217 { 218 returnCode = ADDR_PARAMSIZEMISMATCH; 219 } 220 } 221 222 if ((returnCode == ADDR_OK) && 223 (pCreateIn->callbacks.allocSysMem != NULL) && 224 (pCreateIn->callbacks.freeSysMem != NULL)) 225 { 226 AddrClient client = { 227 pCreateIn->hClient, 228 pCreateIn->callbacks 229 }; 230 231 switch (pCreateIn->chipEngine) 232 { 233 case CIASICIDGFXENGINE_SOUTHERNISLAND: 234 switch (pCreateIn->chipFamily) 235 { 236 case FAMILY_SI: 237 pLib = AddrSIHwlInit(&client); 238 break; 239 case FAMILY_VI: 240 case FAMILY_CZ: // VI based fusion(carrizo) 241 case FAMILY_CI: 242 case FAMILY_KV: // CI based fusion 243 pLib = AddrCIHwlInit(&client); 244 break; 245 default: 246 ADDR_ASSERT_ALWAYS(); 247 break; 248 } 249 break; 250 default: 251 ADDR_ASSERT_ALWAYS(); 252 break; 253 } 254 } 255 256 if ((pLib != NULL)) 257 { 258 BOOL_32 initValid; 259 260 // Pass createFlags to configFlags first since these flags may be overwritten 261 pLib->m_configFlags.noCubeMipSlicesPad = pCreateIn->createFlags.noCubeMipSlicesPad; 262 pLib->m_configFlags.fillSizeFields = pCreateIn->createFlags.fillSizeFields; 263 pLib->m_configFlags.useTileIndex = pCreateIn->createFlags.useTileIndex; 264 pLib->m_configFlags.useCombinedSwizzle = pCreateIn->createFlags.useCombinedSwizzle; 265 pLib->m_configFlags.checkLast2DLevel = pCreateIn->createFlags.checkLast2DLevel; 266 pLib->m_configFlags.useHtileSliceAlign = pCreateIn->createFlags.useHtileSliceAlign; 267 pLib->m_configFlags.degradeBaseLevel = pCreateIn->createFlags.degradeBaseLevel; 268 pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile; 269 270 pLib->SetAddrChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision); 271 272 pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels); 273 274 // Global parameters initialized and remaining configFlags bits are set as well 275 initValid = pLib->HwlInitGlobalParams(pCreateIn); 276 277 if (initValid) 278 { 279 pLib->m_pElemLib = AddrElemLib::Create(pLib); 280 } 281 else 282 { 283 pLib->m_pElemLib = NULL; // Don't go on allocating element lib 284 returnCode = ADDR_INVALIDGBREGVALUES; 285 } 286 287 if (pLib->m_pElemLib == NULL) 288 { 289 delete pLib; 290 pLib = NULL; 291 ADDR_ASSERT_ALWAYS(); 292 } 293 else 294 { 295 pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags); 296 } 297 } 298 299 pCreateOut->hLib = pLib; 300 301 if ((pLib == NULL) && 302 (returnCode == ADDR_OK)) 303 { 304 // Unknown failures, we return the general error code 305 returnCode = ADDR_ERROR; 306 } 307 308 return returnCode; 309 } 310 311 /** 312 *************************************************************************************************** 313 * AddrLib::SetAddrChipFamily 314 * 315 * @brief 316 * Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision 317 * @return 318 * N/A 319 *************************************************************************************************** 320 */ 321 VOID AddrLib::SetAddrChipFamily( 322 UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h 323 UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h 324 { 325 AddrChipFamily family = ADDR_CHIP_FAMILY_IVLD; 326 327 family = HwlConvertChipFamily(uChipFamily, uChipRevision); 328 329 ADDR_ASSERT(family != ADDR_CHIP_FAMILY_IVLD); 330 331 m_chipFamily = family; 332 m_chipRevision = uChipRevision; 333 } 334 335 /** 336 *************************************************************************************************** 337 * AddrLib::SetMinPitchAlignPixels 338 * 339 * @brief 340 * Set m_minPitchAlignPixels with input param 341 * 342 * @return 343 * N/A 344 *************************************************************************************************** 345 */ 346 VOID AddrLib::SetMinPitchAlignPixels( 347 UINT_32 minPitchAlignPixels) ///< [in] minmum pitch alignment in pixels 348 { 349 m_minPitchAlignPixels = (minPitchAlignPixels == 0)? 1 : minPitchAlignPixels; 350 } 351 352 /** 353 *************************************************************************************************** 354 * AddrLib::GetAddrLib 355 * 356 * @brief 357 * Get AddrLib pointer 358 * 359 * @return 360 * An AddrLib class pointer 361 *************************************************************************************************** 362 */ 363 AddrLib * AddrLib::GetAddrLib( 364 ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE 365 { 366 return static_cast<AddrLib *>(hLib); 367 } 368 369 370 371 /////////////////////////////////////////////////////////////////////////////////////////////////// 372 // Surface Methods 373 /////////////////////////////////////////////////////////////////////////////////////////////////// 374 375 376 /** 377 *************************************************************************************************** 378 * AddrLib::ComputeSurfaceInfo 379 * 380 * @brief 381 * Interface function stub of AddrComputeSurfaceInfo. 382 * 383 * @return 384 * ADDR_E_RETURNCODE 385 *************************************************************************************************** 386 */ 387 ADDR_E_RETURNCODE AddrLib::ComputeSurfaceInfo( 388 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure 389 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure 390 ) const 391 { 392 ADDR_E_RETURNCODE returnCode = ADDR_OK; 393 394 if (GetFillSizeFieldsFlags() == TRUE) 395 { 396 if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT)) || 397 (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT))) 398 { 399 returnCode = ADDR_PARAMSIZEMISMATCH; 400 } 401 } 402 403 // We suggest client do sanity check but a check here is also good 404 if (pIn->bpp > 128) 405 { 406 returnCode = ADDR_INVALIDPARAMS; 407 } 408 409 // Thick modes don't support multisample 410 if (ComputeSurfaceThickness(pIn->tileMode) > 1 && pIn->numSamples > 1) 411 { 412 returnCode = ADDR_INVALIDPARAMS; 413 } 414 415 if (returnCode == ADDR_OK) 416 { 417 // Get a local copy of input structure and only reference pIn for unadjusted values 418 ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn; 419 ADDR_TILEINFO tileInfoNull = {0}; 420 421 if (UseTileInfo()) 422 { 423 // If the original input has a valid ADDR_TILEINFO pointer then copy its contents. 424 // Otherwise the default 0's in tileInfoNull are used. 425 if (pIn->pTileInfo) 426 { 427 tileInfoNull = *pIn->pTileInfo; 428 } 429 localIn.pTileInfo = &tileInfoNull; 430 } 431 432 localIn.numSamples = pIn->numSamples == 0 ? 1 : pIn->numSamples; 433 434 // Do mipmap check first 435 // If format is BCn, pre-pad dimension to power-of-two according to HWL 436 ComputeMipLevel(&localIn); 437 438 if (m_configFlags.checkLast2DLevel) 439 { 440 // Save this level's original height in pixels 441 pOut->height = pIn->height; 442 } 443 444 UINT_32 expandX = 1; 445 UINT_32 expandY = 1; 446 AddrElemMode elemMode; 447 448 // Save outputs that may not go through HWL 449 pOut->pixelBits = localIn.bpp; 450 pOut->numSamples = localIn.numSamples; 451 pOut->last2DLevel = FALSE; 452 453 #if !ALT_TEST 454 if (localIn.numSamples > 1) 455 { 456 ADDR_ASSERT(localIn.mipLevel == 0); 457 } 458 #endif 459 460 if (localIn.format != ADDR_FMT_INVALID) // Set format to INVALID will skip this conversion 461 { 462 // Get compression/expansion factors and element mode 463 // (which indicates compression/expansion 464 localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format, 465 &elemMode, 466 &expandX, 467 &expandY); 468 469 // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is 470 // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear- 471 // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw 472 // restrictions are different. 473 // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround 474 // but we use this flag to skip RestoreSurfaceInfo below 475 476 if ((elemMode == ADDR_EXPANDED) && 477 (expandX > 1)) 478 { 479 ADDR_ASSERT(localIn.tileMode == ADDR_TM_LINEAR_ALIGNED || localIn.height == 1); 480 } 481 482 GetElemLib()->AdjustSurfaceInfo(elemMode, 483 expandX, 484 expandY, 485 &localIn.bpp, 486 &localIn.basePitch, 487 &localIn.width, 488 &localIn.height); 489 490 // Overwrite these parameters if we have a valid format 491 } 492 else if (localIn.bpp != 0) 493 { 494 localIn.width = (localIn.width != 0) ? localIn.width : 1; 495 localIn.height = (localIn.height != 0) ? localIn.height : 1; 496 } 497 else // Rule out some invalid parameters 498 { 499 ADDR_ASSERT_ALWAYS(); 500 501 returnCode = ADDR_INVALIDPARAMS; 502 } 503 504 // Check mipmap after surface expansion 505 if (returnCode == ADDR_OK) 506 { 507 returnCode = PostComputeMipLevel(&localIn, pOut); 508 } 509 510 if (returnCode == ADDR_OK) 511 { 512 if (UseTileIndex(localIn.tileIndex)) 513 { 514 // Make sure pTileInfo is not NULL 515 ADDR_ASSERT(localIn.pTileInfo); 516 517 UINT_32 numSamples = GetNumFragments(localIn.numSamples, localIn.numFrags); 518 519 INT_32 macroModeIndex = TileIndexNoMacroIndex; 520 521 if (localIn.tileIndex != TileIndexLinearGeneral) 522 { 523 // Try finding a macroModeIndex 524 macroModeIndex = HwlComputeMacroModeIndex(localIn.tileIndex, 525 localIn.flags, 526 localIn.bpp, 527 numSamples, 528 localIn.pTileInfo, 529 &localIn.tileMode, 530 &localIn.tileType); 531 } 532 533 // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info 534 if (macroModeIndex == TileIndexNoMacroIndex) 535 { 536 returnCode = HwlSetupTileCfg(localIn.tileIndex, macroModeIndex, 537 localIn.pTileInfo, 538 &localIn.tileMode, &localIn.tileType); 539 } 540 // If macroModeIndex is invalid, then assert this is not macro tiled 541 else if (macroModeIndex == TileIndexInvalid) 542 { 543 ADDR_ASSERT(!IsMacroTiled(localIn.tileMode)); 544 } 545 } 546 } 547 548 if (returnCode == ADDR_OK) 549 { 550 AddrTileMode tileMode = localIn.tileMode; 551 AddrTileType tileType = localIn.tileType; 552 553 // HWL layer may override tile mode if necessary 554 if (HwlOverrideTileMode(&localIn, &tileMode, &tileType)) 555 { 556 localIn.tileMode = tileMode; 557 localIn.tileType = tileType; 558 } 559 // Degrade base level if applicable 560 if (DegradeBaseLevel(&localIn, &tileMode)) 561 { 562 localIn.tileMode = tileMode; 563 } 564 } 565 566 // Call main function to compute surface info 567 if (returnCode == ADDR_OK) 568 { 569 returnCode = HwlComputeSurfaceInfo(&localIn, pOut); 570 } 571 572 if (returnCode == ADDR_OK) 573 { 574 // Since bpp might be changed we just pass it through 575 pOut->bpp = localIn.bpp; 576 577 // Also original width/height/bpp 578 pOut->pixelPitch = pOut->pitch; 579 pOut->pixelHeight = pOut->height; 580 581 #if DEBUG 582 if (localIn.flags.display) 583 { 584 ADDR_ASSERT((pOut->pitchAlign % 32) == 0); 585 } 586 #endif //DEBUG 587 588 if (localIn.format != ADDR_FMT_INVALID) 589 { 590 // 591 // 96 bits surface of level 1+ requires element pitch of 32 bits instead 592 // In hwl function we skip multiplication of 3 then we should skip division of 3 593 // We keep pitch that represents 32 bit element instead of 96 bits since we 594 // will get an odd number if divided by 3. 595 // 596 if (!((expandX == 3) && (localIn.mipLevel > 0))) 597 { 598 599 GetElemLib()->RestoreSurfaceInfo(elemMode, 600 expandX, 601 expandY, 602 &localIn.bpp, 603 &pOut->pixelPitch, 604 &pOut->pixelHeight); 605 } 606 } 607 608 if (localIn.flags.qbStereo) 609 { 610 if (pOut->pStereoInfo) 611 { 612 ComputeQbStereoInfo(pOut); 613 } 614 } 615 616 if (localIn.flags.volume) // For volume sliceSize equals to all z-slices 617 { 618 pOut->sliceSize = pOut->surfSize; 619 } 620 else // For array: sliceSize is likely to have slice-padding (the last one) 621 { 622 pOut->sliceSize = pOut->surfSize / pOut->depth; 623 624 // array or cubemap 625 if (pIn->numSlices > 1) 626 { 627 // If this is the last slice then add the padding size to this slice 628 if (pIn->slice == (pIn->numSlices - 1)) 629 { 630 pOut->sliceSize += pOut->sliceSize * (pOut->depth - pIn->numSlices); 631 } 632 else if (m_configFlags.checkLast2DLevel) 633 { 634 // Reset last2DLevel flag if this is not the last array slice 635 pOut->last2DLevel = FALSE; 636 } 637 } 638 } 639 640 pOut->pitchTileMax = pOut->pitch / 8 - 1; 641 pOut->heightTileMax = pOut->height / 8 - 1; 642 pOut->sliceTileMax = pOut->pitch * pOut->height / 64 - 1; 643 } 644 } 645 646 return returnCode; 647 } 648 649 /** 650 *************************************************************************************************** 651 * AddrLib::ComputeSurfaceInfo 652 * 653 * @brief 654 * Interface function stub of AddrComputeSurfaceInfo. 655 * 656 * @return 657 * ADDR_E_RETURNCODE 658 *************************************************************************************************** 659 */ 660 ADDR_E_RETURNCODE AddrLib::ComputeSurfaceAddrFromCoord( 661 const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure 662 ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure 663 ) const 664 { 665 ADDR_E_RETURNCODE returnCode = ADDR_OK; 666 667 if (GetFillSizeFieldsFlags() == TRUE) 668 { 669 if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) || 670 (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT))) 671 { 672 returnCode = ADDR_PARAMSIZEMISMATCH; 673 } 674 } 675 676 if (returnCode == ADDR_OK) 677 { 678 ADDR_TILEINFO tileInfoNull; 679 ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input; 680 681 if (UseTileIndex(pIn->tileIndex)) 682 { 683 input = *pIn; 684 // Use temp tile info for calcalation 685 input.pTileInfo = &tileInfoNull; 686 687 const ADDR_SURFACE_FLAGS flags = {{0}}; 688 UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags); 689 690 // Try finding a macroModeIndex 691 INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex, 692 flags, 693 input.bpp, 694 numSamples, 695 input.pTileInfo, 696 &input.tileMode, 697 &input.tileType); 698 699 // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info 700 if (macroModeIndex == TileIndexNoMacroIndex) 701 { 702 returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, 703 input.pTileInfo, &input.tileMode, &input.tileType); 704 } 705 // If macroModeIndex is invalid, then assert this is not macro tiled 706 else if (macroModeIndex == TileIndexInvalid) 707 { 708 ADDR_ASSERT(!IsMacroTiled(input.tileMode)); 709 } 710 711 // Change the input structure 712 pIn = &input; 713 } 714 715 if (returnCode == ADDR_OK) 716 { 717 returnCode = HwlComputeSurfaceAddrFromCoord(pIn, pOut); 718 719 if (returnCode == ADDR_OK) 720 { 721 pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024)); 722 } 723 } 724 } 725 726 return returnCode; 727 } 728 729 /** 730 *************************************************************************************************** 731 * AddrLib::ComputeSurfaceCoordFromAddr 732 * 733 * @brief 734 * Interface function stub of ComputeSurfaceCoordFromAddr. 735 * 736 * @return 737 * ADDR_E_RETURNCODE 738 *************************************************************************************************** 739 */ 740 ADDR_E_RETURNCODE AddrLib::ComputeSurfaceCoordFromAddr( 741 const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure 742 ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure 743 ) const 744 { 745 ADDR_E_RETURNCODE returnCode = ADDR_OK; 746 747 if (GetFillSizeFieldsFlags() == TRUE) 748 { 749 if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) || 750 (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT))) 751 { 752 returnCode = ADDR_PARAMSIZEMISMATCH; 753 } 754 } 755 756 if (returnCode == ADDR_OK) 757 { 758 ADDR_TILEINFO tileInfoNull; 759 ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT input; 760 761 if (UseTileIndex(pIn->tileIndex)) 762 { 763 input = *pIn; 764 // Use temp tile info for calcalation 765 input.pTileInfo = &tileInfoNull; 766 767 const ADDR_SURFACE_FLAGS flags = {{0}}; 768 UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags); 769 770 // Try finding a macroModeIndex 771 INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex, 772 flags, 773 input.bpp, 774 numSamples, 775 input.pTileInfo, 776 &input.tileMode, 777 &input.tileType); 778 779 // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info 780 if (macroModeIndex == TileIndexNoMacroIndex) 781 { 782 returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, 783 input.pTileInfo, &input.tileMode, &input.tileType); 784 } 785 // If macroModeIndex is invalid, then assert this is not macro tiled 786 else if (macroModeIndex == TileIndexInvalid) 787 { 788 ADDR_ASSERT(!IsMacroTiled(input.tileMode)); 789 } 790 791 // Change the input structure 792 pIn = &input; 793 } 794 795 if (returnCode == ADDR_OK) 796 { 797 returnCode = HwlComputeSurfaceCoordFromAddr(pIn, pOut); 798 } 799 } 800 801 return returnCode; 802 } 803 804 /** 805 *************************************************************************************************** 806 * AddrLib::ComputeSliceTileSwizzle 807 * 808 * @brief 809 * Interface function stub of ComputeSliceTileSwizzle. 810 * 811 * @return 812 * ADDR_E_RETURNCODE 813 *************************************************************************************************** 814 */ 815 ADDR_E_RETURNCODE AddrLib::ComputeSliceTileSwizzle( 816 const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure 817 ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure 818 ) const 819 { 820 ADDR_E_RETURNCODE returnCode = ADDR_OK; 821 822 if (GetFillSizeFieldsFlags() == TRUE) 823 { 824 if ((pIn->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_INPUT)) || 825 (pOut->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_OUTPUT))) 826 { 827 returnCode = ADDR_PARAMSIZEMISMATCH; 828 } 829 } 830 831 if (returnCode == ADDR_OK) 832 { 833 ADDR_TILEINFO tileInfoNull; 834 ADDR_COMPUTE_SLICESWIZZLE_INPUT input; 835 836 if (UseTileIndex(pIn->tileIndex)) 837 { 838 input = *pIn; 839 // Use temp tile info for calcalation 840 input.pTileInfo = &tileInfoNull; 841 842 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, 843 input.pTileInfo, &input.tileMode); 844 // Change the input structure 845 pIn = &input; 846 } 847 848 if (returnCode == ADDR_OK) 849 { 850 returnCode = HwlComputeSliceTileSwizzle(pIn, pOut); 851 } 852 } 853 854 return returnCode; 855 } 856 857 /** 858 *************************************************************************************************** 859 * AddrLib::ExtractBankPipeSwizzle 860 * 861 * @brief 862 * Interface function stub of AddrExtractBankPipeSwizzle. 863 * 864 * @return 865 * ADDR_E_RETURNCODE 866 *************************************************************************************************** 867 */ 868 ADDR_E_RETURNCODE AddrLib::ExtractBankPipeSwizzle( 869 const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure 870 ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure 871 ) const 872 { 873 ADDR_E_RETURNCODE returnCode = ADDR_OK; 874 875 if (GetFillSizeFieldsFlags() == TRUE) 876 { 877 if ((pIn->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT)) || 878 (pOut->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT))) 879 { 880 returnCode = ADDR_PARAMSIZEMISMATCH; 881 } 882 } 883 884 if (returnCode == ADDR_OK) 885 { 886 ADDR_TILEINFO tileInfoNull; 887 ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT input; 888 889 if (UseTileIndex(pIn->tileIndex)) 890 { 891 input = *pIn; 892 // Use temp tile info for calcalation 893 input.pTileInfo = &tileInfoNull; 894 895 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 896 // Change the input structure 897 pIn = &input; 898 } 899 900 if (returnCode == ADDR_OK) 901 { 902 returnCode = HwlExtractBankPipeSwizzle(pIn, pOut); 903 } 904 } 905 906 return returnCode; 907 } 908 909 /** 910 *************************************************************************************************** 911 * AddrLib::CombineBankPipeSwizzle 912 * 913 * @brief 914 * Interface function stub of AddrCombineBankPipeSwizzle. 915 * 916 * @return 917 * ADDR_E_RETURNCODE 918 *************************************************************************************************** 919 */ 920 ADDR_E_RETURNCODE AddrLib::CombineBankPipeSwizzle( 921 const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure 922 ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure 923 ) const 924 { 925 ADDR_E_RETURNCODE returnCode = ADDR_OK; 926 927 if (GetFillSizeFieldsFlags() == TRUE) 928 { 929 if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) || 930 (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT))) 931 { 932 returnCode = ADDR_PARAMSIZEMISMATCH; 933 } 934 } 935 936 if (returnCode == ADDR_OK) 937 { 938 ADDR_TILEINFO tileInfoNull; 939 ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT input; 940 941 if (UseTileIndex(pIn->tileIndex)) 942 { 943 input = *pIn; 944 // Use temp tile info for calcalation 945 input.pTileInfo = &tileInfoNull; 946 947 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 948 // Change the input structure 949 pIn = &input; 950 } 951 952 if (returnCode == ADDR_OK) 953 { 954 returnCode = HwlCombineBankPipeSwizzle(pIn->bankSwizzle, 955 pIn->pipeSwizzle, 956 pIn->pTileInfo, 957 pIn->baseAddr, 958 &pOut->tileSwizzle); 959 } 960 } 961 962 return returnCode; 963 } 964 965 /** 966 *************************************************************************************************** 967 * AddrLib::ComputeBaseSwizzle 968 * 969 * @brief 970 * Interface function stub of AddrCompueBaseSwizzle. 971 * @return 972 * ADDR_E_RETURNCODE 973 *************************************************************************************************** 974 */ 975 ADDR_E_RETURNCODE AddrLib::ComputeBaseSwizzle( 976 const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, 977 ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const 978 { 979 ADDR_E_RETURNCODE returnCode = ADDR_OK; 980 981 if (GetFillSizeFieldsFlags() == TRUE) 982 { 983 if ((pIn->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT)) || 984 (pOut->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT))) 985 { 986 returnCode = ADDR_PARAMSIZEMISMATCH; 987 } 988 } 989 990 if (returnCode == ADDR_OK) 991 { 992 ADDR_TILEINFO tileInfoNull; 993 ADDR_COMPUTE_BASE_SWIZZLE_INPUT input; 994 995 if (UseTileIndex(pIn->tileIndex)) 996 { 997 input = *pIn; 998 // Use temp tile info for calcalation 999 input.pTileInfo = &tileInfoNull; 1000 1001 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1002 // Change the input structure 1003 pIn = &input; 1004 } 1005 1006 if (returnCode == ADDR_OK) 1007 { 1008 if (IsMacroTiled(pIn->tileMode)) 1009 { 1010 returnCode = HwlComputeBaseSwizzle(pIn, pOut); 1011 } 1012 else 1013 { 1014 pOut->tileSwizzle = 0; 1015 } 1016 } 1017 } 1018 1019 return returnCode; 1020 } 1021 1022 /** 1023 *************************************************************************************************** 1024 * AddrLib::ComputeFmaskInfo 1025 * 1026 * @brief 1027 * Interface function stub of ComputeFmaskInfo. 1028 * 1029 * @return 1030 * ADDR_E_RETURNCODE 1031 *************************************************************************************************** 1032 */ 1033 ADDR_E_RETURNCODE AddrLib::ComputeFmaskInfo( 1034 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure 1035 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure 1036 ) 1037 { 1038 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1039 1040 if (GetFillSizeFieldsFlags() == TRUE) 1041 { 1042 if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) || 1043 (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT))) 1044 { 1045 returnCode = ADDR_PARAMSIZEMISMATCH; 1046 } 1047 } 1048 1049 // No thick MSAA 1050 if (ComputeSurfaceThickness(pIn->tileMode) > 1) 1051 { 1052 returnCode = ADDR_INVALIDPARAMS; 1053 } 1054 1055 if (returnCode == ADDR_OK) 1056 { 1057 ADDR_TILEINFO tileInfoNull; 1058 ADDR_COMPUTE_FMASK_INFO_INPUT input; 1059 1060 if (UseTileIndex(pIn->tileIndex)) 1061 { 1062 input = *pIn; 1063 1064 if (pOut->pTileInfo) 1065 { 1066 // Use temp tile info for calcalation 1067 input.pTileInfo = pOut->pTileInfo; 1068 } 1069 else 1070 { 1071 input.pTileInfo = &tileInfoNull; 1072 } 1073 1074 ADDR_SURFACE_FLAGS flags = {{0}}; 1075 flags.fmask = 1; 1076 1077 // Try finding a macroModeIndex 1078 INT_32 macroModeIndex = HwlComputeMacroModeIndex(pIn->tileIndex, 1079 flags, 1080 HwlComputeFmaskBits(pIn, NULL), 1081 pIn->numSamples, 1082 input.pTileInfo, 1083 &input.tileMode); 1084 1085 // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info 1086 if (macroModeIndex == TileIndexNoMacroIndex) 1087 { 1088 returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, 1089 input.pTileInfo, &input.tileMode); 1090 } 1091 1092 ADDR_ASSERT(macroModeIndex != TileIndexInvalid); 1093 1094 // Change the input structure 1095 pIn = &input; 1096 } 1097 1098 if (returnCode == ADDR_OK) 1099 { 1100 if (pIn->numSamples > 1) 1101 { 1102 returnCode = HwlComputeFmaskInfo(pIn, pOut); 1103 } 1104 else 1105 { 1106 memset(pOut, 0, sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)); 1107 1108 returnCode = ADDR_INVALIDPARAMS; 1109 } 1110 } 1111 } 1112 1113 return returnCode; 1114 } 1115 1116 /** 1117 *************************************************************************************************** 1118 * AddrLib::ComputeFmaskAddrFromCoord 1119 * 1120 * @brief 1121 * Interface function stub of ComputeFmaskAddrFromCoord. 1122 * 1123 * @return 1124 * ADDR_E_RETURNCODE 1125 *************************************************************************************************** 1126 */ 1127 ADDR_E_RETURNCODE AddrLib::ComputeFmaskAddrFromCoord( 1128 const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure 1129 ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure 1130 ) const 1131 { 1132 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1133 1134 if (GetFillSizeFieldsFlags() == TRUE) 1135 { 1136 if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT)) || 1137 (pOut->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT))) 1138 { 1139 returnCode = ADDR_PARAMSIZEMISMATCH; 1140 } 1141 } 1142 1143 if (returnCode == ADDR_OK) 1144 { 1145 ADDR_ASSERT(pIn->numSamples > 1); 1146 1147 if (pIn->numSamples > 1) 1148 { 1149 returnCode = HwlComputeFmaskAddrFromCoord(pIn, pOut); 1150 } 1151 else 1152 { 1153 returnCode = ADDR_INVALIDPARAMS; 1154 } 1155 } 1156 1157 return returnCode; 1158 } 1159 1160 /** 1161 *************************************************************************************************** 1162 * AddrLib::ComputeFmaskCoordFromAddr 1163 * 1164 * @brief 1165 * Interface function stub of ComputeFmaskAddrFromCoord. 1166 * 1167 * @return 1168 * ADDR_E_RETURNCODE 1169 *************************************************************************************************** 1170 */ 1171 ADDR_E_RETURNCODE AddrLib::ComputeFmaskCoordFromAddr( 1172 const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure 1173 ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure 1174 ) const 1175 { 1176 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1177 1178 if (GetFillSizeFieldsFlags() == TRUE) 1179 { 1180 if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT)) || 1181 (pOut->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT))) 1182 { 1183 returnCode = ADDR_PARAMSIZEMISMATCH; 1184 } 1185 } 1186 1187 if (returnCode == ADDR_OK) 1188 { 1189 ADDR_ASSERT(pIn->numSamples > 1); 1190 1191 if (pIn->numSamples > 1) 1192 { 1193 returnCode = HwlComputeFmaskCoordFromAddr(pIn, pOut); 1194 } 1195 else 1196 { 1197 returnCode = ADDR_INVALIDPARAMS; 1198 } 1199 } 1200 1201 return returnCode; 1202 } 1203 1204 /** 1205 *************************************************************************************************** 1206 * AddrLib::ConvertTileInfoToHW 1207 * 1208 * @brief 1209 * Convert tile info from real value to HW register value in HW layer 1210 * 1211 * @return 1212 * ADDR_E_RETURNCODE 1213 *************************************************************************************************** 1214 */ 1215 ADDR_E_RETURNCODE AddrLib::ConvertTileInfoToHW( 1216 const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure 1217 ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure 1218 ) const 1219 { 1220 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1221 1222 if (GetFillSizeFieldsFlags() == TRUE) 1223 { 1224 if ((pIn->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT)) || 1225 (pOut->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT))) 1226 { 1227 returnCode = ADDR_PARAMSIZEMISMATCH; 1228 } 1229 } 1230 1231 if (returnCode == ADDR_OK) 1232 { 1233 ADDR_TILEINFO tileInfoNull; 1234 ADDR_CONVERT_TILEINFOTOHW_INPUT input; 1235 // if pIn->reverse is TRUE, indices are ignored 1236 if (pIn->reverse == FALSE && UseTileIndex(pIn->tileIndex)) 1237 { 1238 input = *pIn; 1239 input.pTileInfo = &tileInfoNull; 1240 1241 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1242 1243 pIn = &input; 1244 } 1245 1246 if (returnCode == ADDR_OK) 1247 { 1248 returnCode = HwlConvertTileInfoToHW(pIn, pOut); 1249 } 1250 } 1251 1252 return returnCode; 1253 } 1254 1255 /** 1256 *************************************************************************************************** 1257 * AddrLib::ConvertTileIndex 1258 * 1259 * @brief 1260 * Convert tile index to tile mode/type/info 1261 * 1262 * @return 1263 * ADDR_E_RETURNCODE 1264 *************************************************************************************************** 1265 */ 1266 ADDR_E_RETURNCODE AddrLib::ConvertTileIndex( 1267 const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ///< [in] input structure 1268 ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure 1269 ) const 1270 { 1271 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1272 1273 if (GetFillSizeFieldsFlags() == TRUE) 1274 { 1275 if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX_INPUT)) || 1276 (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT))) 1277 { 1278 returnCode = ADDR_PARAMSIZEMISMATCH; 1279 } 1280 } 1281 1282 if (returnCode == ADDR_OK) 1283 { 1284 1285 returnCode = HwlSetupTileCfg(pIn->tileIndex, pIn->macroModeIndex, 1286 pOut->pTileInfo, &pOut->tileMode, &pOut->tileType); 1287 1288 if (returnCode == ADDR_OK && pIn->tileInfoHw) 1289 { 1290 ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0}; 1291 ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0}; 1292 1293 hwInput.pTileInfo = pOut->pTileInfo; 1294 hwInput.tileIndex = -1; 1295 hwOutput.pTileInfo = pOut->pTileInfo; 1296 1297 returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput); 1298 } 1299 } 1300 1301 return returnCode; 1302 } 1303 1304 /** 1305 *************************************************************************************************** 1306 * AddrLib::ConvertTileIndex1 1307 * 1308 * @brief 1309 * Convert tile index to tile mode/type/info 1310 * 1311 * @return 1312 * ADDR_E_RETURNCODE 1313 *************************************************************************************************** 1314 */ 1315 ADDR_E_RETURNCODE AddrLib::ConvertTileIndex1( 1316 const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ///< [in] input structure 1317 ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure 1318 ) const 1319 { 1320 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1321 1322 if (GetFillSizeFieldsFlags() == TRUE) 1323 { 1324 if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX1_INPUT)) || 1325 (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT))) 1326 { 1327 returnCode = ADDR_PARAMSIZEMISMATCH; 1328 } 1329 } 1330 1331 if (returnCode == ADDR_OK) 1332 { 1333 ADDR_SURFACE_FLAGS flags = {{0}}; 1334 1335 HwlComputeMacroModeIndex(pIn->tileIndex, flags, pIn->bpp, pIn->numSamples, 1336 pOut->pTileInfo, &pOut->tileMode, &pOut->tileType); 1337 1338 if (pIn->tileInfoHw) 1339 { 1340 ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0}; 1341 ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0}; 1342 1343 hwInput.pTileInfo = pOut->pTileInfo; 1344 hwInput.tileIndex = -1; 1345 hwOutput.pTileInfo = pOut->pTileInfo; 1346 1347 returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput); 1348 } 1349 } 1350 1351 return returnCode; 1352 } 1353 1354 /** 1355 *************************************************************************************************** 1356 * AddrLib::GetTileIndex 1357 * 1358 * @brief 1359 * Get tile index from tile mode/type/info 1360 * 1361 * @return 1362 * ADDR_E_RETURNCODE 1363 *************************************************************************************************** 1364 */ 1365 ADDR_E_RETURNCODE AddrLib::GetTileIndex( 1366 const ADDR_GET_TILEINDEX_INPUT* pIn, ///< [in] input structure 1367 ADDR_GET_TILEINDEX_OUTPUT* pOut ///< [out] output structure 1368 ) const 1369 { 1370 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1371 1372 if (GetFillSizeFieldsFlags() == TRUE) 1373 { 1374 if ((pIn->size != sizeof(ADDR_GET_TILEINDEX_INPUT)) || 1375 (pOut->size != sizeof(ADDR_GET_TILEINDEX_OUTPUT))) 1376 { 1377 returnCode = ADDR_PARAMSIZEMISMATCH; 1378 } 1379 } 1380 1381 if (returnCode == ADDR_OK) 1382 { 1383 returnCode = HwlGetTileIndex(pIn, pOut); 1384 } 1385 1386 return returnCode; 1387 } 1388 1389 /** 1390 *************************************************************************************************** 1391 * AddrLib::ComputeSurfaceThickness 1392 * 1393 * @brief 1394 * Compute surface thickness 1395 * 1396 * @return 1397 * Surface thickness 1398 *************************************************************************************************** 1399 */ 1400 UINT_32 AddrLib::ComputeSurfaceThickness( 1401 AddrTileMode tileMode) ///< [in] tile mode 1402 { 1403 return m_modeFlags[tileMode].thickness; 1404 } 1405 1406 1407 1408 /////////////////////////////////////////////////////////////////////////////////////////////////// 1409 // CMASK/HTILE 1410 /////////////////////////////////////////////////////////////////////////////////////////////////// 1411 1412 /** 1413 *************************************************************************************************** 1414 * AddrLib::ComputeHtileInfo 1415 * 1416 * @brief 1417 * Interface function stub of AddrComputeHtilenfo 1418 * 1419 * @return 1420 * ADDR_E_RETURNCODE 1421 *************************************************************************************************** 1422 */ 1423 ADDR_E_RETURNCODE AddrLib::ComputeHtileInfo( 1424 const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] input structure 1425 ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut ///< [out] output structure 1426 ) const 1427 { 1428 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1429 1430 BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; 1431 BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; 1432 1433 if (GetFillSizeFieldsFlags() == TRUE) 1434 { 1435 if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT)) || 1436 (pOut->size != sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT))) 1437 { 1438 returnCode = ADDR_PARAMSIZEMISMATCH; 1439 } 1440 } 1441 1442 if (returnCode == ADDR_OK) 1443 { 1444 ADDR_TILEINFO tileInfoNull; 1445 ADDR_COMPUTE_HTILE_INFO_INPUT input; 1446 1447 if (UseTileIndex(pIn->tileIndex)) 1448 { 1449 input = *pIn; 1450 // Use temp tile info for calcalation 1451 input.pTileInfo = &tileInfoNull; 1452 1453 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1454 1455 // Change the input structure 1456 pIn = &input; 1457 } 1458 1459 if (returnCode == ADDR_OK) 1460 { 1461 pOut->bpp = ComputeHtileInfo(pIn->flags, 1462 pIn->pitch, 1463 pIn->height, 1464 pIn->numSlices, 1465 pIn->isLinear, 1466 isWidth8, 1467 isHeight8, 1468 pIn->pTileInfo, 1469 &pOut->pitch, 1470 &pOut->height, 1471 &pOut->htileBytes, 1472 &pOut->macroWidth, 1473 &pOut->macroHeight, 1474 &pOut->sliceSize, 1475 &pOut->baseAlign); 1476 } 1477 } 1478 1479 return returnCode; 1480 } 1481 1482 /** 1483 *************************************************************************************************** 1484 * AddrLib::ComputeCmaskInfo 1485 * 1486 * @brief 1487 * Interface function stub of AddrComputeCmaskInfo 1488 * 1489 * @return 1490 * ADDR_E_RETURNCODE 1491 *************************************************************************************************** 1492 */ 1493 ADDR_E_RETURNCODE AddrLib::ComputeCmaskInfo( 1494 const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] input structure 1495 ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut ///< [out] output structure 1496 ) const 1497 { 1498 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1499 1500 if (GetFillSizeFieldsFlags() == TRUE) 1501 { 1502 if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_INFO_INPUT)) || 1503 (pOut->size != sizeof(ADDR_COMPUTE_CMASK_INFO_OUTPUT))) 1504 { 1505 returnCode = ADDR_PARAMSIZEMISMATCH; 1506 } 1507 } 1508 1509 if (returnCode == ADDR_OK) 1510 { 1511 ADDR_TILEINFO tileInfoNull; 1512 ADDR_COMPUTE_CMASK_INFO_INPUT input; 1513 1514 if (UseTileIndex(pIn->tileIndex)) 1515 { 1516 input = *pIn; 1517 // Use temp tile info for calcalation 1518 input.pTileInfo = &tileInfoNull; 1519 1520 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1521 1522 // Change the input structure 1523 pIn = &input; 1524 } 1525 1526 if (returnCode == ADDR_OK) 1527 { 1528 returnCode = ComputeCmaskInfo(pIn->flags, 1529 pIn->pitch, 1530 pIn->height, 1531 pIn->numSlices, 1532 pIn->isLinear, 1533 pIn->pTileInfo, 1534 &pOut->pitch, 1535 &pOut->height, 1536 &pOut->cmaskBytes, 1537 &pOut->macroWidth, 1538 &pOut->macroHeight, 1539 &pOut->sliceSize, 1540 &pOut->baseAlign, 1541 &pOut->blockMax); 1542 } 1543 } 1544 1545 return returnCode; 1546 } 1547 1548 /** 1549 *************************************************************************************************** 1550 * AddrLib::ComputeDccInfo 1551 * 1552 * @brief 1553 * Interface function to compute DCC key info 1554 * 1555 * @return 1556 * return code of HwlComputeDccInfo 1557 *************************************************************************************************** 1558 */ 1559 ADDR_E_RETURNCODE AddrLib::ComputeDccInfo( 1560 const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input structure 1561 ADDR_COMPUTE_DCCINFO_OUTPUT* pOut ///< [out] output structure 1562 ) const 1563 { 1564 ADDR_E_RETURNCODE ret = ADDR_OK; 1565 1566 if (GetFillSizeFieldsFlags() == TRUE) 1567 { 1568 if ((pIn->size != sizeof(ADDR_COMPUTE_DCCINFO_INPUT)) || 1569 (pOut->size != sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT))) 1570 { 1571 ret = ADDR_PARAMSIZEMISMATCH; 1572 } 1573 } 1574 1575 if (ret == ADDR_OK) 1576 { 1577 ADDR_COMPUTE_DCCINFO_INPUT input; 1578 1579 if (UseTileIndex(pIn->tileIndex)) 1580 { 1581 input = *pIn; 1582 1583 ret = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, 1584 &input.tileInfo, &input.tileMode); 1585 1586 pIn = &input; 1587 } 1588 1589 if (ADDR_OK == ret) 1590 { 1591 ret = HwlComputeDccInfo(pIn, pOut); 1592 } 1593 } 1594 1595 return ret; 1596 } 1597 1598 /** 1599 *************************************************************************************************** 1600 * AddrLib::ComputeHtileAddrFromCoord 1601 * 1602 * @brief 1603 * Interface function stub of AddrComputeHtileAddrFromCoord 1604 * 1605 * @return 1606 * ADDR_E_RETURNCODE 1607 *************************************************************************************************** 1608 */ 1609 ADDR_E_RETURNCODE AddrLib::ComputeHtileAddrFromCoord( 1610 const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure 1611 ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure 1612 ) const 1613 { 1614 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1615 1616 BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; 1617 BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; 1618 1619 if (GetFillSizeFieldsFlags() == TRUE) 1620 { 1621 if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) || 1622 (pOut->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT))) 1623 { 1624 returnCode = ADDR_PARAMSIZEMISMATCH; 1625 } 1626 } 1627 1628 if (returnCode == ADDR_OK) 1629 { 1630 ADDR_TILEINFO tileInfoNull; 1631 ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT input; 1632 1633 if (UseTileIndex(pIn->tileIndex)) 1634 { 1635 input = *pIn; 1636 // Use temp tile info for calcalation 1637 input.pTileInfo = &tileInfoNull; 1638 1639 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1640 1641 // Change the input structure 1642 pIn = &input; 1643 } 1644 1645 if (returnCode == ADDR_OK) 1646 { 1647 pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch, 1648 pIn->height, 1649 pIn->x, 1650 pIn->y, 1651 pIn->slice, 1652 pIn->numSlices, 1653 1, 1654 pIn->isLinear, 1655 isWidth8, 1656 isHeight8, 1657 pIn->pTileInfo, 1658 &pOut->bitPosition); 1659 } 1660 } 1661 1662 return returnCode; 1663 1664 } 1665 1666 /** 1667 *************************************************************************************************** 1668 * AddrLib::ComputeHtileCoordFromAddr 1669 * 1670 * @brief 1671 * Interface function stub of AddrComputeHtileCoordFromAddr 1672 * 1673 * @return 1674 * ADDR_E_RETURNCODE 1675 *************************************************************************************************** 1676 */ 1677 ADDR_E_RETURNCODE AddrLib::ComputeHtileCoordFromAddr( 1678 const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure 1679 ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure 1680 ) const 1681 { 1682 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1683 1684 BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; 1685 BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; 1686 1687 if (GetFillSizeFieldsFlags() == TRUE) 1688 { 1689 if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT)) || 1690 (pOut->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT))) 1691 { 1692 returnCode = ADDR_PARAMSIZEMISMATCH; 1693 } 1694 } 1695 1696 if (returnCode == ADDR_OK) 1697 { 1698 ADDR_TILEINFO tileInfoNull; 1699 ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT input; 1700 1701 if (UseTileIndex(pIn->tileIndex)) 1702 { 1703 input = *pIn; 1704 // Use temp tile info for calcalation 1705 input.pTileInfo = &tileInfoNull; 1706 1707 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1708 1709 // Change the input structure 1710 pIn = &input; 1711 } 1712 1713 if (returnCode == ADDR_OK) 1714 { 1715 HwlComputeXmaskCoordFromAddr(pIn->addr, 1716 pIn->bitPosition, 1717 pIn->pitch, 1718 pIn->height, 1719 pIn->numSlices, 1720 1, 1721 pIn->isLinear, 1722 isWidth8, 1723 isHeight8, 1724 pIn->pTileInfo, 1725 &pOut->x, 1726 &pOut->y, 1727 &pOut->slice); 1728 } 1729 } 1730 1731 return returnCode; 1732 } 1733 1734 /** 1735 *************************************************************************************************** 1736 * AddrLib::ComputeCmaskAddrFromCoord 1737 * 1738 * @brief 1739 * Interface function stub of AddrComputeCmaskAddrFromCoord 1740 * 1741 * @return 1742 * ADDR_E_RETURNCODE 1743 *************************************************************************************************** 1744 */ 1745 ADDR_E_RETURNCODE AddrLib::ComputeCmaskAddrFromCoord( 1746 const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure 1747 ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure 1748 ) const 1749 { 1750 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1751 1752 if (GetFillSizeFieldsFlags() == TRUE) 1753 { 1754 if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) || 1755 (pOut->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT))) 1756 { 1757 returnCode = ADDR_PARAMSIZEMISMATCH; 1758 } 1759 } 1760 1761 if (returnCode == ADDR_OK) 1762 { 1763 ADDR_TILEINFO tileInfoNull; 1764 ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT input; 1765 1766 if (UseTileIndex(pIn->tileIndex)) 1767 { 1768 input = *pIn; 1769 // Use temp tile info for calcalation 1770 input.pTileInfo = &tileInfoNull; 1771 1772 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1773 1774 // Change the input structure 1775 pIn = &input; 1776 } 1777 1778 if (returnCode == ADDR_OK) 1779 { 1780 if (pIn->flags.tcCompatible == TRUE) 1781 { 1782 returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut); 1783 } 1784 else 1785 { 1786 pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch, 1787 pIn->height, 1788 pIn->x, 1789 pIn->y, 1790 pIn->slice, 1791 pIn->numSlices, 1792 2, 1793 pIn->isLinear, 1794 FALSE, //this is cmask, isWidth8 is not needed 1795 FALSE, //this is cmask, isHeight8 is not needed 1796 pIn->pTileInfo, 1797 &pOut->bitPosition); 1798 } 1799 1800 } 1801 } 1802 1803 return returnCode; 1804 } 1805 1806 /** 1807 *************************************************************************************************** 1808 * AddrLib::ComputeCmaskCoordFromAddr 1809 * 1810 * @brief 1811 * Interface function stub of AddrComputeCmaskCoordFromAddr 1812 * 1813 * @return 1814 * ADDR_E_RETURNCODE 1815 *************************************************************************************************** 1816 */ 1817 ADDR_E_RETURNCODE AddrLib::ComputeCmaskCoordFromAddr( 1818 const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure 1819 ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure 1820 ) const 1821 { 1822 ADDR_E_RETURNCODE returnCode = ADDR_OK; 1823 1824 if (GetFillSizeFieldsFlags() == TRUE) 1825 { 1826 if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT)) || 1827 (pOut->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT))) 1828 { 1829 returnCode = ADDR_PARAMSIZEMISMATCH; 1830 } 1831 } 1832 1833 if (returnCode == ADDR_OK) 1834 { 1835 ADDR_TILEINFO tileInfoNull; 1836 ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT input; 1837 1838 if (UseTileIndex(pIn->tileIndex)) 1839 { 1840 input = *pIn; 1841 // Use temp tile info for calcalation 1842 input.pTileInfo = &tileInfoNull; 1843 1844 returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); 1845 1846 // Change the input structure 1847 pIn = &input; 1848 } 1849 1850 if (returnCode == ADDR_OK) 1851 { 1852 HwlComputeXmaskCoordFromAddr(pIn->addr, 1853 pIn->bitPosition, 1854 pIn->pitch, 1855 pIn->height, 1856 pIn->numSlices, 1857 2, 1858 pIn->isLinear, 1859 FALSE, 1860 FALSE, 1861 pIn->pTileInfo, 1862 &pOut->x, 1863 &pOut->y, 1864 &pOut->slice); 1865 } 1866 } 1867 1868 return returnCode; 1869 } 1870 1871 /** 1872 *************************************************************************************************** 1873 * AddrLib::ComputeTileDataWidthAndHeight 1874 * 1875 * @brief 1876 * Compute the squared cache shape for per-tile data (CMASK and HTILE) 1877 * 1878 * @return 1879 * N/A 1880 * 1881 * @note 1882 * MacroWidth and macroHeight are measured in pixels 1883 *************************************************************************************************** 1884 */ 1885 VOID AddrLib::ComputeTileDataWidthAndHeight( 1886 UINT_32 bpp, ///< [in] bits per pixel 1887 UINT_32 cacheBits, ///< [in] bits of cache 1888 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 1889 UINT_32* pMacroWidth, ///< [out] macro tile width 1890 UINT_32* pMacroHeight ///< [out] macro tile height 1891 ) const 1892 { 1893 UINT_32 height = 1; 1894 UINT_32 width = cacheBits / bpp; 1895 UINT_32 pipes = HwlGetPipes(pTileInfo); 1896 1897 // Double height until the macro-tile is close to square 1898 // Height can only be doubled if width is even 1899 1900 while ((width > height * 2 * pipes) && !(width & 1)) 1901 { 1902 width /= 2; 1903 height *= 2; 1904 } 1905 1906 *pMacroWidth = 8 * width; 1907 *pMacroHeight = 8 * height * pipes; 1908 1909 // Note: The above iterative comptuation is equivalent to the following 1910 // 1911 //int log2_height = ((log2(cacheBits)-log2(bpp)-log2(pipes))/2); 1912 //int macroHeight = pow2( 3+log2(pipes)+log2_height ); 1913 } 1914 1915 /** 1916 *************************************************************************************************** 1917 * AddrLib::HwlComputeTileDataWidthAndHeightLinear 1918 * 1919 * @brief 1920 * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout 1921 * 1922 * @return 1923 * N/A 1924 * 1925 * @note 1926 * MacroWidth and macroHeight are measured in pixels 1927 *************************************************************************************************** 1928 */ 1929 VOID AddrLib::HwlComputeTileDataWidthAndHeightLinear( 1930 UINT_32* pMacroWidth, ///< [out] macro tile width 1931 UINT_32* pMacroHeight, ///< [out] macro tile height 1932 UINT_32 bpp, ///< [in] bits per pixel 1933 ADDR_TILEINFO* pTileInfo ///< [in] tile info 1934 ) const 1935 { 1936 ADDR_ASSERT(bpp != 4); // Cmask does not support linear layout prior to SI 1937 *pMacroWidth = 8 * 512 / bpp; // Align width to 512-bit memory accesses 1938 *pMacroHeight = 8 * m_pipes; // Align height to number of pipes 1939 } 1940 1941 /** 1942 *************************************************************************************************** 1943 * AddrLib::ComputeHtileInfo 1944 * 1945 * @brief 1946 * Compute htile pitch,width, bytes per 2D slice 1947 * 1948 * @return 1949 * Htile bpp i.e. How many bits for an 8x8 tile 1950 * Also returns by output parameters: 1951 * *Htile pitch, height, total size in bytes, macro-tile dimensions and slice size* 1952 *************************************************************************************************** 1953 */ 1954 UINT_32 AddrLib::ComputeHtileInfo( 1955 ADDR_HTILE_FLAGS flags, ///< [in] htile flags 1956 UINT_32 pitchIn, ///< [in] pitch input 1957 UINT_32 heightIn, ///< [in] height input 1958 UINT_32 numSlices, ///< [in] number of slices 1959 BOOL_32 isLinear, ///< [in] if it is linear mode 1960 BOOL_32 isWidth8, ///< [in] if htile block width is 8 1961 BOOL_32 isHeight8, ///< [in] if htile block height is 8 1962 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 1963 UINT_32* pPitchOut, ///< [out] pitch output 1964 UINT_32* pHeightOut, ///< [out] height output 1965 UINT_64* pHtileBytes, ///< [out] bytes per 2D slice 1966 UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels 1967 UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels 1968 UINT_64* pSliceSize, ///< [out] slice size in bytes 1969 UINT_32* pBaseAlign ///< [out] base alignment 1970 ) const 1971 { 1972 1973 UINT_32 macroWidth; 1974 UINT_32 macroHeight; 1975 UINT_32 baseAlign; 1976 UINT_64 surfBytes; 1977 UINT_64 sliceBytes; 1978 1979 numSlices = Max(1u, numSlices); 1980 1981 const UINT_32 bpp = HwlComputeHtileBpp(isWidth8, isHeight8); 1982 const UINT_32 cacheBits = HtileCacheBits; 1983 1984 if (isLinear) 1985 { 1986 HwlComputeTileDataWidthAndHeightLinear(¯oWidth, 1987 ¯oHeight, 1988 bpp, 1989 pTileInfo); 1990 } 1991 else 1992 { 1993 ComputeTileDataWidthAndHeight(bpp, 1994 cacheBits, 1995 pTileInfo, 1996 ¯oWidth, 1997 ¯oHeight); 1998 } 1999 2000 *pPitchOut = PowTwoAlign(pitchIn, macroWidth); 2001 *pHeightOut = PowTwoAlign(heightIn, macroHeight); 2002 2003 baseAlign = HwlComputeHtileBaseAlign(flags.tcCompatible, isLinear, pTileInfo); 2004 2005 surfBytes = HwlComputeHtileBytes(*pPitchOut, 2006 *pHeightOut, 2007 bpp, 2008 isLinear, 2009 numSlices, 2010 &sliceBytes, 2011 baseAlign); 2012 2013 *pHtileBytes = surfBytes; 2014 2015 // 2016 // Use SafeAssign since they are optional 2017 // 2018 SafeAssign(pMacroWidth, macroWidth); 2019 2020 SafeAssign(pMacroHeight, macroHeight); 2021 2022 SafeAssign(pSliceSize, sliceBytes); 2023 2024 SafeAssign(pBaseAlign, baseAlign); 2025 2026 return bpp; 2027 } 2028 2029 /** 2030 *************************************************************************************************** 2031 * AddrLib::ComputeCmaskBaseAlign 2032 * 2033 * @brief 2034 * Compute cmask base alignment 2035 * 2036 * @return 2037 * Cmask base alignment 2038 *************************************************************************************************** 2039 */ 2040 UINT_32 AddrLib::ComputeCmaskBaseAlign( 2041 ADDR_CMASK_FLAGS flags, ///< [in] Cmask flags 2042 ADDR_TILEINFO* pTileInfo ///< [in] Tile info 2043 ) const 2044 { 2045 UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo); 2046 2047 if (flags.tcCompatible) 2048 { 2049 ADDR_ASSERT(pTileInfo != NULL); 2050 if (pTileInfo) 2051 { 2052 baseAlign *= pTileInfo->banks; 2053 } 2054 } 2055 2056 return baseAlign; 2057 } 2058 2059 /** 2060 *************************************************************************************************** 2061 * AddrLib::ComputeCmaskBytes 2062 * 2063 * @brief 2064 * Compute cmask size in bytes 2065 * 2066 * @return 2067 * Cmask size in bytes 2068 *************************************************************************************************** 2069 */ 2070 UINT_64 AddrLib::ComputeCmaskBytes( 2071 UINT_32 pitch, ///< [in] pitch 2072 UINT_32 height, ///< [in] height 2073 UINT_32 numSlices ///< [in] number of slices 2074 ) const 2075 { 2076 return BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * numSlices * CmaskElemBits) / 2077 MicroTilePixels; 2078 } 2079 2080 /** 2081 *************************************************************************************************** 2082 * AddrLib::ComputeCmaskInfo 2083 * 2084 * @brief 2085 * Compute cmask pitch,width, bytes per 2D slice 2086 * 2087 * @return 2088 * BlockMax. Also by output parameters: Cmask pitch,height, total size in bytes, 2089 * macro-tile dimensions 2090 *************************************************************************************************** 2091 */ 2092 ADDR_E_RETURNCODE AddrLib::ComputeCmaskInfo( 2093 ADDR_CMASK_FLAGS flags, ///< [in] cmask flags 2094 UINT_32 pitchIn, ///< [in] pitch input 2095 UINT_32 heightIn, ///< [in] height input 2096 UINT_32 numSlices, ///< [in] number of slices 2097 BOOL_32 isLinear, ///< [in] is linear mode 2098 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 2099 UINT_32* pPitchOut, ///< [out] pitch output 2100 UINT_32* pHeightOut, ///< [out] height output 2101 UINT_64* pCmaskBytes, ///< [out] bytes per 2D slice 2102 UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels 2103 UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels 2104 UINT_64* pSliceSize, ///< [out] slice size in bytes 2105 UINT_32* pBaseAlign, ///< [out] base alignment 2106 UINT_32* pBlockMax ///< [out] block max == slice / 128 / 128 - 1 2107 ) const 2108 { 2109 UINT_32 macroWidth; 2110 UINT_32 macroHeight; 2111 UINT_32 baseAlign; 2112 UINT_64 surfBytes; 2113 UINT_64 sliceBytes; 2114 2115 numSlices = Max(1u, numSlices); 2116 2117 const UINT_32 bpp = CmaskElemBits; 2118 const UINT_32 cacheBits = CmaskCacheBits; 2119 2120 ADDR_E_RETURNCODE returnCode = ADDR_OK; 2121 2122 if (isLinear) 2123 { 2124 HwlComputeTileDataWidthAndHeightLinear(¯oWidth, 2125 ¯oHeight, 2126 bpp, 2127 pTileInfo); 2128 } 2129 else 2130 { 2131 ComputeTileDataWidthAndHeight(bpp, 2132 cacheBits, 2133 pTileInfo, 2134 ¯oWidth, 2135 ¯oHeight); 2136 } 2137 2138 *pPitchOut = (pitchIn + macroWidth - 1) & ~(macroWidth - 1); 2139 *pHeightOut = (heightIn + macroHeight - 1) & ~(macroHeight - 1); 2140 2141 2142 sliceBytes = ComputeCmaskBytes(*pPitchOut, 2143 *pHeightOut, 2144 1); 2145 2146 baseAlign = ComputeCmaskBaseAlign(flags, pTileInfo); 2147 2148 while (sliceBytes % baseAlign) 2149 { 2150 *pHeightOut += macroHeight; 2151 2152 sliceBytes = ComputeCmaskBytes(*pPitchOut, 2153 *pHeightOut, 2154 1); 2155 } 2156 2157 surfBytes = sliceBytes * numSlices; 2158 2159 *pCmaskBytes = surfBytes; 2160 2161 // 2162 // Use SafeAssign since they are optional 2163 // 2164 SafeAssign(pMacroWidth, macroWidth); 2165 2166 SafeAssign(pMacroHeight, macroHeight); 2167 2168 SafeAssign(pBaseAlign, baseAlign); 2169 2170 SafeAssign(pSliceSize, sliceBytes); 2171 2172 UINT_32 slice = (*pPitchOut) * (*pHeightOut); 2173 UINT_32 blockMax = slice / 128 / 128 - 1; 2174 2175 #if DEBUG 2176 if (slice % (64*256) != 0) 2177 { 2178 ADDR_ASSERT_ALWAYS(); 2179 } 2180 #endif //DEBUG 2181 2182 UINT_32 maxBlockMax = HwlGetMaxCmaskBlockMax(); 2183 2184 if (blockMax > maxBlockMax) 2185 { 2186 blockMax = maxBlockMax; 2187 returnCode = ADDR_INVALIDPARAMS; 2188 } 2189 2190 SafeAssign(pBlockMax, blockMax); 2191 2192 return returnCode; 2193 } 2194 2195 /** 2196 *************************************************************************************************** 2197 * AddrLib::ComputeXmaskCoordYFromPipe 2198 * 2199 * @brief 2200 * Compute the Y coord from pipe number for cmask/htile 2201 * 2202 * @return 2203 * Y coordinate 2204 * 2205 *************************************************************************************************** 2206 */ 2207 UINT_32 AddrLib::ComputeXmaskCoordYFromPipe( 2208 UINT_32 pipe, ///< [in] pipe number 2209 UINT_32 x ///< [in] x coordinate 2210 ) const 2211 { 2212 UINT_32 pipeBit0; 2213 UINT_32 pipeBit1; 2214 UINT_32 xBit0; 2215 UINT_32 xBit1; 2216 UINT_32 yBit0; 2217 UINT_32 yBit1; 2218 2219 UINT_32 y = 0; 2220 2221 UINT_32 numPipes = m_pipes; // SI has its implementation 2222 // 2223 // Convert pipe + x to y coordinate. 2224 // 2225 switch (numPipes) 2226 { 2227 case 1: 2228 // 2229 // 1 pipe 2230 // 2231 // p0 = 0 2232 // 2233 y = 0; 2234 break; 2235 case 2: 2236 // 2237 // 2 pipes 2238 // 2239 // p0 = x0 ^ y0 2240 // 2241 // y0 = p0 ^ x0 2242 // 2243 pipeBit0 = pipe & 0x1; 2244 2245 xBit0 = x & 0x1; 2246 2247 yBit0 = pipeBit0 ^ xBit0; 2248 2249 y = yBit0; 2250 break; 2251 case 4: 2252 // 2253 // 4 pipes 2254 // 2255 // p0 = x1 ^ y0 2256 // p1 = x0 ^ y1 2257 // 2258 // y0 = p0 ^ x1 2259 // y1 = p1 ^ x0 2260 // 2261 pipeBit0 = pipe & 0x1; 2262 pipeBit1 = (pipe & 0x2) >> 1; 2263 2264 xBit0 = x & 0x1; 2265 xBit1 = (x & 0x2) >> 1; 2266 2267 yBit0 = pipeBit0 ^ xBit1; 2268 yBit1 = pipeBit1 ^ xBit0; 2269 2270 y = (yBit0 | 2271 (yBit1 << 1)); 2272 break; 2273 case 8: 2274 // 2275 // 8 pipes 2276 // 2277 // r600 and r800 have different method 2278 // 2279 y = HwlComputeXmaskCoordYFrom8Pipe(pipe, x); 2280 break; 2281 default: 2282 break; 2283 } 2284 return y; 2285 } 2286 2287 /** 2288 *************************************************************************************************** 2289 * AddrLib::HwlComputeXmaskCoordFromAddr 2290 * 2291 * @brief 2292 * Compute the coord from an address of a cmask/htile 2293 * 2294 * @return 2295 * N/A 2296 * 2297 * @note 2298 * This method is reused by htile, so rename to Xmask 2299 *************************************************************************************************** 2300 */ 2301 VOID AddrLib::HwlComputeXmaskCoordFromAddr( 2302 UINT_64 addr, ///< [in] address 2303 UINT_32 bitPosition, ///< [in] bitPosition in a byte 2304 UINT_32 pitch, ///< [in] pitch 2305 UINT_32 height, ///< [in] height 2306 UINT_32 numSlices, ///< [in] number of slices 2307 UINT_32 factor, ///< [in] factor that indicates cmask or htile 2308 BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout 2309 BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 2310 BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 2311 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 2312 UINT_32* pX, ///< [out] x coord 2313 UINT_32* pY, ///< [out] y coord 2314 UINT_32* pSlice ///< [out] slice index 2315 ) const 2316 { 2317 UINT_32 pipe; 2318 UINT_32 numPipes; 2319 UINT_32 numPipeBits; 2320 UINT_32 macroTilePitch; 2321 UINT_32 macroTileHeight; 2322 2323 UINT_64 bitAddr; 2324 2325 UINT_32 microTileCoordY; 2326 2327 UINT_32 elemBits; 2328 2329 UINT_32 pitchAligned = pitch; 2330 UINT_32 heightAligned = height; 2331 UINT_64 totalBytes; 2332 2333 UINT_64 elemOffset; 2334 2335 UINT_64 macroIndex; 2336 UINT_32 microIndex; 2337 2338 UINT_64 macroNumber; 2339 UINT_32 microNumber; 2340 2341 UINT_32 macroX; 2342 UINT_32 macroY; 2343 UINT_32 macroZ; 2344 2345 UINT_32 microX; 2346 UINT_32 microY; 2347 2348 UINT_32 tilesPerMacro; 2349 UINT_32 macrosPerPitch; 2350 UINT_32 macrosPerSlice; 2351 2352 // 2353 // Extract pipe. 2354 // 2355 numPipes = HwlGetPipes(pTileInfo); 2356 pipe = ComputePipeFromAddr(addr, numPipes); 2357 2358 // 2359 // Compute the number of group and pipe bits. 2360 // 2361 numPipeBits = Log2(numPipes); 2362 2363 UINT_32 groupBits = 8 * m_pipeInterleaveBytes; 2364 UINT_32 pipes = numPipes; 2365 2366 2367 // 2368 // Compute the micro tile size, in bits. And macro tile pitch and height. 2369 // 2370 if (factor == 2) //CMASK 2371 { 2372 ADDR_CMASK_FLAGS flags = {{0}}; 2373 2374 elemBits = CmaskElemBits; 2375 2376 ComputeCmaskInfo(flags, 2377 pitch, 2378 height, 2379 numSlices, 2380 isLinear, 2381 pTileInfo, 2382 &pitchAligned, 2383 &heightAligned, 2384 &totalBytes, 2385 ¯oTilePitch, 2386 ¯oTileHeight); 2387 } 2388 else //HTILE 2389 { 2390 ADDR_HTILE_FLAGS flags = {{0}}; 2391 2392 if (factor != 1) 2393 { 2394 factor = 1; 2395 } 2396 2397 elemBits = HwlComputeHtileBpp(isWidth8, isHeight8); 2398 2399 ComputeHtileInfo(flags, 2400 pitch, 2401 height, 2402 numSlices, 2403 isLinear, 2404 isWidth8, 2405 isHeight8, 2406 pTileInfo, 2407 &pitchAligned, 2408 &heightAligned, 2409 &totalBytes, 2410 ¯oTilePitch, 2411 ¯oTileHeight); 2412 } 2413 2414 // Should use aligned dims 2415 // 2416 pitch = pitchAligned; 2417 height = heightAligned; 2418 2419 2420 // 2421 // Convert byte address to bit address. 2422 // 2423 bitAddr = BYTES_TO_BITS(addr) + bitPosition; 2424 2425 2426 // 2427 // Remove pipe bits from address. 2428 // 2429 2430 bitAddr = (bitAddr % groupBits) + ((bitAddr/groupBits/pipes)*groupBits); 2431 2432 2433 elemOffset = bitAddr / elemBits; 2434 2435 tilesPerMacro = (macroTilePitch/factor) * macroTileHeight / MicroTilePixels >> numPipeBits; 2436 2437 macrosPerPitch = pitch / (macroTilePitch/factor); 2438 macrosPerSlice = macrosPerPitch * height / macroTileHeight; 2439 2440 macroIndex = elemOffset / factor / tilesPerMacro; 2441 microIndex = static_cast<UINT_32>(elemOffset % (tilesPerMacro * factor)); 2442 2443 macroNumber = macroIndex * factor + microIndex % factor; 2444 microNumber = microIndex / factor; 2445 2446 macroX = static_cast<UINT_32>((macroNumber % macrosPerPitch)); 2447 macroY = static_cast<UINT_32>((macroNumber % macrosPerSlice) / macrosPerPitch); 2448 macroZ = static_cast<UINT_32>((macroNumber / macrosPerSlice)); 2449 2450 2451 microX = microNumber % (macroTilePitch / factor / MicroTileWidth); 2452 microY = (microNumber / (macroTilePitch / factor / MicroTileHeight)); 2453 2454 *pX = macroX * (macroTilePitch/factor) + microX * MicroTileWidth; 2455 *pY = macroY * macroTileHeight + (microY * MicroTileHeight << numPipeBits); 2456 *pSlice = macroZ; 2457 2458 microTileCoordY = ComputeXmaskCoordYFromPipe(pipe, 2459 *pX/MicroTileWidth); 2460 2461 2462 // 2463 // Assemble final coordinates. 2464 // 2465 *pY += microTileCoordY * MicroTileHeight; 2466 2467 } 2468 2469 /** 2470 *************************************************************************************************** 2471 * AddrLib::HwlComputeXmaskAddrFromCoord 2472 * 2473 * @brief 2474 * Compute the address from an address of cmask (prior to si) 2475 * 2476 * @return 2477 * Address in bytes 2478 * 2479 *************************************************************************************************** 2480 */ 2481 UINT_64 AddrLib::HwlComputeXmaskAddrFromCoord( 2482 UINT_32 pitch, ///< [in] pitch 2483 UINT_32 height, ///< [in] height 2484 UINT_32 x, ///< [in] x coord 2485 UINT_32 y, ///< [in] y coord 2486 UINT_32 slice, ///< [in] slice/depth index 2487 UINT_32 numSlices, ///< [in] number of slices 2488 UINT_32 factor, ///< [in] factor that indicates cmask(2) or htile(1) 2489 BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout 2490 BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 2491 BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value 2492 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info 2493 UINT_32* pBitPosition ///< [out] bit position inside a byte 2494 ) const 2495 { 2496 UINT_64 addr; 2497 UINT_32 numGroupBits; 2498 UINT_32 numPipeBits; 2499 UINT_32 newPitch = 0; 2500 UINT_32 newHeight = 0; 2501 UINT_64 sliceBytes = 0; 2502 UINT_64 totalBytes = 0; 2503 UINT_64 sliceOffset; 2504 UINT_32 pipe; 2505 UINT_32 macroTileWidth; 2506 UINT_32 macroTileHeight; 2507 UINT_32 macroTilesPerRow; 2508 UINT_32 macroTileBytes; 2509 UINT_32 macroTileIndexX; 2510 UINT_32 macroTileIndexY; 2511 UINT_64 macroTileOffset; 2512 UINT_32 pixelBytesPerRow; 2513 UINT_32 pixelOffsetX; 2514 UINT_32 pixelOffsetY; 2515 UINT_32 pixelOffset; 2516 UINT_64 totalOffset; 2517 UINT_64 offsetLo; 2518 UINT_64 offsetHi; 2519 UINT_64 groupMask; 2520 2521 2522 UINT_32 elemBits = 0; 2523 2524 UINT_32 numPipes = m_pipes; // This function is accessed prior to si only 2525 2526 if (factor == 2) //CMASK 2527 { 2528 elemBits = CmaskElemBits; 2529 2530 // For asics before SI, cmask is always tiled 2531 isLinear = FALSE; 2532 } 2533 else //HTILE 2534 { 2535 if (factor != 1) // Fix compile warning 2536 { 2537 factor = 1; 2538 } 2539 2540 elemBits = HwlComputeHtileBpp(isWidth8, isHeight8); 2541 } 2542 2543 // 2544 // Compute the number of group bits and pipe bits. 2545 // 2546 numGroupBits = Log2(m_pipeInterleaveBytes); 2547 numPipeBits = Log2(numPipes); 2548 2549 // 2550 // Compute macro tile dimensions. 2551 // 2552 if (factor == 2) // CMASK 2553 { 2554 ADDR_CMASK_FLAGS flags = {{0}}; 2555 2556 ComputeCmaskInfo(flags, 2557 pitch, 2558 height, 2559 numSlices, 2560 isLinear, 2561 pTileInfo, 2562 &newPitch, 2563 &newHeight, 2564 &totalBytes, 2565 ¯oTileWidth, 2566 ¯oTileHeight); 2567 2568 sliceBytes = totalBytes / numSlices; 2569 } 2570 else // HTILE 2571 { 2572 ADDR_HTILE_FLAGS flags = {{0}}; 2573 2574 ComputeHtileInfo(flags, 2575 pitch, 2576 height, 2577 numSlices, 2578 isLinear, 2579 isWidth8, 2580 isHeight8, 2581 pTileInfo, 2582 &newPitch, 2583 &newHeight, 2584 &totalBytes, 2585 ¯oTileWidth, 2586 ¯oTileHeight, 2587 &sliceBytes); 2588 } 2589 2590 sliceOffset = slice * sliceBytes; 2591 2592 // 2593 // Get the pipe. Note that neither slice rotation nor pipe swizzling apply for CMASK. 2594 // 2595 pipe = ComputePipeFromCoord(x, 2596 y, 2597 0, 2598 ADDR_TM_2D_TILED_THIN1, 2599 0, 2600 FALSE, 2601 pTileInfo); 2602 2603 // 2604 // Compute the number of macro tiles per row. 2605 // 2606 macroTilesPerRow = newPitch / macroTileWidth; 2607 2608 // 2609 // Compute the number of bytes per macro tile. 2610 // 2611 macroTileBytes = BITS_TO_BYTES((macroTileWidth * macroTileHeight * elemBits) / MicroTilePixels); 2612 2613 // 2614 // Compute the offset to the macro tile containing the specified coordinate. 2615 // 2616 macroTileIndexX = x / macroTileWidth; 2617 macroTileIndexY = y / macroTileHeight; 2618 macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes; 2619 2620 // 2621 // Compute the pixel offset within the macro tile. 2622 // 2623 pixelBytesPerRow = BITS_TO_BYTES(macroTileWidth * elemBits) / MicroTileWidth; 2624 2625 // 2626 // The nibbles are interleaved (see below), so the part of the offset relative to the x 2627 // coordinate repeats halfway across the row. (Not for HTILE) 2628 // 2629 if (factor == 2) 2630 { 2631 pixelOffsetX = (x % (macroTileWidth / 2)) / MicroTileWidth; 2632 } 2633 else 2634 { 2635 pixelOffsetX = (x % (macroTileWidth)) / MicroTileWidth * BITS_TO_BYTES(elemBits); 2636 } 2637 2638 // 2639 // Compute the y offset within the macro tile. 2640 // 2641 pixelOffsetY = (((y % macroTileHeight) / MicroTileHeight) / numPipes) * pixelBytesPerRow; 2642 2643 pixelOffset = pixelOffsetX + pixelOffsetY; 2644 2645 // 2646 // Combine the slice offset and macro tile offset with the pixel offset, accounting for the 2647 // pipe bits in the middle of the address. 2648 // 2649 totalOffset = ((sliceOffset + macroTileOffset) >> numPipeBits) + pixelOffset; 2650 2651 // 2652 // Split the offset to put some bits below the pipe bits and some above. 2653 // 2654 groupMask = (1 << numGroupBits) - 1; 2655 offsetLo = totalOffset & groupMask; 2656 offsetHi = (totalOffset & ~groupMask) << numPipeBits; 2657 2658 // 2659 // Assemble the address from its components. 2660 // 2661 addr = offsetLo; 2662 addr |= offsetHi; 2663 // This is to remove warning with /analyze option 2664 UINT_32 pipeBits = pipe << numGroupBits; 2665 addr |= pipeBits; 2666 2667 // 2668 // Compute the bit position. The lower nibble is used when the x coordinate within the macro 2669 // tile is less than half of the macro tile width, and the upper nibble is used when the x 2670 // coordinate within the macro tile is greater than or equal to half the macro tile width. 2671 // 2672 *pBitPosition = ((x % macroTileWidth) < (macroTileWidth / factor)) ? 0 : 4; 2673 2674 return addr; 2675 } 2676 2677 /////////////////////////////////////////////////////////////////////////////////////////////////// 2678 // Surface Addressing Shared 2679 /////////////////////////////////////////////////////////////////////////////////////////////////// 2680 2681 /** 2682 *************************************************************************************************** 2683 * AddrLib::ComputeSurfaceAddrFromCoordLinear 2684 * 2685 * @brief 2686 * Compute address from coord for linear surface 2687 * 2688 * @return 2689 * Address in bytes 2690 * 2691 *************************************************************************************************** 2692 */ 2693 UINT_64 AddrLib::ComputeSurfaceAddrFromCoordLinear( 2694 UINT_32 x, ///< [in] x coord 2695 UINT_32 y, ///< [in] y coord 2696 UINT_32 slice, ///< [in] slice/depth index 2697 UINT_32 sample, ///< [in] sample index 2698 UINT_32 bpp, ///< [in] bits per pixel 2699 UINT_32 pitch, ///< [in] pitch 2700 UINT_32 height, ///< [in] height 2701 UINT_32 numSlices, ///< [in] number of slices 2702 UINT_32* pBitPosition ///< [out] bit position inside a byte 2703 ) const 2704 { 2705 const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height; 2706 2707 UINT_64 sliceOffset = (slice + sample * numSlices)* sliceSize; 2708 UINT_64 rowOffset = static_cast<UINT_64>(y) * pitch; 2709 UINT_64 pixOffset = x; 2710 2711 UINT_64 addr = (sliceOffset + rowOffset + pixOffset) * bpp; 2712 2713 *pBitPosition = static_cast<UINT_32>(addr % 8); 2714 addr /= 8; 2715 2716 return addr; 2717 } 2718 2719 /** 2720 *************************************************************************************************** 2721 * AddrLib::ComputeSurfaceCoordFromAddrLinear 2722 * 2723 * @brief 2724 * Compute the coord from an address of a linear surface 2725 * 2726 * @return 2727 * N/A 2728 *************************************************************************************************** 2729 */ 2730 VOID AddrLib::ComputeSurfaceCoordFromAddrLinear( 2731 UINT_64 addr, ///< [in] address 2732 UINT_32 bitPosition, ///< [in] bitPosition in a byte 2733 UINT_32 bpp, ///< [in] bits per pixel 2734 UINT_32 pitch, ///< [in] pitch 2735 UINT_32 height, ///< [in] height 2736 UINT_32 numSlices, ///< [in] number of slices 2737 UINT_32* pX, ///< [out] x coord 2738 UINT_32* pY, ///< [out] y coord 2739 UINT_32* pSlice, ///< [out] slice/depth index 2740 UINT_32* pSample ///< [out] sample index 2741 ) const 2742 { 2743 const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height; 2744 const UINT_64 linearOffset = (BYTES_TO_BITS(addr) + bitPosition) / bpp; 2745 2746 *pX = static_cast<UINT_32>((linearOffset % sliceSize) % pitch); 2747 *pY = static_cast<UINT_32>((linearOffset % sliceSize) / pitch % height); 2748 *pSlice = static_cast<UINT_32>((linearOffset / sliceSize) % numSlices); 2749 *pSample = static_cast<UINT_32>((linearOffset / sliceSize) / numSlices); 2750 } 2751 2752 /** 2753 *************************************************************************************************** 2754 * AddrLib::ComputeSurfaceCoordFromAddrMicroTiled 2755 * 2756 * @brief 2757 * Compute the coord from an address of a micro tiled surface 2758 * 2759 * @return 2760 * N/A 2761 *************************************************************************************************** 2762 */ 2763 VOID AddrLib::ComputeSurfaceCoordFromAddrMicroTiled( 2764 UINT_64 addr, ///< [in] address 2765 UINT_32 bitPosition, ///< [in] bitPosition in a byte 2766 UINT_32 bpp, ///< [in] bits per pixel 2767 UINT_32 pitch, ///< [in] pitch 2768 UINT_32 height, ///< [in] height 2769 UINT_32 numSamples, ///< [in] number of samples 2770 AddrTileMode tileMode, ///< [in] tile mode 2771 UINT_32 tileBase, ///< [in] base offset within a tile 2772 UINT_32 compBits, ///< [in] component bits actually needed(for planar surface) 2773 UINT_32* pX, ///< [out] x coord 2774 UINT_32* pY, ///< [out] y coord 2775 UINT_32* pSlice, ///< [out] slice/depth index 2776 UINT_32* pSample, ///< [out] sample index, 2777 AddrTileType microTileType, ///< [in] micro tiling order 2778 BOOL_32 isDepthSampleOrder ///< [in] TRUE if in depth sample order 2779 ) const 2780 { 2781 UINT_64 bitAddr; 2782 UINT_32 microTileThickness; 2783 UINT_32 microTileBits; 2784 UINT_64 sliceBits; 2785 UINT_64 rowBits; 2786 UINT_32 sliceIndex; 2787 UINT_32 microTileCoordX; 2788 UINT_32 microTileCoordY; 2789 UINT_32 pixelOffset; 2790 UINT_32 pixelCoordX = 0; 2791 UINT_32 pixelCoordY = 0; 2792 UINT_32 pixelCoordZ = 0; 2793 UINT_32 pixelCoordS = 0; 2794 2795 // 2796 // Convert byte address to bit address. 2797 // 2798 bitAddr = BYTES_TO_BITS(addr) + bitPosition; 2799 2800 // 2801 // Compute the micro tile size, in bits. 2802 // 2803 switch (tileMode) 2804 { 2805 case ADDR_TM_1D_TILED_THICK: 2806 microTileThickness = ThickTileThickness; 2807 break; 2808 default: 2809 microTileThickness = 1; 2810 break; 2811 } 2812 2813 microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples; 2814 2815 // 2816 // Compute number of bits per slice and number of bits per row of micro tiles. 2817 // 2818 sliceBits = static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples; 2819 2820 rowBits = (pitch / MicroTileWidth) * microTileBits; 2821 2822 // 2823 // Extract the slice index. 2824 // 2825 sliceIndex = static_cast<UINT_32>(bitAddr / sliceBits); 2826 bitAddr -= sliceIndex * sliceBits; 2827 2828 // 2829 // Extract the y coordinate of the micro tile. 2830 // 2831 microTileCoordY = static_cast<UINT_32>(bitAddr / rowBits) * MicroTileHeight; 2832 bitAddr -= (microTileCoordY / MicroTileHeight) * rowBits; 2833 2834 // 2835 // Extract the x coordinate of the micro tile. 2836 // 2837 microTileCoordX = static_cast<UINT_32>(bitAddr / microTileBits) * MicroTileWidth; 2838 2839 // 2840 // Compute the pixel offset within the micro tile. 2841 // 2842 pixelOffset = static_cast<UINT_32>(bitAddr % microTileBits); 2843 2844 // 2845 // Extract pixel coordinates from the offset. 2846 // 2847 HwlComputePixelCoordFromOffset(pixelOffset, 2848 bpp, 2849 numSamples, 2850 tileMode, 2851 tileBase, 2852 compBits, 2853 &pixelCoordX, 2854 &pixelCoordY, 2855 &pixelCoordZ, 2856 &pixelCoordS, 2857 microTileType, 2858 isDepthSampleOrder); 2859 2860 // 2861 // Assemble final coordinates. 2862 // 2863 *pX = microTileCoordX + pixelCoordX; 2864 *pY = microTileCoordY + pixelCoordY; 2865 *pSlice = (sliceIndex * microTileThickness) + pixelCoordZ; 2866 *pSample = pixelCoordS; 2867 2868 if (microTileThickness > 1) 2869 { 2870 *pSample = 0; 2871 } 2872 } 2873 2874 /** 2875 *************************************************************************************************** 2876 * AddrLib::ComputePipeFromAddr 2877 * 2878 * @brief 2879 * Compute the pipe number from an address 2880 * 2881 * @return 2882 * Pipe number 2883 * 2884 *************************************************************************************************** 2885 */ 2886 UINT_32 AddrLib::ComputePipeFromAddr( 2887 UINT_64 addr, ///< [in] address 2888 UINT_32 numPipes ///< [in] number of banks 2889 ) const 2890 { 2891 UINT_32 pipe; 2892 2893 UINT_32 groupBytes = m_pipeInterleaveBytes; //just different terms 2894 2895 // R600 2896 // The LSBs of the address are arranged as follows: 2897 // bank | pipe | group 2898 // 2899 // To get the pipe number, shift off the group bits and mask the pipe bits. 2900 // 2901 2902 // R800 2903 // The LSBs of the address are arranged as follows: 2904 // bank | bankInterleave | pipe | pipeInterleave 2905 // 2906 // To get the pipe number, shift off the pipe interleave bits and mask the pipe bits. 2907 // 2908 2909 pipe = static_cast<UINT_32>(addr >> Log2(groupBytes)) & (numPipes - 1); 2910 2911 return pipe; 2912 } 2913 2914 /** 2915 *************************************************************************************************** 2916 * AddrLib::ComputePixelIndexWithinMicroTile 2917 * 2918 * @brief 2919 * Compute the pixel index inside a micro tile of surface 2920 * 2921 * @return 2922 * Pixel index 2923 * 2924 *************************************************************************************************** 2925 */ 2926 UINT_32 AddrLib::ComputePixelIndexWithinMicroTile( 2927 UINT_32 x, ///< [in] x coord 2928 UINT_32 y, ///< [in] y coord 2929 UINT_32 z, ///< [in] slice/depth index 2930 UINT_32 bpp, ///< [in] bits per pixel 2931 AddrTileMode tileMode, ///< [in] tile mode 2932 AddrTileType microTileType ///< [in] pixel order in display/non-display mode 2933 ) const 2934 { 2935 UINT_32 pixelBit0 = 0; 2936 UINT_32 pixelBit1 = 0; 2937 UINT_32 pixelBit2 = 0; 2938 UINT_32 pixelBit3 = 0; 2939 UINT_32 pixelBit4 = 0; 2940 UINT_32 pixelBit5 = 0; 2941 UINT_32 pixelBit6 = 0; 2942 UINT_32 pixelBit7 = 0; 2943 UINT_32 pixelBit8 = 0; 2944 UINT_32 pixelNumber; 2945 2946 UINT_32 x0 = _BIT(x, 0); 2947 UINT_32 x1 = _BIT(x, 1); 2948 UINT_32 x2 = _BIT(x, 2); 2949 UINT_32 y0 = _BIT(y, 0); 2950 UINT_32 y1 = _BIT(y, 1); 2951 UINT_32 y2 = _BIT(y, 2); 2952 UINT_32 z0 = _BIT(z, 0); 2953 UINT_32 z1 = _BIT(z, 1); 2954 UINT_32 z2 = _BIT(z, 2); 2955 2956 UINT_32 thickness = ComputeSurfaceThickness(tileMode); 2957 2958 // Compute the pixel number within the micro tile. 2959 2960 if (microTileType != ADDR_THICK) 2961 { 2962 if (microTileType == ADDR_DISPLAYABLE) 2963 { 2964 switch (bpp) 2965 { 2966 case 8: 2967 pixelBit0 = x0; 2968 pixelBit1 = x1; 2969 pixelBit2 = x2; 2970 pixelBit3 = y1; 2971 pixelBit4 = y0; 2972 pixelBit5 = y2; 2973 break; 2974 case 16: 2975 pixelBit0 = x0; 2976 pixelBit1 = x1; 2977 pixelBit2 = x2; 2978 pixelBit3 = y0; 2979 pixelBit4 = y1; 2980 pixelBit5 = y2; 2981 break; 2982 case 32: 2983 pixelBit0 = x0; 2984 pixelBit1 = x1; 2985 pixelBit2 = y0; 2986 pixelBit3 = x2; 2987 pixelBit4 = y1; 2988 pixelBit5 = y2; 2989 break; 2990 case 64: 2991 pixelBit0 = x0; 2992 pixelBit1 = y0; 2993 pixelBit2 = x1; 2994 pixelBit3 = x2; 2995 pixelBit4 = y1; 2996 pixelBit5 = y2; 2997 break; 2998 case 128: 2999 pixelBit0 = y0; 3000 pixelBit1 = x0; 3001 pixelBit2 = x1; 3002 pixelBit3 = x2; 3003 pixelBit4 = y1; 3004 pixelBit5 = y2; 3005 break; 3006 default: 3007 ADDR_ASSERT_ALWAYS(); 3008 break; 3009 } 3010 } 3011 else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER) 3012 { 3013 pixelBit0 = x0; 3014 pixelBit1 = y0; 3015 pixelBit2 = x1; 3016 pixelBit3 = y1; 3017 pixelBit4 = x2; 3018 pixelBit5 = y2; 3019 } 3020 else if (microTileType == ADDR_ROTATED) 3021 { 3022 ADDR_ASSERT(thickness == 1); 3023 3024 switch (bpp) 3025 { 3026 case 8: 3027 pixelBit0 = y0; 3028 pixelBit1 = y1; 3029 pixelBit2 = y2; 3030 pixelBit3 = x1; 3031 pixelBit4 = x0; 3032 pixelBit5 = x2; 3033 break; 3034 case 16: 3035 pixelBit0 = y0; 3036 pixelBit1 = y1; 3037 pixelBit2 = y2; 3038 pixelBit3 = x0; 3039 pixelBit4 = x1; 3040 pixelBit5 = x2; 3041 break; 3042 case 32: 3043 pixelBit0 = y0; 3044 pixelBit1 = y1; 3045 pixelBit2 = x0; 3046 pixelBit3 = y2; 3047 pixelBit4 = x1; 3048 pixelBit5 = x2; 3049 break; 3050 case 64: 3051 pixelBit0 = y0; 3052 pixelBit1 = x0; 3053 pixelBit2 = y1; 3054 pixelBit3 = x1; 3055 pixelBit4 = x2; 3056 pixelBit5 = y2; 3057 break; 3058 default: 3059 ADDR_ASSERT_ALWAYS(); 3060 break; 3061 } 3062 } 3063 3064 if (thickness > 1) 3065 { 3066 pixelBit6 = z0; 3067 pixelBit7 = z1; 3068 } 3069 } 3070 else // ADDR_THICK 3071 { 3072 ADDR_ASSERT(thickness > 1); 3073 3074 switch (bpp) 3075 { 3076 case 8: 3077 case 16: 3078 pixelBit0 = x0; 3079 pixelBit1 = y0; 3080 pixelBit2 = x1; 3081 pixelBit3 = y1; 3082 pixelBit4 = z0; 3083 pixelBit5 = z1; 3084 break; 3085 case 32: 3086 pixelBit0 = x0; 3087 pixelBit1 = y0; 3088 pixelBit2 = x1; 3089 pixelBit3 = z0; 3090 pixelBit4 = y1; 3091 pixelBit5 = z1; 3092 break; 3093 case 64: 3094 case 128: 3095 pixelBit0 = y0; 3096 pixelBit1 = x0; 3097 pixelBit2 = z0; 3098 pixelBit3 = x1; 3099 pixelBit4 = y1; 3100 pixelBit5 = z1; 3101 break; 3102 default: 3103 ADDR_ASSERT_ALWAYS(); 3104 break; 3105 } 3106 3107 pixelBit6 = x2; 3108 pixelBit7 = y2; 3109 } 3110 3111 if (thickness == 8) 3112 { 3113 pixelBit8 = z2; 3114 } 3115 3116 pixelNumber = ((pixelBit0 ) | 3117 (pixelBit1 << 1) | 3118 (pixelBit2 << 2) | 3119 (pixelBit3 << 3) | 3120 (pixelBit4 << 4) | 3121 (pixelBit5 << 5) | 3122 (pixelBit6 << 6) | 3123 (pixelBit7 << 7) | 3124 (pixelBit8 << 8)); 3125 3126 return pixelNumber; 3127 } 3128 3129 /** 3130 *************************************************************************************************** 3131 * AddrLib::AdjustPitchAlignment 3132 * 3133 * @brief 3134 * Adjusts pitch alignment for flipping surface 3135 * 3136 * @return 3137 * N/A 3138 * 3139 *************************************************************************************************** 3140 */ 3141 VOID AddrLib::AdjustPitchAlignment( 3142 ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags 3143 UINT_32* pPitchAlign ///< [out] Pointer to pitch alignment 3144 ) const 3145 { 3146 // Display engine hardwires lower 5 bit of GRPH_PITCH to ZERO which means 32 pixel alignment 3147 // Maybe it will be fixed in future but let's make it general for now. 3148 if (flags.display || flags.overlay) 3149 { 3150 *pPitchAlign = PowTwoAlign(*pPitchAlign, 32); 3151 3152 if(flags.display) 3153 { 3154 *pPitchAlign = Max(m_minPitchAlignPixels, *pPitchAlign); 3155 } 3156 } 3157 } 3158 3159 /** 3160 *************************************************************************************************** 3161 * AddrLib::PadDimensions 3162 * 3163 * @brief 3164 * Helper function to pad dimensions 3165 * 3166 * @return 3167 * N/A 3168 * 3169 *************************************************************************************************** 3170 */ 3171 VOID AddrLib::PadDimensions( 3172 AddrTileMode tileMode, ///< [in] tile mode 3173 UINT_32 bpp, ///< [in] bits per pixel 3174 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags 3175 UINT_32 numSamples, ///< [in] number of samples 3176 ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure. 3177 UINT_32 padDims, ///< [in] Dimensions to pad valid value 1,2,3 3178 UINT_32 mipLevel, ///< [in] MipLevel 3179 UINT_32* pPitch, ///< [in/out] pitch in pixels 3180 UINT_32 pitchAlign, ///< [in] pitch alignment 3181 UINT_32* pHeight, ///< [in/out] height in pixels 3182 UINT_32 heightAlign, ///< [in] height alignment 3183 UINT_32* pSlices, ///< [in/out] number of slices 3184 UINT_32 sliceAlign ///< [in] number of slice alignment 3185 ) const 3186 { 3187 UINT_32 thickness = ComputeSurfaceThickness(tileMode); 3188 3189 ADDR_ASSERT(padDims <= 3); 3190 3191 // 3192 // Override padding for mip levels 3193 // 3194 if (mipLevel > 0) 3195 { 3196 if (flags.cube) 3197 { 3198 // for cubemap, we only pad when client call with 6 faces as an identity 3199 if (*pSlices > 1) 3200 { 3201 padDims = 3; // we should pad cubemap sub levels when we treat it as 3d texture 3202 } 3203 else 3204 { 3205 padDims = 2; 3206 } 3207 } 3208 } 3209 3210 // Any possibilities that padDims is 0? 3211 if (padDims == 0) 3212 { 3213 padDims = 3; 3214 } 3215 3216 if (IsPow2(pitchAlign)) 3217 { 3218 *pPitch = PowTwoAlign((*pPitch), pitchAlign); 3219 } 3220 else // add this code to pass unit test, r600 linear mode is not align bpp to pow2 for linear 3221 { 3222 *pPitch += pitchAlign - 1; 3223 *pPitch /= pitchAlign; 3224 *pPitch *= pitchAlign; 3225 } 3226 3227 if (padDims > 1) 3228 { 3229 *pHeight = PowTwoAlign((*pHeight), heightAlign); 3230 } 3231 3232 if (padDims > 2 || thickness > 1) 3233 { 3234 // for cubemap single face, we do not pad slices. 3235 // if we pad it, the slice number should be set to 6 and current mip level > 1 3236 if (flags.cube && (!m_configFlags.noCubeMipSlicesPad || flags.cubeAsArray)) 3237 { 3238 *pSlices = NextPow2(*pSlices); 3239 } 3240 3241 // normal 3D texture or arrays or cubemap has a thick mode? (Just pass unit test) 3242 if (thickness > 1) 3243 { 3244 *pSlices = PowTwoAlign((*pSlices), sliceAlign); 3245 } 3246 3247 } 3248 3249 HwlPadDimensions(tileMode, 3250 bpp, 3251 flags, 3252 numSamples, 3253 pTileInfo, 3254 padDims, 3255 mipLevel, 3256 pPitch, 3257 pitchAlign, 3258 pHeight, 3259 heightAlign, 3260 pSlices, 3261 sliceAlign); 3262 } 3263 3264 3265 /** 3266 *************************************************************************************************** 3267 * AddrLib::HwlPreHandleBaseLvl3xPitch 3268 * 3269 * @brief 3270 * Pre-handler of 3x pitch (96 bit) adjustment 3271 * 3272 * @return 3273 * Expected pitch 3274 *************************************************************************************************** 3275 */ 3276 UINT_32 AddrLib::HwlPreHandleBaseLvl3xPitch( 3277 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input 3278 UINT_32 expPitch ///< [in] pitch 3279 ) const 3280 { 3281 ADDR_ASSERT(pIn->width == expPitch); 3282 // 3283 // If pitch is pre-multiplied by 3, we retrieve original one here to get correct miplevel size 3284 // 3285 if (AddrElemLib::IsExpand3x(pIn->format) && 3286 pIn->mipLevel == 0 && 3287 pIn->tileMode == ADDR_TM_LINEAR_ALIGNED) 3288 { 3289 expPitch /= 3; 3290 expPitch = NextPow2(expPitch); 3291 } 3292 3293 return expPitch; 3294 } 3295 3296 /** 3297 *************************************************************************************************** 3298 * AddrLib::HwlPostHandleBaseLvl3xPitch 3299 * 3300 * @brief 3301 * Post-handler of 3x pitch adjustment 3302 * 3303 * @return 3304 * Expected pitch 3305 *************************************************************************************************** 3306 */ 3307 UINT_32 AddrLib::HwlPostHandleBaseLvl3xPitch( 3308 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input 3309 UINT_32 expPitch ///< [in] pitch 3310 ) const 3311 { 3312 // 3313 // 96 bits surface of sub levels require element pitch of 32 bits instead 3314 // So we just return pitch in 32 bit pixels without timing 3 3315 // 3316 if (AddrElemLib::IsExpand3x(pIn->format) && 3317 pIn->mipLevel == 0 && 3318 pIn->tileMode == ADDR_TM_LINEAR_ALIGNED) 3319 { 3320 expPitch *= 3; 3321 } 3322 3323 return expPitch; 3324 } 3325 3326 3327 /** 3328 *************************************************************************************************** 3329 * AddrLib::IsMacroTiled 3330 * 3331 * @brief 3332 * Check if the tile mode is macro tiled 3333 * 3334 * @return 3335 * TRUE if it is macro tiled (2D/2B/3D/3B) 3336 *************************************************************************************************** 3337 */ 3338 BOOL_32 AddrLib::IsMacroTiled( 3339 AddrTileMode tileMode) ///< [in] tile mode 3340 { 3341 return m_modeFlags[tileMode].isMacro; 3342 } 3343 3344 /** 3345 *************************************************************************************************** 3346 * AddrLib::IsMacro3dTiled 3347 * 3348 * @brief 3349 * Check if the tile mode is 3D macro tiled 3350 * 3351 * @return 3352 * TRUE if it is 3D macro tiled 3353 *************************************************************************************************** 3354 */ 3355 BOOL_32 AddrLib::IsMacro3dTiled( 3356 AddrTileMode tileMode) ///< [in] tile mode 3357 { 3358 return m_modeFlags[tileMode].isMacro3d; 3359 } 3360 3361 /** 3362 *************************************************************************************************** 3363 * AddrLib::IsMicroTiled 3364 * 3365 * @brief 3366 * Check if the tile mode is micro tiled 3367 * 3368 * @return 3369 * TRUE if micro tiled 3370 *************************************************************************************************** 3371 */ 3372 BOOL_32 AddrLib::IsMicroTiled( 3373 AddrTileMode tileMode) ///< [in] tile mode 3374 { 3375 return m_modeFlags[tileMode].isMicro; 3376 } 3377 3378 /** 3379 *************************************************************************************************** 3380 * AddrLib::IsLinear 3381 * 3382 * @brief 3383 * Check if the tile mode is linear 3384 * 3385 * @return 3386 * TRUE if linear 3387 *************************************************************************************************** 3388 */ 3389 BOOL_32 AddrLib::IsLinear( 3390 AddrTileMode tileMode) ///< [in] tile mode 3391 { 3392 return m_modeFlags[tileMode].isLinear; 3393 } 3394 3395 /** 3396 *************************************************************************************************** 3397 * AddrLib::IsPrtNoRotationTileMode 3398 * 3399 * @brief 3400 * Return TRUE if it is prt tile without rotation 3401 * @note 3402 * This function just used by CI 3403 *************************************************************************************************** 3404 */ 3405 BOOL_32 AddrLib::IsPrtNoRotationTileMode( 3406 AddrTileMode tileMode) 3407 { 3408 return m_modeFlags[tileMode].isPrtNoRotation; 3409 } 3410 3411 /** 3412 *************************************************************************************************** 3413 * AddrLib::IsPrtTileMode 3414 * 3415 * @brief 3416 * Return TRUE if it is prt tile 3417 * @note 3418 * This function just used by CI 3419 *************************************************************************************************** 3420 */ 3421 BOOL_32 AddrLib::IsPrtTileMode( 3422 AddrTileMode tileMode) 3423 { 3424 return m_modeFlags[tileMode].isPrt; 3425 } 3426 3427 /** 3428 *************************************************************************************************** 3429 * AddrLib::Bits2Number 3430 * 3431 * @brief 3432 * Cat a array of binary bit to a number 3433 * 3434 * @return 3435 * The number combined with the array of bits 3436 *************************************************************************************************** 3437 */ 3438 UINT_32 AddrLib::Bits2Number( 3439 UINT_32 bitNum, ///< [in] how many bits 3440 ...) ///< [in] varaible bits value starting from MSB 3441 { 3442 UINT_32 number = 0; 3443 UINT_32 i; 3444 va_list bits_ptr; 3445 3446 va_start(bits_ptr, bitNum); 3447 3448 for(i = 0; i < bitNum; i++) 3449 { 3450 number |= va_arg(bits_ptr, UINT_32); 3451 number <<= 1; 3452 } 3453 3454 number>>=1; 3455 3456 va_end(bits_ptr); 3457 3458 return number; 3459 } 3460 3461 /** 3462 *************************************************************************************************** 3463 * AddrLib::ComputeMipLevel 3464 * 3465 * @brief 3466 * Compute mipmap level width/height/slices 3467 * @return 3468 * N/A 3469 *************************************************************************************************** 3470 */ 3471 VOID AddrLib::ComputeMipLevel( 3472 ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure 3473 ) const 3474 { 3475 if (AddrElemLib::IsBlockCompressed(pIn->format)) 3476 { 3477 if (pIn->mipLevel == 0) 3478 { 3479 // DXTn's level 0 must be multiple of 4 3480 // But there are exceptions: 3481 // 1. Internal surface creation in hostblt/vsblt/etc... 3482 // 2. Runtime doesn't reject ATI1/ATI2 whose width/height are not multiple of 4 3483 pIn->width = PowTwoAlign(pIn->width, 4); 3484 pIn->height = PowTwoAlign(pIn->height, 4); 3485 } 3486 } 3487 3488 HwlComputeMipLevel(pIn); 3489 } 3490 3491 /** 3492 *************************************************************************************************** 3493 * AddrLib::DegradeBaseLevel 3494 * 3495 * @brief 3496 * Check if base level's tile mode can be degraded 3497 * @return 3498 * TRUE if degraded, also returns degraded tile mode (unchanged if not degraded) 3499 *************************************************************************************************** 3500 */ 3501 BOOL_32 AddrLib::DegradeBaseLevel( 3502 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure for surface info 3503 AddrTileMode* pTileMode ///< [out] Degraded tile mode 3504 ) const 3505 { 3506 BOOL_32 degraded = FALSE; 3507 AddrTileMode tileMode = pIn->tileMode; 3508 UINT_32 thickness = ComputeSurfaceThickness(tileMode); 3509 3510 if (m_configFlags.degradeBaseLevel) // This is a global setting 3511 { 3512 if (pIn->flags.degrade4Space && // Degradation per surface 3513 pIn->mipLevel == 0 && 3514 pIn->numSamples == 1 && 3515 IsMacroTiled(tileMode)) 3516 { 3517 if (HwlDegradeBaseLevel(pIn)) 3518 { 3519 *pTileMode = thickness == 1 ? ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK; 3520 degraded = TRUE; 3521 } 3522 else if (thickness > 1) 3523 { 3524 // As in the following HwlComputeSurfaceInfo, thick modes may be degraded to 3525 // thinner modes, we should re-evaluate whether the corresponding thinner modes 3526 // need to be degraded. If so, we choose 1D thick mode instead. 3527 tileMode = DegradeLargeThickTile(pIn->tileMode, pIn->bpp); 3528 if (tileMode != pIn->tileMode) 3529 { 3530 ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pIn; 3531 input.tileMode = tileMode; 3532 if (HwlDegradeBaseLevel(&input)) 3533 { 3534 *pTileMode = ADDR_TM_1D_TILED_THICK; 3535 degraded = TRUE; 3536 } 3537 } 3538 } 3539 } 3540 } 3541 3542 return degraded; 3543 } 3544 3545 /** 3546 *************************************************************************************************** 3547 * AddrLib::DegradeLargeThickTile 3548 * 3549 * @brief 3550 * Check if the thickness needs to be reduced if a tile is too large 3551 * @return 3552 * The degraded tile mode (unchanged if not degraded) 3553 *************************************************************************************************** 3554 */ 3555 AddrTileMode AddrLib::DegradeLargeThickTile( 3556 AddrTileMode tileMode, 3557 UINT_32 bpp) const 3558 { 3559 // Override tilemode 3560 // When tile_width (8) * tile_height (8) * thickness * element_bytes is > row_size, 3561 // it is better to just use THIN mode in this case 3562 UINT_32 thickness = ComputeSurfaceThickness(tileMode); 3563 3564 if (thickness > 1 && m_configFlags.allowLargeThickTile == 0) 3565 { 3566 UINT_32 tileSize = MicroTilePixels * thickness * (bpp >> 3); 3567 3568 if (tileSize > m_rowSize) 3569 { 3570 switch (tileMode) 3571 { 3572 case ADDR_TM_2D_TILED_XTHICK: 3573 if ((tileSize >> 1) <= m_rowSize) 3574 { 3575 tileMode = ADDR_TM_2D_TILED_THICK; 3576 break; 3577 } 3578 // else fall through 3579 case ADDR_TM_2D_TILED_THICK: 3580 tileMode = ADDR_TM_2D_TILED_THIN1; 3581 break; 3582 3583 case ADDR_TM_3D_TILED_XTHICK: 3584 if ((tileSize >> 1) <= m_rowSize) 3585 { 3586 tileMode = ADDR_TM_3D_TILED_THICK; 3587 break; 3588 } 3589 // else fall through 3590 case ADDR_TM_3D_TILED_THICK: 3591 tileMode = ADDR_TM_3D_TILED_THIN1; 3592 break; 3593 3594 case ADDR_TM_PRT_TILED_THICK: 3595 tileMode = ADDR_TM_PRT_TILED_THIN1; 3596 break; 3597 3598 case ADDR_TM_PRT_2D_TILED_THICK: 3599 tileMode = ADDR_TM_PRT_2D_TILED_THIN1; 3600 break; 3601 3602 case ADDR_TM_PRT_3D_TILED_THICK: 3603 tileMode = ADDR_TM_PRT_3D_TILED_THIN1; 3604 break; 3605 3606 default: 3607 break; 3608 } 3609 } 3610 } 3611 3612 return tileMode; 3613 } 3614 3615 /** 3616 *************************************************************************************************** 3617 * AddrLib::PostComputeMipLevel 3618 * @brief 3619 * Compute MipLevel info (including level 0) after surface adjustment 3620 * @return 3621 * ADDR_E_RETURNCODE 3622 *************************************************************************************************** 3623 */ 3624 ADDR_E_RETURNCODE AddrLib::PostComputeMipLevel( 3625 ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in/out] Input structure 3626 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output structure 3627 ) const 3628 { 3629 // Mipmap including level 0 must be pow2 padded since either SI hw expects so or it is 3630 // required by CFX for Hw Compatibility between NI and SI. Otherwise it is only needed for 3631 // mipLevel > 0. Any h/w has different requirement should implement its own virtual function 3632 3633 if (pIn->flags.pow2Pad) 3634 { 3635 pIn->width = NextPow2(pIn->width); 3636 pIn->height = NextPow2(pIn->height); 3637 pIn->numSlices = NextPow2(pIn->numSlices); 3638 } 3639 else if (pIn->mipLevel > 0) 3640 { 3641 pIn->width = NextPow2(pIn->width); 3642 pIn->height = NextPow2(pIn->height); 3643 3644 if (!pIn->flags.cube) 3645 { 3646 pIn->numSlices = NextPow2(pIn->numSlices); 3647 } 3648 3649 // for cubemap, we keep its value at first 3650 } 3651 3652 return ADDR_OK; 3653 } 3654 3655 /** 3656 *************************************************************************************************** 3657 * AddrLib::HwlSetupTileCfg 3658 * 3659 * @brief 3660 * Map tile index to tile setting. 3661 * @return 3662 * ADDR_E_RETURNCODE 3663 *************************************************************************************************** 3664 */ 3665 ADDR_E_RETURNCODE AddrLib::HwlSetupTileCfg( 3666 INT_32 index, ///< [in] Tile index 3667 INT_32 macroModeIndex, ///< [in] Index in macro tile mode table(CI) 3668 ADDR_TILEINFO* pInfo, ///< [out] Tile Info 3669 AddrTileMode* pMode, ///< [out] Tile mode 3670 AddrTileType* pType ///< [out] Tile type 3671 ) const 3672 { 3673 return ADDR_NOTSUPPORTED; 3674 } 3675 3676 /** 3677 *************************************************************************************************** 3678 * AddrLib::HwlGetPipes 3679 * 3680 * @brief 3681 * Get number pipes 3682 * @return 3683 * num pipes 3684 *************************************************************************************************** 3685 */ 3686 UINT_32 AddrLib::HwlGetPipes( 3687 const ADDR_TILEINFO* pTileInfo ///< [in] Tile info 3688 ) const 3689 { 3690 //pTileInfo can be NULL when asic is 6xx and 8xx. 3691 return m_pipes; 3692 } 3693 3694 /** 3695 *************************************************************************************************** 3696 * AddrLib::ComputeQbStereoInfo 3697 * 3698 * @brief 3699 * Get quad buffer stereo information 3700 * @return 3701 * TRUE if no error 3702 *************************************************************************************************** 3703 */ 3704 BOOL_32 AddrLib::ComputeQbStereoInfo( 3705 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] updated pOut+pStereoInfo 3706 ) const 3707 { 3708 BOOL_32 success = FALSE; 3709 3710 if (pOut->pStereoInfo) 3711 { 3712 ADDR_ASSERT(pOut->bpp >= 8); 3713 ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0); 3714 3715 // Save original height 3716 pOut->pStereoInfo->eyeHeight = pOut->height; 3717 3718 // Right offset 3719 pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize); 3720 3721 pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut); 3722 // Double height 3723 pOut->height <<= 1; 3724 pOut->pixelHeight <<= 1; 3725 3726 // Double size 3727 pOut->surfSize <<= 1; 3728 3729 // Right start address meets the base align since it is guaranteed by AddrLib 3730 3731 // 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo. 3732 success = TRUE; 3733 } 3734 3735 return success; 3736 } 3737 3738 /////////////////////////////////////////////////////////////////////////////////////////////////// 3739 // Element lib 3740 /////////////////////////////////////////////////////////////////////////////////////////////////// 3741 3742 3743 /** 3744 *************************************************************************************************** 3745 * AddrLib::Flt32ToColorPixel 3746 * 3747 * @brief 3748 * Convert a FLT_32 value to a depth/stencil pixel value 3749 * @return 3750 * ADDR_E_RETURNCODE 3751 *************************************************************************************************** 3752 */ 3753 ADDR_E_RETURNCODE AddrLib::Flt32ToDepthPixel( 3754 const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn, 3755 ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const 3756 { 3757 ADDR_E_RETURNCODE returnCode = ADDR_OK; 3758 3759 if (GetFillSizeFieldsFlags() == TRUE) 3760 { 3761 if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) || 3762 (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT))) 3763 { 3764 returnCode = ADDR_PARAMSIZEMISMATCH; 3765 } 3766 } 3767 3768 if (returnCode == ADDR_OK) 3769 { 3770 GetElemLib()->Flt32ToDepthPixel(pIn->format, 3771 pIn->comps, 3772 pOut->pPixel); 3773 UINT_32 depthBase = 0; 3774 UINT_32 stencilBase = 0; 3775 UINT_32 depthBits = 0; 3776 UINT_32 stencilBits = 0; 3777 3778 switch (pIn->format) 3779 { 3780 case ADDR_DEPTH_16: 3781 depthBits = 16; 3782 break; 3783 case ADDR_DEPTH_X8_24: 3784 case ADDR_DEPTH_8_24: 3785 case ADDR_DEPTH_X8_24_FLOAT: 3786 case ADDR_DEPTH_8_24_FLOAT: 3787 depthBase = 8; 3788 depthBits = 24; 3789 stencilBits = 8; 3790 break; 3791 case ADDR_DEPTH_32_FLOAT: 3792 depthBits = 32; 3793 break; 3794 case ADDR_DEPTH_X24_8_32_FLOAT: 3795 depthBase = 8; 3796 depthBits = 32; 3797 stencilBits = 8; 3798 break; 3799 default: 3800 break; 3801 } 3802 3803 // Overwrite base since R800 has no "tileBase" 3804 if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE) 3805 { 3806 depthBase = 0; 3807 stencilBase = 0; 3808 } 3809 3810 depthBase *= 64; 3811 stencilBase *= 64; 3812 3813 pOut->stencilBase = stencilBase; 3814 pOut->depthBase = depthBase; 3815 pOut->depthBits = depthBits; 3816 pOut->stencilBits = stencilBits; 3817 } 3818 3819 return returnCode; 3820 } 3821 3822 /** 3823 *************************************************************************************************** 3824 * AddrLib::Flt32ToColorPixel 3825 * 3826 * @brief 3827 * Convert a FLT_32 value to a red/green/blue/alpha pixel value 3828 * @return 3829 * ADDR_E_RETURNCODE 3830 *************************************************************************************************** 3831 */ 3832 ADDR_E_RETURNCODE AddrLib::Flt32ToColorPixel( 3833 const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn, 3834 ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const 3835 { 3836 ADDR_E_RETURNCODE returnCode = ADDR_OK; 3837 3838 if (GetFillSizeFieldsFlags() == TRUE) 3839 { 3840 if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) || 3841 (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT))) 3842 { 3843 returnCode = ADDR_PARAMSIZEMISMATCH; 3844 } 3845 } 3846 3847 if (returnCode == ADDR_OK) 3848 { 3849 GetElemLib()->Flt32ToColorPixel(pIn->format, 3850 pIn->surfNum, 3851 pIn->surfSwap, 3852 pIn->comps, 3853 pOut->pPixel); 3854 } 3855 3856 return returnCode; 3857 } 3858 3859 3860 /** 3861 *************************************************************************************************** 3862 * AddrLib::GetExportNorm 3863 * 3864 * @brief 3865 * Check one format can be EXPORT_NUM 3866 * @return 3867 * TRUE if EXPORT_NORM can be used 3868 *************************************************************************************************** 3869 */ 3870 BOOL_32 AddrLib::GetExportNorm( 3871 const ELEM_GETEXPORTNORM_INPUT* pIn) const 3872 { 3873 ADDR_E_RETURNCODE returnCode = ADDR_OK; 3874 3875 BOOL_32 enabled = FALSE; 3876 3877 if (GetFillSizeFieldsFlags() == TRUE) 3878 { 3879 if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT)) 3880 { 3881 returnCode = ADDR_PARAMSIZEMISMATCH; 3882 } 3883 } 3884 3885 if (returnCode == ADDR_OK) 3886 { 3887 enabled = GetElemLib()->PixGetExportNorm(pIn->format, 3888 pIn->num, 3889 pIn->swap); 3890 } 3891 3892 return enabled; 3893 } 3894 3895 /** 3896 *************************************************************************************************** 3897 * AddrLib::ComputePrtInfo 3898 * 3899 * @brief 3900 * Compute prt surface related info 3901 * 3902 * @return 3903 * ADDR_E_RETURNCODE 3904 *************************************************************************************************** 3905 */ 3906 ADDR_E_RETURNCODE AddrLib::ComputePrtInfo( 3907 const ADDR_PRT_INFO_INPUT* pIn, 3908 ADDR_PRT_INFO_OUTPUT* pOut) const 3909 { 3910 ADDR_ASSERT(pOut != NULL); 3911 3912 ADDR_E_RETURNCODE returnCode = ADDR_OK; 3913 3914 UINT_32 expandX = 1; 3915 UINT_32 expandY = 1; 3916 AddrElemMode elemMode; 3917 3918 UINT_32 bpp = GetElemLib()->GetBitsPerPixel(pIn->format, 3919 &elemMode, 3920 &expandX, 3921 &expandY); 3922 3923 if (bpp <8 || bpp == 24 || bpp == 48 || bpp == 96 ) 3924 { 3925 returnCode = ADDR_INVALIDPARAMS; 3926 } 3927 3928 UINT_32 numFrags = pIn->numFrags; 3929 ADDR_ASSERT(numFrags <= 8); 3930 3931 UINT_32 tileWidth = 0; 3932 UINT_32 tileHeight = 0; 3933 if (returnCode == ADDR_OK) 3934 { 3935 // 3D texture without depth or 2d texture 3936 if (pIn->baseMipDepth > 1 || pIn->baseMipHeight > 1) 3937 { 3938 if (bpp == 8) 3939 { 3940 tileWidth = 256; 3941 tileHeight = 256; 3942 } 3943 else if (bpp == 16) 3944 { 3945 tileWidth = 256; 3946 tileHeight = 128; 3947 } 3948 else if (bpp == 32) 3949 { 3950 tileWidth = 128; 3951 tileHeight = 128; 3952 } 3953 else if (bpp == 64) 3954 { 3955 // assume it is BC1/4 3956 tileWidth = 512; 3957 tileHeight = 256; 3958 3959 if (elemMode == ADDR_UNCOMPRESSED) 3960 { 3961 tileWidth = 128; 3962 tileHeight = 64; 3963 } 3964 } 3965 else if (bpp == 128) 3966 { 3967 // assume it is BC2/3/5/6H/7 3968 tileWidth = 256; 3969 tileHeight = 256; 3970 3971 if (elemMode == ADDR_UNCOMPRESSED) 3972 { 3973 tileWidth = 64; 3974 tileHeight = 64; 3975 } 3976 } 3977 3978 if (numFrags == 2) 3979 { 3980 tileWidth = tileWidth / 2; 3981 } 3982 else if (numFrags == 4) 3983 { 3984 tileWidth = tileWidth / 2; 3985 tileHeight = tileHeight / 2; 3986 } 3987 else if (numFrags == 8) 3988 { 3989 tileWidth = tileWidth / 4; 3990 tileHeight = tileHeight / 2; 3991 } 3992 } 3993 else // 1d 3994 { 3995 tileHeight = 1; 3996 if (bpp == 8) 3997 { 3998 tileWidth = 65536; 3999 } 4000 else if (bpp == 16) 4001 { 4002 tileWidth = 32768; 4003 } 4004 else if (bpp == 32) 4005 { 4006 tileWidth = 16384; 4007 } 4008 else if (bpp == 64) 4009 { 4010 tileWidth = 8192; 4011 } 4012 else if (bpp == 128) 4013 { 4014 tileWidth = 4096; 4015 } 4016 } 4017 } 4018 4019 pOut->prtTileWidth = tileWidth; 4020 pOut->prtTileHeight = tileHeight; 4021 4022 return returnCode; 4023 } 4024