diff options
Diffstat (limited to 'meta-amdfalconx86/recipes-graphics/mesa/mesa/0009-winsys-amdgpu-add-addrlib-texture-addressing-and-ali.patch')
-rw-r--r-- | meta-amdfalconx86/recipes-graphics/mesa/mesa/0009-winsys-amdgpu-add-addrlib-texture-addressing-and-ali.patch | 22649 |
1 files changed, 22649 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-graphics/mesa/mesa/0009-winsys-amdgpu-add-addrlib-texture-addressing-and-ali.patch b/meta-amdfalconx86/recipes-graphics/mesa/mesa/0009-winsys-amdgpu-add-addrlib-texture-addressing-and-ali.patch new file mode 100644 index 00000000..0ca8a819 --- /dev/null +++ b/meta-amdfalconx86/recipes-graphics/mesa/mesa/0009-winsys-amdgpu-add-addrlib-texture-addressing-and-ali.patch @@ -0,0 +1,22649 @@ +From dbeaed6cf049a0be97631ab74afa1f4ab9a800bf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <marek.olsak@amd.com> +Date: Thu, 16 Apr 2015 19:41:33 +0200 +Subject: [PATCH 09/29] winsys/amdgpu: add addrlib - texture addressing and + alignment calculator + +This is an internal project that Catalyst uses and now open source will do +too. + +Signed-off-by: Arindam Nath <arindam.nath@amd.com> +--- + src/gallium/winsys/radeon/amdgpu/Makefile.am | 7 +- + src/gallium/winsys/radeon/amdgpu/Makefile.sources | 23 + + .../winsys/radeon/amdgpu/addrlib/addrinterface.cpp | 1008 +++++ + .../winsys/radeon/amdgpu/addrlib/addrinterface.h | 2166 +++++++++ + .../winsys/radeon/amdgpu/addrlib/addrtypes.h | 590 +++ + .../winsys/radeon/amdgpu/addrlib/core/addrcommon.h | 558 +++ + .../radeon/amdgpu/addrlib/core/addrelemlib.cpp | 1678 +++++++ + .../radeon/amdgpu/addrlib/core/addrelemlib.h | 270 ++ + .../winsys/radeon/amdgpu/addrlib/core/addrlib.cpp | 4028 +++++++++++++++++ + .../winsys/radeon/amdgpu/addrlib/core/addrlib.h | 695 +++ + .../radeon/amdgpu/addrlib/core/addrobject.cpp | 246 ++ + .../winsys/radeon/amdgpu/addrlib/core/addrobject.h | 89 + + .../amdgpu/addrlib/inc/chip/r800/si_gb_reg.h | 155 + + .../radeon/amdgpu/addrlib/inc/lnx_common_defs.h | 129 + + .../addrlib/r800/chip/si_ci_vi_merged_enum.h | 40 + + .../radeon/amdgpu/addrlib/r800/ciaddrlib.cpp | 1777 ++++++++ + .../winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.h | 197 + + .../radeon/amdgpu/addrlib/r800/egbaddrlib.cpp | 4578 ++++++++++++++++++++ + .../winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.h | 411 ++ + .../radeon/amdgpu/addrlib/r800/siaddrlib.cpp | 2818 ++++++++++++ + .../winsys/radeon/amdgpu/addrlib/r800/siaddrlib.h | 262 ++ + src/gallium/winsys/radeon/amdgpu/amdgpu_id.h | 157 + + src/gallium/winsys/radeon/amdgpu/amdgpu_surface.c | 436 ++ + src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.c | 50 + + src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.h | 6 + + 25 files changed, 22373 insertions(+), 1 deletion(-) + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/addrtypes.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrcommon.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/inc/chip/r800/si_gb_reg.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/inc/lnx_common_defs.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/chip/si_ci_vi_merged_enum.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.cpp + create mode 100644 src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/amdgpu_id.h + create mode 100644 src/gallium/winsys/radeon/amdgpu/amdgpu_surface.c + +diff --git a/src/gallium/winsys/radeon/amdgpu/Makefile.am b/src/gallium/winsys/radeon/amdgpu/Makefile.am +index 80ecb75..a719913 100644 +--- a/src/gallium/winsys/radeon/amdgpu/Makefile.am ++++ b/src/gallium/winsys/radeon/amdgpu/Makefile.am +@@ -3,7 +3,12 @@ include $(top_srcdir)/src/gallium/Automake.inc + + AM_CFLAGS = \ + $(GALLIUM_WINSYS_CFLAGS) \ +- $(AMDGPU_CFLAGS) ++ $(AMDGPU_CFLAGS) \ ++ -I$(srcdir)/addrlib \ ++ -I$(srcdir)/addrlib/core \ ++ -I$(srcdir)/addrlib/inc/chip/r800 \ ++ -I$(srcdir)/addrlib/r800/chip \ ++ -DBRAHMA_BUILD=1 + + AM_CXXFLAGS = $(AM_CFLAGS) + +diff --git a/src/gallium/winsys/radeon/amdgpu/Makefile.sources b/src/gallium/winsys/radeon/amdgpu/Makefile.sources +index 0f55010..6b33841 100644 +--- a/src/gallium/winsys/radeon/amdgpu/Makefile.sources ++++ b/src/gallium/winsys/radeon/amdgpu/Makefile.sources +@@ -1,8 +1,31 @@ + C_SOURCES := \ ++ addrlib/addrinterface.cpp \ ++ addrlib/addrinterface.h \ ++ addrlib/addrtypes.h \ ++ addrlib/core/addrcommon.h \ ++ addrlib/core/addrelemlib.cpp \ ++ addrlib/core/addrelemlib.h \ ++ addrlib/core/addrlib.cpp \ ++ addrlib/core/addrlib.h \ ++ addrlib/core/addrobject.cpp \ ++ addrlib/core/addrobject.h \ ++ addrlib/inc/chip/r800/si_gb_reg.h \ ++ addrlib/inc/lnx_common_defs.h \ ++ addrlib/r800/chip/si_ci_merged_enum.h \ ++ addrlib/r800/chip/si_ci_vi_merged_enum.h \ ++ addrlib/r800/chip/si_enum.h \ ++ addrlib/r800/ciaddrlib.cpp \ ++ addrlib/r800/ciaddrlib.h \ ++ addrlib/r800/egbaddrlib.cpp \ ++ addrlib/r800/egbaddrlib.h \ ++ addrlib/r800/siaddrlib.cpp \ ++ addrlib/r800/siaddrlib.h \ + amdgpu_bo.c \ + amdgpu_bo.h \ + amdgpu_cs.c \ + amdgpu_cs.h \ ++ amdgpu_id.h \ + amdgpu_public.h \ ++ amdgpu_surface.c \ + amdgpu_winsys.c \ + amdgpu_winsys.h +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.cpp +new file mode 100644 +index 0000000..6556927 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.cpp +@@ -0,0 +1,1008 @@ ++/* ++ * 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 addrinterface.cpp ++* @brief Contains the addrlib interface functions ++*************************************************************************************************** ++*/ ++#include "addrinterface.h" ++#include "addrlib.h" ++ ++#include "addrcommon.h" ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Create/Destroy/Config functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrCreate ++* ++* @brief ++* Create address lib object ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrCreate( ++ const ADDR_CREATE_INPUT* pAddrCreateIn, ///< [in] infomation for creating address lib object ++ ADDR_CREATE_OUTPUT* pAddrCreateOut) ///< [out] address lib handle ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ returnCode = AddrLib::Create(pAddrCreateIn, pAddrCreateOut); ++ ++ return returnCode; ++} ++ ++ ++ ++/** ++*************************************************************************************************** ++* AddrDestroy ++* ++* @brief ++* Destroy address lib object ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrDestroy( ++ ADDR_HANDLE hLib) ///< [in] address lib handle ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (hLib) ++ { ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ pLib->Destroy(); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Surface functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceInfo ++* ++* @brief ++* Calculate surface width/height/depth/alignments and suitable tiling mode ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceInfo( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] surface information ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) ///< [out] surface parameters and alignments ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeSurfaceInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceAddrFromCoord ++* ++* @brief ++* Compute surface address according to coordinates ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceAddrFromCoord( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] surface info and coordinates ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] surface address ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeSurfaceAddrFromCoord(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceCoordFromAddr ++* ++* @brief ++* Compute coordinates according to surface address ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceCoordFromAddr( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] surface info and address ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) ///< [out] coordinates ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeSurfaceCoordFromAddr(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// HTile functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileInfo ++* ++* @brief ++* Compute Htile pitch, height, base alignment and size in bytes ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileInfo( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] Htile information ++ ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut) ///< [out] Htile pitch, height and size in bytes ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeHtileInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileAddrFromCoord ++* ++* @brief ++* Compute Htile address according to coordinates (of depth buffer) ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileAddrFromCoord( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] Htile info and coordinates ++ ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] Htile address ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeHtileAddrFromCoord(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileCoordFromAddr ++* ++* @brief ++* Compute coordinates within depth buffer (1st pixel of a micro tile) according to ++* Htile address ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileCoordFromAddr( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] Htile info and address ++ ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut) ///< [out] Htile coordinates ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeHtileCoordFromAddr(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// C-mask functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskInfo ++* ++* @brief ++* Compute Cmask pitch, height, base alignment and size in bytes from color buffer ++* info ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskInfo( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] Cmask pitch and height ++ ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut) ///< [out] Cmask pitch, height and size in bytes ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeCmaskInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskAddrFromCoord ++* ++* @brief ++* Compute Cmask address according to coordinates (of MSAA color buffer) ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskAddrFromCoord( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] Cmask info and coordinates ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] Cmask address ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeCmaskAddrFromCoord(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskCoordFromAddr ++* ++* @brief ++* Compute coordinates within color buffer (1st pixel of a micro tile) according to ++* Cmask address ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskCoordFromAddr( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] Cmask info and address ++ ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut) ///< [out] Cmask coordinates ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeCmaskCoordFromAddr(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// F-mask functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskInfo ++* ++* @brief ++* Compute Fmask pitch/height/depth/alignments and size in bytes ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskInfo( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] Fmask information ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) ///< [out] Fmask pitch and height ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeFmaskInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskAddrFromCoord ++* ++* @brief ++* Compute Fmask address according to coordinates (x,y,slice,sample,plane) ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskAddrFromCoord( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] Fmask info and coordinates ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] Fmask address ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeFmaskAddrFromCoord(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskCoordFromAddr ++* ++* @brief ++* Compute coordinates (x,y,slice,sample,plane) according to Fmask address ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskCoordFromAddr( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] Fmask info and address ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) ///< [out] Fmask coordinates ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeFmaskCoordFromAddr(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// DCC key functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrComputeDccInfo ++* ++* @brief ++* Compute DCC key size, base alignment based on color surface size, tile info or tile index ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeDccInfo( ++ ADDR_HANDLE hLib, ///< [in] handle of addrlib ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) ///< [out] output ++{ ++ ADDR_E_RETURNCODE returnCode; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeDccInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++// Below functions are element related or helper functions ++/////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrGetVersion ++* ++* @brief ++* Get AddrLib version number. Client may check this return value against ADDRLIB_VERSION ++* defined in addrinterface.h to see if there is a mismatch. ++*************************************************************************************************** ++*/ ++UINT_32 ADDR_API AddrGetVersion(ADDR_HANDLE hLib) ++{ ++ UINT_32 version = 0; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_ASSERT(pLib != NULL); ++ ++ if (pLib) ++ { ++ version = pLib->GetVersion(); ++ } ++ ++ return version; ++} ++ ++/** ++*************************************************************************************************** ++* AddrUseTileIndex ++* ++* @brief ++* Return TRUE if tileIndex is enabled in this address library ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API AddrUseTileIndex(ADDR_HANDLE hLib) ++{ ++ BOOL_32 useTileIndex = FALSE; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_ASSERT(pLib != NULL); ++ ++ if (pLib) ++ { ++ useTileIndex = pLib->UseTileIndex(0); ++ } ++ ++ return useTileIndex; ++} ++ ++/** ++*************************************************************************************************** ++* AddrUseCombinedSwizzle ++* ++* @brief ++* Return TRUE if combined swizzle is enabled in this address library ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API AddrUseCombinedSwizzle(ADDR_HANDLE hLib) ++{ ++ BOOL_32 useCombinedSwizzle = FALSE; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_ASSERT(pLib != NULL); ++ ++ if (pLib) ++ { ++ useCombinedSwizzle = pLib->UseCombinedSwizzle(); ++ } ++ ++ return useCombinedSwizzle; ++} ++ ++/** ++*************************************************************************************************** ++* AddrExtractBankPipeSwizzle ++* ++* @brief ++* Extract Bank and Pipe swizzle from base256b ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrExtractBankPipeSwizzle( ++ ADDR_HANDLE hLib, ///< [in] addrlib handle ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut) ///< [out] output structure ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ExtractBankPipeSwizzle(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrCombineBankPipeSwizzle ++* ++* @brief ++* Combine Bank and Pipe swizzle ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrCombineBankPipeSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut) ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->CombineBankPipeSwizzle(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeSliceSwizzle ++* ++* @brief ++* Compute a swizzle for slice from a base swizzle ++* @return ++* ADDR_OK if no error ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSliceSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut) ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeSliceTileSwizzle(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputeBaseSwizzle ++* ++* @brief ++* Return a Combined Bank and Pipe swizzle base on surface based on surface type/index ++* @return ++* ADDR_OK if no error ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeBaseSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputeBaseSwizzle(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* ElemFlt32ToDepthPixel ++* ++* @brief ++* Convert a FLT_32 value to a depth/stencil pixel value ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API ElemFlt32ToDepthPixel( ++ ADDR_HANDLE hLib, ///< [in] addrlib handle ++ const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn, ///< [in] per-component value ++ ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) ///< [out] final pixel value ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ pLib->Flt32ToDepthPixel(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* ElemFlt32ToColorPixel ++* ++* @brief ++* Convert a FLT_32 value to a red/green/blue/alpha pixel value ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API ElemFlt32ToColorPixel( ++ ADDR_HANDLE hLib, ///< [in] addrlib handle ++ const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn, ///< [in] format, surface number and swap value ++ ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) ///< [out] final pixel value ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ pLib->Flt32ToColorPixel(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* ElemGetExportNorm ++* ++* @brief ++* Helper function to check one format can be EXPORT_NUM, ++* which is a register CB_COLOR_INFO.SURFACE_FORMAT. ++* FP16 can be reported as EXPORT_NORM for rv770 in r600 ++* family ++* ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API ElemGetExportNorm( ++ ADDR_HANDLE hLib, ///< [in] addrlib handle ++ const ELEM_GETEXPORTNORM_INPUT* pIn) ///< [in] input structure ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ BOOL_32 enabled = FALSE; ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ enabled = pLib->GetExportNorm(pIn); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ ADDR_ASSERT(returnCode == ADDR_OK); ++ ++ return enabled; ++} ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileInfoToHW ++* ++* @brief ++* Convert tile info from real value to hardware register value ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileInfoToHW( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] tile info with real value ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) ///< [out] tile info with HW register value ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ConvertTileInfoToHW(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileIndex ++* ++* @brief ++* Convert tile index to tile mode/type/info ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileIndex( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ///< [in] input - tile index ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut) ///< [out] tile mode/type/info ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ConvertTileIndex(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileIndex1 ++* ++* @brief ++* Convert tile index to tile mode/type/info ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileIndex1( ++ ADDR_HANDLE hLib, ///< [in] address lib handle ++ const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ///< [in] input - tile index ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut) ///< [out] tile mode/type/info ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ConvertTileIndex1(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrGetTileIndex ++* ++* @brief ++* Get tile index from tile mode/type/info ++* ++* @return ++* ADDR_OK if successful, otherwise an error code of ADDR_E_RETURNCODE ++* ++* @note ++* Only meaningful for SI (and above) ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrGetTileIndex( ++ ADDR_HANDLE hLib, ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut) ++{ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->GetTileIndex(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* AddrComputePrtInfo ++* ++* @brief ++* Interface function for ComputePrtInfo ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputePrtInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_PRT_INFO_INPUT* pIn, ++ ADDR_PRT_INFO_OUTPUT* pOut) ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ AddrLib* pLib = AddrLib::GetAddrLib(hLib); ++ ++ if (pLib != NULL) ++ { ++ returnCode = pLib->ComputePrtInfo(pIn, pOut); ++ } ++ else ++ { ++ returnCode = ADDR_ERROR; ++ } ++ ++ return returnCode; ++} ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.h b/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.h +new file mode 100644 +index 0000000..03fbf2b +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/addrinterface.h +@@ -0,0 +1,2166 @@ ++/* ++ * 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 addrinterface.h ++* @brief Contains the addrlib interfaces declaration and parameter defines ++*************************************************************************************************** ++*/ ++#ifndef __ADDR_INTERFACE_H__ ++#define __ADDR_INTERFACE_H__ ++ ++#if defined(__cplusplus) ++extern "C" ++{ ++#endif ++ ++#include "addrtypes.h" ++ ++#define ADDRLIB_VERSION_MAJOR 5 ++#define ADDRLIB_VERSION_MINOR 25 ++#define ADDRLIB_VERSION ((ADDRLIB_VERSION_MAJOR << 16) | ADDRLIB_VERSION_MINOR) ++ ++/// Virtually all interface functions need ADDR_HANDLE as first parameter ++typedef VOID* ADDR_HANDLE; ++ ++/// Client handle used in callbacks ++typedef VOID* ADDR_CLIENT_HANDLE; ++ ++/** ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // Callback functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* typedef VOID* (ADDR_API* ADDR_ALLOCSYSMEM)( ++* const ADDR_ALLOCSYSMEM_INPUT* pInput); ++* typedef ADDR_E_RETURNCODE (ADDR_API* ADDR_FREESYSMEM)( ++* VOID* pVirtAddr); ++* typedef ADDR_E_RETURNCODE (ADDR_API* ADDR_DEBUGPRINT)( ++* const ADDR_DEBUGPRINT_INPUT* pInput); ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // Create/Destroy/Config functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrCreate() ++* AddrDestroy() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // Surface functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrComputeSurfaceInfo() ++* AddrComputeSurfaceAddrFromCoord() ++* AddrComputeSurfaceCoordFromAddr() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // HTile functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrComputeHtileInfo() ++* AddrComputeHtileAddrFromCoord() ++* AddrComputeHtileCoordFromAddr() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // C-mask functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrComputeCmaskInfo() ++* AddrComputeCmaskAddrFromCoord() ++* AddrComputeCmaskCoordFromAddr() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // F-mask functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrComputeFmaskInfo() ++* AddrComputeFmaskAddrFromCoord() ++* AddrComputeFmaskCoordFromAddr() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // Element/Utility functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* ElemFlt32ToDepthPixel() ++* ElemFlt32ToColorPixel() ++* AddrExtractBankPipeSwizzle() ++* AddrCombineBankPipeSwizzle() ++* AddrComputeSliceSwizzle() ++* AddrConvertTileInfoToHW() ++* AddrConvertTileIndex() ++* AddrConvertTileIndex1() ++* AddrGetTileIndex() ++* AddrComputeBaseSwizzle() ++* AddrUseTileIndex() ++* AddrUseCombinedSwizzle() ++* ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* // Dump functions ++* ///////////////////////////////////////////////////////////////////////////////////////////////// ++* AddrDumpSurfaceInfo() ++* AddrDumpFmaskInfo() ++* AddrDumpCmaskInfo() ++* AddrDumpHtileInfo() ++* ++**/ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Callback functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* @brief Alloc system memory flags. ++* @note These flags are reserved for future use and if flags are added will minimize the impact ++* of the client. ++*************************************************************************************************** ++*/ ++typedef union _ADDR_ALLOCSYSMEM_FLAGS ++{ ++ struct ++ { ++ UINT_32 reserved : 32; ///< Reserved for future use. ++ } fields; ++ UINT_32 value; ++ ++} ADDR_ALLOCSYSMEM_FLAGS; ++ ++/** ++*************************************************************************************************** ++* @brief Alloc system memory input structure ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_ALLOCSYSMEM_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ ADDR_ALLOCSYSMEM_FLAGS flags; ///< System memory flags. ++ UINT_32 sizeInBytes; ///< System memory allocation size in bytes. ++ ADDR_CLIENT_HANDLE hClient; ///< Client handle ++} ADDR_ALLOCSYSMEM_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_ALLOCSYSMEM ++* @brief ++* Allocate system memory callback function. Returns valid pointer on success. ++*************************************************************************************************** ++*/ ++typedef VOID* (ADDR_API* ADDR_ALLOCSYSMEM)( ++ const ADDR_ALLOCSYSMEM_INPUT* pInput); ++ ++/** ++*************************************************************************************************** ++* @brief Free system memory input structure ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_FREESYSMEM_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ VOID* pVirtAddr; ///< Virtual address ++ ADDR_CLIENT_HANDLE hClient; ///< Client handle ++} ADDR_FREESYSMEM_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_FREESYSMEM ++* @brief ++* Free system memory callback function. ++* Returns ADDR_OK on success. ++*************************************************************************************************** ++*/ ++typedef ADDR_E_RETURNCODE (ADDR_API* ADDR_FREESYSMEM)( ++ const ADDR_FREESYSMEM_INPUT* pInput); ++ ++/** ++*************************************************************************************************** ++* @brief Print debug message input structure ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_DEBUGPRINT_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ CHAR* pDebugString; ///< Debug print string ++ va_list ap; ///< Variable argument list ++ ADDR_CLIENT_HANDLE hClient; ///< Client handle ++} ADDR_DEBUGPRINT_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_DEBUGPRINT ++* @brief ++* Print debug message callback function. ++* Returns ADDR_OK on success. ++*************************************************************************************************** ++*/ ++typedef ADDR_E_RETURNCODE (ADDR_API* ADDR_DEBUGPRINT)( ++ const ADDR_DEBUGPRINT_INPUT* pInput); ++ ++/** ++*************************************************************************************************** ++* ADDR_CALLBACKS ++* ++* @brief ++* Address Library needs client to provide system memory alloc/free routines. ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CALLBACKS ++{ ++ ADDR_ALLOCSYSMEM allocSysMem; ///< Routine to allocate system memory ++ ADDR_FREESYSMEM freeSysMem; ///< Routine to free system memory ++ ADDR_DEBUGPRINT debugPrint; ///< Routine to print debug message ++} ADDR_CALLBACKS; ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Create/Destroy functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* ADDR_CREATE_FLAGS ++* ++* @brief ++* This structure is used to pass some setup in creation of AddrLib ++* @note ++*************************************************************************************************** ++*/ ++typedef union _ADDR_CREATE_FLAGS ++{ ++ struct ++ { ++ UINT_32 noCubeMipSlicesPad : 1; ///< Turn cubemap faces padding off ++ UINT_32 fillSizeFields : 1; ///< If clients fill size fields in all input and ++ /// output structure ++ UINT_32 useTileIndex : 1; ///< Make tileIndex field in input valid ++ UINT_32 useCombinedSwizzle : 1; ///< Use combined tile swizzle ++ UINT_32 checkLast2DLevel : 1; ///< Check the last 2D mip sub level ++ UINT_32 useHtileSliceAlign : 1; ///< Do htile single slice alignment ++ UINT_32 degradeBaseLevel : 1; ///< Degrade to 1D modes automatically for base level ++ UINT_32 allowLargeThickTile : 1; ///< Allow 64*thickness*bytesPerPixel > rowSize ++ UINT_32 reserved : 24; ///< Reserved bits for future use ++ }; ++ ++ UINT_32 value; ++} ADDR_CREATE_FLAGS; ++ ++/** ++*************************************************************************************************** ++* ADDR_REGISTER_VALUE ++* ++* @brief ++* Data from registers to setup AddrLib global data, used in AddrCreate ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_REGISTER_VALUE ++{ ++ UINT_32 gbAddrConfig; ///< For R8xx, use GB_ADDR_CONFIG register value. ++ /// For R6xx/R7xx, use GB_TILING_CONFIG. ++ /// But they can be treated as the same. ++ /// if this value is 0, use chip to set default value ++ UINT_32 backendDisables; ///< 1 bit per backend, starting with LSB. 1=disabled,0=enabled. ++ /// Register value of CC_RB_BACKEND_DISABLE.BACKEND_DISABLE ++ ++ /// R800 registers----------------------------------------------- ++ UINT_32 noOfBanks; ///< Number of h/w ram banks - For r800: MC_ARB_RAMCFG.NOOFBANK ++ /// No enums for this value in h/w header files ++ /// 0: 4 ++ /// 1: 8 ++ /// 2: 16 ++ UINT_32 noOfRanks; /// MC_ARB_RAMCFG.NOOFRANK ++ /// 0: 1 ++ /// 1: 2 ++ /// SI (R1000) registers----------------------------------------- ++ const UINT_32* pTileConfig; ///< Global tile setting tables ++ UINT_32 noOfEntries; ///< Number of entries in pTileConfig ++ ++ ///< CI registers------------------------------------------------- ++ const UINT_32* pMacroTileConfig; ///< Global macro tile mode table ++ UINT_32 noOfMacroEntries; ///< Number of entries in pMacroTileConfig ++ ++} ADDR_REGISTER_VALUE; ++ ++/** ++*************************************************************************************************** ++* ADDR_CREATE_INPUT ++* ++* @brief ++* Parameters use to create an AddrLib Object. Caller must provide all fields. ++* ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CREATE_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 chipEngine; ///< Chip Engine ++ UINT_32 chipFamily; ///< Chip Family ++ UINT_32 chipRevision; ///< Chip Revision ++ ADDR_CALLBACKS callbacks; ///< Callbacks for sysmem alloc/free/print ++ ADDR_CREATE_FLAGS createFlags; ///< Flags to setup AddrLib ++ ADDR_REGISTER_VALUE regValue; ///< Data from registers to setup AddrLib global data ++ ADDR_CLIENT_HANDLE hClient; ///< Client handle ++ UINT_32 minPitchAlignPixels; ///< Minimum pitch alignment in pixels ++} ADDR_CREATE_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_CREATEINFO_OUTPUT ++* ++* @brief ++* Return AddrLib handle to client driver ++* ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CREATE_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ ADDR_HANDLE hLib; ///< Address lib handle ++} ADDR_CREATE_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrCreate ++* ++* @brief ++* Create AddrLib object, must be called before any interface calls ++* ++* @return ++* ADDR_OK if successful ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrCreate( ++ const ADDR_CREATE_INPUT* pAddrCreateIn, ++ ADDR_CREATE_OUTPUT* pAddrCreateOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* AddrDestroy ++* ++* @brief ++* Destroy AddrLib object, must be called to free internally allocated resources. ++* ++* @return ++* ADDR_OK if successful ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrDestroy( ++ ADDR_HANDLE hLib); ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Surface functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* @brief ++* Bank/tiling parameters. On function input, these can be set as desired or ++* left 0 for AddrLib to calculate/default. On function output, these are the actual ++* parameters used. ++* @note ++* Valid bankWidth/bankHeight value: ++* 1,2,4,8. They are factors instead of pixels or bytes. ++* ++* The bank number remains constant across each row of the ++* macro tile as each pipe is selected, so the number of ++* tiles in the x direction with the same bank number will ++* be bank_width * num_pipes. ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_TILEINFO ++{ ++ /// Any of these parameters can be set to 0 to use the HW default. ++ UINT_32 banks; ///< Number of banks, numerical value ++ UINT_32 bankWidth; ///< Number of tiles in the X direction in the same bank ++ UINT_32 bankHeight; ///< Number of tiles in the Y direction in the same bank ++ UINT_32 macroAspectRatio; ///< Macro tile aspect ratio. 1-1:1, 2-4:1, 4-16:1, 8-64:1 ++ UINT_32 tileSplitBytes; ///< Tile split size, in bytes ++ AddrPipeCfg pipeConfig; ///< Pipe Config = HW enum + 1 ++} ADDR_TILEINFO; ++ ++// Create a define to avoid client change. The removal of R800 is because we plan to implement SI ++// within 800 HWL - An AddrPipeCfg is added in above data structure ++typedef ADDR_TILEINFO ADDR_R800_TILEINFO; ++ ++/** ++*************************************************************************************************** ++* @brief ++* Information needed by quad buffer stereo support ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_QBSTEREOINFO ++{ ++ UINT_32 eyeHeight; ///< Height (in pixel rows) to right eye ++ UINT_32 rightOffset; ///< Offset (in bytes) to right eye ++ UINT_32 rightSwizzle; ///< TileSwizzle for right eyes ++} ADDR_QBSTEREOINFO; ++ ++/** ++*************************************************************************************************** ++* ADDR_SURFACE_FLAGS ++* ++* @brief ++* Surface flags ++*************************************************************************************************** ++*/ ++typedef union _ADDR_SURFACE_FLAGS ++{ ++ struct ++ { ++ UINT_32 color : 1; ///< Flag indicates this is a color buffer ++ UINT_32 depth : 1; ///< Flag indicates this is a depth/stencil buffer ++ UINT_32 stencil : 1; ///< Flag indicates this is a stencil buffer ++ UINT_32 texture : 1; ///< Flag indicates this is a texture ++ UINT_32 cube : 1; ///< Flag indicates this is a cubemap ++ ++ UINT_32 volume : 1; ///< Flag indicates this is a volume texture ++ UINT_32 fmask : 1; ///< Flag indicates this is an fmask ++ UINT_32 cubeAsArray : 1; ///< Flag indicates if treat cubemap as arrays ++ UINT_32 compressZ : 1; ///< Flag indicates z buffer is compressed ++ UINT_32 overlay : 1; ///< Flag indicates this is an overlay surface ++ UINT_32 noStencil : 1; ///< Flag indicates this depth has no separate stencil ++ UINT_32 display : 1; ///< Flag indicates this should match display controller req. ++ UINT_32 opt4Space : 1; ///< Flag indicates this surface should be optimized for space ++ /// i.e. save some memory but may lose performance ++ UINT_32 prt : 1; ///< Flag for partially resident texture ++ UINT_32 qbStereo : 1; ///< Quad buffer stereo surface ++ UINT_32 pow2Pad : 1; ///< SI: Pad to pow2, must set for mipmap (include level0) ++ UINT_32 interleaved : 1; ///< Special flag for interleaved YUV surface padding ++ UINT_32 degrade4Space : 1; ///< Degrade base level's tile mode to save memory ++ UINT_32 tcCompatible : 1; ///< Flag indicates surface needs to be shader readable ++ UINT_32 dispTileType : 1; ///< NI: force display Tiling for 128 bit shared resoruce ++ UINT_32 dccCompatible : 1; ///< VI: whether to support dcc fast clear ++ UINT_32 czDispCompatible: 1; ///< SI+: CZ family (Carrizo) has a HW bug needs special alignment. ++ ///< This flag indicates we need to follow the alignment with ++ ///< CZ families or other ASICs under PX configuration + CZ. ++ UINT_32 reserved :10; ///< Reserved bits ++ }; ++ ++ UINT_32 value; ++} ADDR_SURFACE_FLAGS; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_INFO_INPUT ++* ++* @brief ++* Input structure for AddrComputeSurfaceInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_INFO_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrTileMode tileMode; ///< Tile mode ++ AddrFormat format; ///< If format is set to valid one, bpp/width/height ++ /// might be overwritten ++ UINT_32 bpp; ///< Bits per pixel ++ UINT_32 numSamples; ///< Number of samples ++ UINT_32 width; ///< Width, in pixels ++ UINT_32 height; ///< Height, in pixels ++ UINT_32 numSlices; ///< Number surface slice/depth, ++ /// Note: ++ /// For cubemap, driver clients usually set numSlices ++ /// to 1 in per-face calc. ++ /// For 7xx and above, we need pad faces as slices. ++ /// In this case, clients should set numSlices to 6 and ++ /// this is also can be turned off by createFlags when ++ /// calling AddrCreate ++ UINT_32 slice; ///< Slice index ++ UINT_32 mipLevel; ///< Current mipmap level. ++ /// Padding/tiling have different rules for level0 and ++ /// sublevels ++ ADDR_SURFACE_FLAGS flags; ///< Surface type flags ++ UINT_32 numFrags; ///< Number of fragments, leave it zero or the same as ++ /// number of samples for normal AA; Set it to the ++ /// number of fragments for EQAA ++ /// r800 and later HWL parameters ++ // Needed by 2D tiling, for linear and 1D tiling, just keep them 0's ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Set to 0 to default/calculate ++ AddrTileType tileType; ///< Micro tiling type, not needed when tileIndex != -1 ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ UINT_32 basePitch; ///< Base level pitch in pixels, 0 means ignored, is a ++ /// must for mip levels from SI+. ++ /// Don't use pitch in blocks for compressed formats! ++} ADDR_COMPUTE_SURFACE_INFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_INFO_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeSurfInfo ++* @note ++ Element: AddrLib unit for computing. e.g. BCn: 4x4 blocks; R32B32B32: 32bit with 3x pitch ++ Pixel: Original pixel ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_INFO_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 pitch; ///< Pitch in elements (in blocks for compressed formats) ++ UINT_32 height; ///< Height in elements (in blocks for compressed formats) ++ UINT_32 depth; ///< Number of slice/depth ++ UINT_64 surfSize; ///< Surface size in bytes ++ AddrTileMode tileMode; ///< Actual tile mode. May differ from that in input ++ UINT_32 baseAlign; ///< Base address alignment ++ UINT_32 pitchAlign; ///< Pitch alignment, in elements ++ UINT_32 heightAlign; ///< Height alignment, in elements ++ UINT_32 depthAlign; ///< Depth alignment, aligned to thickness, for 3d texture ++ UINT_32 bpp; ///< Bits per elements (e.g. blocks for BCn, 1/3 for 96bit) ++ UINT_32 pixelPitch; ///< Pitch in original pixels ++ UINT_32 pixelHeight; ///< Height in original pixels ++ UINT_32 pixelBits; ///< Original bits per pixel, passed from input ++ UINT_64 sliceSize; ///< Size of slice specified by input's slice ++ /// The result is controlled by surface flags & createFlags ++ /// By default this value equals to surfSize for volume ++ UINT_32 pitchTileMax; ///< PITCH_TILE_MAX value for h/w register ++ UINT_32 heightTileMax; ///< HEIGHT_TILE_MAX value for h/w register ++ UINT_32 sliceTileMax; ///< SLICE_TILE_MAX value for h/w register ++ ++ UINT_32 numSamples; ///< Pass the effective numSamples processed in this call ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< Tile parameters used. Filled in if 0 on input ++ AddrTileType tileType; ///< Micro tiling type, only valid when tileIndex != -1 ++ INT_32 tileIndex; ///< Tile index, MAY be "downgraded" ++ ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ /// Special information to work around SI mipmap swizzle bug UBTS #317508 ++ BOOL_32 last2DLevel; ///< TRUE if this is the last 2D(3D) tiled ++ ///< Only meaningful when create flag checkLast2DLevel is set ++ /// Stereo info ++ ADDR_QBSTEREOINFO* pStereoInfo;///< Stereo information, needed when .qbStereo flag is TRUE ++} ADDR_COMPUTE_SURFACE_INFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceInfo ++* ++* @brief ++* Compute surface width/height/depth/alignments and suitable tiling mode ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT ++* ++* @brief ++* Input structure for AddrComputeSurfaceAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Slice index ++ UINT_32 sample; ///< Sample index, use fragment index for EQAA ++ ++ UINT_32 bpp; ///< Bits per pixel ++ UINT_32 pitch; ///< Surface pitch, in pixels ++ UINT_32 height; ///< Surface height, in pixels ++ UINT_32 numSlices; ///< Surface depth ++ UINT_32 numSamples; ///< Number of samples ++ ++ AddrTileMode tileMode; ///< Tile mode ++ BOOL_32 isDepth; ///< TRUE if the surface uses depth sample ordering within ++ /// micro tile. Textures can also choose depth sample order ++ UINT_32 tileBase; ///< Base offset (in bits) inside micro tile which handles ++ /// the case that components are stored separately ++ UINT_32 compBits; ///< The component bits actually needed(for planar surface) ++ ++ UINT_32 numFrags; ///< Number of fragments, leave it zero or the same as ++ /// number of samples for normal AA; Set it to the ++ /// number of fragments for EQAA ++ /// r800 and later HWL parameters ++ // Used for 1D tiling above ++ AddrTileType tileType; ///< See defintion of AddrTileType ++ struct ++ { ++ UINT_32 ignoreSE : 1; ///< TRUE if shader engines are ignored. This is texture ++ /// only flag. Only non-RT texture can set this to TRUE ++ UINT_32 reserved :31; ///< Reserved for future use. ++ }; ++ // 2D tiling needs following structure ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Client must provide all data ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ union ++ { ++ struct ++ { ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++ }; ++ UINT_32 tileSwizzle; ///< Combined swizzle, if useCombinedSwizzle is TRUE ++ }; ++ ++#if ADDR_AM_BUILD // These two fields are not valid in SW blt since no HTILE access ++ UINT_32 addr5Swizzle; ///< ADDR5_SWIZZLE_MASK of DB_DEPTH_INFO ++ BOOL_32 is32ByteTile; ///< Caller must have access to HTILE buffer and know if ++ /// this tile is compressed to 32B ++#endif ++} ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeSurfaceAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Byte address ++ UINT_32 bitPosition; ///< Bit position within surfaceAddr, 0-7. ++ /// For surface bpp < 8, e.g. FMT_1. ++ UINT_32 prtBlockIndex; ///< Index of a PRT tile (64K block) ++} ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceAddrFromCoord ++* ++* @brief ++* Compute surface address from a given coordinate. ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceAddrFromCoord( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT ++* ++* @brief ++* Input structure for AddrComputeSurfaceCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Address in bytes ++ UINT_32 bitPosition; ///< Bit position in addr. 0-7. for surface bpp < 8, ++ /// e.g. FMT_1; ++ UINT_32 bpp; ///< Bits per pixel ++ UINT_32 pitch; ///< Pitch, in pixels ++ UINT_32 height; ///< Height in pixels ++ UINT_32 numSlices; ///< Surface depth ++ UINT_32 numSamples; ///< Number of samples ++ ++ AddrTileMode tileMode; ///< Tile mode ++ BOOL_32 isDepth; ///< Surface uses depth sample ordering within micro tile. ++ /// Note: Textures can choose depth sample order as well. ++ UINT_32 tileBase; ///< Base offset (in bits) inside micro tile which handles ++ /// the case that components are stored separately ++ UINT_32 compBits; ///< The component bits actually needed(for planar surface) ++ ++ UINT_32 numFrags; ///< Number of fragments, leave it zero or the same as ++ /// number of samples for normal AA; Set it to the ++ /// number of fragments for EQAA ++ /// r800 and later HWL parameters ++ // Used for 1D tiling above ++ AddrTileType tileType; ///< See defintion of AddrTileType ++ struct ++ { ++ UINT_32 ignoreSE : 1; ///< TRUE if shader engines are ignored. This is texture ++ /// only flag. Only non-RT texture can set this to TRUE ++ UINT_32 reserved :31; ///< Reserved for future use. ++ }; ++ // 2D tiling needs following structure ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Client must provide all data ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ union ++ { ++ struct ++ { ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++ }; ++ UINT_32 tileSwizzle; ///< Combined swizzle, if useCombinedSwizzle is TRUE ++ }; ++} ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeSurfaceCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Index of slices ++ UINT_32 sample; ///< Index of samples, means fragment index for EQAA ++} ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeSurfaceCoordFromAddr ++* ++* @brief ++* Compute coordinate from a given surface address ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSurfaceCoordFromAddr( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut); ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// HTile functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* ADDR_HTILE_FLAGS ++* ++* @brief ++* HTILE flags ++*************************************************************************************************** ++*/ ++typedef union _ADDR_HTILE_FLAGS ++{ ++ struct ++ { ++ UINT_32 tcCompatible : 1; ///< Flag indicates surface needs to be shader readable ++ UINT_32 reserved :31; ///< Reserved bits ++ }; ++ ++ UINT_32 value; ++} ADDR_HTILE_FLAGS; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_INFO_INPUT ++* ++* @brief ++* Input structure of AddrComputeHtileInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_INFO_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ ADDR_HTILE_FLAGS flags; ///< HTILE flags ++ UINT_32 pitch; ///< Surface pitch, in pixels ++ UINT_32 height; ///< Surface height, in pixels ++ UINT_32 numSlices; ///< Number of slices ++ BOOL_32 isLinear; ///< Linear or tiled HTILE layout ++ AddrHtileBlockSize blockWidth; ///< 4 or 8. EG above only support 8 ++ AddrHtileBlockSize blockHeight; ///< 4 or 8. EG above only support 8 ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_HTILE_INFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_INFO_OUTPUT ++* ++* @brief ++* Output structure of AddrComputeHtileInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_INFO_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 pitch; ///< Pitch in pixels of depth buffer represented in this ++ /// HTile buffer. This might be larger than original depth ++ /// buffer pitch when called with an unaligned pitch. ++ UINT_32 height; ///< Height in pixels, as above ++ UINT_64 htileBytes; ///< Size of HTILE buffer, in bytes ++ UINT_32 baseAlign; ///< Base alignment ++ UINT_32 bpp; ///< Bits per pixel for HTILE is how many bits for an 8x8 block! ++ UINT_32 macroWidth; ///< Macro width in pixels, actually squared cache shape ++ UINT_32 macroHeight; ///< Macro height in pixels ++ UINT_64 sliceSize; ///< Slice size, in bytes. ++} ADDR_COMPUTE_HTILE_INFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileInfo ++* ++* @brief ++* Compute Htile pitch, height, base alignment and size in bytes ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT ++* ++* @brief ++* Input structure for AddrComputeHtileAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 pitch; ///< Pitch, in pixels ++ UINT_32 height; ///< Height in pixels ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Index of slice ++ UINT_32 numSlices; ///< Number of slices ++ BOOL_32 isLinear; ///< Linear or tiled HTILE layout ++ AddrHtileBlockSize blockWidth; ///< 4 or 8. 1 means 8, 0 means 4. EG above only support 8 ++ AddrHtileBlockSize blockHeight; ///< 4 or 8. 1 means 8, 0 means 4. EG above only support 8 ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeHtileAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Address in bytes ++ UINT_32 bitPosition; ///< Bit position, 0 or 4. CMASK and HTILE shares some lib method. ++ /// So we keep bitPosition for HTILE as well ++} ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileAddrFromCoord ++* ++* @brief ++* Compute Htile address according to coordinates (of depth buffer) ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileAddrFromCoord( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT ++* ++* @brief ++* Input structure for AddrComputeHtileCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Address ++ UINT_32 bitPosition; ///< Bit position 0 or 4. CMASK and HTILE share some methods ++ /// so we keep bitPosition for HTILE as well ++ UINT_32 pitch; ///< Pitch, in pixels ++ UINT_32 height; ///< Height, in pixels ++ UINT_32 numSlices; ///< Number of slices ++ BOOL_32 isLinear; ///< Linear or tiled HTILE layout ++ AddrHtileBlockSize blockWidth; ///< 4 or 8. 1 means 8, 0 means 4. R8xx/R9xx only support 8 ++ AddrHtileBlockSize blockHeight; ///< 4 or 8. 1 means 8, 0 means 4. R8xx/R9xx only support 8 ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeHtileCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Slice index ++} ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeHtileCoordFromAddr ++* ++* @brief ++* Compute coordinates within depth buffer (1st pixel of a micro tile) according to ++* Htile address ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeHtileCoordFromAddr( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut); ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// C-mask functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* ADDR_CMASK_FLAGS ++* ++* @brief ++* CMASK flags ++*************************************************************************************************** ++*/ ++typedef union _ADDR_CMASK_FLAGS ++{ ++ struct ++ { ++ UINT_32 tcCompatible : 1; ///< Flag indicates surface needs to be shader readable ++ UINT_32 reserved :31; ///< Reserved bits ++ }; ++ ++ UINT_32 value; ++} ADDR_CMASK_FLAGS; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_INFO_INPUT ++* ++* @brief ++* Input structure of AddrComputeCmaskInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASKINFO_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ ADDR_CMASK_FLAGS flags; ///< CMASK flags ++ UINT_32 pitch; ///< Pitch, in pixels, of color buffer ++ UINT_32 height; ///< Height, in pixels, of color buffer ++ UINT_32 numSlices; ///< Number of slices, of color buffer ++ BOOL_32 isLinear; ///< Linear or tiled layout, Only SI can be linear ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_CMASK_INFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_INFO_OUTPUT ++* ++* @brief ++* Output structure of AddrComputeCmaskInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASK_INFO_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 pitch; ///< Pitch in pixels of color buffer which ++ /// this Cmask matches. The size might be larger than ++ /// original color buffer pitch when called with ++ /// an unaligned pitch. ++ UINT_32 height; ///< Height in pixels, as above ++ UINT_64 cmaskBytes; ///< Size in bytes of CMask buffer ++ UINT_32 baseAlign; ///< Base alignment ++ UINT_32 blockMax; ///< Cmask block size. Need this to set CB_COLORn_MASK register ++ UINT_32 macroWidth; ///< Macro width in pixels, actually squared cache shape ++ UINT_32 macroHeight; ///< Macro height in pixels ++ UINT_64 sliceSize; ///< Slice size, in bytes. ++} ADDR_COMPUTE_CMASK_INFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskInfo ++* ++* @brief ++* Compute Cmask pitch, height, base alignment and size in bytes from color buffer ++* info ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT ++* ++* @brief ++* Input structure for AddrComputeCmaskAddrFromCoord ++* ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_64 fmaskAddr; ///< Fmask addr for tc compatible Cmask ++ UINT_32 slice; ///< Slice index ++ UINT_32 pitch; ///< Pitch in pixels, of color buffer ++ UINT_32 height; ///< Height in pixels, of color buffer ++ UINT_32 numSlices; ///< Number of slices ++ UINT_32 bpp; ++ BOOL_32 isLinear; ///< Linear or tiled layout, Only SI can be linear ++ ADDR_CMASK_FLAGS flags; ///< CMASK flags ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ ///< while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeCmaskAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< CMASK address in bytes ++ UINT_32 bitPosition; ///< Bit position within addr, 0-7. CMASK is 4 bpp, ++ /// so the address may be located in bit 0 (0) or 4 (4) ++} ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskAddrFromCoord ++* ++* @brief ++* Compute Cmask address according to coordinates (of MSAA color buffer) ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskAddrFromCoord( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT ++* ++* @brief ++* Input structure for AddrComputeCmaskCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< CMASK address in bytes ++ UINT_32 bitPosition; ///< Bit position within addr, 0-7. CMASK is 4 bpp, ++ /// so the address may be located in bit 0 (0) or 4 (4) ++ UINT_32 pitch; ///< Pitch, in pixels ++ UINT_32 height; ///< Height in pixels ++ UINT_32 numSlices; ///< Number of slices ++ BOOL_32 isLinear; ///< Linear or tiled layout, Only SI can be linear ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeCmaskCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Slice index ++} ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeCmaskCoordFromAddr ++* ++* @brief ++* Compute coordinates within color buffer (1st pixel of a micro tile) according to ++* Cmask address ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeCmaskCoordFromAddr( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut); ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// F-mask functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_INFO_INPUT ++* ++* @brief ++* Input structure for AddrComputeFmaskInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_INFO_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrTileMode tileMode; ///< Tile mode ++ UINT_32 pitch; ///< Surface pitch, in pixels ++ UINT_32 height; ///< Surface height, in pixels ++ UINT_32 numSlices; ///< Number of slice/depth ++ UINT_32 numSamples; ///< Number of samples ++ UINT_32 numFrags; ///< Number of fragments, leave it zero or the same as ++ /// number of samples for normal AA; Set it to the ++ /// number of fragments for EQAA ++ /// r800 and later HWL parameters ++ struct ++ { ++ UINT_32 resolved: 1; ///< TRUE if the surface is for resolved fmask, only used ++ /// by H/W clients. S/W should always set it to FALSE. ++ UINT_32 reserved: 31; ///< Reserved for future use. ++ }; ++ ADDR_TILEINFO* pTileInfo; ///< 2D tiling parameters. Clients must give valid data ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++} ADDR_COMPUTE_FMASK_INFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_INFO_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeFmaskInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_INFO_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 pitch; ///< Pitch of fmask in pixels ++ UINT_32 height; ///< Height of fmask in pixels ++ UINT_32 numSlices; ///< Slices of fmask ++ UINT_64 fmaskBytes; ///< Size of fmask in bytes ++ UINT_32 baseAlign; ///< Base address alignment ++ UINT_32 pitchAlign; ///< Pitch alignment ++ UINT_32 heightAlign; ///< Height alignment ++ UINT_32 bpp; ///< Bits per pixel of FMASK is: number of bit planes ++ UINT_32 numSamples; ///< Number of samples, used for dump, export this since input ++ /// may be changed in 9xx and above ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< Tile parameters used. Fmask can have different ++ /// bank_height from color buffer ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ UINT_64 sliceSize; ///< Size of slice in bytes ++} ADDR_COMPUTE_FMASK_INFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskInfo ++* ++* @brief ++* Compute Fmask pitch/height/depth/alignments and size in bytes ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT ++* ++* @brief ++* Input structure for AddrComputeFmaskAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Slice index ++ UINT_32 plane; ///< Plane number ++ UINT_32 sample; ///< Sample index (fragment index for EQAA) ++ ++ UINT_32 pitch; ///< Surface pitch, in pixels ++ UINT_32 height; ///< Surface height, in pixels ++ UINT_32 numSamples; ///< Number of samples ++ UINT_32 numFrags; ///< Number of fragments, leave it zero or the same as ++ /// number of samples for normal AA; Set it to the ++ /// number of fragments for EQAA ++ ++ AddrTileMode tileMode; ///< Tile mode ++ union ++ { ++ struct ++ { ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++ }; ++ UINT_32 tileSwizzle; ///< Combined swizzle, if useCombinedSwizzle is TRUE ++ }; ++ ++ /// r800 and later HWL parameters ++ struct ++ { ++ UINT_32 resolved: 1; ///< TRUE if this is a resolved fmask, used by H/W clients ++ UINT_32 ignoreSE: 1; ///< TRUE if shader engines are ignored. ++ UINT_32 reserved: 30; ///< Reserved for future use. ++ }; ++ ADDR_TILEINFO* pTileInfo; ///< 2D tiling parameters. Client must provide all data ++ ++} ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeFmaskAddrFromCoord ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Fmask address ++ UINT_32 bitPosition; ///< Bit position within fmaskAddr, 0-7. ++} ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskAddrFromCoord ++* ++* @brief ++* Compute Fmask address according to coordinates (x,y,slice,sample,plane) ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskAddrFromCoord( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT ++* ++* @brief ++* Input structure for AddrComputeFmaskCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_64 addr; ///< Address ++ UINT_32 bitPosition; ///< Bit position within addr, 0-7. ++ ++ UINT_32 pitch; ///< Pitch, in pixels ++ UINT_32 height; ///< Height in pixels ++ UINT_32 numSamples; ///< Number of samples ++ UINT_32 numFrags; ///< Number of fragments ++ AddrTileMode tileMode; ///< Tile mode ++ union ++ { ++ struct ++ { ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++ }; ++ UINT_32 tileSwizzle; ///< Combined swizzle, if useCombinedSwizzle is TRUE ++ }; ++ ++ /// r800 and later HWL parameters ++ struct ++ { ++ UINT_32 resolved: 1; ///< TRUE if this is a resolved fmask, used by HW components ++ UINT_32 ignoreSE: 1; ///< TRUE if shader engines are ignored. ++ UINT_32 reserved: 30; ///< Reserved for future use. ++ }; ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Client must provide all data ++ ++} ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT ++* ++* @brief ++* Output structure for AddrComputeFmaskCoordFromAddr ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 x; ///< X coordinate ++ UINT_32 y; ///< Y coordinate ++ UINT_32 slice; ///< Slice index ++ UINT_32 plane; ///< Plane number ++ UINT_32 sample; ///< Sample index (fragment index for EQAA) ++} ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeFmaskCoordFromAddr ++* ++* @brief ++* Compute FMASK coordinate from an given address ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeFmaskCoordFromAddr( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut); ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Element/utility functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrGetVersion ++* ++* @brief ++* Get AddrLib version number ++*************************************************************************************************** ++*/ ++UINT_32 ADDR_API AddrGetVersion(ADDR_HANDLE hLib); ++ ++/** ++*************************************************************************************************** ++* AddrUseTileIndex ++* ++* @brief ++* Return TRUE if tileIndex is enabled in this address library ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API AddrUseTileIndex(ADDR_HANDLE hLib); ++ ++/** ++*************************************************************************************************** ++* AddrUseCombinedSwizzle ++* ++* @brief ++* Return TRUE if combined swizzle is enabled in this address library ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API AddrUseCombinedSwizzle(ADDR_HANDLE hLib); ++ ++/** ++*************************************************************************************************** ++* ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT ++* ++* @brief ++* Input structure of AddrExtractBankPipeSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 base256b; ///< Base256b value ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Client must provide all data ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT ++* ++* @brief ++* Output structure of AddrExtractBankPipeSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++} ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrExtractBankPipeSwizzle ++* ++* @brief ++* Extract Bank and Pipe swizzle from base256b ++* @return ++* ADDR_OK if no error ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrExtractBankPipeSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut); ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT ++* ++* @brief ++* Input structure of AddrCombineBankPipeSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 bankSwizzle; ///< Bank swizzle ++ UINT_32 pipeSwizzle; ///< Pipe swizzle ++ UINT_64 baseAddr; ///< Base address (leave it zero for driver clients) ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Client must provide all data ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT ++* ++* @brief ++* Output structure of AddrCombineBankPipeSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 tileSwizzle; ///< Combined swizzle ++} ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrCombineBankPipeSwizzle ++* ++* @brief ++* Combine Bank and Pipe swizzle ++* @return ++* ADDR_OK if no error ++* @note ++* baseAddr here is full MCAddress instead of base256b ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrCombineBankPipeSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SLICESWIZZLE_INPUT ++* ++* @brief ++* Input structure of AddrComputeSliceSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SLICESWIZZLE_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrTileMode tileMode; ///< Tile Mode ++ UINT_32 baseSwizzle; ///< Base tile swizzle ++ UINT_32 slice; ///< Slice index ++ UINT_64 baseAddr; ///< Base address, driver should leave it 0 in most cases ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Actually banks needed here! ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_SLICESWIZZLE_INPUT; ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_SLICESWIZZLE_OUTPUT ++* ++* @brief ++* Output structure of AddrComputeSliceSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_SLICESWIZZLE_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 tileSwizzle; ///< Recalculated tileSwizzle value ++} ADDR_COMPUTE_SLICESWIZZLE_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeSliceSwizzle ++* ++* @brief ++* Extract Bank and Pipe swizzle from base256b ++* @return ++* ADDR_OK if no error ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeSliceSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut); ++ ++ ++/** ++*************************************************************************************************** ++* AddrSwizzleGenOption ++* ++* @brief ++* Which swizzle generating options: legacy or linear ++*************************************************************************************************** ++*/ ++typedef enum _AddrSwizzleGenOption ++{ ++ ADDR_SWIZZLE_GEN_DEFAULT = 0, ///< As is in client driver implemention for swizzle ++ ADDR_SWIZZLE_GEN_LINEAR = 1, ///< Using a linear increment of swizzle ++} AddrSwizzleGenOption; ++ ++/** ++*************************************************************************************************** ++* AddrSwizzleOption ++* ++* @brief ++* Controls how swizzle is generated ++*************************************************************************************************** ++*/ ++typedef union _ADDR_SWIZZLE_OPTION ++{ ++ struct ++ { ++ UINT_32 genOption : 1; ///< The way swizzle is generated, see AddrSwizzleGenOption ++ UINT_32 reduceBankBit : 1; ///< TRUE if we need reduce swizzle bits ++ UINT_32 reserved :30; ///< Reserved bits ++ }; ++ ++ UINT_32 value; ++ ++} ADDR_SWIZZLE_OPTION; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_BASE_SWIZZLE_INPUT ++* ++* @brief ++* Input structure of AddrComputeBaseSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_BASE_SWIZZLE_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ ADDR_SWIZZLE_OPTION option; ///< Swizzle option ++ UINT_32 surfIndex; ///< Index of this surface type ++ AddrTileMode tileMode; ///< Tile Mode ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< 2D tile parameters. Actually banks needed here! ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_BASE_SWIZZLE_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT ++* ++* @brief ++* Output structure of AddrComputeBaseSwizzle ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_32 tileSwizzle; ///< Combined swizzle ++} ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeBaseSwizzle ++* ++* @brief ++* Return a Combined Bank and Pipe swizzle base on surface based on surface type/index ++* @return ++* ADDR_OK if no error ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeBaseSwizzle( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ELEM_GETEXPORTNORM_INPUT ++* ++* @brief ++* Input structure for ElemGetExportNorm ++* ++*************************************************************************************************** ++*/ ++typedef struct _ELEM_GETEXPORTNORM_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrColorFormat format; ///< Color buffer format; Client should use ColorFormat ++ AddrSurfaceNumber num; ///< Surface number type; Client should use NumberType ++ AddrSurfaceSwap swap; ///< Surface swap byte swap; Client should use SurfaceSwap ++ UINT_32 numSamples; ///< Number of samples ++} ELEM_GETEXPORTNORM_INPUT; ++ ++/** ++*************************************************************************************************** ++* ElemGetExportNorm ++* ++* @brief ++* Helper function to check one format can be EXPORT_NUM, which is a register ++* CB_COLOR_INFO.SURFACE_FORMAT. FP16 can be reported as EXPORT_NORM for rv770 in r600 ++* family ++* @note ++* The implementation is only for r600. ++* 00 - EXPORT_FULL: PS exports are 4 pixels with 4 components with 32-bits-per-component. (two ++* clocks per export) ++* 01 - EXPORT_NORM: PS exports are 4 pixels with 4 components with 16-bits-per-component. (one ++* clock per export) ++* ++*************************************************************************************************** ++*/ ++BOOL_32 ADDR_API ElemGetExportNorm( ++ ADDR_HANDLE hLib, ++ const ELEM_GETEXPORTNORM_INPUT* pIn); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ELEM_FLT32TODEPTHPIXEL_INPUT ++* ++* @brief ++* Input structure for addrFlt32ToDepthPixel ++* ++*************************************************************************************************** ++*/ ++typedef struct _ELEM_FLT32TODEPTHPIXEL_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrDepthFormat format; ///< Depth buffer format ++ ADDR_FLT_32 comps[2]; ///< Component values (Z/stencil) ++} ELEM_FLT32TODEPTHPIXEL_INPUT; ++ ++/** ++*************************************************************************************************** ++* ELEM_FLT32TODEPTHPIXEL_INPUT ++* ++* @brief ++* Output structure for ElemFlt32ToDepthPixel ++* ++*************************************************************************************************** ++*/ ++typedef struct _ELEM_FLT32TODEPTHPIXEL_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_8* pPixel; ///< Real depth value. Same data type as depth buffer. ++ /// Client must provide enough storage for this type. ++ UINT_32 depthBase; ///< Tile base in bits for depth bits ++ UINT_32 stencilBase; ///< Tile base in bits for stencil bits ++ UINT_32 depthBits; ///< Bits for depth ++ UINT_32 stencilBits; ///< Bits for stencil ++} ELEM_FLT32TODEPTHPIXEL_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* ElemFlt32ToDepthPixel ++* ++* @brief ++* Convert a FLT_32 value to a depth/stencil pixel value ++* ++* @return ++* Return code ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API ElemFlt32ToDepthPixel( ++ ADDR_HANDLE hLib, ++ const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn, ++ ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ELEM_FLT32TOCOLORPIXEL_INPUT ++* ++* @brief ++* Input structure for addrFlt32ToColorPixel ++* ++*************************************************************************************************** ++*/ ++typedef struct _ELEM_FLT32TOCOLORPIXEL_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrColorFormat format; ///< Color buffer format ++ AddrSurfaceNumber surfNum; ///< Surface number ++ AddrSurfaceSwap surfSwap; ///< Surface swap ++ ADDR_FLT_32 comps[4]; ///< Component values (r/g/b/a) ++} ELEM_FLT32TOCOLORPIXEL_INPUT; ++ ++/** ++*************************************************************************************************** ++* ELEM_FLT32TOCOLORPIXEL_INPUT ++* ++* @brief ++* Output structure for ElemFlt32ToColorPixel ++* ++*************************************************************************************************** ++*/ ++typedef struct _ELEM_FLT32TOCOLORPIXEL_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ UINT_8* pPixel; ///< Real color value. Same data type as color buffer. ++ /// Client must provide enough storage for this type. ++} ELEM_FLT32TOCOLORPIXEL_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* ElemFlt32ToColorPixel ++* ++* @brief ++* Convert a FLT_32 value to a red/green/blue/alpha pixel value ++* ++* @return ++* Return code ++* ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API ElemFlt32ToColorPixel( ++ ADDR_HANDLE hLib, ++ const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn, ++ ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut); ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_CONVERT_TILEINFOTOHW_INPUT ++* ++* @brief ++* Input structure for AddrConvertTileInfoToHW ++* @note ++* When reverse is TRUE, indices are igonred ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CONVERT_TILEINFOTOHW_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ BOOL_32 reverse; ///< Convert control flag. ++ /// FALSE: convert from real value to HW value; ++ /// TRUE: convert from HW value to real value. ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< Tile parameters with real value ++ ++ INT_32 tileIndex; ///< Tile index, MUST be -1 if you don't want to use it ++ /// while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_CONVERT_TILEINFOTOHW_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_CONVERT_TILEINFOTOHW_OUTPUT ++* ++* @brief ++* Output structure for AddrConvertTileInfoToHW ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CONVERT_TILEINFOTOHW_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ /// r800 and later HWL parameters ++ ADDR_TILEINFO* pTileInfo; ///< Tile parameters with hardware register value ++ ++} ADDR_CONVERT_TILEINFOTOHW_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileInfoToHW ++* ++* @brief ++* Convert tile info from real value to hardware register value ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileInfoToHW( ++ ADDR_HANDLE hLib, ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_CONVERT_TILEINDEX_INPUT ++* ++* @brief ++* Input structure for AddrConvertTileIndex ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CONVERT_TILEINDEX_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ INT_32 tileIndex; ///< Tile index ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ BOOL_32 tileInfoHw; ///< Set to TRUE if client wants HW enum, otherwise actual ++} ADDR_CONVERT_TILEINDEX_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_CONVERT_TILEINDEX_OUTPUT ++* ++* @brief ++* Output structure for AddrConvertTileIndex ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CONVERT_TILEINDEX_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrTileMode tileMode; ///< Tile mode ++ AddrTileType tileType; ///< Tile type ++ ADDR_TILEINFO* pTileInfo; ///< Tile info ++ ++} ADDR_CONVERT_TILEINDEX_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileIndex ++* ++* @brief ++* Convert tile index to tile mode/type/info ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileIndex( ++ ADDR_HANDLE hLib, ++ const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_CONVERT_TILEINDEX1_INPUT ++* ++* @brief ++* Input structure for AddrConvertTileIndex1 (without macro mode index) ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_CONVERT_TILEINDEX1_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ INT_32 tileIndex; ///< Tile index ++ UINT_32 bpp; ///< Bits per pixel ++ UINT_32 numSamples; ///< Number of samples ++ BOOL_32 tileInfoHw; ///< Set to TRUE if client wants HW enum, otherwise actual ++} ADDR_CONVERT_TILEINDEX1_INPUT; ++ ++/** ++*************************************************************************************************** ++* AddrConvertTileIndex1 ++* ++* @brief ++* Convert tile index to tile mode/type/info ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrConvertTileIndex1( ++ ADDR_HANDLE hLib, ++ const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut); ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_GET_TILEINDEX_INPUT ++* ++* @brief ++* Input structure for AddrGetTileIndex ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_GET_TILEINDEX_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ AddrTileMode tileMode; ///< Tile mode ++ AddrTileType tileType; ///< Tile-type: disp/non-disp/... ++ ADDR_TILEINFO* pTileInfo; ///< Pointer to tile-info structure, can be NULL for linear/1D ++} ADDR_GET_TILEINDEX_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_GET_TILEINDEX_OUTPUT ++* ++* @brief ++* Output structure for AddrGetTileIndex ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_GET_TILEINDEX_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ ++ INT_32 index; ///< index in table ++} ADDR_GET_TILEINDEX_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrGetTileIndex ++* ++* @brief ++* Get the tiling mode index in table ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrGetTileIndex( ++ ADDR_HANDLE hLib, ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut); ++ ++ ++ ++ ++/** ++*************************************************************************************************** ++* ADDR_PRT_INFO_INPUT ++* ++* @brief ++* Input structure for AddrComputePrtInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_PRT_INFO_INPUT ++{ ++ AddrFormat format; ///< Surface format ++ UINT_32 baseMipWidth; ///< Base mipmap width ++ UINT_32 baseMipHeight; ///< Base mipmap height ++ UINT_32 baseMipDepth; ///< Base mipmap depth ++ UINT_32 numFrags; ///< Number of fragments, ++} ADDR_PRT_INFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_PRT_INFO_OUTPUT ++* ++* @brief ++* Input structure for AddrComputePrtInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_PRT_INFO_OUTPUT ++{ ++ UINT_32 prtTileWidth; ++ UINT_32 prtTileHeight; ++} ADDR_PRT_INFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputePrtInfo ++* ++* @brief ++* Compute prt surface related information ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputePrtInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_PRT_INFO_INPUT* pIn, ++ ADDR_PRT_INFO_OUTPUT* pOut); ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// DCC key functions ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* _ADDR_COMPUTE_DCCINFO_INPUT ++* ++* @brief ++* Input structure of AddrComputeDccInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_DCCINFO_INPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ UINT_32 bpp; ///< BitPP of color surface ++ UINT_32 numSamples; ///< Sample number of color surface ++ UINT_64 colorSurfSize; ///< Size of color surface to which dcc key is bound ++ AddrTileMode tileMode; ///< Tile mode of color surface ++ ADDR_TILEINFO tileInfo; ///< Tile info of color surface ++ UINT_32 tileSwizzle; ///< Tile swizzle ++ INT_32 tileIndex; ///< Tile index of color surface, ++ ///< MUST be -1 if you don't want to use it ++ ///< while the global useTileIndex is set to 1 ++ INT_32 macroModeIndex; ///< Index in macro tile mode table if there is one (CI) ++ ///< README: When tileIndex is not -1, this must be valid ++} ADDR_COMPUTE_DCCINFO_INPUT; ++ ++/** ++*************************************************************************************************** ++* ADDR_COMPUTE_DCCINFO_OUTPUT ++* ++* @brief ++* Output structure of AddrComputeDccInfo ++*************************************************************************************************** ++*/ ++typedef struct _ADDR_COMPUTE_DCCINFO_OUTPUT ++{ ++ UINT_32 size; ///< Size of this structure in bytes ++ UINT_64 dccRamBaseAlign; ///< Base alignment of dcc key ++ UINT_64 dccRamSize; ///< Size of dcc key ++ UINT_64 dccFastClearSize; ///< Size of dcc key portion that can be fast cleared ++ BOOL_32 subLvlCompressible; ///< whether sub resource is compressiable ++} ADDR_COMPUTE_DCCINFO_OUTPUT; ++ ++/** ++*************************************************************************************************** ++* AddrComputeDccInfo ++* ++* @brief ++* Compute DCC key size, base alignment ++* info ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE ADDR_API AddrComputeDccInfo( ++ ADDR_HANDLE hLib, ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut); ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif // __ADDR_INTERFACE_H__ ++ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/addrtypes.h b/src/gallium/winsys/radeon/amdgpu/addrlib/addrtypes.h +new file mode 100644 +index 0000000..4c68ac5 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/addrtypes.h +@@ -0,0 +1,590 @@ ++/* ++ * 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 addrtypes.h ++* @brief Contains the helper function and constants ++*************************************************************************************************** ++*/ ++#ifndef __ADDR_TYPES_H__ ++#define __ADDR_TYPES_H__ ++ ++#if defined(__APPLE__) || defined(TCORE_BUILD) ++// External definitions header maintained by Mac driver team (and TCORE team) ++// Helps address compilation issues & reduces code covered by NDA ++#include "addrExtDef.h" ++ ++#else ++ ++// Windows and/or Linux ++#if !defined(VOID) ++typedef void VOID; ++#endif ++ ++#if !defined(FLOAT) ++typedef float FLOAT; ++#endif ++ ++#if !defined(CHAR) ++typedef char CHAR; ++#endif ++ ++#if !defined(INT) ++typedef int INT; ++#endif ++ ++#include <stdarg.h> // va_list...etc need this header ++ ++#endif // defined (__APPLE__) ++ ++/** ++*************************************************************************************************** ++* Calling conventions ++*************************************************************************************************** ++*/ ++#ifndef ADDR_CDECL ++ #if defined(__GNUC__) ++ #define ADDR_CDECL __attribute__((cdecl)) ++ #else ++ #define ADDR_CDECL __cdecl ++ #endif ++#endif ++ ++#ifndef ADDR_STDCALL ++ #if defined(__GNUC__) ++ #if defined(__AMD64__) ++ #define ADDR_STDCALL ++ #else ++ #define ADDR_STDCALL __attribute__((stdcall)) ++ #endif ++ #else ++ #define ADDR_STDCALL __stdcall ++ #endif ++#endif ++ ++#ifndef ADDR_FASTCALL ++ #if defined(__GNUC__) ++ #define ADDR_FASTCALL __attribute__((regparm(0))) ++ #else ++ #define ADDR_FASTCALL __fastcall ++ #endif ++#endif ++ ++#ifndef GC_CDECL ++ #define GC_CDECL ADDR_CDECL ++#endif ++ ++#ifndef GC_STDCALL ++ #define GC_STDCALL ADDR_STDCALL ++#endif ++ ++#ifndef GC_FASTCALL ++ #define GC_FASTCALL ADDR_FASTCALL ++#endif ++ ++ ++#if defined(__GNUC__) ++ #define ADDR_INLINE static inline // inline needs to be static to link ++#else ++ // win32, win64, other platforms ++ #define ADDR_INLINE __inline ++#endif // #if defined(__GNUC__) ++ ++#define ADDR_API ADDR_FASTCALL //default call convention is fast call ++ ++/** ++*************************************************************************************************** ++* Global defines used by other modules ++*************************************************************************************************** ++*/ ++#if !defined(TILEINDEX_INVALID) ++#define TILEINDEX_INVALID -1 ++#endif ++ ++#if !defined(TILEINDEX_LINEAR_GENERAL) ++#define TILEINDEX_LINEAR_GENERAL -2 ++#endif ++ ++#if !defined(TILEINDEX_LINEAR_ALIGNED) ++#define TILEINDEX_LINEAR_ALIGNED 8 ++#endif ++ ++/** ++*************************************************************************************************** ++* Return codes ++*************************************************************************************************** ++*/ ++typedef enum _ADDR_E_RETURNCODE ++{ ++ // General Return ++ ADDR_OK = 0, ++ ADDR_ERROR = 1, ++ ++ // Specific Errors ++ ADDR_OUTOFMEMORY, ++ ADDR_INVALIDPARAMS, ++ ADDR_NOTSUPPORTED, ++ ADDR_NOTIMPLEMENTED, ++ ADDR_PARAMSIZEMISMATCH, ++ ADDR_INVALIDGBREGVALUES, ++ ++} ADDR_E_RETURNCODE; ++ ++/** ++*************************************************************************************************** ++* @brief ++* Neutral enums that define tile modes for all H/W ++* @note ++* R600/R800 tiling mode can be cast to hw enums directly but never cast into HW enum from ++* ADDR_TM_2D_TILED_XTHICK ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrTileMode ++{ ++ ADDR_TM_LINEAR_GENERAL = 0, ///< Least restrictions, pitch: multiple of 8 if not buffer ++ ADDR_TM_LINEAR_ALIGNED = 1, ///< Requests pitch or slice to be multiple of 64 pixels ++ ADDR_TM_1D_TILED_THIN1 = 2, ///< Linear array of 8x8 tiles ++ ADDR_TM_1D_TILED_THICK = 3, ///< Linear array of 8x8x4 tiles ++ ADDR_TM_2D_TILED_THIN1 = 4, ///< A set of macro tiles consist of 8x8 tiles ++ ADDR_TM_2D_TILED_THIN2 = 5, ///< 600 HWL only, macro tile ratio is 1:4 ++ ADDR_TM_2D_TILED_THIN4 = 6, ///< 600 HWL only, macro tile ratio is 1:16 ++ ADDR_TM_2D_TILED_THICK = 7, ///< A set of macro tiles consist of 8x8x4 tiles ++ ADDR_TM_2B_TILED_THIN1 = 8, ///< 600 HWL only, with bank swap ++ ADDR_TM_2B_TILED_THIN2 = 9, ///< 600 HWL only, with bank swap and ratio is 1:4 ++ ADDR_TM_2B_TILED_THIN4 = 10, ///< 600 HWL only, with bank swap and ratio is 1:16 ++ ADDR_TM_2B_TILED_THICK = 11, ///< 600 HWL only, with bank swap, consists of 8x8x4 tiles ++ ADDR_TM_3D_TILED_THIN1 = 12, ///< Macro tiling w/ pipe rotation between slices ++ ADDR_TM_3D_TILED_THICK = 13, ///< Macro tiling w/ pipe rotation bwtween slices, thick ++ ADDR_TM_3B_TILED_THIN1 = 14, ///< 600 HWL only, with bank swap ++ ADDR_TM_3B_TILED_THICK = 15, ///< 600 HWL only, with bank swap, thick ++ ADDR_TM_2D_TILED_XTHICK = 16, ///< Tile is 8x8x8, valid from NI ++ ADDR_TM_3D_TILED_XTHICK = 17, ///< Tile is 8x8x8, valid from NI ++ ADDR_TM_POWER_SAVE = 18, ///< Power save mode, only used by KMD on NI ++ ADDR_TM_PRT_TILED_THIN1 = 19, ///< No bank/pipe rotation or hashing beyond macrotile size ++ ADDR_TM_PRT_2D_TILED_THIN1 = 20, ///< Same as 2D_TILED_THIN1, PRT only ++ ADDR_TM_PRT_3D_TILED_THIN1 = 21, ///< Same as 3D_TILED_THIN1, PRT only ++ ADDR_TM_PRT_TILED_THICK = 22, ///< No bank/pipe rotation or hashing beyond macrotile size ++ ADDR_TM_PRT_2D_TILED_THICK = 23, ///< Same as 2D_TILED_THICK, PRT only ++ ADDR_TM_PRT_3D_TILED_THICK = 24, ///< Same as 3D_TILED_THICK, PRT only ++ ADDR_TM_COUNT = 25, ///< Must be the value of the last tile mode ++} AddrTileMode; ++ ++/** ++*************************************************************************************************** ++* AddrFormat ++* ++* @brief ++* Neutral enum for SurfaceFormat ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrFormat { ++ ADDR_FMT_INVALID = 0x00000000, ++ ADDR_FMT_8 = 0x00000001, ++ ADDR_FMT_4_4 = 0x00000002, ++ ADDR_FMT_3_3_2 = 0x00000003, ++ ADDR_FMT_RESERVED_4 = 0x00000004, ++ ADDR_FMT_16 = 0x00000005, ++ ADDR_FMT_16_FLOAT = 0x00000006, ++ ADDR_FMT_8_8 = 0x00000007, ++ ADDR_FMT_5_6_5 = 0x00000008, ++ ADDR_FMT_6_5_5 = 0x00000009, ++ ADDR_FMT_1_5_5_5 = 0x0000000a, ++ ADDR_FMT_4_4_4_4 = 0x0000000b, ++ ADDR_FMT_5_5_5_1 = 0x0000000c, ++ ADDR_FMT_32 = 0x0000000d, ++ ADDR_FMT_32_FLOAT = 0x0000000e, ++ ADDR_FMT_16_16 = 0x0000000f, ++ ADDR_FMT_16_16_FLOAT = 0x00000010, ++ ADDR_FMT_8_24 = 0x00000011, ++ ADDR_FMT_8_24_FLOAT = 0x00000012, ++ ADDR_FMT_24_8 = 0x00000013, ++ ADDR_FMT_24_8_FLOAT = 0x00000014, ++ ADDR_FMT_10_11_11 = 0x00000015, ++ ADDR_FMT_10_11_11_FLOAT = 0x00000016, ++ ADDR_FMT_11_11_10 = 0x00000017, ++ ADDR_FMT_11_11_10_FLOAT = 0x00000018, ++ ADDR_FMT_2_10_10_10 = 0x00000019, ++ ADDR_FMT_8_8_8_8 = 0x0000001a, ++ ADDR_FMT_10_10_10_2 = 0x0000001b, ++ ADDR_FMT_X24_8_32_FLOAT = 0x0000001c, ++ ADDR_FMT_32_32 = 0x0000001d, ++ ADDR_FMT_32_32_FLOAT = 0x0000001e, ++ ADDR_FMT_16_16_16_16 = 0x0000001f, ++ ADDR_FMT_16_16_16_16_FLOAT = 0x00000020, ++ ADDR_FMT_RESERVED_33 = 0x00000021, ++ ADDR_FMT_32_32_32_32 = 0x00000022, ++ ADDR_FMT_32_32_32_32_FLOAT = 0x00000023, ++ ADDR_FMT_RESERVED_36 = 0x00000024, ++ ADDR_FMT_1 = 0x00000025, ++ ADDR_FMT_1_REVERSED = 0x00000026, ++ ADDR_FMT_GB_GR = 0x00000027, ++ ADDR_FMT_BG_RG = 0x00000028, ++ ADDR_FMT_32_AS_8 = 0x00000029, ++ ADDR_FMT_32_AS_8_8 = 0x0000002a, ++ ADDR_FMT_5_9_9_9_SHAREDEXP = 0x0000002b, ++ ADDR_FMT_8_8_8 = 0x0000002c, ++ ADDR_FMT_16_16_16 = 0x0000002d, ++ ADDR_FMT_16_16_16_FLOAT = 0x0000002e, ++ ADDR_FMT_32_32_32 = 0x0000002f, ++ ADDR_FMT_32_32_32_FLOAT = 0x00000030, ++ ADDR_FMT_BC1 = 0x00000031, ++ ADDR_FMT_BC2 = 0x00000032, ++ ADDR_FMT_BC3 = 0x00000033, ++ ADDR_FMT_BC4 = 0x00000034, ++ ADDR_FMT_BC5 = 0x00000035, ++ ADDR_FMT_BC6 = 0x00000036, ++ ADDR_FMT_BC7 = 0x00000037, ++ ADDR_FMT_32_AS_32_32_32_32 = 0x00000038, ++ ADDR_FMT_APC3 = 0x00000039, ++ ADDR_FMT_APC4 = 0x0000003a, ++ ADDR_FMT_APC5 = 0x0000003b, ++ ADDR_FMT_APC6 = 0x0000003c, ++ ADDR_FMT_APC7 = 0x0000003d, ++ ADDR_FMT_CTX1 = 0x0000003e, ++ ADDR_FMT_RESERVED_63 = 0x0000003f, ++} AddrFormat; ++ ++/** ++*************************************************************************************************** ++* AddrDepthFormat ++* ++* @brief ++* Neutral enum for addrFlt32ToDepthPixel ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrDepthFormat ++{ ++ ADDR_DEPTH_INVALID = 0x00000000, ++ ADDR_DEPTH_16 = 0x00000001, ++ ADDR_DEPTH_X8_24 = 0x00000002, ++ ADDR_DEPTH_8_24 = 0x00000003, ++ ADDR_DEPTH_X8_24_FLOAT = 0x00000004, ++ ADDR_DEPTH_8_24_FLOAT = 0x00000005, ++ ADDR_DEPTH_32_FLOAT = 0x00000006, ++ ADDR_DEPTH_X24_8_32_FLOAT = 0x00000007, ++ ++} AddrDepthFormat; ++ ++/** ++*************************************************************************************************** ++* AddrColorFormat ++* ++* @brief ++* Neutral enum for ColorFormat ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrColorFormat ++{ ++ ADDR_COLOR_INVALID = 0x00000000, ++ ADDR_COLOR_8 = 0x00000001, ++ ADDR_COLOR_4_4 = 0x00000002, ++ ADDR_COLOR_3_3_2 = 0x00000003, ++ ADDR_COLOR_RESERVED_4 = 0x00000004, ++ ADDR_COLOR_16 = 0x00000005, ++ ADDR_COLOR_16_FLOAT = 0x00000006, ++ ADDR_COLOR_8_8 = 0x00000007, ++ ADDR_COLOR_5_6_5 = 0x00000008, ++ ADDR_COLOR_6_5_5 = 0x00000009, ++ ADDR_COLOR_1_5_5_5 = 0x0000000a, ++ ADDR_COLOR_4_4_4_4 = 0x0000000b, ++ ADDR_COLOR_5_5_5_1 = 0x0000000c, ++ ADDR_COLOR_32 = 0x0000000d, ++ ADDR_COLOR_32_FLOAT = 0x0000000e, ++ ADDR_COLOR_16_16 = 0x0000000f, ++ ADDR_COLOR_16_16_FLOAT = 0x00000010, ++ ADDR_COLOR_8_24 = 0x00000011, ++ ADDR_COLOR_8_24_FLOAT = 0x00000012, ++ ADDR_COLOR_24_8 = 0x00000013, ++ ADDR_COLOR_24_8_FLOAT = 0x00000014, ++ ADDR_COLOR_10_11_11 = 0x00000015, ++ ADDR_COLOR_10_11_11_FLOAT = 0x00000016, ++ ADDR_COLOR_11_11_10 = 0x00000017, ++ ADDR_COLOR_11_11_10_FLOAT = 0x00000018, ++ ADDR_COLOR_2_10_10_10 = 0x00000019, ++ ADDR_COLOR_8_8_8_8 = 0x0000001a, ++ ADDR_COLOR_10_10_10_2 = 0x0000001b, ++ ADDR_COLOR_X24_8_32_FLOAT = 0x0000001c, ++ ADDR_COLOR_32_32 = 0x0000001d, ++ ADDR_COLOR_32_32_FLOAT = 0x0000001e, ++ ADDR_COLOR_16_16_16_16 = 0x0000001f, ++ ADDR_COLOR_16_16_16_16_FLOAT = 0x00000020, ++ ADDR_COLOR_RESERVED_33 = 0x00000021, ++ ADDR_COLOR_32_32_32_32 = 0x00000022, ++ ADDR_COLOR_32_32_32_32_FLOAT = 0x00000023, ++} AddrColorFormat; ++ ++/** ++*************************************************************************************************** ++* AddrSurfaceNumber ++* ++* @brief ++* Neutral enum for SurfaceNumber ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrSurfaceNumber { ++ ADDR_NUMBER_UNORM = 0x00000000, ++ ADDR_NUMBER_SNORM = 0x00000001, ++ ADDR_NUMBER_USCALED = 0x00000002, ++ ADDR_NUMBER_SSCALED = 0x00000003, ++ ADDR_NUMBER_UINT = 0x00000004, ++ ADDR_NUMBER_SINT = 0x00000005, ++ ADDR_NUMBER_SRGB = 0x00000006, ++ ADDR_NUMBER_FLOAT = 0x00000007, ++} AddrSurfaceNumber; ++ ++/** ++*************************************************************************************************** ++* AddrSurfaceSwap ++* ++* @brief ++* Neutral enum for SurfaceSwap ++* ++*************************************************************************************************** ++*/ ++typedef enum _AddrSurfaceSwap { ++ ADDR_SWAP_STD = 0x00000000, ++ ADDR_SWAP_ALT = 0x00000001, ++ ADDR_SWAP_STD_REV = 0x00000002, ++ ADDR_SWAP_ALT_REV = 0x00000003, ++} AddrSurfaceSwap; ++ ++/** ++*************************************************************************************************** ++* AddrHtileBlockSize ++* ++* @brief ++* Size of HTILE blocks, valid values are 4 or 8 for now ++*************************************************************************************************** ++*/ ++typedef enum _AddrHtileBlockSize ++{ ++ ADDR_HTILE_BLOCKSIZE_4 = 4, ++ ADDR_HTILE_BLOCKSIZE_8 = 8, ++} AddrHtileBlockSize; ++ ++ ++/** ++*************************************************************************************************** ++* AddrPipeCfg ++* ++* @brief ++* The pipe configuration field specifies both the number of pipes and ++* how pipes are interleaved on the surface. ++* The expression of number of pipes, the shader engine tile size, and packer tile size ++* is encoded in a PIPE_CONFIG register field. ++* In general the number of pipes usually matches the number of memory channels of the ++* hardware configuration. ++* For hw configurations w/ non-pow2 memory number of memory channels, it usually matches ++* the number of ROP units(? TODO: which registers??) ++* The enum value = hw enum + 1 which is to reserve 0 for requesting default. ++*************************************************************************************************** ++*/ ++typedef enum _AddrPipeCfg ++{ ++ ADDR_PIPECFG_INVALID = 0, ++ ADDR_PIPECFG_P2 = 1, /// 2 pipes, ++ ADDR_PIPECFG_P4_8x16 = 5, /// 4 pipes, ++ ADDR_PIPECFG_P4_16x16 = 6, ++ ADDR_PIPECFG_P4_16x32 = 7, ++ ADDR_PIPECFG_P4_32x32 = 8, ++ ADDR_PIPECFG_P8_16x16_8x16 = 9, /// 8 pipes ++ ADDR_PIPECFG_P8_16x32_8x16 = 10, ++ ADDR_PIPECFG_P8_32x32_8x16 = 11, ++ ADDR_PIPECFG_P8_16x32_16x16 = 12, ++ ADDR_PIPECFG_P8_32x32_16x16 = 13, ++ ADDR_PIPECFG_P8_32x32_16x32 = 14, ++ ADDR_PIPECFG_P8_32x64_32x32 = 15, ++ ADDR_PIPECFG_P16_32x32_8x16 = 17, /// 16 pipes ++ ADDR_PIPECFG_P16_32x32_16x16 = 18, ++ ADDR_PIPECFG_MAX = 19, ++} AddrPipeCfg; ++ ++/** ++*************************************************************************************************** ++* AddrTileType ++* ++* @brief ++* Neutral enums that specifies micro tile type (MICRO_TILE_MODE) ++*************************************************************************************************** ++*/ ++typedef enum _AddrTileType ++{ ++ ADDR_DISPLAYABLE = 0, ///< Displayable tiling ++ ADDR_NON_DISPLAYABLE = 1, ///< Non-displayable tiling, a.k.a thin micro tiling ++ ADDR_DEPTH_SAMPLE_ORDER = 2, ///< Same as non-displayable plus depth-sample-order ++ ADDR_ROTATED = 3, ///< Rotated displayable tiling ++ ADDR_THICK = 4, ///< Thick micro-tiling, only valid for THICK and XTHICK ++} AddrTileType; ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// ++// Type definitions: short system-independent names for address library types ++// ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++#if !defined(__APPLE__) ++ ++#ifndef BOOL_32 // no bool type in C ++/// @brief Boolean type, since none is defined in C ++/// @ingroup type ++#define BOOL_32 int ++#endif ++ ++#ifndef INT_32 ++#define INT_32 int ++#endif ++ ++#ifndef UINT_32 ++#define UINT_32 unsigned int ++#endif ++ ++#ifndef INT_16 ++#define INT_16 short ++#endif ++ ++#ifndef UINT_16 ++#define UINT_16 unsigned short ++#endif ++ ++#ifndef INT_8 ++#define INT_8 char ++#endif ++ ++#ifndef UINT_8 ++#define UINT_8 unsigned char ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++// ++// 64-bit integer types depend on the compiler ++// ++#if defined( __GNUC__ ) || defined( __WATCOMC__ ) ++#define INT_64 long long ++#define UINT_64 unsigned long long ++ ++#elif defined( _WIN32 ) ++#define INT_64 __int64 ++#define UINT_64 unsigned __int64 ++ ++#else ++#error Unsupported compiler and/or operating system for 64-bit integers ++ ++/// @brief 64-bit signed integer type (compiler dependent) ++/// @ingroup type ++/// ++/// The addrlib defines a 64-bit signed integer type for either ++/// Gnu/Watcom compilers (which use the first syntax) or for ++/// the Windows VCC compiler (which uses the second syntax). ++#define INT_64 long long OR __int64 ++ ++/// @brief 64-bit unsigned integer type (compiler dependent) ++/// @ingroup type ++/// ++/// The addrlib defines a 64-bit unsigned integer type for either ++/// Gnu/Watcom compilers (which use the first syntax) or for ++/// the Windows VCC compiler (which uses the second syntax). ++/// ++#define UINT_64 unsigned long long OR unsigned __int64 ++#endif ++ ++#endif // #if !defined(__APPLE__) ++ ++// ADDR64X is used to print addresses in hex form on both Windows and Linux ++// ++#if defined( __GNUC__ ) || defined( __WATCOMC__ ) ++#define ADDR64X "llx" ++#define ADDR64D "lld" ++ ++#elif defined( _WIN32 ) ++#define ADDR64X "I64x" ++#define ADDR64D "I64d" ++ ++#else ++#error Unsupported compiler and/or operating system for 64-bit integers ++ ++/// @brief Addrlib device address 64-bit printf tag (compiler dependent) ++/// @ingroup type ++/// ++/// This allows printf to display an ADDR_64 for either the Windows VCC compiler ++/// (which used this value) or the Gnu/Watcom compilers (which use "llx". ++/// An example of use is printf("addr 0x%"ADDR64X"\n", address); ++/// ++#define ADDR64X "llx" OR "I64x" ++#define ADDR64D "lld" OR "I64d" ++#endif ++ ++ ++/// @brief Union for storing a 32-bit float or 32-bit integer ++/// @ingroup type ++/// ++/// This union provides a simple way to convert between a 32-bit float ++/// and a 32-bit integer. It also prevents the compiler from producing ++/// code that alters NaN values when assiging or coying floats. ++/// Therefore, all address library routines that pass or return 32-bit ++/// floating point data do so by passing or returning a FLT_32. ++/// ++typedef union { ++ INT_32 i; ++ UINT_32 u; ++ float f; ++} ADDR_FLT_32; ++ ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// ++// Macros for controlling linking and building on multiple systems ++// ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++#if defined(_MSC_VER) ++#if defined(va_copy) ++#undef va_copy //redefine va_copy to support VC2013 ++#endif ++#endif ++ ++#if !defined(va_copy) ++#define va_copy(dst, src) \ ++ ((void) memcpy(&(dst), &(src), sizeof(va_list))) ++#endif ++ ++#endif // __ADDR_TYPES_H__ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrcommon.h b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrcommon.h +new file mode 100644 +index 0000000..f996c9a +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrcommon.h +@@ -0,0 +1,558 @@ ++/* ++ * 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 addrcommon.h ++* @brief Contains the helper function and constants ++*************************************************************************************************** ++*/ ++ ++#ifndef __ADDR_COMMON_H__ ++#define __ADDR_COMMON_H__ ++ ++#include "addrinterface.h" ++ ++ ++// ADDR_LNX_KERNEL_BUILD is for internal build ++// Moved from addrinterface.h so __KERNEL__ is not needed any more ++#if ADDR_LNX_KERNEL_BUILD // || (defined(__GNUC__) && defined(__KERNEL__)) ++ #include "lnx_common_defs.h" // ported from cmmqs ++#elif !defined(__APPLE__) ++ #include <stdlib.h> ++ #include <string.h> ++#endif ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Common constants ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++static const UINT_32 MicroTileWidth = 8; ///< Micro tile width, for 1D and 2D tiling ++static const UINT_32 MicroTileHeight = 8; ///< Micro tile height, for 1D and 2D tiling ++static const UINT_32 ThickTileThickness = 4; ///< Micro tile thickness, for THICK modes ++static const UINT_32 XThickTileThickness = 8; ///< Extra thick tiling thickness ++static const UINT_32 PowerSaveTileBytes = 64; ///< Nuber of bytes per tile for power save 64 ++static const UINT_32 CmaskCacheBits = 1024; ///< Number of bits for CMASK cache ++static const UINT_32 CmaskElemBits = 4; ///< Number of bits for CMASK element ++static const UINT_32 HtileCacheBits = 16384; ///< Number of bits for HTILE cache 512*32 ++ ++static const UINT_32 MicroTilePixels = MicroTileWidth * MicroTileHeight; ++ ++static const INT_32 TileIndexInvalid = TILEINDEX_INVALID; ++static const INT_32 TileIndexLinearGeneral = TILEINDEX_LINEAR_GENERAL; ++static const INT_32 TileIndexNoMacroIndex = -3; ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Common macros ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++#define BITS_PER_BYTE 8 ++#define BITS_TO_BYTES(x) ( ((x) + (BITS_PER_BYTE-1)) / BITS_PER_BYTE ) ++#define BYTES_TO_BITS(x) ( (x) * BITS_PER_BYTE ) ++ ++/// Helper macros to select a single bit from an int (undefined later in section) ++#define _BIT(v,b) (((v) >> (b) ) & 1) ++ ++/** ++*************************************************************************************************** ++* @brief Enums to identify AddrLib type ++*************************************************************************************************** ++*/ ++enum AddrLibClass ++{ ++ BASE_ADDRLIB = 0x0, ++ R600_ADDRLIB = 0x6, ++ R800_ADDRLIB = 0x8, ++ SI_ADDRLIB = 0xa, ++ CI_ADDRLIB = 0xb, ++}; ++ ++/** ++*************************************************************************************************** ++* AddrChipFamily ++* ++* @brief ++* Neutral enums that specifies chip family. ++* ++*************************************************************************************************** ++*/ ++enum AddrChipFamily ++{ ++ ADDR_CHIP_FAMILY_IVLD, ///< Invalid family ++ ADDR_CHIP_FAMILY_R6XX, ++ ADDR_CHIP_FAMILY_R7XX, ++ ADDR_CHIP_FAMILY_R8XX, ++ ADDR_CHIP_FAMILY_NI, ++ ADDR_CHIP_FAMILY_SI, ++ ADDR_CHIP_FAMILY_CI, ++ ADDR_CHIP_FAMILY_VI, ++}; ++ ++/** ++*************************************************************************************************** ++* ADDR_CONFIG_FLAGS ++* ++* @brief ++* This structure is used to set addr configuration flags. ++*************************************************************************************************** ++*/ ++union ADDR_CONFIG_FLAGS ++{ ++ struct ++ { ++ /// Clients do not need to set these flags except forceLinearAligned. ++ /// There flags are set up by AddrLib inside thru AddrInitGlobalParamsFromRegister ++ UINT_32 optimalBankSwap : 1; ///< New bank tiling for RV770 only ++ UINT_32 noCubeMipSlicesPad : 1; ///< Disables faces padding for cubemap mipmaps ++ UINT_32 fillSizeFields : 1; ///< If clients fill size fields in all input and ++ /// output structure ++ UINT_32 ignoreTileInfo : 1; ///< Don't use tile info structure ++ UINT_32 useTileIndex : 1; ///< Make tileIndex field in input valid ++ UINT_32 useCombinedSwizzle : 1; ///< Use combined swizzle ++ UINT_32 checkLast2DLevel : 1; ///< Check the last 2D mip sub level ++ UINT_32 useHtileSliceAlign : 1; ///< Do htile single slice alignment ++ UINT_32 degradeBaseLevel : 1; ///< Degrade to 1D modes automatically for base level ++ UINT_32 allowLargeThickTile : 1; ///< Allow 64*thickness*bytesPerPixel > rowSize ++ UINT_32 reserved : 22; ///< Reserved bits for future use ++ }; ++ ++ UINT_32 value; ++}; ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Platform specific debug break defines ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++#if DEBUG ++ #if defined(__GNUC__) ++ #define ADDR_DBG_BREAK() ++ #elif defined(__APPLE__) ++ #define ADDR_DBG_BREAK() { IOPanic("");} ++ #else ++ #define ADDR_DBG_BREAK() { __debugbreak(); } ++ #endif ++#else ++ #define ADDR_DBG_BREAK() ++#endif ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Debug assertions used in AddrLib ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++#if DEBUG ++#define ADDR_ASSERT(__e) if ( !((__e) ? TRUE : FALSE)) { ADDR_DBG_BREAK(); } ++#define ADDR_ASSERT_ALWAYS() ADDR_DBG_BREAK() ++#define ADDR_UNHANDLED_CASE() ADDR_ASSERT(!"Unhandled case") ++#define ADDR_NOT_IMPLEMENTED() ADDR_ASSERT(!"Not implemented"); ++#else //DEBUG ++#define ADDR_ASSERT(__e) ++#define ADDR_ASSERT_ALWAYS() ++#define ADDR_UNHANDLED_CASE() ++#define ADDR_NOT_IMPLEMENTED() ++#endif //DEBUG ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Debug print macro from legacy address library ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++#if DEBUG ++ ++#define ADDR_PRNT(a) AddrObject::DebugPrint a ++ ++/// @brief Macro for reporting informational messages ++/// @ingroup util ++/// ++/// This macro optionally prints an informational message to stdout. ++/// The first parameter is a condition -- if it is true, nothing is done. ++/// The second pararmeter MUST be a parenthesis-enclosed list of arguments, ++/// starting with a string. This is passed to printf() or an equivalent ++/// in order to format the informational message. For example, ++/// ADDR_INFO(0, ("test %d",3) ); prints out "test 3". ++/// ++#define ADDR_INFO(cond, a) \ ++{ if (!(cond)) { ADDR_PRNT(a); } } ++ ++ ++/// @brief Macro for reporting error warning messages ++/// @ingroup util ++/// ++/// This macro optionally prints an error warning message to stdout, ++/// followed by the file name and line number where the macro was called. ++/// The first parameter is a condition -- if it is true, nothing is done. ++/// The second pararmeter MUST be a parenthesis-enclosed list of arguments, ++/// starting with a string. This is passed to printf() or an equivalent ++/// in order to format the informational message. For example, ++/// ADDR_WARN(0, ("test %d",3) ); prints out "test 3" followed by ++/// a second line with the file name and line number. ++/// ++#define ADDR_WARN(cond, a) \ ++{ if (!(cond)) \ ++ { ADDR_PRNT(a); \ ++ ADDR_PRNT((" WARNING in file %s, line %d\n", __FILE__, __LINE__)); \ ++} } ++ ++ ++/// @brief Macro for reporting fatal error conditions ++/// @ingroup util ++/// ++/// This macro optionally stops execution of the current routine ++/// after printing an error warning message to stdout, ++/// followed by the file name and line number where the macro was called. ++/// The first parameter is a condition -- if it is true, nothing is done. ++/// The second pararmeter MUST be a parenthesis-enclosed list of arguments, ++/// starting with a string. This is passed to printf() or an equivalent ++/// in order to format the informational message. For example, ++/// ADDR_EXIT(0, ("test %d",3) ); prints out "test 3" followed by ++/// a second line with the file name and line number, then stops execution. ++/// ++#define ADDR_EXIT(cond, a) \ ++{ if (!(cond)) \ ++ { ADDR_PRNT(a); ADDR_DBG_BREAK();\ ++} } ++ ++#else // DEBUG ++ ++#define ADDRDPF 1 ? (void)0 : (void) ++ ++#define ADDR_PRNT(a) ++ ++#define ADDR_DBG_BREAK() ++ ++#define ADDR_INFO(cond, a) ++ ++#define ADDR_WARN(cond, a) ++ ++#define ADDR_EXIT(cond, a) ++ ++#endif // DEBUG ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++// Misc helper functions ++//////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrXorReduce ++* ++* @brief ++* Xor the right-side numberOfBits bits of x. ++*************************************************************************************************** ++*/ ++static inline UINT_32 XorReduce( ++ UINT_32 x, ++ UINT_32 numberOfBits) ++{ ++ UINT_32 i; ++ UINT_32 result = x & 1; ++ ++ for (i=1; i<numberOfBits; i++) ++ { ++ result ^= ((x>>i) & 1); ++ } ++ ++ return result; ++} ++ ++/** ++*************************************************************************************************** ++* IsPow2 ++* ++* @brief ++* Check if the size (UINT_32) is pow 2 ++*************************************************************************************************** ++*/ ++static inline UINT_32 IsPow2( ++ UINT_32 dim) ///< [in] dimension of miplevel ++{ ++ ADDR_ASSERT(dim > 0); ++ return !(dim & (dim - 1)); ++} ++ ++/** ++*************************************************************************************************** ++* IsPow2 ++* ++* @brief ++* Check if the size (UINT_64) is pow 2 ++*************************************************************************************************** ++*/ ++static inline UINT_64 IsPow2( ++ UINT_64 dim) ///< [in] dimension of miplevel ++{ ++ ADDR_ASSERT(dim > 0); ++ return !(dim & (dim - 1)); ++} ++ ++/** ++*************************************************************************************************** ++* ByteAlign ++* ++* @brief ++* Align UINT_32 "x" to "align" alignment, "align" should be power of 2 ++*************************************************************************************************** ++*/ ++static inline UINT_32 PowTwoAlign( ++ UINT_32 x, ++ UINT_32 align) ++{ ++ // ++ // Assert that x is a power of two. ++ // ++ ADDR_ASSERT(IsPow2(align)); ++ return (x + (align - 1)) & (~(align - 1)); ++} ++ ++/** ++*************************************************************************************************** ++* ByteAlign ++* ++* @brief ++* Align UINT_64 "x" to "align" alignment, "align" should be power of 2 ++*************************************************************************************************** ++*/ ++static inline UINT_64 PowTwoAlign( ++ UINT_64 x, ++ UINT_64 align) ++{ ++ // ++ // Assert that x is a power of two. ++ // ++ ADDR_ASSERT(IsPow2(align)); ++ return (x + (align - 1)) & (~(align - 1)); ++} ++ ++/** ++*************************************************************************************************** ++* Min ++* ++* @brief ++* Get the min value between two unsigned values ++*************************************************************************************************** ++*/ ++static inline UINT_32 Min( ++ UINT_32 value1, ++ UINT_32 value2) ++{ ++ return ((value1 < (value2)) ? (value1) : value2); ++} ++ ++/** ++*************************************************************************************************** ++* Min ++* ++* @brief ++* Get the min value between two signed values ++*************************************************************************************************** ++*/ ++static inline INT_32 Min( ++ INT_32 value1, ++ INT_32 value2) ++{ ++ return ((value1 < (value2)) ? (value1) : value2); ++} ++ ++/** ++*************************************************************************************************** ++* Max ++* ++* @brief ++* Get the max value between two unsigned values ++*************************************************************************************************** ++*/ ++static inline UINT_32 Max( ++ UINT_32 value1, ++ UINT_32 value2) ++{ ++ return ((value1 > (value2)) ? (value1) : value2); ++} ++ ++/** ++*************************************************************************************************** ++* Max ++* ++* @brief ++* Get the max value between two signed values ++*************************************************************************************************** ++*/ ++static inline INT_32 Max( ++ INT_32 value1, ++ INT_32 value2) ++{ ++ return ((value1 > (value2)) ? (value1) : value2); ++} ++ ++/** ++*************************************************************************************************** ++* NextPow2 ++* ++* @brief ++* Compute the mipmap's next level dim size ++*************************************************************************************************** ++*/ ++static inline UINT_32 NextPow2( ++ UINT_32 dim) ///< [in] dimension of miplevel ++{ ++ UINT_32 newDim; ++ ++ newDim = 1; ++ ++ if (dim > 0x7fffffff) ++ { ++ ADDR_ASSERT_ALWAYS(); ++ newDim = 0x80000000; ++ } ++ else ++ { ++ while (newDim < dim) ++ { ++ newDim <<= 1; ++ } ++ } ++ ++ return newDim; ++} ++ ++/** ++*************************************************************************************************** ++* Log2 ++* ++* @brief ++* Compute log of base 2 ++*************************************************************************************************** ++*/ ++static inline UINT_32 Log2( ++ UINT_32 x) ///< [in] the value should calculate log based 2 ++{ ++ UINT_32 y; ++ ++ // ++ // Assert that x is a power of two. ++ // ++ ADDR_ASSERT(IsPow2(x)); ++ ++ y = 0; ++ while (x > 1) ++ { ++ x >>= 1; ++ y++; ++ } ++ ++ return y; ++} ++ ++/** ++*************************************************************************************************** ++* QLog2 ++* ++* @brief ++* Compute log of base 2 quickly (<= 16) ++*************************************************************************************************** ++*/ ++static inline UINT_32 QLog2( ++ UINT_32 x) ///< [in] the value should calculate log based 2 ++{ ++ ADDR_ASSERT(x <= 16); ++ ++ UINT_32 y = 0; ++ ++ switch (x) ++ { ++ case 1: ++ y = 0; ++ break; ++ case 2: ++ y = 1; ++ break; ++ case 4: ++ y = 2; ++ break; ++ case 8: ++ y = 3; ++ break; ++ case 16: ++ y = 4; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ } ++ ++ return y; ++} ++ ++/** ++*************************************************************************************************** ++* SafeAssign ++* ++* @brief ++* NULL pointer safe assignment ++*************************************************************************************************** ++*/ ++static inline VOID SafeAssign( ++ UINT_32* pLVal, ///< [in] Pointer to left val ++ UINT_32 rVal) ///< [in] Right value ++{ ++ if (pLVal) ++ { ++ *pLVal = rVal; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* SafeAssign ++* ++* @brief ++* NULL pointer safe assignment for 64bit values ++*************************************************************************************************** ++*/ ++static inline VOID SafeAssign( ++ UINT_64* pLVal, ///< [in] Pointer to left val ++ UINT_64 rVal) ///< [in] Right value ++{ ++ if (pLVal) ++ { ++ *pLVal = rVal; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* SafeAssign ++* ++* @brief ++* NULL pointer safe assignment for AddrTileMode ++*************************************************************************************************** ++*/ ++static inline VOID SafeAssign( ++ AddrTileMode* pLVal, ///< [in] Pointer to left val ++ AddrTileMode rVal) ///< [in] Right value ++{ ++ if (pLVal) ++ { ++ *pLVal = rVal; ++ } ++} ++ ++#endif // __ADDR_COMMON_H__ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.cpp +new file mode 100644 +index 0000000..eb1b7de +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.cpp +@@ -0,0 +1,1678 @@ ++/* ++ * 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 addrelemlib.cpp ++* @brief Contains the class implementation for element/pixel related functions ++*************************************************************************************************** ++*/ ++ ++#include "addrelemlib.h" ++#include "addrlib.h" ++ ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::AddrElemLib ++* ++* @brief ++* constructor ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++AddrElemLib::AddrElemLib( ++ AddrLib* const pAddrLib) : ///< [in] Parent addrlib instance pointer ++ AddrObject(pAddrLib->GetClient()), ++ m_pAddrLib(pAddrLib) ++{ ++ switch (m_pAddrLib->GetAddrChipFamily()) ++ { ++ case ADDR_CHIP_FAMILY_R6XX: ++ m_depthPlanarType = ADDR_DEPTH_PLANAR_R600; ++ m_fp16ExportNorm = 0; ++ break; ++ case ADDR_CHIP_FAMILY_R7XX: ++ m_depthPlanarType = ADDR_DEPTH_PLANAR_R600; ++ m_fp16ExportNorm = 1; ++ break; ++ case ADDR_CHIP_FAMILY_R8XX: ++ case ADDR_CHIP_FAMILY_NI: // Same as 8xx ++ m_depthPlanarType = ADDR_DEPTH_PLANAR_R800; ++ m_fp16ExportNorm = 1; ++ break; ++ default: ++ m_fp16ExportNorm = 1; ++ m_depthPlanarType = ADDR_DEPTH_PLANAR_R800; ++ } ++ ++ m_configFlags.value = 0; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::~AddrElemLib ++* ++* @brief ++* destructor ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++AddrElemLib::~AddrElemLib() ++{ ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::Create ++* ++* @brief ++* Creates and initializes AddrLib object. ++* ++* @return ++* Returns point to ADDR_CREATEINFO if successful. ++*************************************************************************************************** ++*/ ++AddrElemLib* AddrElemLib::Create( ++ const AddrLib* const pAddrLib) ///< [in] Pointer of parent AddrLib instance ++{ ++ AddrElemLib* pElemLib = NULL; ++ ++ if (pAddrLib) ++ { ++ pElemLib = new(pAddrLib->GetClient()) AddrElemLib(const_cast<AddrLib* const>(pAddrLib)); ++ } ++ ++ return pElemLib; ++} ++ ++/************************************************************************************************** ++* AddrElemLib::Flt32sToInt32s ++* ++* @brief ++* Convert a ADDR_FLT_32 value to Int32 value ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::Flt32sToInt32s( ++ ADDR_FLT_32 value, ///< [in] ADDR_FLT_32 value ++ UINT_32 bits, ///< [in] nubmer of bits in value ++ AddrNumberType numberType, ///< [in] the type of number ++ UINT_32* pResult) ///< [out] Int32 value ++{ ++ UINT_8 round = 128; //ADDR_ROUND_BY_HALF ++ UINT_32 uscale; ++ UINT_32 sign; ++ ++ //convert each component to an INT_32 ++ switch ( numberType ) ++ { ++ case ADDR_NO_NUMBER: //fall through ++ case ADDR_ZERO: //fall through ++ case ADDR_ONE: //fall through ++ case ADDR_EPSILON: //fall through ++ return; // these are zero-bit components, so don't set result ++ ++ case ADDR_UINT_BITS: // unsigned integer bit field, clamped to range ++ uscale = (1<<bits) - 1; ++ if (bits == 32) // special case unsigned 32-bit int ++ { ++ *pResult = value.i; ++ } ++ else ++ { ++ if ((value.i < 0) || (value.u > uscale)) ++ { ++ *pResult = uscale; ++ } ++ else ++ { ++ *pResult = value.i; ++ } ++ return; ++ } ++ ++ // The algorithm used in the DB and TX differs at one value for 24-bit unorms ++ case ADDR_UNORM_R6XXDB: // unsigned repeating fraction ++ if ((bits==24) && (value.i == 0x33000000)) ++ { ++ *pResult = 1; ++ return; ++ } // Else treat like ADDR_UNORM_R6XX ++ ++ case ADDR_UNORM_R6XX: // unsigned repeating fraction ++ if (value.f <= 0) ++ { ++ *pResult = 0; // first clamp to [0..1] ++ } ++ else ++ { ++ if (value.f >= 1) ++ { ++ *pResult = (1<<bits) - 1; ++ } ++ else ++ { ++ if ((value.i | 0x87FFFFFF) == 0xFFFFFFFF) ++ { ++ *pResult = 0; // NaN, so force to 0 ++ } ++ ++ #if 0 // floating point version for documentation ++ else ++ { ++ FLOAT f = value.f * ((1<<bits) - 1); ++ *pResult = static_cast<INT_32>(f + (round/256.0f)); ++ } ++ #endif ++ else ++ { ++ ADDR_FLT_32 scaled; ++ ADDR_FLT_32 shifted; ++ UINT_64 truncated, rounded; ++ UINT_32 altShift; ++ UINT_32 mask = (1 << bits) - 1; ++ UINT_32 half = 1 << (bits - 1); ++ UINT_32 mant24 = (value.i & 0x7FFFFF) + 0x800000; ++ UINT_64 temp = mant24 - (mant24>>bits) - ++ static_cast<INT_32>((mant24 & mask) > half); ++ UINT_32 exp8 = value.i >> 23; ++ UINT_32 shift = 126 - exp8 + 24 - bits; ++ UINT_64 final; ++ ++ if (shift >= 32) // This is zero, even with maximum dither add ++ { ++ final = 0; ++ } ++ else ++ { ++ final = ((temp<<8) + (static_cast<UINT_64>(round)<<shift)) >> (shift+8); ++ } ++ //ADDR_EXIT( *pResult == final, ++ // ("Float %x converted to %d-bit Unorm %x != bitwise %x", ++ // value.u, bits, (UINT_32)*pResult, (UINT_32)final) ); ++ if (final > mask) ++ { ++ final = mask; ++ } ++ ++ scaled.f = value.f * ((1<<bits) - 1); ++ shifted.f = (scaled.f * 256); ++ truncated = ((shifted.i&0x7FFFFF) + (INT_64)0x800000) << 8; ++ altShift = 126 + 24 + 8 - ((shifted.i>>23)&0xFF); ++ truncated = (altShift > 60) ? 0 : truncated >> altShift; ++ rounded = static_cast<INT_32>((round + truncated) >> 8); ++ //if (rounded > ((1<<bits) - 1)) ++ // rounded = ((1<<bits) - 1); ++ *pResult = static_cast<INT_32>(rounded); //(INT_32)final; ++ } ++ } ++ } ++ ++ return; ++ ++ case ADDR_S8FLOAT32: // 32-bit IEEE float, passes through NaN values ++ *pResult = value.i; ++ return; ++ ++ // @@ FIX ROUNDING in this code, fix the denorm case ++ case ADDR_U4FLOATC: // Unsigned float, 4-bit exponent. bias 15, clamped [0..1] ++ sign = (value.i >> 31) & 1; ++ if ((value.i&0x7F800000) == 0x7F800000) // If NaN or INF: ++ { ++ if ((value.i&0x007FFFFF) != 0) // then if NaN ++ { ++ *pResult = 0; // return 0 ++ } ++ else ++ { ++ *pResult = (sign)?0:0xF00000; // else +INF->+1, -INF->0 ++ } ++ return; ++ } ++ if (value.f <= 0) ++ { ++ *pResult = 0; ++ } ++ else ++ { ++ if (value.f>=1) ++ { ++ *pResult = 0xF << (bits-4); ++ } ++ else ++ { ++ if ((value.i>>23) > 112 ) ++ { ++ // 24-bit float: normalized ++ // value.i += 1 << (22-bits+4); ++ // round the IEEE mantissa to mantissa size ++ // @@ NOTE: add code to support rounding ++ value.u &= 0x7FFFFFF; // mask off high 4 exponent bits ++ *pResult = value.i >> (23-bits+4);// shift off unused mantissa bits ++ } ++ else ++ { ++ // 24-bit float: denormalized ++ value.f = value.f / (1<<28) / (1<<28); ++ value.f = value.f / (1<<28) / (1<<28); // convert to IEEE denorm ++ // value.i += 1 << (22-bits+4); ++ // round the IEEE mantissa to mantissa size ++ // @@ NOTE: add code to support rounding ++ *pResult = value.i >> (23-bits+4); // shift off unused mantissa bits ++ } ++ } ++ } ++ ++ return; ++ ++ default: // invalid number mode ++ //ADDR_EXIT(0, ("Invalid AddrNumber %d", numberType) ); ++ break; ++ ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::Int32sToPixel ++* ++* @brief ++* Pack 32-bit integer values into an uncompressed pixel, ++* in the proper order ++* ++* @return ++* N/A ++* ++* @note ++* This entry point packes four 32-bit integer values into ++* an uncompressed pixel. The pixel values are specifies in ++* standard order, e.g. depth/stencil. This routine asserts ++* if called on compressed pixel. ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::Int32sToPixel( ++ UINT_32 numComps, ///< [in] number of components ++ UINT_32* pComps, ///< [in] compnents ++ UINT_32* pCompBits, ///< [in] total bits in each component ++ UINT_32* pCompStart, ///< [in] the first bit position of each component ++ ADDR_COMPONENT_FLAGS properties, ///< [in] properties about byteAligned, exportNorm ++ UINT_32 resultBits, ///< [in] result bits: total bpp after decompression ++ UINT_8* pPixel) ///< [out] a depth/stencil pixel value ++{ ++ UINT_32 i; ++ UINT_32 j; ++ UINT_32 start; ++ UINT_32 size; ++ UINT_32 byte; ++ UINT_32 value = 0; ++ UINT_32 compMask; ++ UINT_32 elemMask=0; ++ UINT_32 elementXor = 0; // address xor when reading bytes from elements ++ ++ ++ // @@ NOTE: assert if called on a compressed format! ++ ++ if (properties.byteAligned) // Components are all byte-sized ++ { ++ for (i = 0; i < numComps; i++) // Then for each component ++ { ++ // Copy the bytes of the component into the element ++ start = pCompStart[i] / 8; ++ size = pCompBits[i] / 8; ++ for (j = 0; j < size; j++) ++ { ++ pPixel[(j+start)^elementXor] = static_cast<UINT_8>(pComps[i] >> (8*j)); ++ } ++ } ++ } ++ else // Element is 32-bits or less, components are bit fields ++ { ++ // First, extract each component in turn and combine it into a 32-bit value ++ for (i = 0; i < numComps; i++) ++ { ++ compMask = (1 << pCompBits[i]) - 1; ++ elemMask |= compMask << pCompStart[i]; ++ value |= (pComps[i] & compMask) << pCompStart[i]; ++ } ++ ++ // Mext, copy the masked value into the element ++ size = (resultBits + 7) / 8; ++ for (i = 0; i < size; i++) ++ { ++ byte = pPixel[i^elementXor] & ~(elemMask >> (8*i)); ++ pPixel[i^elementXor] = static_cast<UINT_8>(byte | ((elemMask & value) >> (8*i))); ++ } ++ } ++} ++ ++/** ++*************************************************************************************************** ++* Flt32ToDepthPixel ++* ++* @brief ++* Convert a FLT_32 value to a depth/stencil pixel value ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::Flt32ToDepthPixel( ++ AddrDepthFormat format, ///< [in] Depth format ++ const ADDR_FLT_32 comps[2], ///< [in] two components of depth ++ UINT_8* pPixel ///< [out] depth pixel value ++ ) const ++{ ++ UINT_32 i; ++ UINT_32 values[2]; ++ ADDR_COMPONENT_FLAGS properties; // byteAligned, exportNorm ++ UINT_32 resultBits = 0; // result bits: total bits per pixel after decompression ++ ++ ADDR_PIXEL_FORMATINFO fmt; ++ ++ // get type for each component ++ PixGetDepthCompInfo(format, &fmt); ++ ++ //initialize properties ++ properties.byteAligned = TRUE; ++ properties.exportNorm = TRUE; ++ properties.floatComp = FALSE; ++ ++ //set properties and result bits ++ for (i = 0; i < 2; i++) ++ { ++ if ((fmt.compBit[i] & 7) || (fmt.compStart[i] & 7)) ++ { ++ properties.byteAligned = FALSE; ++ } ++ ++ if (resultBits < fmt.compStart[i] + fmt.compBit[i]) ++ { ++ resultBits = fmt.compStart[i] + fmt.compBit[i]; ++ } ++ ++ // Clear ADDR_EXPORT_NORM if can't be represented as 11-bit or smaller [-1..+1] format ++ if (fmt.compBit[i] > 11 || fmt.numType[i] >= ADDR_USCALED) ++ { ++ properties.exportNorm = FALSE; ++ } ++ ++ // Mark if there are any floating point components ++ if ((fmt.numType[i] == ADDR_U4FLOATC) || (fmt.numType[i] >= ADDR_S8FLOAT) ) ++ { ++ properties.floatComp = TRUE; ++ } ++ } ++ ++ // Convert the two input floats to integer values ++ for (i = 0; i < 2; i++) ++ { ++ Flt32sToInt32s(comps[i], fmt.compBit[i], fmt.numType[i], &values[i]); ++ } ++ ++ // Then pack the two integer components, in the proper order ++ Int32sToPixel(2, values, fmt.compBit, fmt.compStart, properties, resultBits, pPixel ); ++ ++} ++ ++/** ++*************************************************************************************************** ++* Flt32ToColorPixel ++* ++* @brief ++* Convert a FLT_32 value to a red/green/blue/alpha pixel value ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::Flt32ToColorPixel( ++ AddrColorFormat format, ///< [in] Color format ++ AddrSurfaceNumber surfNum, ///< [in] Surface number ++ AddrSurfaceSwap surfSwap, ///< [in] Surface swap ++ const ADDR_FLT_32 comps[4], ///< [in] four components of color ++ UINT_8* pPixel ///< [out] a red/green/blue/alpha pixel value ++ ) const ++{ ++ ADDR_PIXEL_FORMATINFO pixelInfo; ++ ++ UINT_32 i; ++ UINT_32 values[4]; ++ ADDR_COMPONENT_FLAGS properties; // byteAligned, exportNorm ++ UINT_32 resultBits = 0; // result bits: total bits per pixel after decompression ++ ++ memset(&pixelInfo, 0, sizeof(ADDR_PIXEL_FORMATINFO)); ++ ++ PixGetColorCompInfo(format, surfNum, surfSwap, &pixelInfo); ++ ++ //initialize properties ++ properties.byteAligned = TRUE; ++ properties.exportNorm = TRUE; ++ properties.floatComp = FALSE; ++ ++ //set properties and result bits ++ for (i = 0; i < 4; i++) ++ { ++ if ( (pixelInfo.compBit[i] & 7) || (pixelInfo.compStart[i] & 7) ) ++ { ++ properties.byteAligned = FALSE; ++ } ++ ++ if (resultBits < pixelInfo.compStart[i] + pixelInfo.compBit[i]) ++ { ++ resultBits = pixelInfo.compStart[i] + pixelInfo.compBit[i]; ++ } ++ ++ if (m_fp16ExportNorm) ++ { ++ // Clear ADDR_EXPORT_NORM if can't be represented as 11-bit or smaller [-1..+1] format ++ // or if it's not FP and <=16 bits ++ if (((pixelInfo.compBit[i] > 11) || (pixelInfo.numType[i] >= ADDR_USCALED)) ++ && (pixelInfo.numType[i] !=ADDR_U4FLOATC)) ++ { ++ properties.exportNorm = FALSE; ++ } ++ } ++ else ++ { ++ // Clear ADDR_EXPORT_NORM if can't be represented as 11-bit or smaller [-1..+1] format ++ if (pixelInfo.compBit[i] > 11 || pixelInfo.numType[i] >= ADDR_USCALED) ++ { ++ properties.exportNorm = FALSE; ++ } ++ } ++ ++ // Mark if there are any floating point components ++ if ( (pixelInfo.numType[i] == ADDR_U4FLOATC) || ++ (pixelInfo.numType[i] >= ADDR_S8FLOAT) ) ++ { ++ properties.floatComp = TRUE; ++ } ++ } ++ ++ // Convert the four input floats to integer values ++ for (i = 0; i < 4; i++) ++ { ++ Flt32sToInt32s(comps[i], pixelInfo.compBit[i], pixelInfo.numType[i], &values[i]); ++ } ++ ++ // Then pack the four integer components, in the proper order ++ Int32sToPixel(4, values, &pixelInfo.compBit[0], &pixelInfo.compStart[0], ++ properties, resultBits, pPixel); ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetCompType ++* ++* @brief ++* Fill per component info ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::GetCompType( ++ AddrColorFormat format, ///< [in] surface format ++ AddrSurfaceNumber numType, ///< [in] number type ++ ADDR_PIXEL_FORMATINFO* pInfo) ///< [in][out] per component info out ++{ ++ BOOL_32 handled = FALSE; ++ ++ // Floating point formats override the number format ++ switch (format) ++ { ++ case ADDR_COLOR_16_FLOAT: // fall through for all pure floating point format ++ case ADDR_COLOR_16_16_FLOAT: ++ case ADDR_COLOR_16_16_16_16_FLOAT: ++ case ADDR_COLOR_32_FLOAT: ++ case ADDR_COLOR_32_32_FLOAT: ++ case ADDR_COLOR_32_32_32_32_FLOAT: ++ case ADDR_COLOR_10_11_11_FLOAT: ++ case ADDR_COLOR_11_11_10_FLOAT: ++ numType = ADDR_NUMBER_FLOAT; ++ break; ++ // Special handling for the depth formats ++ case ADDR_COLOR_8_24: // fall through for these 2 similar format ++ case ADDR_COLOR_24_8: ++ for (UINT_32 c = 0; c < 4; c++) ++ { ++ if (pInfo->compBit[c] == 8) ++ { ++ pInfo->numType[c] = ADDR_UINT_BITS; ++ } ++ else if (pInfo->compBit[c] == 24) ++ { ++ pInfo->numType[c] = ADDR_UNORM_R6XX; ++ } ++ else ++ { ++ pInfo->numType[c] = ADDR_NO_NUMBER; ++ } ++ } ++ handled = TRUE; ++ break; ++ case ADDR_COLOR_8_24_FLOAT: // fall through for these 3 similar format ++ case ADDR_COLOR_24_8_FLOAT: ++ case ADDR_COLOR_X24_8_32_FLOAT: ++ for (UINT_32 c = 0; c < 4; c++) ++ { ++ if (pInfo->compBit[c] == 8) ++ { ++ pInfo->numType[c] = ADDR_UINT_BITS; ++ } ++ else if (pInfo->compBit[c] == 24) ++ { ++ pInfo->numType[c] = ADDR_U4FLOATC; ++ } ++ else if (pInfo->compBit[c] == 32) ++ { ++ pInfo->numType[c] = ADDR_S8FLOAT32; ++ } ++ else ++ { ++ pInfo->numType[c] = ADDR_NO_NUMBER; ++ } ++ } ++ handled = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ if (!handled) ++ { ++ for (UINT_32 c = 0; c < 4; c++) ++ { ++ // Assign a number type for each component ++ AddrSurfaceNumber cnum; ++ ++ // First handle default component values ++ if (pInfo->compBit[c] == 0) ++ { ++ if (c < 3) ++ { ++ pInfo->numType[c] = ADDR_ZERO; // Default is zero for RGB ++ } ++ else if (numType == ADDR_NUMBER_UINT || numType == ADDR_NUMBER_SINT) ++ { ++ pInfo->numType[c] = ADDR_EPSILON; // Alpha INT_32 bits default is 0x01 ++ } ++ else ++ { ++ pInfo->numType[c] = ADDR_ONE; // Alpha normal default is float 1.0 ++ } ++ continue; ++ } ++ // Now handle small components ++ else if (pInfo->compBit[c] == 1) ++ { ++ if (numType == ADDR_NUMBER_UINT || numType == ADDR_NUMBER_SINT) ++ { ++ cnum = ADDR_NUMBER_UINT; ++ } ++ else ++ { ++ cnum = ADDR_NUMBER_UNORM; ++ } ++ } ++ else ++ { ++ cnum = numType; ++ } ++ ++ // If no default, set the number type fom num, compbits, and architecture ++ switch (cnum) ++ { ++ case ADDR_NUMBER_SRGB: ++ pInfo->numType[c] = (c < 3) ? ADDR_GAMMA8_R6XX : ADDR_UNORM_R6XX; ++ break; ++ case ADDR_NUMBER_UNORM: ++ pInfo->numType[c] = ADDR_UNORM_R6XX; ++ break; ++ case ADDR_NUMBER_SNORM: ++ pInfo->numType[c] = ADDR_SNORM_R6XX; ++ break; ++ case ADDR_NUMBER_USCALED: ++ pInfo->numType[c] = ADDR_USCALED; // @@ Do we need separate Pele routine? ++ break; ++ case ADDR_NUMBER_SSCALED: ++ pInfo->numType[c] = ADDR_SSCALED; // @@ Do we need separate Pele routine? ++ break; ++ case ADDR_NUMBER_FLOAT: ++ if (pInfo->compBit[c] == 32) ++ { ++ pInfo->numType[c] = ADDR_S8FLOAT32; ++ } ++ else if (pInfo->compBit[c] == 16) ++ { ++ pInfo->numType[c] = ADDR_S5FLOAT; ++ } ++ else if (pInfo->compBit[c] >= 10) ++ { ++ pInfo->numType[c] = ADDR_U5FLOAT; ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ } ++ break; ++ case ADDR_NUMBER_SINT: ++ pInfo->numType[c] = ADDR_SINT_BITS; ++ break; ++ case ADDR_NUMBER_UINT: ++ pInfo->numType[c] = ADDR_UINT_BITS; ++ break; ++ ++ default: ++ ADDR_ASSERT(!"Invalid number type"); ++ pInfo->numType[c] = ADDR_NO_NUMBER; ++ break; ++ } ++ } ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetCompSwap ++* ++* @brief ++* Get components swapped for color surface ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::GetCompSwap( ++ AddrSurfaceSwap swap, ///< [in] swap mode ++ ADDR_PIXEL_FORMATINFO* pInfo) ///< [in/out] output per component info ++{ ++ switch (pInfo->comps) ++ { ++ case 4: ++ switch (swap) ++ { ++ case ADDR_SWAP_ALT: ++ SwapComps( 0, 2, pInfo ); ++ break; // BGRA ++ case ADDR_SWAP_STD_REV: ++ SwapComps( 0, 3, pInfo ); ++ SwapComps( 1, 2, pInfo ); ++ break; // ABGR ++ case ADDR_SWAP_ALT_REV: ++ SwapComps( 0, 3, pInfo ); ++ SwapComps( 0, 2, pInfo ); ++ SwapComps( 0, 1, pInfo ); ++ break; // ARGB ++ default: ++ break; ++ } ++ break; ++ case 3: ++ switch (swap) ++ { ++ case ADDR_SWAP_ALT_REV: ++ SwapComps( 0, 3, pInfo ); ++ SwapComps( 0, 2, pInfo ); ++ break; // AGR ++ case ADDR_SWAP_STD_REV: ++ SwapComps( 0, 2, pInfo ); ++ break; // BGR ++ case ADDR_SWAP_ALT: ++ SwapComps( 2, 3, pInfo ); ++ break; // RGA ++ default: ++ break; // RGB ++ } ++ break; ++ case 2: ++ switch (swap) ++ { ++ case ADDR_SWAP_ALT_REV: ++ SwapComps( 0, 1, pInfo ); ++ SwapComps( 1, 3, pInfo ); ++ break; // AR ++ case ADDR_SWAP_STD_REV: ++ SwapComps( 0, 1, pInfo ); ++ break; // GR ++ case ADDR_SWAP_ALT: ++ SwapComps( 1, 3, pInfo ); ++ break; // RA ++ default: ++ break; // RG ++ } ++ break; ++ case 1: ++ switch (swap) ++ { ++ case ADDR_SWAP_ALT_REV: ++ SwapComps( 0, 3, pInfo ); ++ break; // A ++ case ADDR_SWAP_STD_REV: ++ SwapComps( 0, 2, pInfo ); ++ break; // B ++ case ADDR_SWAP_ALT: ++ SwapComps( 0, 1, pInfo ); ++ break; // G ++ default: ++ break; // R ++ } ++ break; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetCompSwap ++* ++* @brief ++* Get components swapped for color surface ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::SwapComps( ++ UINT_32 c0, ///< [in] component index 0 ++ UINT_32 c1, ///< [in] component index 1 ++ ADDR_PIXEL_FORMATINFO* pInfo) ///< [in/out] output per component info ++{ ++ UINT_32 start; ++ UINT_32 bits; ++ ++ start = pInfo->compStart[c0]; ++ pInfo->compStart[c0] = pInfo->compStart[c1]; ++ pInfo->compStart[c1] = start; ++ ++ bits = pInfo->compBit[c0]; ++ pInfo->compBit[c0] = pInfo->compBit[c1]; ++ pInfo->compBit[c1] = bits; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::PixGetColorCompInfo ++* ++* @brief ++* Get per component info for color surface ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::PixGetColorCompInfo( ++ AddrColorFormat format, ///< [in] surface format, read from register ++ AddrSurfaceNumber number, ///< [in] pixel number type ++ AddrSurfaceSwap swap, ///< [in] component swap mode ++ ADDR_PIXEL_FORMATINFO* pInfo ///< [out] output per component info ++ ) const ++{ ++ // 1. Get componet bits ++ switch (format) ++ { ++ case ADDR_COLOR_8: ++ GetCompBits(8, 0, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_1_5_5_5: ++ GetCompBits(5, 5, 5, 1, pInfo); ++ break; ++ case ADDR_COLOR_5_6_5: ++ GetCompBits(8, 6, 5, 0, pInfo); ++ break; ++ case ADDR_COLOR_6_5_5: ++ GetCompBits(5, 5, 6, 0, pInfo); ++ break; ++ case ADDR_COLOR_8_8: ++ GetCompBits(8, 8, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_4_4_4_4: ++ GetCompBits(4, 4, 4, 4, pInfo); ++ break; ++ case ADDR_COLOR_16: ++ GetCompBits(16, 0, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_8_8_8_8: ++ GetCompBits(8, 8, 8, 8, pInfo); ++ break; ++ case ADDR_COLOR_2_10_10_10: ++ GetCompBits(10, 10, 10, 2, pInfo); ++ break; ++ case ADDR_COLOR_10_11_11: ++ GetCompBits(11, 11, 10, 0, pInfo); ++ break; ++ case ADDR_COLOR_11_11_10: ++ GetCompBits(10, 11, 11, 0, pInfo); ++ break; ++ case ADDR_COLOR_16_16: ++ GetCompBits(16, 16, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_16_16_16_16: ++ GetCompBits(16, 16, 16, 16, pInfo); ++ break; ++ case ADDR_COLOR_16_FLOAT: ++ GetCompBits(16, 0, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_16_16_FLOAT: ++ GetCompBits(16, 16, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_32_FLOAT: ++ GetCompBits(32, 0, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_32_32_FLOAT: ++ GetCompBits(32, 32, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_16_16_16_16_FLOAT: ++ GetCompBits(16, 16, 16, 16, pInfo); ++ break; ++ case ADDR_COLOR_32_32_32_32_FLOAT: ++ GetCompBits(32, 32, 32, 32, pInfo); ++ break; ++ ++ case ADDR_COLOR_32: ++ GetCompBits(32, 0, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_32_32: ++ GetCompBits(32, 32, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_32_32_32_32: ++ GetCompBits(32, 32, 32, 32, pInfo); ++ break; ++ case ADDR_COLOR_10_10_10_2: ++ GetCompBits(2, 10, 10, 10, pInfo); ++ break; ++ case ADDR_COLOR_10_11_11_FLOAT: ++ GetCompBits(11, 11, 10, 0, pInfo); ++ break; ++ case ADDR_COLOR_11_11_10_FLOAT: ++ GetCompBits(10, 11, 11, 0, pInfo); ++ break; ++ case ADDR_COLOR_5_5_5_1: ++ GetCompBits(1, 5, 5, 5, pInfo); ++ break; ++ case ADDR_COLOR_3_3_2: ++ GetCompBits(2, 3, 3, 0, pInfo); ++ break; ++ case ADDR_COLOR_4_4: ++ GetCompBits(4, 4, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_8_24: ++ case ADDR_COLOR_8_24_FLOAT: // same bit count, fall through ++ GetCompBits(24, 8, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_24_8: ++ case ADDR_COLOR_24_8_FLOAT: // same bit count, fall through ++ GetCompBits(8, 24, 0, 0, pInfo); ++ break; ++ case ADDR_COLOR_X24_8_32_FLOAT: ++ GetCompBits(32, 8, 0, 0, pInfo); ++ break; ++ ++ case ADDR_COLOR_INVALID: ++ GetCompBits(0, 0, 0, 0, pInfo); ++ break; ++ default: ++ ADDR_ASSERT(0); ++ GetCompBits(0, 0, 0, 0, pInfo); ++ break; ++ } ++ ++ // 2. Get component number type ++ ++ GetCompType(format, number, pInfo); ++ ++ // 3. Swap components if needed ++ ++ GetCompSwap(swap, pInfo); ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::PixGetDepthCompInfo ++* ++* @brief ++* Get per component info for depth surface ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::PixGetDepthCompInfo( ++ AddrDepthFormat format, ///< [in] surface format, read from register ++ ADDR_PIXEL_FORMATINFO* pInfo ///< [out] output per component bits and type ++ ) const ++{ ++ if (m_depthPlanarType == ADDR_DEPTH_PLANAR_R800) ++ { ++ if (format == ADDR_DEPTH_8_24_FLOAT) ++ { ++ format = ADDR_DEPTH_X24_8_32_FLOAT; // Use this format to represent R800's D24FS8 ++ } ++ ++ if (format == ADDR_DEPTH_X8_24_FLOAT) ++ { ++ format = ADDR_DEPTH_32_FLOAT; ++ } ++ } ++ ++ switch (format) ++ { ++ case ADDR_DEPTH_16: ++ GetCompBits(16, 0, 0, 0, pInfo); ++ break; ++ case ADDR_DEPTH_8_24: ++ case ADDR_DEPTH_8_24_FLOAT: // similar format, fall through ++ GetCompBits(24, 8, 0, 0, pInfo); ++ break; ++ case ADDR_DEPTH_X8_24: ++ case ADDR_DEPTH_X8_24_FLOAT: // similar format, fall through ++ GetCompBits(24, 0, 0, 0, pInfo); ++ break; ++ case ADDR_DEPTH_32_FLOAT: ++ GetCompBits(32, 0, 0, 0, pInfo); ++ break; ++ case ADDR_DEPTH_X24_8_32_FLOAT: ++ GetCompBits(32, 8, 0, 0, pInfo); ++ break; ++ case ADDR_DEPTH_INVALID: ++ GetCompBits(0, 0, 0, 0, pInfo); ++ break; ++ default: ++ ADDR_ASSERT(0); ++ GetCompBits(0, 0, 0, 0, pInfo); ++ break; ++ } ++ ++ switch (format) ++ { ++ case ADDR_DEPTH_16: ++ pInfo->numType [0] = ADDR_UNORM_R6XX; ++ pInfo->numType [1] = ADDR_ZERO; ++ break; ++ case ADDR_DEPTH_8_24: ++ pInfo->numType [0] = ADDR_UNORM_R6XXDB; ++ pInfo->numType [1] = ADDR_UINT_BITS; ++ break; ++ case ADDR_DEPTH_8_24_FLOAT: ++ pInfo->numType [0] = ADDR_U4FLOATC; ++ pInfo->numType [1] = ADDR_UINT_BITS; ++ break; ++ case ADDR_DEPTH_X8_24: ++ pInfo->numType [0] = ADDR_UNORM_R6XXDB; ++ pInfo->numType [1] = ADDR_ZERO; ++ break; ++ case ADDR_DEPTH_X8_24_FLOAT: ++ pInfo->numType [0] = ADDR_U4FLOATC; ++ pInfo->numType [1] = ADDR_ZERO; ++ break; ++ case ADDR_DEPTH_32_FLOAT: ++ pInfo->numType [0] = ADDR_S8FLOAT32; ++ pInfo->numType [1] = ADDR_ZERO; ++ break; ++ case ADDR_DEPTH_X24_8_32_FLOAT: ++ pInfo->numType [0] = ADDR_S8FLOAT32; ++ pInfo->numType [1] = ADDR_UINT_BITS; ++ break; ++ default: ++ pInfo->numType [0] = ADDR_NO_NUMBER; ++ pInfo->numType [1] = ADDR_NO_NUMBER; ++ break; ++ } ++ ++ pInfo->numType [2] = ADDR_NO_NUMBER; ++ pInfo->numType [3] = ADDR_NO_NUMBER; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::PixGetExportNorm ++* ++* @brief ++* Check if fp16 export norm can be enabled. ++* ++* @return ++* TRUE if this can be enabled. ++* ++*************************************************************************************************** ++*/ ++BOOL_32 AddrElemLib::PixGetExportNorm( ++ AddrColorFormat colorFmt, ///< [in] surface format, read from register ++ AddrSurfaceNumber numberFmt, ///< [in] pixel number type ++ AddrSurfaceSwap swap ///< [in] components swap type ++ ) const ++{ ++ BOOL_32 enabled = TRUE; ++ ++ ADDR_PIXEL_FORMATINFO formatInfo; ++ ++ PixGetColorCompInfo(colorFmt, numberFmt, swap, &formatInfo); ++ ++ for (UINT_32 c = 0; c < 4; c++) ++ { ++ if (m_fp16ExportNorm) ++ { ++ if (((formatInfo.compBit[c] > 11) || (formatInfo.numType[c] > ADDR_USCALED)) && ++ (formatInfo.numType[c] != ADDR_U4FLOATC) && ++ (formatInfo.numType[c] != ADDR_S5FLOAT) && ++ (formatInfo.numType[c] != ADDR_S5FLOATM) && ++ (formatInfo.numType[c] != ADDR_U5FLOAT) && ++ (formatInfo.numType[c] != ADDR_U3FLOATM)) ++ { ++ enabled = FALSE; ++ break; ++ } ++ } ++ else ++ { ++ if ((formatInfo.compBit[c] > 11) || (formatInfo.numType[c] > ADDR_USCALED)) ++ { ++ enabled = FALSE; ++ break; ++ } ++ } ++ } ++ ++ return enabled; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::AdjustSurfaceInfo ++* ++* @brief ++* Adjust bpp/base pitch/width/height according to elemMode and expandX/Y ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::AdjustSurfaceInfo( ++ AddrElemMode elemMode, ///< [in] element mode ++ UINT_32 expandX, ///< [in] decompression expansion factor in X ++ UINT_32 expandY, ///< [in] decompression expansion factor in Y ++ UINT_32* pBpp, ///< [in/out] bpp ++ UINT_32* pBasePitch, ///< [in/out] base pitch ++ UINT_32* pWidth, ///< [in/out] width ++ UINT_32* pHeight) ///< [in/out] height ++{ ++ UINT_32 packedBits; ++ UINT_32 basePitch; ++ UINT_32 width; ++ UINT_32 height; ++ UINT_32 bpp; ++ BOOL_32 bBCnFormat = FALSE; ++ ++ ADDR_ASSERT(pBpp != NULL); ++ ADDR_ASSERT(pWidth != NULL && pHeight != NULL && pBasePitch != NULL); ++ ++ if (pBpp) ++ { ++ bpp = *pBpp; ++ ++ switch (elemMode) ++ { ++ case ADDR_EXPANDED: ++ packedBits = bpp / expandX / expandY; ++ break; ++ case ADDR_PACKED_STD: // Different bit order ++ case ADDR_PACKED_REV: ++ packedBits = bpp * expandX * expandY; ++ break; ++ case ADDR_PACKED_GBGR: ++ case ADDR_PACKED_BGRG: ++ packedBits = bpp; // 32-bit packed ==> 2 32-bit result ++ break; ++ case ADDR_PACKED_BC1: // Fall through ++ case ADDR_PACKED_BC4: ++ packedBits = 64; ++ bBCnFormat = TRUE; ++ break; ++ case ADDR_PACKED_BC2: // Fall through ++ case ADDR_PACKED_BC3: // Fall through ++ case ADDR_PACKED_BC5: // Fall through ++ bBCnFormat = TRUE; ++ packedBits = 128; ++ break; ++ case ADDR_ROUND_BY_HALF: // Fall through ++ case ADDR_ROUND_TRUNCATE: // Fall through ++ case ADDR_ROUND_DITHER: // Fall through ++ case ADDR_UNCOMPRESSED: ++ packedBits = bpp; ++ break; ++ default: ++ packedBits = bpp; ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ *pBpp = packedBits; ++ } ++ ++ if (pWidth && pHeight && pBasePitch) ++ { ++ basePitch = *pBasePitch; ++ width = *pWidth; ++ height = *pHeight; ++ ++ if ((expandX > 1) || (expandY > 1)) ++ { ++ if (elemMode == ADDR_EXPANDED) ++ { ++ basePitch *= expandX; ++ width *= expandX; ++ height *= expandY; ++ } ++ else ++ { ++ // Evergreen family workaround ++ if (bBCnFormat && (m_pAddrLib->GetAddrChipFamily() == ADDR_CHIP_FAMILY_R8XX)) ++ { ++ // For BCn we now pad it to POW2 at the beginning so it is safe to ++ // divide by 4 directly ++ basePitch = basePitch / expandX; ++ width = width / expandX; ++ height = height / expandY; ++#if DEBUG ++ width = (width == 0) ? 1 : width; ++ height = (height == 0) ? 1 : height; ++ ++ if ((*pWidth > PowTwoAlign(width, 8) * expandX) || ++ (*pHeight > PowTwoAlign(height, 8) * expandY)) // 8 is 1D tiling alignment ++ { ++ // if this assertion is hit we may have issues if app samples ++ // rightmost/bottommost pixels ++ ADDR_ASSERT_ALWAYS(); ++ } ++#endif ++ } ++ else // Not BCn format we still keep old way (FMT_1? No real test yet) ++ { ++ basePitch = (basePitch + expandX - 1) / expandX; ++ width = (width + expandX - 1) / expandX; ++ height = (height + expandY - 1) / expandY; ++ } ++ } ++ ++ *pBasePitch = basePitch; // 0 is legal value for base pitch. ++ *pWidth = (width == 0) ? 1 : width; ++ *pHeight = (height == 0) ? 1 : height; ++ } //if (pWidth && pHeight && pBasePitch) ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::RestoreSurfaceInfo ++* ++* @brief ++* Reverse operation of AdjustSurfaceInfo ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::RestoreSurfaceInfo( ++ AddrElemMode elemMode, ///< [in] element mode ++ UINT_32 expandX, ///< [in] decompression expansion factor in X ++ UINT_32 expandY, ///< [out] decompression expansion factor in Y ++ UINT_32* pBpp, ///< [in/out] bpp ++ UINT_32* pWidth, ///< [in/out] width ++ UINT_32* pHeight) ///< [in/out] height ++{ ++ UINT_32 originalBits; ++ UINT_32 width; ++ UINT_32 height; ++ UINT_32 bpp; ++ ++ BOOL_32 bBCnFormat = FALSE; ++ ++ ADDR_ASSERT(pBpp != NULL); ++ ADDR_ASSERT(pWidth != NULL && pHeight != NULL); ++ ++ if (pBpp) ++ { ++ bpp = *pBpp; ++ ++ switch (elemMode) ++ { ++ case ADDR_EXPANDED: ++ originalBits = bpp * expandX * expandY; ++ break; ++ case ADDR_PACKED_STD: // Different bit order ++ case ADDR_PACKED_REV: ++ originalBits = bpp / expandX / expandY; ++ break; ++ case ADDR_PACKED_GBGR: ++ case ADDR_PACKED_BGRG: ++ originalBits = bpp; // 32-bit packed ==> 2 32-bit result ++ break; ++ case ADDR_PACKED_BC1: // Fall through ++ case ADDR_PACKED_BC4: ++ originalBits = 64; ++ bBCnFormat = TRUE; ++ break; ++ case ADDR_PACKED_BC2: // Fall through ++ case ADDR_PACKED_BC3: // Fall through ++ case ADDR_PACKED_BC5: ++ bBCnFormat = TRUE; ++ originalBits = 128; ++ break; ++ case ADDR_ROUND_BY_HALF: // Fall through ++ case ADDR_ROUND_TRUNCATE: // Fall through ++ case ADDR_ROUND_DITHER: // Fall through ++ case ADDR_UNCOMPRESSED: ++ originalBits = bpp; ++ break; ++ default: ++ originalBits = bpp; ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ *pBpp = originalBits; ++ } ++ ++ if (pWidth && pHeight) ++ { ++ width = *pWidth; ++ height = *pHeight; ++ ++ if ((expandX > 1) || (expandY > 1)) ++ { ++ if (elemMode == ADDR_EXPANDED) ++ { ++ width /= expandX; ++ height /= expandY; ++ } ++ else ++ { ++ width *= expandX; ++ height *= expandY; ++ } ++ } ++ ++ *pWidth = (width == 0) ? 1 : width; ++ *pHeight = (height == 0) ? 1 : height; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetBitsPerPixel ++* ++* @brief ++* Compute the total bits per element according to a format ++* code. For compressed formats, this is not the same as ++* the number of bits per decompressed element. ++* ++* @return ++* Bits per pixel ++*************************************************************************************************** ++*/ ++UINT_32 AddrElemLib::GetBitsPerPixel( ++ AddrFormat format, ///< [in] surface format code ++ AddrElemMode* pElemMode, ///< [out] element mode ++ UINT_32* pExpandX, ///< [out] decompression expansion factor in X ++ UINT_32* pExpandY, ///< [out] decompression expansion factor in Y ++ UINT_32* pUnusedBits) ///< [out] bits unused ++{ ++ UINT_32 bpp; ++ UINT_32 expandX = 1; ++ UINT_32 expandY = 1; ++ UINT_32 bitUnused = 0; ++ AddrElemMode elemMode = ADDR_UNCOMPRESSED; // default value ++ ++ switch (format) ++ { ++ case ADDR_FMT_8: ++ bpp = 8; ++ break; ++ case ADDR_FMT_1_5_5_5: ++ case ADDR_FMT_5_6_5: ++ case ADDR_FMT_6_5_5: ++ case ADDR_FMT_8_8: ++ case ADDR_FMT_4_4_4_4: ++ case ADDR_FMT_16: ++ case ADDR_FMT_16_FLOAT: ++ bpp = 16; ++ break; ++ case ADDR_FMT_GB_GR: // treat as FMT_8_8 ++ elemMode = ADDR_PACKED_GBGR; ++ bpp = 16; ++ break; ++ case ADDR_FMT_BG_RG: // treat as FMT_8_8 ++ elemMode = ADDR_PACKED_BGRG; ++ bpp = 16; ++ break; ++ case ADDR_FMT_8_8_8_8: ++ case ADDR_FMT_2_10_10_10: ++ case ADDR_FMT_10_11_11: ++ case ADDR_FMT_11_11_10: ++ case ADDR_FMT_16_16: ++ case ADDR_FMT_16_16_FLOAT: ++ case ADDR_FMT_32: ++ case ADDR_FMT_32_FLOAT: ++ case ADDR_FMT_24_8: ++ case ADDR_FMT_24_8_FLOAT: ++ bpp = 32; ++ break; ++ case ADDR_FMT_16_16_16_16: ++ case ADDR_FMT_16_16_16_16_FLOAT: ++ case ADDR_FMT_32_32: ++ case ADDR_FMT_32_32_FLOAT: ++ case ADDR_FMT_CTX1: ++ bpp = 64; ++ break; ++ case ADDR_FMT_32_32_32_32: ++ case ADDR_FMT_32_32_32_32_FLOAT: ++ bpp = 128; ++ break; ++ case ADDR_FMT_INVALID: ++ bpp = 0; ++ break; ++ case ADDR_FMT_1_REVERSED: ++ elemMode = ADDR_PACKED_REV; ++ expandX = 8; ++ bpp = 1; ++ break; ++ case ADDR_FMT_1: ++ elemMode = ADDR_PACKED_STD; ++ expandX = 8; ++ bpp = 1; ++ break; ++ case ADDR_FMT_4_4: ++ case ADDR_FMT_3_3_2: ++ bpp = 8; ++ break; ++ case ADDR_FMT_5_5_5_1: ++ bpp = 16; ++ break; ++ case ADDR_FMT_32_AS_8: ++ case ADDR_FMT_32_AS_8_8: ++ case ADDR_FMT_8_24: ++ case ADDR_FMT_8_24_FLOAT: ++ case ADDR_FMT_10_10_10_2: ++ case ADDR_FMT_10_11_11_FLOAT: ++ case ADDR_FMT_11_11_10_FLOAT: ++ case ADDR_FMT_5_9_9_9_SHAREDEXP: ++ bpp = 32; ++ break; ++ case ADDR_FMT_X24_8_32_FLOAT: ++ bpp = 64; ++ bitUnused = 24; ++ break; ++ case ADDR_FMT_8_8_8: ++ elemMode = ADDR_EXPANDED; ++ bpp = 24;//@@ 8; // read 3 elements per pixel ++ expandX = 3; ++ break; ++ case ADDR_FMT_16_16_16: ++ case ADDR_FMT_16_16_16_FLOAT: ++ elemMode = ADDR_EXPANDED; ++ bpp = 48;//@@ 16; // read 3 elements per pixel ++ expandX = 3; ++ break; ++ case ADDR_FMT_32_32_32_FLOAT: ++ case ADDR_FMT_32_32_32: ++ elemMode = ADDR_EXPANDED; ++ expandX = 3; ++ bpp = 96;//@@ 32; // read 3 elements per pixel ++ break; ++ case ADDR_FMT_BC1: ++ elemMode = ADDR_PACKED_BC1; ++ expandX = 4; ++ expandY = 4; ++ bpp = 64; ++ break; ++ case ADDR_FMT_BC4: ++ elemMode = ADDR_PACKED_BC4; ++ expandX = 4; ++ expandY = 4; ++ bpp = 64; ++ break; ++ case ADDR_FMT_BC2: ++ elemMode = ADDR_PACKED_BC2; ++ expandX = 4; ++ expandY = 4; ++ bpp = 128; ++ break; ++ case ADDR_FMT_BC3: ++ elemMode = ADDR_PACKED_BC3; ++ expandX = 4; ++ expandY = 4; ++ bpp = 128; ++ break; ++ case ADDR_FMT_BC5: ++ case ADDR_FMT_BC6: // reuse ADDR_PACKED_BC5 ++ case ADDR_FMT_BC7: // reuse ADDR_PACKED_BC5 ++ elemMode = ADDR_PACKED_BC5; ++ expandX = 4; ++ expandY = 4; ++ bpp = 128; ++ break; ++ default: ++ bpp = 0; ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ // @@ or should this be an error? ++ } ++ ++ SafeAssign(pExpandX, expandX); ++ SafeAssign(pExpandY, expandY); ++ SafeAssign(pUnusedBits, bitUnused); ++ SafeAssign(reinterpret_cast<UINT_32*>(pElemMode), elemMode); ++ ++ return bpp; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetCompBits ++* ++* @brief ++* Set each component's bit size and bit start. And set element mode and number type ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::GetCompBits( ++ UINT_32 c0, ///< [in] bits of component 0 ++ UINT_32 c1, ///< [in] bits of component 1 ++ UINT_32 c2, ///< [in] bits of component 2 ++ UINT_32 c3, ///< [in] bits of component 3 ++ ADDR_PIXEL_FORMATINFO* pInfo, ///< [out] per component info out ++ AddrElemMode elemMode) ///< [in] element mode ++{ ++ pInfo->comps = 0; ++ ++ pInfo->compBit[0] = c0; ++ pInfo->compBit[1] = c1; ++ pInfo->compBit[2] = c2; ++ pInfo->compBit[3] = c3; ++ ++ pInfo->compStart[0] = 0; ++ pInfo->compStart[1] = c0; ++ pInfo->compStart[2] = c0+c1; ++ pInfo->compStart[3] = c0+c1+c2; ++ ++ pInfo->elemMode = elemMode; ++ // still needed since component swap may depend on number of components ++ for (INT i=0; i<4; i++) ++ { ++ if (pInfo->compBit[i] == 0) ++ { ++ pInfo->compStart[i] = 0; // all null components start at bit 0 ++ pInfo->numType[i] = ADDR_NO_NUMBER; // and have no number type ++ } ++ else ++ { ++ pInfo->comps++; ++ } ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::GetCompBits ++* ++* @brief ++* Set the clear color (or clear depth/stencil) for a surface ++* ++* @note ++* If clearColor is zero, a default clear value is used in place of comps[4]. ++* If float32 is set, full precision is used, else the mantissa is reduced to 12-bits ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrElemLib::SetClearComps( ++ ADDR_FLT_32 comps[4], ///< [in/out] components ++ BOOL_32 clearColor, ///< [in] TRUE if clear color is set (CLEAR_COLOR) ++ BOOL_32 float32) ///< [in] TRUE if float32 component (BLEND_FLOAT32) ++{ ++ INT_32 i; ++ ++ // Use default clearvalues if clearColor is disabled ++ if (clearColor == FALSE) ++ { ++ for (i=0; i<3; i++) ++ { ++ comps[i].f = 0.0; ++ } ++ comps[3].f = 1.0; ++ } ++ ++ // Otherwise use the (modified) clear value ++ else ++ { ++ for (i=0; i<4; i++) ++ { // If full precision, use clear value unchanged ++ if (float32) ++ { ++ // Do nothing ++ //comps[i] = comps[i]; ++ } ++ // Else if it is a NaN, use the standard NaN value ++ else if ((comps[i].u & 0x7FFFFFFF) > 0x7F800000) ++ { ++ comps[i].u = 0xFFC00000; ++ } ++ // Else reduce the mantissa precision ++ else ++ { ++ comps[i].u = comps[i].u & 0xFFFFF000; ++ } ++ } ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::IsBlockCompressed ++* ++* @brief ++* TRUE if this is block compressed format ++* ++* @note ++* ++* @return ++* BOOL_32 ++*************************************************************************************************** ++*/ ++BOOL_32 AddrElemLib::IsBlockCompressed( ++ AddrFormat format) ///< [in] Format ++{ ++ return format >= ADDR_FMT_BC1 && format <= ADDR_FMT_BC7; ++} ++ ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::IsCompressed ++* ++* @brief ++* TRUE if this is block compressed format or 1 bit format ++* ++* @note ++* ++* @return ++* BOOL_32 ++*************************************************************************************************** ++*/ ++BOOL_32 AddrElemLib::IsCompressed( ++ AddrFormat format) ///< [in] Format ++{ ++ return IsBlockCompressed(format) || format == ADDR_FMT_BC1 || format == ADDR_FMT_BC7; ++} ++ ++/** ++*************************************************************************************************** ++* AddrElemLib::IsExpand3x ++* ++* @brief ++* TRUE if this is 3x expand format ++* ++* @note ++* ++* @return ++* BOOL_32 ++*************************************************************************************************** ++*/ ++BOOL_32 AddrElemLib::IsExpand3x( ++ AddrFormat format) ///< [in] Format ++{ ++ BOOL_32 is3x = FALSE; ++ ++ switch (format) ++ { ++ case ADDR_FMT_8_8_8: ++ case ADDR_FMT_16_16_16: ++ case ADDR_FMT_16_16_16_FLOAT: ++ case ADDR_FMT_32_32_32: ++ case ADDR_FMT_32_32_32_FLOAT: ++ is3x = TRUE; ++ break; ++ default: ++ break; ++ } ++ ++ return is3x; ++} ++ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.h b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.h +new file mode 100644 +index 0000000..c302b3b +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrelemlib.h +@@ -0,0 +1,270 @@ ++/* ++ * 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 addrelemlib.h ++* @brief Contains the class for element/pixel related functions ++*************************************************************************************************** ++*/ ++ ++#ifndef __ELEM_LIB_H__ ++#define __ELEM_LIB_H__ ++ ++#include "addrinterface.h" ++#include "addrobject.h" ++#include "addrcommon.h" ++ ++class AddrLib; ++ ++// The masks for property bits within the Properties INT_32 ++union ADDR_COMPONENT_FLAGS ++{ ++ struct ++ { ++ UINT_32 byteAligned : 1; ///< all components are byte aligned ++ UINT_32 exportNorm : 1; ///< components support R6xx NORM compression ++ UINT_32 floatComp : 1; ///< there is at least one floating point component ++ }; ++ ++ UINT_32 value; ++}; ++ ++// Copy from legacy lib's AddrNumberType ++enum AddrNumberType ++{ ++ // The following number types have the range [-1..1] ++ ADDR_NO_NUMBER, // This component doesn't exist and has no default value ++ ADDR_EPSILON, // Force component value to integer 0x00000001 ++ ADDR_ZERO, // Force component value to integer 0x00000000 ++ ADDR_ONE, // Force component value to floating point 1.0 ++ // Above values don't have any bits per component (keep ADDR_ONE the last of these) ++ ++ ADDR_UNORM, // Unsigned normalized (repeating fraction) full precision ++ ADDR_SNORM, // Signed normalized (repeating fraction) full precision ++ ADDR_GAMMA, // Gamma-corrected, full precision ++ ++ ADDR_UNORM_R5XXRB, // Unsigned normalized (repeating fraction) for r5xx RB ++ ADDR_SNORM_R5XXRB, // Signed normalized (repeating fraction) for r5xx RB ++ ADDR_GAMMA_R5XXRB, // Gamma-corrected for r5xx RB (note: unnormalized value) ++ ADDR_UNORM_R5XXBC, // Unsigned normalized (repeating fraction) for r5xx BC ++ ADDR_SNORM_R5XXBC, // Signed normalized (repeating fraction) for r5xx BC ++ ADDR_GAMMA_R5XXBC, // Gamma-corrected for r5xx BC (note: unnormalized value) ++ ++ ADDR_UNORM_R6XX, // Unsigned normalized (repeating fraction) for R6xx ++ ADDR_UNORM_R6XXDB, // Unorms for 24-bit depth: one value differs from ADDR_UNORM_R6XX ++ ADDR_SNORM_R6XX, // Signed normalized (repeating fraction) for R6xx ++ ADDR_GAMMA8_R6XX, // Gamma-corrected for r6xx ++ ADDR_GAMMA8_R7XX_TP, // Gamma-corrected for r7xx TP 12bit unorm 8.4. ++ ++ ADDR_U4FLOATC, // Unsigned float: 4-bit exponent, bias=15, no NaN, clamp [0..1] ++ ADDR_GAMMA_4SEG, // Gamma-corrected, four segment approximation ++ ADDR_U0FIXED, // Unsigned 0.N-bit fixed point ++ ++ // The following number types have large ranges (LEAVE ADDR_USCALED first or fix Finish routine) ++ ADDR_USCALED, // Unsigned integer converted to/from floating point ++ ADDR_SSCALED, // Signed integer converted to/from floating point ++ ADDR_USCALED_R5XXRB, // Unsigned integer to/from floating point for r5xx RB ++ ADDR_SSCALED_R5XXRB, // Signed integer to/from floating point for r5xx RB ++ ADDR_UINT_BITS, // Keep in unsigned integer form, clamped to specified range ++ ADDR_SINT_BITS, // Keep in signed integer form, clamped to specified range ++ ADDR_UINTBITS, // @@ remove Keep in unsigned integer form, use modulus to reduce bits ++ ADDR_SINTBITS, // @@ remove Keep in signed integer form, use modulus to reduce bits ++ ++ // The following number types and ADDR_U4FLOATC have exponents ++ // (LEAVE ADDR_S8FLOAT first or fix Finish routine) ++ ADDR_S8FLOAT, // Signed floating point with 8-bit exponent, bias=127 ++ ADDR_S8FLOAT32, // 32-bit IEEE float, passes through NaN values ++ ADDR_S5FLOAT, // Signed floating point with 5-bit exponent, bias=15 ++ ADDR_S5FLOATM, // Signed floating point with 5-bit exponent, bias=15, no NaN/Inf ++ ADDR_U5FLOAT, // Signed floating point with 5-bit exponent, bias=15 ++ ADDR_U3FLOATM, // Unsigned floating point with 3-bit exponent, bias=3 ++ ++ ADDR_S5FIXED, // Signed 5.N-bit fixed point, with rounding ++ ++ ADDR_END_NUMBER // Used for range comparisons ++}; ++ ++// Copy from legacy lib's AddrElement ++enum AddrElemMode ++{ ++ // These formats allow both packing an unpacking ++ ADDR_ROUND_BY_HALF, // add 1/2 and truncate when packing this element ++ ADDR_ROUND_TRUNCATE, // truncate toward 0 for sign/mag, else toward neg ++ ADDR_ROUND_DITHER, // Pack by dithering -- requires (x,y) position ++ ++ // These formats only allow unpacking, no packing ++ ADDR_UNCOMPRESSED, // Elements are not compressed: one data element per pixel/texel ++ ADDR_EXPANDED, // Elements are split up and stored in multiple data elements ++ ADDR_PACKED_STD, // Elements are compressed into ExpandX by ExpandY data elements ++ ADDR_PACKED_REV, // Like ADDR_PACKED, but X order of pixels is reverved ++ ADDR_PACKED_GBGR, // Elements are compressed 4:2:2 in G1B_G0R order (high to low) ++ ADDR_PACKED_BGRG, // Elements are compressed 4:2:2 in BG1_RG0 order (high to low) ++ ADDR_PACKED_BC1, // Each data element is uncompressed to a 4x4 pixel/texel array ++ ADDR_PACKED_BC2, // Each data element is uncompressed to a 4x4 pixel/texel array ++ ADDR_PACKED_BC3, // Each data element is uncompressed to a 4x4 pixel/texel array ++ ADDR_PACKED_BC4, // Each data element is uncompressed to a 4x4 pixel/texel array ++ ADDR_PACKED_BC5, // Each data element is uncompressed to a 4x4 pixel/texel array ++ ++ // These formats provide various kinds of compression ++ ADDR_ZPLANE_R5XX, // Compressed Zplane using r5xx architecture format ++ ADDR_ZPLANE_R6XX, // Compressed Zplane using r6xx architecture format ++ //@@ Fill in the compression modes ++ ++ ADDR_END_ELEMENT // Used for range comparisons ++}; ++ ++enum AddrDepthPlanarType ++{ ++ ADDR_DEPTH_PLANAR_NONE = 0, // No plane z/stencl ++ ADDR_DEPTH_PLANAR_R600 = 1, // R600 z and stencil planes are store within a tile ++ ADDR_DEPTH_PLANAR_R800 = 2, // R800 has separate z and stencil planes ++}; ++ ++/** ++*************************************************************************************************** ++* ADDR_PIXEL_FORMATINFO ++* ++* @brief ++* Per component info ++* ++*************************************************************************************************** ++*/ ++struct ADDR_PIXEL_FORMATINFO ++{ ++ UINT_32 compBit[4]; ++ AddrNumberType numType[4]; ++ UINT_32 compStart[4]; ++ AddrElemMode elemMode; ++ UINT_32 comps; ///< Number of components ++}; ++ ++/** ++*************************************************************************************************** ++* @brief This class contains asic indepentent element related attributes and operations ++*************************************************************************************************** ++*/ ++class AddrElemLib : public AddrObject ++{ ++protected: ++ AddrElemLib(AddrLib* const pAddrLib); ++ ++public: ++ ++ /// Makes this class virtual ++ virtual ~AddrElemLib(); ++ ++ static AddrElemLib *Create( ++ const AddrLib* const pAddrLib); ++ ++ /// The implementation is only for R6xx/R7xx, so make it virtual in case we need for R8xx ++ BOOL_32 PixGetExportNorm( ++ AddrColorFormat colorFmt, ++ AddrSurfaceNumber numberFmt, AddrSurfaceSwap swap) const; ++ ++ /// Below method are asic independent, so make them just static. ++ /// Remove static if we need different operation in hwl. ++ ++ VOID Flt32ToDepthPixel( ++ AddrDepthFormat format, const ADDR_FLT_32 comps[2], UINT_8 *pPixel) const; ++ ++ VOID Flt32ToColorPixel( ++ AddrColorFormat format, AddrSurfaceNumber surfNum, AddrSurfaceSwap surfSwap, ++ const ADDR_FLT_32 comps[4], UINT_8 *pPixel) const; ++ ++ static VOID Flt32sToInt32s( ++ ADDR_FLT_32 value, UINT_32 bits, AddrNumberType numberType, UINT_32* pResult); ++ ++ static VOID Int32sToPixel( ++ UINT_32 numComps, UINT_32* pComps, UINT_32* pCompBits, UINT_32* pCompStart, ++ ADDR_COMPONENT_FLAGS properties, UINT_32 resultBits, UINT_8* pPixel); ++ ++ VOID PixGetColorCompInfo( ++ AddrColorFormat format, AddrSurfaceNumber number, AddrSurfaceSwap swap, ++ ADDR_PIXEL_FORMATINFO* pInfo) const; ++ ++ VOID PixGetDepthCompInfo( ++ AddrDepthFormat format, ADDR_PIXEL_FORMATINFO* pInfo) const; ++ ++ UINT_32 GetBitsPerPixel( ++ AddrFormat format, AddrElemMode* pElemMode, ++ UINT_32* pExpandX = NULL, UINT_32* pExpandY = NULL, UINT_32* pBitsUnused = NULL); ++ ++ static VOID SetClearComps( ++ ADDR_FLT_32 comps[4], BOOL_32 clearColor, BOOL_32 float32); ++ ++ VOID AdjustSurfaceInfo( ++ AddrElemMode elemMode, UINT_32 expandX, UINT_32 expandY, ++ UINT_32* pBpp, UINT_32* pBasePitch, UINT_32* pWidth, UINT_32* pHeight); ++ ++ VOID RestoreSurfaceInfo( ++ AddrElemMode elemMode, UINT_32 expandX, UINT_32 expandY, ++ UINT_32* pBpp, UINT_32* pWidth, UINT_32* pHeight); ++ ++ /// Checks if depth and stencil are planar inside a tile ++ BOOL_32 IsDepthStencilTilePlanar() ++ { ++ return (m_depthPlanarType == ADDR_DEPTH_PLANAR_R600) ? TRUE : FALSE; ++ } ++ ++ /// Sets m_configFlags, copied from AddrLib ++ VOID SetConfigFlags(ADDR_CONFIG_FLAGS flags) ++ { ++ m_configFlags = flags; ++ } ++ ++ static BOOL_32 IsCompressed(AddrFormat format); ++ static BOOL_32 IsBlockCompressed(AddrFormat format); ++ static BOOL_32 IsExpand3x(AddrFormat format); ++ ++protected: ++ ++ static VOID GetCompBits( ++ UINT_32 c0, UINT_32 c1, UINT_32 c2, UINT_32 c3, ++ ADDR_PIXEL_FORMATINFO* pInfo, ++ AddrElemMode elemMode = ADDR_ROUND_BY_HALF); ++ ++ static VOID GetCompType( ++ AddrColorFormat format, AddrSurfaceNumber numType, ++ ADDR_PIXEL_FORMATINFO* pInfo); ++ ++ static VOID GetCompSwap( ++ AddrSurfaceSwap swap, ADDR_PIXEL_FORMATINFO* pInfo); ++ ++ static VOID SwapComps( ++ UINT_32 c0, UINT_32 c1, ADDR_PIXEL_FORMATINFO* pInfo); ++ ++private: ++ ++ UINT_32 m_fp16ExportNorm; ///< If allow FP16 to be reported as EXPORT_NORM ++ AddrDepthPlanarType m_depthPlanarType; ++ ++ ADDR_CONFIG_FLAGS m_configFlags; ///< Copy of AddrLib's configFlags ++ AddrLib* const m_pAddrLib; ///< Pointer to parent addrlib instance ++}; ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.cpp +new file mode 100644 +index 0000000..51b1eab +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.cpp +@@ -0,0 +1,4028 @@ ++/* ++ * 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 numGroupBits; ++ 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. ++ // ++ numGroupBits = Log2(m_pipeInterleaveBytes); ++ 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 ++{ ++ // Check if HWL has handled ++ BOOL_32 hwlHandled = FALSE; ++ ++ 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); ++ } ++ } ++ ++ hwlHandled = 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; ++} +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.h b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.h +new file mode 100644 +index 0000000..43c55ff +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrlib.h +@@ -0,0 +1,695 @@ ++/* ++ * 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.h ++* @brief Contains the AddrLib base class definition. ++*************************************************************************************************** ++*/ ++ ++#ifndef __ADDR_LIB_H__ ++#define __ADDR_LIB_H__ ++ ++ ++#include "addrinterface.h" ++#include "addrobject.h" ++#include "addrelemlib.h" ++ ++#if BRAHMA_BUILD ++#include "amdgpu_id.h" ++#else ++#include "atiid.h" ++#endif ++ ++#ifndef CIASICIDGFXENGINE_R600 ++#define CIASICIDGFXENGINE_R600 0x00000006 ++#endif ++ ++#ifndef CIASICIDGFXENGINE_R800 ++#define CIASICIDGFXENGINE_R800 0x00000008 ++#endif ++ ++#ifndef CIASICIDGFXENGINE_SOUTHERNISLAND ++#define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A ++#endif ++ ++#ifndef CIASICIDGFXENGINE_SEAISLAND ++#define CIASICIDGFXENGINE_SEAISLAND 0x0000000B ++#endif ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define pipeinterleave ++*************************************************************************************************** ++*/ ++enum AddrPipeInterleave ++{ ++ ADDR_PIPEINTERLEAVE_256B = 256, ++ ADDR_PIPEINTERLEAVE_512B = 512, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define DRAM row size ++*************************************************************************************************** ++*/ ++enum AddrRowSize ++{ ++ ADDR_ROWSIZE_1KB = 1024, ++ ADDR_ROWSIZE_2KB = 2048, ++ ADDR_ROWSIZE_4KB = 4096, ++ ADDR_ROWSIZE_8KB = 8192, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define bank interleave ++*************************************************************************************************** ++*/ ++enum AddrBankInterleave ++{ ++ ADDR_BANKINTERLEAVE_1 = 1, ++ ADDR_BANKINTERLEAVE_2 = 2, ++ ADDR_BANKINTERLEAVE_4 = 4, ++ ADDR_BANKINTERLEAVE_8 = 8, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define MGPU chip tile size ++*************************************************************************************************** ++*/ ++enum AddrChipTileSize ++{ ++ ADDR_CHIPTILESIZE_16 = 16, ++ ADDR_CHIPTILESIZE_32 = 32, ++ ADDR_CHIPTILESIZE_64 = 64, ++ ADDR_CHIPTILESIZE_128 = 128, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define shader engine tile size ++*************************************************************************************************** ++*/ ++enum AddrEngTileSize ++{ ++ ADDR_SE_TILESIZE_16 = 16, ++ ADDR_SE_TILESIZE_32 = 32, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define bank swap size ++*************************************************************************************************** ++*/ ++enum AddrBankSwapSize ++{ ++ ADDR_BANKSWAP_128B = 128, ++ ADDR_BANKSWAP_256B = 256, ++ ADDR_BANKSWAP_512B = 512, ++ ADDR_BANKSWAP_1KB = 1024, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Neutral enums that define bank swap size ++*************************************************************************************************** ++*/ ++enum AddrSampleSplitSize ++{ ++ ADDR_SAMPLESPLIT_1KB = 1024, ++ ADDR_SAMPLESPLIT_2KB = 2048, ++ ADDR_SAMPLESPLIT_4KB = 4096, ++ ADDR_SAMPLESPLIT_8KB = 8192, ++}; ++ ++/** ++*************************************************************************************************** ++* @brief Flags for AddrTileMode ++*************************************************************************************************** ++*/ ++struct AddrTileModeFlags ++{ ++ UINT_32 thickness : 4; ++ UINT_32 isLinear : 1; ++ UINT_32 isMicro : 1; ++ UINT_32 isMacro : 1; ++ UINT_32 isMacro3d : 1; ++ UINT_32 isPrt : 1; ++ UINT_32 isPrtNoRotation : 1; ++ UINT_32 isBankSwapped : 1; ++}; ++ ++/** ++*************************************************************************************************** ++* @brief This class contains asic independent address lib functionalities ++*************************************************************************************************** ++*/ ++class AddrLib : public AddrObject ++{ ++public: ++ virtual ~AddrLib(); ++ ++ static ADDR_E_RETURNCODE Create( ++ const ADDR_CREATE_INPUT* pCreateInfo, ADDR_CREATE_OUTPUT* pCreateOut); ++ ++ /// Pair of Create ++ VOID Destroy() ++ { ++ delete this; ++ } ++ ++ static AddrLib* GetAddrLib( ++ ADDR_HANDLE hLib); ++ ++ /// Returns AddrLib version (from compiled binary instead include file) ++ UINT_32 GetVersion() ++ { ++ return m_version; ++ } ++ ++ /// Returns asic chip family name defined by AddrLib ++ AddrChipFamily GetAddrChipFamily() ++ { ++ return m_chipFamily; ++ } ++ ++ /// Returns tileIndex support ++ BOOL_32 UseTileIndex(INT_32 index) const ++ { ++ return m_configFlags.useTileIndex && (index != TileIndexInvalid); ++ } ++ ++ /// Returns combined swizzle support ++ BOOL_32 UseCombinedSwizzle() const ++ { ++ return m_configFlags.useCombinedSwizzle; ++ } ++ ++ // ++ // Interface stubs ++ // ++ ADDR_E_RETURNCODE ComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeSliceTileSwizzle( ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ExtractBankPipeSwizzle( ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE CombineBankPipeSwizzle( ++ const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeBaseSwizzle( ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); ++ ++ ADDR_E_RETURNCODE ComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ConvertTileIndex( ++ const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ConvertTileIndex1( ++ const ADDR_CONVERT_TILEINDEX1_INPUT* pIn, ++ ADDR_CONVERT_TILEINDEX_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE GetTileIndex( ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeHtileInfo( ++ const ADDR_COMPUTE_HTILE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_INFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeCmaskInfo( ++ const ADDR_COMPUTE_CMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_INFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeDccInfo( ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeHtileAddrFromCoord( ++ const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeCmaskAddrFromCoord( ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeHtileCoordFromAddr( ++ const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputeCmaskCoordFromAddr( ++ const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE ComputePrtInfo( ++ const ADDR_PRT_INFO_INPUT* pIn, ++ ADDR_PRT_INFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE Flt32ToDepthPixel( ++ const ELEM_FLT32TODEPTHPIXEL_INPUT* pIn, ++ ELEM_FLT32TODEPTHPIXEL_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE Flt32ToColorPixel( ++ const ELEM_FLT32TOCOLORPIXEL_INPUT* pIn, ++ ELEM_FLT32TOCOLORPIXEL_OUTPUT* pOut) const; ++ ++ BOOL_32 GetExportNorm( ++ const ELEM_GETEXPORTNORM_INPUT* pIn) const; ++ ++protected: ++ AddrLib(); // Constructor is protected ++ AddrLib(const AddrClient* pClient); ++ ++ /// Pure Virtual function for Hwl computing surface info ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl computing surface address from coord ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl computing surface coord from address ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl computing surface tile swizzle ++ virtual ADDR_E_RETURNCODE HwlComputeSliceTileSwizzle( ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl extracting bank/pipe swizzle from base256b ++ virtual ADDR_E_RETURNCODE HwlExtractBankPipeSwizzle( ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl combining bank/pipe swizzle ++ virtual ADDR_E_RETURNCODE HwlCombineBankPipeSwizzle( ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, ADDR_TILEINFO* pTileInfo, ++ UINT_64 baseAddr, UINT_32* pTileSwizzle) const = 0; ++ ++ /// Pure Virtual function for Hwl computing base swizzle ++ virtual ADDR_E_RETURNCODE HwlComputeBaseSwizzle( ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl computing HTILE base align ++ virtual UINT_32 HwlComputeHtileBaseAlign( ++ BOOL_32 isTcCompatible, BOOL_32 isLinear, ADDR_TILEINFO* pTileInfo) const = 0; ++ ++ /// Pure Virtual function for Hwl computing HTILE bpp ++ virtual UINT_32 HwlComputeHtileBpp( ++ BOOL_32 isWidth8, BOOL_32 isHeight8) const = 0; ++ ++ /// Pure Virtual function for Hwl computing HTILE bytes ++ virtual UINT_64 HwlComputeHtileBytes( ++ UINT_32 pitch, UINT_32 height, UINT_32 bpp, ++ BOOL_32 isLinear, UINT_32 numSlices, UINT_64* pSliceBytes, UINT_32 baseAlign) const = 0; ++ ++ /// Pure Virtual function for Hwl computing FMASK info ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) = 0; ++ ++ /// Pure Virtual function for Hwl FMASK address from coord ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl FMASK coord from address ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl convert tile info from real value to HW value ++ virtual ADDR_E_RETURNCODE HwlConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const = 0; ++ ++ /// Pure Virtual function for Hwl compute mipmap info ++ virtual BOOL_32 HwlComputeMipLevel( ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const = 0; ++ ++ /// Pure Virtual function for Hwl compute max cmask blockMax value ++ virtual BOOL_32 HwlGetMaxCmaskBlockMax() const = 0; ++ ++ /// Pure Virtual function for Hwl compute fmask bits ++ virtual UINT_32 HwlComputeFmaskBits( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ UINT_32* pNumSamples) const = 0; ++ ++ /// Virtual function to get index (not pure then no need to implement this in all hwls ++ virtual ADDR_E_RETURNCODE HwlGetTileIndex( ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut) const ++ { ++ return ADDR_NOTSUPPORTED; ++ } ++ ++ /// Virtual function for Hwl to compute Dcc info ++ virtual ADDR_E_RETURNCODE HwlComputeDccInfo( ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const ++ { ++ return ADDR_NOTSUPPORTED; ++ } ++ ++ /// Virtual function to get cmask address for tc compatible cmask ++ virtual ADDR_E_RETURNCODE HwlComputeCmaskAddrFromCoord( ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) const ++ { ++ return ADDR_NOTSUPPORTED; ++ } ++ // Compute attributes ++ ++ // HTILE ++ UINT_32 ComputeHtileInfo( ++ ADDR_HTILE_FLAGS flags, ++ UINT_32 pitchIn, UINT_32 heightIn, UINT_32 numSlices, ++ BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, ++ ADDR_TILEINFO* pTileInfo, ++ UINT_32* pPitchOut, UINT_32* pHeightOut, UINT_64* pHtileBytes, ++ UINT_32* pMacroWidth = NULL, UINT_32* pMacroHeight = NULL, ++ UINT_64* pSliceSize = NULL, UINT_32* pBaseAlign = NULL) const; ++ ++ // CMASK ++ ADDR_E_RETURNCODE ComputeCmaskInfo( ++ ADDR_CMASK_FLAGS flags, ++ UINT_32 pitchIn, UINT_32 heightIn, UINT_32 numSlices, BOOL_32 isLinear, ++ ADDR_TILEINFO* pTileInfo, UINT_32* pPitchOut, UINT_32* pHeightOut, UINT_64* pCmaskBytes, ++ UINT_32* pMacroWidth, UINT_32* pMacroHeight, UINT_64* pSliceSize = NULL, ++ UINT_32* pBaseAlign = NULL, UINT_32* pBlockMax = NULL) const; ++ ++ virtual VOID HwlComputeTileDataWidthAndHeightLinear( ++ UINT_32* pMacroWidth, UINT_32* pMacroHeight, ++ UINT_32 bpp, ADDR_TILEINFO* pTileInfo) const; ++ ++ // CMASK & HTILE addressing ++ virtual UINT_64 HwlComputeXmaskAddrFromCoord( ++ UINT_32 pitch, UINT_32 height, UINT_32 x, UINT_32 y, UINT_32 slice, ++ UINT_32 numSlices, UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, ++ BOOL_32 isHeight8, ADDR_TILEINFO* pTileInfo, ++ UINT_32* bitPosition) const; ++ ++ virtual VOID HwlComputeXmaskCoordFromAddr( ++ UINT_64 addr, UINT_32 bitPosition, UINT_32 pitch, UINT_32 height, UINT_32 numSlices, ++ UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, ++ ADDR_TILEINFO* pTileInfo, UINT_32* pX, UINT_32* pY, UINT_32* pSlice) const; ++ ++ // Surface mipmap ++ VOID ComputeMipLevel( ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const; ++ ++ /// Pure Virtual function for Hwl checking degrade for base level ++ virtual BOOL_32 HwlDegradeBaseLevel( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const = 0; ++ ++ virtual BOOL_32 HwlOverrideTileMode( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ AddrTileMode* pTileMode, ++ AddrTileType* pTileType) const ++ { ++ // not supported in hwl layer, FALSE for not-overrided ++ return FALSE; ++ } ++ ++ AddrTileMode DegradeLargeThickTile(AddrTileMode tileMode, UINT_32 bpp) const; ++ ++ VOID PadDimensions( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, ++ UINT_32 numSamples, ADDR_TILEINFO* pTileInfo, UINT_32 padDims, UINT_32 mipLevel, ++ UINT_32* pPitch, UINT_32 pitchAlign, UINT_32* pHeight, UINT_32 heightAlign, ++ UINT_32* pSlices, UINT_32 sliceAlign) const; ++ ++ virtual VOID HwlPadDimensions( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, ++ UINT_32 numSamples, ADDR_TILEINFO* pTileInfo, UINT_32 padDims, UINT_32 mipLevel, ++ UINT_32* pPitch, UINT_32 pitchAlign, UINT_32* pHeight, UINT_32 heightAlign, ++ UINT_32* pSlices, UINT_32 sliceAlign) const ++ { ++ } ++ ++ // ++ // Addressing shared for linear/1D tiling ++ // ++ UINT_64 ComputeSurfaceAddrFromCoordLinear( ++ UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSlices, ++ UINT_32* pBitPosition) const; ++ ++ VOID ComputeSurfaceCoordFromAddrLinear( ++ UINT_64 addr, UINT_32 bitPosition, UINT_32 bpp, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSlices, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample) const; ++ ++ VOID ComputeSurfaceCoordFromAddrMicroTiled( ++ UINT_64 addr, UINT_32 bitPosition, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, ++ AddrTileType microTileType, BOOL_32 isDepthSampleOrder) const; ++ ++ UINT_32 ComputePixelIndexWithinMicroTile( ++ UINT_32 x, UINT_32 y, UINT_32 z, ++ UINT_32 bpp, AddrTileMode tileMode, AddrTileType microTileType) const; ++ ++ /// Pure Virtual function for Hwl computing coord from offset inside micro tile ++ virtual VOID HwlComputePixelCoordFromOffset( ++ UINT_32 offset, UINT_32 bpp, UINT_32 numSamples, ++ AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, ++ AddrTileType microTileType, BOOL_32 isDepthSampleOrder) const = 0; ++ ++ // ++ // Addressing shared by all ++ // ++ virtual UINT_32 HwlGetPipes( ++ const ADDR_TILEINFO* pTileInfo) const; ++ ++ UINT_32 ComputePipeFromAddr( ++ UINT_64 addr, UINT_32 numPipes) const; ++ ++ /// Pure Virtual function for Hwl computing pipe from coord ++ virtual UINT_32 ComputePipeFromCoord( ++ UINT_32 x, UINT_32 y, UINT_32 slice, AddrTileMode tileMode, ++ UINT_32 pipeSwizzle, BOOL_32 flags, ADDR_TILEINFO* pTileInfo) const = 0; ++ ++ /// Pure Virtual function for Hwl computing coord Y for 8 pipe cmask/htile ++ virtual UINT_32 HwlComputeXmaskCoordYFrom8Pipe( ++ UINT_32 pipe, UINT_32 x) const = 0; ++ ++ // ++ // Initialization ++ // ++ /// Pure Virtual function for Hwl computing internal global parameters from h/w registers ++ virtual BOOL_32 HwlInitGlobalParams( ++ const ADDR_CREATE_INPUT* pCreateIn) = 0; ++ ++ /// Pure Virtual function for Hwl converting chip family ++ virtual AddrChipFamily HwlConvertChipFamily(UINT_32 uChipFamily, UINT_32 uChipRevision) = 0; ++ ++ // ++ // Misc helper ++ // ++ static const AddrTileModeFlags m_modeFlags[ADDR_TM_COUNT]; ++ ++ static UINT_32 ComputeSurfaceThickness( ++ AddrTileMode tileMode); ++ ++ // Checking tile mode ++ static BOOL_32 IsMacroTiled(AddrTileMode tileMode); ++ static BOOL_32 IsMacro3dTiled(AddrTileMode tileMode); ++ static BOOL_32 IsLinear(AddrTileMode tileMode); ++ static BOOL_32 IsMicroTiled(AddrTileMode tileMode); ++ static BOOL_32 IsPrtTileMode(AddrTileMode tileMode); ++ static BOOL_32 IsPrtNoRotationTileMode(AddrTileMode tileMode); ++ ++ static UINT_32 Bits2Number(UINT_32 bitNum,...); ++ ++ static UINT_32 GetNumFragments(UINT_32 numSamples, UINT_32 numFrags) ++ { ++ return numFrags != 0 ? numFrags : Max(1u, numSamples); ++ } ++ ++ /// Returns pointer of AddrElemLib ++ AddrElemLib* GetElemLib() const ++ { ++ return m_pElemLib; ++ } ++ ++ /// Return TRUE if tile info is needed ++ BOOL_32 UseTileInfo() const ++ { ++ return !m_configFlags.ignoreTileInfo; ++ } ++ ++ /// Returns fillSizeFields flag ++ UINT_32 GetFillSizeFieldsFlags() const ++ { ++ return m_configFlags.fillSizeFields; ++ } ++ ++ /// Adjusts pitch alignment for flipping surface ++ VOID AdjustPitchAlignment( ++ ADDR_SURFACE_FLAGS flags, UINT_32* pPitchAlign) const; ++ ++ /// Overwrite tile config according to tile index ++ virtual ADDR_E_RETURNCODE HwlSetupTileCfg( ++ INT_32 index, INT_32 macroModeIndex, ++ ADDR_TILEINFO* pInfo, AddrTileMode* mode = NULL, AddrTileType* type = NULL) const; ++ ++ /// Overwrite macro tile config according to tile index ++ virtual INT_32 HwlComputeMacroModeIndex( ++ INT_32 index, ADDR_SURFACE_FLAGS flags, UINT_32 bpp, UINT_32 numSamples, ++ ADDR_TILEINFO* pTileInfo, AddrTileMode *pTileMode = NULL, AddrTileType *pTileType = NULL ++ ) const ++ { ++ return TileIndexNoMacroIndex; ++ } ++ ++ /// Pre-handler of 3x pitch (96 bit) adjustment ++ virtual UINT_32 HwlPreHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; ++ /// Post-handler of 3x pitch adjustment ++ virtual UINT_32 HwlPostHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; ++ /// Check miplevel after surface adjustment ++ ADDR_E_RETURNCODE PostComputeMipLevel( ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ /// Quad buffer stereo support, has its implementation in ind. layer ++ virtual BOOL_32 ComputeQbStereoInfo( ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ /// Pure virutual function to compute stereo bank swizzle for right eye ++ virtual UINT_32 HwlComputeQbStereoRightSwizzle( ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; ++ ++private: ++ // Disallow the copy constructor ++ AddrLib(const AddrLib& a); ++ ++ // Disallow the assignment operator ++ AddrLib& operator=(const AddrLib& a); ++ ++ VOID SetAddrChipFamily(UINT_32 uChipFamily, UINT_32 uChipRevision); ++ ++ UINT_32 ComputeCmaskBaseAlign( ++ ADDR_CMASK_FLAGS flags, ADDR_TILEINFO* pTileInfo) const; ++ ++ UINT_64 ComputeCmaskBytes( ++ UINT_32 pitch, UINT_32 height, UINT_32 numSlices) const; ++ ++ // ++ // CMASK/HTILE shared methods ++ // ++ VOID ComputeTileDataWidthAndHeight( ++ UINT_32 bpp, UINT_32 cacheBits, ADDR_TILEINFO* pTileInfo, ++ UINT_32* pMacroWidth, UINT_32* pMacroHeight) const; ++ ++ UINT_32 ComputeXmaskCoordYFromPipe( ++ UINT_32 pipe, UINT_32 x) const; ++ ++ VOID SetMinPitchAlignPixels(UINT_32 minPitchAlignPixels); ++ ++ BOOL_32 DegradeBaseLevel( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, AddrTileMode* pTileMode) const; ++ ++protected: ++ AddrLibClass m_class; ///< Store class type (HWL type) ++ ++ AddrChipFamily m_chipFamily; ///< Chip family translated from the one in atiid.h ++ ++ UINT_32 m_chipRevision; ///< Revision id from xxx_id.h ++ ++ UINT_32 m_version; ///< Current version ++ ++ // ++ // Global parameters ++ // ++ ADDR_CONFIG_FLAGS m_configFlags; ///< Global configuration flags. Note this is setup by ++ /// AddrLib instead of Client except forceLinearAligned ++ ++ UINT_32 m_pipes; ///< Number of pipes ++ UINT_32 m_banks; ///< Number of banks ++ /// For r800 this is MC_ARB_RAMCFG.NOOFBANK ++ /// Keep it here to do default parameter calculation ++ ++ UINT_32 m_pipeInterleaveBytes; ++ ///< Specifies the size of contiguous address space ++ /// within each tiling pipe when making linear ++ /// accesses. (Formerly Group Size) ++ ++ UINT_32 m_rowSize; ///< DRAM row size, in bytes ++ ++ UINT_32 m_minPitchAlignPixels; ///< Minimum pitch alignment in pixels ++ UINT_32 m_maxSamples; ///< Max numSamples ++private: ++ AddrElemLib* m_pElemLib; ///< Element Lib pointer ++}; ++ ++AddrLib* AddrSIHwlInit (const AddrClient* pClient); ++AddrLib* AddrCIHwlInit (const AddrClient* pClient); ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.cpp +new file mode 100644 +index 0000000..863a252 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.cpp +@@ -0,0 +1,246 @@ ++/* ++ * 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 addrobject.cpp ++* @brief Contains the AddrObject base class implementation. ++*************************************************************************************************** ++*/ ++ ++#include "addrinterface.h" ++#include "addrobject.h" ++ ++/** ++*************************************************************************************************** ++* AddrObject::AddrObject ++* ++* @brief ++* Constructor for the AddrObject class. ++*************************************************************************************************** ++*/ ++AddrObject::AddrObject() ++{ ++ m_client.handle = NULL; ++ m_client.callbacks.allocSysMem = NULL; ++ m_client.callbacks.freeSysMem = NULL; ++ m_client.callbacks.debugPrint = NULL; ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::AddrObject ++* ++* @brief ++* Constructor for the AddrObject class. ++*************************************************************************************************** ++*/ ++AddrObject::AddrObject(const AddrClient* pClient) ++{ ++ m_client = *pClient; ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::~AddrObject ++* ++* @brief ++* Destructor for the AddrObject class. ++*************************************************************************************************** ++*/ ++AddrObject::~AddrObject() ++{ ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::ClientAlloc ++* ++* @brief ++* Calls instanced allocSysMem inside AddrClient ++*************************************************************************************************** ++*/ ++VOID* AddrObject::ClientAlloc( ++ size_t objSize, ///< [in] Size to allocate ++ const AddrClient* pClient) ///< [in] Client pointer ++{ ++ VOID* pObjMem = NULL; ++ ++ if (pClient->callbacks.allocSysMem != NULL) ++ { ++ ADDR_ALLOCSYSMEM_INPUT allocInput = {0}; ++ ++ allocInput.size = sizeof(ADDR_ALLOCSYSMEM_INPUT); ++ allocInput.flags.value = 0; ++ allocInput.sizeInBytes = static_cast<UINT_32>(objSize); ++ allocInput.hClient = pClient->handle; ++ ++ pObjMem = pClient->callbacks.allocSysMem(&allocInput); ++ } ++ ++ return pObjMem; ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::AddrMalloc ++* ++* @brief ++* A wrapper of ClientAlloc ++*************************************************************************************************** ++*/ ++VOID* AddrObject::AddrMalloc( ++ size_t objSize) const ///< [in] Size to allocate ++{ ++ return ClientAlloc(objSize, &m_client);; ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::ClientFree ++* ++* @brief ++* Calls freeSysMem inside AddrClient ++*************************************************************************************************** ++*/ ++VOID AddrObject::ClientFree( ++ VOID* pObjMem, ///< [in] User virtual address to free. ++ const AddrClient* pClient) ///< [in] Client pointer ++{ ++ if (pClient->callbacks.freeSysMem != NULL) ++ { ++ if (pObjMem != NULL) ++ { ++ ADDR_FREESYSMEM_INPUT freeInput = {0}; ++ ++ freeInput.size = sizeof(ADDR_FREESYSMEM_INPUT); ++ freeInput.hClient = pClient->handle; ++ freeInput.pVirtAddr = pObjMem; ++ ++ pClient->callbacks.freeSysMem(&freeInput); ++ } ++ } ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::AddrFree ++* ++* @brief ++* A wrapper of ClientFree ++*************************************************************************************************** ++*/ ++VOID AddrObject::AddrFree( ++ VOID* pObjMem) const ///< [in] User virtual address to free. ++{ ++ ClientFree(pObjMem, &m_client); ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::operator new ++* ++* @brief ++* Allocates memory needed for AddrObject object. (with ADDR_CLIENT_HANDLE) ++* ++* @return ++* Returns NULL if unsuccessful. ++*************************************************************************************************** ++*/ ++VOID* AddrObject::operator new( ++ size_t objSize, ///< [in] Size to allocate ++ const AddrClient* pClient) ///< [in] Client pointer ++{ ++ return ClientAlloc(objSize, pClient); ++} ++ ++ ++/** ++*************************************************************************************************** ++* AddrObject::operator delete ++* ++* @brief ++* Frees AddrObject object memory. ++*************************************************************************************************** ++*/ ++VOID AddrObject::operator delete( ++ VOID* pObjMem, ///< [in] User virtual address to free. ++ const AddrClient* pClient) ///< [in] Client handle ++{ ++ ClientFree(pObjMem, pClient); ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::operator delete ++* ++* @brief ++* Frees AddrObject object memory. ++*************************************************************************************************** ++*/ ++VOID AddrObject::operator delete( ++ VOID* pObjMem) ///< [in] User virtual address to free. ++{ ++ AddrObject* pObj = static_cast<AddrObject*>(pObjMem); ++ ClientFree(pObjMem, &pObj->m_client); ++} ++ ++/** ++*************************************************************************************************** ++* AddrObject::DebugPrint ++* ++* @brief ++* Print debug message ++* ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID AddrObject::DebugPrint( ++ const CHAR* pDebugString, ///< [in] Debug string ++ ...) const ++{ ++#if DEBUG ++ if (m_client.callbacks.debugPrint != NULL) ++ { ++ va_list ap; ++ ++ va_start(ap, pDebugString); ++ ++ ADDR_DEBUGPRINT_INPUT debugPrintInput = {0}; ++ ++ debugPrintInput.size = sizeof(ADDR_DEBUGPRINT_INPUT); ++ debugPrintInput.pDebugString = const_cast<CHAR*>(pDebugString); ++ debugPrintInput.hClient = m_client.handle; ++ va_copy(debugPrintInput.ap, ap); ++ ++ m_client.callbacks.debugPrint(&debugPrintInput); ++ ++ va_end(ap); ++ } ++#endif ++} ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.h b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.h +new file mode 100644 +index 0000000..3540088 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/core/addrobject.h +@@ -0,0 +1,89 @@ ++/* ++ * 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 addrobject.h ++* @brief Contains the AddrObject base class definition. ++*************************************************************************************************** ++*/ ++ ++#ifndef __ADDR_OBJECT_H__ ++#define __ADDR_OBJECT_H__ ++ ++#include "addrtypes.h" ++#include "addrcommon.h" ++ ++/** ++*************************************************************************************************** ++* @brief This structure contains client specific data ++*************************************************************************************************** ++*/ ++struct AddrClient ++{ ++ ADDR_CLIENT_HANDLE handle; ++ ADDR_CALLBACKS callbacks; ++}; ++/** ++*************************************************************************************************** ++* @brief This class is the base class for all ADDR class objects. ++*************************************************************************************************** ++*/ ++class AddrObject ++{ ++public: ++ AddrObject(); ++ AddrObject(const AddrClient* pClient); ++ virtual ~AddrObject(); ++ ++ VOID* operator new(size_t size, const AddrClient* pClient); ++ VOID operator delete(VOID* pObj, const AddrClient* pClient); ++ VOID operator delete(VOID* pObj); ++ VOID* AddrMalloc(size_t size) const; ++ VOID AddrFree(VOID* pObj) const; ++ ++ VOID DebugPrint( ++ const CHAR* pDebugString, ++ ...) const; ++ ++ const AddrClient* GetClient() const {return &m_client;} ++ ++protected: ++ AddrClient m_client; ++ ++private: ++ static VOID* ClientAlloc(size_t size, const AddrClient* pClient); ++ static VOID ClientFree(VOID* pObj, const AddrClient* pClient); ++ ++ // disallow the copy constructor ++ AddrObject(const AddrObject& a); ++ ++ // disallow the assignment operator ++ AddrObject& operator=(const AddrObject& a); ++}; ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/inc/chip/r800/si_gb_reg.h b/src/gallium/winsys/radeon/amdgpu/addrlib/inc/chip/r800/si_gb_reg.h +new file mode 100644 +index 0000000..cf67f60 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/inc/chip/r800/si_gb_reg.h +@@ -0,0 +1,155 @@ ++#if !defined (__SI_GB_REG_H__) ++#define __SI_GB_REG_H__ ++ ++/* ++ * 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. ++ */ ++ ++// ++// Make sure the necessary endian defines are there. ++// ++#if defined(LITTLEENDIAN_CPU) ++#elif defined(BIGENDIAN_CPU) ++#else ++#error "BIGENDIAN_CPU or LITTLEENDIAN_CPU must be defined" ++#endif ++ ++/* ++ * GB_ADDR_CONFIG struct ++ */ ++ ++#if defined(LITTLEENDIAN_CPU) ++ ++ typedef struct _GB_ADDR_CONFIG_T { ++ unsigned int num_pipes : 3; ++ unsigned int : 1; ++ unsigned int pipe_interleave_size : 3; ++ unsigned int : 1; ++ unsigned int bank_interleave_size : 3; ++ unsigned int : 1; ++ unsigned int num_shader_engines : 2; ++ unsigned int : 2; ++ unsigned int shader_engine_tile_size : 3; ++ unsigned int : 1; ++ unsigned int num_gpus : 3; ++ unsigned int : 1; ++ unsigned int multi_gpu_tile_size : 2; ++ unsigned int : 2; ++ unsigned int row_size : 2; ++ unsigned int num_lower_pipes : 1; ++ unsigned int : 1; ++ } GB_ADDR_CONFIG_T; ++ ++#elif defined(BIGENDIAN_CPU) ++ ++ typedef struct _GB_ADDR_CONFIG_T { ++ unsigned int : 1; ++ unsigned int num_lower_pipes : 1; ++ unsigned int row_size : 2; ++ unsigned int : 2; ++ unsigned int multi_gpu_tile_size : 2; ++ unsigned int : 1; ++ unsigned int num_gpus : 3; ++ unsigned int : 1; ++ unsigned int shader_engine_tile_size : 3; ++ unsigned int : 2; ++ unsigned int num_shader_engines : 2; ++ unsigned int : 1; ++ unsigned int bank_interleave_size : 3; ++ unsigned int : 1; ++ unsigned int pipe_interleave_size : 3; ++ unsigned int : 1; ++ unsigned int num_pipes : 3; ++ } GB_ADDR_CONFIG_T; ++ ++#endif ++ ++typedef union { ++ unsigned int val : 32; ++ GB_ADDR_CONFIG_T f; ++} GB_ADDR_CONFIG; ++ ++#if defined(LITTLEENDIAN_CPU) ++ ++ typedef struct _GB_TILE_MODE_T { ++ unsigned int micro_tile_mode : 2; ++ unsigned int array_mode : 4; ++ unsigned int pipe_config : 5; ++ unsigned int tile_split : 3; ++ unsigned int bank_width : 2; ++ unsigned int bank_height : 2; ++ unsigned int macro_tile_aspect : 2; ++ unsigned int num_banks : 2; ++ unsigned int micro_tile_mode_new : 3; ++ unsigned int sample_split : 2; ++ unsigned int : 5; ++ } GB_TILE_MODE_T; ++ ++ typedef struct _GB_MACROTILE_MODE_T { ++ unsigned int bank_width : 2; ++ unsigned int bank_height : 2; ++ unsigned int macro_tile_aspect : 2; ++ unsigned int num_banks : 2; ++ unsigned int : 24; ++ } GB_MACROTILE_MODE_T; ++ ++#elif defined(BIGENDIAN_CPU) ++ ++ typedef struct _GB_TILE_MODE_T { ++ unsigned int : 5; ++ unsigned int sample_split : 2; ++ unsigned int micro_tile_mode_new : 3; ++ unsigned int num_banks : 2; ++ unsigned int macro_tile_aspect : 2; ++ unsigned int bank_height : 2; ++ unsigned int bank_width : 2; ++ unsigned int tile_split : 3; ++ unsigned int pipe_config : 5; ++ unsigned int array_mode : 4; ++ unsigned int micro_tile_mode : 2; ++ } GB_TILE_MODE_T; ++ ++ typedef struct _GB_MACROTILE_MODE_T { ++ unsigned int : 24; ++ unsigned int num_banks : 2; ++ unsigned int macro_tile_aspect : 2; ++ unsigned int bank_height : 2; ++ unsigned int bank_width : 2; ++ } GB_MACROTILE_MODE_T; ++ ++#endif ++ ++typedef union { ++ unsigned int val : 32; ++ GB_TILE_MODE_T f; ++} GB_TILE_MODE; ++ ++typedef union { ++ unsigned int val : 32; ++ GB_MACROTILE_MODE_T f; ++} GB_MACROTILE_MODE; ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/inc/lnx_common_defs.h b/src/gallium/winsys/radeon/amdgpu/addrlib/inc/lnx_common_defs.h +new file mode 100644 +index 0000000..61540f4 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/inc/lnx_common_defs.h +@@ -0,0 +1,129 @@ ++/* ++ * 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. ++ */ ++#ifndef _lnx_common_defs_h_ ++#define _lnx_common_defs_h_ ++ ++#if DBG ++#include <stdarg.h> // We do not have any choice: need variable ++ // number of parameters support for debug ++ // build. ++#endif // #if DBG ++ ++// ++// -------------- External functions from Linux kernel driver ---------------- ++// ++// Note: The definitions/declararions below must match the original ones. ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef unsigned long __ke_size_t; // as it is defined in firegl_public.h ++typedef int __kernel_ptrdiff_t; // as it is defined in posix_types.h ++ ++ ++#if !defined(ATI_API_CALL) ++#define ATI_API_CALL __attribute__((regparm(0))) ++#endif ++ ++extern void * ATI_API_CALL __ke_memset(void* s, int c, __ke_size_t count); ++extern void * ATI_API_CALL __ke_memcpy(void* d, const void* s, __ke_size_t count); ++extern ATI_API_CALL __ke_size_t __ke_strlen(const char *s); ++extern char* ATI_API_CALL __ke_strcpy(char* d, const char* s); ++extern char* ATI_API_CALL __ke_strncpy(char* d, const char* s, __ke_size_t count); ++extern void __ke_printk(const char* fmt, ...); ++ ++extern int ATI_API_CALL __ke_snprintf(char* buf, __ke_size_t size, const char* fmt, ...); ++extern int ATI_API_CALL KCL_CopyFromUserSpace(void* to, const void* from, __ke_size_t size); ++extern int ATI_API_CALL KCL_CopyToUserSpace(void* to, const void* from, __ke_size_t size); ++#define __ke_copy_from_user KCL_CopyFromUserSpace ++#define __ke_copy_to_user KCL_CopyToUserSpace ++extern int ATI_API_CALL __ke_verify_area(int type, const void * addr, unsigned long size); ++ ++extern unsigned long ATI_API_CALL KAS_GetTickCounter(void); ++extern unsigned long ATI_API_CALL KAS_GetTicksPerSecond(void); ++ ++ ++#if DBG ++extern int ATI_API_CALL __ke_vsnprintf(char *buf, __ke_size_t size, const char *fmt, va_list ap); ++#define vsnprintf(_dst, _size, _fmt, varg) __ke_snprintf(_dst, _size, _fmt, varg) ++#endif // #if DBG ++ ++ ++// Note: This function is not defined in firegl_public.h. ++void firegl_hardwareHangRecovery(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++// ++// -------------------------- C/C++ standard typedefs ---------------------------- ++// ++#ifdef __SIZE_TYPE__ ++typedef __SIZE_TYPE__ size_t; ++#else // #ifdef __SIZE_TYPE__ ++typedef unsigned int size_t; ++#endif // #ifdef __SIZE_TYPE__ ++ ++#ifdef __PTRDIFF_TYPE__ ++typedef __PTRDIFF_TYPE__ ptrdiff_t; ++#else // #ifdef __PTRDIFF_TYPE__ ++typedef int ptrdiff_t; ++#endif // #ifdef __PTRDIFF_TYPE__ ++ ++#ifndef NULL ++#ifdef __cplusplus ++#define NULL __null ++#else ++#define NULL ((void *)0) ++#endif ++#endif ++ ++ ++// ++// ------------------------- C/C++ standard macros --------------------------- ++// ++ ++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) // as it is defined in stddef.h ++#define CHAR_BIT 8 // as it is defined in limits.h ++ ++// ++// --------------------------------- C RTL ----------------------------------- ++// ++ ++#define memset(_p, _v, _n) __ke_memset(_p, _v, _n) ++#define memcpy(_d, _s, _n) __ke_memcpy(_d, _s, _n) ++#define strlen(_s) __ke_strlen(_s) ++#define strcpy(_d, _s) __ke_strcpy(_d, _s) ++#define strncpy(_d, _s, _n) __ke_strncpy(_d, _s, _n) ++// Note: C99 supports macros with variable number of arguments. GCC also supports this C99 feature as ++// C++ extension. ++#define snprintf(_dst, _size, _fmt, arg...) __ke_snprintf(_dst, _size, _fmt, ##arg) ++ ++ ++#endif // #ifdef _lnx_common_defs_h_ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/chip/si_ci_vi_merged_enum.h b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/chip/si_ci_vi_merged_enum.h +new file mode 100644 +index 0000000..5ed81ad +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/chip/si_ci_vi_merged_enum.h +@@ -0,0 +1,40 @@ ++/* ++ * 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. ++ */ ++#if !defined (SI_CI_VI_MERGED_ENUM_HEADER) ++#define SI_CI_VI_MERGED_ENUM_HEADER ++ ++typedef enum PipeInterleaveSize { ++ADDR_CONFIG_PIPE_INTERLEAVE_256B = 0x00000000, ++ADDR_CONFIG_PIPE_INTERLEAVE_512B = 0x00000001, ++} PipeInterleaveSize; ++ ++typedef enum RowSize { ++ADDR_CONFIG_1KB_ROW = 0x00000000, ++ADDR_CONFIG_2KB_ROW = 0x00000001, ++ADDR_CONFIG_4KB_ROW = 0x00000002, ++} RowSize; ++ ++#endif +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.cpp +new file mode 100644 +index 0000000..264e2ef +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.cpp +@@ -0,0 +1,1777 @@ ++/* ++ * 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 ciaddrlib.cpp ++* @brief Contains the implementation for the CIAddrLib class. ++*************************************************************************************************** ++*/ ++ ++#include "ciaddrlib.h" ++ ++#include "si_gb_reg.h" ++ ++#include "si_ci_vi_merged_enum.h" ++ ++#if BRAHMA_BUILD ++#include "amdgpu_id.h" ++#else ++#include "ci_id.h" ++#include "kv_id.h" ++#include "vi_id.h" ++#endif ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrMask ++* ++* @brief ++* Gets a mask of "width" ++* @return ++* Bit mask ++*************************************************************************************************** ++*/ ++static UINT_64 AddrMask( ++ UINT_32 width) ///< Width of bits ++{ ++ UINT_64 ret; ++ ++ if (width >= sizeof(UINT_64)*8) ++ { ++ ret = ~((UINT_64) 0); ++ } ++ else ++ { ++ return (((UINT_64) 1) << width) - 1; ++ } ++ return ret; ++} ++ ++/** ++*************************************************************************************************** ++* AddrGetBits ++* ++* @brief ++* Gets bits within a range of [msb, lsb] ++* @return ++* Bits of this range ++*************************************************************************************************** ++*/ ++static UINT_64 AddrGetBits( ++ UINT_64 bits, ///< Source bits ++ UINT_32 msb, ///< Most signicant bit ++ UINT_32 lsb) ///< Least signicant bit ++{ ++ UINT_64 ret = 0; ++ ++ if (msb >= lsb) ++ { ++ ret = (bits >> lsb) & (AddrMask(1 + msb - lsb)); ++ } ++ return ret; ++} ++ ++/** ++*************************************************************************************************** ++* AddrRemoveBits ++* ++* @brief ++* Removes bits within the range of [msb, lsb] ++* @return ++* Modified bits ++*************************************************************************************************** ++*/ ++static UINT_64 AddrRemoveBits( ++ UINT_64 bits, ///< Source bits ++ UINT_32 msb, ///< Most signicant bit ++ UINT_32 lsb) ///< Least signicant bit ++{ ++ UINT_64 ret = bits; ++ ++ if (msb >= lsb) ++ { ++ ret = AddrGetBits(bits, lsb - 1, 0) // low bits ++ | (AddrGetBits(bits, 8 * sizeof(bits) - 1, msb + 1) << lsb); //high bits ++ } ++ return ret; ++} ++ ++/** ++*************************************************************************************************** ++* AddrInsertBits ++* ++* @brief ++* Inserts new bits into the range of [msb, lsb] ++* @return ++* Modified bits ++*************************************************************************************************** ++*/ ++static UINT_64 AddrInsertBits( ++ UINT_64 bits, ///< Source bits ++ UINT_64 newBits, ///< New bits to be inserted ++ UINT_32 msb, ///< Most signicant bit ++ UINT_32 lsb) ///< Least signicant bit ++{ ++ UINT_64 ret = bits; ++ ++ if (msb >= lsb) ++ { ++ ret = AddrGetBits(bits, lsb - 1, 0) // old low bitss ++ | (AddrGetBits(newBits, msb - lsb, 0) << lsb) //new bits ++ | (AddrGetBits(bits, 8 * sizeof(bits) - 1, lsb) << (msb + 1)); //old high bits ++ } ++ return ret; ++} ++ ++ ++/** ++*************************************************************************************************** ++* AddrCIHwlInit ++* ++* @brief ++* Creates an CIAddrLib object. ++* ++* @return ++* Returns an CIAddrLib object pointer. ++*************************************************************************************************** ++*/ ++AddrLib* AddrCIHwlInit(const AddrClient* pClient) ++{ ++ return CIAddrLib::CreateObj(pClient); ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::CIAddrLib ++* ++* @brief ++* Constructor ++* ++*************************************************************************************************** ++*/ ++CIAddrLib::CIAddrLib(const AddrClient* pClient) : ++ SIAddrLib(pClient), ++ m_noOfMacroEntries(0), ++ m_allowNonDispThickModes(FALSE) ++{ ++ m_class = CI_ADDRLIB; ++ memset(&m_settings, 0, sizeof(m_settings)); ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::~CIAddrLib ++* ++* @brief ++* Destructor ++*************************************************************************************************** ++*/ ++CIAddrLib::~CIAddrLib() ++{ ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlComputeDccInfo ++* ++* @brief ++* Compute DCC key size, base alignment ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE CIAddrLib::HwlComputeDccInfo( ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ if (m_settings.isVolcanicIslands && IsMacroTiled(pIn->tileMode)) ++ { ++ UINT_64 dccFastClearSize = pIn->colorSurfSize >> 8; ++ ++ ADDR_ASSERT(0 == (pIn->colorSurfSize & 0xff)); ++ ++ if (pIn->numSamples > 1) ++ { ++ UINT_32 tileSizePerSample = BITS_TO_BYTES(pIn->bpp * MicroTileWidth * MicroTileHeight); ++ UINT_32 samplesPerSplit = pIn->tileInfo.tileSplitBytes / tileSizePerSample; ++ ++ if (samplesPerSplit < pIn->numSamples) ++ { ++ UINT_32 numSplits = pIn->numSamples / samplesPerSplit; ++ UINT_32 fastClearBaseAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes; ++ ++ ADDR_ASSERT(IsPow2(fastClearBaseAlign)); ++ ++ dccFastClearSize /= numSplits; ++ ++ if (0 != (dccFastClearSize & (fastClearBaseAlign - 1))) ++ { ++ // Disable dcc fast clear ++ // if key size of fisrt sample split is not pipe*interleave aligned ++ dccFastClearSize = 0; ++ } ++ } ++ } ++ ++ pOut->dccRamSize = pIn->colorSurfSize >> 8; ++ pOut->dccRamBaseAlign = pIn->tileInfo.banks * ++ HwlGetPipes(&pIn->tileInfo) * ++ m_pipeInterleaveBytes; ++ pOut->dccFastClearSize = dccFastClearSize; ++ ++ ADDR_ASSERT(IsPow2(pOut->dccRamBaseAlign)); ++ ++ if (0 == (pOut->dccRamSize & (pOut->dccRamBaseAlign - 1))) ++ { ++ pOut->subLvlCompressible = TRUE; ++ } ++ else ++ { ++ UINT_64 dccRamSizeAlign = HwlGetPipes(&pIn->tileInfo) * m_pipeInterleaveBytes; ++ ++ if (pOut->dccRamSize == pOut->dccFastClearSize) ++ { ++ pOut->dccFastClearSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign); ++ } ++ pOut->dccRamSize = PowTwoAlign(pOut->dccRamSize, dccRamSizeAlign); ++ pOut->subLvlCompressible = FALSE; ++ } ++ } ++ else ++ { ++ returnCode = ADDR_NOTSUPPORTED; ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlComputeCmaskAddrFromCoord ++* ++* @brief ++* Compute tc compatible Cmask address from fmask ram address ++* ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE CIAddrLib::HwlComputeCmaskAddrFromCoord( ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] fmask addr/bpp/tile input ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] cmask address ++ ) const ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_NOTSUPPORTED; ++ ++ if ((m_settings.isVolcanicIslands == TRUE) && ++ (pIn->flags.tcCompatible == TRUE)) ++ { ++ UINT_32 numOfPipes = HwlGetPipes(pIn->pTileInfo); ++ UINT_32 numOfBanks = pIn->pTileInfo->banks; ++ UINT_64 fmaskAddress = pIn->fmaskAddr; ++ UINT_32 elemBits = pIn->bpp; ++ UINT_32 blockByte = 64 * elemBits / 8; ++ UINT_64 metaNibbleAddress = HwlComputeMetadataNibbleAddress(fmaskAddress, ++ 0, ++ 0, ++ 4, ++ elemBits, ++ blockByte, ++ m_pipeInterleaveBytes, ++ numOfPipes, ++ numOfBanks, ++ 1); ++ pOut->addr = (metaNibbleAddress >> 1); ++ pOut->bitPosition = (metaNibbleAddress % 2) ? 4 : 0; ++ returnCode = ADDR_OK; ++ } ++ ++ return returnCode; ++} ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlConvertChipFamily ++* ++* @brief ++* Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision ++* @return ++* AddrChipFamily ++*************************************************************************************************** ++*/ ++AddrChipFamily CIAddrLib::HwlConvertChipFamily( ++ 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_CI; ++ ++ switch (uChipFamily) ++ { ++ case FAMILY_CI: ++ m_settings.isSeaIsland = 1; ++ m_settings.isBonaire = ASICREV_IS_BONAIRE_M(uChipRevision); ++ m_settings.isHawaii = ASICREV_IS_HAWAII_P(uChipRevision); ++ break; ++ case FAMILY_KV: ++ m_settings.isKaveri = 1; ++ m_settings.isSpectre = ASICREV_IS_SPECTRE(uChipRevision); ++ m_settings.isSpooky = ASICREV_IS_SPOOKY(uChipRevision); ++ m_settings.isKalindi = ASICREV_IS_KALINDI(uChipRevision); ++ break; ++ case FAMILY_VI: ++ m_settings.isVolcanicIslands = 1; ++ m_settings.isIceland = ASICREV_IS_ICELAND_M(uChipRevision); ++ m_settings.isTonga = ASICREV_IS_TONGA_P(uChipRevision); ++ break; ++ case FAMILY_CZ: ++ m_settings.isCarrizo = 1; ++ m_settings.isVolcanicIslands = 1; ++ break; ++ default: ++ ADDR_ASSERT(!"This should be a unexpected Fusion"); ++ break; ++ } ++ ++ return family; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlInitGlobalParams ++* ++* @brief ++* Initializes global parameters ++* ++* @return ++* TRUE if all settings are valid ++* ++*************************************************************************************************** ++*/ ++BOOL_32 CIAddrLib::HwlInitGlobalParams( ++ const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input ++{ ++ BOOL_32 valid = TRUE; ++ ++ const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue; ++ ++ valid = DecodeGbRegs(pRegValue); ++ ++ // The following assignments for m_pipes is only for fail-safe, InitTileSettingTable should ++ // read the correct pipes from tile mode table ++ if (m_settings.isHawaii) ++ { ++ // Hawaii has 16-pipe, see GFXIP_Config_Summary.xls ++ m_pipes = 16; ++ } ++ else if (m_settings.isBonaire || m_settings.isSpectre) ++ { ++ m_pipes = 4; ++ } ++ else // Treat other KV asics to be 2-pipe ++ { ++ m_pipes = 2; ++ } ++ ++ // @todo: VI ++ // Move this to VI code path once created ++ if (m_settings.isTonga) ++ { ++ m_pipes = 8; ++ } ++ else if (m_settings.isIceland) ++ { ++ m_pipes = 2; ++ } ++ ++ if (valid) ++ { ++ valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries); ++ } ++ if (valid) ++ { ++ valid = InitMacroTileCfgTable(pRegValue->pMacroTileConfig, pRegValue->noOfMacroEntries); ++ } ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlPostCheckTileIndex ++* ++* @brief ++* Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches ++* tile mode/type/info and change the index if needed ++* @return ++* Tile index. ++*************************************************************************************************** ++*/ ++INT_32 CIAddrLib::HwlPostCheckTileIndex( ++ const ADDR_TILEINFO* pInfo, ///< [in] Tile Info ++ AddrTileMode mode, ///< [in] Tile mode ++ AddrTileType type, ///< [in] Tile type ++ INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo ++ ) const ++{ ++ INT_32 index = curIndex; ++ ++ if (mode == ADDR_TM_LINEAR_GENERAL) ++ { ++ index = TileIndexLinearGeneral; ++ } ++ else ++ { ++ BOOL_32 macroTiled = IsMacroTiled(mode); ++ ++ // We need to find a new index if either of them is true ++ // 1. curIndex is invalid ++ // 2. tile mode is changed ++ // 3. tile info does not match for macro tiled ++ if ((index == TileIndexInvalid) || ++ (mode != m_tileTable[index].mode) || ++ (macroTiled && pInfo->pipeConfig != m_tileTable[index].info.pipeConfig)) ++ { ++ for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++) ++ { ++ if (macroTiled) ++ { ++ // macro tile modes need all to match ++ if ((pInfo->pipeConfig == m_tileTable[index].info.pipeConfig) && ++ (mode == m_tileTable[index].mode) && ++ (type == m_tileTable[index].type)) ++ { ++ // tileSplitBytes stored in m_tileTable is only valid for depth entries ++ if (type == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ if (pInfo->tileSplitBytes == m_tileTable[index].info.tileSplitBytes) ++ { ++ break; ++ } ++ } ++ else // other entries are determined by other 3 fields ++ { ++ break; ++ } ++ } ++ } ++ else if (mode == ADDR_TM_LINEAR_ALIGNED) ++ { ++ // linear mode only needs tile mode to match ++ if (mode == m_tileTable[index].mode) ++ { ++ break; ++ } ++ } ++ else ++ { ++ // micro tile modes only need tile mode and tile type to match ++ if (mode == m_tileTable[index].mode && ++ type == m_tileTable[index].type) ++ { ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries)); ++ ++ if (index >= static_cast<INT_32>(m_noOfEntries)) ++ { ++ index = TileIndexInvalid; ++ } ++ ++ return index; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlSetupTileCfg ++* ++* @brief ++* Map tile index to tile setting. ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE CIAddrLib::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 ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ // Global flag to control usage of tileIndex ++ if (UseTileIndex(index)) ++ { ++ if (static_cast<UINT_32>(index) >= m_noOfEntries) ++ { ++ returnCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index); ++ ++ if (pInfo != NULL) ++ { ++ if (IsMacroTiled(pCfgTable->mode)) ++ { ++ ADDR_ASSERT(((macroModeIndex != TileIndexInvalid) ++ && (macroModeIndex != TileIndexNoMacroIndex))); ++ // Here we used tile_bytes to replace of tile_split ++ // According info as below: ++ // "tile_split_c = MIN(ROW_SIZE, tile_split) ++ // "tile_bytes = MIN(tile_split_c, num_samples * tile_bytes_1x) ++ // when using tile_bytes replacing of tile_split, the result of ++ // alignment and others(such as slicesPerTile) are unaffected - ++ // since if tile_split_c is larger, split won't happen, otherwise ++ // (num_samples * tile_bytes_1x is larger), a correct tile_split is ++ // returned. ++ *pInfo = m_macroTileTable[macroModeIndex]; ++ ++ if (pCfgTable->type == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ pInfo->tileSplitBytes = pCfgTable->info.tileSplitBytes; ++ } ++ pInfo->pipeConfig = pCfgTable->info.pipeConfig; ++ } ++ else // 1D and linear modes, we return default value stored in table ++ { ++ *pInfo = pCfgTable->info; ++ } ++ } ++ ++ if (pMode != NULL) ++ { ++ *pMode = pCfgTable->mode; ++ } ++ ++ if (pType != NULL) ++ { ++ *pType = pCfgTable->type; ++ } ++ } ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlComputeSurfaceInfo ++* ++* @brief ++* Entry of ci's ComputeSurfaceInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE CIAddrLib::HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ // If tileIndex is invalid, force macroModeIndex to be invalid, too ++ if (pIn->tileIndex == TileIndexInvalid) ++ { ++ pOut->macroModeIndex = TileIndexInvalid; ++ } ++ ++ ADDR_E_RETURNCODE retCode = SIAddrLib::HwlComputeSurfaceInfo(pIn,pOut); ++ ++ if (pOut->macroModeIndex == TileIndexNoMacroIndex) ++ { ++ pOut->macroModeIndex = TileIndexInvalid; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlFmaskSurfaceInfo ++* @brief ++* Entry of r800's ComputeFmaskInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE CIAddrLib::HwlComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure ++ ) ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ ADDR_TILEINFO tileInfo = {0}; ++ ADDR_COMPUTE_FMASK_INFO_INPUT fmaskIn; ++ fmaskIn = *pIn; ++ ++ AddrTileMode tileMode = pIn->tileMode; ++ ++ // Use internal tile info if pOut does not have a valid pTileInfo ++ if (pOut->pTileInfo == NULL) ++ { ++ pOut->pTileInfo = &tileInfo; ++ } ++ ++ ADDR_ASSERT(tileMode == ADDR_TM_2D_TILED_THIN1 || ++ tileMode == ADDR_TM_3D_TILED_THIN1 || ++ tileMode == ADDR_TM_PRT_TILED_THIN1 || ++ tileMode == ADDR_TM_PRT_2D_TILED_THIN1 || ++ tileMode == ADDR_TM_PRT_3D_TILED_THIN1); ++ ++ ADDR_ASSERT(m_tileTable[14].mode == ADDR_TM_2D_TILED_THIN1); ++ ADDR_ASSERT(m_tileTable[15].mode == ADDR_TM_3D_TILED_THIN1); ++ ++ // The only valid tile modes for fmask are 2D_THIN1 and 3D_THIN1 plus non-displayable ++ INT_32 tileIndex = tileMode == ADDR_TM_2D_TILED_THIN1 ? 14 : 15; ++ ADDR_SURFACE_FLAGS flags = {{0}}; ++ flags.fmask = 1; ++ ++ INT_32 macroModeIndex = TileIndexInvalid; ++ ++ UINT_32 numSamples = pIn->numSamples; ++ UINT_32 numFrags = pIn->numFrags == 0 ? numSamples : pIn->numFrags; ++ ++ UINT_32 bpp = QLog2(numFrags); ++ ++ // EQAA needs one more bit ++ if (numSamples > numFrags) ++ { ++ bpp++; ++ } ++ ++ if (bpp == 3) ++ { ++ bpp = 4; ++ } ++ ++ bpp = Max(8u, bpp * numSamples); ++ ++ macroModeIndex = HwlComputeMacroModeIndex(tileIndex, flags, bpp, numSamples, pOut->pTileInfo); ++ ++ fmaskIn.tileIndex = tileIndex; ++ fmaskIn.pTileInfo = pOut->pTileInfo; ++ pOut->macroModeIndex = macroModeIndex; ++ pOut->tileIndex = tileIndex; ++ ++ retCode = DispatchComputeFmaskInfo(&fmaskIn, pOut); ++ ++ if (retCode == ADDR_OK) ++ { ++ pOut->tileIndex = ++ HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE, ++ pOut->tileIndex); ++ } ++ ++ // Resets pTileInfo to NULL if the internal tile info is used ++ if (pOut->pTileInfo == &tileInfo) ++ { ++ pOut->pTileInfo = NULL; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlFmaskPreThunkSurfInfo ++* ++* @brief ++* Some preparation before thunking a ComputeSurfaceInfo call for Fmask ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::HwlFmaskPreThunkSurfInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info ++ const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info ++ ) const ++{ ++ pSurfIn->tileIndex = pFmaskIn->tileIndex; ++ pSurfOut->macroModeIndex = pFmaskOut->macroModeIndex; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlFmaskPostThunkSurfInfo ++* ++* @brief ++* Copy hwl extra field after calling thunked ComputeSurfaceInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::HwlFmaskPostThunkSurfInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info ++ ) const ++{ ++ pFmaskOut->tileIndex = pSurfOut->tileIndex; ++ pFmaskOut->macroModeIndex = pSurfOut->macroModeIndex; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlDegradeThickTileMode ++* ++* @brief ++* Degrades valid tile mode for thick modes if needed ++* ++* @return ++* Suitable tile mode ++*************************************************************************************************** ++*/ ++AddrTileMode CIAddrLib::HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, ///< [in] base tile mode ++ UINT_32 numSlices, ///< [in] current number of slices ++ UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice ++ ) const ++{ ++ return baseTileMode; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlOverrideTileMode ++* ++* @brief ++* Override THICK to THIN, for specific formats on CI ++* ++* @return ++* Suitable tile mode ++* ++*************************************************************************************************** ++*/ ++BOOL_32 CIAddrLib::HwlOverrideTileMode( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ AddrTileMode* pTileMode, ///< [in/out] pointer to the tile mode ++ AddrTileType* pTileType ///< [in/out] pointer to the tile type ++ ) const ++{ ++ BOOL_32 bOverrided = FALSE; ++ AddrTileMode tileMode = *pTileMode; ++ ++ // currently, all CI/VI family do not ++ // support ADDR_TM_PRT_2D_TILED_THICK,ADDR_TM_PRT_3D_TILED_THICK and ++ // ADDR_TM_PRT_2D_TILED_THIN1, ADDR_TM_PRT_3D_TILED_THIN1 ++ switch (tileMode) ++ { ++ case ADDR_TM_PRT_2D_TILED_THICK: ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ tileMode = ADDR_TM_PRT_TILED_THICK; ++ break; ++ case ADDR_TM_PRT_2D_TILED_THIN1: ++ case ADDR_TM_PRT_3D_TILED_THIN1: ++ tileMode = ADDR_TM_PRT_TILED_THIN1; ++ break; ++ default: ++ break; ++ } ++ ++ // UBTS#404321, we do not need such overriding, as THICK+THICK entries removed from the tile-mode table ++ if (!m_settings.isBonaire) ++ { ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ ++ // tile_thickness = (array_mode == XTHICK) ? 8 : ((array_mode == THICK) ? 4 : 1) ++ if (thickness > 1) ++ { ++ switch (pIn->format) ++ { ++ // see //gfxip/gcB/devel/cds/src/verif/tc/models/csim/tcp.cpp ++ // tcpError("Thick micro tiling is not supported for format... ++ case ADDR_FMT_X24_8_32_FLOAT: ++ case ADDR_FMT_32_AS_8: ++ case ADDR_FMT_32_AS_8_8: ++ case ADDR_FMT_32_AS_32_32_32_32: ++ ++ // packed formats ++ case ADDR_FMT_GB_GR: ++ case ADDR_FMT_BG_RG: ++ case ADDR_FMT_1_REVERSED: ++ case ADDR_FMT_1: ++ case ADDR_FMT_BC1: ++ case ADDR_FMT_BC2: ++ case ADDR_FMT_BC3: ++ case ADDR_FMT_BC4: ++ case ADDR_FMT_BC5: ++ case ADDR_FMT_BC6: ++ case ADDR_FMT_BC7: ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THICK: ++ tileMode = ADDR_TM_1D_TILED_THIN1; ++ break; ++ ++ case ADDR_TM_2D_TILED_XTHICK: ++ case ADDR_TM_2D_TILED_THICK: ++ tileMode = ADDR_TM_2D_TILED_THIN1; ++ break; ++ ++ case ADDR_TM_3D_TILED_XTHICK: ++ 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; ++ ++ } ++ ++ // Switch tile type from thick to thin ++ if (tileMode != *pTileMode) ++ { ++ // see tileIndex: 13-18 ++ *pTileType = ADDR_NON_DISPLAYABLE; ++ } ++ ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ if (tileMode != *pTileMode) ++ { ++ *pTileMode = tileMode; ++ bOverrided = TRUE; ++ } ++ ++ return bOverrided; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlSetupTileInfo ++* ++* @brief ++* Setup default value of tile info for SI ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::HwlSetupTileInfo( ++ AddrTileMode tileMode, ///< [in] Tile mode ++ ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags ++ UINT_32 bpp, ///< [in] Bits per pixel ++ UINT_32 pitch, ///< [in] Pitch in pixels ++ UINT_32 height, ///< [in] Height in pixels ++ UINT_32 numSamples, ///< [in] Number of samples ++ ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default ++ ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output ++ AddrTileType inTileType, ///< [in] Tile type ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output ++ ) const ++{ ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ ADDR_TILEINFO* pTileInfo = pTileInfoOut; ++ INT index = TileIndexInvalid; ++ INT macroModeIndex = TileIndexInvalid; ++ ++ // Fail-safe code ++ if (!IsLinear(tileMode)) ++ { ++ // Thick tile modes must use thick micro tile mode but Bonaire does not support due to ++ // old derived netlists (UBTS 404321) ++ if (thickness > 1) ++ { ++ if (m_settings.isBonaire) ++ { ++ inTileType = ADDR_NON_DISPLAYABLE; ++ } ++ else if ((m_allowNonDispThickModes == FALSE) || (inTileType != ADDR_NON_DISPLAYABLE)) ++ { ++ inTileType = ADDR_THICK; ++ } ++ } ++ // 128 bpp tiling must be non-displayable. ++ // Fmask reuse color buffer's entry but bank-height field can be from another entry ++ // To simplify the logic, fmask entry should be picked from non-displayable ones ++ else if (bpp == 128 || flags.fmask) ++ { ++ inTileType = ADDR_NON_DISPLAYABLE; ++ } ++ // These two modes only have non-disp entries though they can be other micro tile modes ++ else if (tileMode == ADDR_TM_3D_TILED_THIN1 || tileMode == ADDR_TM_PRT_3D_TILED_THIN1) ++ { ++ inTileType = ADDR_NON_DISPLAYABLE; ++ } ++ ++ if (flags.depth || flags.stencil) ++ { ++ inTileType = ADDR_DEPTH_SAMPLE_ORDER; ++ } ++ } ++ ++ if (IsTileInfoAllZero(pTileInfo)) ++ { ++ // See table entries 0-4 ++ if (flags.depth || flags.stencil) ++ { ++ if (flags.depth && flags.tcCompatible) ++ { ++ // tileSize = bpp * numSamples * 8 * 8 / 8 ++ UINT_32 tileSize = bpp * numSamples * 8; ++ ++ // Texure readable depth surface should not be split ++ switch (tileSize) ++ { ++ case 128: ++ index = 1; ++ break; ++ case 256: ++ index = 2; ++ break; ++ case 512: ++ index = 3; ++ break; ++ default: ++ index = 4; ++ break; ++ } ++ } ++ else ++ { ++ // Depth and stencil need to use the same index, thus the pre-defined tile_split ++ // can meet the requirement to choose the same macro mode index ++ // uncompressed depth/stencil are not supported for now ++ switch (numSamples) ++ { ++ case 1: ++ index = 0; ++ break; ++ case 2: ++ case 4: ++ index = 1; ++ break; ++ case 8: ++ index = 2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ ++ // See table entries 5-6 ++ if (inTileType == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ index = 5; ++ break; ++ case ADDR_TM_PRT_TILED_THIN1: ++ index = 6; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ // See table entries 8-12 ++ if (inTileType == ADDR_DISPLAYABLE) ++ { ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ index = 9; ++ break; ++ case ADDR_TM_2D_TILED_THIN1: ++ index = 10; ++ break; ++ case ADDR_TM_PRT_TILED_THIN1: ++ index = 11; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ // See table entries 13-18 ++ if (inTileType == ADDR_NON_DISPLAYABLE) ++ { ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ index = 13; ++ break; ++ case ADDR_TM_2D_TILED_THIN1: ++ index = 14; ++ break; ++ case ADDR_TM_3D_TILED_THIN1: ++ index = 15; ++ break; ++ case ADDR_TM_PRT_TILED_THIN1: ++ index = 16; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ // See table entries 19-26 ++ if (thickness > 1) ++ { ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THICK: ++ //special check for bonaire, for the compatablity between old KMD and new UMD for bonaire ++ index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 19 : 18; ++ break; ++ case ADDR_TM_2D_TILED_THICK: ++ // special check for bonaire, for the compatablity between old KMD and new UMD for bonaire ++ index = ((inTileType == ADDR_THICK) || m_settings.isBonaire) ? 20 : 24; ++ break; ++ case ADDR_TM_3D_TILED_THICK: ++ index = 21; ++ break; ++ case ADDR_TM_PRT_TILED_THICK: ++ index = 22; ++ break; ++ case ADDR_TM_2D_TILED_XTHICK: ++ index = 25; ++ break; ++ case ADDR_TM_3D_TILED_XTHICK: ++ index = 26; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ // See table entries 27-30 ++ if (inTileType == ADDR_ROTATED) ++ { ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ index = 27; ++ break; ++ case ADDR_TM_2D_TILED_THIN1: ++ index = 28; ++ break; ++ case ADDR_TM_PRT_TILED_THIN1: ++ index = 29; ++ break; ++ case ADDR_TM_PRT_2D_TILED_THIN1: ++ index = 30; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (m_pipes >= 8) ++ { ++ ADDR_ASSERT((index + 1) < static_cast<INT_32>(m_noOfEntries)); ++ // Only do this when tile mode table is updated. ++ if (((tileMode == ADDR_TM_PRT_TILED_THIN1) || (tileMode == ADDR_TM_PRT_TILED_THICK)) && ++ (m_tileTable[index+1].mode == tileMode)) ++ { ++ UINT_32 bytesXSamples = bpp * numSamples / 8; ++ UINT_32 bytesXThickness = bpp * thickness / 8; ++ UINT_32 switchP4Threshold = (m_pipes == 16) ? 8 : 32; ++ ++ if ((bytesXSamples > switchP4Threshold) || (bytesXThickness > switchP4Threshold)) ++ { ++ // Pick next 4 pipe entry ++ index += 1; ++ } ++ } ++ } ++ } ++ else ++ { ++ // A pre-filled tile info is ready ++ index = pOut->tileIndex; ++ macroModeIndex = pOut->macroModeIndex; ++ ++ // pass tile type back for post tile index compute ++ pOut->tileType = inTileType; ++ } ++ ++ // We only need to set up tile info if there is a valid index but macroModeIndex is invalid ++ if (index != TileIndexInvalid && macroModeIndex == TileIndexInvalid) ++ { ++ macroModeIndex = HwlComputeMacroModeIndex(index, flags, bpp, numSamples, pTileInfo); ++ ++ /// Copy to pOut->tileType/tileIndex/macroModeIndex ++ pOut->tileIndex = index; ++ pOut->tileType = m_tileTable[index].type; // Or inTileType, the samea ++ pOut->macroModeIndex = macroModeIndex; ++ } ++ else if (tileMode == ADDR_TM_LINEAR_GENERAL) ++ { ++ pOut->tileIndex = TileIndexLinearGeneral; ++ ++ // Copy linear-aligned entry?? ++ *pTileInfo = m_tileTable[8].info; ++ } ++ else if (tileMode == ADDR_TM_LINEAR_ALIGNED) ++ { ++ pOut->tileIndex = 8; ++ *pTileInfo = m_tileTable[8].info; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::ReadGbTileMode ++* ++* @brief ++* Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG. ++* @return ++* NA. ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::ReadGbTileMode( ++ UINT_32 regValue, ///< [in] GB_TILE_MODE register ++ ADDR_TILECONFIG* pCfg ///< [out] output structure ++ ) const ++{ ++ GB_TILE_MODE gbTileMode; ++ gbTileMode.val = regValue; ++ ++ pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode_new); ++ pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1); ++ ++ if (pCfg->type == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split; ++ } ++ else ++ { ++ pCfg->info.tileSplitBytes = 1 << gbTileMode.f.sample_split; ++ } ++ ++ UINT_32 regArrayMode = gbTileMode.f.array_mode; ++ ++ pCfg->mode = static_cast<AddrTileMode>(regArrayMode); ++ ++ switch (regArrayMode) ++ { ++ case 5: ++ pCfg->mode = ADDR_TM_PRT_TILED_THIN1; ++ break; ++ case 6: ++ pCfg->mode = ADDR_TM_PRT_2D_TILED_THIN1; ++ break; ++ case 8: ++ pCfg->mode = ADDR_TM_2D_TILED_XTHICK; ++ break; ++ case 9: ++ pCfg->mode = ADDR_TM_PRT_TILED_THICK; ++ break; ++ case 0xa: ++ pCfg->mode = ADDR_TM_PRT_2D_TILED_THICK; ++ break; ++ case 0xb: ++ pCfg->mode = ADDR_TM_PRT_3D_TILED_THIN1; ++ break; ++ case 0xe: ++ pCfg->mode = ADDR_TM_3D_TILED_XTHICK; ++ break; ++ case 0xf: ++ pCfg->mode = ADDR_TM_PRT_3D_TILED_THICK; ++ break; ++ default: ++ break; ++ } ++ ++ // Fail-safe code for these always convert tile info, as the non-macro modes ++ // return the entry of tile mode table directly without looking up macro mode table ++ if (!IsMacroTiled(pCfg->mode)) ++ { ++ pCfg->info.banks = 2; ++ pCfg->info.bankWidth = 1; ++ pCfg->info.bankHeight = 1; ++ pCfg->info.macroAspectRatio = 1; ++ pCfg->info.tileSplitBytes = 64; ++ } ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::InitTileSettingTable ++* ++* @brief ++* Initialize the ADDR_TILE_CONFIG table. ++* @return ++* TRUE if tile table is correctly initialized ++*************************************************************************************************** ++*/ ++BOOL_32 CIAddrLib::InitTileSettingTable( ++ const UINT_32* pCfg, ///< [in] Pointer to table of tile configs ++ UINT_32 noOfEntries ///< [in] Numbe of entries in the table above ++ ) ++{ ++ BOOL_32 initOk = TRUE; ++ ++ ADDR_ASSERT(noOfEntries <= TileTableSize); ++ ++ memset(m_tileTable, 0, sizeof(m_tileTable)); ++ ++ if (noOfEntries != 0) ++ { ++ m_noOfEntries = noOfEntries; ++ } ++ else ++ { ++ m_noOfEntries = TileTableSize; ++ } ++ ++ if (pCfg) // From Client ++ { ++ for (UINT_32 i = 0; i < m_noOfEntries; i++) ++ { ++ ReadGbTileMode(*(pCfg + i), &m_tileTable[i]); ++ } ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ initOk = FALSE; ++ } ++ ++ if (initOk) ++ { ++ ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED); ++ ++ if (m_settings.isBonaire == FALSE) ++ { ++ // Check if entry 18 is "thick+thin" combination ++ if ((m_tileTable[18].mode == ADDR_TM_1D_TILED_THICK) && ++ (m_tileTable[18].type == ADDR_NON_DISPLAYABLE)) ++ { ++ m_allowNonDispThickModes = TRUE; ++ ADDR_ASSERT(m_tileTable[24].mode == ADDR_TM_2D_TILED_THICK); ++ } ++ } ++ else ++ { ++ m_allowNonDispThickModes = TRUE; ++ } ++ ++ // Assume the first entry is always programmed with full pipes ++ m_pipes = HwlGetPipes(&m_tileTable[0].info); ++ } ++ ++ return initOk; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::ReadGbMacroTileCfg ++* ++* @brief ++* Convert GB_MACRO_TILE_CFG HW value to ADDR_TILE_CONFIG. ++* @return ++* NA. ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::ReadGbMacroTileCfg( ++ UINT_32 regValue, ///< [in] GB_MACRO_TILE_MODE register ++ ADDR_TILEINFO* pCfg ///< [out] output structure ++ ) const ++{ ++ GB_MACROTILE_MODE gbTileMode; ++ gbTileMode.val = regValue; ++ ++ pCfg->bankHeight = 1 << gbTileMode.f.bank_height; ++ pCfg->bankWidth = 1 << gbTileMode.f.bank_width; ++ pCfg->banks = 1 << (gbTileMode.f.num_banks + 1); ++ pCfg->macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::InitMacroTileCfgTable ++* ++* @brief ++* Initialize the ADDR_MACRO_TILE_CONFIG table. ++* @return ++* TRUE if macro tile table is correctly initialized ++*************************************************************************************************** ++*/ ++BOOL_32 CIAddrLib::InitMacroTileCfgTable( ++ const UINT_32* pCfg, ///< [in] Pointer to table of tile configs ++ UINT_32 noOfMacroEntries ///< [in] Numbe of entries in the table above ++ ) ++{ ++ BOOL_32 initOk = TRUE; ++ ++ ADDR_ASSERT(noOfMacroEntries <= MacroTileTableSize); ++ ++ memset(m_macroTileTable, 0, sizeof(m_macroTileTable)); ++ ++ if (noOfMacroEntries != 0) ++ { ++ m_noOfMacroEntries = noOfMacroEntries; ++ } ++ else ++ { ++ m_noOfMacroEntries = MacroTileTableSize; ++ } ++ ++ if (pCfg) // From Client ++ { ++ for (UINT_32 i = 0; i < m_noOfMacroEntries; i++) ++ { ++ ReadGbMacroTileCfg(*(pCfg + i), &m_macroTileTable[i]); ++ ++ m_macroTileTable[i].tileSplitBytes = 64 << (i % 8); ++ } ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ initOk = FALSE; ++ } ++ return initOk; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlComputeMacroModeIndex ++* ++* @brief ++* Computes macro tile mode index ++* @return ++* TRUE if macro tile table is correctly initialized ++*************************************************************************************************** ++*/ ++INT_32 CIAddrLib::HwlComputeMacroModeIndex( ++ INT_32 tileIndex, ///< [in] Tile mode index ++ ADDR_SURFACE_FLAGS flags, ///< [in] Surface flags ++ UINT_32 bpp, ///< [in] Bit per pixel ++ UINT_32 numSamples, ///< [in] Number of samples ++ ADDR_TILEINFO* pTileInfo, ///< [out] Pointer to ADDR_TILEINFO ++ AddrTileMode* pTileMode, ///< [out] Pointer to AddrTileMode ++ AddrTileType* pTileType ///< [out] Pointer to AddrTileType ++ ) const ++{ ++ INT_32 macroModeIndex = TileIndexInvalid; ++ ++ if (flags.tcCompatible && flags.stencil) ++ { ++ // Don't compute macroModeIndex for tc compatible stencil surface ++ macroModeIndex = TileIndexNoMacroIndex; ++ } ++ else ++ { ++ AddrTileMode tileMode = m_tileTable[tileIndex].mode; ++ AddrTileType tileType = m_tileTable[tileIndex].type; ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ ++ if (!IsMacroTiled(tileMode)) ++ { ++ *pTileInfo = m_tileTable[tileIndex].info; ++ macroModeIndex = TileIndexNoMacroIndex; ++ } ++ else ++ { ++ UINT_32 tileBytes1x = BITS_TO_BYTES(bpp * MicroTilePixels * thickness); ++ UINT_32 tileSplit; ++ ++ if (m_tileTable[tileIndex].type == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ // Depth entries store real tileSplitBytes ++ tileSplit = m_tileTable[tileIndex].info.tileSplitBytes; ++ } ++ else ++ { ++ // Non-depth entries store a split factor ++ UINT_32 sampleSplit = m_tileTable[tileIndex].info.tileSplitBytes; ++ UINT_32 colorTileSplit = Max(256u, sampleSplit * tileBytes1x); ++ ++ tileSplit = colorTileSplit; ++ } ++ ++ UINT_32 tileSplitC = Min(m_rowSize, tileSplit); ++ UINT_32 tileBytes; ++ ++ if (flags.fmask) ++ { ++ tileBytes = Min(tileSplitC, tileBytes1x); ++ } ++ else ++ { ++ tileBytes = Min(tileSplitC, numSamples * tileBytes1x); ++ } ++ ++ if (tileBytes < 64) ++ { ++ tileBytes = 64; ++ } ++ ++ macroModeIndex = Log2(tileBytes / 64); ++ ++ if (flags.prt || IsPrtTileMode(tileMode)) ++ { ++ // Unknown - assume it is 1/2 of table size ++ const UINT_32 PrtMacroModeOffset = MacroTileTableSize / 2; ++ ++ macroModeIndex += PrtMacroModeOffset; ++ *pTileInfo = m_macroTileTable[macroModeIndex]; ++ } ++ else ++ { ++ *pTileInfo = m_macroTileTable[macroModeIndex]; ++ } ++ ++ pTileInfo->pipeConfig = m_tileTable[tileIndex].info.pipeConfig; ++ ++ if (m_tileTable[tileIndex].type != ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ pTileInfo->tileSplitBytes = tileSplitC; ++ } ++ else ++ { ++ pTileInfo->tileSplitBytes = m_tileTable[tileIndex].info.tileSplitBytes; ++ } ++ } ++ ++ if (NULL != pTileMode) ++ { ++ *pTileMode = tileMode; ++ } ++ ++ if (NULL != pTileType) ++ { ++ *pTileType = tileType; ++ } ++ } ++ ++ return macroModeIndex; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::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 CIAddrLib::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(pTileInfo != NULL); ++ ++ UINT_32 numTiles; ++ ++ switch (pTileInfo->pipeConfig) ++ { ++ case ADDR_PIPECFG_P16_32x32_8x16: ++ case ADDR_PIPECFG_P16_32x32_16x16: ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ case ADDR_PIPECFG_P4_32x32: ++ numTiles = 8; ++ break; ++ default: ++ numTiles = 4; ++ break; ++ } ++ ++ *pMacroWidth = numTiles * MicroTileWidth; ++ *pMacroHeight = numTiles * MicroTileHeight; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlStereoCheckRightOffsetPadding ++* ++* @brief ++* check if the height needs extra padding for stereo right eye offset, to avoid swizzling ++* ++* @return ++* TRUE is the extra padding is needed ++* ++* @note ++* Kalindi (Kabini) is the only one that needs this padding as there is a uncertain ++* possible HW issue where the right eye displays incorrectly with some type of swizzles, if ++* the right eye offset is not 64KB aligned - EPR#366461 ++* Other Kaveri APUs also need the padding according to DXX team's report otherwise ++* corruption observed. - EPR#374788 ++*************************************************************************************************** ++*/ ++BOOL_32 CIAddrLib::HwlStereoCheckRightOffsetPadding() const ++{ ++ BOOL_32 bNeedPadding = FALSE; ++ ++ if (m_settings.isKaveri) ++ { ++ bNeedPadding = TRUE; ++ } ++ ++ return bNeedPadding; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlComputeMetadataNibbleAddress ++* ++* @brief ++* calculate meta data address based on input information ++* ++* ¶meter ++* uncompressedDataByteAddress - address of a pixel in color surface ++* dataBaseByteAddress - base address of color surface ++* metadataBaseByteAddress - base address of meta ram ++* metadataBitSize - meta key size, 8 for DCC, 4 for cmask ++* elementBitSize - element size of color surface ++* blockByteSize - compression block size, 256 for DCC ++* pipeInterleaveBytes - pipe interleave size ++* numOfPipes - number of pipes ++* numOfBanks - number of banks ++* numOfSamplesPerSplit - number of samples per tile split ++* @return ++* meta data nibble address (nibble address is used to support DCC compatible cmask) ++* ++*************************************************************************************************** ++*/ ++UINT_64 CIAddrLib::HwlComputeMetadataNibbleAddress( ++ UINT_64 uncompressedDataByteAddress, ++ UINT_64 dataBaseByteAddress, ++ UINT_64 metadataBaseByteAddress, ++ UINT_32 metadataBitSize, ++ UINT_32 elementBitSize, ++ UINT_32 blockByteSize, ++ UINT_32 pipeInterleaveBytes, ++ UINT_32 numOfPipes, ++ UINT_32 numOfBanks, ++ UINT_32 numOfSamplesPerSplit) const ++{ ++ ///-------------------------------------------------------------------------------------------- ++ /// Get pipe interleave, bank and pipe bits ++ ///-------------------------------------------------------------------------------------------- ++ UINT_32 pipeInterleaveBits = Log2(pipeInterleaveBytes); ++ UINT_32 pipeBits = Log2(numOfPipes); ++ UINT_32 bankBits = Log2(numOfBanks); ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Clear pipe and bank swizzles ++ ///-------------------------------------------------------------------------------------------- ++ UINT_32 dataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits; ++ UINT_32 metadataMacrotileBits = pipeInterleaveBits + pipeBits + bankBits; ++ ++ UINT_64 dataMacrotileClearMask = ~((1L << dataMacrotileBits) - 1); ++ UINT_64 metadataMacrotileClearMask = ~((1L << metadataMacrotileBits) - 1); ++ ++ UINT_64 dataBaseByteAddressNoSwizzle = dataBaseByteAddress & dataMacrotileClearMask; ++ UINT_64 metadataBaseByteAddressNoSwizzle = metadataBaseByteAddress & metadataMacrotileClearMask; ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Modify metadata base before adding in so that when final address is divided by data ratio, ++ /// the base address returns to where it should be ++ ///-------------------------------------------------------------------------------------------- ++ ADDR_ASSERT((0 != metadataBitSize)); ++ UINT_64 metadataBaseShifted = metadataBaseByteAddressNoSwizzle * blockByteSize * 8 / ++ metadataBitSize; ++ UINT_64 offset = uncompressedDataByteAddress - ++ dataBaseByteAddressNoSwizzle + ++ metadataBaseShifted; ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Save bank data bits ++ ///-------------------------------------------------------------------------------------------- ++ UINT_32 lsb = pipeBits + pipeInterleaveBits; ++ UINT_32 msb = bankBits - 1 + lsb; ++ ++ UINT_64 bankDataBits = AddrGetBits(offset, msb, lsb); ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Save pipe data bits ++ ///-------------------------------------------------------------------------------------------- ++ lsb = pipeInterleaveBits; ++ msb = pipeBits - 1 + lsb; ++ ++ UINT_64 pipeDataBits = AddrGetBits(offset, msb, lsb); ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Remove pipe and bank bits ++ ///-------------------------------------------------------------------------------------------- ++ lsb = pipeInterleaveBits; ++ msb = dataMacrotileBits - 1; ++ ++ UINT_64 offsetWithoutPipeBankBits = AddrRemoveBits(offset, msb, lsb); ++ ++ ADDR_ASSERT((0 != blockByteSize)); ++ UINT_64 blockInBankpipe = offsetWithoutPipeBankBits / blockByteSize; ++ ++ UINT_32 tileSize = 8 * 8 * elementBitSize/8 * numOfSamplesPerSplit; ++ UINT_32 blocksInTile = tileSize / blockByteSize; ++ ++ if (0 == blocksInTile) ++ { ++ lsb = 0; ++ } ++ else ++ { ++ lsb = Log2(blocksInTile); ++ } ++ msb = bankBits - 1 + lsb; ++ ++ UINT_64 blockInBankpipeWithBankBits = AddrInsertBits(blockInBankpipe, bankDataBits, msb, lsb); ++ ++ /// NOTE *2 because we are converting to Nibble address in this step ++ UINT_64 metaAddressInPipe = blockInBankpipeWithBankBits * 2 * metadataBitSize / 8; ++ ++ ++ ///-------------------------------------------------------------------------------------------- ++ /// Reinsert pipe bits back into the final address ++ ///-------------------------------------------------------------------------------------------- ++ lsb = pipeInterleaveBits + 1; ///<+1 due to Nibble address now gives interleave bits extra lsb. ++ msb = pipeBits - 1 + lsb; ++ UINT_64 metadataAddress = AddrInsertBits(metaAddressInPipe, pipeDataBits, msb, lsb); ++ ++ return metadataAddress; ++} ++ ++/** ++*************************************************************************************************** ++* CIAddrLib::HwlPadDimensions ++* ++* @brief ++* Helper function to pad dimensions ++* ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID CIAddrLib::HwlPadDimensions( ++ 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 ++{ ++ if (m_settings.isVolcanicIslands && ++ flags.dccCompatible && ++ (numSamples > 1) && ++ (mipLevel == 0) && ++ IsMacroTiled(tileMode)) ++ { ++ UINT_32 tileSizePerSample = BITS_TO_BYTES(bpp * MicroTileWidth * MicroTileHeight); ++ UINT_32 samplesPerSplit = pTileInfo->tileSplitBytes / tileSizePerSample; ++ ++ if (samplesPerSplit < numSamples) ++ { ++ UINT_32 dccFastClearByteAlign = HwlGetPipes(pTileInfo) * m_pipeInterleaveBytes * 256; ++ UINT_32 bytesPerSplit = BITS_TO_BYTES((*pPitch) * (*pHeight) * bpp * samplesPerSplit); ++ ++ ADDR_ASSERT(IsPow2(dccFastClearByteAlign)); ++ ++ if (0 != (bytesPerSplit & (dccFastClearByteAlign - 1))) ++ { ++ UINT_32 dccFastClearPixelAlign = dccFastClearByteAlign / ++ BITS_TO_BYTES(bpp) / ++ samplesPerSplit; ++ UINT_32 macroTilePixelAlign = pitchAlign * heightAlign; ++ ++ if ((dccFastClearPixelAlign >= macroTilePixelAlign) && ++ ((dccFastClearPixelAlign % macroTilePixelAlign) == 0)) ++ { ++ UINT_32 dccFastClearPitchAlignInMacroTile = ++ dccFastClearPixelAlign / macroTilePixelAlign; ++ UINT_32 heightInMacroTile = *pHeight / heightAlign; ++ UINT_32 dccFastClearPitchAlignInPixels; ++ ++ while ((heightInMacroTile > 1) && ++ ((heightInMacroTile % 2) == 0) && ++ (dccFastClearPitchAlignInMacroTile > 1) && ++ ((dccFastClearPitchAlignInMacroTile % 2) == 0)) ++ { ++ heightInMacroTile >>= 1; ++ dccFastClearPitchAlignInMacroTile >>= 1; ++ } ++ ++ dccFastClearPitchAlignInPixels = pitchAlign * dccFastClearPitchAlignInMacroTile; ++ ++ if (IsPow2(dccFastClearPitchAlignInPixels)) ++ { ++ *pPitch = PowTwoAlign((*pPitch), dccFastClearPitchAlignInPixels); ++ } ++ else ++ { ++ *pPitch += (dccFastClearPitchAlignInPixels - 1); ++ *pPitch /= dccFastClearPitchAlignInPixels; ++ *pPitch *= dccFastClearPitchAlignInPixels; ++ } ++ } ++ } ++ } ++ } ++} ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.h b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.h +new file mode 100644 +index 0000000..0220736 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/ciaddrlib.h +@@ -0,0 +1,197 @@ ++/* ++ * 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 ciaddrlib.h ++* @brief Contains the CIAddrLib class definition. ++*************************************************************************************************** ++*/ ++ ++#ifndef __CI_ADDR_LIB_H__ ++#define __CI_ADDR_LIB_H__ ++ ++#include "addrlib.h" ++#include "siaddrlib.h" ++ ++/** ++*************************************************************************************************** ++* @brief CI specific settings structure. ++*************************************************************************************************** ++*/ ++struct CIChipSettings ++{ ++ struct ++ { ++ UINT_32 isSeaIsland : 1; ++ UINT_32 isBonaire : 1; ++ UINT_32 isKaveri : 1; ++ UINT_32 isSpectre : 1; ++ UINT_32 isSpooky : 1; ++ UINT_32 isKalindi : 1; ++ // Hawaii is GFXIP 7.2, similar with CI (Bonaire) ++ UINT_32 isHawaii : 1; ++ ++ // VI ++ UINT_32 isVolcanicIslands : 1; ++ UINT_32 isIceland : 1; ++ UINT_32 isTonga : 1; ++ // VI fusion (Carrizo) ++ UINT_32 isCarrizo : 1; ++ }; ++}; ++ ++/** ++*************************************************************************************************** ++* @brief This class is the CI specific address library ++* function set. ++*************************************************************************************************** ++*/ ++class CIAddrLib : public SIAddrLib ++{ ++public: ++ /// Creates CIAddrLib object ++ static AddrLib* CreateObj(const AddrClient* pClient) ++ { ++ return new(pClient) CIAddrLib(pClient); ++ } ++ ++private: ++ CIAddrLib(const AddrClient* pClient); ++ virtual ~CIAddrLib(); ++ ++protected: ++ ++ // Hwl interface - defined in AddrLib ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); ++ ++ virtual AddrChipFamily HwlConvertChipFamily( ++ UINT_32 uChipFamily, UINT_32 uChipRevision); ++ ++ virtual BOOL_32 HwlInitGlobalParams( ++ const ADDR_CREATE_INPUT* pCreateIn); ++ ++ virtual ADDR_E_RETURNCODE HwlSetupTileCfg( ++ INT_32 index, INT_32 macroModeIndex, ADDR_TILEINFO* pInfo, ++ AddrTileMode* pMode = 0, AddrTileType* pType = 0) const; ++ ++ virtual VOID HwlComputeTileDataWidthAndHeightLinear( ++ UINT_32* pMacroWidth, UINT_32* pMacroHeight, ++ UINT_32 bpp, ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual INT_32 HwlComputeMacroModeIndex( ++ INT_32 tileIndex, ADDR_SURFACE_FLAGS flags, UINT_32 bpp, UINT_32 numSamples, ++ ADDR_TILEINFO* pTileInfo, AddrTileMode* pTileMode = NULL, AddrTileType* pTileType = NULL ++ ) const; ++ ++ // Sub-hwl interface - defined in EgBasedAddrLib ++ virtual VOID HwlSetupTileInfo( ++ AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, ++ AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual INT_32 HwlPostCheckTileIndex( ++ const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, ++ INT curIndex = TileIndexInvalid) const; ++ ++ virtual VOID HwlFmaskPreThunkSurfInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ++ const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const; ++ ++ virtual VOID HwlFmaskPostThunkSurfInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const; ++ ++ virtual AddrTileMode HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; ++ ++ virtual BOOL_32 HwlOverrideTileMode( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ AddrTileMode* pTileMode, ++ AddrTileType* pTileType) const; ++ ++ virtual BOOL_32 HwlStereoCheckRightOffsetPadding() const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeDccInfo( ++ const ADDR_COMPUTE_DCCINFO_INPUT* pIn, ++ ADDR_COMPUTE_DCCINFO_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeCmaskAddrFromCoord( ++ const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++protected: ++ virtual VOID HwlPadDimensions( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, ++ UINT_32 numSamples, ADDR_TILEINFO* pTileInfo, UINT_32 padDims, UINT_32 mipLevel, ++ UINT_32* pPitch, UINT_32 pitchAlign, UINT_32* pHeight, UINT_32 heightAlign, ++ UINT_32* pSlices, UINT_32 sliceAlign) const; ++ ++private: ++ VOID ReadGbTileMode( ++ UINT_32 regValue, ADDR_TILECONFIG* pCfg) const; ++ ++ VOID ReadGbMacroTileCfg( ++ UINT_32 regValue, ADDR_TILEINFO* pCfg) const; ++ ++ BOOL_32 InitTileSettingTable( ++ const UINT_32 *pSetting, UINT_32 noOfEntries); ++ ++ BOOL_32 InitMacroTileCfgTable( ++ const UINT_32 *pSetting, UINT_32 noOfEntries); ++ ++ UINT_64 HwlComputeMetadataNibbleAddress( ++ UINT_64 uncompressedDataByteAddress, ++ UINT_64 dataBaseByteAddress, ++ UINT_64 metadataBaseByteAddress, ++ UINT_32 metadataBitSize, ++ UINT_32 elementBitSize, ++ UINT_32 blockByteSize, ++ UINT_32 pipeInterleaveBytes, ++ UINT_32 numOfPipes, ++ UINT_32 numOfBanks, ++ UINT_32 numOfSamplesPerSplit) const; ++ ++ static const UINT_32 MacroTileTableSize = 16; ++ ADDR_TILEINFO m_macroTileTable[MacroTileTableSize]; ++ UINT_32 m_noOfMacroEntries; ++ BOOL_32 m_allowNonDispThickModes; ++ ++ CIChipSettings m_settings; ++}; ++ ++#endif ++ ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.cpp +new file mode 100644 +index 0000000..2e16cb3 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.cpp +@@ -0,0 +1,4578 @@ ++/* ++ * 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 egbaddrlib.cpp ++* @brief Contains the EgBasedAddrLib class implementation ++*************************************************************************************************** ++*/ ++ ++#include "egbaddrlib.h" ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::EgBasedAddrLib ++* ++* @brief ++* Constructor ++* ++* @note ++* ++*************************************************************************************************** ++*/ ++EgBasedAddrLib::EgBasedAddrLib(const AddrClient* pClient) : ++ AddrLib(pClient), ++ m_ranks(0), ++ m_logicalBanks(0), ++ m_bankInterleave(1) ++{ ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::~EgBasedAddrLib ++* ++* @brief ++* Destructor ++*************************************************************************************************** ++*/ ++EgBasedAddrLib::~EgBasedAddrLib() ++{ ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeSurfaceInfo ++* ++* @brief ++* Compute surface sizes include padded pitch,height,slices,total size in bytes, ++* meanwhile output suitable tile mode and base alignment might be changed in this ++* call as well. Results are returned through output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::DispatchComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ AddrTileMode tileMode = pIn->tileMode; ++ UINT_32 bpp = pIn->bpp; ++ UINT_32 numSamples = pIn->numSamples; ++ UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); ++ UINT_32 pitch = pIn->width; ++ UINT_32 height = pIn->height; ++ UINT_32 numSlices = pIn->numSlices; ++ UINT_32 mipLevel = pIn->mipLevel; ++ ADDR_SURFACE_FLAGS flags = pIn->flags; ++ ++ ADDR_TILEINFO tileInfoDef = {0}; ++ ADDR_TILEINFO* pTileInfo = &tileInfoDef; ++ ++ UINT_32 padDims = 0; ++ BOOL_32 valid; ++ ++ tileMode = DegradeLargeThickTile(tileMode, bpp); ++ ++ // Only override numSamples for NI above ++ if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) ++ { ++ if (numFrags != numSamples) // This means EQAA ++ { ++ // The real surface size needed is determined by number of fragments ++ numSamples = numFrags; ++ } ++ ++ // Save altered numSamples in pOut ++ pOut->numSamples = numSamples; ++ } ++ ++ // Caller makes sure pOut->pTileInfo is not NULL, see HwlComputeSurfaceInfo ++ ADDR_ASSERT(pOut->pTileInfo); ++ ++ if (pOut->pTileInfo != NULL) ++ { ++ pTileInfo = pOut->pTileInfo; ++ } ++ ++ // Set default values ++ if (pIn->pTileInfo != NULL) ++ { ++ if (pTileInfo != pIn->pTileInfo) ++ { ++ *pTileInfo = *pIn->pTileInfo; ++ } ++ } ++ else ++ { ++ memset(pTileInfo, 0, sizeof(ADDR_TILEINFO)); ++ } ++ ++ // For macro tile mode, we should calculate default tiling parameters ++ HwlSetupTileInfo(tileMode, ++ flags, ++ bpp, ++ pitch, ++ height, ++ numSamples, ++ pIn->pTileInfo, ++ pTileInfo, ++ pIn->tileType, ++ pOut); ++ ++ if (flags.cube) ++ { ++ if (mipLevel == 0) ++ { ++ padDims = 2; ++ } ++ ++ if (numSlices == 1) ++ { ++ // This is calculating one face, remove cube flag ++ flags.cube = 0; ++ } ++ } ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_LINEAR_GENERAL://fall through ++ case ADDR_TM_LINEAR_ALIGNED: ++ valid = ComputeSurfaceInfoLinear(pIn, pOut, padDims); ++ break; ++ ++ case ADDR_TM_1D_TILED_THIN1://fall through ++ case ADDR_TM_1D_TILED_THICK: ++ valid = ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, tileMode); ++ break; ++ ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_2D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THICK: //fall through ++ case ADDR_TM_2D_TILED_XTHICK: //fall through ++ case ADDR_TM_3D_TILED_XTHICK: //fall through ++ case ADDR_TM_PRT_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_2D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_3D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_TILED_THICK: //fall through ++ case ADDR_TM_PRT_2D_TILED_THICK://fall through ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ valid = ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, tileMode); ++ break; ++ ++ default: ++ valid = FALSE; ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceInfoLinear ++* ++* @brief ++* Compute linear surface sizes include padded pitch, height, slices, total size in ++* bytes, meanwhile alignments as well. Since it is linear mode, so output tile mode ++* will not be changed here. Results are returned through output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoLinear( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure ++ UINT_32 padDims ///< [in] Dimensions to padd ++ ) const ++{ ++ UINT_32 expPitch = pIn->width; ++ UINT_32 expHeight = pIn->height; ++ UINT_32 expNumSlices = pIn->numSlices; ++ ++ // No linear MSAA on real H/W, keep this for TGL ++ UINT_32 numSamples = pOut->numSamples; ++ ++ const UINT_32 microTileThickness = 1; ++ ++ // ++ // Compute the surface alignments. ++ // ++ ComputeSurfaceAlignmentsLinear(pIn->tileMode, ++ pIn->bpp, ++ pIn->flags, ++ &pOut->baseAlign, ++ &pOut->pitchAlign, ++ &pOut->heightAlign); ++ ++ if ((pIn->tileMode == ADDR_TM_LINEAR_GENERAL) && pIn->flags.color && (pIn->height > 1)) ++ { ++#if !ALT_TEST ++ // When linear_general surface is accessed in multiple lines, it requires 8 pixels in pitch ++ // alignment since PITCH_TILE_MAX is in unit of 8 pixels. ++ // It is OK if it is accessed per line. ++ ADDR_ASSERT((pIn->width % 8) == 0); ++#endif ++ } ++ ++ pOut->depthAlign = microTileThickness; ++ ++ expPitch = HwlPreHandleBaseLvl3xPitch(pIn, expPitch); ++ ++ // ++ // Pad pitch and height to the required granularities. ++ // ++ PadDimensions(pIn->tileMode, ++ pIn->bpp, ++ pIn->flags, ++ numSamples, ++ pOut->pTileInfo, ++ padDims, ++ pIn->mipLevel, ++ &expPitch, pOut->pitchAlign, ++ &expHeight, pOut->heightAlign, ++ &expNumSlices, microTileThickness); ++ ++ expPitch = HwlPostHandleBaseLvl3xPitch(pIn, expPitch); ++ ++ // ++ // Adjust per HWL ++ // ++ ++ UINT_64 logicalSliceSize; ++ ++ logicalSliceSize = HwlGetSizeAdjustmentLinear(pIn->tileMode, ++ pIn->bpp, ++ numSamples, ++ pOut->baseAlign, ++ pOut->pitchAlign, ++ &expPitch, ++ &expHeight, ++ &pOut->heightAlign); ++ ++ ++ pOut->pitch = expPitch; ++ pOut->height = expHeight; ++ pOut->depth = expNumSlices; ++ ++ pOut->surfSize = logicalSliceSize * expNumSlices; ++ ++ pOut->tileMode = pIn->tileMode; ++ ++ return TRUE; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceInfoMicroTiled ++* ++* @brief ++* Compute 1D/Micro Tiled surface sizes include padded pitch, height, slices, total ++* size in bytes, meanwhile alignments as well. Results are returned through output ++* parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMicroTiled( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure ++ UINT_32 padDims, ///< [in] Dimensions to padd ++ AddrTileMode expTileMode ///< [in] Expected tile mode ++ ) const ++{ ++ BOOL_32 valid = TRUE; ++ ++ UINT_32 microTileThickness; ++ UINT_32 expPitch = pIn->width; ++ UINT_32 expHeight = pIn->height; ++ UINT_32 expNumSlices = pIn->numSlices; ++ ++ // No 1D MSAA on real H/W, keep this for TGL ++ UINT_32 numSamples = pOut->numSamples; ++ ++ // ++ // Compute the micro tile thickness. ++ // ++ microTileThickness = ComputeSurfaceThickness(expTileMode); ++ ++ // ++ // Extra override for mip levels ++ // ++ if (pIn->mipLevel > 0) ++ { ++ // ++ // Reduce tiling mode from thick to thin if the number of slices is less than the ++ // micro tile thickness. ++ // ++ if ((expTileMode == ADDR_TM_1D_TILED_THICK) && ++ (expNumSlices < ThickTileThickness)) ++ { ++ expTileMode = HwlDegradeThickTileMode(ADDR_TM_1D_TILED_THICK, expNumSlices, NULL); ++ if (expTileMode != ADDR_TM_1D_TILED_THICK) ++ { ++ microTileThickness = 1; ++ } ++ } ++ } ++ ++ // ++ // Compute the surface restrictions. ++ // ++ ComputeSurfaceAlignmentsMicroTiled(expTileMode, ++ pIn->bpp, ++ pIn->flags, ++ numSamples, ++ &pOut->baseAlign, ++ &pOut->pitchAlign, ++ &pOut->heightAlign); ++ ++ pOut->depthAlign = microTileThickness; ++ ++ // ++ // Pad pitch and height to the required granularities. ++ // Compute surface size. ++ // Return parameters. ++ // ++ PadDimensions(expTileMode, ++ pIn->bpp, ++ pIn->flags, ++ numSamples, ++ pOut->pTileInfo, ++ padDims, ++ pIn->mipLevel, ++ &expPitch, pOut->pitchAlign, ++ &expHeight, pOut->heightAlign, ++ &expNumSlices, microTileThickness); ++ ++ // ++ // Get HWL specific pitch adjustment ++ // ++ UINT_64 logicalSliceSize = HwlGetSizeAdjustmentMicroTiled(microTileThickness, ++ pIn->bpp, ++ pIn->flags, ++ numSamples, ++ pOut->baseAlign, ++ pOut->pitchAlign, ++ &expPitch, ++ &expHeight); ++ ++ ++ pOut->pitch = expPitch; ++ pOut->height = expHeight; ++ pOut->depth = expNumSlices; ++ ++ pOut->surfSize = logicalSliceSize * expNumSlices; ++ ++ pOut->tileMode = expTileMode; ++ ++ return valid; ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceInfoMacroTiled ++* ++* @brief ++* Compute 2D/macro tiled surface sizes include padded pitch, height, slices, total ++* size in bytes, meanwhile output suitable tile mode and alignments might be changed ++* in this call as well. Results are returned through output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMacroTiled( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure ++ UINT_32 padDims, ///< [in] Dimensions to padd ++ AddrTileMode expTileMode ///< [in] Expected tile mode ++ ) const ++{ ++ BOOL_32 valid = TRUE; ++ ++ AddrTileMode origTileMode = expTileMode; ++ UINT_32 microTileThickness; ++ ++ UINT_32 paddedPitch; ++ UINT_32 paddedHeight; ++ UINT_64 bytesPerSlice; ++ ++ UINT_32 expPitch = pIn->width; ++ UINT_32 expHeight = pIn->height; ++ UINT_32 expNumSlices = pIn->numSlices; ++ ++ UINT_32 numSamples = pOut->numSamples; ++ ++ // ++ // Compute the surface restrictions as base ++ // SanityCheckMacroTiled is called in ComputeSurfaceAlignmentsMacroTiled ++ // ++ valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode, ++ pIn->bpp, ++ pIn->flags, ++ pIn->mipLevel, ++ numSamples, ++ pOut->pTileInfo, ++ &pOut->baseAlign, ++ &pOut->pitchAlign, ++ &pOut->heightAlign); ++ ++ if (valid) ++ { ++ // ++ // Compute the micro tile thickness. ++ // ++ microTileThickness = ComputeSurfaceThickness(expTileMode); ++ ++ // ++ // Find the correct tiling mode for mip levels ++ // ++ if (pIn->mipLevel > 0) ++ { ++ // ++ // Try valid tile mode ++ // ++ expTileMode = ComputeSurfaceMipLevelTileMode(expTileMode, ++ pIn->bpp, ++ expPitch, ++ expHeight, ++ expNumSlices, ++ numSamples, ++ pOut->pitchAlign, ++ pOut->heightAlign, ++ pOut->pTileInfo); ++ ++ if (!IsMacroTiled(expTileMode)) // Downgraded to micro-tiled ++ { ++ return ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, expTileMode); ++ } ++ else ++ { ++ if (microTileThickness != ComputeSurfaceThickness(expTileMode)) ++ { ++ // ++ // Re-compute if thickness changed since bank-height may be changed! ++ // ++ return ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, expTileMode); ++ } ++ } ++ } ++ ++ paddedPitch = expPitch; ++ paddedHeight = expHeight; ++ ++ // ++ // Re-cal alignment ++ // ++ if (expTileMode != origTileMode) // Tile mode is changed but still macro-tiled ++ { ++ valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode, ++ pIn->bpp, ++ pIn->flags, ++ pIn->mipLevel, ++ numSamples, ++ pOut->pTileInfo, ++ &pOut->baseAlign, ++ &pOut->pitchAlign, ++ &pOut->heightAlign); ++ } ++ ++ // ++ // Do padding ++ // ++ PadDimensions(expTileMode, ++ pIn->bpp, ++ pIn->flags, ++ numSamples, ++ pOut->pTileInfo, ++ padDims, ++ pIn->mipLevel, ++ &paddedPitch, pOut->pitchAlign, ++ &paddedHeight, pOut->heightAlign, ++ &expNumSlices, microTileThickness); ++ ++ if (pIn->flags.qbStereo && ++ (pOut->pStereoInfo != NULL) && ++ HwlStereoCheckRightOffsetPadding()) ++ { ++ // Eye height's bank bits are different from y == 0? ++ // Since 3D rendering treats right eye buffer starting from y == "eye height" while ++ // display engine treats it to be 0, so the bank bits may be different, we pad ++ // more in height to make sure y == "eye height" has the same bank bits as y == 0. ++ UINT_32 checkMask = pOut->pTileInfo->banks - 1; ++ UINT_32 bankBits = 0; ++ do ++ { ++ bankBits = (paddedHeight / 8 / pOut->pTileInfo->bankHeight) & checkMask; ++ ++ if (bankBits) ++ { ++ paddedHeight += pOut->heightAlign; ++ } ++ } while (bankBits); ++ } ++ ++ // ++ // Compute the size of a slice. ++ // ++ bytesPerSlice = BITS_TO_BYTES(static_cast<UINT_64>(paddedPitch) * ++ paddedHeight * NextPow2(pIn->bpp) * numSamples); ++ ++ pOut->pitch = paddedPitch; ++ // Put this check right here to workaround special mipmap cases which the original height ++ // is needed. ++ // The original height is pre-stored in pOut->height in PostComputeMipLevel and ++ // pOut->pitch is needed in HwlCheckLastMacroTiledLvl, too. ++ if (m_configFlags.checkLast2DLevel && numSamples == 1) // Don't check MSAA ++ { ++ // Set a TRUE in pOut if next Level is the first 1D sub level ++ HwlCheckLastMacroTiledLvl(pIn, pOut); ++ } ++ pOut->height = paddedHeight; ++ ++ pOut->depth = expNumSlices; ++ ++ pOut->surfSize = bytesPerSlice * expNumSlices; ++ ++ pOut->tileMode = expTileMode; ++ ++ pOut->depthAlign = microTileThickness; ++ ++ } // if (valid) ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceAlignmentsLinear ++* ++* @brief ++* Compute linear surface alignment, calculation results are returned through ++* output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsLinear( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags, ///< [in] surface flags ++ UINT_32* pBaseAlign, ///< [out] base address alignment in bytes ++ UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels ++ UINT_32* pHeightAlign ///< [out] height alignment in pixels ++ ) const ++{ ++ BOOL_32 valid = TRUE; ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_LINEAR_GENERAL: ++ // ++ // The required base alignment and pitch and height granularities is to 1 element. ++ // ++ *pBaseAlign = (bpp > 8) ? bpp / 8 : 1; ++ *pPitchAlign = 1; ++ *pHeightAlign = 1; ++ break; ++ case ADDR_TM_LINEAR_ALIGNED: ++ // ++ // The required alignment for base is the pipe interleave size. ++ // The required granularity for pitch is hwl dependent. ++ // The required granularity for height is one row. ++ // ++ *pBaseAlign = m_pipeInterleaveBytes; ++ *pPitchAlign = HwlGetPitchAlignmentLinear(bpp, flags); ++ *pHeightAlign = 1; ++ break; ++ default: ++ *pBaseAlign = 1; ++ *pPitchAlign = 1; ++ *pHeightAlign = 1; ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ AdjustPitchAlignment(flags, pPitchAlign); ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled ++* ++* @brief ++* Compute 1D tiled surface alignment, calculation results are returned through ++* output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled( ++ 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 ++ UINT_32* pBaseAlign, ///< [out] base address alignment in bytes ++ UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels ++ UINT_32* pHeightAlign ///< [out] height alignment in pixels ++ ) const ++{ ++ BOOL_32 valid = TRUE; ++ ++ // ++ // The required alignment for base is the pipe interleave size. ++ // ++ *pBaseAlign = m_pipeInterleaveBytes; ++ ++ *pPitchAlign = HwlGetPitchAlignmentMicroTiled(tileMode, bpp, flags, numSamples); ++ ++ *pHeightAlign = MicroTileHeight; ++ ++ AdjustPitchAlignment(flags, pPitchAlign); ++ ++ // ECR#393489 ++ // Workaround 2 for 1D tiling - There is HW bug for Carrizo ++ // where it requires the following alignments for 1D tiling. ++ if (flags.czDispCompatible) ++ { ++ *pBaseAlign = PowTwoAlign(*pBaseAlign, 4096); //Base address MOD 4096 = 0 ++ *pPitchAlign = PowTwoAlign(*pPitchAlign, 512 >> (BITS_TO_BYTES(bpp))); //(8 lines * pitch * bytes per pixel) MOD 4096 = 0 ++ } ++ // end Carrizo workaround for 1D tilling ++ ++ return valid; ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlReduceBankWidthHeight ++* ++* @brief ++* Additional checks, reduce bankHeight/bankWidth if needed and possible ++* tileSize*BANK_WIDTH*BANK_HEIGHT <= ROW_SIZE ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::HwlReduceBankWidthHeight( ++ UINT_32 tileSize, ///< [in] tile size ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags, ///< [in] surface flags ++ UINT_32 numSamples, ///< [in] number of samples ++ UINT_32 bankHeightAlign, ///< [in] bank height alignment ++ UINT_32 pipes, ///< [in] pipes ++ ADDR_TILEINFO* pTileInfo ///< [in/out] bank structure. ++ ) const ++{ ++ UINT_32 macroAspectAlign; ++ BOOL_32 valid = TRUE; ++ ++ if (tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize) ++ { ++ BOOL_32 stillGreater = TRUE; ++ ++ // Try reducing bankWidth first ++ if (stillGreater && pTileInfo->bankWidth > 1) ++ { ++ while (stillGreater && pTileInfo->bankWidth > 0) ++ { ++ pTileInfo->bankWidth >>= 1; ++ ++ if (pTileInfo->bankWidth == 0) ++ { ++ pTileInfo->bankWidth = 1; ++ break; ++ } ++ ++ stillGreater = ++ tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize; ++ } ++ ++ // bankWidth is reduced above, so we need to recalculate bankHeight and ratio ++ bankHeightAlign = Max(1u, ++ m_pipeInterleaveBytes * m_bankInterleave / ++ (tileSize * pTileInfo->bankWidth) ++ ); ++ ++ // We cannot increase bankHeight so just assert this case. ++ ADDR_ASSERT((pTileInfo->bankHeight % bankHeightAlign) == 0); ++ ++ if (numSamples == 1) ++ { ++ macroAspectAlign = Max(1u, ++ m_pipeInterleaveBytes * m_bankInterleave / ++ (tileSize * pipes * pTileInfo->bankWidth) ++ ); ++ pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, ++ macroAspectAlign); ++ } ++ } ++ ++ // Early quit bank_height degradation for "64" bit z buffer ++ if (flags.depth && bpp >= 64) ++ { ++ stillGreater = FALSE; ++ } ++ ++ // Then try reducing bankHeight ++ if (stillGreater && pTileInfo->bankHeight > bankHeightAlign) ++ { ++ while (stillGreater && pTileInfo->bankHeight > bankHeightAlign) ++ { ++ pTileInfo->bankHeight >>= 1; ++ ++ if (pTileInfo->bankHeight < bankHeightAlign) ++ { ++ pTileInfo->bankHeight = bankHeightAlign; ++ break; ++ } ++ ++ stillGreater = ++ tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize; ++ } ++ } ++ ++ valid = !stillGreater; ++ ++ // Generate a warning if we still fail to meet this constraint ++ if (!valid) ++ { ++ ADDR_WARN( ++ 0, ("TILE_SIZE(%d)*BANK_WIDTH(%d)*BANK_HEIGHT(%d) <= ROW_SIZE(%d)", ++ tileSize, pTileInfo->bankWidth, pTileInfo->bankHeight, m_rowSize)); ++ } ++ } ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled ++* ++* @brief ++* Compute 2D tiled surface alignment, calculation results are returned through ++* output parameters. ++* ++* @return ++* TRUE if no error occurs ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags, ///< [in] surface flags ++ UINT_32 mipLevel, ///< [in] mip level ++ UINT_32 numSamples, ///< [in] number of samples ++ ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure. ++ UINT_32* pBaseAlign, ///< [out] base address alignment in bytes ++ UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels ++ UINT_32* pHeightAlign ///< [out] height alignment in pixels ++ ) const ++{ ++ BOOL_32 valid = SanityCheckMacroTiled(pTileInfo); ++ ++ if (valid) ++ { ++ UINT_32 macroTileWidth; ++ UINT_32 macroTileHeight; ++ ++ UINT_32 tileSize; ++ UINT_32 bankHeightAlign; ++ UINT_32 macroAspectAlign; ++ ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ UINT_32 pipes = HwlGetPipes(pTileInfo); ++ ++ // ++ // Align bank height first according to latest h/w spec ++ // ++ ++ // tile_size = MIN(tile_split, 64 * tile_thickness * element_bytes * num_samples) ++ tileSize = Min(pTileInfo->tileSplitBytes, ++ BITS_TO_BYTES(64 * thickness * bpp * numSamples)); ++ ++ // bank_height_align = ++ // MAX(1, (pipe_interleave_bytes * bank_interleave)/(tile_size*bank_width)) ++ bankHeightAlign = Max(1u, ++ m_pipeInterleaveBytes * m_bankInterleave / ++ (tileSize * pTileInfo->bankWidth) ++ ); ++ ++ pTileInfo->bankHeight = PowTwoAlign(pTileInfo->bankHeight, bankHeightAlign); ++ ++ // num_pipes * bank_width * macro_tile_aspect >= ++ // (pipe_interleave_size * bank_interleave) / tile_size ++ if (numSamples == 1) ++ { ++ // this restriction is only for mipmap (mipmap's numSamples must be 1) ++ macroAspectAlign = Max(1u, ++ m_pipeInterleaveBytes * m_bankInterleave / ++ (tileSize * pipes * pTileInfo->bankWidth) ++ ); ++ pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, macroAspectAlign); ++ } ++ ++ valid = HwlReduceBankWidthHeight(tileSize, ++ bpp, ++ flags, ++ numSamples, ++ bankHeightAlign, ++ pipes, ++ pTileInfo); ++ ++ // ++ // The required granularity for pitch is the macro tile width. ++ // ++ macroTileWidth = MicroTileWidth * pTileInfo->bankWidth * pipes * ++ pTileInfo->macroAspectRatio; ++ ++ *pPitchAlign = macroTileWidth; ++ ++ AdjustPitchAlignment(flags, pPitchAlign); ++ ++ // ++ // The required granularity for height is the macro tile height. ++ // ++ macroTileHeight = MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks / ++ pTileInfo->macroAspectRatio; ++ ++ *pHeightAlign = macroTileHeight; ++ ++ // ++ // Compute base alignment ++ // ++ *pBaseAlign = pipes * ++ pTileInfo->bankWidth * pTileInfo->banks * pTileInfo->bankHeight * tileSize; ++ ++ if ((mipLevel == 0) && (flags.prt) && (m_chipFamily == ADDR_CHIP_FAMILY_SI)) ++ { ++ static const UINT_32 PrtTileSize = 0x10000; ++ ++ UINT_32 macroTileSize = macroTileWidth * macroTileHeight * numSamples * bpp / 8; ++ ++ if (macroTileSize < PrtTileSize) ++ { ++ UINT_32 numMacroTiles = PrtTileSize / macroTileSize; ++ ++ ADDR_ASSERT((PrtTileSize % macroTileSize) == 0); ++ ++ *pPitchAlign *= numMacroTiles; ++ *pBaseAlign *= numMacroTiles; ++ } ++ } ++ } ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::SanityCheckMacroTiled ++* ++* @brief ++* Check if macro-tiled parameters are valid ++* @return ++* TRUE if valid ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::SanityCheckMacroTiled( ++ ADDR_TILEINFO* pTileInfo ///< [in] macro-tiled parameters ++ ) const ++{ ++ BOOL_32 valid = TRUE; ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ ++ switch (pTileInfo->banks) ++ { ++ case 2: //fall through ++ case 4: //fall through ++ case 8: //fall through ++ case 16: ++ break; ++ default: ++ valid = FALSE; ++ break; ++ ++ } ++ ++ if (valid) ++ { ++ switch (pTileInfo->bankWidth) ++ { ++ case 1: //fall through ++ case 2: //fall through ++ case 4: //fall through ++ case 8: ++ break; ++ default: ++ valid = FALSE; ++ break; ++ } ++ } ++ ++ if (valid) ++ { ++ switch (pTileInfo->bankHeight) ++ { ++ case 1: //fall through ++ case 2: //fall through ++ case 4: //fall through ++ case 8: ++ break; ++ default: ++ valid = FALSE; ++ break; ++ } ++ } ++ ++ if (valid) ++ { ++ switch (pTileInfo->macroAspectRatio) ++ { ++ case 1: //fall through ++ case 2: //fall through ++ case 4: //fall through ++ case 8: ++ break; ++ default: ++ valid = FALSE; ++ break; ++ } ++ } ++ ++ if (valid) ++ { ++ if (pTileInfo->banks < pTileInfo->macroAspectRatio) ++ { ++ // This will generate macro tile height <= 1 ++ valid = FALSE; ++ } ++ } ++ ++ if (valid) ++ { ++ if (pTileInfo->tileSplitBytes > m_rowSize) ++ { ++ valid = FALSE; ++ } ++ } ++ ++ if (valid) ++ { ++ valid = HwlSanityCheckMacroTiled(pTileInfo); ++ } ++ ++ ADDR_ASSERT(valid == TRUE); ++ ++ // Add this assert for guidance ++ ADDR_ASSERT(numPipes * pTileInfo->banks >= 4); ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceMipLevelTileMode ++* ++* @brief ++* Compute valid tile mode for surface mipmap sub-levels ++* ++* @return ++* Suitable tile mode ++*************************************************************************************************** ++*/ ++AddrTileMode EgBasedAddrLib::ComputeSurfaceMipLevelTileMode( ++ AddrTileMode baseTileMode, ///< [in] base tile mode ++ UINT_32 bpp, ///< [in] bits per pixels ++ UINT_32 pitch, ///< [in] current level pitch ++ UINT_32 height, ///< [in] current level height ++ UINT_32 numSlices, ///< [in] current number of slices ++ UINT_32 numSamples, ///< [in] number of samples ++ UINT_32 pitchAlign, ///< [in] pitch alignment ++ UINT_32 heightAlign, ///< [in] height alignment ++ ADDR_TILEINFO* pTileInfo ///< [in] ptr to bank structure ++ ) const ++{ ++ UINT_64 bytesPerSlice; ++ UINT_32 bytesPerTile; ++ ++ AddrTileMode expTileMode = baseTileMode; ++ UINT_32 microTileThickness = ComputeSurfaceThickness(expTileMode); ++ UINT_32 interleaveSize = m_pipeInterleaveBytes * m_bankInterleave; ++ ++ // ++ // Compute the size of a slice. ++ // ++ bytesPerSlice = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); ++ bytesPerTile = BITS_TO_BYTES(MicroTilePixels * microTileThickness * NextPow2(bpp) * numSamples); ++ ++ // ++ // Reduce tiling mode from thick to thin if the number of slices is less than the ++ // micro tile thickness. ++ // ++ if (numSlices < microTileThickness) ++ { ++ expTileMode = HwlDegradeThickTileMode(expTileMode, numSlices, &bytesPerTile); ++ } ++ ++ if (bytesPerTile > pTileInfo->tileSplitBytes) ++ { ++ bytesPerTile = pTileInfo->tileSplitBytes; ++ } ++ ++ UINT_32 threshold1 = ++ bytesPerTile * HwlGetPipes(pTileInfo) * pTileInfo->bankWidth * pTileInfo->macroAspectRatio; ++ ++ UINT_32 threshold2 = ++ bytesPerTile * pTileInfo->bankWidth * pTileInfo->bankHeight; ++ ++ // ++ // Reduce the tile mode from 2D/3D to 1D in following conditions ++ // ++ switch (expTileMode) ++ { ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THIN1: ++ case ADDR_TM_PRT_TILED_THIN1: ++ case ADDR_TM_PRT_2D_TILED_THIN1: ++ case ADDR_TM_PRT_3D_TILED_THIN1: ++ if ((pitch < pitchAlign) || ++ (height < heightAlign) || ++ (interleaveSize > threshold1) || ++ (interleaveSize > threshold2)) ++ { ++ expTileMode = ADDR_TM_1D_TILED_THIN1; ++ } ++ break; ++ case ADDR_TM_2D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_THICK: ++ case ADDR_TM_2D_TILED_XTHICK: ++ case ADDR_TM_3D_TILED_XTHICK: ++ case ADDR_TM_PRT_TILED_THICK: ++ case ADDR_TM_PRT_2D_TILED_THICK: ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ if ((pitch < pitchAlign) || ++ (height < heightAlign)) ++ { ++ expTileMode = ADDR_TM_1D_TILED_THICK; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return expTileMode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlDegradeBaseLevel ++* @brief ++* Check if degrade is needed for base level ++* @return ++* TRUE if degrade is suggested ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::HwlDegradeBaseLevel( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const ++{ ++ BOOL_32 degrade = FALSE; ++ BOOL_32 valid = TRUE; ++ ++ ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); ++ ++ UINT_32 baseAlign; ++ UINT_32 pitchAlign; ++ UINT_32 heightAlign; ++ ++ ADDR_ASSERT(pIn->pTileInfo); ++ ADDR_TILEINFO tileInfo = *pIn->pTileInfo; ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT out = {0}; ++ ++ if (UseTileIndex(pIn->tileIndex)) ++ { ++ out.tileIndex = pIn->tileIndex; ++ out.macroModeIndex = TileIndexInvalid; ++ } ++ ++ HwlSetupTileInfo(pIn->tileMode, ++ pIn->flags, ++ pIn->bpp, ++ pIn->width, ++ pIn->height, ++ pIn->numSamples, ++ &tileInfo, ++ &tileInfo, ++ pIn->tileType, ++ &out); ++ ++ valid = ComputeSurfaceAlignmentsMacroTiled(pIn->tileMode, ++ pIn->bpp, ++ pIn->flags, ++ pIn->mipLevel, ++ pIn->numSamples, ++ &tileInfo, ++ &baseAlign, ++ &pitchAlign, ++ &heightAlign); ++ ++ if (valid) ++ { ++ degrade = (pIn->width < pitchAlign || pIn->height < heightAlign); ++ } ++ else ++ { ++ degrade = TRUE; ++ } ++ ++ return degrade; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlDegradeThickTileMode ++* ++* @brief ++* Degrades valid tile mode for thick modes if needed ++* ++* @return ++* Suitable tile mode ++*************************************************************************************************** ++*/ ++AddrTileMode EgBasedAddrLib::HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, ///< [in] base tile mode ++ UINT_32 numSlices, ///< [in] current number of slices ++ UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice ++ ) const ++{ ++ ADDR_ASSERT(numSlices < ComputeSurfaceThickness(baseTileMode)); ++ // if pBytesPerTile is NULL, this is a don't-care.... ++ UINT_32 bytesPerTile = pBytesPerTile != NULL ? *pBytesPerTile : 64; ++ ++ AddrTileMode expTileMode = baseTileMode; ++ switch (baseTileMode) ++ { ++ case ADDR_TM_1D_TILED_THICK: ++ expTileMode = ADDR_TM_1D_TILED_THIN1; ++ bytesPerTile >>= 2; ++ break; ++ case ADDR_TM_2D_TILED_THICK: ++ expTileMode = ADDR_TM_2D_TILED_THIN1; ++ bytesPerTile >>= 2; ++ break; ++ case ADDR_TM_3D_TILED_THICK: ++ expTileMode = ADDR_TM_3D_TILED_THIN1; ++ bytesPerTile >>= 2; ++ break; ++ case ADDR_TM_2D_TILED_XTHICK: ++ if (numSlices < ThickTileThickness) ++ { ++ expTileMode = ADDR_TM_2D_TILED_THIN1; ++ bytesPerTile >>= 3; ++ } ++ else ++ { ++ expTileMode = ADDR_TM_2D_TILED_THICK; ++ bytesPerTile >>= 1; ++ } ++ break; ++ case ADDR_TM_3D_TILED_XTHICK: ++ if (numSlices < ThickTileThickness) ++ { ++ expTileMode = ADDR_TM_3D_TILED_THIN1; ++ bytesPerTile >>= 3; ++ } ++ else ++ { ++ expTileMode = ADDR_TM_3D_TILED_THICK; ++ bytesPerTile >>= 1; ++ } ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ if (pBytesPerTile != NULL) ++ { ++ *pBytesPerTile = bytesPerTile; ++ } ++ ++ return expTileMode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord ++* ++* @brief ++* Compute surface address from given coord (x, y, slice,sample) ++* ++* @return ++* Address in bytes ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ UINT_32 x = pIn->x; ++ UINT_32 y = pIn->y; ++ UINT_32 slice = pIn->slice; ++ UINT_32 sample = pIn->sample; ++ UINT_32 bpp = pIn->bpp; ++ UINT_32 pitch = pIn->pitch; ++ UINT_32 height = pIn->height; ++ UINT_32 numSlices = pIn->numSlices; ++ UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples); ++ UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); ++ AddrTileMode tileMode = pIn->tileMode; ++ AddrTileType microTileType = pIn->tileType; ++ BOOL_32 ignoreSE = pIn->ignoreSE; ++ BOOL_32 isDepthSampleOrder = pIn->isDepth; ++ ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; ++ ++ UINT_32* pBitPosition = &pOut->bitPosition; ++ UINT_64 addr; ++ ++#if ADDR_AM_BUILD ++ UINT_32 addr5Bit = 0; ++ UINT_32 addr5Swizzle = pIn->addr5Swizzle; ++ BOOL_32 is32ByteTile = pIn->is32ByteTile; ++#endif ++ ++ // ADDR_DEPTH_SAMPLE_ORDER = non-disp + depth-sample-order ++ if (microTileType == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ isDepthSampleOrder = TRUE; ++ } ++ ++ if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) ++ { ++ if (numFrags != numSamples) ++ { ++ numSamples = numFrags; ++ ADDR_ASSERT(sample < numSamples); ++ } ++ ++ /// @note ++ /// 128 bit/thick tiled surface doesn't support display tiling and ++ /// mipmap chain must have the same tileType, so please fill tileType correctly ++ if (!IsLinear(pIn->tileMode)) ++ { ++ if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1) ++ { ++ ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE); ++ } ++ } ++ } ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_LINEAR_GENERAL://fall through ++ case ADDR_TM_LINEAR_ALIGNED: ++ addr = ComputeSurfaceAddrFromCoordLinear(x, ++ y, ++ slice, ++ sample, ++ bpp, ++ pitch, ++ height, ++ numSlices, ++ pBitPosition); ++ break; ++ case ADDR_TM_1D_TILED_THIN1://fall through ++ case ADDR_TM_1D_TILED_THICK: ++ addr = ComputeSurfaceAddrFromCoordMicroTiled(x, ++ y, ++ slice, ++ sample, ++ bpp, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ microTileType, ++ isDepthSampleOrder, ++ pBitPosition); ++ break; ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_2D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THICK: //fall through ++ case ADDR_TM_2D_TILED_XTHICK: //fall through ++ case ADDR_TM_3D_TILED_XTHICK: //fall through ++ case ADDR_TM_PRT_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_2D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_3D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_TILED_THICK: //fall through ++ case ADDR_TM_PRT_2D_TILED_THICK://fall through ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ UINT_32 pipeSwizzle; ++ UINT_32 bankSwizzle; ++ ++ if (m_configFlags.useCombinedSwizzle) ++ { ++ ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, ++ &bankSwizzle, &pipeSwizzle); ++ } ++ else ++ { ++ pipeSwizzle = pIn->pipeSwizzle; ++ bankSwizzle = pIn->bankSwizzle; ++ } ++ ++ addr = ComputeSurfaceAddrFromCoordMacroTiled(x, ++ y, ++ slice, ++ sample, ++ bpp, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ microTileType, ++ ignoreSE, ++ isDepthSampleOrder, ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pBitPosition); ++ break; ++ default: ++ addr = 0; ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++#if ADDR_AM_BUILD ++ if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) ++ { ++ if (addr5Swizzle && isDepthSampleOrder && is32ByteTile) ++ { ++ UINT_32 tx = x >> 3; ++ UINT_32 ty = y >> 3; ++ UINT_32 tileBits = ((ty&0x3) << 2) | (tx&0x3); ++ ++ tileBits = tileBits & addr5Swizzle; ++ addr5Bit = XorReduce(tileBits, 4); ++ ++ addr = addr | static_cast<UINT_64>(addr5Bit << 5); ++ } ++ } ++#endif ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled ++* ++* @brief ++* Computes the surface address and bit position from a ++* coordinate for 2D tilied (macro tiled) ++* @return ++* The byte address ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMacroTiled( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 sample, ///< [in] sample index ++ UINT_32 bpp, ///< [in] bits per pixel ++ UINT_32 pitch, ///< [in] surface pitch, in pixels ++ UINT_32 height, ///< [in] surface height, in pixels ++ UINT_32 numSamples, ///< [in] number of samples ++ AddrTileMode tileMode, ///< [in] tile mode ++ AddrTileType microTileType, ///< [in] micro tiling type ++ BOOL_32 ignoreSE, ///< [in] TRUE if shader enginers can be ignored ++ BOOL_32 isDepthSampleOrder, ///< [in] TRUE if it depth sample ordering is used ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ ADDR_TILEINFO* pTileInfo, ///< [in] bank structure ++ /// **All fields to be valid on entry** ++ UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this ++ ) const ++{ ++ UINT_64 addr; ++ ++ UINT_32 microTileBytes; ++ UINT_32 microTileBits; ++ UINT_32 sampleOffset; ++ UINT_32 pixelIndex; ++ UINT_32 pixelOffset; ++ UINT_32 elementOffset; ++ UINT_32 tileSplitSlice; ++ UINT_32 pipe; ++ UINT_32 bank; ++ UINT_64 sliceBytes; ++ UINT_64 sliceOffset; ++ UINT_32 macroTilePitch; ++ UINT_32 macroTileHeight; ++ UINT_32 macroTilesPerRow; ++ UINT_32 macroTilesPerSlice; ++ UINT_64 macroTileBytes; ++ UINT_32 macroTileIndexX; ++ UINT_32 macroTileIndexY; ++ UINT_64 macroTileOffset; ++ UINT_64 totalOffset; ++ UINT_64 pipeInterleaveMask; ++ UINT_64 bankInterleaveMask; ++ UINT_64 pipeInterleaveOffset; ++ UINT_32 bankInterleaveOffset; ++ UINT_64 offset; ++ UINT_32 tileRowIndex; ++ UINT_32 tileColumnIndex; ++ UINT_32 tileIndex; ++ UINT_32 tileOffset; ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ // ++ // Compute the number of group, pipe, and bank bits. ++ // ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ UINT_32 numPipeInterleaveBits = Log2(m_pipeInterleaveBytes); ++ UINT_32 numPipeBits = Log2(numPipes); ++ UINT_32 numBankInterleaveBits = Log2(m_bankInterleave); ++ UINT_32 numBankBits = Log2(pTileInfo->banks); ++ ++ // ++ // Compute the micro tile size. ++ // ++ microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples; ++ ++ microTileBytes = microTileBits / 8; ++ // ++ // Compute the pixel index within the micro tile. ++ // ++ pixelIndex = ComputePixelIndexWithinMicroTile(x, ++ y, ++ slice, ++ bpp, ++ tileMode, ++ microTileType); ++ ++ // ++ // Compute the sample offset and pixel offset. ++ // ++ if (isDepthSampleOrder) ++ { ++ // ++ // For depth surfaces, samples are stored contiguously for each element, so the sample ++ // offset is the sample number times the element size. ++ // ++ sampleOffset = sample * bpp; ++ pixelOffset = pixelIndex * bpp * numSamples; ++ } ++ else ++ { ++ // ++ // For color surfaces, all elements for a particular sample are stored contiguously, so ++ // the sample offset is the sample number times the micro tile size divided yBit the number ++ // of samples. ++ // ++ sampleOffset = sample * (microTileBits / numSamples); ++ pixelOffset = pixelIndex * bpp; ++ } ++ ++ // ++ // Compute the element offset. ++ // ++ elementOffset = pixelOffset + sampleOffset; ++ ++ *pBitPosition = static_cast<UINT_32>(elementOffset % 8); ++ ++ elementOffset /= 8; //bit-to-byte ++ ++ // ++ // Determine if tiles need to be split across slices. ++ // ++ // If the size of the micro tile is larger than the tile split size, then the tile will be ++ // split across multiple slices. ++ // ++ UINT_32 slicesPerTile = 1; ++ ++ if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1)) ++ { //don't support for thick mode ++ ++ // ++ // Compute the number of slices per tile. ++ // ++ slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes; ++ ++ // ++ // Compute the tile split slice number for use in rotating the bank. ++ // ++ tileSplitSlice = elementOffset / pTileInfo->tileSplitBytes; ++ ++ // ++ // Adjust the element offset to account for the portion of the tile that is being moved to ++ // a new slice.. ++ // ++ elementOffset %= pTileInfo->tileSplitBytes; ++ ++ // ++ // Adjust the microTileBytes size to tileSplitBytes size since ++ // a new slice.. ++ // ++ microTileBytes = pTileInfo->tileSplitBytes; ++ } ++ else ++ { ++ tileSplitSlice = 0; ++ } ++ ++ // ++ // Compute macro tile pitch and height. ++ // ++ macroTilePitch = ++ (MicroTileWidth * pTileInfo->bankWidth * numPipes) * pTileInfo->macroAspectRatio; ++ macroTileHeight = ++ (MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks) / pTileInfo->macroAspectRatio; ++ ++ // ++ // Compute the number of bytes per macro tile. Note: bytes of the same bank/pipe actually ++ // ++ macroTileBytes = ++ static_cast<UINT_64>(microTileBytes) * ++ (macroTilePitch / MicroTileWidth) * (macroTileHeight / MicroTileHeight) / ++ (numPipes * pTileInfo->banks); ++ ++ // ++ // Compute the number of macro tiles per row. ++ // ++ macroTilesPerRow = pitch / macroTilePitch; ++ ++ // ++ // Compute the offset to the macro tile containing the specified coordinate. ++ // ++ macroTileIndexX = x / macroTilePitch; ++ macroTileIndexY = y / macroTileHeight; ++ macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes; ++ ++ // ++ // Compute the number of macro tiles per slice. ++ // ++ macroTilesPerSlice = macroTilesPerRow * (height / macroTileHeight); ++ ++ // ++ // Compute the slice size. ++ // ++ sliceBytes = macroTilesPerSlice * macroTileBytes; ++ ++ // ++ // Compute the slice offset. ++ // ++ sliceOffset = sliceBytes * (tileSplitSlice + slicesPerTile * (slice / microTileThickness)); ++ ++ // ++ // Compute tile offest ++ // ++ tileRowIndex = (y / MicroTileHeight) % pTileInfo->bankHeight; ++ tileColumnIndex = ((x / MicroTileWidth) / numPipes) % pTileInfo->bankWidth; ++ tileIndex = (tileRowIndex * pTileInfo->bankWidth) + tileColumnIndex; ++ tileOffset = tileIndex * microTileBytes; ++ ++ // ++ // Combine the slice offset and macro tile offset with the pixel and sample offsets, accounting ++ // for the pipe and bank bits in the middle of the address. ++ // ++ totalOffset = sliceOffset + macroTileOffset + elementOffset + tileOffset; ++ ++ // ++ // Get the pipe and bank. ++ // ++ ++ // when the tileMode is PRT type, then adjust x and y coordinates ++ if (IsPrtNoRotationTileMode(tileMode)) ++ { ++ x = x % macroTilePitch; ++ y = y % macroTileHeight; ++ } ++ ++ pipe = ComputePipeFromCoord(x, ++ y, ++ slice, ++ tileMode, ++ pipeSwizzle, ++ ignoreSE, ++ pTileInfo); ++ ++ bank = ComputeBankFromCoord(x, ++ y, ++ slice, ++ tileMode, ++ bankSwizzle, ++ tileSplitSlice, ++ pTileInfo); ++ ++ ++ // ++ // Split the offset to put some bits below the pipe+bank bits and some above. ++ // ++ pipeInterleaveMask = (1 << numPipeInterleaveBits) - 1; ++ bankInterleaveMask = (1 << numBankInterleaveBits) - 1; ++ pipeInterleaveOffset = totalOffset & pipeInterleaveMask; ++ bankInterleaveOffset = static_cast<UINT_32>((totalOffset >> numPipeInterleaveBits) & ++ bankInterleaveMask); ++ offset = totalOffset >> (numPipeInterleaveBits + numBankInterleaveBits); ++ ++ // ++ // Assemble the address from its components. ++ // ++ addr = pipeInterleaveOffset; ++ // This is to remove /analyze warnings ++ UINT_32 pipeBits = pipe << numPipeInterleaveBits; ++ UINT_32 bankInterleaveBits = bankInterleaveOffset << (numPipeInterleaveBits + numPipeBits); ++ UINT_32 bankBits = bank << (numPipeInterleaveBits + numPipeBits + ++ numBankInterleaveBits); ++ UINT_64 offsetBits = offset << (numPipeInterleaveBits + numPipeBits + ++ numBankInterleaveBits + numBankBits); ++ ++ addr |= pipeBits; ++ addr |= bankInterleaveBits; ++ addr |= bankBits; ++ addr |= offsetBits; ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled ++* ++* @brief ++* Computes the surface address and bit position from a coordinate for 1D tilied ++* (micro tiled) ++* @return ++* The byte address ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 sample, ///< [in] sample index ++ UINT_32 bpp, ///< [in] bits per pixel ++ UINT_32 pitch, ///< [in] pitch, in pixels ++ UINT_32 height, ///< [in] height, in pixels ++ UINT_32 numSamples, ///< [in] number of samples ++ AddrTileMode tileMode, ///< [in] tile mode ++ AddrTileType microTileType, ///< [in] micro tiling type ++ BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample ordering is used ++ UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this ++ ) const ++{ ++ UINT_64 addr = 0; ++ ++ UINT_32 microTileBytes; ++ UINT_64 sliceBytes; ++ UINT_32 microTilesPerRow; ++ UINT_32 microTileIndexX; ++ UINT_32 microTileIndexY; ++ UINT_32 microTileIndexZ; ++ UINT_64 sliceOffset; ++ UINT_64 microTileOffset; ++ UINT_32 sampleOffset; ++ UINT_32 pixelIndex; ++ UINT_32 pixelOffset; ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ // ++ // Compute the micro tile size. ++ // ++ microTileBytes = BITS_TO_BYTES(MicroTilePixels * microTileThickness * bpp * numSamples); ++ ++ // ++ // Compute the slice size. ++ // ++ sliceBytes = ++ BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples); ++ ++ // ++ // Compute the number of micro tiles per row. ++ // ++ microTilesPerRow = pitch / MicroTileWidth; ++ ++ // ++ // Compute the micro tile index. ++ // ++ microTileIndexX = x / MicroTileWidth; ++ microTileIndexY = y / MicroTileHeight; ++ microTileIndexZ = slice / microTileThickness; ++ ++ // ++ // Compute the slice offset. ++ // ++ sliceOffset = static_cast<UINT_64>(microTileIndexZ) * sliceBytes; ++ ++ // ++ // Compute the offset to the micro tile containing the specified coordinate. ++ // ++ microTileOffset = (static_cast<UINT_64>(microTileIndexY) * microTilesPerRow + microTileIndexX) * ++ microTileBytes; ++ ++ // ++ // Compute the pixel index within the micro tile. ++ // ++ pixelIndex = ComputePixelIndexWithinMicroTile(x, ++ y, ++ slice, ++ bpp, ++ tileMode, ++ microTileType); ++ ++ // Compute the sample offset. ++ // ++ if (isDepthSampleOrder) ++ { ++ // ++ // For depth surfaces, samples are stored contiguously for each element, so the sample ++ // offset is the sample number times the element size. ++ // ++ sampleOffset = sample * bpp; ++ pixelOffset = pixelIndex * bpp * numSamples; ++ } ++ else ++ { ++ // ++ // For color surfaces, all elements for a particular sample are stored contiguously, so ++ // the sample offset is the sample number times the micro tile size divided yBit the number ++ // of samples. ++ // ++ sampleOffset = sample * (microTileBytes*8 / numSamples); ++ pixelOffset = pixelIndex * bpp; ++ } ++ ++ // ++ // Compute the bit position of the pixel. Each element is stored with one bit per sample. ++ // ++ ++ UINT_32 elemOffset = sampleOffset + pixelOffset; ++ ++ *pBitPosition = elemOffset % 8; ++ elemOffset /= 8; ++ ++ // ++ // Combine the slice offset, micro tile offset, sample offset, and pixel offsets. ++ // ++ addr = sliceOffset + microTileOffset + elemOffset; ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputePixelCoordFromOffset ++* ++* @brief ++* Compute pixel coordinate from offset inside a micro tile ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::HwlComputePixelCoordFromOffset( ++ UINT_32 offset, ///< [in] offset inside micro tile in bits ++ UINT_32 bpp, ///< [in] bits per pixel ++ 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 coordinate ++ UINT_32* pY, ///< [out] y coordinate ++ UINT_32* pSlice, ///< [out] slice index ++ UINT_32* pSample, ///< [out] sample index ++ AddrTileType microTileType, ///< [in] micro tiling type ++ BOOL_32 isDepthSampleOrder ///< [in] TRUE if depth sample order in microtile is used ++ ) const ++{ ++ UINT_32 x = 0; ++ UINT_32 y = 0; ++ UINT_32 z = 0; ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ ++ // For planar surface, we adjust offset acoording to tile base ++ if ((bpp != compBits) && (compBits != 0) && isDepthSampleOrder) ++ { ++ offset -= tileBase; ++ ++ ADDR_ASSERT(microTileType == ADDR_NON_DISPLAYABLE || ++ microTileType == ADDR_DEPTH_SAMPLE_ORDER); ++ ++ bpp = compBits; ++ } ++ ++ UINT_32 sampleTileBits; ++ UINT_32 samplePixelBits; ++ UINT_32 pixelIndex; ++ ++ if (isDepthSampleOrder) ++ { ++ samplePixelBits = bpp * numSamples; ++ pixelIndex = offset / samplePixelBits; ++ *pSample = (offset % samplePixelBits) / bpp; ++ } ++ else ++ { ++ sampleTileBits = MicroTilePixels * bpp * thickness; ++ *pSample = offset / sampleTileBits; ++ pixelIndex = (offset % sampleTileBits) / bpp; ++ } ++ ++ if (microTileType != ADDR_THICK) ++ { ++ if (microTileType == ADDR_DISPLAYABLE) // displayable ++ { ++ switch (bpp) ++ { ++ case 8: ++ x = pixelIndex & 0x7; ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4)); ++ break; ++ case 16: ++ x = pixelIndex & 0x7; ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3)); ++ break; ++ case 32: ++ x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2)); ++ break; ++ case 64: ++ x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); ++ break; ++ case 128: ++ x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,1)); ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,0)); ++ break; ++ default: ++ break; ++ } ++ } ++ else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); ++ } ++ else if (microTileType == ADDR_ROTATED) ++ { ++ /* ++ 8-Bit Elements ++ element_index[5:0] = { x[2], x[0], x[1], y[2], y[1], y[0] } ++ ++ 16-Bit Elements ++ element_index[5:0] = { x[2], x[1], x[0], y[2], y[1], y[0] } ++ ++ 32-Bit Elements ++ element_index[5:0] = { x[2], x[1], y[2], x[0], y[1], y[0] } ++ ++ 64-Bit Elements ++ element_index[5:0] = { y[2], x[2], x[1], y[1], x[0], y[0] } ++ */ ++ switch(bpp) ++ { ++ case 8: ++ x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4)); ++ y = pixelIndex & 0x7; ++ break; ++ case 16: ++ x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3)); ++ y = pixelIndex & 0x7; ++ break; ++ case 32: ++ x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2)); ++ y = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0)); ++ break; ++ case 64: ++ x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); ++ y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ } ++ ++ if (thickness > 1) // thick ++ { ++ z = Bits2Number(3, _BIT(pixelIndex,8),_BIT(pixelIndex,7),_BIT(pixelIndex,6)); ++ } ++ } ++ else ++ { ++ ADDR_ASSERT((m_chipFamily >= ADDR_CHIP_FAMILY_CI) && (thickness > 1)); ++ /* ++ 8-Bit Elements and 16-Bit Elements ++ element_index[7:0] = { y[2], x[2], z[1], z[0], y[1], x[1], y[0], x[0] } ++ ++ 32-Bit Elements ++ element_index[7:0] = { y[2], x[2], z[1], y[1], z[0], x[1], y[0], x[0] } ++ ++ 64-Bit Elements and 128-Bit Elements ++ element_index[7:0] = { y[2], x[2], z[1], y[1], x[1], z[0], y[0], x[0] } ++ ++ The equation to compute the element index for the extra thick tile: ++ element_index[8] = z[2] ++ */ ++ switch (bpp) ++ { ++ case 8: ++ case 16: // fall-through ++ x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,3),_BIT(pixelIndex,1)); ++ z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,4)); ++ break; ++ case 32: ++ x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); ++ z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,3)); ++ break; ++ case 64: ++ case 128: // fall-through ++ x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,3),_BIT(pixelIndex,0)); ++ y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1)); ++ z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,2)); ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ if (thickness == 8) ++ { ++ z += Bits2Number(3,_BIT(pixelIndex,8),0,0); ++ } ++ } ++ ++ *pX = x; ++ *pY = y; ++ *pSlice += z; ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddrDispatch ++* ++* @brief ++* Compute (x,y,slice,sample) coordinates from surface address ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ UINT_64 addr = pIn->addr; ++ UINT_32 bitPosition = pIn->bitPosition; ++ UINT_32 bpp = pIn->bpp; ++ UINT_32 pitch = pIn->pitch; ++ UINT_32 height = pIn->height; ++ UINT_32 numSlices = pIn->numSlices; ++ UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples); ++ UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags); ++ AddrTileMode tileMode = pIn->tileMode; ++ UINT_32 tileBase = pIn->tileBase; ++ UINT_32 compBits = pIn->compBits; ++ AddrTileType microTileType = pIn->tileType; ++ BOOL_32 ignoreSE = pIn->ignoreSE; ++ BOOL_32 isDepthSampleOrder = pIn->isDepth; ++ ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; ++ ++ UINT_32* pX = &pOut->x; ++ UINT_32* pY = &pOut->y; ++ UINT_32* pSlice = &pOut->slice; ++ UINT_32* pSample = &pOut->sample; ++ ++ if (microTileType == ADDR_DEPTH_SAMPLE_ORDER) ++ { ++ isDepthSampleOrder = TRUE; ++ } ++ ++ if (m_chipFamily >= ADDR_CHIP_FAMILY_NI) ++ { ++ if (numFrags != numSamples) ++ { ++ numSamples = numFrags; ++ } ++ ++ /// @note ++ /// 128 bit/thick tiled surface doesn't support display tiling and ++ /// mipmap chain must have the same tileType, so please fill tileType correctly ++ if (!IsLinear(pIn->tileMode)) ++ { ++ if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1) ++ { ++ ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE); ++ } ++ } ++ } ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_LINEAR_GENERAL://fall through ++ case ADDR_TM_LINEAR_ALIGNED: ++ ComputeSurfaceCoordFromAddrLinear(addr, ++ bitPosition, ++ bpp, ++ pitch, ++ height, ++ numSlices, ++ pX, ++ pY, ++ pSlice, ++ pSample); ++ break; ++ case ADDR_TM_1D_TILED_THIN1://fall through ++ case ADDR_TM_1D_TILED_THICK: ++ ComputeSurfaceCoordFromAddrMicroTiled(addr, ++ bitPosition, ++ bpp, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ tileBase, ++ compBits, ++ pX, ++ pY, ++ pSlice, ++ pSample, ++ microTileType, ++ isDepthSampleOrder); ++ break; ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_2D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THICK: //fall through ++ case ADDR_TM_2D_TILED_XTHICK: //fall through ++ case ADDR_TM_3D_TILED_XTHICK: //fall through ++ case ADDR_TM_PRT_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_2D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_3D_TILED_THIN1://fall through ++ case ADDR_TM_PRT_TILED_THICK: //fall through ++ case ADDR_TM_PRT_2D_TILED_THICK://fall through ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ UINT_32 pipeSwizzle; ++ UINT_32 bankSwizzle; ++ ++ if (m_configFlags.useCombinedSwizzle) ++ { ++ ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, ++ &bankSwizzle, &pipeSwizzle); ++ } ++ else ++ { ++ pipeSwizzle = pIn->pipeSwizzle; ++ bankSwizzle = pIn->bankSwizzle; ++ } ++ ++ ComputeSurfaceCoordFromAddrMacroTiled(addr, ++ bitPosition, ++ bpp, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ tileBase, ++ compBits, ++ microTileType, ++ ignoreSE, ++ isDepthSampleOrder, ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pX, ++ pY, ++ pSlice, ++ pSample); ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ } ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled ++* ++* @brief ++* Compute surface coordinates from address for macro tiled surface ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled( ++ UINT_64 addr, ///< [in] byte address ++ UINT_32 bitPosition, ///< [in] bit position ++ UINT_32 bpp, ///< [in] bits per pixel ++ UINT_32 pitch, ///< [in] pitch in pixels ++ UINT_32 height, ///< [in] height in pixels ++ UINT_32 numSamples, ///< [in] number of samples ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 tileBase, ///< [in] tile base offset ++ UINT_32 compBits, ///< [in] component bits (for planar surface) ++ AddrTileType microTileType, ///< [in] micro tiling type ++ BOOL_32 ignoreSE, ///< [in] TRUE if shader engines can be ignored ++ BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample order is used ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. ++ /// **All fields to be valid on entry** ++ UINT_32* pX, ///< [out] X coord ++ UINT_32* pY, ///< [out] Y coord ++ UINT_32* pSlice, ///< [out] slice index ++ UINT_32* pSample ///< [out] sample index ++ ) const ++{ ++ UINT_32 mx; ++ UINT_32 my; ++ UINT_64 tileBits; ++ UINT_64 macroTileBits; ++ UINT_32 slices; ++ UINT_32 tileSlices; ++ UINT_64 elementOffset; ++ UINT_64 macroTileIndex; ++ UINT_32 tileIndex; ++ UINT_64 totalOffset; ++ ++ ++ UINT_32 bank; ++ UINT_32 pipe; ++ UINT_32 groupBits = m_pipeInterleaveBytes << 3; ++ UINT_32 pipes = HwlGetPipes(pTileInfo); ++ UINT_32 banks = pTileInfo->banks; ++ ++ UINT_32 bankInterleave = m_bankInterleave; ++ ++ UINT_64 addrBits = BYTES_TO_BITS(addr) + bitPosition; ++ ++ // ++ // remove bits for bank and pipe ++ // ++ totalOffset = (addrBits % groupBits) + ++ (((addrBits / groupBits / pipes) % bankInterleave) * groupBits) + ++ (((addrBits / groupBits / pipes) / bankInterleave) / banks) * groupBits * bankInterleave; ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ UINT_32 microTileBits = bpp * microTileThickness * MicroTilePixels * numSamples; ++ ++ UINT_32 microTileBytes = BITS_TO_BYTES(microTileBits); ++ // ++ // Determine if tiles need to be split across slices. ++ // ++ // If the size of the micro tile is larger than the tile split size, then the tile will be ++ // split across multiple slices. ++ // ++ UINT_32 slicesPerTile = 1; //_State->TileSlices ++ ++ if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1)) ++ { //don't support for thick mode ++ ++ // ++ // Compute the number of slices per tile. ++ // ++ slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes; ++ } ++ ++ tileBits = microTileBits / slicesPerTile; // micro tile bits ++ ++ // in micro tiles because not MicroTileWidth timed. ++ UINT_32 macroWidth = pTileInfo->bankWidth * pipes * pTileInfo->macroAspectRatio; ++ // in micro tiles as well ++ UINT_32 macroHeight = pTileInfo->bankHeight * banks / pTileInfo->macroAspectRatio; ++ ++ UINT_32 pitchInMacroTiles = pitch / MicroTileWidth / macroWidth; ++ ++ macroTileBits = (macroWidth * macroHeight) * tileBits / (banks * pipes); ++ ++ macroTileIndex = totalOffset / macroTileBits; ++ ++ // pitchMacros * height / heightMacros; macroTilesPerSlice == _State->SliceMacros ++ UINT_32 macroTilesPerSlice = (pitch / (macroWidth * MicroTileWidth)) * height / ++ (macroHeight * MicroTileWidth); ++ ++ slices = static_cast<UINT_32>(macroTileIndex / macroTilesPerSlice); ++ ++ *pSlice = static_cast<UINT_32>(slices / slicesPerTile * microTileThickness); ++ ++ // ++ // calculate element offset and x[2:0], y[2:0], z[1:0] for thick ++ // ++ tileSlices = slices % slicesPerTile; ++ ++ elementOffset = tileSlices * tileBits; ++ elementOffset += totalOffset % tileBits; ++ ++ UINT_32 coordZ = 0; ++ ++ HwlComputePixelCoordFromOffset(static_cast<UINT_32>(elementOffset), ++ bpp, ++ numSamples, ++ tileMode, ++ tileBase, ++ compBits, ++ pX, ++ pY, ++ &coordZ, ++ pSample, ++ microTileType, ++ isDepthSampleOrder); ++ ++ macroTileIndex = macroTileIndex % macroTilesPerSlice; ++ *pY += static_cast<UINT_32>(macroTileIndex / pitchInMacroTiles * macroHeight * MicroTileHeight); ++ *pX += static_cast<UINT_32>(macroTileIndex % pitchInMacroTiles * macroWidth * MicroTileWidth); ++ ++ *pSlice += coordZ; ++ ++ tileIndex = static_cast<UINT_32>((totalOffset % macroTileBits) / tileBits); ++ ++ my = (tileIndex / pTileInfo->bankWidth) % pTileInfo->bankHeight * MicroTileHeight; ++ mx = (tileIndex % pTileInfo->bankWidth) * pipes * MicroTileWidth; ++ ++ *pY += my; ++ *pX += mx; ++ ++ bank = ComputeBankFromAddr(addr, banks, pipes); ++ pipe = ComputePipeFromAddr(addr, pipes); ++ ++ HwlComputeSurfaceCoord2DFromBankPipe(tileMode, ++ pX, ++ pY, ++ *pSlice, ++ bank, ++ pipe, ++ bankSwizzle, ++ pipeSwizzle, ++ tileSlices, ++ ignoreSE, ++ pTileInfo); ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe ++* ++* @brief ++* Compute surface x,y coordinates from bank/pipe info ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 bank, ///< [in] bank number ++ UINT_32 pipe, ///< [in] pipe number ++ UINT_32 bankSwizzle,///< [in] bank swizzle ++ UINT_32 pipeSwizzle,///< [in] pipe swizzle ++ UINT_32 tileSlices, ///< [in] slices in a micro tile ++ ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry** ++ CoordFromBankPipe* pOutput ///< [out] pointer to extracted x/y bits ++ ) const ++{ ++ UINT_32 yBit3 = 0; ++ UINT_32 yBit4 = 0; ++ UINT_32 yBit5 = 0; ++ UINT_32 yBit6 = 0; ++ ++ UINT_32 xBit3 = 0; ++ UINT_32 xBit4 = 0; ++ UINT_32 xBit5 = 0; ++ ++ UINT_32 tileSplitRotation; ++ ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ ++ UINT_32 bankRotation = ComputeBankRotation(tileMode, ++ pTileInfo->banks, numPipes); ++ ++ UINT_32 pipeRotation = ComputePipeRotation(tileMode, numPipes); ++ ++ UINT_32 xBit = x / (MicroTileWidth * pTileInfo->bankWidth * numPipes); ++ UINT_32 yBit = y / (MicroTileHeight * pTileInfo->bankHeight); ++ ++ //calculate the bank and pipe before rotation and swizzle ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_2D_TILED_THICK: //fall through ++ case ADDR_TM_2D_TILED_XTHICK: //fall through ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_XTHICK: ++ tileSplitRotation = ((pTileInfo->banks / 2) + 1); ++ break; ++ default: ++ tileSplitRotation = 0; ++ break; ++ } ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ bank ^= tileSplitRotation * tileSlices; ++ if (pipeRotation == 0) ++ { ++ bank ^= bankRotation * (slice / microTileThickness) + bankSwizzle; ++ bank %= pTileInfo->banks; ++ pipe ^= pipeSwizzle; ++ } ++ else ++ { ++ bank ^= bankRotation * (slice / microTileThickness) / numPipes + bankSwizzle; ++ bank %= pTileInfo->banks; ++ pipe ^= pipeRotation * (slice / microTileThickness) + pipeSwizzle; ++ } ++ ++ if (pTileInfo->macroAspectRatio == 1) ++ { ++ switch (pTileInfo->banks) ++ { ++ case 2: ++ yBit3 = _BIT(bank, 0) ^ _BIT(xBit,0); ++ break; ++ case 4: ++ yBit4 = _BIT(bank, 0) ^ _BIT(xBit,0); ++ yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1); ++ break; ++ case 8: ++ yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); ++ yBit5 = _BIT(bank, 0) ^ _BIT(xBit,0); ++ yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ yBit5; ++ break; ++ case 16: ++ yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); ++ yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); ++ yBit6 = _BIT(bank, 0) ^ _BIT(xBit, 0); ++ yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ yBit6; ++ break; ++ default: ++ break; ++ } ++ ++ } ++ else if (pTileInfo->macroAspectRatio == 2) ++ { ++ switch (pTileInfo->banks) ++ { ++ case 2: //xBit3 = yBit3^b0 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,0); ++ break; ++ case 4: //xBit3=yBit4^b0; yBit3=xBit4^b1 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1); ++ yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1); ++ break; ++ case 8: //xBit4, xBit5, yBit5 are known ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); ++ yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); ++ yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ _BIT(yBit, 2); ++ break; ++ case 16://x4,x5,x6,y6 are known ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3); //x3 = y6 ^ b0 ++ yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3 ++ yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = x5 ^ b2 ++ yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ _BIT(yBit, 3); //y5=x4^y6^b1 ++ break; ++ default: ++ break; ++ } ++ } ++ else if (pTileInfo->macroAspectRatio == 4) ++ { ++ switch (pTileInfo->banks) ++ { ++ case 4: //yBit3, yBit4 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1); ++ xBit4 = _BIT(bank, 1) ^ _BIT(yBit,0); ++ break; ++ case 8: //xBit5, yBit4, yBit5 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); ++ yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2); ++ xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit,2); ++ break; ++ case 16: //xBit5, xBit6, yBit5, yBit6 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = b0 ^ y6 ++ xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = b1 ^ y5 ^ y6; ++ yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = b3 ^ x6; ++ yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = b2 ^ x5; ++ break; ++ default: ++ break; ++ } ++ } ++ else if (pTileInfo->macroAspectRatio == 8) ++ { ++ switch (pTileInfo->banks) ++ { ++ case 8: //yBit3, yBit4, yBit5 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); //x3 = b0 ^ y5; ++ xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit, 2);//x4 = b1 ^ y4 ^ y5; ++ xBit5 = _BIT(bank, 2) ^ _BIT(yBit,0); ++ break; ++ case 16: //xBit6, yBit4, yBit5, yBit6 ++ xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = y6 ^ b0 ++ xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = y5 ^ y6 ^ b1 ++ xBit5 = _BIT(bank, 2) ^ _BIT(yBit, 1);//x5 = y4 ^ b2 ++ yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3 ++ break; ++ default: ++ break; ++ } ++ } ++ ++ pOutput->xBits = xBit; ++ pOutput->yBits = yBit; ++ ++ pOutput->xBit3 = xBit3; ++ pOutput->xBit4 = xBit4; ++ pOutput->xBit5 = xBit5; ++ pOutput->yBit3 = yBit3; ++ pOutput->yBit4 = yBit4; ++ pOutput->yBit5 = yBit5; ++ pOutput->yBit6 = yBit6; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlExtractBankPipeSwizzle ++* @brief ++* Entry of EgBasedAddrLib ExtractBankPipeSwizzle ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlExtractBankPipeSwizzle( ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ExtractBankPipeSwizzle(pIn->base256b, ++ pIn->pTileInfo, ++ &pOut->bankSwizzle, ++ &pOut->pipeSwizzle); ++ ++ return ADDR_OK; ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlCombineBankPipeSwizzle ++* @brief ++* Combine bank/pipe swizzle ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlCombineBankPipeSwizzle( ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ ADDR_TILEINFO* pTileInfo, ///< [in] tile info ++ UINT_64 baseAddr, ///< [in] base address ++ UINT_32* pTileSwizzle ///< [out] combined swizzle ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ if (pTileSwizzle) ++ { ++ *pTileSwizzle = GetBankPipeSwizzle(bankSwizzle, pipeSwizzle, baseAddr, pTileInfo); ++ } ++ else ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeBaseSwizzle ++* @brief ++* Compute base swizzle ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeBaseSwizzle( ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut ++ ) const ++{ ++ UINT_32 bankSwizzle = 0; ++ UINT_32 pipeSwizzle = 0; ++ ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; ++ ++ ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); ++ ADDR_ASSERT(pIn->pTileInfo); ++ ++ /// This is a legacy misreading of h/w doc, use it as it doesn't hurt. ++ static const UINT_8 bankRotationArray[4][16] = { ++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_2_BANK ++ { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_4_BANK ++ { 0, 3, 6, 1, 4, 7, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_8_BANK ++ { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }, // ADDR_SURF_16_BANK ++ }; ++ ++ UINT_32 pipes = HwlGetPipes(pTileInfo); ++ UINT_32 banks = pTileInfo ? pTileInfo->banks : 2; ++ UINT_32 hwNumBanks; ++ ++ // Uses less bank swizzle bits ++ if (pIn->option.reduceBankBit && banks > 2) ++ { ++ banks >>= 1; ++ } ++ ++ switch (banks) ++ { ++ case 2: ++ hwNumBanks = 0; ++ break; ++ case 4: ++ hwNumBanks = 1; ++ break; ++ case 8: ++ hwNumBanks = 2; ++ break; ++ case 16: ++ hwNumBanks = 3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ hwNumBanks = 0; ++ break; ++ } ++ ++ if (pIn->option.genOption == ADDR_SWIZZLE_GEN_LINEAR) ++ { ++ bankSwizzle = pIn->surfIndex & (banks - 1); ++ } ++ else // (pIn->option.genOption == ADDR_SWIZZLE_GEN_DEFAULT) ++ { ++ bankSwizzle = bankRotationArray[hwNumBanks][pIn->surfIndex & (banks - 1)]; ++ } ++ ++ if (IsMacro3dTiled(pIn->tileMode)) ++ { ++ pipeSwizzle = pIn->surfIndex & (HwlGetPipes(pTileInfo) - 1); ++ } ++ ++ return HwlCombineBankPipeSwizzle(bankSwizzle, pipeSwizzle, pTileInfo, 0, &pOut->tileSwizzle); ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ExtractBankPipeSwizzle ++* @brief ++* Extract bank/pipe swizzle from base256b ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::ExtractBankPipeSwizzle( ++ UINT_32 base256b, ///< [in] input base256b register value ++ ADDR_TILEINFO* pTileInfo, ///< [in] 2D tile parameters. Client must provide all data ++ UINT_32* pBankSwizzle, ///< [out] bank swizzle ++ UINT_32* pPipeSwizzle ///< [out] pipe swizzle ++ ) const ++{ ++ UINT_32 bankSwizzle = 0; ++ UINT_32 pipeSwizzle = 0; ++ ++ if (base256b != 0) ++ { ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ UINT_32 bankBits = QLog2(pTileInfo->banks); ++ UINT_32 pipeBits = QLog2(numPipes); ++ UINT_32 groupBytes = m_pipeInterleaveBytes; ++ UINT_32 bankInterleave = m_bankInterleave; ++ ++ pipeSwizzle = ++ (base256b / (groupBytes >> 8)) & ((1<<pipeBits)-1); ++ ++ bankSwizzle = ++ (base256b / (groupBytes >> 8) / numPipes / bankInterleave) & ((1 << bankBits) - 1); ++ } ++ ++ *pPipeSwizzle = pipeSwizzle; ++ *pBankSwizzle = bankSwizzle; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::GetBankPipeSwizzle ++* @brief ++* Combine bank/pipe swizzle ++* @return ++* Base256b bits (only filled bank/pipe bits) ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::GetBankPipeSwizzle( ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ UINT_64 baseAddr, ///< [in] base address ++ ADDR_TILEINFO* pTileInfo ///< [in] tile info ++ ) const ++{ ++ UINT_32 pipeBits = QLog2(HwlGetPipes(pTileInfo)); ++ UINT_32 bankInterleaveBits = QLog2(m_bankInterleave); ++ UINT_32 tileSwizzle = pipeSwizzle + ((bankSwizzle << bankInterleaveBits) << pipeBits); ++ ++ baseAddr ^= tileSwizzle * m_pipeInterleaveBytes; ++ baseAddr >>= 8; ++ ++ return static_cast<UINT_32>(baseAddr); ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeSliceTileSwizzle ++* @brief ++* Compute cubemap/3d texture faces/slices tile swizzle ++* @return ++* Tile swizzle ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeSliceTileSwizzle( ++ AddrTileMode tileMode, ///< [in] Tile mode ++ UINT_32 baseSwizzle, ///< [in] Base swizzle ++ UINT_32 slice, ///< [in] Slice index, Cubemap face index, 0 means +X ++ UINT_64 baseAddr, ///< [in] Base address ++ ADDR_TILEINFO* pTileInfo ///< [in] Bank structure ++ ) const ++{ ++ UINT_32 tileSwizzle = 0; ++ ++ if (IsMacroTiled(tileMode)) // Swizzle only for macro tile mode ++ { ++ UINT_32 firstSlice = slice / ComputeSurfaceThickness(tileMode); ++ ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ UINT_32 numBanks = pTileInfo->banks; ++ ++ UINT_32 pipeRotation; ++ UINT_32 bankRotation; ++ ++ UINT_32 bankSwizzle = 0; ++ UINT_32 pipeSwizzle = 0; ++ ++ pipeRotation = ComputePipeRotation(tileMode, numPipes); ++ bankRotation = ComputeBankRotation(tileMode, numBanks, numPipes); ++ ++ if (baseSwizzle != 0) ++ { ++ ExtractBankPipeSwizzle(baseSwizzle, ++ pTileInfo, ++ &bankSwizzle, ++ &pipeSwizzle); ++ } ++ ++ if (pipeRotation == 0) //2D mode ++ { ++ bankSwizzle += firstSlice * bankRotation; ++ bankSwizzle %= numBanks; ++ } ++ else //3D mode ++ { ++ pipeSwizzle += firstSlice * pipeRotation; ++ pipeSwizzle %= numPipes; ++ bankSwizzle += firstSlice * bankRotation / numPipes; ++ bankSwizzle %= numBanks; ++ } ++ ++ tileSwizzle = GetBankPipeSwizzle(bankSwizzle, ++ pipeSwizzle, ++ baseAddr, ++ pTileInfo); ++ } ++ ++ return tileSwizzle; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeQbStereoRightSwizzle ++* ++* @brief ++* Compute right eye swizzle ++* @return ++* swizzle ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::HwlComputeQbStereoRightSwizzle( ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo ///< [in] Surface info, must be valid ++ ) const ++{ ++ UINT_32 bankBits = 0; ++ UINT_32 swizzle = 0; ++ ++ // The assumption is default swizzle for left eye is 0 ++ if (IsMacroTiled(pInfo->tileMode) && pInfo->pStereoInfo && pInfo->pTileInfo) ++ { ++ bankBits = ComputeBankFromCoord(0, pInfo->height, 0, ++ pInfo->tileMode, 0, 0, pInfo->pTileInfo); ++ ++ if (bankBits) ++ { ++ HwlCombineBankPipeSwizzle(bankBits, 0, pInfo->pTileInfo, 0, &swizzle); ++ } ++ } ++ ++ return swizzle; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeBankFromCoord ++* ++* @brief ++* Compute bank number from coordinates ++* @return ++* Bank number ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeBankFromCoord( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ UINT_32 tileSplitSlice, ///< [in] If the size of the pixel offset is larger than the ++ /// tile split size, then the pixel will be moved to a separate ++ /// slice. This value equals pixelOffset / tileSplitBytes ++ /// in this case. Otherwise this is 0. ++ ADDR_TILEINFO* pTileInfo ///< [in] tile info ++ ) const ++{ ++ UINT_32 pipes = HwlGetPipes(pTileInfo); ++ UINT_32 bankBit0 = 0; ++ UINT_32 bankBit1 = 0; ++ UINT_32 bankBit2 = 0; ++ UINT_32 bankBit3 = 0; ++ UINT_32 sliceRotation; ++ UINT_32 tileSplitRotation; ++ UINT_32 bank; ++ UINT_32 numBanks = pTileInfo->banks; ++ UINT_32 bankWidth = pTileInfo->bankWidth; ++ UINT_32 bankHeight = pTileInfo->bankHeight; ++ ++ UINT_32 tx = x / MicroTileWidth / (bankWidth * pipes); ++ UINT_32 ty = y / MicroTileHeight / bankHeight; ++ ++ UINT_32 x3 = _BIT(tx,0); ++ UINT_32 x4 = _BIT(tx,1); ++ UINT_32 x5 = _BIT(tx,2); ++ UINT_32 x6 = _BIT(tx,3); ++ UINT_32 y3 = _BIT(ty,0); ++ UINT_32 y4 = _BIT(ty,1); ++ UINT_32 y5 = _BIT(ty,2); ++ UINT_32 y6 = _BIT(ty,3); ++ ++ switch (numBanks) ++ { ++ case 16: ++ bankBit0 = x3 ^ y6; ++ bankBit1 = x4 ^ y5 ^ y6; ++ bankBit2 = x5 ^ y4; ++ bankBit3 = x6 ^ y3; ++ break; ++ case 8: ++ bankBit0 = x3 ^ y5; ++ bankBit1 = x4 ^ y4 ^ y5; ++ bankBit2 = x5 ^ y3; ++ break; ++ case 4: ++ bankBit0 = x3 ^ y4; ++ bankBit1 = x4 ^ y3; ++ break; ++ case 2: ++ bankBit0 = x3 ^ y3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ ++ bank = bankBit0 | (bankBit1 << 1) | (bankBit2 << 2) | (bankBit3 << 3); ++ ++ //Bits2Number(4, bankBit3, bankBit2, bankBit1, bankBit0); ++ ++ bank = HwlPreAdjustBank((x / MicroTileWidth), bank, pTileInfo); ++ // ++ // Compute bank rotation for the slice. ++ // ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_2D_TILED_THIN1: // fall through ++ case ADDR_TM_2D_TILED_THICK: // fall through ++ case ADDR_TM_2D_TILED_XTHICK: ++ sliceRotation = ((numBanks / 2) - 1) * (slice / microTileThickness); ++ break; ++ case ADDR_TM_3D_TILED_THIN1: // fall through ++ case ADDR_TM_3D_TILED_THICK: // fall through ++ case ADDR_TM_3D_TILED_XTHICK: ++ sliceRotation = ++ Max(1u, (pipes / 2) - 1) * (slice / microTileThickness) / pipes; ++ break; ++ default: ++ sliceRotation = 0; ++ break; ++ } ++ ++ ++ // ++ // Compute bank rotation for the tile split slice. ++ // ++ // The sample slice will be non-zero if samples must be split across multiple slices. ++ // This situation arises when the micro tile size multiplied yBit the number of samples exceeds ++ // the split size (set in GB_ADDR_CONFIG). ++ // ++ switch (tileMode) ++ { ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_2D_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_3D_TILED_THIN1: //fall through ++ tileSplitRotation = ((numBanks / 2) + 1) * tileSplitSlice; ++ break; ++ default: ++ tileSplitRotation = 0; ++ break; ++ } ++ ++ // ++ // Apply bank rotation for the slice and tile split slice. ++ // ++ bank ^= bankSwizzle + sliceRotation; ++ bank ^= tileSplitRotation; ++ ++ bank &= (numBanks - 1); ++ ++ return bank; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeBankFromAddr ++* ++* @brief ++* Compute the bank number from an address ++* @return ++* Bank number ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeBankFromAddr( ++ UINT_64 addr, ///< [in] address ++ UINT_32 numBanks, ///< [in] number of banks ++ UINT_32 numPipes ///< [in] number of pipes ++ ) const ++{ ++ UINT_32 bank; ++ ++ // ++ // The LSBs of the address are arranged as follows: ++ // bank | bankInterleave | pipe | pipeInterleave ++ // ++ // To get the bank number, shift off the pipe interleave, pipe, and bank interlave bits and ++ // mask the bank bits. ++ // ++ bank = static_cast<UINT_32>( ++ (addr >> Log2(m_pipeInterleaveBytes * numPipes * m_bankInterleave)) & ++ (numBanks - 1) ++ ); ++ ++ return bank; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputePipeRotation ++* ++* @brief ++* Compute pipe rotation value ++* @return ++* Pipe rotation ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputePipeRotation( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 numPipes ///< [in] number of pipes ++ ) const ++{ ++ UINT_32 rotation; ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_3D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THICK: //fall through ++ case ADDR_TM_3D_TILED_XTHICK: //fall through ++ case ADDR_TM_PRT_3D_TILED_THIN1: //fall through ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); ++ break; ++ default: ++ rotation = 0; ++ } ++ ++ return rotation; ++} ++ ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeBankRotation ++* ++* @brief ++* Compute bank rotation value ++* @return ++* Bank rotation ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeBankRotation( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 numBanks, ///< [in] number of banks ++ UINT_32 numPipes ///< [in] number of pipes ++ ) const ++{ ++ UINT_32 rotation; ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_2D_TILED_THIN1: // fall through ++ case ADDR_TM_2D_TILED_THICK: // fall through ++ case ADDR_TM_2D_TILED_XTHICK: ++ case ADDR_TM_PRT_2D_TILED_THIN1: ++ case ADDR_TM_PRT_2D_TILED_THICK: ++ // Rotate banks per Z-slice yBit 1 for 4-bank or 3 for 8-bank ++ rotation = numBanks / 2 - 1; ++ break; ++ case ADDR_TM_3D_TILED_THIN1: // fall through ++ case ADDR_TM_3D_TILED_THICK: // fall through ++ case ADDR_TM_3D_TILED_XTHICK: ++ case ADDR_TM_PRT_3D_TILED_THIN1: ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); // rotate pipes & banks ++ break; ++ default: ++ rotation = 0; ++ } ++ ++ return rotation; ++} ++ ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeHtileBytes ++* ++* @brief ++* Compute htile size in bytes ++* ++* @return ++* Htile size in bytes ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::ComputeHtileBytes( ++ UINT_32 pitch, ///< [in] pitch ++ UINT_32 height, ///< [in] height ++ UINT_32 bpp, ///< [in] bits per pixel ++ BOOL_32 isLinear, ///< [in] if it is linear mode ++ UINT_32 numSlices, ///< [in] number of slices ++ UINT_64* sliceBytes, ///< [out] bytes per slice ++ UINT_32 baseAlign ///< [in] base alignments ++ ) const ++{ ++ UINT_64 surfBytes; ++ ++ const UINT_64 HtileCacheLineSize = BITS_TO_BYTES(HtileCacheBits); ++ ++ *sliceBytes = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp / 64); ++ ++ if (m_configFlags.useHtileSliceAlign) ++ { ++ // Align the sliceSize to htilecachelinesize * pipes at first ++ *sliceBytes = PowTwoAlign(*sliceBytes, HtileCacheLineSize * m_pipes); ++ surfBytes = *sliceBytes * numSlices; ++ } ++ else ++ { ++ // Align the surfSize to htilecachelinesize * pipes at last ++ surfBytes = *sliceBytes * numSlices; ++ surfBytes = PowTwoAlign(surfBytes, HtileCacheLineSize * m_pipes); ++ } ++ ++ return surfBytes; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeFmaskInfo ++* ++* @brief ++* Compute fmask sizes include padded pitch, height, slices, total size in bytes, ++* meanwhile output suitable tile mode and alignments as well. Results are returned ++* through output parameters. ++* ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::DispatchComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) ///< [out] output structure ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ ADDR_COMPUTE_SURFACE_INFO_INPUT surfIn = {0}; ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT surfOut = {0}; ++ ++ // Setup input structure ++ surfIn.tileMode = pIn->tileMode; ++ surfIn.width = pIn->pitch; ++ surfIn.height = pIn->height; ++ surfIn.numSlices = pIn->numSlices; ++ surfIn.pTileInfo = pIn->pTileInfo; ++ surfIn.tileType = ADDR_NON_DISPLAYABLE; ++ surfIn.flags.fmask = 1; ++ ++ // Setup output structure ++ surfOut.pTileInfo = pOut->pTileInfo; ++ ++ // Setup hwl specific fields ++ HwlFmaskPreThunkSurfInfo(pIn, pOut, &surfIn, &surfOut); ++ ++ surfIn.bpp = HwlComputeFmaskBits(pIn, &surfIn.numSamples); ++ ++ // ComputeSurfaceInfo needs numSamples in surfOut as surface routines need adjusted numSamples ++ surfOut.numSamples = surfIn.numSamples; ++ ++ retCode = HwlComputeSurfaceInfo(&surfIn, &surfOut); ++ ++ // Save bpp field for surface dump support ++ surfOut.bpp = surfIn.bpp; ++ ++ if (retCode == ADDR_OK) ++ { ++ pOut->bpp = surfOut.bpp; ++ pOut->pitch = surfOut.pitch; ++ pOut->height = surfOut.height; ++ pOut->numSlices = surfOut.depth; ++ pOut->fmaskBytes = surfOut.surfSize; ++ pOut->baseAlign = surfOut.baseAlign; ++ pOut->pitchAlign = surfOut.pitchAlign; ++ pOut->heightAlign = surfOut.heightAlign; ++ ++ if (surfOut.depth > 1) ++ { ++ // For fmask, expNumSlices is stored in depth. ++ pOut->sliceSize = surfOut.surfSize / surfOut.depth; ++ } ++ else ++ { ++ pOut->sliceSize = surfOut.surfSize; ++ } ++ ++ // Save numSamples field for surface dump support ++ pOut->numSamples = surfOut.numSamples; ++ ++ HwlFmaskPostThunkSurfInfo(&surfOut, pOut); ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlFmaskSurfaceInfo ++* @brief ++* Entry of EgBasedAddrLib ComputeFmaskInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure ++ ) ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ ADDR_TILEINFO tileInfo = {0}; ++ ++ // Use internal tile info if pOut does not have a valid pTileInfo ++ if (pOut->pTileInfo == NULL) ++ { ++ pOut->pTileInfo = &tileInfo; ++ } ++ ++ retCode = DispatchComputeFmaskInfo(pIn, pOut); ++ ++ if (retCode == ADDR_OK) ++ { ++ pOut->tileIndex = ++ HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE, ++ pOut->tileIndex); ++ } ++ ++ // Resets pTileInfo to NULL if the internal tile info is used ++ if (pOut->pTileInfo == &tileInfo) ++ { ++ pOut->pTileInfo = NULL; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeFmaskAddrFromCoord ++* @brief ++* Entry of EgBasedAddrLib ComputeFmaskAddrFromCoord ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++#if ADDR_AM_BUILD ++ if ((pIn->x > pIn->pitch) || ++ (pIn->y > pIn->height) || ++ (pIn->numSamples > m_maxSamples) || ++ (pIn->sample >= m_maxSamples)) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ pOut->addr = DispatchComputeFmaskAddrFromCoord(pIn, pOut); ++ } ++#endif ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeFmaskCoordFromAddr ++* @brief ++* Entry of EgBasedAddrLib ComputeFmaskCoordFromAddr ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++#if ADDR_AM_BUILD ++ if ((pIn->bitPosition >= 8) || ++ (pIn->numSamples > m_maxSamples)) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ DispatchComputeFmaskCoordFromAddr(pIn, pOut); ++ } ++#endif ++ ++ return retCode; ++} ++ ++#if ADDR_AM_BUILD ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord ++* ++* @brief ++* Computes the FMASK address and bit position from a coordinate. ++* @return ++* The byte address ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ UINT_32 x = pIn->x; ++ UINT_32 y = pIn->y; ++ UINT_32 slice = pIn->slice; ++ UINT_32 sample = pIn->sample; ++ UINT_32 plane = pIn->plane; ++ UINT_32 pitch = pIn->pitch; ++ UINT_32 height = pIn->height; ++ UINT_32 numSamples = pIn->numSamples; ++ AddrTileMode tileMode = pIn->tileMode; ++ BOOL_32 ignoreSE = pIn->ignoreSE; ++ ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; ++ BOOL_32 resolved = pIn->resolved; ++ ++ UINT_32* pBitPosition = &pOut->bitPosition; ++ UINT_64 addr = 0; ++ ++ ADDR_ASSERT(numSamples > 1); ++ ADDR_ASSERT(ComputeSurfaceThickness(tileMode) == 1); ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ addr = ComputeFmaskAddrFromCoordMicroTiled(x, ++ y, ++ slice, ++ sample, ++ plane, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ resolved, ++ pBitPosition); ++ break; ++ case ADDR_TM_2D_TILED_THIN1: //fall through ++ case ADDR_TM_3D_TILED_THIN1: ++ UINT_32 pipeSwizzle; ++ UINT_32 bankSwizzle; ++ ++ if (m_configFlags.useCombinedSwizzle) ++ { ++ ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, ++ &bankSwizzle, &pipeSwizzle); ++ } ++ else ++ { ++ pipeSwizzle = pIn->pipeSwizzle; ++ bankSwizzle = pIn->bankSwizzle; ++ } ++ ++ addr = ComputeFmaskAddrFromCoordMacroTiled(x, ++ y, ++ slice, ++ sample, ++ plane, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ pipeSwizzle, ++ bankSwizzle, ++ ignoreSE, ++ pTileInfo, ++ resolved, ++ pBitPosition); ++ break; ++ default: ++ *pBitPosition = 0; ++ break; ++ } ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled ++* ++* @brief ++* Computes the FMASK address and bit position from a coordinate for 1D tilied (micro ++* tiled) ++* @return ++* The byte address ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 sample, ///< [in] sample number ++ UINT_32 plane, ///< [in] plane number ++ UINT_32 pitch, ///< [in] surface pitch in pixels ++ UINT_32 height, ///< [in] surface height in pixels ++ UINT_32 numSamples, ///< [in] number of samples ++ AddrTileMode tileMode, ///< [in] tile mode ++ BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask ++ UINT_32* pBitPosition ///< [out] pointer to returned bit position ++ ) const ++{ ++ UINT_64 addr = 0; ++ UINT_32 effectiveBpp; ++ UINT_32 effectiveSamples; ++ ++ // ++ // 2xAA use the same layout as 4xAA ++ // ++ if (numSamples == 2) ++ { ++ numSamples = 4; ++ } ++ ++ // ++ // Compute the number of planes. ++ // ++ if (!resolved) ++ { ++ effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);; ++ effectiveBpp = numSamples; ++ ++ // ++ // Compute the address just like a color surface with numSamples bits per element and ++ // numPlanes samples. ++ // ++ addr = ComputeSurfaceAddrFromCoordMicroTiled(x, ++ y, ++ slice, ++ plane, // sample ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ ADDR_NON_DISPLAYABLE, ++ FALSE, ++ pBitPosition); ++ ++ // ++ // Compute the real bit position. Each (sample, plane) is stored with one bit per sample. ++ // ++ ++ // ++ // Compute the pixel index with in the micro tile ++ // ++ UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x % 8, ++ y % 8, ++ slice, ++ 1, ++ tileMode, ++ ADDR_NON_DISPLAYABLE); ++ ++ *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1); ++ ++ UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition; ++ ++ addr = bitAddr / 8; ++ } ++ else ++ { ++ effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); ++ effectiveSamples = 1; ++ ++ // ++ // Compute the address just like a color surface with numSamples bits per element and ++ // numPlanes samples. ++ // ++ addr = ComputeSurfaceAddrFromCoordMicroTiled(x, ++ y, ++ slice, ++ sample, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ ADDR_NON_DISPLAYABLE, ++ TRUE, ++ pBitPosition); ++ } ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled ++* ++* @brief ++* Computes the FMASK address and bit position from a coordinate for 2D tilied (macro ++* tiled) ++* @return ++* The byte address ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 sample, ///< [in] sample number ++ UINT_32 plane, ///< [in] plane number ++ UINT_32 pitch, ///< [in] surface pitch in pixels ++ UINT_32 height, ///< [in] surface height in pixels ++ UINT_32 numSamples, ///< [in] number of samples ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ UINT_32 bankSwizzle, ///< [in] bank swizzle ++ BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine ++ ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.**All fields to be valid on entry** ++ BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask ++ UINT_32* pBitPosition ///< [out] pointer to returned bit position ++ ) const ++{ ++ UINT_64 addr = 0; ++ UINT_32 effectiveBpp; ++ UINT_32 effectiveSamples; ++ ++ // ++ // 2xAA use the same layout as 4xAA ++ // ++ if (numSamples == 2) ++ { ++ numSamples = 4; ++ } ++ ++ // ++ // Compute the number of planes. ++ // ++ if (!resolved) ++ { ++ effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); ++ effectiveBpp = numSamples; ++ ++ // ++ // Compute the address just like a color surface with numSamples bits per element and ++ // numPlanes samples. ++ // ++ addr = ComputeSurfaceAddrFromCoordMacroTiled(x, ++ y, ++ slice, ++ plane, // sample ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ ADDR_NON_DISPLAYABLE,// isdisp ++ ignoreSE,// ignore_shader ++ FALSE,// depth_sample_order ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pBitPosition); ++ ++ // ++ // Compute the real bit position. Each (sample, plane) is stored with one bit per sample. ++ // ++ ++ ++ // ++ // Compute the pixel index with in the micro tile ++ // ++ UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x , ++ y , ++ slice, ++ effectiveBpp, ++ tileMode, ++ ADDR_NON_DISPLAYABLE); ++ ++ *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1); ++ ++ UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition; ++ ++ addr = bitAddr / 8; ++ ++ } ++ else ++ { ++ effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); ++ effectiveSamples = 1; ++ ++ // ++ // Compute the address just like a color surface with numSamples bits per element and ++ // numPlanes samples. ++ // ++ addr = ComputeSurfaceAddrFromCoordMacroTiled(x, ++ y, ++ slice, ++ sample, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ ADDR_NON_DISPLAYABLE, ++ ignoreSE, ++ TRUE, ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pBitPosition); ++ } ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled ++* ++* @brief ++* Compute (x,y,slice,sample,plane) coordinates from fmask address ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled( ++ UINT_64 addr, ///< [in] byte address ++ UINT_32 bitPosition,///< [in] bit position ++ UINT_32 pitch, ///< [in] pitch in pixels ++ UINT_32 height, ///< [in] height in pixels ++ UINT_32 numSamples, ///< [in] number of samples (of color buffer) ++ AddrTileMode tileMode, ///< [in] tile mode ++ BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask ++ UINT_32* pX, ///< [out] X coord ++ UINT_32* pY, ///< [out] Y coord ++ UINT_32* pSlice, ///< [out] slice index ++ UINT_32* pSample, ///< [out] sample index ++ UINT_32* pPlane ///< [out] plane index ++ ) const ++{ ++ UINT_32 effectiveBpp; ++ UINT_32 effectiveSamples; ++ ++ // 2xAA use the same layout as 4xAA ++ if (numSamples == 2) ++ { ++ numSamples = 4; ++ } ++ ++ if (!resolved) ++ { ++ effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); ++ effectiveBpp = numSamples; ++ ++ ComputeSurfaceCoordFromAddrMicroTiled(addr, ++ bitPosition, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ 0, // tileBase ++ 0, // compBits ++ pX, ++ pY, ++ pSlice, ++ pPlane, ++ ADDR_NON_DISPLAYABLE, // microTileType ++ FALSE // isDepthSampleOrder ++ ); ++ ++ ++ if ( pSample ) ++ { ++ *pSample = bitPosition % numSamples; ++ } ++ } ++ else ++ { ++ effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); ++ effectiveSamples = 1; ++ ++ ComputeSurfaceCoordFromAddrMicroTiled(addr, ++ bitPosition, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ 0, // tileBase ++ 0, // compBits ++ pX, ++ pY, ++ pSlice, ++ pSample, ++ ADDR_NON_DISPLAYABLE, // microTileType ++ TRUE // isDepthSampleOrder ++ ); ++ } ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled ++* ++* @brief ++* Compute (x,y,slice,sample,plane) coordinates from ++* fmask address ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled( ++ UINT_64 addr, ///< [in] byte address ++ UINT_32 bitPosition,///< [in] bit position ++ UINT_32 pitch, ///< [in] pitch in pixels ++ UINT_32 height, ///< [in] height in pixels ++ UINT_32 numSamples, ///< [in] number of samples (of color buffer) ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 pipeSwizzle,///< [in] pipe swizzle ++ UINT_32 bankSwizzle,///< [in] bank swizzle ++ BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine ++ ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry** ++ BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask ++ UINT_32* pX, ///< [out] X coord ++ UINT_32* pY, ///< [out] Y coord ++ UINT_32* pSlice, ///< [out] slice index ++ UINT_32* pSample, ///< [out] sample index ++ UINT_32* pPlane ///< [out] plane index ++ ) const ++{ ++ UINT_32 effectiveBpp; ++ UINT_32 effectiveSamples; ++ ++ // 2xAA use the same layout as 4xAA ++ if (numSamples == 2) ++ { ++ numSamples = 4; ++ } ++ ++ // ++ // Compute the number of planes. ++ // ++ if (!resolved) ++ { ++ effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples); ++ effectiveBpp = numSamples; ++ ++ ComputeSurfaceCoordFromAddrMacroTiled(addr, ++ bitPosition, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ 0, // No tileBase ++ 0, // No compBits ++ ADDR_NON_DISPLAYABLE, ++ ignoreSE, ++ FALSE, ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pX, ++ pY, ++ pSlice, ++ pPlane); ++ ++ if (pSample) ++ { ++ *pSample = bitPosition % numSamples; ++ } ++ } ++ else ++ { ++ effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); ++ effectiveSamples = 1; ++ ++ ComputeSurfaceCoordFromAddrMacroTiled(addr, ++ bitPosition, ++ effectiveBpp, ++ pitch, ++ height, ++ effectiveSamples, ++ tileMode, ++ 0, // No tileBase ++ 0, // No compBits ++ ADDR_NON_DISPLAYABLE, ++ ignoreSE, ++ TRUE, ++ pipeSwizzle, ++ bankSwizzle, ++ pTileInfo, ++ pX, ++ pY, ++ pSlice, ++ pSample); ++ } ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr ++* ++* @brief ++* Compute (x,y,slice,sample,plane) coordinates from ++* fmask address ++* @return ++* N/A ++* ++*************************************************************************************************** ++*/ ++VOID EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ UINT_64 addr = pIn->addr; ++ UINT_32 bitPosition = pIn->bitPosition; ++ UINT_32 pitch = pIn->pitch; ++ UINT_32 height = pIn->height; ++ UINT_32 numSamples = pIn->numSamples; ++ AddrTileMode tileMode = pIn->tileMode; ++ BOOL_32 ignoreSE = pIn->ignoreSE; ++ ADDR_TILEINFO* pTileInfo = pIn->pTileInfo; ++ BOOL_32 resolved = pIn->resolved; ++ ++ UINT_32* pX = &pOut->x; ++ UINT_32* pY = &pOut->y; ++ UINT_32* pSlice = &pOut->slice; ++ UINT_32* pSample = &pOut->sample; ++ UINT_32* pPlane = &pOut->plane; ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_1D_TILED_THIN1: ++ ComputeFmaskCoordFromAddrMicroTiled(addr, ++ bitPosition, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ resolved, ++ pX, ++ pY, ++ pSlice, ++ pSample, ++ pPlane); ++ break; ++ case ADDR_TM_2D_TILED_THIN1://fall through ++ case ADDR_TM_3D_TILED_THIN1: ++ UINT_32 pipeSwizzle; ++ UINT_32 bankSwizzle; ++ ++ if (m_configFlags.useCombinedSwizzle) ++ { ++ ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo, ++ &bankSwizzle, &pipeSwizzle); ++ } ++ else ++ { ++ pipeSwizzle = pIn->pipeSwizzle; ++ bankSwizzle = pIn->bankSwizzle; ++ } ++ ++ ComputeFmaskCoordFromAddrMacroTiled(addr, ++ bitPosition, ++ pitch, ++ height, ++ numSamples, ++ tileMode, ++ pipeSwizzle, ++ bankSwizzle, ++ ignoreSE, ++ pTileInfo, ++ resolved, ++ pX, ++ pY, ++ pSlice, ++ pSample, ++ pPlane); ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ ++ } ++} ++#endif ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples ++* ++* @brief ++* Compute fmask number of planes from number of samples ++* ++* @return ++* Number of planes ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples( ++ UINT_32 numSamples) ///< [in] number of samples ++{ ++ UINT_32 numPlanes; ++ ++ // ++ // FMASK is stored such that each micro tile is composed of elements containing N bits, where ++ // N is the number of samples. There is a micro tile for each bit in the FMASK address, and ++ // micro tiles for each address bit, sometimes referred to as a plane, are stored sequentially. ++ // The FMASK for a 2-sample surface looks like a general surface with 2 bits per element. ++ // The FMASK for a 4-sample surface looks like a general surface with 4 bits per element and ++ // 2 samples. The FMASK for an 8-sample surface looks like a general surface with 8 bits per ++ // element and 4 samples. R6xx and R7xx only stored 3 planes for 8-sample FMASK surfaces. ++ // This was changed for R8xx to simplify the logic in the CB. ++ // ++ switch (numSamples) ++ { ++ case 2: ++ numPlanes = 1; ++ break; ++ case 4: ++ numPlanes = 2; ++ break; ++ case 8: ++ numPlanes = 4; ++ break; ++ default: ++ ADDR_UNHANDLED_CASE(); ++ numPlanes = 0; ++ break; ++ } ++ return numPlanes; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples ++* ++* @brief ++* Compute resolved fmask effective bpp based on number of samples ++* ++* @return ++* bpp ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples( ++ UINT_32 numSamples) ///< number of samples ++{ ++ UINT_32 bpp; ++ ++ // ++ // Resolved FMASK surfaces are generated yBit the CB and read yBit the texture unit ++ // so that the texture unit can read compressed multi-sample color data. ++ // These surfaces store each index value packed per element. ++ // Each element contains at least num_samples * log2(num_samples) bits. ++ // Resolved FMASK surfaces are addressed as follows: ++ // 2-sample Addressed similarly to a color surface with 8 bits per element and 1 sample. ++ // 4-sample Addressed similarly to a color surface with 8 bits per element and 1 sample. ++ // 8-sample Addressed similarly to a color surface with 32 bits per element and 1 sample. ++ ++ switch (numSamples) ++ { ++ case 2: ++ bpp = 8; ++ break; ++ case 4: ++ bpp = 8; ++ break; ++ case 8: ++ bpp = 32; ++ break; ++ default: ++ ADDR_UNHANDLED_CASE(); ++ bpp = 0; ++ break; ++ } ++ return bpp; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::IsTileInfoAllZero ++* ++* @brief ++* Return TRUE if all field are zero ++* @note ++* Since NULL input is consider to be all zero ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::IsTileInfoAllZero( ++ ADDR_TILEINFO* pTileInfo) ++{ ++ BOOL_32 allZero = TRUE; ++ ++ if (pTileInfo) ++ { ++ if ((pTileInfo->banks != 0) || ++ (pTileInfo->bankWidth != 0) || ++ (pTileInfo->bankHeight != 0) || ++ (pTileInfo->macroAspectRatio != 0) || ++ (pTileInfo->tileSplitBytes != 0) || ++ (pTileInfo->pipeConfig != 0) ++ ) ++ { ++ allZero = FALSE; ++ } ++ } ++ ++ return allZero; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlTileInfoEqual ++* ++* @brief ++* Return TRUE if all field are equal ++* @note ++* Only takes care of current HWL's data ++*************************************************************************************************** ++*/ ++BOOL_32 EgBasedAddrLib::HwlTileInfoEqual( ++ const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand ++ const ADDR_TILEINFO* pRight ///<[in] Right compare operand ++ ) const ++{ ++ BOOL_32 equal = FALSE; ++ ++ if (pLeft->banks == pRight->banks && ++ pLeft->bankWidth == pRight->bankWidth && ++ pLeft->bankHeight == pRight->bankHeight && ++ pLeft->macroAspectRatio == pRight->macroAspectRatio && ++ pLeft->tileSplitBytes == pRight->tileSplitBytes) ++ { ++ equal = TRUE; ++ } ++ ++ return equal; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlConvertTileInfoToHW ++* @brief ++* Entry of EgBasedAddrLib ConvertTileInfoToHW ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ ADDR_TILEINFO *pTileInfoIn = pIn->pTileInfo; ++ ADDR_TILEINFO *pTileInfoOut = pOut->pTileInfo; ++ ++ if ((pTileInfoIn != NULL) && (pTileInfoOut != NULL)) ++ { ++ if (pIn->reverse == FALSE) ++ { ++ switch (pTileInfoIn->banks) ++ { ++ case 2: ++ pTileInfoOut->banks = 0; ++ break; ++ case 4: ++ pTileInfoOut->banks = 1; ++ break; ++ case 8: ++ pTileInfoOut->banks = 2; ++ break; ++ case 16: ++ pTileInfoOut->banks = 3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->banks = 0; ++ break; ++ } ++ ++ switch (pTileInfoIn->bankWidth) ++ { ++ case 1: ++ pTileInfoOut->bankWidth = 0; ++ break; ++ case 2: ++ pTileInfoOut->bankWidth = 1; ++ break; ++ case 4: ++ pTileInfoOut->bankWidth = 2; ++ break; ++ case 8: ++ pTileInfoOut->bankWidth = 3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->bankWidth = 0; ++ break; ++ } ++ ++ switch (pTileInfoIn->bankHeight) ++ { ++ case 1: ++ pTileInfoOut->bankHeight = 0; ++ break; ++ case 2: ++ pTileInfoOut->bankHeight = 1; ++ break; ++ case 4: ++ pTileInfoOut->bankHeight = 2; ++ break; ++ case 8: ++ pTileInfoOut->bankHeight = 3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->bankHeight = 0; ++ break; ++ } ++ ++ switch (pTileInfoIn->macroAspectRatio) ++ { ++ case 1: ++ pTileInfoOut->macroAspectRatio = 0; ++ break; ++ case 2: ++ pTileInfoOut->macroAspectRatio = 1; ++ break; ++ case 4: ++ pTileInfoOut->macroAspectRatio = 2; ++ break; ++ case 8: ++ pTileInfoOut->macroAspectRatio = 3; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->macroAspectRatio = 0; ++ break; ++ } ++ ++ switch (pTileInfoIn->tileSplitBytes) ++ { ++ case 64: ++ pTileInfoOut->tileSplitBytes = 0; ++ break; ++ case 128: ++ pTileInfoOut->tileSplitBytes = 1; ++ break; ++ case 256: ++ pTileInfoOut->tileSplitBytes = 2; ++ break; ++ case 512: ++ pTileInfoOut->tileSplitBytes = 3; ++ break; ++ case 1024: ++ pTileInfoOut->tileSplitBytes = 4; ++ break; ++ case 2048: ++ pTileInfoOut->tileSplitBytes = 5; ++ break; ++ case 4096: ++ pTileInfoOut->tileSplitBytes = 6; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->tileSplitBytes = 0; ++ break; ++ } ++ } ++ else ++ { ++ switch (pTileInfoIn->banks) ++ { ++ case 0: ++ pTileInfoOut->banks = 2; ++ break; ++ case 1: ++ pTileInfoOut->banks = 4; ++ break; ++ case 2: ++ pTileInfoOut->banks = 8; ++ break; ++ case 3: ++ pTileInfoOut->banks = 16; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->banks = 2; ++ break; ++ } ++ ++ switch (pTileInfoIn->bankWidth) ++ { ++ case 0: ++ pTileInfoOut->bankWidth = 1; ++ break; ++ case 1: ++ pTileInfoOut->bankWidth = 2; ++ break; ++ case 2: ++ pTileInfoOut->bankWidth = 4; ++ break; ++ case 3: ++ pTileInfoOut->bankWidth = 8; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->bankWidth = 1; ++ break; ++ } ++ ++ switch (pTileInfoIn->bankHeight) ++ { ++ case 0: ++ pTileInfoOut->bankHeight = 1; ++ break; ++ case 1: ++ pTileInfoOut->bankHeight = 2; ++ break; ++ case 2: ++ pTileInfoOut->bankHeight = 4; ++ break; ++ case 3: ++ pTileInfoOut->bankHeight = 8; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->bankHeight = 1; ++ break; ++ } ++ ++ switch (pTileInfoIn->macroAspectRatio) ++ { ++ case 0: ++ pTileInfoOut->macroAspectRatio = 1; ++ break; ++ case 1: ++ pTileInfoOut->macroAspectRatio = 2; ++ break; ++ case 2: ++ pTileInfoOut->macroAspectRatio = 4; ++ break; ++ case 3: ++ pTileInfoOut->macroAspectRatio = 8; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->macroAspectRatio = 1; ++ break; ++ } ++ ++ switch (pTileInfoIn->tileSplitBytes) ++ { ++ case 0: ++ pTileInfoOut->tileSplitBytes = 64; ++ break; ++ case 1: ++ pTileInfoOut->tileSplitBytes = 128; ++ break; ++ case 2: ++ pTileInfoOut->tileSplitBytes = 256; ++ break; ++ case 3: ++ pTileInfoOut->tileSplitBytes = 512; ++ break; ++ case 4: ++ pTileInfoOut->tileSplitBytes = 1024; ++ break; ++ case 5: ++ pTileInfoOut->tileSplitBytes = 2048; ++ break; ++ case 6: ++ pTileInfoOut->tileSplitBytes = 4096; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ pTileInfoOut->tileSplitBytes = 64; ++ break; ++ } ++ } ++ ++ if (pTileInfoIn != pTileInfoOut) ++ { ++ pTileInfoOut->pipeConfig = pTileInfoIn->pipeConfig; ++ } ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeSurfaceInfo ++* @brief ++* Entry of EgBasedAddrLib ComputeSurfaceInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ if (pIn->numSamples < pIn->numFrags) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ ++ ADDR_TILEINFO tileInfo = {0}; ++ ++ if (retCode == ADDR_OK) ++ { ++ // Uses internal tile info if pOut does not have a valid pTileInfo ++ if (pOut->pTileInfo == NULL) ++ { ++ pOut->pTileInfo = &tileInfo; ++ } ++ ++ if (!DispatchComputeSurfaceInfo(pIn, pOut)) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ ++ // Returns an index ++ pOut->tileIndex = HwlPostCheckTileIndex(pOut->pTileInfo, ++ pOut->tileMode, ++ pOut->tileType, ++ pOut->tileIndex); ++ ++ if (IsMacroTiled(pOut->tileMode) && (pOut->macroModeIndex == TileIndexInvalid)) ++ { ++ pOut->macroModeIndex = HwlComputeMacroModeIndex(pOut->tileIndex, ++ pIn->flags, ++ pIn->bpp, ++ pIn->numSamples, ++ pOut->pTileInfo); ++ } ++ ++ // Resets pTileInfo to NULL if the internal tile info is used ++ if (pOut->pTileInfo == &tileInfo) ++ { ++#if DEBUG ++ // Client does not pass in a valid pTileInfo ++ if (IsMacroTiled(pOut->tileMode)) ++ { ++ // If a valid index is returned, then no pTileInfo is okay ++ ADDR_ASSERT(!m_configFlags.useTileIndex || pOut->tileIndex != TileIndexInvalid); ++ ++ if (!IsTileInfoAllZero(pIn->pTileInfo)) ++ { ++ // The initial value of pIn->pTileInfo is copied to tileInfo ++ // We do not expect any of these value to be changed nor any 0 of inputs ++ ADDR_ASSERT(tileInfo.banks == pIn->pTileInfo->banks); ++ ADDR_ASSERT(tileInfo.bankWidth == pIn->pTileInfo->bankWidth); ++ ADDR_ASSERT(tileInfo.bankHeight == pIn->pTileInfo->bankHeight); ++ ADDR_ASSERT(tileInfo.macroAspectRatio == pIn->pTileInfo->macroAspectRatio); ++ ADDR_ASSERT(tileInfo.tileSplitBytes == pIn->pTileInfo->tileSplitBytes); ++ } ++ } ++#endif ++ pOut->pTileInfo = NULL; ++ } ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord ++* @brief ++* Entry of EgBasedAddrLib ComputeSurfaceAddrFromCoord ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ if ( ++#if !ALT_TEST // Overflow test needs this out-of-boundary coord ++ (pIn->x > pIn->pitch) || ++ (pIn->y > pIn->height) || ++#endif ++ (pIn->numSamples > m_maxSamples)) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ pOut->addr = DispatchComputeSurfaceAddrFromCoord(pIn, pOut); ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr ++* @brief ++* Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ if ((pIn->bitPosition >= 8) || ++ (pIn->numSamples > m_maxSamples)) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ DispatchComputeSurfaceCoordFromAddr(pIn, pOut); ++ } ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeSliceTileSwizzle ++* @brief ++* Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSliceTileSwizzle( ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ if (pIn->pTileInfo && (pIn->pTileInfo->banks > 0)) ++ { ++ ++ pOut->tileSwizzle = ComputeSliceTileSwizzle(pIn->tileMode, ++ pIn->baseSwizzle, ++ pIn->slice, ++ pIn->baseAddr, ++ pIn->pTileInfo); ++ } ++ else ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeHtileBpp ++* ++* @brief ++* Compute htile bpp ++* ++* @return ++* Htile bpp ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::HwlComputeHtileBpp( ++ BOOL_32 isWidth8, ///< [in] TRUE if block width is 8 ++ BOOL_32 isHeight8 ///< [in] TRUE if block height is 8 ++ ) const ++{ ++ // only support 8x8 mode ++ ADDR_ASSERT(isWidth8 && isHeight8); ++ return 32; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlComputeHtileBaseAlign ++* ++* @brief ++* Compute htile base alignment ++* ++* @return ++* Htile base alignment ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::HwlComputeHtileBaseAlign( ++ BOOL_32 isTcCompatible, ///< [in] if TC compatible ++ BOOL_32 isLinear, ///< [in] if it is linear mode ++ ADDR_TILEINFO* pTileInfo ///< [in] Tile info ++ ) const ++{ ++ UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo); ++ ++ if (isTcCompatible) ++ { ++ ADDR_ASSERT(pTileInfo != NULL); ++ if (pTileInfo) ++ { ++ baseAlign *= pTileInfo->banks; ++ } ++ } ++ ++ return baseAlign; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled ++* ++* @brief ++* Compute 1D tiled surface pitch alignment, calculation results are returned through ++* output parameters. ++* ++* @return ++* pitch alignment ++*************************************************************************************************** ++*/ ++UINT_32 EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled( ++ 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 ++ ) const ++{ ++ UINT_32 pitchAlign; ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ UINT_32 pixelsPerMicroTile; ++ UINT_32 pixelsPerPipeInterleave; ++ UINT_32 microTilesPerPipeInterleave; ++ ++ // ++ // Special workaround for depth/stencil buffer, use 8 bpp to meet larger requirement for ++ // stencil buffer since pitch alignment is related to bpp. ++ // For a depth only buffer do not set this. ++ // ++ // Note: this actually does not work for mipmap but mipmap depth texture is not really ++ // sampled with mipmap. ++ // ++ if (flags.depth && !flags.noStencil) ++ { ++ bpp = 8; ++ } ++ ++ pixelsPerMicroTile = MicroTilePixels * microTileThickness; ++ pixelsPerPipeInterleave = BYTES_TO_BITS(m_pipeInterleaveBytes) / (bpp * numSamples); ++ microTilesPerPipeInterleave = pixelsPerPipeInterleave / pixelsPerMicroTile; ++ ++ pitchAlign = Max(MicroTileWidth, microTilesPerPipeInterleave * MicroTileWidth); ++ ++ return pitchAlign; ++} ++ ++/** ++*************************************************************************************************** ++* EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled ++* ++* @brief ++* Adjust 1D tiled surface pitch and slice size ++* ++* @return ++* Logical slice size in bytes ++*************************************************************************************************** ++*/ ++UINT_64 EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled( ++ UINT_32 thickness, ///< [in] thickness ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags, ///< [in] surface flags ++ UINT_32 numSamples, ///< [in] number of samples ++ UINT_32 baseAlign, ///< [in] base alignment ++ UINT_32 pitchAlign, ///< [in] pitch alignment ++ UINT_32* pPitch, ///< [in/out] pointer to pitch ++ UINT_32* pHeight ///< [in/out] pointer to height ++ ) const ++{ ++ UINT_64 logicalSliceSize; ++ UINT_64 physicalSliceSize; ++ ++ UINT_32 pitch = *pPitch; ++ UINT_32 height = *pHeight; ++ ++ // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1) ++ logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); ++ ++ // Physical slice: multiplied by thickness ++ physicalSliceSize = logicalSliceSize * thickness; ++ ++ // ++ // R800 will always pad physical slice size to baseAlign which is pipe_interleave_bytes ++ // ++ ADDR_ASSERT((physicalSliceSize % baseAlign) == 0) ++ ++ return logicalSliceSize; ++} ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.h b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.h +new file mode 100644 +index 0000000..84adb66 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/egbaddrlib.h +@@ -0,0 +1,411 @@ ++/* ++ * 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 egbaddrlib.h ++* @brief Contains the EgBasedAddrLib class definition. ++*************************************************************************************************** ++*/ ++ ++#ifndef __EG_BASED_ADDR_LIB_H__ ++#define __EG_BASED_ADDR_LIB_H__ ++ ++#include "addrlib.h" ++ ++ ++/// Structures for functions ++struct CoordFromBankPipe ++{ ++ UINT_32 xBits : 3; ++ UINT_32 yBits : 4; ++ ++ UINT_32 xBit3 : 1; ++ UINT_32 xBit4 : 1; ++ UINT_32 xBit5 : 1; ++ UINT_32 yBit3 : 1; ++ UINT_32 yBit4 : 1; ++ UINT_32 yBit5 : 1; ++ UINT_32 yBit6 : 1; ++}; ++ ++/** ++*************************************************************************************************** ++* @brief This class is the Evergreen based address library ++* @note Abstract class ++*************************************************************************************************** ++*/ ++class EgBasedAddrLib : public AddrLib ++{ ++protected: ++ EgBasedAddrLib(const AddrClient* pClient); ++ virtual ~EgBasedAddrLib(); ++ ++public: ++ ++ /// Surface info functions ++ ++ // NOTE: DispatchComputeSurfaceInfo using TileInfo takes both an input and an output. ++ // On input: ++ // One or more fields may be 0 to be calculated/defaulted - pre-SI h/w. ++ // H/W using tile mode index only accepts none or all 0's - SI and newer h/w. ++ // It then returns the actual tiling configuration used. ++ // Other methods' TileInfo must be valid on entry ++ BOOL_32 DispatchComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ ADDR_E_RETURNCODE DispatchComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); ++ ++protected: ++ // Hwl interface ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeSliceTileSwizzle( ++ const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlExtractBankPipeSwizzle( ++ const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ++ ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlCombineBankPipeSwizzle( ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, ADDR_TILEINFO* pTileInfo, ++ UINT_64 baseAddr, UINT_32* pTileSwizzle) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeBaseSwizzle( ++ const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn, ++ ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const; ++ ++ virtual UINT_32 HwlComputeHtileBpp( ++ BOOL_32 isWidth8, BOOL_32 isHeight8) const; ++ ++ virtual UINT_32 HwlComputeHtileBaseAlign( ++ BOOL_32 isTcCompatible, BOOL_32 isLinear, ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut); ++ ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ virtual BOOL_32 HwlDegradeBaseLevel( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const; ++ ++ virtual UINT_32 HwlComputeQbStereoRightSwizzle( ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo) const; ++ ++ virtual VOID HwlComputePixelCoordFromOffset( ++ UINT_32 offset, UINT_32 bpp, UINT_32 numSamples, ++ AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, ++ AddrTileType microTileType, BOOL_32 isDepthSampleOrder) const; ++ ++ /// Return Cmask block max ++ virtual BOOL_32 HwlGetMaxCmaskBlockMax() const ++ { ++ return 16383; // 14 bits ++ } ++ ++ // Sub-hwl interface ++ /// Pure virtual function to setup tile info (indices) if client requests to do so ++ virtual VOID HwlSetupTileInfo( ++ AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, ++ AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; ++ ++ /// Pure virtual function to get pitch alignment for linear modes ++ virtual UINT_32 HwlGetPitchAlignmentLinear(UINT_32 bpp, ADDR_SURFACE_FLAGS flags) const = 0; ++ ++ /// Pure virtual function to get size adjustment for linear modes ++ virtual UINT_64 HwlGetSizeAdjustmentLinear( ++ AddrTileMode tileMode, ++ UINT_32 bpp, UINT_32 numSamples, UINT_32 baseAlign, UINT_32 pitchAlign, ++ UINT_32 *pPitch, UINT_32 *pHeight, UINT_32 *pHeightAlign) const = 0; ++ ++ virtual UINT_32 HwlGetPitchAlignmentMicroTiled( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples) const; ++ ++ virtual UINT_64 HwlGetSizeAdjustmentMicroTiled( ++ UINT_32 thickness, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, ++ UINT_32 baseAlign, UINT_32 pitchAlign, ++ UINT_32 *pPitch, UINT_32 *pHeight) const; ++ ++ /// Pure virtual function to do extra sanity check ++ virtual BOOL_32 HwlSanityCheckMacroTiled( ++ ADDR_TILEINFO* pTileInfo) const = 0; ++ ++ /// Pure virtual function to check current level to be the last macro tiled one ++ virtual VOID HwlCheckLastMacroTiledLvl( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const = 0; ++ ++ /// Adjusts bank before bank is modified by rotation ++ virtual UINT_32 HwlPreAdjustBank( ++ UINT_32 tileX, UINT_32 bank, ADDR_TILEINFO* pTileInfo) const = 0; ++ ++ virtual VOID HwlComputeSurfaceCoord2DFromBankPipe( ++ AddrTileMode tileMode, UINT_32* pX, UINT_32* pY, UINT_32 slice, ++ UINT_32 bank, UINT_32 pipe, ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, ++ BOOL_32 ignoreSE, ++ ADDR_TILEINFO* pTileInfo) const = 0; ++ ++ virtual BOOL_32 HwlTileInfoEqual( ++ const ADDR_TILEINFO* pLeft, const ADDR_TILEINFO* pRight) const; ++ ++ virtual AddrTileMode HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; ++ ++ virtual INT_32 HwlPostCheckTileIndex( ++ const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, ++ INT curIndex = TileIndexInvalid) const ++ { ++ return TileIndexInvalid; ++ } ++ ++ virtual VOID HwlFmaskPreThunkSurfInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ++ const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const ++ { ++ } ++ ++ virtual VOID HwlFmaskPostThunkSurfInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const ++ { ++ } ++ ++ /// Virtual function to check if the height needs extra padding ++ /// for stereo right eye offset, to avoid bank pipe swizzle ++ virtual BOOL_32 HwlStereoCheckRightOffsetPadding() const ++ { ++ return FALSE; ++ } ++ ++ virtual BOOL_32 HwlReduceBankWidthHeight( ++ UINT_32 tileSize, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, ++ UINT_32 bankHeightAlign, UINT_32 pipes, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ // Protected non-virtual functions ++ ++ /// Mip level functions ++ AddrTileMode ComputeSurfaceMipLevelTileMode( ++ AddrTileMode baseTileMode, UINT_32 bpp, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSlices, UINT_32 numSamples, ++ UINT_32 pitchAlign, UINT_32 heightAlign, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ /// Swizzle functions ++ VOID ExtractBankPipeSwizzle( ++ UINT_32 base256b, ADDR_TILEINFO* pTileInfo, ++ UINT_32* pBankSwizzle, UINT_32* pPipeSwizzle) const; ++ ++ UINT_32 GetBankPipeSwizzle( ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, ++ UINT_64 baseAddr, ADDR_TILEINFO* pTileInfo) const; ++ ++ UINT_32 ComputeSliceTileSwizzle( ++ AddrTileMode tileMode, UINT_32 baseSwizzle, UINT_32 slice, UINT_64 baseAddr, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ /// Addressing functions ++ UINT_32 ComputeBankFromCoord( ++ UINT_32 x, UINT_32 y, UINT_32 slice, ++ AddrTileMode tileMode, UINT_32 bankSwizzle, UINT_32 tileSpitSlice, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ UINT_32 ComputeBankFromAddr( ++ UINT_64 addr, UINT_32 numBanks, UINT_32 numPipes) const; ++ ++ UINT_32 ComputePipeRotation( ++ AddrTileMode tileMode, UINT_32 numPipes) const; ++ ++ UINT_32 ComputeBankRotation( ++ AddrTileMode tileMode, UINT_32 numBanks, ++ UINT_32 numPipes) const; ++ ++ VOID ComputeSurfaceCoord2DFromBankPipe( ++ AddrTileMode tileMode, UINT_32 x, UINT_32 y, UINT_32 slice, ++ UINT_32 bank, UINT_32 pipe, ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, ++ ADDR_TILEINFO* pTileInfo, ++ CoordFromBankPipe *pOutput) const; ++ ++ /// Htile/Cmask functions ++ UINT_64 ComputeHtileBytes( ++ UINT_32 pitch, UINT_32 height, UINT_32 bpp, ++ BOOL_32 isLinear, UINT_32 numSlices, UINT_64* sliceBytes, UINT_32 baseAlign) const; ++ ++ // Static functions ++ static BOOL_32 IsTileInfoAllZero(ADDR_TILEINFO* pTileInfo); ++ static UINT_32 ComputeFmaskNumPlanesFromNumSamples(UINT_32 numSamples); ++ static UINT_32 ComputeFmaskResolvedBppFromNumSamples(UINT_32 numSamples); ++ ++private: ++ ++ BOOL_32 ComputeSurfaceInfoLinear( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ++ UINT_32 padDims) const; ++ ++ BOOL_32 ComputeSurfaceInfoMicroTiled( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ++ UINT_32 padDims, ++ AddrTileMode expTileMode) const; ++ ++ BOOL_32 ComputeSurfaceInfoMacroTiled( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ++ UINT_32 padDims, ++ AddrTileMode expTileMode) const; ++ ++ BOOL_32 ComputeSurfaceAlignmentsLinear( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, ++ UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; ++ ++ BOOL_32 ComputeSurfaceAlignmentsMicroTiled( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, ++ UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; ++ ++ BOOL_32 ComputeSurfaceAlignmentsMacroTiled( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, ++ UINT_32 mipLevel, UINT_32 numSamples, ++ ADDR_TILEINFO* pTileInfo, ++ UINT_32* pBaseAlign, UINT_32* pPitchAlign, UINT_32* pHeightAlign) const; ++ ++ /// Surface addressing functions ++ UINT_64 DispatchComputeSurfaceAddrFromCoord( ++ const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ VOID DispatchComputeSurfaceCoordFromAddr( ++ const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ UINT_64 ComputeSurfaceAddrFromCoordMicroTiled( ++ UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, ++ AddrTileType microTileType, BOOL_32 isDepthSampleOrder, ++ UINT_32* pBitPosition) const; ++ ++ UINT_64 ComputeSurfaceAddrFromCoordMacroTiled( ++ UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, ++ AddrTileType microTileType, BOOL_32 ignoreSE, BOOL_32 isDepthSampleOrder, ++ UINT_32 pipeSwizzle, UINT_32 bankSwizzle, ++ ADDR_TILEINFO* pTileInfo, ++ UINT_32* pBitPosition) const; ++ ++ VOID ComputeSurfaceCoordFromAddrMacroTiled( ++ UINT_64 addr, UINT_32 bitPosition, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, UINT_32 tileBase, UINT_32 compBits, ++ AddrTileType microTileType, BOOL_32 ignoreSE, BOOL_32 isDepthSampleOrder, ++ UINT_32 pipeSwizzle, UINT_32 bankSwizzle, ++ ADDR_TILEINFO* pTileInfo, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample) const; ++ ++ /// Fmask functions ++ UINT_64 DispatchComputeFmaskAddrFromCoord( ++ const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut) const; ++ ++ VOID DispatchComputeFmaskCoordFromAddr( ++ const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ++ ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut) const; ++ ++ // FMASK related methods - private ++ UINT_64 ComputeFmaskAddrFromCoordMicroTiled( ++ UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, UINT_32 plane, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSamples, AddrTileMode tileMode, ++ BOOL_32 resolved, UINT_32* pBitPosition) const; ++ ++ VOID ComputeFmaskCoordFromAddrMicroTiled( ++ UINT_64 addr, UINT_32 bitPosition, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, BOOL_32 resolved, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, UINT_32* pPlane) const; ++ ++ VOID ComputeFmaskCoordFromAddrMacroTiled( ++ UINT_64 addr, UINT_32 bitPosition, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSamples, AddrTileMode tileMode, ++ UINT_32 pipeSwizzle, UINT_32 bankSwizzle, ++ BOOL_32 ignoreSE, ++ ADDR_TILEINFO* pTileInfo, ++ BOOL_32 resolved, ++ UINT_32* pX, UINT_32* pY, UINT_32* pSlice, UINT_32* pSample, UINT_32* pPlane) const; ++ ++ UINT_64 ComputeFmaskAddrFromCoordMacroTiled( ++ UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 sample, UINT_32 plane, ++ UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ AddrTileMode tileMode, UINT_32 pipeSwizzle, UINT_32 bankSwizzle, ++ BOOL_32 ignoreSE, ++ ADDR_TILEINFO* pTileInfo, ++ BOOL_32 resolved, ++ UINT_32* pBitPosition) const; ++ ++ /// Sanity check functions ++ BOOL_32 SanityCheckMacroTiled( ++ ADDR_TILEINFO* pTileInfo) const; ++ ++protected: ++ UINT_32 m_ranks; ///< Number of ranks - MC_ARB_RAMCFG.NOOFRANK ++ UINT_32 m_logicalBanks; ///< Logical banks = m_banks * m_ranks if m_banks != 16 ++ UINT_32 m_bankInterleave; ///< Bank interleave, as a multiple of pipe interleave size ++}; ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.cpp b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.cpp +new file mode 100644 +index 0000000..a858b55 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.cpp +@@ -0,0 +1,2818 @@ ++/* ++ * 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 siaddrlib.cpp ++* @brief Contains the implementation for the SIAddrLib class. ++*************************************************************************************************** ++*/ ++ ++#include "siaddrlib.h" ++ ++#include "si_gb_reg.h" ++ ++#include "si_ci_vi_merged_enum.h" ++ ++#if BRAHMA_BUILD ++#include "amdgpu_id.h" ++#else ++#include "si_id.h" ++#endif ++ ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++/////////////////////////////////////////////////////////////////////////////////////////////////// ++ ++/** ++*************************************************************************************************** ++* AddrSIHwlInit ++* ++* @brief ++* Creates an SIAddrLib object. ++* ++* @return ++* Returns an SIAddrLib object pointer. ++*************************************************************************************************** ++*/ ++AddrLib* AddrSIHwlInit(const AddrClient* pClient) ++{ ++ return SIAddrLib::CreateObj(pClient); ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::SIAddrLib ++* ++* @brief ++* Constructor ++* ++*************************************************************************************************** ++*/ ++SIAddrLib::SIAddrLib(const AddrClient* pClient) : ++ EgBasedAddrLib(pClient), ++ m_noOfEntries(0) ++{ ++ m_class = SI_ADDRLIB; ++ memset(&m_settings, 0, sizeof(m_settings)); ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::~SIAddrLib ++* ++* @brief ++* Destructor ++*************************************************************************************************** ++*/ ++SIAddrLib::~SIAddrLib() ++{ ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetPipes ++* ++* @brief ++* Get number pipes ++* @return ++* num pipes ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlGetPipes( ++ const ADDR_TILEINFO* pTileInfo ///< [in] Tile info ++ ) const ++{ ++ UINT_32 numPipes; ++ ++ if (pTileInfo) ++ { ++ numPipes = GetPipePerSurf(pTileInfo->pipeConfig); ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ numPipes = m_pipes; // Suppose we should still have a global pipes ++ } ++ ++ return numPipes; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::GetPipePerSurf ++* @brief ++* get pipe num base on inputing tileinfo->pipeconfig ++* @return ++* pipe number ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::GetPipePerSurf( ++ AddrPipeCfg pipeConfig ///< [in] pipe config ++ ) const ++{ ++ UINT_32 numPipes = 0; ++ ++ switch (pipeConfig) ++ { ++ case ADDR_PIPECFG_P2: ++ numPipes = 2; ++ break; ++ case ADDR_PIPECFG_P4_8x16: ++ case ADDR_PIPECFG_P4_16x16: ++ case ADDR_PIPECFG_P4_16x32: ++ case ADDR_PIPECFG_P4_32x32: ++ numPipes = 4; ++ break; ++ case ADDR_PIPECFG_P8_16x16_8x16: ++ case ADDR_PIPECFG_P8_16x32_8x16: ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ case ADDR_PIPECFG_P8_16x32_16x16: ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P16_32x32_8x16: ++ case ADDR_PIPECFG_P16_32x32_16x16: ++ numPipes = 16; ++ break; ++ default: ++ ADDR_ASSERT(!"Invalid pipe config"); ++ numPipes = m_pipes; ++ } ++ return numPipes; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::ComputePipeFromCoord ++* ++* @brief ++* Compute pipe number from coordinates ++* @return ++* Pipe number ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::ComputePipeFromCoord( ++ UINT_32 x, ///< [in] x coordinate ++ UINT_32 y, ///< [in] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 pipeSwizzle, ///< [in] pipe swizzle ++ BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored ++ ADDR_TILEINFO* pTileInfo ///< [in] Tile info ++ ) const ++{ ++ UINT_32 pipe; ++ UINT_32 pipeBit0 = 0; ++ UINT_32 pipeBit1 = 0; ++ UINT_32 pipeBit2 = 0; ++ UINT_32 pipeBit3 = 0; ++ UINT_32 sliceRotation; ++ UINT_32 numPipes = 0; ++ ++ UINT_32 tx = x / MicroTileWidth; ++ UINT_32 ty = y / MicroTileHeight; ++ UINT_32 x3 = _BIT(tx,0); ++ UINT_32 x4 = _BIT(tx,1); ++ UINT_32 x5 = _BIT(tx,2); ++ UINT_32 x6 = _BIT(tx,3); ++ UINT_32 y3 = _BIT(ty,0); ++ UINT_32 y4 = _BIT(ty,1); ++ UINT_32 y5 = _BIT(ty,2); ++ UINT_32 y6 = _BIT(ty,3); ++ ++ switch (pTileInfo->pipeConfig) ++ { ++ case ADDR_PIPECFG_P2: ++ pipeBit0 = x3 ^ y3; ++ numPipes = 2; ++ break; ++ case ADDR_PIPECFG_P4_8x16: ++ pipeBit0 = x4 ^ y3; ++ pipeBit1 = x3 ^ y4; ++ numPipes = 4; ++ break; ++ case ADDR_PIPECFG_P4_16x16: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x4 ^ y4; ++ numPipes = 4; ++ break; ++ case ADDR_PIPECFG_P4_16x32: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x4 ^ y5; ++ numPipes = 4; ++ break; ++ case ADDR_PIPECFG_P4_32x32: ++ pipeBit0 = x3 ^ y3 ^ x5; ++ pipeBit1 = x5 ^ y5; ++ numPipes = 4; ++ break; ++ case ADDR_PIPECFG_P8_16x16_8x16: ++ pipeBit0 = x4 ^ y3 ^ x5; ++ pipeBit1 = x3 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_16x32_8x16: ++ pipeBit0 = x4 ^ y3 ^ x5; ++ pipeBit1 = x3 ^ y4; ++ pipeBit2 = x4 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_16x32_16x16: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x5 ^ y4; ++ pipeBit2 = x4 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ pipeBit0 = x4 ^ y3 ^ x5; ++ pipeBit1 = x3 ^ y4; ++ pipeBit2 = x5 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x4 ^ y4; ++ pipeBit2 = x5 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x4 ^ y6; ++ pipeBit2 = x5 ^ y5; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ pipeBit0 = x3 ^ y3 ^ x5; ++ pipeBit1 = x6 ^ y5; ++ pipeBit2 = x5 ^ y6; ++ numPipes = 8; ++ break; ++ case ADDR_PIPECFG_P16_32x32_8x16: ++ pipeBit0 = x4 ^ y3; ++ pipeBit1 = x3 ^ y4; ++ pipeBit2 = x5 ^ y6; ++ pipeBit3 = x6 ^ y5; ++ numPipes = 16; ++ break; ++ case ADDR_PIPECFG_P16_32x32_16x16: ++ pipeBit0 = x3 ^ y3 ^ x4; ++ pipeBit1 = x4 ^ y4; ++ pipeBit2 = x5 ^ y6; ++ pipeBit3 = x6 ^ y5; ++ numPipes = 16; ++ break; ++ default: ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ pipe = pipeBit0 | (pipeBit1 << 1) | (pipeBit2 << 2) | (pipeBit3 << 3); ++ ++ UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode); ++ ++ // ++ // Apply pipe rotation for the slice. ++ // ++ switch (tileMode) ++ { ++ case ADDR_TM_3D_TILED_THIN1: //fall through thin ++ case ADDR_TM_3D_TILED_THICK: //fall through thick ++ case ADDR_TM_3D_TILED_XTHICK: ++ sliceRotation = ++ Max(1, static_cast<INT_32>(numPipes / 2) - 1) * (slice / microTileThickness); ++ break; ++ default: ++ sliceRotation = 0; ++ break; ++ } ++ pipeSwizzle += sliceRotation; ++ pipeSwizzle &= (numPipes - 1); ++ ++ pipe = pipe ^ pipeSwizzle; ++ ++ return pipe; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::ComputeTileCoordFromPipeAndElemIdx ++* ++* @brief ++* Compute (x,y) of a tile within a macro tile from address ++* @return ++* Pipe number ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::ComputeTileCoordFromPipeAndElemIdx( ++ UINT_32 elemIdx, ///< [in] per pipe element index within a macro tile ++ UINT_32 pipe, ///< [in] pipe index ++ AddrPipeCfg pipeCfg, ///< [in] pipe config ++ UINT_32 pitchInMacroTile, ///< [in] surface pitch in macro tile ++ UINT_32 x, ///< [in] x coordinate of the (0,0) tile in a macro tile ++ UINT_32 y, ///< [in] y coordinate of the (0,0) tile in a macro tile ++ UINT_32* pX, ///< [out] x coordinate ++ UINT_32* pY ///< [out] y coordinate ++ ) const ++{ ++ UINT_32 pipebit0 = _BIT(pipe,0); ++ UINT_32 pipebit1 = _BIT(pipe,1); ++ UINT_32 pipebit2 = _BIT(pipe,2); ++ UINT_32 pipebit3 = _BIT(pipe,3); ++ UINT_32 elemIdx0 = _BIT(elemIdx,0); ++ UINT_32 elemIdx1 = _BIT(elemIdx,1); ++ UINT_32 elemIdx2 = _BIT(elemIdx,2); ++ UINT_32 x3 = 0; ++ UINT_32 x4 = 0; ++ UINT_32 x5 = 0; ++ UINT_32 x6 = 0; ++ UINT_32 y3 = 0; ++ UINT_32 y4 = 0; ++ UINT_32 y5 = 0; ++ UINT_32 y6 = 0; ++ ++ switch(pipeCfg) ++ { ++ case ADDR_PIPECFG_P2: ++ x4 = elemIdx2; ++ y4 = elemIdx1 ^ x4; ++ y3 = elemIdx0 ^ x4; ++ x3 = pipebit0 ^ y3; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P4_8x16: ++ x4 = elemIdx1; ++ y4 = elemIdx0 ^ x4; ++ x3 = pipebit1 ^ y4; ++ y3 = pipebit0 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P4_16x16: ++ x4 = elemIdx1; ++ y3 = elemIdx0 ^ x4; ++ y4 = pipebit1 ^ x4; ++ x3 = pipebit0 ^ y3 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P4_16x32: ++ x3 = elemIdx0 ^ pipebit0; ++ y5 = _BIT(y,5); ++ x4 = pipebit1 ^ y5; ++ y3 = pipebit0 ^ x3 ^ x4; ++ y4 = elemIdx1 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P4_32x32: ++ x4 = elemIdx2; ++ y3 = elemIdx0 ^ x4; ++ y4 = elemIdx1 ^ x4; ++ if((pitchInMacroTile % 2) == 0) ++ { //even ++ y5 = _BIT(y,5); ++ x5 = pipebit1 ^ y5; ++ x3 = pipebit0 ^ y3 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ else ++ { //odd ++ x5 = _BIT(x,5); ++ x3 = pipebit0 ^ y3 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P8_16x16_8x16: ++ x4 = elemIdx0; ++ y5 = _BIT(y,5); ++ x5 = _BIT(x,5); ++ x3 = pipebit1 ^ y5; ++ y4 = pipebit2 ^ x4; ++ y3 = pipebit0 ^ x5 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P8_16x32_8x16: ++ x3 = elemIdx0; ++ y4 = pipebit1 ^ x3; ++ y5 = _BIT(y,5); ++ x5 = _BIT(x,5); ++ x4 = pipebit2 ^ y5; ++ y3 = pipebit0 ^ x4 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ x4 = elemIdx1; ++ y4 = elemIdx0 ^ x4; ++ x3 = pipebit1 ^ y4; ++ if((pitchInMacroTile % 2) == 0) ++ { //even ++ y5 = _BIT(y,5); ++ x5 = _BIT(x,5); ++ x5 = pipebit2 ^ y5; ++ y3 = pipebit0 ^ x4 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ else ++ { //odd ++ x5 = _BIT(x,5); ++ y3 = pipebit0 ^ x4 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P8_16x32_16x16: ++ x3 = elemIdx0; ++ x5 = _BIT(x,5); ++ y5 = _BIT(y,5); ++ x4 = pipebit2 ^ y5; ++ y4 = pipebit1 ^ x5; ++ y3 = pipebit0 ^ x3 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ x4 = elemIdx1; ++ y3 = elemIdx0 ^ x4; ++ x3 = y3^x4^pipebit0; ++ y4 = pipebit1 ^ x4; ++ if((pitchInMacroTile % 2) == 0) ++ { //even ++ y5 = _BIT(y,5); ++ x5 = pipebit2 ^ y5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ else ++ { //odd ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ if((pitchInMacroTile % 2) == 0) ++ { //even ++ y5 = _BIT(y,5); ++ y6 = _BIT(y,6); ++ x4 = pipebit1 ^ y6; ++ y3 = elemIdx0 ^ x4; ++ y4 = elemIdx1 ^ x4; ++ x3 = pipebit0 ^ y3 ^ x4; ++ x5 = pipebit2 ^ y5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ else ++ { //odd ++ y6 = _BIT(y,6); ++ x4 = pipebit1 ^ y6; ++ y3 = elemIdx0 ^ x4; ++ y4 = elemIdx1 ^ x4; ++ x3 = pipebit0 ^ y3 ^ x4; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(2, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ x4 = elemIdx2; ++ y3 = elemIdx0 ^ x4; ++ y4 = elemIdx1 ^ x4; ++ if((pitchInMacroTile % 4) == 0) ++ { //multiple of 4 ++ y5 = _BIT(y,5); ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ x6 = pipebit1 ^ y5; ++ x3 = pipebit0 ^ y3 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(4, x6, x5, x4, x3); ++ } ++ else ++ { ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ x3 = pipebit0 ^ y3 ^ x5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P16_32x32_8x16: ++ x4 = elemIdx1; ++ y4 = elemIdx0 ^ x4; ++ y3 = pipebit0 ^ x4; ++ x3 = pipebit1 ^ y4; ++ if((pitchInMacroTile % 4) == 0) ++ { //multiple of 4 ++ y5 = _BIT(y,5); ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ x6 = pipebit3 ^ y5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(4, x6, x5,x4, x3); ++ } ++ else ++ { ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ break; ++ case ADDR_PIPECFG_P16_32x32_16x16: ++ x4 = elemIdx1; ++ y3 = elemIdx0 ^ x4; ++ y4 = pipebit1 ^ x4; ++ x3 = pipebit0 ^ y3 ^ x4; ++ if((pitchInMacroTile % 4) == 0) ++ { //multiple of 4 ++ y5 = _BIT(y,5); ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ x6 = pipebit3 ^ y5; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(4, x6, x5, x4, x3); ++ } ++ else ++ { ++ y6 = _BIT(y,6); ++ x5 = pipebit2 ^ y6; ++ *pY = Bits2Number(2, y4, y3); ++ *pX = Bits2Number(3, x5, x4, x3); ++ } ++ break; ++ default: ++ ADDR_UNHANDLED_CASE(); ++ } ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::TileCoordToMaskElementIndex ++* ++* @brief ++* Compute element index from coordinates in tiles ++* @return ++* Element index ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::TileCoordToMaskElementIndex( ++ UINT_32 tx, ///< [in] x coord, in Tiles ++ UINT_32 ty, ///< [in] y coord, in Tiles ++ AddrPipeCfg pipeConfig, ///< [in] pipe config ++ UINT_32* macroShift, ///< [out] macro shift ++ UINT_32* elemIdxBits ///< [out] tile offset bits ++ ) const ++{ ++ UINT_32 elemIdx = 0; ++ UINT_32 elemIdx0, elemIdx1, elemIdx2; ++ UINT_32 tx0, tx1; ++ UINT_32 ty0, ty1; ++ ++ tx0 = _BIT(tx,0); ++ tx1 = _BIT(tx,1); ++ ty0 = _BIT(ty,0); ++ ty1 = _BIT(ty,1); ++ ++ switch(pipeConfig) ++ { ++ case ADDR_PIPECFG_P2: ++ *macroShift = 3; ++ *elemIdxBits =3; ++ elemIdx2 = tx1; ++ elemIdx1 = tx1 ^ ty1; ++ elemIdx0 = tx1 ^ ty0; ++ elemIdx = Bits2Number(3,elemIdx2,elemIdx1,elemIdx0); ++ break; ++ case ADDR_PIPECFG_P4_8x16: ++ *macroShift = 2; ++ *elemIdxBits =2; ++ elemIdx1 = tx1; ++ elemIdx0 = tx1 ^ ty1; ++ elemIdx = Bits2Number(2,elemIdx1,elemIdx0); ++ break; ++ case ADDR_PIPECFG_P4_16x16: ++ *macroShift = 2; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P4_16x32: ++ *macroShift = 2; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1^ty1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P4_32x32: ++ *macroShift = 2; ++ *elemIdxBits =3; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1^ty1; ++ elemIdx2 = tx1; ++ elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P8_16x16_8x16: ++ *macroShift = 1; ++ *elemIdxBits =1; ++ elemIdx0 = tx1; ++ elemIdx = elemIdx0; ++ break; ++ case ADDR_PIPECFG_P8_16x32_8x16: ++ *macroShift = 1; ++ *elemIdxBits =1; ++ elemIdx0 = tx0; ++ elemIdx = elemIdx0; ++ break; ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ *macroShift = 1; ++ *elemIdxBits =2; ++ elemIdx1 = tx1; ++ elemIdx0 = tx1^ty1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P8_16x32_16x16: ++ *macroShift = 1; ++ *elemIdxBits =1; ++ elemIdx0 = tx0; ++ elemIdx = elemIdx0; ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ *macroShift = 1; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ *macroShift = 1; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1^ty1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ *macroShift = 1; ++ *elemIdxBits =3; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1^ty1; ++ elemIdx2 = tx1; ++ elemIdx = Bits2Number(3, elemIdx2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P16_32x32_8x16: ++ *macroShift = 0; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty1; ++ elemIdx1 = tx1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ case ADDR_PIPECFG_P16_32x32_16x16: ++ *macroShift = 0; ++ *elemIdxBits =2; ++ elemIdx0 = tx1^ty0; ++ elemIdx1 = tx1; ++ elemIdx = Bits2Number(2, elemIdx1, elemIdx0); ++ break; ++ default: ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ return elemIdx; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::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 SIAddrLib::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(pTileInfo != NULL); ++ UINT_32 macroWidth; ++ UINT_32 macroHeight; ++ ++ /// In linear mode, the htile or cmask buffer must be padded out to 4 tiles ++ /// but for P8_32x64_32x32, it must be padded out to 8 tiles ++ /// Actually there are more pipe configs which need 8-tile padding but SI family ++ /// has a bug which is fixed in CI family ++ if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) || ++ (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || ++ (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x32_16x16)) ++ { ++ macroWidth = 8*MicroTileWidth; ++ macroHeight = 8*MicroTileHeight; ++ } ++ else ++ { ++ macroWidth = 4*MicroTileWidth; ++ macroHeight = 4*MicroTileHeight; ++ } ++ ++ *pMacroWidth = macroWidth; ++ *pMacroHeight = macroHeight; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeHtileBytes ++* ++* @brief ++* Compute htile size in bytes ++* ++* @return ++* Htile size in bytes ++*************************************************************************************************** ++*/ ++UINT_64 SIAddrLib::HwlComputeHtileBytes( ++ UINT_32 pitch, ///< [in] pitch ++ UINT_32 height, ///< [in] height ++ UINT_32 bpp, ///< [in] bits per pixel ++ BOOL_32 isLinear, ///< [in] if it is linear mode ++ UINT_32 numSlices, ///< [in] number of slices ++ UINT_64* pSliceBytes, ///< [out] bytes per slice ++ UINT_32 baseAlign ///< [in] base alignments ++ ) const ++{ ++ return ComputeHtileBytes(pitch, height, bpp, isLinear, numSlices, pSliceBytes, baseAlign); ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeXmaskAddrFromCoord ++* ++* @brief ++* Compute address from coordinates for htile/cmask ++* @return ++* Byte address ++*************************************************************************************************** ++*/ ++UINT_64 SIAddrLib::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_32 tx = x / MicroTileWidth; ++ UINT_32 ty = y / MicroTileHeight; ++ UINT_32 newPitch; ++ UINT_32 newHeight; ++ UINT_64 totalBytes; ++ UINT_32 macroWidth; ++ UINT_32 macroHeight; ++ UINT_64 pSliceBytes; ++ UINT_32 pBaseAlign; ++ UINT_32 tileNumPerPipe; ++ UINT_32 elemBits; ++ ++ if (factor == 2) //CMASK ++ { ++ ADDR_CMASK_FLAGS flags = {{0}}; ++ ++ tileNumPerPipe = 256; ++ ++ ComputeCmaskInfo(flags, ++ pitch, ++ height, ++ numSlices, ++ isLinear, ++ pTileInfo, ++ &newPitch, ++ &newHeight, ++ &totalBytes, ++ ¯oWidth, ++ ¯oHeight); ++ elemBits = CmaskElemBits; ++ } ++ else //HTile ++ { ++ ADDR_HTILE_FLAGS flags = {{0}}; ++ ++ tileNumPerPipe = 512; ++ ++ ComputeHtileInfo(flags, ++ pitch, ++ height, ++ numSlices, ++ isLinear, ++ TRUE, ++ TRUE, ++ pTileInfo, ++ &newPitch, ++ &newHeight, ++ &totalBytes, ++ ¯oWidth, ++ ¯oHeight, ++ &pSliceBytes, ++ &pBaseAlign); ++ elemBits = 32; ++ } ++ ++ const UINT_32 pitchInTile = newPitch / MicroTileWidth; ++ const UINT_32 heightInTile = newHeight / MicroTileWidth; ++ UINT_64 macroOffset; // Per pipe starting offset of the macro tile in which this tile lies. ++ UINT_64 microNumber; // Per pipe starting offset of the macro tile in which this tile lies. ++ UINT_32 microX; ++ UINT_32 microY; ++ UINT_64 microOffset; ++ UINT_32 microShift; ++ UINT_64 totalOffset; ++ UINT_32 elemIdxBits; ++ UINT_32 elemIdx = ++ TileCoordToMaskElementIndex(tx, ty, pTileInfo->pipeConfig, µShift, &elemIdxBits); ++ ++ UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ ++ if (isLinear) ++ { //linear addressing ++ // Linear addressing is extremelly wasting memory if slice > 1, since each pipe has the full ++ // slice memory foot print instead of divided by numPipes. ++ microX = tx / 4; // Macro Tile is 4x4 ++ microY = ty / 4 ; ++ microNumber = static_cast<UINT_64>(microX + microY * (pitchInTile / 4)) << microShift; ++ ++ UINT_32 sliceBits = pitchInTile * heightInTile; ++ ++ // do htile single slice alignment if the flag is true ++ if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile ++ { ++ sliceBits = PowTwoAlign(sliceBits, BITS_TO_BYTES(HtileCacheBits) * numPipes / elemBits); ++ } ++ macroOffset = slice * (sliceBits / numPipes) * elemBits ; ++ } ++ else ++ { //tiled addressing ++ const UINT_32 macroWidthInTile = macroWidth / MicroTileWidth; // Now in unit of Tiles ++ const UINT_32 macroHeightInTile = macroHeight / MicroTileHeight; ++ const UINT_32 pitchInCL = pitchInTile / macroWidthInTile; ++ const UINT_32 heightInCL = heightInTile / macroHeightInTile; ++ ++ const UINT_32 macroX = x / macroWidth; ++ const UINT_32 macroY = y / macroHeight; ++ const UINT_32 macroNumber = macroX + macroY * pitchInCL + slice * pitchInCL * heightInCL; ++ ++ // Per pipe starting offset of the cache line in which this tile lies. ++ microX = (x % macroWidth) / MicroTileWidth / 4; // Macro Tile is 4x4 ++ microY = (y % macroHeight) / MicroTileHeight / 4 ; ++ microNumber = static_cast<UINT_64>(microX + microY * (macroWidth / MicroTileWidth / 4)) << microShift; ++ ++ macroOffset = macroNumber * tileNumPerPipe * elemBits; ++ } ++ ++ if(elemIdxBits == microShift) ++ { ++ microNumber += elemIdx; ++ } ++ else ++ { ++ microNumber >>= elemIdxBits; ++ microNumber <<= elemIdxBits; ++ microNumber += elemIdx; ++ } ++ ++ microOffset = elemBits * microNumber; ++ totalOffset = microOffset + macroOffset; ++ ++ UINT_32 pipe = ComputePipeFromCoord(x, y, 0, ADDR_TM_2D_TILED_THIN1, 0, FALSE, pTileInfo); ++ UINT_64 addrInBits = totalOffset % (m_pipeInterleaveBytes * 8) + ++ pipe * (m_pipeInterleaveBytes * 8) + ++ totalOffset / (m_pipeInterleaveBytes * 8) * (m_pipeInterleaveBytes * 8) * numPipes; ++ *pBitPosition = static_cast<UINT_32>(addrInBits) % 8; ++ UINT_64 addr = addrInBits / 8; ++ ++ return addr; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::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 SIAddrLib::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] Not used by SI ++ BOOL_32 isHeight8, ///< [in] Not used by SI ++ 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 newPitch; ++ UINT_32 newHeight; ++ UINT_64 totalBytes; ++ UINT_32 clWidth; ++ UINT_32 clHeight; ++ UINT_32 tileNumPerPipe; ++ UINT_64 sliceBytes; ++ ++ *pX = 0; ++ *pY = 0; ++ *pSlice = 0; ++ ++ if (factor == 2) //CMASK ++ { ++ ADDR_CMASK_FLAGS flags = {{0}}; ++ ++ tileNumPerPipe = 256; ++ ++ ComputeCmaskInfo(flags, ++ pitch, ++ height, ++ numSlices, ++ isLinear, ++ pTileInfo, ++ &newPitch, ++ &newHeight, ++ &totalBytes, ++ &clWidth, ++ &clHeight); ++ } ++ else //HTile ++ { ++ ADDR_HTILE_FLAGS flags = {{0}}; ++ ++ tileNumPerPipe = 512; ++ ++ ComputeHtileInfo(flags, ++ pitch, ++ height, ++ numSlices, ++ isLinear, ++ TRUE, ++ TRUE, ++ pTileInfo, ++ &newPitch, ++ &newHeight, ++ &totalBytes, ++ &clWidth, ++ &clHeight, ++ &sliceBytes); ++ } ++ ++ const UINT_32 pitchInTile = newPitch / MicroTileWidth; ++ const UINT_32 heightInTile = newHeight / MicroTileWidth; ++ const UINT_32 pitchInMacroTile = pitchInTile / 4; ++ UINT_32 macroShift; ++ UINT_32 elemIdxBits; ++ // get macroShift and elemIdxBits ++ TileCoordToMaskElementIndex(0, 0, pTileInfo->pipeConfig, ¯oShift, &elemIdxBits); ++ ++ const UINT_32 numPipes = HwlGetPipes(pTileInfo); ++ const UINT_32 pipe = (UINT_32)((addr / m_pipeInterleaveBytes) % numPipes); ++ // per pipe ++ UINT_64 localOffset = (addr % m_pipeInterleaveBytes) + ++ (addr / m_pipeInterleaveBytes / numPipes)* m_pipeInterleaveBytes; ++ ++ UINT_32 tileIndex; ++ if (factor == 2) //CMASK ++ { ++ tileIndex = (UINT_32)(localOffset * 2 + (bitPosition != 0)); ++ } ++ else ++ { ++ tileIndex = (UINT_32)(localOffset / 4); ++ } ++ ++ UINT_32 macroOffset; ++ if (isLinear) ++ { ++ UINT_32 sliceSizeInTile = pitchInTile * heightInTile; ++ ++ // do htile single slice alignment if the flag is true ++ if (m_configFlags.useHtileSliceAlign && (factor == 1)) //Htile ++ { ++ sliceSizeInTile = PowTwoAlign(sliceSizeInTile, static_cast<UINT_32>(sliceBytes) / 64); ++ } ++ *pSlice = tileIndex / (sliceSizeInTile / numPipes); ++ macroOffset = tileIndex % (sliceSizeInTile / numPipes); ++ } ++ else ++ { ++ const UINT_32 clWidthInTile = clWidth / MicroTileWidth; // Now in unit of Tiles ++ const UINT_32 clHeightInTile = clHeight / MicroTileHeight; ++ const UINT_32 pitchInCL = pitchInTile / clWidthInTile; ++ const UINT_32 heightInCL = heightInTile / clHeightInTile; ++ const UINT_32 clIndex = tileIndex / tileNumPerPipe; ++ ++ UINT_32 clX = clIndex % pitchInCL; ++ UINT_32 clY = (clIndex % (heightInCL * pitchInCL)) / pitchInCL; ++ ++ *pX = clX * clWidthInTile * MicroTileWidth; ++ *pY = clY * clHeightInTile * MicroTileHeight; ++ *pSlice = clIndex / (heightInCL * pitchInCL); ++ ++ macroOffset = tileIndex % tileNumPerPipe; ++ } ++ ++ UINT_32 elemIdx = macroOffset & 7; ++ macroOffset >>= elemIdxBits; ++ ++ if (elemIdxBits != macroShift) ++ { ++ macroOffset <<= (elemIdxBits - macroShift); ++ ++ UINT_32 pipebit1 = _BIT(pipe,1); ++ UINT_32 pipebit2 = _BIT(pipe,2); ++ UINT_32 pipebit3 = _BIT(pipe,3); ++ if (pitchInMacroTile % 2) ++ { //odd ++ switch (pTileInfo->pipeConfig) ++ { ++ case ADDR_PIPECFG_P4_32x32: ++ macroOffset |= pipebit1; ++ break; ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ macroOffset |= pipebit2; ++ break; ++ default: ++ break; ++ } ++ ++ } ++ ++ if (pitchInMacroTile % 4) ++ { ++ if (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32) ++ { ++ macroOffset |= (pipebit1<<1); ++ } ++ if((pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_8x16) || ++ (pTileInfo->pipeConfig == ADDR_PIPECFG_P16_32x32_16x16)) ++ { ++ macroOffset |= (pipebit3<<1); ++ } ++ } ++ } ++ ++ UINT_32 macroX; ++ UINT_32 macroY; ++ ++ if (isLinear) ++ { ++ macroX = macroOffset % pitchInMacroTile; ++ macroY = macroOffset / pitchInMacroTile; ++ } ++ else ++ { ++ const UINT_32 clWidthInMacroTile = clWidth / (MicroTileWidth * 4); ++ macroX = macroOffset % clWidthInMacroTile; ++ macroY = macroOffset / clWidthInMacroTile; ++ } ++ ++ *pX += macroX * 4 * MicroTileWidth; ++ *pY += macroY * 4 * MicroTileHeight; ++ ++ UINT_32 microX; ++ UINT_32 microY; ++ ComputeTileCoordFromPipeAndElemIdx(elemIdx, pipe, pTileInfo->pipeConfig, pitchInMacroTile, ++ *pX, *pY, µX, µY); ++ ++ *pX += microX * MicroTileWidth; ++ *pY += microY * MicroTileWidth; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetPitchAlignmentLinear ++* @brief ++* Get pitch alignment ++* @return ++* pitch alignment ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlGetPitchAlignmentLinear( ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags ///< [in] surface flags ++ ) const ++{ ++ UINT_32 pitchAlign; ++ ++ // Interleaved access requires a 256B aligned pitch, so fall back to pre-SI alignment ++ if (flags.interleaved) ++ { ++ pitchAlign = Max(64u, m_pipeInterleaveBytes / BITS_TO_BYTES(bpp)); ++ ++ } ++ else ++ { ++ pitchAlign = Max(8u, 64 / BITS_TO_BYTES(bpp)); ++ } ++ ++ return pitchAlign; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetSizeAdjustmentLinear ++* ++* @brief ++* Adjust linear surface pitch and slice size ++* ++* @return ++* Logical slice size in bytes ++*************************************************************************************************** ++*/ ++UINT_64 SIAddrLib::HwlGetSizeAdjustmentLinear( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32 bpp, ///< [in] bits per pixel ++ UINT_32 numSamples, ///< [in] number of samples ++ UINT_32 baseAlign, ///< [in] base alignment ++ UINT_32 pitchAlign, ///< [in] pitch alignment ++ UINT_32* pPitch, ///< [in/out] pointer to pitch ++ UINT_32* pHeight, ///< [in/out] pointer to height ++ UINT_32* pHeightAlign ///< [in/out] pointer to height align ++ ) const ++{ ++ UINT_64 sliceSize; ++ if (tileMode == ADDR_TM_LINEAR_GENERAL) ++ { ++ sliceSize = BITS_TO_BYTES(static_cast<UINT_64>(*pPitch) * (*pHeight) * bpp * numSamples); ++ } ++ else ++ { ++ UINT_32 pitch = *pPitch; ++ UINT_32 height = *pHeight; ++ ++ UINT_32 pixelsPerPipeInterleave = m_pipeInterleaveBytes / BITS_TO_BYTES(bpp); ++ UINT_32 sliceAlignInPixel = pixelsPerPipeInterleave < 64 ? 64 : pixelsPerPipeInterleave; ++ ++ // numSamples should be 1 in real cases (no MSAA for linear but TGL may pass non 1 value) ++ UINT_64 pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; ++ ++ while (pixelPerSlice % sliceAlignInPixel) ++ { ++ pitch += pitchAlign; ++ pixelPerSlice = static_cast<UINT_64>(pitch) * height * numSamples; ++ } ++ ++ *pPitch = pitch; ++ ++ UINT_32 heightAlign = 1; ++ ++ while ((pitch * heightAlign) % sliceAlignInPixel) ++ { ++ heightAlign++; ++ } ++ ++ *pHeightAlign = heightAlign; ++ ++ sliceSize = BITS_TO_BYTES(pixelPerSlice * bpp); ++ } ++ ++ return sliceSize; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlPreHandleBaseLvl3xPitch ++* ++* @brief ++* Pre-handler of 3x pitch (96 bit) adjustment ++* ++* @return ++* Expected pitch ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlPreHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input ++ UINT_32 expPitch ///< [in] pitch ++ ) const ++{ ++ ADDR_ASSERT(pIn->width == expPitch); ++ ++ // From SI, if pow2Pad is 1 the pitch is expanded 3x first, then padded to pow2, so nothing to ++ // do here ++ if (!pIn->flags.pow2Pad) ++ { ++ AddrLib::HwlPreHandleBaseLvl3xPitch(pIn, expPitch); ++ } ++ else ++ { ++ ADDR_ASSERT(IsPow2(expPitch)); ++ } ++ ++ return expPitch; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlPostHandleBaseLvl3xPitch ++* ++* @brief ++* Post-handler of 3x pitch adjustment ++* ++* @return ++* Expected pitch ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlPostHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input ++ UINT_32 expPitch ///< [in] pitch ++ ) const ++{ ++ /** ++ * @note The pitch will be divided by 3 in the end so the value will look odd but h/w should ++ * be able to compute a correct pitch from it as h/w address library is doing the job. ++ */ ++ // From SI, the pitch is expanded 3x first, then padded to pow2, so no special handler here ++ if (!pIn->flags.pow2Pad) ++ { ++ AddrLib::HwlPostHandleBaseLvl3xPitch(pIn, expPitch); ++ } ++ ++ return expPitch; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetPitchAlignmentMicroTiled ++* ++* @brief ++* Compute 1D tiled surface pitch alignment ++* ++* @return ++* pitch alignment ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlGetPitchAlignmentMicroTiled( ++ 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 ++ ) const ++{ ++ UINT_32 pitchAlign; ++ ++ if (flags.qbStereo) ++ { ++ pitchAlign = EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled(tileMode,bpp,flags,numSamples); ++ } ++ else ++ { ++ pitchAlign = 8; ++ } ++ ++ return pitchAlign; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetSizeAdjustmentMicroTiled ++* ++* @brief ++* Adjust 1D tiled surface pitch and slice size ++* ++* @return ++* Logical slice size in bytes ++*************************************************************************************************** ++*/ ++UINT_64 SIAddrLib::HwlGetSizeAdjustmentMicroTiled( ++ UINT_32 thickness, ///< [in] thickness ++ UINT_32 bpp, ///< [in] bits per pixel ++ ADDR_SURFACE_FLAGS flags, ///< [in] surface flags ++ UINT_32 numSamples, ///< [in] number of samples ++ UINT_32 baseAlign, ///< [in] base alignment ++ UINT_32 pitchAlign, ///< [in] pitch alignment ++ UINT_32* pPitch, ///< [in/out] pointer to pitch ++ UINT_32* pHeight ///< [in/out] pointer to height ++ ) const ++{ ++ UINT_64 logicalSliceSize; ++ UINT_64 physicalSliceSize; ++ ++ UINT_32 pitch = *pPitch; ++ UINT_32 height = *pHeight; ++ ++ // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1) ++ logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); ++ ++ // Physical slice: multiplied by thickness ++ physicalSliceSize = logicalSliceSize * thickness; ++ ++ // Pitch alignment is always 8, so if slice size is not padded to base alignment ++ // (pipe_interleave_size), we need to increase pitch ++ while ((physicalSliceSize % baseAlign) != 0) ++ { ++ pitch += pitchAlign; ++ ++ logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples); ++ ++ physicalSliceSize = logicalSliceSize * thickness; ++ } ++ ++#if !ALT_TEST ++ // ++ // Special workaround for depth/stencil buffer, use 8 bpp to align depth buffer again since ++ // the stencil plane may have larger pitch if the slice size is smaller than base alignment. ++ // ++ // Note: this actually does not work for mipmap but mipmap depth texture is not really ++ // sampled with mipmap. ++ // ++ if (flags.depth && !flags.noStencil) ++ { ++ ADDR_ASSERT(numSamples == 1); ++ ++ UINT_64 logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; // 1 byte stencil ++ ++ while ((logicalSiceSizeStencil % baseAlign) != 0) ++ { ++ pitch += pitchAlign; // Stencil plane's pitch alignment is the same as depth plane's ++ ++ logicalSiceSizeStencil = static_cast<UINT_64>(pitch) * height; ++ } ++ ++ if (pitch != *pPitch) ++ { ++ // If this is a mipmap, this padded one cannot be sampled as a whole mipmap! ++ logicalSliceSize = logicalSiceSizeStencil * BITS_TO_BYTES(bpp); ++ } ++ } ++#endif ++ *pPitch = pitch; ++ ++ // No adjust for pHeight ++ ++ return logicalSliceSize; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlConvertChipFamily ++* ++* @brief ++* Convert familyID defined in atiid.h to AddrChipFamily and set m_chipFamily/m_chipRevision ++* @return ++* AddrChipFamily ++*************************************************************************************************** ++*/ ++AddrChipFamily SIAddrLib::HwlConvertChipFamily( ++ 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_SI; ++ ++ switch (uChipFamily) ++ { ++ case FAMILY_SI: ++ m_settings.isSouthernIsland = 1; ++ m_settings.isTahiti = ASICREV_IS_TAHITI_P(uChipRevision); ++ m_settings.isPitCairn = ASICREV_IS_PITCAIRN_PM(uChipRevision); ++ m_settings.isCapeVerde = ASICREV_IS_CAPEVERDE_M(uChipRevision); ++ m_settings.isOland = ASICREV_IS_OLAND_M(uChipRevision); ++ m_settings.isHainan = ASICREV_IS_HAINAN_V(uChipRevision); ++ break; ++ default: ++ ADDR_ASSERT(!"This should be a Fusion"); ++ break; ++ } ++ ++ return family; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlSetupTileInfo ++* ++* @brief ++* Setup default value of tile info for SI ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::HwlSetupTileInfo( ++ AddrTileMode tileMode, ///< [in] Tile mode ++ ADDR_SURFACE_FLAGS flags, ///< [in] Surface type flags ++ UINT_32 bpp, ///< [in] Bits per pixel ++ UINT_32 pitch, ///< [in] Pitch in pixels ++ UINT_32 height, ///< [in] Height in pixels ++ UINT_32 numSamples, ///< [in] Number of samples ++ ADDR_TILEINFO* pTileInfoIn, ///< [in] Tile info input: NULL for default ++ ADDR_TILEINFO* pTileInfoOut, ///< [out] Tile info output ++ AddrTileType inTileType, ///< [in] Tile type ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] Output ++ ) const ++{ ++ UINT_32 thickness = ComputeSurfaceThickness(tileMode); ++ ADDR_TILEINFO* pTileInfo = pTileInfoOut; ++ INT index = TileIndexInvalid; ++ ++ // Fail-safe code ++ if (!IsLinear(tileMode)) ++ { ++ // 128 bpp/thick tiling must be non-displayable. ++ // Fmask reuse color buffer's entry but bank-height field can be from another entry ++ // To simplify the logic, fmask entry should be picked from non-displayable ones ++ if (bpp == 128 || thickness > 1 || flags.fmask || flags.prt) ++ { ++ inTileType = ADDR_NON_DISPLAYABLE; ++ } ++ ++ if (flags.depth || flags.stencil) ++ { ++ inTileType = ADDR_DEPTH_SAMPLE_ORDER; ++ } ++ } ++ ++ // Partial valid fields are not allowed for SI. ++ if (IsTileInfoAllZero(pTileInfo)) ++ { ++ if (IsMacroTiled(tileMode)) ++ { ++ if (flags.prt) ++ { ++ if (numSamples == 1) ++ { ++ if (flags.depth) ++ { ++ switch (bpp) ++ { ++ case 16: ++ index = 3; ++ break; ++ case 32: ++ index = 6; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ } ++ else ++ { ++ switch (bpp) ++ { ++ case 8: ++ index = 21; ++ break; ++ case 16: ++ index = 22; ++ break; ++ case 32: ++ index = 23; ++ break; ++ case 64: ++ index = 24; ++ break; ++ case 128: ++ index = 25; ++ break; ++ default: ++ break; ++ } ++ ++ if (thickness > 1) ++ { ++ ADDR_ASSERT(bpp != 128); ++ index += 5; ++ } ++ } ++ } ++ else ++ { ++ ADDR_ASSERT(numSamples == 4); ++ ++ if (flags.depth) ++ { ++ switch (bpp) ++ { ++ case 16: ++ index = 5; ++ break; ++ case 32: ++ index = 7; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ } ++ else ++ { ++ switch (bpp) ++ { ++ case 8: ++ index = 23; ++ break; ++ case 16: ++ index = 24; ++ break; ++ case 32: ++ index = 25; ++ break; ++ case 64: ++ index = 30; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ break; ++ } ++ } ++ } ++ }//end of PRT part ++ // See table entries 0-7 ++ else if (flags.depth || flags.stencil) ++ { ++ if (flags.compressZ) ++ { ++ if (flags.stencil) ++ { ++ index = 0; ++ } ++ else ++ { ++ // optimal tile index for compressed depth/stencil. ++ switch (numSamples) ++ { ++ case 1: ++ index = 0; ++ break; ++ case 2: ++ case 4: ++ index = 1; ++ break; ++ case 8: ++ index = 2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ else // unCompressZ ++ { ++ index = 3; ++ } ++ } ++ else //non PRT & non Depth & non Stencil ++ { ++ // See table entries 9-12 ++ if (inTileType == ADDR_DISPLAYABLE) ++ { ++ switch (bpp) ++ { ++ case 8: ++ index = 10; ++ break; ++ case 16: ++ index = 11; ++ break; ++ case 32: ++ index = 12; ++ break; ++ case 64: ++ index = 12; ++ break; ++ default: ++ break; ++ } ++ } ++ else ++ { ++ // See table entries 13-17 ++ if (thickness == 1) ++ { ++ if (flags.fmask) ++ { ++ UINT_32 fmaskPixelSize = bpp * numSamples; ++ ++ switch (fmaskPixelSize) ++ { ++ case 8: ++ index = 14; ++ break; ++ case 16: ++ index = 15; ++ break; ++ case 32: ++ index = 16; ++ break; ++ case 64: ++ index = 17; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ } ++ } ++ else ++ { ++ switch (bpp) ++ { ++ case 8: ++ index = 14; ++ break; ++ case 16: ++ index = 15; ++ break; ++ case 32: ++ index = 16; ++ break; ++ case 64: ++ index = 17; ++ break; ++ case 128: ++ index = 17; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ else // thick tiling - entries 18-20 ++ { ++ switch (thickness) ++ { ++ case 4: ++ index = 20; ++ break; ++ case 8: ++ index = 19; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ } ++ else ++ { ++ if (tileMode == ADDR_TM_LINEAR_ALIGNED) ++ { ++ index = 8; ++ } ++ else if (tileMode == ADDR_TM_LINEAR_GENERAL) ++ { ++ index = TileIndexLinearGeneral; ++ } ++ else ++ { ++ if (flags.depth || flags.stencil) ++ { ++ index = 4; ++ } ++ else if (inTileType == ADDR_DISPLAYABLE) ++ { ++ index = 9; ++ } ++ else if (thickness == 1) ++ { ++ index = 13; ++ } ++ else ++ { ++ index = 18; ++ } ++ } ++ } ++ ++ if (index >= 0 && index <= 31) ++ { ++ *pTileInfo = m_tileTable[index].info; ++ pOut->tileType = m_tileTable[index].type; ++ } ++ ++ if (index == TileIndexLinearGeneral) ++ { ++ *pTileInfo = m_tileTable[8].info; ++ pOut->tileType = m_tileTable[8].type; ++ } ++ } ++ else ++ { ++ if (pTileInfoIn) ++ { ++ if (flags.stencil && pTileInfoIn->tileSplitBytes == 0) ++ { ++ // Stencil always uses index 0 ++ *pTileInfo = m_tileTable[0].info; ++ } ++ } ++ // Pass through tile type ++ pOut->tileType = inTileType; ++ } ++ ++ pOut->tileIndex = index; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::DecodeGbRegs ++* ++* @brief ++* Decodes GB_ADDR_CONFIG and noOfBanks/noOfRanks ++* ++* @return ++* TRUE if all settings are valid ++* ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::DecodeGbRegs( ++ const ADDR_REGISTER_VALUE* pRegValue) ///< [in] create input ++{ ++ GB_ADDR_CONFIG reg; ++ BOOL_32 valid = TRUE; ++ ++ reg.val = pRegValue->gbAddrConfig; ++ ++ switch (reg.f.pipe_interleave_size) ++ { ++ case ADDR_CONFIG_PIPE_INTERLEAVE_256B: ++ m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_256B; ++ break; ++ case ADDR_CONFIG_PIPE_INTERLEAVE_512B: ++ m_pipeInterleaveBytes = ADDR_PIPEINTERLEAVE_512B; ++ break; ++ default: ++ valid = FALSE; ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ switch (reg.f.row_size) ++ { ++ case ADDR_CONFIG_1KB_ROW: ++ m_rowSize = ADDR_ROWSIZE_1KB; ++ break; ++ case ADDR_CONFIG_2KB_ROW: ++ m_rowSize = ADDR_ROWSIZE_2KB; ++ break; ++ case ADDR_CONFIG_4KB_ROW: ++ m_rowSize = ADDR_ROWSIZE_4KB; ++ break; ++ default: ++ valid = FALSE; ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ switch (pRegValue->noOfBanks) ++ { ++ case 0: ++ m_banks = 4; ++ break; ++ case 1: ++ m_banks = 8; ++ break; ++ case 2: ++ m_banks = 16; ++ break; ++ default: ++ valid = FALSE; ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ switch (pRegValue->noOfRanks) ++ { ++ case 0: ++ m_ranks = 1; ++ break; ++ case 1: ++ m_ranks = 2; ++ break; ++ default: ++ valid = FALSE; ++ ADDR_UNHANDLED_CASE(); ++ break; ++ } ++ ++ m_logicalBanks = m_banks * m_ranks; ++ ++ ADDR_ASSERT(m_logicalBanks <= 16); ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlInitGlobalParams ++* ++* @brief ++* Initializes global parameters ++* ++* @return ++* TRUE if all settings are valid ++* ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::HwlInitGlobalParams( ++ const ADDR_CREATE_INPUT* pCreateIn) ///< [in] create input ++{ ++ BOOL_32 valid = TRUE; ++ const ADDR_REGISTER_VALUE* pRegValue = &pCreateIn->regValue; ++ ++ valid = DecodeGbRegs(pRegValue); ++ ++ if (valid) ++ { ++ if (m_settings.isTahiti || m_settings.isPitCairn) ++ { ++ m_pipes = 8; ++ } ++ else if (m_settings.isCapeVerde || m_settings.isOland) ++ { ++ m_pipes = 4; ++ } ++ else ++ { ++ // Hainan is 2-pipe (m_settings.isHainan == 1) ++ m_pipes = 2; ++ } ++ ++ valid = InitTileSettingTable(pRegValue->pTileConfig, pRegValue->noOfEntries); ++ ++ m_maxSamples = 16; ++ } ++ ++ return valid; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlConvertTileInfoToHW ++* @brief ++* Entry of si's ConvertTileInfoToHW ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE SIAddrLib::HwlConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ ADDR_E_RETURNCODE retCode = ADDR_OK; ++ ++ retCode = EgBasedAddrLib::HwlConvertTileInfoToHW(pIn, pOut); ++ ++ if (retCode == ADDR_OK) ++ { ++ if (pIn->reverse == FALSE) ++ { ++ if (pIn->pTileInfo->pipeConfig == ADDR_PIPECFG_INVALID) ++ { ++ retCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ pOut->pTileInfo->pipeConfig = ++ static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig - 1); ++ } ++ } ++ else ++ { ++ pOut->pTileInfo->pipeConfig = ++ static_cast<AddrPipeCfg>(pIn->pTileInfo->pipeConfig + 1); ++ } ++ } ++ ++ return retCode; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe ++* ++* @brief ++* Compute the Y coord which will be added to Xmask Y ++* coord. ++* @return ++* Y coord ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlComputeXmaskCoordYFrom8Pipe( ++ UINT_32 pipe, ///< [in] pipe id ++ UINT_32 x ///< [in] tile coord x, which is original x coord / 8 ++ ) const ++{ ++ // This function should never be called since it is 6xx/8xx specfic. ++ // Keep this empty implementation to avoid any mis-use. ++ ADDR_ASSERT_ALWAYS(); ++ ++ return 0; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe ++* ++* @brief ++* Compute surface x,y coordinates from bank/pipe info ++* @return ++* N/A ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::HwlComputeSurfaceCoord2DFromBankPipe( ++ AddrTileMode tileMode, ///< [in] tile mode ++ UINT_32* pX, ///< [in/out] x coordinate ++ UINT_32* pY, ///< [in/out] y coordinate ++ UINT_32 slice, ///< [in] slice index ++ UINT_32 bank, ///< [in] bank number ++ UINT_32 pipe, ///< [in] pipe number ++ UINT_32 bankSwizzle,///< [in] bank swizzle ++ UINT_32 pipeSwizzle,///< [in] pipe swizzle ++ UINT_32 tileSlices, ///< [in] slices in a micro tile ++ BOOL_32 ignoreSE, ///< [in] TRUE if shader engines are ignored ++ ADDR_TILEINFO* pTileInfo ///< [in] bank structure. **All fields to be valid on entry** ++ ) const ++{ ++ UINT_32 xBit; ++ UINT_32 yBit; ++ UINT_32 yBit3 = 0; ++ UINT_32 yBit4 = 0; ++ UINT_32 yBit5 = 0; ++ UINT_32 yBit6 = 0; ++ ++ UINT_32 xBit3 = 0; ++ UINT_32 xBit4 = 0; ++ UINT_32 xBit5 = 0; ++ ++ UINT_32 numPipes = GetPipePerSurf(pTileInfo->pipeConfig); ++ ++ CoordFromBankPipe xyBits = {0}; ++ ComputeSurfaceCoord2DFromBankPipe(tileMode, *pX, *pY, slice, bank, pipe, ++ bankSwizzle, pipeSwizzle, tileSlices, pTileInfo, ++ &xyBits); ++ yBit3 = xyBits.yBit3; ++ yBit4 = xyBits.yBit4; ++ yBit5 = xyBits.yBit5; ++ yBit6 = xyBits.yBit6; ++ ++ xBit3 = xyBits.xBit3; ++ xBit4 = xyBits.xBit4; ++ xBit5 = xyBits.xBit5; ++ ++ yBit = xyBits.yBits; ++ ++ UINT_32 yBitTemp = 0; ++ ++ if ((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || ++ (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) ++ { ++ ADDR_ASSERT(pTileInfo->bankWidth == 1 && pTileInfo->macroAspectRatio > 1); ++ UINT_32 yBitToCheck = QLog2(pTileInfo->banks) - 1; ++ ++ ADDR_ASSERT(yBitToCheck <= 3); ++ ++ yBitTemp = _BIT(yBit, yBitToCheck); ++ ++ xBit3 = 0; ++ } ++ ++ yBit = Bits2Number(4, yBit6, yBit5, yBit4, yBit3); ++ xBit = Bits2Number(3, xBit5, xBit4, xBit3); ++ ++ *pY += yBit * pTileInfo->bankHeight * MicroTileHeight; ++ *pX += xBit * numPipes * pTileInfo->bankWidth * MicroTileWidth; ++ ++ //calculate the bank and pipe bits in x, y ++ UINT_32 xTile; //x in micro tile ++ UINT_32 x3 = 0; ++ UINT_32 x4 = 0; ++ UINT_32 x5 = 0; ++ UINT_32 x6 = 0; ++ UINT_32 y = *pY; ++ ++ UINT_32 pipeBit0 = _BIT(pipe,0); ++ UINT_32 pipeBit1 = _BIT(pipe,1); ++ UINT_32 pipeBit2 = _BIT(pipe,2); ++ ++ UINT_32 y3 = _BIT(y, 3); ++ UINT_32 y4 = _BIT(y, 4); ++ UINT_32 y5 = _BIT(y, 5); ++ UINT_32 y6 = _BIT(y, 6); ++ ++ // bankbit0 after ^x4^x5 ++ UINT_32 bankBit00 = _BIT(bank,0); ++ UINT_32 bankBit0 = 0; ++ ++ switch (pTileInfo->pipeConfig) ++ { ++ case ADDR_PIPECFG_P2: ++ x3 = pipeBit0 ^ y3; ++ break; ++ case ADDR_PIPECFG_P4_8x16: ++ x4 = pipeBit0 ^ y3; ++ x3 = pipeBit0 ^ y4; ++ break; ++ case ADDR_PIPECFG_P4_16x16: ++ x4 = pipeBit1 ^ y4; ++ x3 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P4_16x32: ++ x4 = pipeBit1 ^ y4; ++ x3 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P4_32x32: ++ x5 = pipeBit1 ^ y5; ++ x3 = pipeBit0 ^ y3 ^ x5; ++ bankBit0 = yBitTemp ^ x5; ++ x4 = bankBit00 ^ x5 ^ bankBit0; ++ *pX += x5 * 4 * 1 * 8; // x5 * num_pipes * bank_width * 8; ++ break; ++ case ADDR_PIPECFG_P8_16x16_8x16: ++ x3 = pipeBit1 ^ y5; ++ x4 = pipeBit2 ^ y4; ++ x5 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P8_16x32_8x16: ++ x3 = pipeBit1 ^ y4; ++ x4 = pipeBit2 ^ y5; ++ x5 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P8_32x32_8x16: ++ x3 = pipeBit1 ^ y4; ++ x5 = pipeBit2 ^ y5; ++ x4 = pipeBit0 ^ y3 ^ x5; ++ break; ++ case ADDR_PIPECFG_P8_16x32_16x16: ++ x4 = pipeBit2 ^ y5; ++ x5 = pipeBit1 ^ y4; ++ x3 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x16: ++ x5 = pipeBit2 ^ y5; ++ x4 = pipeBit1 ^ y4; ++ x3 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P8_32x32_16x32: ++ x5 = pipeBit2 ^ y5; ++ x4 = pipeBit1 ^ y6; ++ x3 = pipeBit0 ^ y3 ^ x4; ++ break; ++ case ADDR_PIPECFG_P8_32x64_32x32: ++ x6 = pipeBit1 ^ y5; ++ x5 = pipeBit2 ^ y6; ++ x3 = pipeBit0 ^ y3 ^ x5; ++ bankBit0 = yBitTemp ^ x6; ++ x4 = bankBit00 ^ x5 ^ bankBit0; ++ *pX += x6 * 8 * 1 * 8; // x6 * num_pipes * bank_width * 8; ++ break; ++ default: ++ ADDR_ASSERT_ALWAYS(); ++ } ++ ++ xTile = Bits2Number(3, x5, x4, x3); ++ ++ *pX += xTile << 3; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlPreAdjustBank ++* ++* @brief ++* Adjust bank before calculating address acoording to bank/pipe ++* @return ++* Adjusted bank ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlPreAdjustBank( ++ UINT_32 tileX, ///< [in] x coordinate in unit of tile ++ UINT_32 bank, ///< [in] bank ++ ADDR_TILEINFO* pTileInfo ///< [in] tile info ++ ) const ++{ ++ if (((pTileInfo->pipeConfig == ADDR_PIPECFG_P4_32x32) || ++ (pTileInfo->pipeConfig == ADDR_PIPECFG_P8_32x64_32x32)) && (pTileInfo->bankWidth == 1)) ++ { ++ UINT_32 bankBit0 = _BIT(bank, 0); ++ UINT_32 x4 = _BIT(tileX, 1); ++ UINT_32 x5 = _BIT(tileX, 2); ++ ++ bankBit0 = bankBit0 ^ x4 ^ x5; ++ bank |= bankBit0; ++ ++ ADDR_ASSERT(pTileInfo->macroAspectRatio > 1) ++ } ++ ++ return bank; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeSurfaceInfo ++* ++* @brief ++* Entry of si's ComputeSurfaceInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE SIAddrLib::HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure ++ ) const ++{ ++ pOut->tileIndex = pIn->tileIndex; ++ ++ return EgBasedAddrLib::HwlComputeSurfaceInfo(pIn,pOut); ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeMipLevel ++* @brief ++* Compute MipLevel info (including level 0) ++* @return ++* TRUE if HWL's handled ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::HwlComputeMipLevel( ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in/out] Input structure ++ ) const ++{ ++ // basePitch is calculated from level 0 so we only check this for mipLevel > 0 ++ if (pIn->mipLevel > 0) ++ { ++ // Note: Don't check expand 3x formats(96 bit) as the basePitch is not pow2 even if ++ // we explicity set pow2Pad flag. The 3x base pitch is padded to pow2 but after being ++ // divided by expandX factor (3) - to program texture pitch, the basePitch is never pow2. ++ if (!AddrElemLib::IsExpand3x(pIn->format)) ++ { ++ // Sublevel pitches are generated from base level pitch instead of width on SI ++ // If pow2Pad is 0, we don't assert - as this is not really used for a mip chain ++ ADDR_ASSERT(!pIn->flags.pow2Pad || ((pIn->basePitch != 0) && IsPow2(pIn->basePitch))); ++ } ++ ++ if (pIn->basePitch != 0) ++ { ++ pIn->width = Max(1u, pIn->basePitch >> pIn->mipLevel); ++ } ++ } ++ ++ // pow2Pad is done in PostComputeMipLevel ++ ++ return TRUE; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlCheckLastMacroTiledLvl ++* ++* @brief ++* Sets pOut->last2DLevel to TRUE if it is ++* @note ++* ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::HwlCheckLastMacroTiledLvl( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in/out] Output structure (used as input, too) ++ ) const ++{ ++ // pow2Pad covers all mipmap cases ++ if (pIn->flags.pow2Pad) ++ { ++ ADDR_ASSERT(IsMacroTiled(pIn->tileMode)); ++ ++ UINT_32 nextPitch; ++ UINT_32 nextHeight; ++ UINT_32 nextSlices; ++ ++ AddrTileMode nextTileMode; ++ ++ if (pIn->mipLevel == 0 || pIn->basePitch == 0) ++ { ++ // Base level or fail-safe case (basePitch == 0) ++ nextPitch = pOut->pitch >> 1; ++ } ++ else ++ { ++ // Sub levels ++ nextPitch = pIn->basePitch >> (pIn->mipLevel + 1); ++ } ++ ++ // nextHeight must be shifted from this level's original height rather than a pow2 padded ++ // one but this requires original height stored somewhere (pOut->height) ++ ADDR_ASSERT(pOut->height != 0); ++ ++ // next level's height is just current level's >> 1 in pixels ++ nextHeight = pOut->height >> 1; ++ // Special format such as FMT_1 and FMT_32_32_32 can be linear only so we consider block ++ // compressed foramts ++ if (AddrElemLib::IsBlockCompressed(pIn->format)) ++ { ++ nextHeight = (nextHeight + 3) / 4; ++ } ++ nextHeight = NextPow2(nextHeight); ++ ++ // nextSlices may be 0 if this level's is 1 ++ if (pIn->flags.volume) ++ { ++ nextSlices = Max(1u, pIn->numSlices >> 1); ++ } ++ else ++ { ++ nextSlices = pIn->numSlices; ++ } ++ ++ nextTileMode = ComputeSurfaceMipLevelTileMode(pIn->tileMode, ++ pIn->bpp, ++ nextPitch, ++ nextHeight, ++ nextSlices, ++ pIn->numSamples, ++ pOut->pitchAlign, ++ pOut->heightAlign, ++ pOut->pTileInfo); ++ ++ pOut->last2DLevel = IsMicroTiled(nextTileMode); ++ } ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlDegradeThickTileMode ++* ++* @brief ++* Degrades valid tile mode for thick modes if needed ++* ++* @return ++* Suitable tile mode ++*************************************************************************************************** ++*/ ++AddrTileMode SIAddrLib::HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, ///< [in] base tile mode ++ UINT_32 numSlices, ///< [in] current number of slices ++ UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice ++ ) const ++{ ++ return EgBasedAddrLib::HwlDegradeThickTileMode(baseTileMode, numSlices, pBytesPerTile); ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlTileInfoEqual ++* ++* @brief ++* Return TRUE if all field are equal ++* @note ++* Only takes care of current HWL's data ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::HwlTileInfoEqual( ++ const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand ++ const ADDR_TILEINFO* pRight ///<[in] Right compare operand ++ ) const ++{ ++ BOOL_32 equal = FALSE; ++ ++ if (pLeft->pipeConfig == pRight->pipeConfig) ++ { ++ equal = EgBasedAddrLib::HwlTileInfoEqual(pLeft, pRight); ++ } ++ ++ return equal; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::GetTileSettings ++* ++* @brief ++* Get tile setting infos by index. ++* @return ++* Tile setting info. ++*************************************************************************************************** ++*/ ++const ADDR_TILECONFIG* SIAddrLib::GetTileSetting( ++ UINT_32 index ///< [in] Tile index ++ ) const ++{ ++ ADDR_ASSERT(index < m_noOfEntries); ++ return &m_tileTable[index]; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlPostCheckTileIndex ++* ++* @brief ++* Map a tile setting to index if curIndex is invalid, otherwise check if curIndex matches ++* tile mode/type/info and change the index if needed ++* @return ++* Tile index. ++*************************************************************************************************** ++*/ ++INT_32 SIAddrLib::HwlPostCheckTileIndex( ++ const ADDR_TILEINFO* pInfo, ///< [in] Tile Info ++ AddrTileMode mode, ///< [in] Tile mode ++ AddrTileType type, ///< [in] Tile type ++ INT curIndex ///< [in] Current index assigned in HwlSetupTileInfo ++ ) const ++{ ++ INT_32 index = curIndex; ++ ++ if (mode == ADDR_TM_LINEAR_GENERAL) ++ { ++ index = TileIndexLinearGeneral; ++ } ++ else ++ { ++ BOOL_32 macroTiled = IsMacroTiled(mode); ++ ++ // We need to find a new index if either of them is true ++ // 1. curIndex is invalid ++ // 2. tile mode is changed ++ // 3. tile info does not match for macro tiled ++ if ((index == TileIndexInvalid || ++ (mode != m_tileTable[index].mode) || ++ (macroTiled && !HwlTileInfoEqual(pInfo, &m_tileTable[index].info)))) ++ { ++ for (index = 0; index < static_cast<INT_32>(m_noOfEntries); index++) ++ { ++ if (macroTiled) ++ { ++ // macro tile modes need all to match ++ if (HwlTileInfoEqual(pInfo, &m_tileTable[index].info) && ++ (mode == m_tileTable[index].mode) && ++ (type == m_tileTable[index].type)) ++ { ++ break; ++ } ++ } ++ else if (mode == ADDR_TM_LINEAR_ALIGNED) ++ { ++ // linear mode only needs tile mode to match ++ if (mode == m_tileTable[index].mode) ++ { ++ break; ++ } ++ } ++ else ++ { ++ // micro tile modes only need tile mode and tile type to match ++ if (mode == m_tileTable[index].mode && ++ type == m_tileTable[index].type) ++ { ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ ADDR_ASSERT(index < static_cast<INT_32>(m_noOfEntries)); ++ ++ if (index >= static_cast<INT_32>(m_noOfEntries)) ++ { ++ index = TileIndexInvalid; ++ } ++ ++ return index; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlSetupTileCfg ++* ++* @brief ++* Map tile index to tile setting. ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE SIAddrLib::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 ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ // Global flag to control usage of tileIndex ++ if (UseTileIndex(index)) ++ { ++ if (index == TileIndexLinearGeneral) ++ { ++ if (pMode) ++ { ++ *pMode = ADDR_TM_LINEAR_GENERAL; ++ } ++ ++ if (pType) ++ { ++ *pType = ADDR_DISPLAYABLE; ++ } ++ ++ if (pInfo) ++ { ++ pInfo->banks = 2; ++ pInfo->bankWidth = 1; ++ pInfo->bankHeight = 1; ++ pInfo->macroAspectRatio = 1; ++ pInfo->tileSplitBytes = 64; ++ pInfo->pipeConfig = ADDR_PIPECFG_P2; ++ } ++ } ++ else if (static_cast<UINT_32>(index) >= m_noOfEntries) ++ { ++ returnCode = ADDR_INVALIDPARAMS; ++ } ++ else ++ { ++ const ADDR_TILECONFIG* pCfgTable = GetTileSetting(index); ++ ++ if (pInfo) ++ { ++ *pInfo = pCfgTable->info; ++ } ++ else ++ { ++ if (IsMacroTiled(pCfgTable->mode)) ++ { ++ returnCode = ADDR_INVALIDPARAMS; ++ } ++ } ++ ++ if (pMode) ++ { ++ *pMode = pCfgTable->mode; ++ } ++ ++ if (pType) ++ { ++ *pType = pCfgTable->type; ++ } ++ } ++ } ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::ReadGbTileMode ++* ++* @brief ++* Convert GB_TILE_MODE HW value to ADDR_TILE_CONFIG. ++* @return ++* NA. ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::ReadGbTileMode( ++ UINT_32 regValue, ///< [in] GB_TILE_MODE register ++ ADDR_TILECONFIG* pCfg ///< [out] output structure ++ ) const ++{ ++ GB_TILE_MODE gbTileMode; ++ gbTileMode.val = regValue; ++ ++ pCfg->type = static_cast<AddrTileType>(gbTileMode.f.micro_tile_mode); ++ pCfg->info.bankHeight = 1 << gbTileMode.f.bank_height; ++ pCfg->info.bankWidth = 1 << gbTileMode.f.bank_width; ++ pCfg->info.banks = 1 << (gbTileMode.f.num_banks + 1); ++ pCfg->info.macroAspectRatio = 1 << gbTileMode.f.macro_tile_aspect; ++ pCfg->info.tileSplitBytes = 64 << gbTileMode.f.tile_split; ++ pCfg->info.pipeConfig = static_cast<AddrPipeCfg>(gbTileMode.f.pipe_config + 1); ++ ++ UINT_32 regArrayMode = gbTileMode.f.array_mode; ++ ++ pCfg->mode = static_cast<AddrTileMode>(regArrayMode); ++ ++ if (regArrayMode == 8) //ARRAY_2D_TILED_XTHICK ++ { ++ pCfg->mode = ADDR_TM_2D_TILED_XTHICK; ++ } ++ else if (regArrayMode >= 14) //ARRAY_3D_TILED_XTHICK ++ { ++ pCfg->mode = static_cast<AddrTileMode>(pCfg->mode + 3); ++ } ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::InitTileSettingTable ++* ++* @brief ++* Initialize the ADDR_TILE_CONFIG table. ++* @return ++* TRUE if tile table is correctly initialized ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::InitTileSettingTable( ++ const UINT_32* pCfg, ///< [in] Pointer to table of tile configs ++ UINT_32 noOfEntries ///< [in] Numbe of entries in the table above ++ ) ++{ ++ BOOL_32 initOk = TRUE; ++ ++ ADDR_ASSERT(noOfEntries <= TileTableSize); ++ ++ memset(m_tileTable, 0, sizeof(m_tileTable)); ++ ++ if (noOfEntries != 0) ++ { ++ m_noOfEntries = noOfEntries; ++ } ++ else ++ { ++ m_noOfEntries = TileTableSize; ++ } ++ ++ if (pCfg) // From Client ++ { ++ for (UINT_32 i = 0; i < m_noOfEntries; i++) ++ { ++ ReadGbTileMode(*(pCfg + i), &m_tileTable[i]); ++ } ++ } ++ else ++ { ++ ADDR_ASSERT_ALWAYS(); ++ initOk = FALSE; ++ } ++ ++ if (initOk) ++ { ++ ADDR_ASSERT(m_tileTable[TILEINDEX_LINEAR_ALIGNED].mode == ADDR_TM_LINEAR_ALIGNED); ++ } ++ ++ return initOk; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlGetTileIndex ++* ++* @brief ++* Return the virtual/real index for given mode/type/info ++* @return ++* ADDR_OK if successful. ++*************************************************************************************************** ++*/ ++ADDR_E_RETURNCODE SIAddrLib::HwlGetTileIndex( ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut) const ++{ ++ ADDR_E_RETURNCODE returnCode = ADDR_OK; ++ ++ pOut->index = HwlPostCheckTileIndex(pIn->pTileInfo, pIn->tileMode, pIn->tileType); ++ ++ return returnCode; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlFmaskPreThunkSurfInfo ++* ++* @brief ++* Some preparation before thunking a ComputeSurfaceInfo call for Fmask ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::HwlFmaskPreThunkSurfInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ///< [in] Input of fmask info ++ const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ///< [in] Output of fmask info ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ///< [out] Input of thunked surface info ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut ///< [out] Output of thunked surface info ++ ) const ++{ ++ pSurfIn->tileIndex = pFmaskIn->tileIndex; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlFmaskPostThunkSurfInfo ++* ++* @brief ++* Copy hwl extra field after calling thunked ComputeSurfaceInfo ++* @return ++* ADDR_E_RETURNCODE ++*************************************************************************************************** ++*/ ++VOID SIAddrLib::HwlFmaskPostThunkSurfInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ///< [in] Output of surface info ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut ///< [out] Output of fmask info ++ ) const ++{ ++ pFmaskOut->macroModeIndex = TileIndexInvalid; ++ pFmaskOut->tileIndex = pSurfOut->tileIndex; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlComputeFmaskBits ++* @brief ++* Computes fmask bits ++* @return ++* Fmask bits ++*************************************************************************************************** ++*/ ++UINT_32 SIAddrLib::HwlComputeFmaskBits( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ UINT_32* pNumSamples ++ ) const ++{ ++ UINT_32 numSamples = pIn->numSamples; ++ UINT_32 numFrags = GetNumFragments(numSamples, pIn->numFrags); ++ UINT_32 bpp; ++ ++ if (numFrags != numSamples) // EQAA ++ { ++ ADDR_ASSERT(numFrags <= 8); ++ ++ if (!pIn->resolved) ++ { ++ if (numFrags == 1) ++ { ++ bpp = 1; ++ numSamples = numSamples == 16 ? 16 : 8; ++ } ++ else if (numFrags == 2) ++ { ++ ADDR_ASSERT(numSamples >= 4); ++ ++ bpp = 2; ++ numSamples = numSamples; ++ } ++ else if (numFrags == 4) ++ { ++ ADDR_ASSERT(numSamples >= 4); ++ ++ bpp = 4; ++ numSamples = numSamples; ++ } ++ else // numFrags == 8 ++ { ++ ADDR_ASSERT(numSamples == 16); ++ ++ bpp = 4; ++ numSamples = numSamples; ++ } ++ } ++ else ++ { ++ if (numFrags == 1) ++ { ++ bpp = (numSamples == 16) ? 16 : 8; ++ numSamples = 1; ++ } ++ else if (numFrags == 2) ++ { ++ ADDR_ASSERT(numSamples >= 4); ++ ++ bpp = numSamples*2; ++ numSamples = 1; ++ } ++ else if (numFrags == 4) ++ { ++ ADDR_ASSERT(numSamples >= 4); ++ ++ bpp = numSamples*4; ++ numSamples = 1; ++ } ++ else // numFrags == 8 ++ { ++ ADDR_ASSERT(numSamples >= 16); ++ ++ bpp = 16*4; ++ numSamples = 1; ++ } ++ } ++ } ++ else // Normal AA ++ { ++ if (!pIn->resolved) ++ { ++ bpp = ComputeFmaskNumPlanesFromNumSamples(numSamples); ++ numSamples = numSamples == 2 ? 8 : numSamples; ++ } ++ else ++ { ++ // The same as 8XX ++ bpp = ComputeFmaskResolvedBppFromNumSamples(numSamples); ++ numSamples = 1; // 1x sample ++ } ++ } ++ ++ SafeAssign(pNumSamples, numSamples); ++ ++ return bpp; ++} ++ ++/** ++*************************************************************************************************** ++* SIAddrLib::HwlOverrideTileMode ++* ++* @brief ++* Override tile modes (for PRT only, avoid client passes in an invalid PRT mode for SI. ++* ++* @return ++* Suitable tile mode ++* ++*************************************************************************************************** ++*/ ++BOOL_32 SIAddrLib::HwlOverrideTileMode( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure ++ AddrTileMode* pTileMode, ///< [in/out] pointer to the tile mode ++ AddrTileType* pTileType ///< [in/out] pointer to the tile type ++ ) const ++{ ++ BOOL_32 bOverrided = FALSE; ++ AddrTileMode tileMode = *pTileMode; ++ ++ switch (tileMode) ++ { ++ case ADDR_TM_PRT_TILED_THIN1: ++ tileMode = ADDR_TM_2D_TILED_THIN1; ++ break; ++ ++ case ADDR_TM_PRT_TILED_THICK: ++ tileMode = ADDR_TM_2D_TILED_THICK; ++ break; ++ ++ case ADDR_TM_PRT_2D_TILED_THICK: ++ tileMode = ADDR_TM_2D_TILED_THICK; ++ break; ++ ++ case ADDR_TM_PRT_3D_TILED_THICK: ++ tileMode = ADDR_TM_3D_TILED_THICK; ++ break; ++ ++ default: ++ break; ++ } ++ ++ if (tileMode != *pTileMode) ++ { ++ *pTileMode = tileMode; ++ bOverrided = TRUE; ++ ADDR_ASSERT(pIn->flags.prt == TRUE); ++ } ++ ++ return bOverrided; ++} ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.h b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.h +new file mode 100644 +index 0000000..897beb1 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/addrlib/r800/siaddrlib.h +@@ -0,0 +1,262 @@ ++/* ++ * 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 siaddrlib.h ++* @brief Contains the R800AddrLib class definition. ++*************************************************************************************************** ++*/ ++ ++#ifndef __SI_ADDR_LIB_H__ ++#define __SI_ADDR_LIB_H__ ++ ++#include "addrlib.h" ++#include "egbaddrlib.h" ++ ++/** ++*************************************************************************************************** ++* @brief Describes the information in tile mode table ++*************************************************************************************************** ++*/ ++struct ADDR_TILECONFIG ++{ ++ AddrTileMode mode; ++ AddrTileType type; ++ ADDR_TILEINFO info; ++}; ++ ++/** ++*************************************************************************************************** ++* @brief SI specific settings structure. ++*************************************************************************************************** ++*/ ++struct SIChipSettings ++{ ++ struct ++ { ++ UINT_32 isSouthernIsland : 1; ++ UINT_32 isTahiti : 1; ++ UINT_32 isPitCairn : 1; ++ UINT_32 isCapeVerde : 1; ++ /// Oland/Hainan are of GFXIP 6.0, similar with SI ++ UINT_32 isOland : 1; ++ UINT_32 isHainan : 1; ++ }; ++}; ++ ++/** ++*************************************************************************************************** ++* @brief This class is the SI specific address library ++* function set. ++*************************************************************************************************** ++*/ ++class SIAddrLib : public EgBasedAddrLib ++{ ++public: ++ /// Creates SIAddrLib object ++ static AddrLib* CreateObj(const AddrClient* pClient) ++ { ++ return new(pClient) SIAddrLib(pClient); ++ } ++ ++protected: ++ SIAddrLib(const AddrClient* pClient); ++ virtual ~SIAddrLib(); ++ ++ // Hwl interface - defined in AddrLib ++ virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual ADDR_E_RETURNCODE HwlConvertTileInfoToHW( ++ const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ++ ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut) const; ++ ++ virtual UINT_64 HwlComputeXmaskAddrFromCoord( ++ UINT_32 pitch, UINT_32 height, UINT_32 x, UINT_32 y, UINT_32 slice, UINT_32 numSlices, ++ UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, ++ ADDR_TILEINFO* pTileInfo, UINT_32* pBitPosition) const; ++ ++ virtual VOID HwlComputeXmaskCoordFromAddr( ++ UINT_64 addr, UINT_32 bitPosition, UINT_32 pitch, UINT_32 height, UINT_32 numSlices, ++ UINT_32 factor, BOOL_32 isLinear, BOOL_32 isWidth8, BOOL_32 isHeight8, ++ ADDR_TILEINFO* pTileInfo, UINT_32* pX, UINT_32* pY, UINT_32* pSlice) const; ++ ++ virtual ADDR_E_RETURNCODE HwlGetTileIndex( ++ const ADDR_GET_TILEINDEX_INPUT* pIn, ++ ADDR_GET_TILEINDEX_OUTPUT* pOut) const; ++ ++ virtual BOOL_32 HwlComputeMipLevel( ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const; ++ ++ virtual AddrChipFamily HwlConvertChipFamily( ++ UINT_32 uChipFamily, UINT_32 uChipRevision); ++ ++ virtual BOOL_32 HwlInitGlobalParams( ++ const ADDR_CREATE_INPUT* pCreateIn); ++ ++ virtual ADDR_E_RETURNCODE HwlSetupTileCfg( ++ INT_32 index, INT_32 macroModeIndex, ++ ADDR_TILEINFO* pInfo, AddrTileMode* pMode = 0, AddrTileType* pType = 0) const; ++ ++ virtual VOID HwlComputeTileDataWidthAndHeightLinear( ++ UINT_32* pMacroWidth, UINT_32* pMacroHeight, ++ UINT_32 bpp, ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual UINT_64 HwlComputeHtileBytes( ++ UINT_32 pitch, UINT_32 height, UINT_32 bpp, ++ BOOL_32 isLinear, UINT_32 numSlices, UINT_64* pSliceBytes, UINT_32 baseAlign) const; ++ ++ virtual UINT_32 ComputePipeFromCoord( ++ UINT_32 x, UINT_32 y, UINT_32 slice, ++ AddrTileMode tileMode, UINT_32 pipeSwizzle, BOOL_32 ignoreSE, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual UINT_32 HwlGetPipes(const ADDR_TILEINFO* pTileInfo) const; ++ ++ /// Pre-handler of 3x pitch (96 bit) adjustment ++ virtual UINT_32 HwlPreHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; ++ /// Post-handler of 3x pitch adjustment ++ virtual UINT_32 HwlPostHandleBaseLvl3xPitch( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, UINT_32 expPitch) const; ++ ++ /// Dummy function to finalize the inheritance ++ virtual UINT_32 HwlComputeXmaskCoordYFrom8Pipe( ++ UINT_32 pipe, UINT_32 x) const; ++ ++ // Sub-hwl interface - defined in EgBasedAddrLib ++ virtual VOID HwlSetupTileInfo( ++ AddrTileMode tileMode, ADDR_SURFACE_FLAGS flags, ++ UINT_32 bpp, UINT_32 pitch, UINT_32 height, UINT_32 numSamples, ++ ADDR_TILEINFO* inputTileInfo, ADDR_TILEINFO* outputTileInfo, ++ AddrTileType inTileType, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual UINT_32 HwlGetPitchAlignmentMicroTiled( ++ AddrTileMode tileMode, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples) const; ++ ++ virtual UINT_64 HwlGetSizeAdjustmentMicroTiled( ++ UINT_32 thickness, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, ++ UINT_32 baseAlign, UINT_32 pitchAlign, ++ UINT_32 *pPitch, UINT_32 *pHeight) const; ++ ++ virtual VOID HwlCheckLastMacroTiledLvl( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const; ++ ++ virtual BOOL_32 HwlTileInfoEqual( ++ const ADDR_TILEINFO* pLeft, const ADDR_TILEINFO* pRight) const; ++ ++ virtual AddrTileMode HwlDegradeThickTileMode( ++ AddrTileMode baseTileMode, UINT_32 numSlices, UINT_32* pBytesPerTile) const; ++ ++ virtual BOOL_32 HwlOverrideTileMode( ++ const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ++ AddrTileMode* pTileMode, ++ AddrTileType* pTileType) const; ++ ++ virtual BOOL_32 HwlSanityCheckMacroTiled( ++ ADDR_TILEINFO* pTileInfo) const ++ { ++ return TRUE; ++ } ++ ++ virtual UINT_32 HwlGetPitchAlignmentLinear(UINT_32 bpp, ADDR_SURFACE_FLAGS flags) const; ++ ++ virtual UINT_64 HwlGetSizeAdjustmentLinear( ++ AddrTileMode tileMode, ++ UINT_32 bpp, UINT_32 numSamples, UINT_32 baseAlign, UINT_32 pitchAlign, ++ UINT_32 *pPitch, UINT_32 *pHeight, UINT_32 *pHeightAlign) const; ++ ++ virtual VOID HwlComputeSurfaceCoord2DFromBankPipe( ++ AddrTileMode tileMode, UINT_32* pX, UINT_32* pY, UINT_32 slice, ++ UINT_32 bank, UINT_32 pipe, ++ UINT_32 bankSwizzle, UINT_32 pipeSwizzle, UINT_32 tileSlices, ++ BOOL_32 ignoreSE, ++ ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual UINT_32 HwlPreAdjustBank( ++ UINT_32 tileX, UINT_32 bank, ADDR_TILEINFO* pTileInfo) const; ++ ++ virtual INT_32 HwlPostCheckTileIndex( ++ const ADDR_TILEINFO* pInfo, AddrTileMode mode, AddrTileType type, ++ INT curIndex = TileIndexInvalid) const; ++ ++ virtual VOID HwlFmaskPreThunkSurfInfo( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pFmaskIn, ++ const ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut, ++ ADDR_COMPUTE_SURFACE_INFO_INPUT* pSurfIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut) const; ++ ++ virtual VOID HwlFmaskPostThunkSurfInfo( ++ const ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pSurfOut, ++ ADDR_COMPUTE_FMASK_INFO_OUTPUT* pFmaskOut) const; ++ ++ virtual UINT_32 HwlComputeFmaskBits( ++ const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ++ UINT_32* pNumSamples) const; ++ ++ virtual BOOL_32 HwlReduceBankWidthHeight( ++ UINT_32 tileSize, UINT_32 bpp, ADDR_SURFACE_FLAGS flags, UINT_32 numSamples, ++ UINT_32 bankHeightAlign, UINT_32 pipes, ++ ADDR_TILEINFO* pTileInfo) const ++ { ++ return TRUE; ++ } ++ ++ // Protected non-virtual functions ++ VOID ComputeTileCoordFromPipeAndElemIdx( ++ UINT_32 elemIdx, UINT_32 pipe, AddrPipeCfg pipeCfg, UINT_32 pitchInMacroTile, ++ UINT_32 x, UINT_32 y, UINT_32* pX, UINT_32* pY) const; ++ ++ UINT_32 TileCoordToMaskElementIndex( ++ UINT_32 tx, UINT_32 ty, AddrPipeCfg pipeConfig, ++ UINT_32 *macroShift, UINT_32 *elemIdxBits) const; ++ ++ BOOL_32 DecodeGbRegs( ++ const ADDR_REGISTER_VALUE* pRegValue); ++ ++ const ADDR_TILECONFIG* GetTileSetting( ++ UINT_32 index) const; ++ ++ static const UINT_32 TileTableSize = 32; ++ ADDR_TILECONFIG m_tileTable[TileTableSize]; ++ UINT_32 m_noOfEntries; ++ ++private: ++ ++ UINT_32 GetPipePerSurf(AddrPipeCfg pipeConfig) const; ++ ++ VOID ReadGbTileMode( ++ UINT_32 regValue, ADDR_TILECONFIG* pCfg) const; ++ BOOL_32 InitTileSettingTable( ++ const UINT_32 *pSetting, UINT_32 noOfEntries); ++ ++ SIChipSettings m_settings; ++}; ++ ++#endif ++ +diff --git a/src/gallium/winsys/radeon/amdgpu/amdgpu_id.h b/src/gallium/winsys/radeon/amdgpu/amdgpu_id.h +new file mode 100644 +index 0000000..08a1591 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/amdgpu_id.h +@@ -0,0 +1,157 @@ ++/* ++ * 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. ++ */ ++ ++/** ++ * This file is included by addrlib. It adds GPU family definitions and ++ * macros compatible with addrlib. ++ */ ++ ++#ifndef AMDGPU_ID_H ++#define AMDGPU_ID_H ++ ++#include "pipe/p_config.h" ++ ++#if defined(PIPE_ARCH_LITTLE_ENDIAN) ++#define LITTLEENDIAN_CPU ++#elif defined(PIPE_ARCH_BIG_ENDIAN) ++#define BIGENDIAN_CPU ++#endif ++ ++enum { ++ FAMILY_UNKNOWN, ++ FAMILY_SI, ++ FAMILY_CI, ++ FAMILY_KV, ++ FAMILY_VI, ++ FAMILY_CZ, ++ FAMILY_PI, ++ FAMILY_LAST, ++}; ++ ++/* SI specific rev IDs */ ++enum { ++ SI_TAHITI_P_A11 = 1, ++ SI_TAHITI_P_A0 = SI_TAHITI_P_A11, /*A0 is alias of A11*/ ++ SI_TAHITI_P_A21 = 5, ++ SI_TAHITI_P_B0 = SI_TAHITI_P_A21, /*B0 is alias of A21*/ ++ SI_TAHITI_P_A22 = 6, ++ SI_TAHITI_P_B1 = SI_TAHITI_P_A22, /*B1 is alias of A22*/ ++ ++ SI_PITCAIRN_PM_A11 = 20, ++ SI_PITCAIRN_PM_A0 = SI_PITCAIRN_PM_A11, /*A0 is alias of A11*/ ++ SI_PITCAIRN_PM_A12 = 21, ++ SI_PITCAIRN_PM_A1 = SI_PITCAIRN_PM_A12, /*A1 is alias of A12*/ ++ ++ SI_CAPEVERDE_M_A11 = 40, ++ SI_CAPEVERDE_M_A0 = SI_CAPEVERDE_M_A11, /*A0 is alias of A11*/ ++ SI_CAPEVERDE_M_A12 = 41, ++ SI_CAPEVERDE_M_A1 = SI_CAPEVERDE_M_A12, /*A1 is alias of A12*/ ++ ++ SI_OLAND_M_A0 = 60, ++ ++ SI_HAINAN_V_A0 = 70, ++ ++ SI_UNKNOWN = 0xFF ++}; ++ ++ ++#define ASICREV_IS_TAHITI_P(eChipRev) \ ++ (eChipRev < SI_PITCAIRN_PM_A11) ++#define ASICREV_IS_PITCAIRN_PM(eChipRev) \ ++ ((eChipRev >= SI_PITCAIRN_PM_A11) && (eChipRev < SI_CAPEVERDE_M_A11)) ++#define ASICREV_IS_CAPEVERDE_M(eChipRev) \ ++ ((eChipRev >= SI_CAPEVERDE_M_A11) && (eChipRev < SI_OLAND_M_A0)) ++#define ASICREV_IS_OLAND_M(eChipRev) \ ++ ((eChipRev >= SI_OLAND_M_A0) && (eChipRev < SI_HAINAN_V_A0)) ++#define ASICREV_IS_HAINAN_V(eChipRev) \ ++(eChipRev >= SI_HAINAN_V_A0) ++ ++/* CI specific revIDs */ ++enum { ++ CI_BONAIRE_M_A0 = 20, ++ CI_BONAIRE_M_A1 = 21, ++ ++ CI_HAWAII_P_A0 = 40, ++ ++ CI_UNKNOWN = 0xFF ++}; ++ ++#define ASICREV_IS_BONAIRE_M(eChipRev) \ ++ ((eChipRev >= CI_BONAIRE_M_A0) && (eChipRev < CI_HAWAII_P_A0)) ++#define ASICREV_IS_HAWAII_P(eChipRev) \ ++ (eChipRev >= CI_HAWAII_P_A0) ++ ++/* KV specific rev IDs */ ++enum { ++ KV_SPECTRE_A0 = 0x01, /* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */ ++ KV_SPOOKY_A0 = 0x41, /* KV2 with Spooky GFX core, including downgraded from Spectre core, 3-4-1-1 (CU-Pix-Primitive-RB) */ ++ KB_KALINDI_A0 = 0x81, /* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ ++ KB_KALINDI_A1 = 0x82, /* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ ++ BV_KALINDI_A2 = 0x85, /* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ ++ ML_GODAVARI_A0 = 0xa1, /* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ ++ ML_GODAVARI_A1 = 0xa2, /* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */ ++ KV_UNKNOWN = 0xFF ++}; ++ ++#define ASICREV_IS_SPECTRE(eChipRev) \ ++ ((eChipRev >= KV_SPECTRE_A0) && (eChipRev < KV_SPOOKY_A0)) /* identify all versions of SPRECTRE and supported features set */ ++#define ASICREV_IS_SPOOKY(eChipRev) \ ++ ((eChipRev >= KV_SPOOKY_A0) && (eChipRev < KB_KALINDI_A0)) /* identify all versions of SPOOKY and supported features set */ ++#define ASICREV_IS_KALINDI(eChipRev) \ ++ ((eChipRev >= KB_KALINDI_A0) && (eChipRev < KV_UNKNOWN)) /* identify all versions of KALINDI and supported features set */ ++ ++/* Following macros are subset of ASICREV_IS_KALINDI macro */ ++#define ASICREV_IS_KALINDI_BHAVANI(eChipRev) \ ++ ((eChipRev >= BV_KALINDI_A2) && (eChipRev < ML_GODAVARI_A0)) /* identify all versions of BHAVANI and supported features set */ ++#define ASICREV_IS_KALINDI_GODAVARI(eChipRev) \ ++ ((eChipRev >= ML_GODAVARI_A0) && (eChipRev < KV_UNKNOWN)) /* identify all versions of GODAVARI and supported features set */ ++ ++/* VI specific rev IDs */ ++enum { ++ VI_ICELAND_M_A0 = 1, ++ ++ VI_TONGA_P_A0 = 20, ++ VI_TONGA_P_A1 = 21, ++ ++ VI_UNKNOWN = 0xFF ++}; ++ ++ ++#define ASICREV_IS_ICELAND_M(eChipRev) \ ++ (eChipRev < VI_TONGA_P_A0) ++#define ASICREV_IS_TONGA_P(eChipRev) \ ++ (eChipRev >= VI_TONGA_P_A0) ++ ++/* CZ specific rev IDs */ ++enum { ++ CZ_CARRIZO_A0 = 0x01, ++ CZ_UNKNOWN = 0xFF ++}; ++ ++#define ASICREV_IS_CARRIZO(eChipRev) \ ++ (eChipRev >= CARRIZO_A0) ++ ++#endif /* AMDGPU_ID_H */ +diff --git a/src/gallium/winsys/radeon/amdgpu/amdgpu_surface.c b/src/gallium/winsys/radeon/amdgpu/amdgpu_surface.c +new file mode 100644 +index 0000000..aa32413 +--- /dev/null ++++ b/src/gallium/winsys/radeon/amdgpu/amdgpu_surface.c +@@ -0,0 +1,436 @@ ++/* ++ * Copyright © 2011 Red Hat All Rights Reserved. ++ * 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. ++ */ ++ ++/* Contact: ++ * Marek Olšák <maraeo@gmail.com> ++ */ ++ ++#include "amdgpu_winsys.h" ++ ++#ifndef NO_ENTRIES ++#define NO_ENTRIES 32 ++#endif ++ ++#ifndef NO_MACRO_ENTRIES ++#define NO_MACRO_ENTRIES 16 ++#endif ++ ++#ifndef CIASICIDGFXENGINE_SOUTHERNISLAND ++#define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A ++#endif ++ ++ ++static int amdgpu_surface_sanity(const struct radeon_surf *surf) ++{ ++ unsigned type = RADEON_SURF_GET(surf->flags, TYPE); ++ ++ if (!(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) ++ return -EINVAL; ++ ++ /* all dimension must be at least 1 ! */ ++ if (!surf->npix_x || !surf->npix_y || !surf->npix_z || ++ !surf->array_size) ++ return -EINVAL; ++ ++ if (!surf->blk_w || !surf->blk_h || !surf->blk_d) ++ return -EINVAL; ++ ++ switch (surf->nsamples) { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (type) { ++ case RADEON_SURF_TYPE_1D: ++ if (surf->npix_y > 1) ++ return -EINVAL; ++ /* fall through */ ++ case RADEON_SURF_TYPE_2D: ++ case RADEON_SURF_TYPE_CUBEMAP: ++ if (surf->npix_z > 1 || surf->array_size > 1) ++ return -EINVAL; ++ break; ++ case RADEON_SURF_TYPE_3D: ++ if (surf->array_size > 1) ++ return -EINVAL; ++ break; ++ case RADEON_SURF_TYPE_1D_ARRAY: ++ if (surf->npix_y > 1) ++ return -EINVAL; ++ /* fall through */ ++ case RADEON_SURF_TYPE_2D_ARRAY: ++ if (surf->npix_z > 1) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void *ADDR_API allocSysMem(const ADDR_ALLOCSYSMEM_INPUT * pInput) ++{ ++ return malloc(pInput->sizeInBytes); ++} ++ ++static ADDR_E_RETURNCODE ADDR_API freeSysMem(const ADDR_FREESYSMEM_INPUT * pInput) ++{ ++ free(pInput->pVirtAddr); ++ return ADDR_OK; ++} ++ ++/** ++ * This returns the number of banks for the surface. ++ * Possible values: 2, 4, 8, 16. ++ */ ++static uint32_t cik_num_banks(struct amdgpu_winsys *ws, ++ struct radeon_surf *surf) ++{ ++ unsigned index, tileb; ++ ++ tileb = 8 * 8 * surf->bpe; ++ tileb = MIN2(surf->tile_split, tileb); ++ ++ for (index = 0; tileb > 64; index++) { ++ tileb >>= 1; ++ } ++ assert(index < 16); ++ ++ return 2 << ((ws->amdinfo.gb_macro_tile_mode[index] >> 6) & 0x3); ++} ++ ++ADDR_HANDLE amdgpu_addr_create(struct amdgpu_winsys *ws) ++{ ++ ADDR_CREATE_INPUT addrCreateInput = {0}; ++ ADDR_CREATE_OUTPUT addrCreateOutput = {0}; ++ ADDR_REGISTER_VALUE regValue = {0}; ++ ADDR_CREATE_FLAGS createFlags = {{0}}; ++ ADDR_E_RETURNCODE addrRet; ++ ++ addrCreateInput.size = sizeof(ADDR_CREATE_INPUT); ++ addrCreateOutput.size = sizeof(ADDR_CREATE_OUTPUT); ++ ++ regValue.noOfBanks = ws->amdinfo.mc_arb_ramcfg & 0x3; ++ regValue.gbAddrConfig = ws->amdinfo.gb_addr_cfg; ++ regValue.noOfRanks = (ws->amdinfo.mc_arb_ramcfg & 0x4) >> 2; ++ ++ regValue.backendDisables = ws->amdinfo.backend_disable[0]; ++ regValue.pTileConfig = ws->amdinfo.gb_tile_mode; ++ regValue.noOfEntries = sizeof(ws->amdinfo.gb_tile_mode) / ++ sizeof(ws->amdinfo.gb_tile_mode[0]); ++ regValue.pMacroTileConfig = ws->amdinfo.gb_macro_tile_mode; ++ regValue.noOfMacroEntries = sizeof(ws->amdinfo.gb_macro_tile_mode) / ++ sizeof(ws->amdinfo.gb_macro_tile_mode[0]); ++ ++ createFlags.value = 0; ++ createFlags.useTileIndex = 1; ++ createFlags.degradeBaseLevel = 1; ++ ++ addrCreateInput.chipEngine = CIASICIDGFXENGINE_SOUTHERNISLAND; ++ addrCreateInput.chipFamily = ws->family; ++ addrCreateInput.chipRevision = ws->rev_id; ++ addrCreateInput.createFlags = createFlags; ++ addrCreateInput.callbacks.allocSysMem = allocSysMem; ++ addrCreateInput.callbacks.freeSysMem = freeSysMem; ++ addrCreateInput.callbacks.debugPrint = 0; ++ addrCreateInput.regValue = regValue; ++ ++ addrRet = AddrCreate(&addrCreateInput, &addrCreateOutput); ++ if (addrRet != ADDR_OK) ++ return NULL; ++ ++ return addrCreateOutput.hLib; ++} ++ ++static int compute_level(struct amdgpu_winsys *ws, ++ struct radeon_surf *surf, bool is_stencil, ++ unsigned level, unsigned type, bool compressed, ++ ADDR_COMPUTE_SURFACE_INFO_INPUT *AddrSurfInfoIn, ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut) ++{ ++ struct radeon_surf_level *surf_level; ++ ADDR_E_RETURNCODE ret; ++ ++ AddrSurfInfoIn->mipLevel = level; ++ AddrSurfInfoIn->width = u_minify(surf->npix_x, level); ++ AddrSurfInfoIn->height = u_minify(surf->npix_y, level); ++ ++ if (type == RADEON_SURF_TYPE_3D) ++ AddrSurfInfoIn->numSlices = u_minify(surf->npix_z, level); ++ else if (type == RADEON_SURF_TYPE_CUBEMAP) ++ AddrSurfInfoIn->numSlices = 6; ++ else ++ AddrSurfInfoIn->numSlices = surf->array_size; ++ ++ if (level > 0) { ++ /* Set the base level pitch. This is needed for calculation ++ * of non-zero levels. */ ++ if (is_stencil) ++ AddrSurfInfoIn->basePitch = surf->stencil_level[0].nblk_x; ++ else ++ AddrSurfInfoIn->basePitch = surf->level[0].nblk_x; ++ ++ /* Convert blocks to pixels for compressed formats. */ ++ if (compressed) ++ AddrSurfInfoIn->basePitch *= surf->blk_w; ++ } ++ ++ ret = AddrComputeSurfaceInfo(ws->addrlib, ++ AddrSurfInfoIn, ++ AddrSurfInfoOut); ++ if (ret != ADDR_OK) { ++ return ret; ++ } ++ ++ surf_level = is_stencil ? &surf->stencil_level[level] : &surf->level[level]; ++ surf_level->offset = align(surf->bo_size, AddrSurfInfoOut->baseAlign); ++ surf_level->slice_size = AddrSurfInfoOut->sliceSize; ++ surf_level->pitch_bytes = AddrSurfInfoOut->pitch * (is_stencil ? 1 : surf->bpe); ++ surf_level->npix_x = u_minify(surf->npix_x, level); ++ surf_level->npix_y = u_minify(surf->npix_y, level); ++ surf_level->npix_z = u_minify(surf->npix_z, level); ++ surf_level->nblk_x = AddrSurfInfoOut->pitch; ++ surf_level->nblk_y = AddrSurfInfoOut->height; ++ if (type == RADEON_SURF_TYPE_3D) ++ surf_level->nblk_z = AddrSurfInfoOut->depth; ++ else ++ surf_level->nblk_z = 1; ++ ++ switch (AddrSurfInfoOut->tileMode) { ++ case ADDR_TM_LINEAR_GENERAL: ++ surf_level->mode = RADEON_SURF_MODE_LINEAR; ++ break; ++ case ADDR_TM_LINEAR_ALIGNED: ++ surf_level->mode = RADEON_SURF_MODE_LINEAR_ALIGNED; ++ break; ++ case ADDR_TM_1D_TILED_THIN1: ++ surf_level->mode = RADEON_SURF_MODE_1D; ++ break; ++ case ADDR_TM_2D_TILED_THIN1: ++ surf_level->mode = RADEON_SURF_MODE_2D; ++ break; ++ default: ++ assert(0); ++ } ++ ++ if (is_stencil) ++ surf->stencil_tiling_index[level] = AddrSurfInfoOut->tileIndex; ++ else ++ surf->tiling_index[level] = AddrSurfInfoOut->tileIndex; ++ ++ surf->bo_size = surf_level->offset + AddrSurfInfoOut->surfSize; ++ return 0; ++} ++ ++static int amdgpu_surface_init(struct radeon_winsys *rws, ++ struct radeon_surf *surf) ++{ ++ struct amdgpu_winsys *ws = (struct amdgpu_winsys*)rws; ++ unsigned level, mode, type; ++ bool compressed; ++ ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; ++ ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0}; ++ ADDR_TILEINFO AddrTileInfoIn = {0}; ++ ADDR_TILEINFO AddrTileInfoOut = {0}; ++ int r; ++ ++ r = amdgpu_surface_sanity(surf); ++ if (r) ++ return r; ++ ++ AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); ++ AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); ++ AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut; ++ ++ type = RADEON_SURF_GET(surf->flags, TYPE); ++ mode = RADEON_SURF_GET(surf->flags, MODE); ++ compressed = surf->blk_w == 4 && surf->blk_h == 4; ++ ++ /* MSAA and FMASK require 2D tiling. */ ++ if (surf->nsamples > 1 || ++ (surf->flags & RADEON_SURF_FMASK)) ++ mode = RADEON_SURF_MODE_2D; ++ ++ /* DB doesn't support linear layouts. */ ++ if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER) && ++ mode < RADEON_SURF_MODE_1D) ++ mode = RADEON_SURF_MODE_1D; ++ ++ /* Set the requested tiling mode. */ ++ switch (mode) { ++ case RADEON_SURF_MODE_LINEAR: ++ AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_GENERAL; ++ break; ++ case RADEON_SURF_MODE_LINEAR_ALIGNED: ++ AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED; ++ break; ++ case RADEON_SURF_MODE_1D: ++ AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; ++ break; ++ case RADEON_SURF_MODE_2D: ++ AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1; ++ break; ++ default: ++ assert(0); ++ } ++ ++ /* The format must be set correctly for the allocation of compressed ++ * textures to work. In other cases, setting the bpp is sufficient. */ ++ if (compressed) { ++ switch (surf->bpe) { ++ case 8: ++ AddrSurfInfoIn.format = ADDR_FMT_BC1; ++ break; ++ case 16: ++ AddrSurfInfoIn.format = ADDR_FMT_BC3; ++ break; ++ default: ++ assert(0); ++ } ++ } ++ else { ++ AddrSurfInfoIn.bpp = surf->bpe * 8; ++ } ++ ++ AddrSurfInfoIn.numSamples = surf->nsamples; ++ AddrSurfInfoIn.tileIndex = -1; ++ ++ /* Set the micro tile type. */ ++ if (surf->flags & RADEON_SURF_SCANOUT) ++ AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE; ++ else if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) ++ AddrSurfInfoIn.tileType = ADDR_DEPTH_SAMPLE_ORDER; ++ else ++ AddrSurfInfoIn.tileType = ADDR_NON_DISPLAYABLE; ++ ++ AddrSurfInfoIn.flags.color = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER); ++ AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) != 0; ++ AddrSurfInfoIn.flags.stencil = (surf->flags & RADEON_SURF_SBUFFER) != 0; ++ AddrSurfInfoIn.flags.cube = type == RADEON_SURF_TYPE_CUBEMAP; ++ AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0; ++ AddrSurfInfoIn.flags.pow2Pad = surf->last_level > 0; ++ AddrSurfInfoIn.flags.degrade4Space = 1; ++ ++ /* This disables incorrect calculations (hacks) in addrlib. */ ++ AddrSurfInfoIn.flags.noStencil = 1; ++ ++ /* Set preferred macrotile parameters. This is usually required ++ * for shared resources. This is for 2D tiling only. */ ++ if (AddrSurfInfoIn.tileMode >= ADDR_TM_2D_TILED_THIN1 && ++ surf->bankw && surf->bankh && surf->mtilea && surf->tile_split) { ++ /* If any of these parameters are incorrect, the calculation ++ * will fail. */ ++ AddrTileInfoIn.banks = cik_num_banks(ws, surf); ++ AddrTileInfoIn.bankWidth = surf->bankw; ++ AddrTileInfoIn.bankHeight = surf->bankh; ++ AddrTileInfoIn.macroAspectRatio = surf->mtilea; ++ AddrTileInfoIn.tileSplitBytes = surf->tile_split; ++ AddrSurfInfoIn.flags.degrade4Space = 0; ++ AddrSurfInfoIn.pTileInfo = &AddrTileInfoIn; ++ ++ /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set ++ * the tile index, because we are expected to know it if ++ * we know the other parameters. ++ * ++ * This is something that can easily be fixed in Addrlib. ++ * For now, just figure it out here. ++ * Note that only 2D_TILE_THIN1 is handled here. ++ */ ++ assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER)); ++ assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1); ++ ++ if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) ++ AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */ ++ else ++ AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */ ++ } ++ ++ surf->bo_size = 0; ++ ++ /* Calculate texture layout information. */ ++ for (level = 0; level <= surf->last_level; level++) { ++ r = compute_level(ws, surf, false, level, type, compressed, ++ &AddrSurfInfoIn, &AddrSurfInfoOut); ++ if (r) ++ return r; ++ ++ if (level == 0) { ++ surf->bo_alignment = AddrSurfInfoOut.baseAlign; ++ ++ /* For 2D modes only. */ ++ if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { ++ surf->bankw = AddrSurfInfoOut.pTileInfo->bankWidth; ++ surf->bankh = AddrSurfInfoOut.pTileInfo->bankHeight; ++ surf->mtilea = AddrSurfInfoOut.pTileInfo->macroAspectRatio; ++ surf->tile_split = AddrSurfInfoOut.pTileInfo->tileSplitBytes; ++ } ++ } ++ } ++ ++ /* Calculate texture layout information for stencil. */ ++ if (surf->flags & RADEON_SURF_SBUFFER) { ++ AddrSurfInfoIn.bpp = 8; ++ /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */ ++ AddrTileInfoIn.tileSplitBytes = surf->stencil_tile_split; ++ ++ for (level = 0; level <= surf->last_level; level++) { ++ r = compute_level(ws, surf, true, level, type, compressed, ++ &AddrSurfInfoIn, &AddrSurfInfoOut); ++ if (r) ++ return r; ++ ++ if (level == 0) { ++ surf->stencil_offset = surf->stencil_level[0].offset; ++ ++ /* For 2D modes only. */ ++ if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { ++ surf->stencil_tile_split = ++ AddrSurfInfoOut.pTileInfo->tileSplitBytes; ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int amdgpu_surface_best(struct radeon_winsys *rws, ++ struct radeon_surf *surf) ++{ ++ return 0; ++} ++ ++void amdgpu_surface_init_functions(struct amdgpu_winsys *ws) ++{ ++ ws->base.surface_init = amdgpu_surface_init; ++ ws->base.surface_best = amdgpu_surface_best; ++} +diff --git a/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.c b/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.c +index 0f3367a..d3992e9 100644 +--- a/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.c ++++ b/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.c +@@ -39,6 +39,7 @@ + #include <xf86drm.h> + #include <stdio.h> + #include <sys/stat.h> ++#include "amdgpu_id.h" + + #define CIK_TILE_MODE_COLOR_2D 14 + +@@ -198,6 +199,51 @@ static boolean do_winsys_init(struct amdgpu_winsys *ws) + goto fail; + } + ++ /* family and rev_id are for addrlib */ ++ switch (ws->info.family) { ++ case CHIP_BONAIRE: ++ ws->family = FAMILY_CI; ++ ws->rev_id = CI_BONAIRE_M_A0; ++ break; ++ case CHIP_KAVERI: ++ ws->family = FAMILY_KV; ++ ws->rev_id = KV_SPECTRE_A0; ++ break; ++ case CHIP_KABINI: ++ ws->family = FAMILY_KV; ++ ws->rev_id = KB_KALINDI_A0; ++ break; ++ case CHIP_HAWAII: ++ ws->family = FAMILY_CI; ++ ws->rev_id = CI_HAWAII_P_A0; ++ break; ++ case CHIP_MULLINS: ++ ws->family = FAMILY_KV; ++ ws->rev_id = ML_GODAVARI_A0; ++ break; ++ case CHIP_TONGA: ++ ws->family = FAMILY_VI; ++ ws->rev_id = VI_TONGA_P_A0; ++ break; ++ case CHIP_ICELAND: ++ ws->family = FAMILY_VI; ++ ws->rev_id = VI_ICELAND_M_A0; ++ break; ++ case CHIP_CARRIZO: ++ ws->family = FAMILY_CZ; ++ ws->rev_id = CZ_CARRIZO_A0; ++ break; ++ default: ++ fprintf(stderr, "amdgpu: Unknown family.\n"); ++ goto fail; ++ } ++ ++ ws->addrlib = amdgpu_addr_create(ws); ++ if (!ws->addrlib) { ++ fprintf(stderr, "amdgpu: Cannot create addrlib.\n"); ++ goto fail; ++ } ++ + /* Set hardware information. */ + ws->info.gart_size = gtt.heap_size; + ws->info.vram_size = vram.heap_size; +@@ -232,6 +278,8 @@ fail: + if (ws->ctx) { + amdgpu_cs_ctx_free(ws->dev, ws->ctx); + } ++ if (ws->addrlib) ++ AddrDestroy(ws->addrlib); + amdgpu_device_deinitialize(ws->dev); + ws->dev = NULL; + return FALSE; +@@ -251,6 +299,7 @@ static void amdgpu_winsys_destroy(struct radeon_winsys *rws) + + ws->cman->destroy(ws->cman); + ws->kman->destroy(ws->kman); ++ AddrDestroy(ws->addrlib); + + amdgpu_cs_ctx_free(ws->dev, ws->ctx); + amdgpu_device_deinitialize(ws->dev); +@@ -451,6 +500,7 @@ struct radeon_winsys * + + amdgpu_bomgr_init_functions(ws); + amdgpu_cs_init_functions(ws); ++ amdgpu_surface_init_functions(ws); + + pipe_mutex_init(ws->cs_stack_lock); + +diff --git a/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.h b/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.h +index fc27f1c..8755108 100644 +--- a/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.h ++++ b/src/gallium/winsys/radeon/amdgpu/amdgpu_winsys.h +@@ -31,6 +31,7 @@ + #define AMDGPU_DRM_WINSYS_H + + #include "../radeon_winsys.h" ++#include "addrlib/addrinterface.h" + #include "os/os_thread.h" + #include <amdgpu.h> + +@@ -67,6 +68,9 @@ struct amdgpu_winsys { + struct amdgpu_cs *cs_stack[RING_LAST]; + + struct amdgpu_gpu_info amdinfo; ++ ADDR_HANDLE addrlib; ++ uint32_t rev_id; ++ unsigned family; + }; + + static INLINE struct amdgpu_winsys * +@@ -76,5 +80,7 @@ amdgpu_winsys(struct radeon_winsys *base) + } + + void amdgpu_ws_queue_cs(struct amdgpu_winsys *ws, struct amdgpu_cs *cs); ++void amdgpu_surface_init_functions(struct amdgpu_winsys *ws); ++ADDR_HANDLE amdgpu_addr_create(struct amdgpu_winsys *ws); + + #endif +-- +1.9.1 + |