/*---------------------------------------------------------------------------* Copyright (C) Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #if !defined(_TC_PLUGINAPI_INCLUDED_) #define _TC_PLUGINAPI_INCLUDED_ /// @addtogroup GX2TexUtilGroup /// @{ #include #include #include #include "Texture.h" #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifdef __cplusplus extern "C" { #endif ///\def MAKEFOURCC(ch0, ch1, ch2, ch3) /// Utility macro for defining a FourCC code. #ifndef MAKEFOURCC #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ ((u32)(BYTE)(ch0) | ((u32)(BYTE)(ch1) << 8) | \ ((u32)(BYTE)(ch2) << 16) | ((u32)(BYTE)(ch3) << 24 )) #endif /// A structure for storing compression parameters specific to each codec. typedef struct { void* pPluginSpecific; ///< Usually used as a pointer to a user-defined structure that can contain all the necessary file save options. const TCHAR* pszTextParams; ///< A string containing the command line options for the file handler when the app is called from the command line. } TC_FileSaveParams; #ifdef __cplusplus }; #endif /// \brief Get number of mipmap levels. /// /// \donotcall \notthreadsafe \hostonly \enddonotcall /// static GX2_INLINE int GetNumMipLevels(int nWidth, int nHeight, int nDepth, int nMinMipSize) { int mipLevels = 1; ASSERT(nWidth > 0 && nHeight > 0 && nDepth > 0); while (nWidth > nMinMipSize || nHeight > nMinMipSize || nDepth > nMinMipSize) { mipLevels++; //div by 2 nWidth = nWidth > 1 ? nWidth >> 1 : 1; nHeight = nHeight > 1 ? nHeight >> 1 : 1; nDepth = nDepth > 1 ? nDepth>>1 : 1; } return mipLevels; } /// \brief Find the max number of faces or slices /// /// \donotcall \notthreadsafe \hostonly \enddonotcall /// GX2_INLINE s32 MaxFacesOrSlices(const GX2Surface* pSurface, u32 nMipLevel) { if(!pSurface) { return 0; } if(pSurface->depth < 1) { return 0; } if(pSurface->dim == GX2_SURFACE_DIM_2D || pSurface->dim == GX2_SURFACE_DIM_CUBE) { return pSurface->depth; } else if(pSurface->dim == GX2_SURFACE_DIM_3D) { u32 count; for(count = 0; count < pSurface->numMips + 1; count++) { int lvlDepth = pSurface->depth; lvlDepth >>= count; lvlDepth = (lvlDepth > 1) ? lvlDepth : 1; if(count == nMipLevel) return lvlDepth; } } return 0; } /// \brief Get Mipmap Size of surface. /// /// \donotcall \notthreadsafe \hostonly \enddonotcall /// #ifdef __cplusplus static GX2_INLINE u32 GetMipSize(const GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice = 0) #else static GX2_INLINE u32 GetMipSize(const GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice) #endif { u32 depthShift; u32 sliceCountThisLevel; if(!pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1))) { ASSERT(pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1))); return 0; } if(nMipLevel >= pSurface->numMips) { ASSERT(nMipLevel < pSurface->numMips); return 0; } if(nFaceOrSlice < 0) { return 0; //not an error, indicates requested face doesn't exist } depthShift = (pSurface->dim == GX2_SURFACE_DIM_3D) ? nMipLevel : 0; sliceCountThisLevel = ((pSurface->depth >> depthShift) > 1) ? (pSurface->depth >> depthShift) : 1; ASSERT(nFaceOrSlice <= sliceCountThisLevel); if (!nMipLevel) { return pSurface->imageSize / sliceCountThisLevel; } else if ((pSurface->numMips == 2) && (nMipLevel == 1)) { return pSurface->mipSize / sliceCountThisLevel; } else if (nMipLevel == (pSurface->numMips - 1)) { return (pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel; } else if (nMipLevel == 1) { return pSurface->mipOffset[nMipLevel] / sliceCountThisLevel; } return (pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel; } /// \brief Fill MipLevel data structure extracted from GX2Surface with specified nMipLevel and nFaceOrSlice flag /// /// \param pSurface surface data /// \param nMipLevel user specified mipmap level /// \param nFaceOrSlice flag if surface has n-faces or slices /// \param pLevel output MipLevel data /// /// \donotcall \notthreadsafe \hostonly \enddonotcall /// static GX2_INLINE BOOL GetMipLevel(GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice, MipLevel* pLevel) { u32 depthShift; u32 sliceCountThisLevel; if(!pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1))) { ASSERT(pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1))); return 0; } if(nMipLevel >= pSurface->numMips) { ASSERT(nMipLevel < pSurface->numMips); return 0; } if(nFaceOrSlice < 0) { return 0; //not an error, indicates requested face doesn't exist } memset(pLevel, 0, sizeof(*pLevel)); depthShift = (pSurface->dim == GX2_SURFACE_DIM_3D) ? nMipLevel : 0; sliceCountThisLevel = ((pSurface->depth >> depthShift) > 1) ? (pSurface->depth >> depthShift) : 1; ASSERT(nFaceOrSlice <= sliceCountThisLevel); if (!nMipLevel) { pLevel->pData = (u8*)pSurface->imagePtr + ((pSurface->imageSize / sliceCountThisLevel) * nFaceOrSlice); pLevel->byteSize = pSurface->imageSize / sliceCountThisLevel; } else if ((pSurface->numMips == 2) && (nMipLevel == 1)) { pLevel->pData = (u8*)pSurface->mipPtr + ((pSurface->mipSize / sliceCountThisLevel) * nFaceOrSlice); pLevel->byteSize = pSurface->mipSize / sliceCountThisLevel; } else if (nMipLevel == (pSurface->numMips - 1)) { pLevel->pData = (u8*)pSurface->mipPtr + pSurface->mipOffset[nMipLevel - 1] + (((pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1])/ sliceCountThisLevel) * nFaceOrSlice); pLevel->byteSize = (pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel; } else if (nMipLevel == 1) { pLevel->pData = (u8*)pSurface->mipPtr + ((pSurface->mipOffset[nMipLevel] / sliceCountThisLevel) * nFaceOrSlice); pLevel->byteSize = pSurface->mipOffset[nMipLevel] / sliceCountThisLevel; } else { pLevel->pData = (u8*)pSurface->mipPtr + pSurface->mipOffset[nMipLevel - 1] + (((pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1])/ sliceCountThisLevel) * nFaceOrSlice); pLevel->byteSize = (pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel; } pLevel->width = pSurface->width >> nMipLevel; pLevel->height = pSurface->height >> nMipLevel; if (pLevel->width < 1) { pLevel->width = 1; } if (pLevel->height < 1) { pLevel->height = 1; } return TRUE; } #include "Texture.h" /// @} #endif // !defined(_TC_PLUGINAPI_INCLUDED_)