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