Home | History | Annotate | Download | only in core
      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(&macroWidth,
   1851                                                &macroHeight,
   1852                                                bpp,
   1853                                                pTileInfo);
   1854     }
   1855     else
   1856     {
   1857         ComputeTileDataWidthAndHeight(bpp,
   1858                                       cacheBits,
   1859                                       pTileInfo,
   1860                                       &macroWidth,
   1861                                       &macroHeight);
   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(&macroWidth,
   1989                                                &macroHeight,
   1990                                                bpp,
   1991                                                pTileInfo);
   1992     }
   1993     else
   1994     {
   1995         ComputeTileDataWidthAndHeight(bpp,
   1996                                       cacheBits,
   1997                                       pTileInfo,
   1998                                       &macroWidth,
   1999                                       &macroHeight);
   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                          &macroTilePitch,
   2253                          &macroTileHeight);
   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                          &macroTilePitch,
   2278                          &macroTileHeight);
   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                          &macroTileWidth,
   2433                          &macroTileHeight);
   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                          &macroTileWidth,
   2453                          &macroTileHeight,
   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                                                          &macroWidthAlign,
   3627                                                          &macroHeightAlign,
   3628                                                          &macroSizeAlign);
   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                                                                          &macroWidthAlign,
   3672                                                                          &macroHeightAlign,
   3673                                                                          &macroSizeAlign);
   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