2#include <c3d/renderqueue.h>
5static inline size_t fmtSize(GPU_TEXCOLOR fmt)
33static inline bool checkTexSize(u32 size)
35 if (size < 8 || size > 1024)
42static inline void allocFree(
void* addr)
50static void C3Di_TexCubeDelete(C3D_TexCube* cube)
53 for (i = 0; i < 6; i ++)
57 allocFree(cube->data[i]);
65 if (!checkTexSize(p.width) || !checkTexSize(p.height))
return false;
67 bool isCube = typeIsCube(p.type);
68 if (isCube && !cube)
return false;
70 u32 size = fmtSize(p.format);
71 if (!size)
return false;
72 size *= (u32)p.width * p.height / 8;
73 u32 total_size = C3D_TexCalcTotalSize(size, p.maxLevel);
77 tex->data = p.onVram ? vramAlloc(total_size) : linearAlloc(total_size);
78 if (!tex->data)
return false;
81 memset(cube, 0,
sizeof(*cube));
83 for (i = 0; i < 6; i ++)
85 cube->data[i] = p.onVram ? vramAlloc(total_size) : linearAlloc(total_size);
87 (i>0 && (((u32)cube->data[0] ^ (u32)cube->data[i])>>(3+22))))
89 C3Di_TexCubeDelete(cube);
97 tex->height = p.height;
98 tex->param = GPU_TEXTURE_MODE(p.type);
99 if (p.format == GPU_ETC1)
100 tex->param |= GPU_TEXTURE_ETC1_PARAM;
101 if (p.type == GPU_TEX_SHADOW_2D || p.type == GPU_TEX_SHADOW_CUBE)
102 tex->param |= GPU_TEXTURE_SHADOW_PARAM;
107 tex->maxLevel = p.maxLevel;
115 void* out = C3D_TexGetImagePtr(tex,
116 C3Di_TexIs2D(tex) ? tex->data : tex->cube->data[face],
119 if (!addrIsVRAM(out))
120 memcpy(out,
data, size);
125static void C3Di_DownscaleRGBA8(u32* dst,
const u32* src[4])
128 for (i = 0; i < 64; i ++)
130 const u32* a = src[i>>4] + (i<<2 & 0x3F);
132 for (j = 0; j < 32; j += 8)
134 u32 val = (((a[0]>>j)&0xFF)+((a[1]>>j)&0xFF)+((a[2]>>j)&0xFF)+((a[3]>>j)&0xFF))>>2;
141static void C3Di_DownscaleRGB8(u8* dst,
const u8* src[4])
144 for (i = 0; i < 64; i ++)
146 const u8* a = src[i>>4] + 3*(i<<2 & 0x3F);
147 for (j = 0; j < 3; j ++)
149 *dst++ = ((u32)a[0] + a[3] + a[6] + a[9])>>2;
158 size_t block_size = (8*8*fmtSize(fmt))/8;
166 void* src = C3Di_TexIs2D(tex) ? tex->data : tex->cube->data[face];
171 u32 level_size = tex->size;
172 u32 src_width = tex->width;
173 u32 src_height = tex->height;
174 for (i = 0; i < tex->maxLevel; i ++)
176 void* dst = (u8*)src + level_size;
177 u32 dst_width = src_width>>1;
178 u32 dst_height = src_height>>1;
188 u32 src_stride = src_width/8;
189 u32 dst_stride = dst_width/8;
190 for (j = 0; j < (dst_height/8); j ++)
192 for (i = 0; i < dst_stride; i ++)
194 void* dst_block = (u8*)dst + block_size*(i + j*dst_stride);
195 const void* src_blocks[4] =
197 (u8*)src + block_size*(2*i+0 + (2*j+0)*src_stride),
198 (u8*)src + block_size*(2*i+1 + (2*j+0)*src_stride),
199 (u8*)src + block_size*(2*i+0 + (2*j+1)*src_stride),
200 (u8*)src + block_size*(2*i+1 + (2*j+1)*src_stride),
205 C3Di_DownscaleRGBA8(dst_block, (
const u32**)src_blocks);
208 C3Di_DownscaleRGB8(dst_block, (
const u8**)src_blocks);
217 src_width = dst_width;
218 src_height = dst_height;
229 if (unitId > 0 && C3D_TexGetType(tex) != GPU_TEX_2D)
233 ctx->
tex[unitId] = tex;
238 if (!addrIsVRAM(tex->data))
239 GSPGPU_FlushDataCache(tex->data, C3D_TexCalcTotalSize(tex->size, tex->maxLevel));
244 if (C3Di_TexIs2D(tex))
245 allocFree(tex->data);
247 C3Di_TexCubeDelete(tex->cube);
257 u32 iBias = (u32)(fabs(bias) * BIT(24));
258 if (iBias >= BIT(24))
261 ctx->
texShadow = (iBias &~ 1) | (perspective ? 0 : 1);
269 reg[0] = tex->border;
272 reg[3] = tex->lodParam;
273 if (C3Di_TexIs2D(tex))
274 reg[4] = osConvertVirtToPhys(tex->data) >> 3;
278 C3D_TexCube* cube = tex->cube;
280 reg[4] = osConvertVirtToPhys(cube->data[0]) >> 3;
281 for (i = 1; i < 6; i ++)
282 reg[4+i] = (osConvertVirtToPhys(cube->data[i]) >> 3) & 0x3FFFFF;
288 GPUCMD_AddIncrementalWrites(GPUREG_TEXUNIT0_BORDER_COLOR, reg, regcount);
289 GPUCMD_AddWrite(GPUREG_TEXUNIT0_TYPE, tex->fmt);
292 GPUCMD_AddIncrementalWrites(GPUREG_TEXUNIT1_BORDER_COLOR, reg, 5);
293 GPUCMD_AddWrite(GPUREG_TEXUNIT1_TYPE, tex->fmt);
296 GPUCMD_AddIncrementalWrites(GPUREG_TEXUNIT2_BORDER_COLOR, reg, 5);
297 GPUCMD_AddWrite(GPUREG_TEXUNIT2_TYPE, tex->fmt);
void C3D_SyncTextureCopy(u32 *inadr, u32 indim, u32 *outadr, u32 outdim, u32 size, u32 flags)
void C3D_TexFlush(C3D_Tex *tex)
void C3D_TexBind(int unitId, C3D_Tex *tex)
void C3Di_SetTex(int unit, C3D_Tex *tex)
void C3D_TexGenerateMipmap(C3D_Tex *tex, GPU_TEXFACE face)
void C3D_TexLoadImage(C3D_Tex *tex, const void *data, GPU_TEXFACE face, int level)
void C3D_TexShadowParams(bool perspective, float bias)
void C3D_TexDelete(C3D_Tex *tex)
bool C3D_TexInitWithParams(C3D_Tex *tex, C3D_TexCube *cube, C3D_TexInitParams p)