/* * Copyright © 2014 Advanced Micro Devices, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. */ /** *************************************************************************************************** * @file addrlib.cpp * @brief Contains the implementation for the AddrLib base class.. *************************************************************************************************** */ #include "addrinterface.h" #include "addrlib.h" #include "addrcommon.h" #if defined(__APPLE__) UINT_32 div64_32(UINT_64 n, UINT_32 base) { UINT_64 rem = n; UINT_64 b = base; UINT_64 res, d = 1; UINT_32 high = rem >> 32; res = 0; if (high >= base) { high /= base; res = (UINT_64) high << 32; rem -= (UINT_64) (high*base) << 32; } while ((INT_64)b > 0 && b < rem) { b = b+b; d = d+d; } do { if (rem >= b) { rem -= b; res += d; } b >>= 1; d >>= 1; } while (d); n = res; return rem; } extern "C" UINT_32 __umoddi3(UINT_64 n, UINT_32 base) { return div64_32(n, base); } #endif // __APPLE__ /////////////////////////////////////////////////////////////////////////////////////////////////// // Static Const Member /////////////////////////////////////////////////////////////////////////////////////////////////// const AddrTileModeFlags AddrLib::m_modeFlags[ADDR_TM_COUNT] = {// T L 1 2 3 P Pr B {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_GENERAL {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_ALIGNED {1, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THIN1 {4, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THICK {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN1 {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN2 {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN4 {4, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THICK {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN1 {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN2 {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN4 {4, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THICK {1, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THIN1 {4, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THICK {1, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THIN1 {4, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THICK {8, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_XTHICK {8, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_XTHICK {1, 0, 0, 0, 0, 0, 0, 0}, // ADDR_TM_POWER_SAVE {1, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THIN1 {1, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THIN1 {1, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THIN1 {4, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THICK {4, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THICK {4, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THICK }; /////////////////////////////////////////////////////////////////////////////////////////////////// // Constructor/Destructor /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::AddrLib * * @brief * Constructor for the AddrLib class * *************************************************************************************************** */ AddrLib::AddrLib() : m_class(BASE_ADDRLIB), m_chipFamily(ADDR_CHIP_FAMILY_IVLD), m_chipRevision(0), m_version(ADDRLIB_VERSION), m_pipes(0), m_banks(0), m_pipeInterleaveBytes(0), m_rowSize(0), m_minPitchAlignPixels(1), m_maxSamples(8), m_pElemLib(NULL) { m_configFlags.value = 0; } /** *************************************************************************************************** * AddrLib::AddrLib * * @brief * Constructor for the AddrLib class with hClient as parameter * *************************************************************************************************** */ AddrLib::AddrLib(const AddrClient* pClient) : AddrObject(pClient), m_class(BASE_ADDRLIB), m_chipFamily(ADDR_CHIP_FAMILY_IVLD), m_chipRevision(0), m_version(ADDRLIB_VERSION), m_pipes(0), m_banks(0), m_pipeInterleaveBytes(0), m_rowSize(0), m_minPitchAlignPixels(1), m_maxSamples(8), m_pElemLib(NULL) { m_configFlags.value = 0; } /** *************************************************************************************************** * AddrLib::~AddrLib * * @brief * Destructor for the AddrLib class * *************************************************************************************************** */ AddrLib::~AddrLib() { if (m_pElemLib) { delete m_pElemLib; } } /////////////////////////////////////////////////////////////////////////////////////////////////// // Initialization/Helper /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::Create * * @brief * Creates and initializes AddrLib object. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::Create( const ADDR_CREATE_INPUT* pCreateIn, ///< [in] pointer to ADDR_CREATE_INPUT ADDR_CREATE_OUTPUT* pCreateOut) ///< [out] pointer to ADDR_CREATE_OUTPUT { AddrLib* pLib = NULL; ADDR_E_RETURNCODE returnCode = ADDR_OK; if (pCreateIn->createFlags.fillSizeFields == TRUE) { if ((pCreateIn->size != sizeof(ADDR_CREATE_INPUT)) || (pCreateOut->size != sizeof(ADDR_CREATE_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if ((returnCode == ADDR_OK) && (pCreateIn->callbacks.allocSysMem != NULL) && (pCreateIn->callbacks.freeSysMem != NULL)) { AddrClient client = { pCreateIn->hClient, pCreateIn->callbacks }; switch (pCreateIn->chipEngine) { case CIASICIDGFXENGINE_SOUTHERNISLAND: switch (pCreateIn->chipFamily) { case FAMILY_SI: pLib = AddrSIHwlInit(&client); break; case FAMILY_VI: case FAMILY_CZ: // VI based fusion(carrizo) case FAMILY_CI: case FAMILY_KV: // CI based fusion pLib = AddrCIHwlInit(&client); break; default: ADDR_ASSERT_ALWAYS(); break; } break; default: ADDR_ASSERT_ALWAYS(); break; } } if ((pLib != NULL)) { BOOL_32 initValid; // Pass createFlags to configFlags first since these flags may be overwritten pLib->m_configFlags.noCubeMipSlicesPad = pCreateIn->createFlags.noCubeMipSlicesPad; pLib->m_configFlags.fillSizeFields = pCreateIn->createFlags.fillSizeFields; pLib->m_configFlags.useTileIndex = pCreateIn->createFlags.useTileIndex; pLib->m_configFlags.useCombinedSwizzle = pCreateIn->createFlags.useCombinedSwizzle; pLib->m_configFlags.checkLast2DLevel = pCreateIn->createFlags.checkLast2DLevel; pLib->m_configFlags.useHtileSliceAlign = pCreateIn->createFlags.useHtileSliceAlign; pLib->m_configFlags.degradeBaseLevel = pCreateIn->createFlags.degradeBaseLevel; pLib->m_configFlags.allowLargeThickTile = pCreateIn->createFlags.allowLargeThickTile; pLib->SetAddrChipFamily(pCreateIn->chipFamily, pCreateIn->chipRevision); pLib->SetMinPitchAlignPixels(pCreateIn->minPitchAlignPixels); // Global parameters initialized and remaining configFlags bits are set as well initValid = pLib->HwlInitGlobalParams(pCreateIn); if (initValid) { pLib->m_pElemLib = AddrElemLib::Create(pLib); } else { pLib->m_pElemLib = NULL; // Don't go on allocating element lib returnCode = ADDR_INVALIDGBREGVALUES; } if (pLib->m_pElemLib == NULL) { delete pLib; pLib = NULL; ADDR_ASSERT_ALWAYS(); } else { pLib->m_pElemLib->SetConfigFlags(pLib->m_configFlags); } } pCreateOut->hLib = pLib; if ((pLib == NULL) && (returnCode == ADDR_OK)) { // Unknown failures, we return the general error code returnCode = ADDR_ERROR; } return returnCode; } /** *************************************************************************************************** * AddrLib::SetAddrChipFamily * * @brief * Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision * @return * N/A *************************************************************************************************** */ VOID AddrLib::SetAddrChipFamily( UINT_32 uChipFamily, ///< [in] chip family defined in atiih.h UINT_32 uChipRevision) ///< [in] chip revision defined in "asic_family"_id.h { AddrChipFamily family = ADDR_CHIP_FAMILY_IVLD; family = HwlConvertChipFamily(uChipFamily, uChipRevision); ADDR_ASSERT(family != ADDR_CHIP_FAMILY_IVLD); m_chipFamily = family; m_chipRevision = uChipRevision; } /** *************************************************************************************************** * AddrLib::SetMinPitchAlignPixels * * @brief * Set m_minPitchAlignPixels with input param * * @return * N/A *************************************************************************************************** */ VOID AddrLib::SetMinPitchAlignPixels( UINT_32 minPitchAlignPixels) ///< [in] minmum pitch alignment in pixels { m_minPitchAlignPixels = (minPitchAlignPixels == 0)? 1 : minPitchAlignPixels; } /** *************************************************************************************************** * AddrLib::GetAddrLib * * @brief * Get AddrLib pointer * * @return * An AddrLib class pointer *************************************************************************************************** */ AddrLib * AddrLib::GetAddrLib( ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE { return static_cast<AddrLib *>(hLib); } /////////////////////////////////////////////////////////////////////////////////////////////////// // Surface Methods /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::ComputeSurfaceInfo * * @brief * Interface function stub of AddrComputeSurfaceInfo. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeSurfaceInfo( const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } // We suggest client do sanity check but a check here is also good if (pIn->bpp > 128) { returnCode = ADDR_INVALIDPARAMS; } // Thick modes don't support multisample if (ComputeSurfaceThickness(pIn->tileMode) > 1 && pIn->numSamples > 1) { returnCode = ADDR_INVALIDPARAMS; } if (returnCode == ADDR_OK) { // Get a local copy of input structure and only reference pIn for unadjusted values ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn; ADDR_TILEINFO tileInfoNull = {0}; if (UseTileInfo()) { // If the original input has a valid ADDR_TILEINFO pointer then copy its contents. // Otherwise the default 0's in tileInfoNull are used. if (pIn->pTileInfo) { tileInfoNull = *pIn->pTileInfo; } localIn.pTileInfo = &tileInfoNull; } localIn.numSamples = pIn->numSamples == 0 ? 1 : pIn->numSamples; // Do mipmap check first // If format is BCn, pre-pad dimension to power-of-two according to HWL ComputeMipLevel(&localIn); if (m_configFlags.checkLast2DLevel) { // Save this level's original height in pixels pOut->height = pIn->height; } UINT_32 expandX = 1; UINT_32 expandY = 1; AddrElemMode elemMode; // Save outputs that may not go through HWL pOut->pixelBits = localIn.bpp; pOut->numSamples = localIn.numSamples; pOut->last2DLevel = FALSE; #if !ALT_TEST if (localIn.numSamples > 1) { ADDR_ASSERT(localIn.mipLevel == 0); } #endif if (localIn.format != ADDR_FMT_INVALID) // Set format to INVALID will skip this conversion { // Get compression/expansion factors and element mode // (which indicates compression/expansion localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format, &elemMode, &expandX, &expandY); // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear- // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw // restrictions are different. // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround // but we use this flag to skip RestoreSurfaceInfo below if ((elemMode == ADDR_EXPANDED) && (expandX > 1)) { ADDR_ASSERT(localIn.tileMode == ADDR_TM_LINEAR_ALIGNED || localIn.height == 1); } GetElemLib()->AdjustSurfaceInfo(elemMode, expandX, expandY, &localIn.bpp, &localIn.basePitch, &localIn.width, &localIn.height); // Overwrite these parameters if we have a valid format } else if (localIn.bpp != 0) { localIn.width = (localIn.width != 0) ? localIn.width : 1; localIn.height = (localIn.height != 0) ? localIn.height : 1; } else // Rule out some invalid parameters { ADDR_ASSERT_ALWAYS(); returnCode = ADDR_INVALIDPARAMS; } // Check mipmap after surface expansion if (returnCode == ADDR_OK) { returnCode = PostComputeMipLevel(&localIn, pOut); } if (returnCode == ADDR_OK) { if (UseTileIndex(localIn.tileIndex)) { // Make sure pTileInfo is not NULL ADDR_ASSERT(localIn.pTileInfo); UINT_32 numSamples = GetNumFragments(localIn.numSamples, localIn.numFrags); INT_32 macroModeIndex = TileIndexNoMacroIndex; if (localIn.tileIndex != TileIndexLinearGeneral) { // Try finding a macroModeIndex macroModeIndex = HwlComputeMacroModeIndex(localIn.tileIndex, localIn.flags, localIn.bpp, numSamples, localIn.pTileInfo, &localIn.tileMode, &localIn.tileType); } // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info if (macroModeIndex == TileIndexNoMacroIndex) { returnCode = HwlSetupTileCfg(localIn.tileIndex, macroModeIndex, localIn.pTileInfo, &localIn.tileMode, &localIn.tileType); } // If macroModeIndex is invalid, then assert this is not macro tiled else if (macroModeIndex == TileIndexInvalid) { ADDR_ASSERT(!IsMacroTiled(localIn.tileMode)); } } } if (returnCode == ADDR_OK) { AddrTileMode tileMode = localIn.tileMode; AddrTileType tileType = localIn.tileType; // HWL layer may override tile mode if necessary if (HwlOverrideTileMode(&localIn, &tileMode, &tileType)) { localIn.tileMode = tileMode; localIn.tileType = tileType; } // Degrade base level if applicable if (DegradeBaseLevel(&localIn, &tileMode)) { localIn.tileMode = tileMode; } } // Call main function to compute surface info if (returnCode == ADDR_OK) { returnCode = HwlComputeSurfaceInfo(&localIn, pOut); } if (returnCode == ADDR_OK) { // Since bpp might be changed we just pass it through pOut->bpp = localIn.bpp; // Also original width/height/bpp pOut->pixelPitch = pOut->pitch; pOut->pixelHeight = pOut->height; #if DEBUG if (localIn.flags.display) { ADDR_ASSERT((pOut->pitchAlign % 32) == 0); } #endif //DEBUG if (localIn.format != ADDR_FMT_INVALID) { // // 96 bits surface of level 1+ requires element pitch of 32 bits instead // In hwl function we skip multiplication of 3 then we should skip division of 3 // We keep pitch that represents 32 bit element instead of 96 bits since we // will get an odd number if divided by 3. // if (!((expandX == 3) && (localIn.mipLevel > 0))) { GetElemLib()->RestoreSurfaceInfo(elemMode, expandX, expandY, &localIn.bpp, &pOut->pixelPitch, &pOut->pixelHeight); } } if (localIn.flags.qbStereo) { if (pOut->pStereoInfo) { ComputeQbStereoInfo(pOut); } } if (localIn.flags.volume) // For volume sliceSize equals to all z-slices { pOut->sliceSize = pOut->surfSize; } else // For array: sliceSize is likely to have slice-padding (the last one) { pOut->sliceSize = pOut->surfSize / pOut->depth; // array or cubemap if (pIn->numSlices > 1) { // If this is the last slice then add the padding size to this slice if (pIn->slice == (pIn->numSlices - 1)) { pOut->sliceSize += pOut->sliceSize * (pOut->depth - pIn->numSlices); } else if (m_configFlags.checkLast2DLevel) { // Reset last2DLevel flag if this is not the last array slice pOut->last2DLevel = FALSE; } } } pOut->pitchTileMax = pOut->pitch / 8 - 1; pOut->heightTileMax = pOut->height / 8 - 1; pOut->sliceTileMax = pOut->pitch * pOut->height / 64 - 1; } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeSurfaceInfo * * @brief * Interface function stub of AddrComputeSurfaceInfo. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeSurfaceAddrFromCoord( const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; const ADDR_SURFACE_FLAGS flags = {{0}}; UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags); // Try finding a macroModeIndex INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex, flags, input.bpp, numSamples, input.pTileInfo, &input.tileMode, &input.tileType); // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info if (macroModeIndex == TileIndexNoMacroIndex) { returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, input.pTileInfo, &input.tileMode, &input.tileType); } // If macroModeIndex is invalid, then assert this is not macro tiled else if (macroModeIndex == TileIndexInvalid) { ADDR_ASSERT(!IsMacroTiled(input.tileMode)); } // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlComputeSurfaceAddrFromCoord(pIn, pOut); if (returnCode == ADDR_OK) { pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024)); } } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeSurfaceCoordFromAddr * * @brief * Interface function stub of ComputeSurfaceCoordFromAddr. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeSurfaceCoordFromAddr( const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; const ADDR_SURFACE_FLAGS flags = {{0}}; UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags); // Try finding a macroModeIndex INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex, flags, input.bpp, numSamples, input.pTileInfo, &input.tileMode, &input.tileType); // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info if (macroModeIndex == TileIndexNoMacroIndex) { returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, input.pTileInfo, &input.tileMode, &input.tileType); } // If macroModeIndex is invalid, then assert this is not macro tiled else if (macroModeIndex == TileIndexInvalid) { ADDR_ASSERT(!IsMacroTiled(input.tileMode)); } // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlComputeSurfaceCoordFromAddr(pIn, pOut); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeSliceTileSwizzle * * @brief * Interface function stub of ComputeSliceTileSwizzle. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeSliceTileSwizzle( const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_SLICESWIZZLE_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo, &input.tileMode); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlComputeSliceTileSwizzle(pIn, pOut); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ExtractBankPipeSwizzle * * @brief * Interface function stub of AddrExtractBankPipeSwizzle. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ExtractBankPipeSwizzle( const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT)) || (pOut->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlExtractBankPipeSwizzle(pIn, pOut); } } return returnCode; } /** *************************************************************************************************** * AddrLib::CombineBankPipeSwizzle * * @brief * Interface function stub of AddrCombineBankPipeSwizzle. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::CombineBankPipeSwizzle( const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlCombineBankPipeSwizzle(pIn->bankSwizzle, pIn->pipeSwizzle, pIn->pTileInfo, pIn->baseAddr, &pOut->tileSwizzle); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeBaseSwizzle * * @brief * Interface function stub of AddrCompueBaseSwizzle. * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeBaseSwizzle( const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_BASE_SWIZZLE_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { if (IsMacroTiled(pIn->tileMode)) { returnCode = HwlComputeBaseSwizzle(pIn, pOut); } else { pOut->tileSwizzle = 0; } } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeFmaskInfo * * @brief * Interface function stub of ComputeFmaskInfo. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeFmaskInfo( const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure ) { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } // No thick MSAA if (ComputeSurfaceThickness(pIn->tileMode) > 1) { returnCode = ADDR_INVALIDPARAMS; } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_FMASK_INFO_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; if (pOut->pTileInfo) { // Use temp tile info for calcalation input.pTileInfo = pOut->pTileInfo; } else { input.pTileInfo = &tileInfoNull; } ADDR_SURFACE_FLAGS flags = {{0}}; flags.fmask = 1; // Try finding a macroModeIndex INT_32 macroModeIndex = HwlComputeMacroModeIndex(pIn->tileIndex, flags, HwlComputeFmaskBits(pIn, NULL), pIn->numSamples, input.pTileInfo, &input.tileMode); // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info if (macroModeIndex == TileIndexNoMacroIndex) { returnCode = HwlSetupTileCfg(input.tileIndex, macroModeIndex, input.pTileInfo, &input.tileMode); } ADDR_ASSERT(macroModeIndex != TileIndexInvalid); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { if (pIn->numSamples > 1) { returnCode = HwlComputeFmaskInfo(pIn, pOut); } else { memset(pOut, 0, sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)); returnCode = ADDR_INVALIDPARAMS; } } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeFmaskAddrFromCoord * * @brief * Interface function stub of ComputeFmaskAddrFromCoord. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeFmaskAddrFromCoord( const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_ASSERT(pIn->numSamples > 1); if (pIn->numSamples > 1) { returnCode = HwlComputeFmaskAddrFromCoord(pIn, pOut); } else { returnCode = ADDR_INVALIDPARAMS; } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeFmaskCoordFromAddr * * @brief * Interface function stub of ComputeFmaskAddrFromCoord. * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeFmaskCoordFromAddr( const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_ASSERT(pIn->numSamples > 1); if (pIn->numSamples > 1) { returnCode = HwlComputeFmaskCoordFromAddr(pIn, pOut); } else { returnCode = ADDR_INVALIDPARAMS; } } return returnCode; } /** *************************************************************************************************** * AddrLib::ConvertTileInfoToHW * * @brief * Convert tile info from real value to HW register value in HW layer * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ConvertTileInfoToHW( const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT)) || (pOut->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_CONVERT_TILEINFOTOHW_INPUT input; // if pIn->reverse is TRUE, indices are ignored if (pIn->reverse == FALSE && UseTileIndex(pIn->tileIndex)) { input = *pIn; input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); pIn = &input; } if (returnCode == ADDR_OK) { returnCode = HwlConvertTileInfoToHW(pIn, pOut); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ConvertTileIndex * * @brief * Convert tile index to tile mode/type/info * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ConvertTileIndex( const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ///< [in] input structure ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX_INPUT)) || (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { returnCode = HwlSetupTileCfg(pIn->tileIndex, pIn->macroModeIndex, pOut->pTileInfo, &pOut->tileMode, &pOut->tileType); if (returnCode == ADDR_OK && pIn->tileInfoHw) { ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0}; ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0}; hwInput.pTileInfo = pOut->pTileInfo; hwInput.tileIndex = -1; hwOutput.pTileInfo = pOut->pTileInfo; returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ConvertTileIndex1 * * @brief * Convert tile index to tile mode/type/info * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ConvertTileIndex1( const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ///< [in] input structure ADDR_CONVERT_TILEINDEX_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX1_INPUT)) || (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_SURFACE_FLAGS flags = {{0}}; HwlComputeMacroModeIndex(pIn->tileIndex, flags, pIn->bpp, pIn->numSamples, pOut->pTileInfo, &pOut->tileMode, &pOut->tileType); if (pIn->tileInfoHw) { ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0}; ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0}; hwInput.pTileInfo = pOut->pTileInfo; hwInput.tileIndex = -1; hwOutput.pTileInfo = pOut->pTileInfo; returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput); } } return returnCode; } /** *************************************************************************************************** * AddrLib::GetTileIndex * * @brief * Get tile index from tile mode/type/info * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::GetTileIndex( const ADDR_GET_TILEINDEX_INPUT* pIn, ///< [in] input structure ADDR_GET_TILEINDEX_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_GET_TILEINDEX_INPUT)) || (pOut->size != sizeof(ADDR_GET_TILEINDEX_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { returnCode = HwlGetTileIndex(pIn, pOut); } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeSurfaceThickness * * @brief * Compute surface thickness * * @return * Surface thickness *************************************************************************************************** */ UINT_32 AddrLib::ComputeSurfaceThickness( AddrTileMode tileMode) ///< [in] tile mode { return m_modeFlags[tileMode].thickness; } /////////////////////////////////////////////////////////////////////////////////////////////////// // CMASK/HTILE /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::ComputeHtileInfo * * @brief * Interface function stub of AddrComputeHtilenfo * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeHtileInfo( const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_HTILE_INFO_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { pOut->bpp = ComputeHtileInfo(pIn->flags, pIn->pitch, pIn->height, pIn->numSlices, pIn->isLinear, isWidth8, isHeight8, pIn->pTileInfo, &pOut->pitch, &pOut->height, &pOut->htileBytes, &pOut->macroWidth, &pOut->macroHeight, &pOut->sliceSize, &pOut->baseAlign); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeCmaskInfo * * @brief * Interface function stub of AddrComputeCmaskInfo * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeCmaskInfo( const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_INFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_CMASK_INFO_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_CMASK_INFO_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { returnCode = ComputeCmaskInfo(pIn->flags, pIn->pitch, pIn->height, pIn->numSlices, pIn->isLinear, pIn->pTileInfo, &pOut->pitch, &pOut->height, &pOut->cmaskBytes, &pOut->macroWidth, &pOut->macroHeight, &pOut->sliceSize, &pOut->baseAlign, &pOut->blockMax); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeDccInfo * * @brief * Interface function to compute DCC key info * * @return * return code of HwlComputeDccInfo *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeDccInfo( const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_DCCINFO_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE ret = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_DCCINFO_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT))) { ret = ADDR_PARAMSIZEMISMATCH; } } if (ret == ADDR_OK) { ADDR_COMPUTE_DCCINFO_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; ret = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, &input.tileInfo, &input.tileMode); pIn = &input; } if (ADDR_OK == ret) { ret = HwlComputeDccInfo(pIn, pOut); } } return ret; } /** *************************************************************************************************** * AddrLib::ComputeHtileAddrFromCoord * * @brief * Interface function stub of AddrComputeHtileAddrFromCoord * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeHtileAddrFromCoord( const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch, pIn->height, pIn->x, pIn->y, pIn->slice, pIn->numSlices, 1, pIn->isLinear, isWidth8, isHeight8, pIn->pTileInfo, &pOut->bitPosition); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeHtileCoordFromAddr * * @brief * Interface function stub of AddrComputeHtileCoordFromAddr * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeHtileCoordFromAddr( const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; BOOL_32 isWidth8 = (pIn->blockWidth == 8) ? TRUE : FALSE; BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { HwlComputeXmaskCoordFromAddr(pIn->addr, pIn->bitPosition, pIn->pitch, pIn->height, pIn->numSlices, 1, pIn->isLinear, isWidth8, isHeight8, pIn->pTileInfo, &pOut->x, &pOut->y, &pOut->slice); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeCmaskAddrFromCoord * * @brief * Interface function stub of AddrComputeCmaskAddrFromCoord * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeCmaskAddrFromCoord( const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { if (pIn->flags.tcCompatible == TRUE) { returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut); } else { pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch, pIn->height, pIn->x, pIn->y, pIn->slice, pIn->numSlices, 2, pIn->isLinear, FALSE, //this is cmask, isWidth8 is not needed FALSE, //this is cmask, isHeight8 is not needed pIn->pTileInfo, &pOut->bitPosition); } } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeCmaskCoordFromAddr * * @brief * Interface function stub of AddrComputeCmaskCoordFromAddr * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeCmaskCoordFromAddr( const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT)) || (pOut->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { ADDR_TILEINFO tileInfoNull; ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT input; if (UseTileIndex(pIn->tileIndex)) { input = *pIn; // Use temp tile info for calcalation input.pTileInfo = &tileInfoNull; returnCode = HwlSetupTileCfg(input.tileIndex, input.macroModeIndex, input.pTileInfo); // Change the input structure pIn = &input; } if (returnCode == ADDR_OK) { HwlComputeXmaskCoordFromAddr(pIn->addr, pIn->bitPosition, pIn->pitch, pIn->height, pIn->numSlices, 2, pIn->isLinear, FALSE, FALSE, pIn->pTileInfo, &pOut->x, &pOut->y, &pOut->slice); } } return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeTileDataWidthAndHeight * * @brief * Compute the squared cache shape for per-tile data (CMASK and HTILE) * * @return * N/A * * @note * MacroWidth and macroHeight are measured in pixels *************************************************************************************************** */ VOID AddrLib::ComputeTileDataWidthAndHeight( UINT_32 bpp, ///< [in] bits per pixel UINT_32 cacheBits, ///< [in] bits of cache ADDR_TILEINFO* pTileInfo, ///< [in] Tile info UINT_32* pMacroWidth, ///< [out] macro tile width UINT_32* pMacroHeight ///< [out] macro tile height ) const { UINT_32 height = 1; UINT_32 width = cacheBits / bpp; UINT_32 pipes = HwlGetPipes(pTileInfo); // Double height until the macro-tile is close to square // Height can only be doubled if width is even while ((width > height * 2 * pipes) && !(width & 1)) { width /= 2; height *= 2; } *pMacroWidth = 8 * width; *pMacroHeight = 8 * height * pipes; // Note: The above iterative comptuation is equivalent to the following // //int log2_height = ((log2(cacheBits)-log2(bpp)-log2(pipes))/2); //int macroHeight = pow2( 3+log2(pipes)+log2_height ); } /** *************************************************************************************************** * AddrLib::HwlComputeTileDataWidthAndHeightLinear * * @brief * Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout * * @return * N/A * * @note * MacroWidth and macroHeight are measured in pixels *************************************************************************************************** */ VOID AddrLib::HwlComputeTileDataWidthAndHeightLinear( UINT_32* pMacroWidth, ///< [out] macro tile width UINT_32* pMacroHeight, ///< [out] macro tile height UINT_32 bpp, ///< [in] bits per pixel ADDR_TILEINFO* pTileInfo ///< [in] tile info ) const { ADDR_ASSERT(bpp != 4); // Cmask does not support linear layout prior to SI *pMacroWidth = 8 * 512 / bpp; // Align width to 512-bit memory accesses *pMacroHeight = 8 * m_pipes; // Align height to number of pipes } /** *************************************************************************************************** * AddrLib::ComputeHtileInfo * * @brief * Compute htile pitch,width, bytes per 2D slice * * @return * Htile bpp i.e. How many bits for an 8x8 tile * Also returns by output parameters: * *Htile pitch, height, total size in bytes, macro-tile dimensions and slice size* *************************************************************************************************** */ UINT_32 AddrLib::ComputeHtileInfo( ADDR_HTILE_FLAGS flags, ///< [in] htile flags UINT_32 pitchIn, ///< [in] pitch input UINT_32 heightIn, ///< [in] height input UINT_32 numSlices, ///< [in] number of slices BOOL_32 isLinear, ///< [in] if it is linear mode BOOL_32 isWidth8, ///< [in] if htile block width is 8 BOOL_32 isHeight8, ///< [in] if htile block height is 8 ADDR_TILEINFO* pTileInfo, ///< [in] Tile info UINT_32* pPitchOut, ///< [out] pitch output UINT_32* pHeightOut, ///< [out] height output UINT_64* pHtileBytes, ///< [out] bytes per 2D slice UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels UINT_64* pSliceSize, ///< [out] slice size in bytes UINT_32* pBaseAlign ///< [out] base alignment ) const { UINT_32 macroWidth; UINT_32 macroHeight; UINT_32 baseAlign; UINT_64 surfBytes; UINT_64 sliceBytes; numSlices = Max(1u, numSlices); const UINT_32 bpp = HwlComputeHtileBpp(isWidth8, isHeight8); const UINT_32 cacheBits = HtileCacheBits; if (isLinear) { HwlComputeTileDataWidthAndHeightLinear(¯oWidth, ¯oHeight, bpp, pTileInfo); } else { ComputeTileDataWidthAndHeight(bpp, cacheBits, pTileInfo, ¯oWidth, ¯oHeight); } *pPitchOut = PowTwoAlign(pitchIn, macroWidth); *pHeightOut = PowTwoAlign(heightIn, macroHeight); baseAlign = HwlComputeHtileBaseAlign(flags.tcCompatible, isLinear, pTileInfo); surfBytes = HwlComputeHtileBytes(*pPitchOut, *pHeightOut, bpp, isLinear, numSlices, &sliceBytes, baseAlign); *pHtileBytes = surfBytes; // // Use SafeAssign since they are optional // SafeAssign(pMacroWidth, macroWidth); SafeAssign(pMacroHeight, macroHeight); SafeAssign(pSliceSize, sliceBytes); SafeAssign(pBaseAlign, baseAlign); return bpp; } /** *************************************************************************************************** * AddrLib::ComputeCmaskBaseAlign * * @brief * Compute cmask base alignment * * @return * Cmask base alignment *************************************************************************************************** */ UINT_32 AddrLib::ComputeCmaskBaseAlign( ADDR_CMASK_FLAGS flags, ///< [in] Cmask flags ADDR_TILEINFO* pTileInfo ///< [in] Tile info ) const { UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo); if (flags.tcCompatible) { ADDR_ASSERT(pTileInfo != NULL); if (pTileInfo) { baseAlign *= pTileInfo->banks; } } return baseAlign; } /** *************************************************************************************************** * AddrLib::ComputeCmaskBytes * * @brief * Compute cmask size in bytes * * @return * Cmask size in bytes *************************************************************************************************** */ UINT_64 AddrLib::ComputeCmaskBytes( UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 numSlices ///< [in] number of slices ) const { return BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * numSlices * CmaskElemBits) / MicroTilePixels; } /** *************************************************************************************************** * AddrLib::ComputeCmaskInfo * * @brief * Compute cmask pitch,width, bytes per 2D slice * * @return * BlockMax. Also by output parameters: Cmask pitch,height, total size in bytes, * macro-tile dimensions *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputeCmaskInfo( ADDR_CMASK_FLAGS flags, ///< [in] cmask flags UINT_32 pitchIn, ///< [in] pitch input UINT_32 heightIn, ///< [in] height input UINT_32 numSlices, ///< [in] number of slices BOOL_32 isLinear, ///< [in] is linear mode ADDR_TILEINFO* pTileInfo, ///< [in] Tile info UINT_32* pPitchOut, ///< [out] pitch output UINT_32* pHeightOut, ///< [out] height output UINT_64* pCmaskBytes, ///< [out] bytes per 2D slice UINT_32* pMacroWidth, ///< [out] macro-tile width in pixels UINT_32* pMacroHeight, ///< [out] macro-tile width in pixels UINT_64* pSliceSize, ///< [out] slice size in bytes UINT_32* pBaseAlign, ///< [out] base alignment UINT_32* pBlockMax ///< [out] block max == slice / 128 / 128 - 1 ) const { UINT_32 macroWidth; UINT_32 macroHeight; UINT_32 baseAlign; UINT_64 surfBytes; UINT_64 sliceBytes; numSlices = Max(1u, numSlices); const UINT_32 bpp = CmaskElemBits; const UINT_32 cacheBits = CmaskCacheBits; ADDR_E_RETURNCODE returnCode = ADDR_OK; if (isLinear) { HwlComputeTileDataWidthAndHeightLinear(¯oWidth, ¯oHeight, bpp, pTileInfo); } else { ComputeTileDataWidthAndHeight(bpp, cacheBits, pTileInfo, ¯oWidth, ¯oHeight); } *pPitchOut = (pitchIn + macroWidth - 1) & ~(macroWidth - 1); *pHeightOut = (heightIn + macroHeight - 1) & ~(macroHeight - 1); sliceBytes = ComputeCmaskBytes(*pPitchOut, *pHeightOut, 1); baseAlign = ComputeCmaskBaseAlign(flags, pTileInfo); while (sliceBytes % baseAlign) { *pHeightOut += macroHeight; sliceBytes = ComputeCmaskBytes(*pPitchOut, *pHeightOut, 1); } surfBytes = sliceBytes * numSlices; *pCmaskBytes = surfBytes; // // Use SafeAssign since they are optional // SafeAssign(pMacroWidth, macroWidth); SafeAssign(pMacroHeight, macroHeight); SafeAssign(pBaseAlign, baseAlign); SafeAssign(pSliceSize, sliceBytes); UINT_32 slice = (*pPitchOut) * (*pHeightOut); UINT_32 blockMax = slice / 128 / 128 - 1; #if DEBUG if (slice % (64*256) != 0) { ADDR_ASSERT_ALWAYS(); } #endif //DEBUG UINT_32 maxBlockMax = HwlGetMaxCmaskBlockMax(); if (blockMax > maxBlockMax) { blockMax = maxBlockMax; returnCode = ADDR_INVALIDPARAMS; } SafeAssign(pBlockMax, blockMax); return returnCode; } /** *************************************************************************************************** * AddrLib::ComputeXmaskCoordYFromPipe * * @brief * Compute the Y coord from pipe number for cmask/htile * * @return * Y coordinate * *************************************************************************************************** */ UINT_32 AddrLib::ComputeXmaskCoordYFromPipe( UINT_32 pipe, ///< [in] pipe number UINT_32 x ///< [in] x coordinate ) const { UINT_32 pipeBit0; UINT_32 pipeBit1; UINT_32 xBit0; UINT_32 xBit1; UINT_32 yBit0; UINT_32 yBit1; UINT_32 y = 0; UINT_32 numPipes = m_pipes; // SI has its implementation // // Convert pipe + x to y coordinate. // switch (numPipes) { case 1: // // 1 pipe // // p0 = 0 // y = 0; break; case 2: // // 2 pipes // // p0 = x0 ^ y0 // // y0 = p0 ^ x0 // pipeBit0 = pipe & 0x1; xBit0 = x & 0x1; yBit0 = pipeBit0 ^ xBit0; y = yBit0; break; case 4: // // 4 pipes // // p0 = x1 ^ y0 // p1 = x0 ^ y1 // // y0 = p0 ^ x1 // y1 = p1 ^ x0 // pipeBit0 = pipe & 0x1; pipeBit1 = (pipe & 0x2) >> 1; xBit0 = x & 0x1; xBit1 = (x & 0x2) >> 1; yBit0 = pipeBit0 ^ xBit1; yBit1 = pipeBit1 ^ xBit0; y = (yBit0 | (yBit1 << 1)); break; case 8: // // 8 pipes // // r600 and r800 have different method // y = HwlComputeXmaskCoordYFrom8Pipe(pipe, x); break; default: break; } return y; } /** *************************************************************************************************** * AddrLib::HwlComputeXmaskCoordFromAddr * * @brief * Compute the coord from an address of a cmask/htile * * @return * N/A * * @note * This method is reused by htile, so rename to Xmask *************************************************************************************************** */ VOID AddrLib::HwlComputeXmaskCoordFromAddr( UINT_64 addr, ///< [in] address UINT_32 bitPosition, ///< [in] bitPosition in a byte UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 numSlices, ///< [in] number of slices UINT_32 factor, ///< [in] factor that indicates cmask or htile BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value ADDR_TILEINFO* pTileInfo, ///< [in] Tile info UINT_32* pX, ///< [out] x coord UINT_32* pY, ///< [out] y coord UINT_32* pSlice ///< [out] slice index ) const { UINT_32 pipe; UINT_32 numPipes; UINT_32 numPipeBits; UINT_32 macroTilePitch; UINT_32 macroTileHeight; UINT_64 bitAddr; UINT_32 microTileCoordY; UINT_32 elemBits; UINT_32 pitchAligned = pitch; UINT_32 heightAligned = height; UINT_64 totalBytes; UINT_64 elemOffset; UINT_64 macroIndex; UINT_32 microIndex; UINT_64 macroNumber; UINT_32 microNumber; UINT_32 macroX; UINT_32 macroY; UINT_32 macroZ; UINT_32 microX; UINT_32 microY; UINT_32 tilesPerMacro; UINT_32 macrosPerPitch; UINT_32 macrosPerSlice; // // Extract pipe. // numPipes = HwlGetPipes(pTileInfo); pipe = ComputePipeFromAddr(addr, numPipes); // // Compute the number of group and pipe bits. // numPipeBits = Log2(numPipes); UINT_32 groupBits = 8 * m_pipeInterleaveBytes; UINT_32 pipes = numPipes; // // Compute the micro tile size, in bits. And macro tile pitch and height. // if (factor == 2) //CMASK { ADDR_CMASK_FLAGS flags = {{0}}; elemBits = CmaskElemBits; ComputeCmaskInfo(flags, pitch, height, numSlices, isLinear, pTileInfo, &pitchAligned, &heightAligned, &totalBytes, ¯oTilePitch, ¯oTileHeight); } else //HTILE { ADDR_HTILE_FLAGS flags = {{0}}; if (factor != 1) { factor = 1; } elemBits = HwlComputeHtileBpp(isWidth8, isHeight8); ComputeHtileInfo(flags, pitch, height, numSlices, isLinear, isWidth8, isHeight8, pTileInfo, &pitchAligned, &heightAligned, &totalBytes, ¯oTilePitch, ¯oTileHeight); } // Should use aligned dims // pitch = pitchAligned; height = heightAligned; // // Convert byte address to bit address. // bitAddr = BYTES_TO_BITS(addr) + bitPosition; // // Remove pipe bits from address. // bitAddr = (bitAddr % groupBits) + ((bitAddr/groupBits/pipes)*groupBits); elemOffset = bitAddr / elemBits; tilesPerMacro = (macroTilePitch/factor) * macroTileHeight / MicroTilePixels >> numPipeBits; macrosPerPitch = pitch / (macroTilePitch/factor); macrosPerSlice = macrosPerPitch * height / macroTileHeight; macroIndex = elemOffset / factor / tilesPerMacro; microIndex = static_cast<UINT_32>(elemOffset % (tilesPerMacro * factor)); macroNumber = macroIndex * factor + microIndex % factor; microNumber = microIndex / factor; macroX = static_cast<UINT_32>((macroNumber % macrosPerPitch)); macroY = static_cast<UINT_32>((macroNumber % macrosPerSlice) / macrosPerPitch); macroZ = static_cast<UINT_32>((macroNumber / macrosPerSlice)); microX = microNumber % (macroTilePitch / factor / MicroTileWidth); microY = (microNumber / (macroTilePitch / factor / MicroTileHeight)); *pX = macroX * (macroTilePitch/factor) + microX * MicroTileWidth; *pY = macroY * macroTileHeight + (microY * MicroTileHeight << numPipeBits); *pSlice = macroZ; microTileCoordY = ComputeXmaskCoordYFromPipe(pipe, *pX/MicroTileWidth); // // Assemble final coordinates. // *pY += microTileCoordY * MicroTileHeight; } /** *************************************************************************************************** * AddrLib::HwlComputeXmaskAddrFromCoord * * @brief * Compute the address from an address of cmask (prior to si) * * @return * Address in bytes * *************************************************************************************************** */ UINT_64 AddrLib::HwlComputeXmaskAddrFromCoord( UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 x, ///< [in] x coord UINT_32 y, ///< [in] y coord UINT_32 slice, ///< [in] slice/depth index UINT_32 numSlices, ///< [in] number of slices UINT_32 factor, ///< [in] factor that indicates cmask(2) or htile(1) BOOL_32 isLinear, ///< [in] linear or tiled HTILE layout BOOL_32 isWidth8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value BOOL_32 isHeight8, ///< [in] TRUE if width is 8, FALSE means 4. It's register value ADDR_TILEINFO* pTileInfo, ///< [in] Tile info UINT_32* pBitPosition ///< [out] bit position inside a byte ) const { UINT_64 addr; UINT_32 numGroupBits; UINT_32 numPipeBits; UINT_32 newPitch = 0; UINT_32 newHeight = 0; UINT_64 sliceBytes = 0; UINT_64 totalBytes = 0; UINT_64 sliceOffset; UINT_32 pipe; UINT_32 macroTileWidth; UINT_32 macroTileHeight; UINT_32 macroTilesPerRow; UINT_32 macroTileBytes; UINT_32 macroTileIndexX; UINT_32 macroTileIndexY; UINT_64 macroTileOffset; UINT_32 pixelBytesPerRow; UINT_32 pixelOffsetX; UINT_32 pixelOffsetY; UINT_32 pixelOffset; UINT_64 totalOffset; UINT_64 offsetLo; UINT_64 offsetHi; UINT_64 groupMask; UINT_32 elemBits = 0; UINT_32 numPipes = m_pipes; // This function is accessed prior to si only if (factor == 2) //CMASK { elemBits = CmaskElemBits; // For asics before SI, cmask is always tiled isLinear = FALSE; } else //HTILE { if (factor != 1) // Fix compile warning { factor = 1; } elemBits = HwlComputeHtileBpp(isWidth8, isHeight8); } // // Compute the number of group bits and pipe bits. // numGroupBits = Log2(m_pipeInterleaveBytes); numPipeBits = Log2(numPipes); // // Compute macro tile dimensions. // if (factor == 2) // CMASK { ADDR_CMASK_FLAGS flags = {{0}}; ComputeCmaskInfo(flags, pitch, height, numSlices, isLinear, pTileInfo, &newPitch, &newHeight, &totalBytes, ¯oTileWidth, ¯oTileHeight); sliceBytes = totalBytes / numSlices; } else // HTILE { ADDR_HTILE_FLAGS flags = {{0}}; ComputeHtileInfo(flags, pitch, height, numSlices, isLinear, isWidth8, isHeight8, pTileInfo, &newPitch, &newHeight, &totalBytes, ¯oTileWidth, ¯oTileHeight, &sliceBytes); } sliceOffset = slice * sliceBytes; // // Get the pipe. Note that neither slice rotation nor pipe swizzling apply for CMASK. // pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo); // // Compute the number of macro tiles per row. // macroTilesPerRow = newPitch / macroTileWidth; // // Compute the number of bytes per macro tile. // macroTileBytes = BITS_TO_BYTES((macroTileWidth * macroTileHeight * elemBits) / MicroTilePixels); // // Compute the offset to the macro tile containing the specified coordinate. // macroTileIndexX = x / macroTileWidth; macroTileIndexY = y / macroTileHeight; macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes; // // Compute the pixel offset within the macro tile. // pixelBytesPerRow = BITS_TO_BYTES(macroTileWidth * elemBits) / MicroTileWidth; // // The nibbles are interleaved (see below), so the part of the offset relative to the x // coordinate repeats halfway across the row. (Not for HTILE) // if (factor == 2) { pixelOffsetX = (x % (macroTileWidth / 2)) / MicroTileWidth; } else { pixelOffsetX = (x % (macroTileWidth)) / MicroTileWidth * BITS_TO_BYTES(elemBits); } // // Compute the y offset within the macro tile. // pixelOffsetY = (((y % macroTileHeight) / MicroTileHeight) / numPipes) * pixelBytesPerRow; pixelOffset = pixelOffsetX + pixelOffsetY; // // Combine the slice offset and macro tile offset with the pixel offset, accounting for the // pipe bits in the middle of the address. // totalOffset = ((sliceOffset + macroTileOffset) >> numPipeBits) + pixelOffset; // // Split the offset to put some bits below the pipe bits and some above. // groupMask = (1 << numGroupBits) - 1; offsetLo = totalOffset & groupMask; offsetHi = (totalOffset & ~groupMask) << numPipeBits; // // Assemble the address from its components. // addr = offsetLo; addr |= offsetHi; // This is to remove warning with /analyze option UINT_32 pipeBits = pipe << numGroupBits; addr |= pipeBits; // // Compute the bit position. The lower nibble is used when the x coordinate within the macro // tile is less than half of the macro tile width, and the upper nibble is used when the x // coordinate within the macro tile is greater than or equal to half the macro tile width. // *pBitPosition = ((x % macroTileWidth) < (macroTileWidth / factor)) ? 0 : 4; return addr; } /////////////////////////////////////////////////////////////////////////////////////////////////// // Surface Addressing Shared /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::ComputeSurfaceAddrFromCoordLinear * * @brief * Compute address from coord for linear surface * * @return * Address in bytes * *************************************************************************************************** */ UINT_64 AddrLib::ComputeSurfaceAddrFromCoordLinear( UINT_32 x, ///< [in] x coord UINT_32 y, ///< [in] y coord UINT_32 slice, ///< [in] slice/depth index UINT_32 sample, ///< [in] sample index UINT_32 bpp, ///< [in] bits per pixel UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 numSlices, ///< [in] number of slices UINT_32* pBitPosition ///< [out] bit position inside a byte ) const { const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height; UINT_64 sliceOffset = (slice + sample * numSlices)* sliceSize; UINT_64 rowOffset = static_cast<UINT_64>(y) * pitch; UINT_64 pixOffset = x; UINT_64 addr = (sliceOffset + rowOffset + pixOffset) * bpp; *pBitPosition = static_cast<UINT_32>(addr % 8); addr /= 8; return addr; } /** *************************************************************************************************** * AddrLib::ComputeSurfaceCoordFromAddrLinear * * @brief * Compute the coord from an address of a linear surface * * @return * N/A *************************************************************************************************** */ VOID AddrLib::ComputeSurfaceCoordFromAddrLinear( UINT_64 addr, ///< [in] address UINT_32 bitPosition, ///< [in] bitPosition in a byte UINT_32 bpp, ///< [in] bits per pixel UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 numSlices, ///< [in] number of slices UINT_32* pX, ///< [out] x coord UINT_32* pY, ///< [out] y coord UINT_32* pSlice, ///< [out] slice/depth index UINT_32* pSample ///< [out] sample index ) const { const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height; const UINT_64 linearOffset = (BYTES_TO_BITS(addr) + bitPosition) / bpp; *pX = static_cast<UINT_32>((linearOffset % sliceSize) % pitch); *pY = static_cast<UINT_32>((linearOffset % sliceSize) / pitch % height); *pSlice = static_cast<UINT_32>((linearOffset / sliceSize) % numSlices); *pSample = static_cast<UINT_32>((linearOffset / sliceSize) / numSlices); } /** *************************************************************************************************** * AddrLib::ComputeSurfaceCoordFromAddrMicroTiled * * @brief * Compute the coord from an address of a micro tiled surface * * @return * N/A *************************************************************************************************** */ VOID AddrLib::ComputeSurfaceCoordFromAddrMicroTiled( UINT_64 addr, ///< [in] address UINT_32 bitPosition, ///< [in] bitPosition in a byte UINT_32 bpp, ///< [in] bits per pixel UINT_32 pitch, ///< [in] pitch UINT_32 height, ///< [in] height UINT_32 numSamples, ///< [in] number of samples AddrTileMode tileMode, ///< [in] tile mode UINT_32 tileBase, ///< [in] base offset within a tile UINT_32 compBits, ///< [in] component bits actually needed(for planar surface) UINT_32* pX, ///< [out] x coord UINT_32* pY, ///< [out] y coord UINT_32* pSlice, ///< [out] slice/depth index UINT_32* pSample, ///< [out] sample index, AddrTileType microTileType, ///< [in] micro tiling order BOOL_32 isDepthSampleOrder ///< [in] TRUE if in depth sample order ) const { UINT_64 bitAddr; UINT_32 microTileThickness; UINT_32 microTileBits; UINT_64 sliceBits; UINT_64 rowBits; UINT_32 sliceIndex; UINT_32 microTileCoordX; UINT_32 microTileCoordY; UINT_32 pixelOffset; UINT_32 pixelCoordX = 0; UINT_32 pixelCoordY = 0; UINT_32 pixelCoordZ = 0; UINT_32 pixelCoordS = 0; // // Convert byte address to bit address. // bitAddr = BYTES_TO_BITS(addr) + bitPosition; // // Compute the micro tile size, in bits. // switch (tileMode) { case ADDR_TM_1D_TILED_THICK: microTileThickness = ThickTileThickness; break; default: microTileThickness = 1; break; } microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples; // // Compute number of bits per slice and number of bits per row of micro tiles. // sliceBits = static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples; rowBits = (pitch / MicroTileWidth) * microTileBits; // // Extract the slice index. // sliceIndex = static_cast<UINT_32>(bitAddr / sliceBits); bitAddr -= sliceIndex * sliceBits; // // Extract the y coordinate of the micro tile. // microTileCoordY = static_cast<UINT_32>(bitAddr / rowBits) * MicroTileHeight; bitAddr -= (microTileCoordY / MicroTileHeight) * rowBits; // // Extract the x coordinate of the micro tile. // microTileCoordX = static_cast<UINT_32>(bitAddr / microTileBits) * MicroTileWidth; // // Compute the pixel offset within the micro tile. // pixelOffset = static_cast<UINT_32>(bitAddr % microTileBits); // // Extract pixel coordinates from the offset. // HwlComputePixelCoordFromOffset(pixelOffset, bpp, numSamples, tileMode, tileBase, compBits, &pixelCoordX, &pixelCoordY, &pixelCoordZ, &pixelCoordS, microTileType, isDepthSampleOrder); // // Assemble final coordinates. // *pX = microTileCoordX + pixelCoordX; *pY = microTileCoordY + pixelCoordY; *pSlice = (sliceIndex * microTileThickness) + pixelCoordZ; *pSample = pixelCoordS; if (microTileThickness > 1) { *pSample = 0; } } /** *************************************************************************************************** * AddrLib::ComputePipeFromAddr * * @brief * Compute the pipe number from an address * * @return * Pipe number * *************************************************************************************************** */ UINT_32 AddrLib::ComputePipeFromAddr( UINT_64 addr, ///< [in] address UINT_32 numPipes ///< [in] number of banks ) const { UINT_32 pipe; UINT_32 groupBytes = m_pipeInterleaveBytes; //just different terms // R600 // The LSBs of the address are arranged as follows: // bank | pipe | group // // To get the pipe number, shift off the group bits and mask the pipe bits. // // R800 // The LSBs of the address are arranged as follows: // bank | bankInterleave | pipe | pipeInterleave // // To get the pipe number, shift off the pipe interleave bits and mask the pipe bits. // pipe = static_cast<UINT_32>(addr >> Log2(groupBytes)) & (numPipes - 1); return pipe; } /** *************************************************************************************************** * AddrLib::ComputePixelIndexWithinMicroTile * * @brief * Compute the pixel index inside a micro tile of surface * * @return * Pixel index * *************************************************************************************************** */ UINT_32 AddrLib::ComputePixelIndexWithinMicroTile( UINT_32 x, ///< [in] x coord UINT_32 y, ///< [in] y coord UINT_32 z, ///< [in] slice/depth index UINT_32 bpp, ///< [in] bits per pixel AddrTileMode tileMode, ///< [in] tile mode AddrTileType microTileType ///< [in] pixel order in display/non-display mode ) const { UINT_32 pixelBit0 = 0; UINT_32 pixelBit1 = 0; UINT_32 pixelBit2 = 0; UINT_32 pixelBit3 = 0; UINT_32 pixelBit4 = 0; UINT_32 pixelBit5 = 0; UINT_32 pixelBit6 = 0; UINT_32 pixelBit7 = 0; UINT_32 pixelBit8 = 0; UINT_32 pixelNumber; UINT_32 x0 = _BIT(x, 0); UINT_32 x1 = _BIT(x, 1); UINT_32 x2 = _BIT(x, 2); UINT_32 y0 = _BIT(y, 0); UINT_32 y1 = _BIT(y, 1); UINT_32 y2 = _BIT(y, 2); UINT_32 z0 = _BIT(z, 0); UINT_32 z1 = _BIT(z, 1); UINT_32 z2 = _BIT(z, 2); UINT_32 thickness = ComputeSurfaceThickness(tileMode); // Compute the pixel number within the micro tile. if (microTileType != ADDR_THICK) { if (microTileType == ADDR_DISPLAYABLE) { switch (bpp) { case 8: pixelBit0 = x0; pixelBit1 = x1; pixelBit2 = x2; pixelBit3 = y1; pixelBit4 = y0; pixelBit5 = y2; break; case 16: pixelBit0 = x0; pixelBit1 = x1; pixelBit2 = x2; pixelBit3 = y0; pixelBit4 = y1; pixelBit5 = y2; break; case 32: pixelBit0 = x0; pixelBit1 = x1; pixelBit2 = y0; pixelBit3 = x2; pixelBit4 = y1; pixelBit5 = y2; break; case 64: pixelBit0 = x0; pixelBit1 = y0; pixelBit2 = x1; pixelBit3 = x2; pixelBit4 = y1; pixelBit5 = y2; break; case 128: pixelBit0 = y0; pixelBit1 = x0; pixelBit2 = x1; pixelBit3 = x2; pixelBit4 = y1; pixelBit5 = y2; break; default: ADDR_ASSERT_ALWAYS(); break; } } else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER) { pixelBit0 = x0; pixelBit1 = y0; pixelBit2 = x1; pixelBit3 = y1; pixelBit4 = x2; pixelBit5 = y2; } else if (microTileType == ADDR_ROTATED) { ADDR_ASSERT(thickness == 1); switch (bpp) { case 8: pixelBit0 = y0; pixelBit1 = y1; pixelBit2 = y2; pixelBit3 = x1; pixelBit4 = x0; pixelBit5 = x2; break; case 16: pixelBit0 = y0; pixelBit1 = y1; pixelBit2 = y2; pixelBit3 = x0; pixelBit4 = x1; pixelBit5 = x2; break; case 32: pixelBit0 = y0; pixelBit1 = y1; pixelBit2 = x0; pixelBit3 = y2; pixelBit4 = x1; pixelBit5 = x2; break; case 64: pixelBit0 = y0; pixelBit1 = x0; pixelBit2 = y1; pixelBit3 = x1; pixelBit4 = x2; pixelBit5 = y2; break; default: ADDR_ASSERT_ALWAYS(); break; } } if (thickness > 1) { pixelBit6 = z0; pixelBit7 = z1; } } else // ADDR_THICK { ADDR_ASSERT(thickness > 1); switch (bpp) { case 8: case 16: pixelBit0 = x0; pixelBit1 = y0; pixelBit2 = x1; pixelBit3 = y1; pixelBit4 = z0; pixelBit5 = z1; break; case 32: pixelBit0 = x0; pixelBit1 = y0; pixelBit2 = x1; pixelBit3 = z0; pixelBit4 = y1; pixelBit5 = z1; break; case 64: case 128: pixelBit0 = y0; pixelBit1 = x0; pixelBit2 = z0; pixelBit3 = x1; pixelBit4 = y1; pixelBit5 = z1; break; default: ADDR_ASSERT_ALWAYS(); break; } pixelBit6 = x2; pixelBit7 = y2; } if (thickness == 8) { pixelBit8 = z2; } pixelNumber = ((pixelBit0 ) | (pixelBit1 << 1) | (pixelBit2 << 2) | (pixelBit3 << 3) | (pixelBit4 << 4) | (pixelBit5 << 5) | (pixelBit6 << 6) | (pixelBit7 << 7) | (pixelBit8 << 8)); return pixelNumber; } /** *************************************************************************************************** * AddrLib::AdjustPitchAlignment * * @brief * Adjusts pitch alignment for flipping surface * * @return * N/A * *************************************************************************************************** */ VOID AddrLib::AdjustPitchAlignment( ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags UINT_32* pPitchAlign ///< [out] Pointer to pitch alignment ) const { // Display engine hardwires lower 5 bit of GRPH_PITCH to ZERO which means 32 pixel alignment // Maybe it will be fixed in future but let's make it general for now. if (flags.display || flags.overlay) { *pPitchAlign = PowTwoAlign(*pPitchAlign, 32); if(flags.display) { *pPitchAlign = Max(m_minPitchAlignPixels, *pPitchAlign); } } } /** *************************************************************************************************** * AddrLib::PadDimensions * * @brief * Helper function to pad dimensions * * @return * N/A * *************************************************************************************************** */ VOID AddrLib::PadDimensions( AddrTileMode tileMode, ///< [in] tile mode UINT_32 bpp, ///< [in] bits per pixel ADDR_SURFACE_FLAGS flags, ///< [in] surface flags UINT_32 numSamples, ///< [in] number of samples ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure. UINT_32 padDims, ///< [in] Dimensions to pad valid value 1,2,3 UINT_32 mipLevel, ///< [in] MipLevel UINT_32* pPitch, ///< [in/out] pitch in pixels UINT_32 pitchAlign, ///< [in] pitch alignment UINT_32* pHeight, ///< [in/out] height in pixels UINT_32 heightAlign, ///< [in] height alignment UINT_32* pSlices, ///< [in/out] number of slices UINT_32 sliceAlign ///< [in] number of slice alignment ) const { UINT_32 thickness = ComputeSurfaceThickness(tileMode); ADDR_ASSERT(padDims <= 3); // // Override padding for mip levels // if (mipLevel > 0) { if (flags.cube) { // for cubemap, we only pad when client call with 6 faces as an identity if (*pSlices > 1) { padDims = 3; // we should pad cubemap sub levels when we treat it as 3d texture } else { padDims = 2; } } } // Any possibilities that padDims is 0? if (padDims == 0) { padDims = 3; } if (IsPow2(pitchAlign)) { *pPitch = PowTwoAlign((*pPitch), pitchAlign); } else // add this code to pass unit test, r600 linear mode is not align bpp to pow2 for linear { *pPitch += pitchAlign - 1; *pPitch /= pitchAlign; *pPitch *= pitchAlign; } if (padDims > 1) { *pHeight = PowTwoAlign((*pHeight), heightAlign); } if (padDims > 2 || thickness > 1) { // for cubemap single face, we do not pad slices. // if we pad it, the slice number should be set to 6 and current mip level > 1 if (flags.cube && (!m_configFlags.noCubeMipSlicesPad || flags.cubeAsArray)) { *pSlices = NextPow2(*pSlices); } // normal 3D texture or arrays or cubemap has a thick mode? (Just pass unit test) if (thickness > 1) { *pSlices = PowTwoAlign((*pSlices), sliceAlign); } } HwlPadDimensions(tileMode, bpp, flags, numSamples, pTileInfo, padDims, mipLevel, pPitch, pitchAlign, pHeight, heightAlign, pSlices, sliceAlign); } /** *************************************************************************************************** * AddrLib::HwlPreHandleBaseLvl3xPitch * * @brief * Pre-handler of 3x pitch (96 bit) adjustment * * @return * Expected pitch *************************************************************************************************** */ UINT_32 AddrLib::HwlPreHandleBaseLvl3xPitch( const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input UINT_32 expPitch ///< [in] pitch ) const { ADDR_ASSERT(pIn->width == expPitch); // // If pitch is pre-multiplied by 3, we retrieve original one here to get correct miplevel size // if (AddrElemLib::IsExpand3x(pIn->format) && pIn->mipLevel == 0 && pIn->tileMode == ADDR_TM_LINEAR_ALIGNED) { expPitch /= 3; expPitch = NextPow2(expPitch); } return expPitch; } /** *************************************************************************************************** * AddrLib::HwlPostHandleBaseLvl3xPitch * * @brief * Post-handler of 3x pitch adjustment * * @return * Expected pitch *************************************************************************************************** */ UINT_32 AddrLib::HwlPostHandleBaseLvl3xPitch( const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input UINT_32 expPitch ///< [in] pitch ) const { // // 96 bits surface of sub levels require element pitch of 32 bits instead // So we just return pitch in 32 bit pixels without timing 3 // if (AddrElemLib::IsExpand3x(pIn->format) && pIn->mipLevel == 0 && pIn->tileMode == ADDR_TM_LINEAR_ALIGNED) { expPitch *= 3; } return expPitch; } /** *************************************************************************************************** * AddrLib::IsMacroTiled * * @brief * Check if the tile mode is macro tiled * * @return * TRUE if it is macro tiled (2D/2B/3D/3B) *************************************************************************************************** */ BOOL_32 AddrLib::IsMacroTiled( AddrTileMode tileMode) ///< [in] tile mode { return m_modeFlags[tileMode].isMacro; } /** *************************************************************************************************** * AddrLib::IsMacro3dTiled * * @brief * Check if the tile mode is 3D macro tiled * * @return * TRUE if it is 3D macro tiled *************************************************************************************************** */ BOOL_32 AddrLib::IsMacro3dTiled( AddrTileMode tileMode) ///< [in] tile mode { return m_modeFlags[tileMode].isMacro3d; } /** *************************************************************************************************** * AddrLib::IsMicroTiled * * @brief * Check if the tile mode is micro tiled * * @return * TRUE if micro tiled *************************************************************************************************** */ BOOL_32 AddrLib::IsMicroTiled( AddrTileMode tileMode) ///< [in] tile mode { return m_modeFlags[tileMode].isMicro; } /** *************************************************************************************************** * AddrLib::IsLinear * * @brief * Check if the tile mode is linear * * @return * TRUE if linear *************************************************************************************************** */ BOOL_32 AddrLib::IsLinear( AddrTileMode tileMode) ///< [in] tile mode { return m_modeFlags[tileMode].isLinear; } /** *************************************************************************************************** * AddrLib::IsPrtNoRotationTileMode * * @brief * Return TRUE if it is prt tile without rotation * @note * This function just used by CI *************************************************************************************************** */ BOOL_32 AddrLib::IsPrtNoRotationTileMode( AddrTileMode tileMode) { return m_modeFlags[tileMode].isPrtNoRotation; } /** *************************************************************************************************** * AddrLib::IsPrtTileMode * * @brief * Return TRUE if it is prt tile * @note * This function just used by CI *************************************************************************************************** */ BOOL_32 AddrLib::IsPrtTileMode( AddrTileMode tileMode) { return m_modeFlags[tileMode].isPrt; } /** *************************************************************************************************** * AddrLib::Bits2Number * * @brief * Cat a array of binary bit to a number * * @return * The number combined with the array of bits *************************************************************************************************** */ UINT_32 AddrLib::Bits2Number( UINT_32 bitNum, ///< [in] how many bits ...) ///< [in] varaible bits value starting from MSB { UINT_32 number = 0; UINT_32 i; va_list bits_ptr; va_start(bits_ptr, bitNum); for(i = 0; i < bitNum; i++) { number |= va_arg(bits_ptr, UINT_32); number <<= 1; } number>>=1; va_end(bits_ptr); return number; } /** *************************************************************************************************** * AddrLib::ComputeMipLevel * * @brief * Compute mipmap level width/height/slices * @return * N/A *************************************************************************************************** */ VOID AddrLib::ComputeMipLevel( ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure ) const { if (AddrElemLib::IsBlockCompressed(pIn->format)) { if (pIn->mipLevel == 0) { // DXTn's level 0 must be multiple of 4 // But there are exceptions: // 1. Internal surface creation in hostblt/vsblt/etc... // 2. Runtime doesn't reject ATI1/ATI2 whose width/height are not multiple of 4 pIn->width = PowTwoAlign(pIn->width, 4); pIn->height = PowTwoAlign(pIn->height, 4); } } HwlComputeMipLevel(pIn); } /** *************************************************************************************************** * AddrLib::DegradeBaseLevel * * @brief * Check if base level's tile mode can be degraded * @return * TRUE if degraded, also returns degraded tile mode (unchanged if not degraded) *************************************************************************************************** */ BOOL_32 AddrLib::DegradeBaseLevel( const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure for surface info AddrTileMode* pTileMode ///< [out] Degraded tile mode ) const { BOOL_32 degraded = FALSE; AddrTileMode tileMode = pIn->tileMode; UINT_32 thickness = ComputeSurfaceThickness(tileMode); if (m_configFlags.degradeBaseLevel) // This is a global setting { if (pIn->flags.degrade4Space && // Degradation per surface pIn->mipLevel == 0 && pIn->numSamples == 1 && IsMacroTiled(tileMode)) { if (HwlDegradeBaseLevel(pIn)) { *pTileMode = thickness == 1 ? ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK; degraded = TRUE; } else if (thickness > 1) { // As in the following HwlComputeSurfaceInfo, thick modes may be degraded to // thinner modes, we should re-evaluate whether the corresponding thinner modes // need to be degraded. If so, we choose 1D thick mode instead. tileMode = DegradeLargeThickTile(pIn->tileMode, pIn->bpp); if (tileMode != pIn->tileMode) { ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pIn; input.tileMode = tileMode; if (HwlDegradeBaseLevel(&input)) { *pTileMode = ADDR_TM_1D_TILED_THICK; degraded = TRUE; } } } } } return degraded; } /** *************************************************************************************************** * AddrLib::DegradeLargeThickTile * * @brief * Check if the thickness needs to be reduced if a tile is too large * @return * The degraded tile mode (unchanged if not degraded) *************************************************************************************************** */ AddrTileMode AddrLib::DegradeLargeThickTile( AddrTileMode tileMode, UINT_32 bpp) const { // Override tilemode // When tile_width (8) * tile_height (8) * thickness * element_bytes is > row_size, // it is better to just use THIN mode in this case UINT_32 thickness = ComputeSurfaceThickness(tileMode); if (thickness > 1 && m_configFlags.allowLargeThickTile == 0) { UINT_32 tileSize = MicroTilePixels * thickness * (bpp >> 3); if (tileSize > m_rowSize) { switch (tileMode) { case ADDR_TM_2D_TILED_XTHICK: if ((tileSize >> 1) <= m_rowSize) { tileMode = ADDR_TM_2D_TILED_THICK; break; } // else fall through case ADDR_TM_2D_TILED_THICK: tileMode = ADDR_TM_2D_TILED_THIN1; break; case ADDR_TM_3D_TILED_XTHICK: if ((tileSize >> 1) <= m_rowSize) { tileMode = ADDR_TM_3D_TILED_THICK; break; } // else fall through case ADDR_TM_3D_TILED_THICK: tileMode = ADDR_TM_3D_TILED_THIN1; break; case ADDR_TM_PRT_TILED_THICK: tileMode = ADDR_TM_PRT_TILED_THIN1; break; case ADDR_TM_PRT_2D_TILED_THICK: tileMode = ADDR_TM_PRT_2D_TILED_THIN1; break; case ADDR_TM_PRT_3D_TILED_THICK: tileMode = ADDR_TM_PRT_3D_TILED_THIN1; break; default: break; } } } return tileMode; } /** *************************************************************************************************** * AddrLib::PostComputeMipLevel * @brief * Compute MipLevel info (including level 0) after surface adjustment * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::PostComputeMipLevel( ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in/out] Input structure ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output structure ) const { // Mipmap including level 0 must be pow2 padded since either SI hw expects so or it is // required by CFX for Hw Compatibility between NI and SI. Otherwise it is only needed for // mipLevel > 0. Any h/w has different requirement should implement its own virtual function if (pIn->flags.pow2Pad) { pIn->width = NextPow2(pIn->width); pIn->height = NextPow2(pIn->height); pIn->numSlices = NextPow2(pIn->numSlices); } else if (pIn->mipLevel > 0) { pIn->width = NextPow2(pIn->width); pIn->height = NextPow2(pIn->height); if (!pIn->flags.cube) { pIn->numSlices = NextPow2(pIn->numSlices); } // for cubemap, we keep its value at first } return ADDR_OK; } /** *************************************************************************************************** * AddrLib::HwlSetupTileCfg * * @brief * Map tile index to tile setting. * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::HwlSetupTileCfg( INT_32 index, ///< [in] Tile index INT_32 macroModeIndex, ///< [in] Index in macro tile mode table(CI) ADDR_TILEINFO* pInfo, ///< [out] Tile Info AddrTileMode* pMode, ///< [out] Tile mode AddrTileType* pType ///< [out] Tile type ) const { return ADDR_NOTSUPPORTED; } /** *************************************************************************************************** * AddrLib::HwlGetPipes * * @brief * Get number pipes * @return * num pipes *************************************************************************************************** */ UINT_32 AddrLib::HwlGetPipes( const ADDR_TILEINFO* pTileInfo ///< [in] Tile info ) const { //pTileInfo can be NULL when asic is 6xx and 8xx. return m_pipes; } /** *************************************************************************************************** * AddrLib::ComputeQbStereoInfo * * @brief * Get quad buffer stereo information * @return * TRUE if no error *************************************************************************************************** */ BOOL_32 AddrLib::ComputeQbStereoInfo( ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] updated pOut+pStereoInfo ) const { BOOL_32 success = FALSE; if (pOut->pStereoInfo) { ADDR_ASSERT(pOut->bpp >= 8); ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0); // Save original height pOut->pStereoInfo->eyeHeight = pOut->height; // Right offset pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize); pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut); // Double height pOut->height <<= 1; pOut->pixelHeight <<= 1; // Double size pOut->surfSize <<= 1; // Right start address meets the base align since it is guaranteed by AddrLib // 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo. success = TRUE; } return success; } /////////////////////////////////////////////////////////////////////////////////////////////////// // Element lib /////////////////////////////////////////////////////////////////////////////////////////////////// /** *************************************************************************************************** * AddrLib::Flt32ToColorPixel * * @brief * Convert a FLT_32 value to a depth/stencil pixel value * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::Flt32ToDepthPixel( const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn, ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ELEM_FLT32TODEPTHPIXEL_INPUT)) || (pOut->size != sizeof(ELEM_FLT32TODEPTHPIXEL_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { GetElemLib()->Flt32ToDepthPixel(pIn->format, pIn->comps, pOut->pPixel); UINT_32 depthBase = 0; UINT_32 stencilBase = 0; UINT_32 depthBits = 0; UINT_32 stencilBits = 0; switch (pIn->format) { case ADDR_DEPTH_16: depthBits = 16; break; case ADDR_DEPTH_X8_24: case ADDR_DEPTH_8_24: case ADDR_DEPTH_X8_24_FLOAT: case ADDR_DEPTH_8_24_FLOAT: depthBase = 8; depthBits = 24; stencilBits = 8; break; case ADDR_DEPTH_32_FLOAT: depthBits = 32; break; case ADDR_DEPTH_X24_8_32_FLOAT: depthBase = 8; depthBits = 32; stencilBits = 8; break; default: break; } // Overwrite base since R800 has no "tileBase" if (GetElemLib()->IsDepthStencilTilePlanar() == FALSE) { depthBase = 0; stencilBase = 0; } depthBase *= 64; stencilBase *= 64; pOut->stencilBase = stencilBase; pOut->depthBase = depthBase; pOut->depthBits = depthBits; pOut->stencilBits = stencilBits; } return returnCode; } /** *************************************************************************************************** * AddrLib::Flt32ToColorPixel * * @brief * Convert a FLT_32 value to a red/green/blue/alpha pixel value * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::Flt32ToColorPixel( const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn, ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; if (GetFillSizeFieldsFlags() == TRUE) { if ((pIn->size != sizeof(ELEM_FLT32TOCOLORPIXEL_INPUT)) || (pOut->size != sizeof(ELEM_FLT32TOCOLORPIXEL_OUTPUT))) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { GetElemLib()->Flt32ToColorPixel(pIn->format, pIn->surfNum, pIn->surfSwap, pIn->comps, pOut->pPixel); } return returnCode; } /** *************************************************************************************************** * AddrLib::GetExportNorm * * @brief * Check one format can be EXPORT_NUM * @return * TRUE if EXPORT_NORM can be used *************************************************************************************************** */ BOOL_32 AddrLib::GetExportNorm( const ELEM_GETEXPORTNORM_INPUT* pIn) const { ADDR_E_RETURNCODE returnCode = ADDR_OK; BOOL_32 enabled = FALSE; if (GetFillSizeFieldsFlags() == TRUE) { if (pIn->size != sizeof(ELEM_GETEXPORTNORM_INPUT)) { returnCode = ADDR_PARAMSIZEMISMATCH; } } if (returnCode == ADDR_OK) { enabled = GetElemLib()->PixGetExportNorm(pIn->format, pIn->num, pIn->swap); } return enabled; } /** *************************************************************************************************** * AddrLib::ComputePrtInfo * * @brief * Compute prt surface related info * * @return * ADDR_E_RETURNCODE *************************************************************************************************** */ ADDR_E_RETURNCODE AddrLib::ComputePrtInfo( const ADDR_PRT_INFO_INPUT* pIn, ADDR_PRT_INFO_OUTPUT* pOut) const { ADDR_ASSERT(pOut != NULL); ADDR_E_RETURNCODE returnCode = ADDR_OK; UINT_32 expandX = 1; UINT_32 expandY = 1; AddrElemMode elemMode; UINT_32 bpp = GetElemLib()->GetBitsPerPixel(pIn->format, &elemMode, &expandX, &expandY); if (bpp <8 || bpp == 24 || bpp == 48 || bpp == 96 ) { returnCode = ADDR_INVALIDPARAMS; } UINT_32 numFrags = pIn->numFrags; ADDR_ASSERT(numFrags <= 8); UINT_32 tileWidth = 0; UINT_32 tileHeight = 0; if (returnCode == ADDR_OK) { // 3D texture without depth or 2d texture if (pIn->baseMipDepth > 1 || pIn->baseMipHeight > 1) { if (bpp == 8) { tileWidth = 256; tileHeight = 256; } else if (bpp == 16) { tileWidth = 256; tileHeight = 128; } else if (bpp == 32) { tileWidth = 128; tileHeight = 128; } else if (bpp == 64) { // assume it is BC1/4 tileWidth = 512; tileHeight = 256; if (elemMode == ADDR_UNCOMPRESSED) { tileWidth = 128; tileHeight = 64; } } else if (bpp == 128) { // assume it is BC2/3/5/6H/7 tileWidth = 256; tileHeight = 256; if (elemMode == ADDR_UNCOMPRESSED) { tileWidth = 64; tileHeight = 64; } } if (numFrags == 2) { tileWidth = tileWidth / 2; } else if (numFrags == 4) { tileWidth = tileWidth / 2; tileHeight = tileHeight / 2; } else if (numFrags == 8) { tileWidth = tileWidth / 4; tileHeight = tileHeight / 2; } } else // 1d { tileHeight = 1; if (bpp == 8) { tileWidth = 65536; } else if (bpp == 16) { tileWidth = 32768; } else if (bpp == 32) { tileWidth = 16384; } else if (bpp == 64) { tileWidth = 8192; } else if (bpp == 128) { tileWidth = 4096; } } } pOut->prtTileWidth = tileWidth; pOut->prtTileHeight = tileHeight; return returnCode; }