citro3d
texture.h
Go to the documentation of this file.
1 /**
2  * @file texture.h
3  * @brief Create and manipulate textures
4  */
5 #pragma once
6 #include "types.h"
7 
8 /// Cubemap texture data
9 typedef struct
10 {
11  void* data[6];
12 } C3D_TexCube;
13 
14 /// Texture data
15 typedef struct
16 {
17  union
18  {
19  void* data;
20  C3D_TexCube* cube;
21  };
22 
23  GPU_TEXCOLOR fmt : 4;
24  size_t size : 28;
25 
26  union
27  {
28  u32 dim;
29  struct
30  {
31  u16 height;
32  u16 width;
33  };
34  };
35 
36  u32 param;
37  u32 border;
38  union
39  {
40  u32 lodParam;
41  struct
42  {
43  u16 lodBias;
44  u8 maxLevel;
45  u8 minLevel;
46  };
47  };
48 } C3D_Tex;
49 
50 /// Parameters for \ref C3D_TexInitWithParams()
51 typedef struct ALIGN(8)
52 {
53  u16 width; ///< Width of texture in pixels. (must be a power of 2)
54  u16 height; ///< Height of texture in pixels. (must be a power of 2)
55  u8 maxLevel : 4; ///< Maximum mipmap level.
56  GPU_TEXCOLOR format : 4; ///< GPU texture format.
57  GPU_TEXTURE_MODE_PARAM type : 3; ///< Texture type
58  bool onVram : 1; ///< Specifies whether to allocate texture data in Vram or linearMemory
60 
61 /**
62  * @brief Initializes texture with specified parameters
63  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
64  * @param[out] cube Pointer to \ref C3D_TexCube. (Only used if texture type is cubemap)
65  * @param[in] p Parameters. See \ref C3D_TexInitParams.
66  * @return True if texture was initialized successfully, otherwise false.
67  */
69 
70 /**
71  * @brief Copies raw texture data into \ref C3D_Tex
72  * @param[out] tex Pointer to \ref C3D_Tex.
73  * @param[in] data Pointer to raw texture data.
74  * @param[in] face Specifies texture face.
75  * @param[in] level Specifies mipmap level.
76  */
77 void C3D_TexLoadImage(C3D_Tex* tex, const void* data, GPU_TEXFACE face, int level);
78 
79 /**
80  * @brief Generates mipmaps for \ref C3D_Tex using previously specified max level
81  * The max level should have been specified using \ref C3D_TexInitMipmap() or \ref C3D_TexInitWithParams()
82  * @note Does not support generating mipmaps for VRAM textures.
83  * @param[in,out] tex Pointer to \ref C3D_Tex.
84  * @param[in] face Specifies texture face.
85  */
87 
88 /**
89  * @brief Binds C3D_Tex to texture unit
90  * @note The 3DS has 3 normal texture units (IDs 0 through 2).
91  * @param[in] unitId Specifies texture unit.
92  * @param[in] tex Pointer to \ref C3D_Tex.
93  */
94 void C3D_TexBind(int unitId, C3D_Tex* tex);
95 
96 /**
97  * @brief Flushes texture data from cache into memory
98  * @param[in] tex Pointer to \ref C3D_Tex.
99  * @sa GSPGPU_FlushDataCache()
100  */
102 
103 /**
104  * @brief Deletes texture data
105  * @param[in] tex Pointer to \ref C3D_Tex.
106  */
108 
109 /**
110  * @brief Configues texunit0 shadow texture properties
111  * @param[in] perspective TODO
112  * @param[in] bias TODO
113  */
114 void C3D_TexShadowParams(bool perspective, float bias);
115 
116 /**
117  * @brief Calculates maximum mipmap level for given texture size
118  * @param[in] width Width of texture.
119  * @param[in] height Height of texture.
120  * @returns Calculated maximum mipmap level.
121  */
122 static inline int C3D_TexCalcMaxLevel(u32 width, u32 height)
123 {
124  return (31-__builtin_clz(width < height ? width : height)) - 3; // avoid sizes smaller than 8
125 }
126 
127 /**
128  * @brief Calculates size of mipmap level
129  * @param[in] size Size of original texture.
130  * @param[in] level Mipmap level.
131  * @returns Calculated level size.
132  */
133 static inline u32 C3D_TexCalcLevelSize(u32 size, int level)
134 {
135  return size >> (2*level);
136 }
137 
138 /**
139  * @brief Calculates total size of mipmap texture data
140  * @param[in] size Size of original texture.
141  * @param[in] maxLevel Maximum mipmap level.
142  * @returns Calculated total size.
143  */
144 static inline u32 C3D_TexCalcTotalSize(u32 size, int maxLevel)
145 {
146  /*
147  S = s + sr + sr^2 + sr^3 + ... + sr^n
148  Sr = sr + sr^2 + sr^3 + ... + sr^(n+1)
149  S-Sr = s - sr^(n+1)
150  S(1-r) = s(1 - r^(n+1))
151  S = s (1 - r^(n+1)) / (1-r)
152 
153  r = 1/4
154  1-r = 3/4
155 
156  S = 4s (1 - (1/4)^(n+1)) / 3
157  S = 4s (1 - 1/4^(n+1)) / 3
158  S = (4/3) (s - s/4^(n+1))
159  S = (4/3) (s - s/(1<<(2n+2)))
160  S = (4/3) (s - s>>(2n+2))
161  */
162  return (size - C3D_TexCalcLevelSize(size,maxLevel+1)) * 4 / 3;
163 }
164 
165 /**
166  * @brief Initializes standard 2D texture
167  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
168  * @param[in] width Specifies width of texture. (must be a power of 2)
169  * @param[in] height Specifies height of texture. (must be a power of 2)
170  * @param[in] format Specifies texture format.
171  * @return True if texture was initialized successfully, otherwise false.
172  */
173 static inline bool C3D_TexInit(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
174 {
175  return C3D_TexInitWithParams(tex, NULL,
176  (C3D_TexInitParams){ width, height, 0, format, GPU_TEX_2D, false });
177 }
178 
179 /**
180  * @brief Initializes standard 2D texture with mipmap
181  * Maximum miplevel is calculated using \ref C3D_TexCalcMaxLevel()
182  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
183  * @param[in] width Specifies width of texture. (must be a power of 2)
184  * @param[in] height Specifies height of texture. (must be a power of 2)
185  * @param[in] format Specifies texture format.
186  * @return True if texture was initialized successfully, otherwise false.
187  */
188 static inline bool C3D_TexInitMipmap(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
189 {
190  return C3D_TexInitWithParams(tex, NULL,
191  (C3D_TexInitParams){ width, height, (u8)C3D_TexCalcMaxLevel(width, height), format, GPU_TEX_2D, false });
192 }
193 
194 /**
195  * @brief Initializes cubemap texture
196  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
197  * @param[out] cube Pointer to \ref C3D_TexCube.
198  * @param[in] width Specifies width of texture. (must be a power of 2)
199  * @param[in] height Specifies height of texture. (must be a power of 2)
200  * @param[in] format Specifies texture format.
201  * @return True if texture was initialized successfully, otherwise false.
202  */
203 static inline bool C3D_TexInitCube(C3D_Tex* tex, C3D_TexCube* cube, u16 width, u16 height, GPU_TEXCOLOR format)
204 {
205  return C3D_TexInitWithParams(tex, cube,
206  (C3D_TexInitParams){ width, height, 0, format, GPU_TEX_CUBE_MAP, false });
207 }
208 
209 /**
210  * @brief Initializes 2D texture in VRAM
211  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
212  * @param[in] width Specifies width of texture. (must be a power of 2)
213  * @param[in] height Specifies height of texture. (must be a power of 2)
214  * @param[in] format Specifies texture format.
215  * @return True if texture was initialized successfully, otherwise false.
216  */
217 static inline bool C3D_TexInitVRAM(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
218 {
219  return C3D_TexInitWithParams(tex, NULL,
220  (C3D_TexInitParams){ width, height, 0, format, GPU_TEX_2D, true });
221 }
222 
223 /**
224  * @brief Initializes 2D shadowmap texture
225  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
226  * @param[in] width Specifies width of texture. (must be a power of 2)
227  * @param[in] height Specifies height of texture. (must be a power of 2)
228  * @return True if texture was initialized successfully, otherwise false.
229  */
230 static inline bool C3D_TexInitShadow(C3D_Tex* tex, u16 width, u16 height)
231 {
232  return C3D_TexInitWithParams(tex, NULL,
233  (C3D_TexInitParams){ width, height, 0, GPU_RGBA8, GPU_TEX_SHADOW_2D, true });
234 }
235 
236 /**
237  * @brief Initializes shadowmap cubemap texture
238  * @param[out] tex Pointer to uninitialized \ref C3D_Tex.
239  * @param[out] cube Pointer to \ref C3D_TexCube.
240  * @param[in] width Specifies width of texture. (must be a power of 2)
241  * @param[in] height Specifies height of texture. (must be a power of 2)
242  * @return True if texture was initialized successfully, otherwise false.
243  */
244 static inline bool C3D_TexInitShadowCube(C3D_Tex* tex, C3D_TexCube* cube, u16 width, u16 height)
245 {
246  return C3D_TexInitWithParams(tex, cube,
247  (C3D_TexInitParams){ width, height, 0, GPU_RGBA8, GPU_TEX_SHADOW_CUBE, true });
248 }
249 
250 /**
251  * @brief Gets type of texture
252  * @param[in] tex Pointer to \ref C3D_Tex.
253  */
255 {
256  return (GPU_TEXTURE_MODE_PARAM)((tex->param>>28)&0x7);
257 }
258 
259 /**
260  * @brief Gets pointer to texture image
261  * @param[in] tex Pointer to \ref C3D_Tex.
262  * @param[in] data Pointer texture face.
263  * @param[in] level Specifies mipmap level.
264  * @param[out] size Can be used to get the size of the image data.
265  * @returns Pointer to raw image data.
266  */
267 static inline void* C3D_TexGetImagePtr(C3D_Tex* tex, void* data, int level, u32* size)
268 {
269  if (size) *size = level >= 0 ? C3D_TexCalcLevelSize(tex->size, level) : C3D_TexCalcTotalSize(tex->size, tex->maxLevel);
270  if (!level) return data;
271  return (u8*)data + (level > 0 ? C3D_TexCalcTotalSize(tex->size, level-1) : 0);
272 }
273 
274 /**
275  * @brief Gets pointer to 2D texture image
276  * @param[in] tex Pointer to \ref C3D_Tex.
277  * @param[in] level Specifies mipmap level.
278  * @param[out] size Can be used to get the size of the image data.
279  * @returns Pointer to raw image data.
280  */
281 static inline void* C3D_Tex2DGetImagePtr(C3D_Tex* tex, int level, u32* size)
282 {
283  return C3D_TexGetImagePtr(tex, tex->data, level, size);
284 }
285 
286 /**
287  * @brief Gets pointer to cubemap texture image
288  * @param[in] tex Pointer to \ref C3D_Tex.
289  * @param[in] face Specifies the cubemap texture face.
290  * @param[in] level Specifies mipmap level.
291  * @param[out] size Can be used to get the size of the image data.
292  * @returns Pointer to raw image data.
293  */
294 static inline void* C3D_TexCubeGetImagePtr(C3D_Tex* tex, GPU_TEXFACE face, int level, u32* size)
295 {
296  return C3D_TexGetImagePtr(tex, tex->cube->data[face], level, size);
297 }
298 
299 /**
300  * @brief Copies raw texture data into standard 2D texture
301  * @param[out] tex Pointer to \ref C3D_Tex.
302  * @param[in] data Pointer to raw texture data.
303  */
304 static inline void C3D_TexUpload(C3D_Tex* tex, const void* data)
305 {
306  C3D_TexLoadImage(tex, data, GPU_TEXFACE_2D, 0);
307 }
308 
309 /**
310  * @brief Configures texture magnification and minification filters
311  * @param[out] tex Pointer to \ref C3D_Tex.
312  * @param[in] magFilter Specifies the filtering to use when magnifying the the texture.
313  * @param[in] minFilter Specifies the filtering to use when minifying the the texture.
314  */
315 static inline void C3D_TexSetFilter(C3D_Tex* tex, GPU_TEXTURE_FILTER_PARAM magFilter, GPU_TEXTURE_FILTER_PARAM minFilter)
316 {
318  tex->param |= GPU_TEXTURE_MAG_FILTER(magFilter) | GPU_TEXTURE_MIN_FILTER(minFilter);
319 }
320 
321 /**
322  * @brief Configures texture mipmap minification filters
323  * @param[out] tex Pointer to \ref C3D_Tex.
324  * @param[in] filter Specifies the filtering to use when minifying the the mipmap.
325  */
327 {
328  tex->param &= ~GPU_TEXTURE_MIP_FILTER(GPU_LINEAR);
329  tex->param |= GPU_TEXTURE_MIP_FILTER(filter);
330 }
331 
332 /**
333  * @brief Configures texture wrapping options
334  * @param[out] tex Pointer to \ref C3D_Tex.
335  * @param[in] wrapS Specifies the texture wrapping mode for texture coordinate S (aka U).
336  * @param[in] wrapT Specifies the texture wrapping mode for texture coordinate T (aka V).
337  */
339 {
340  tex->param &= ~(GPU_TEXTURE_WRAP_S(3) | GPU_TEXTURE_WRAP_T(3));
341  tex->param |= GPU_TEXTURE_WRAP_S(wrapS) | GPU_TEXTURE_WRAP_T(wrapT);
342 }
343 
344 /**
345  * @brief Configures texture level of detail bias used to select the correct mipmap during sampling
346  * @param[out] tex Pointer to \ref C3D_Tex.
347  * @param[in] lodBias Specifies the texture level of detail bias.
348  */
349 static inline void C3D_TexSetLodBias(C3D_Tex* tex, float lodBias)
350 {
351  int iLodBias = (int)(lodBias*0x100);
352  if (iLodBias > 0xFFF)
353  iLodBias = 0xFFF;
354  else if (iLodBias < -0x1000)
355  iLodBias = -0x1000;
356  tex->lodBias = iLodBias & 0x1FFF;
357 }
#define GPU_TEXTURE_MAG_FILTER(v)
#define GPU_TEXTURE_MIP_FILTER(v)
GPU_TEXTURE_FILTER_PARAM
GPU_LINEAR
GPU_TEXFACE
GPU_TEXFACE_2D
GPU_TEXTURE_MODE_PARAM
GPU_TEX_SHADOW_2D
GPU_TEX_SHADOW_CUBE
GPU_TEX_2D
GPU_TEX_CUBE_MAP
GPU_TEXCOLOR
GPU_RGBA8
#define GPU_TEXTURE_WRAP_S(v)
#define GPU_TEXTURE_WRAP_T(v)
#define GPU_TEXTURE_MIN_FILTER(v)
GPU_TEXTURE_WRAP_PARAM
Cubemap texture data.
Definition: texture.h:10
Parameters for C3D_TexInitWithParams()
Definition: texture.h:52
GPU_TEXTURE_MODE_PARAM type
Texture type.
Definition: texture.h:57
u16 height
Height of texture in pixels. (must be a power of 2)
Definition: texture.h:54
u16 width
Width of texture in pixels. (must be a power of 2)
Definition: texture.h:53
u8 maxLevel
Maximum mipmap level.
Definition: texture.h:55
bool onVram
Specifies whether to allocate texture data in Vram or linearMemory.
Definition: texture.h:58
GPU_TEXCOLOR format
GPU texture format.
Definition: texture.h:56
Texture data.
Definition: texture.h:16
static bool C3D_TexInit(C3D_Tex *tex, u16 width, u16 height, GPU_TEXCOLOR format)
Initializes standard 2D texture.
Definition: texture.h:173
static bool C3D_TexInitShadow(C3D_Tex *tex, u16 width, u16 height)
Initializes 2D shadowmap texture.
Definition: texture.h:230
static bool C3D_TexInitMipmap(C3D_Tex *tex, u16 width, u16 height, GPU_TEXCOLOR format)
Initializes standard 2D texture with mipmap Maximum miplevel is calculated using C3D_TexCalcMaxLevel(...
Definition: texture.h:188
void C3D_TexFlush(C3D_Tex *tex)
Flushes texture data from cache into memory.
void C3D_TexBind(int unitId, C3D_Tex *tex)
Binds C3D_Tex to texture unit.
static int C3D_TexCalcMaxLevel(u32 width, u32 height)
Calculates maximum mipmap level for given texture size.
Definition: texture.h:122
static void C3D_TexUpload(C3D_Tex *tex, const void *data)
Copies raw texture data into standard 2D texture.
Definition: texture.h:304
static bool C3D_TexInitVRAM(C3D_Tex *tex, u16 width, u16 height, GPU_TEXCOLOR format)
Initializes 2D texture in VRAM.
Definition: texture.h:217
static void * C3D_TexCubeGetImagePtr(C3D_Tex *tex, GPU_TEXFACE face, int level, u32 *size)
Gets pointer to cubemap texture image.
Definition: texture.h:294
static GPU_TEXTURE_MODE_PARAM C3D_TexGetType(C3D_Tex *tex)
Gets type of texture.
Definition: texture.h:254
static void * C3D_TexGetImagePtr(C3D_Tex *tex, void *data, int level, u32 *size)
Gets pointer to texture image.
Definition: texture.h:267
static bool C3D_TexInitCube(C3D_Tex *tex, C3D_TexCube *cube, u16 width, u16 height, GPU_TEXCOLOR format)
Initializes cubemap texture.
Definition: texture.h:203
static void C3D_TexSetFilter(C3D_Tex *tex, GPU_TEXTURE_FILTER_PARAM magFilter, GPU_TEXTURE_FILTER_PARAM minFilter)
Configures texture magnification and minification filters.
Definition: texture.h:315
static void C3D_TexSetLodBias(C3D_Tex *tex, float lodBias)
Configures texture level of detail bias used to select the correct mipmap during sampling.
Definition: texture.h:349
void C3D_TexGenerateMipmap(C3D_Tex *tex, GPU_TEXFACE face)
Generates mipmaps for C3D_Tex using previously specified max level The max level should have been spe...
void C3D_TexLoadImage(C3D_Tex *tex, const void *data, GPU_TEXFACE face, int level)
Copies raw texture data into C3D_Tex.
static void C3D_TexSetFilterMipmap(C3D_Tex *tex, GPU_TEXTURE_FILTER_PARAM filter)
Configures texture mipmap minification filters.
Definition: texture.h:326
void C3D_TexShadowParams(bool perspective, float bias)
Configues texunit0 shadow texture properties.
static u32 C3D_TexCalcTotalSize(u32 size, int maxLevel)
Calculates total size of mipmap texture data.
Definition: texture.h:144
void C3D_TexDelete(C3D_Tex *tex)
Deletes texture data.
static bool C3D_TexInitShadowCube(C3D_Tex *tex, C3D_TexCube *cube, u16 width, u16 height)
Initializes shadowmap cubemap texture.
Definition: texture.h:244
static void C3D_TexSetWrap(C3D_Tex *tex, GPU_TEXTURE_WRAP_PARAM wrapS, GPU_TEXTURE_WRAP_PARAM wrapT)
Configures texture wrapping options.
Definition: texture.h:338
static u32 C3D_TexCalcLevelSize(u32 size, int level)
Calculates size of mipmap level.
Definition: texture.h:133
bool C3D_TexInitWithParams(C3D_Tex *tex, C3D_TexCube *cube, C3D_TexInitParams p)
Initializes texture with specified parameters.
static void * C3D_Tex2DGetImagePtr(C3D_Tex *tex, int level, u32 *size)
Gets pointer to 2D texture image.
Definition: texture.h:281
uint8_t u8
uint16_t u16
#define ALIGN(m)
uint32_t u32