1 /*---------------------------------------------------------------------------*
2
3 Copyright 2010-2011 Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12 #if !defined(_TC_PLUGINAPI_INCLUDED_)
13 #define _TC_PLUGINAPI_INCLUDED_
14
15 /// @addtogroup GX2TexUtilGroup
16 /// @{
17
18 #include <tchar.h>
19 #include <assert.h>
20 #include <stdlib.h>
21 #include "Texture.h"
22
23 #if _MSC_VER > 1000
24 #pragma once
25 #endif // _MSC_VER > 1000
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 ///\def MAKEFOURCC(ch0, ch1, ch2, ch3)
31 /// Utility macro for defining a FourCC code.
32 #ifndef MAKEFOURCC
33 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
34 ((u32)(BYTE)(ch0) | ((u32)(BYTE)(ch1) << 8) | \
35 ((u32)(BYTE)(ch2) << 16) | ((u32)(BYTE)(ch3) << 24 ))
36 #endif
37
38 /// A structure for storing compression parameters specific to each codec.
39 typedef struct
40 {
41 void* pPluginSpecific; ///< Usually used as a pointer to a user-defined structure that can contain all the necessary file save options.
42 const TCHAR* pszTextParams; ///< A string containing the command line options for the file handler when the app is called from the command line.
43 } TC_FileSaveParams;
44
45 #ifdef __cplusplus
46 };
47 #endif
48
49 /// \brief Get number of mimpap levels.
50 ///
51 /// \donotcall \notthreadsafe \hostonly \enddonotcall
52 ///
GetNumMipLevels(int nWidth,int nHeight,int nDepth,int nMinMipSize)53 static GX2_INLINE int GetNumMipLevels(int nWidth, int nHeight, int nDepth, int nMinMipSize)
54 {
55 int mipLevels = 1;
56 ASSERT(nWidth > 0 && nHeight > 0 && nDepth > 0);
57
58 while (nWidth > nMinMipSize || nHeight > nMinMipSize || nDepth > nMinMipSize)
59 {
60 mipLevels++;
61 //div by 2
62 nWidth = nWidth > 1 ? nWidth >> 1 : 1;
63 nHeight = nHeight > 1 ? nHeight >> 1 : 1;
64 nDepth = nDepth > 1 ? nDepth>>1 : 1;
65 }
66 return mipLevels;
67 }
68
69 /// \brief Find the max number of faces or slices
70 ///
71 /// \donotcall \notthreadsafe \hostonly \enddonotcall
72 ///
MaxFacesOrSlices(const GX2Surface * pSurface,u32 nMipLevel)73 GX2_INLINE s32 MaxFacesOrSlices(const GX2Surface* pSurface, u32 nMipLevel)
74 {
75 if(!pSurface)
76 {
77 return 0;
78 }
79
80 if(pSurface->depth < 1)
81 {
82 return 0;
83 }
84
85 if(pSurface->dim == GX2_SURFACE_DIM_2D || pSurface->dim == GX2_SURFACE_DIM_CUBE)
86 {
87 return pSurface->depth;
88 }
89 else if(pSurface->dim == GX2_SURFACE_DIM_3D)
90 {
91 u32 count;
92 for(count = 0; count < pSurface->numMips + 1; count++)
93 {
94 int lvlDepth = pSurface->depth;
95 lvlDepth >>= count;
96 lvlDepth = (lvlDepth > 1) ? lvlDepth : 1;
97
98 if(count == nMipLevel)
99 return lvlDepth;
100 }
101 }
102
103 return 0;
104 }
105
106 /// \brief Get Mipmap Size of surface.
107 ///
108 /// \donotcall \notthreadsafe \hostonly \enddonotcall
109 ///
110 #ifdef __cplusplus
111 static GX2_INLINE u32 GetMipSize(const GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice = 0)
112 #else
113 static GX2_INLINE u32 GetMipSize(const GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice)
114 #endif
115 {
116 u32 depthShift;
117 u32 sliceCountThisLevel;
118
119 if(!pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1)))
120 {
121 ASSERT(pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1)));
122 return 0;
123 }
124 if(nMipLevel >= pSurface->numMips)
125 {
126 ASSERT(nMipLevel < pSurface->numMips);
127 return 0;
128 }
129 if(nFaceOrSlice < 0)
130 {
131 return 0; //not an error, indicates requested face doesn't exist
132 }
133
134 depthShift = (pSurface->dim == GX2_SURFACE_DIM_3D) ? nMipLevel : 0;
135 sliceCountThisLevel = ((pSurface->depth >> depthShift) > 1) ? (pSurface->depth >> depthShift) : 1;
136
137 ASSERT(nFaceOrSlice <= sliceCountThisLevel);
138
139 if (!nMipLevel)
140 {
141 return pSurface->imageSize / sliceCountThisLevel;
142 }
143 else if ((pSurface->numMips == 2) && (nMipLevel == 1))
144 {
145 return pSurface->mipSize / sliceCountThisLevel;
146 }
147 else if (nMipLevel == (pSurface->numMips - 1))
148 {
149 return (pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel;
150 }
151 else if (nMipLevel == 1)
152 {
153 return pSurface->mipOffset[nMipLevel] / sliceCountThisLevel;
154 }
155
156 return (pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel;
157 }
158
159 /// \brief Fill MipLevel data structure extracted from GX2Surface with specified nMipLevel and nFaceOrSlice flag
160 ///
161 /// \param pSurface surface data
162 /// \param nMipLevel user specified mipmap level
163 /// \param nFaceOrSlice flag if surface has n-faces or slices
164 /// \param pLevel output MipLevel data
165 ///
166 /// \donotcall \notthreadsafe \hostonly \enddonotcall
167 ///
GetMipLevel(GX2Surface * pSurface,u32 nMipLevel,u32 nFaceOrSlice,MipLevel * pLevel)168 static GX2_INLINE BOOL GetMipLevel(GX2Surface* pSurface, u32 nMipLevel, u32 nFaceOrSlice, MipLevel* pLevel)
169 {
170 u32 depthShift;
171 u32 sliceCountThisLevel;
172
173 if(!pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1)))
174 {
175 ASSERT(pSurface || (!pSurface->mipPtr && (pSurface->numMips > 1)));
176 return 0;
177 }
178 if(nMipLevel >= pSurface->numMips)
179 {
180 ASSERT(nMipLevel < pSurface->numMips);
181 return 0;
182 }
183 if(nFaceOrSlice < 0)
184 {
185 return 0; //not an error, indicates requested face doesn't exist
186 }
187
188 memset(pLevel, 0, sizeof(*pLevel));
189
190 depthShift = (pSurface->dim == GX2_SURFACE_DIM_3D) ? nMipLevel : 0;
191 sliceCountThisLevel = ((pSurface->depth >> depthShift) > 1) ? (pSurface->depth >> depthShift) : 1;
192
193 ASSERT(nFaceOrSlice <= sliceCountThisLevel);
194
195 if (!nMipLevel)
196 {
197 pLevel->pData = (u8*)pSurface->imagePtr + ((pSurface->imageSize / sliceCountThisLevel) * nFaceOrSlice);
198 pLevel->byteSize = pSurface->imageSize / sliceCountThisLevel;
199 }
200 else if ((pSurface->numMips == 2) && (nMipLevel == 1))
201 {
202 pLevel->pData = (u8*)pSurface->mipPtr + ((pSurface->mipSize / sliceCountThisLevel) * nFaceOrSlice);
203 pLevel->byteSize = pSurface->mipSize / sliceCountThisLevel;
204 }
205 else if (nMipLevel == (pSurface->numMips - 1))
206 {
207 pLevel->pData = (u8*)pSurface->mipPtr + pSurface->mipOffset[nMipLevel - 1] + (((pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1])/ sliceCountThisLevel) * nFaceOrSlice);
208 pLevel->byteSize = (pSurface->mipSize - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel;
209 }
210 else if (nMipLevel == 1)
211 {
212 pLevel->pData = (u8*)pSurface->mipPtr + ((pSurface->mipOffset[nMipLevel] / sliceCountThisLevel) * nFaceOrSlice);
213 pLevel->byteSize = pSurface->mipOffset[nMipLevel] / sliceCountThisLevel;
214 }
215 else
216 {
217 pLevel->pData = (u8*)pSurface->mipPtr + pSurface->mipOffset[nMipLevel - 1] + (((pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1])/ sliceCountThisLevel) * nFaceOrSlice);
218 pLevel->byteSize = (pSurface->mipOffset[nMipLevel] - pSurface->mipOffset[nMipLevel - 1]) / sliceCountThisLevel;
219 }
220
221 pLevel->width = pSurface->width >> nMipLevel;
222 pLevel->height = pSurface->height >> nMipLevel;
223
224 if (pLevel->width < 1)
225 {
226 pLevel->width = 1;
227 }
228 if (pLevel->height < 1)
229 {
230 pLevel->height = 1;
231 }
232
233 return TRUE;
234 }
235
236 #include "Texture.h"
237
238 /// @}
239
240 #endif // !defined(_TC_PLUGINAPI_INCLUDED_)
241