Citro3d
Loading...
Searching...
No Matches
proctex.c
Go to the documentation of this file.
1#include "internal.h"
2
3void C3D_ProcTexInit(C3D_ProcTex* pt, int offset, int width)
4{
5 memset(pt, 0, sizeof(*pt));
6 pt->offset = offset;
7 pt->width = width;
8 pt->unknown1 = 0x60;
9 pt->unknown2 = 0xE0C080;
10}
11
12void C3D_ProcTexNoiseCoefs(C3D_ProcTex* pt, int mode, float amplitude, float frequency, float phase)
13{
14 u16 f16_ampl = (s32)(amplitude*0x1000);
15 u16 f16_freq = f32tof16(frequency);
16 u16 f16_phase = f32tof16(phase);
17 pt->enableNoise = true;
18 if (mode & C3D_ProcTex_U)
19 {
20 pt->uNoiseAmpl = f16_ampl;
21 pt->uNoiseFreq = f16_freq;
22 pt->uNoisePhase = f16_phase;
23 }
24 if (mode & C3D_ProcTex_V)
25 {
26 pt->vNoiseAmpl = f16_ampl;
27 pt->vNoiseFreq = f16_freq;
28 pt->vNoisePhase = f16_phase;
29 }
30}
31
32void C3D_ProcTexLodBias(C3D_ProcTex* pt, float bias)
33{
34 u32 f16_bias = f32tof16(bias);
35 pt->lodBiasLow = f16_bias;
36 pt->lodBiasHigh = f16_bias>>8;
37}
38
39void C3D_ProcTexBind(int texCoordId, C3D_ProcTex* pt)
40{
41 C3D_Context* ctx = C3Di_GetContext();
42
43 if (!(ctx->flags & C3DiF_Active))
44 return;
45
46 ctx->flags |= C3DiF_TexStatus;
47 ctx->texConfig &= ~(7<<8);
48 ctx->procTex = pt;
49 if (pt)
50 {
51 ctx->flags |= C3DiF_ProcTex;
52 ctx->texConfig |= BIT(10) | ((texCoordId&3)<<8);
53 } else
54 ctx->flags &= ~C3DiF_ProcTex;
55}
56
57static inline int lutid2idx(GPU_PROCTEX_LUTID id)
58{
59 switch (id)
60 {
61 case GPU_LUT_NOISE: return 0;
62 case GPU_LUT_RGBMAP: return 1;
63 case GPU_LUT_ALPHAMAP: return 2;
64 default: return -1;
65 }
66}
67
68void C3D_ProcTexLutBind(GPU_PROCTEX_LUTID id, C3D_ProcTexLut* lut)
69{
70 C3D_Context* ctx = C3Di_GetContext();
71
72 if (!(ctx->flags & C3DiF_Active))
73 return;
74
75 int idx = lutid2idx(id);
76 if (idx < 0)
77 return;
78
79 ctx->procTexLut[idx] = lut;
80 if (lut)
81 ctx->flags |= C3DiF_ProcTexLut(idx);
82 else
83 ctx->flags &= ~C3DiF_ProcTexLut(idx);
84}
85
86static inline float clampLut(float val)
87{
88 if (val < 0.0f) return 0.0f;
89 if (val > 1.0f) return 1.0f;
90 return val;
91}
92
93void ProcTexLut_FromArray(C3D_ProcTexLut* lut, const float in[129])
94{
95 int i;
96 for (i = 0; i < 128; i ++)
97 {
98 u32 cur = 0xFFF*clampLut(in[i]);
99 u32 next = 0xFFF*clampLut(in[i+1]);
100 u32 diff = (next-cur)&0xFFF;
101 (*lut)[i] = cur | (diff<<12);
102 }
103}
104
105void C3D_ProcTexColorLutBind(C3D_ProcTexColorLut* lut)
106{
107 C3D_Context* ctx = C3Di_GetContext();
108
109 if (!(ctx->flags & C3DiF_Active))
110 return;
111
112 ctx->procTexColorLut = lut;
113 if (lut)
115 else
116 ctx->flags &= ~C3DiF_ProcTexColorLut;
117}
118
119static inline u32 calc_diff(u32 cur, u32 next, int pos)
120{
121 cur = (cur>>pos)&0xFF;
122 next = (next>>pos)&0xFF;
123 u32 diff = (((s32)next-(s32)cur)>>1)&0xFF;
124 return diff<<pos;
125}
126
127void ProcTexColorLut_Write(C3D_ProcTexColorLut* out, const u32* in, int offset, int width)
128{
129 int i;
130 memcpy(&out->color[offset], in, 4*width);
131 for (i = 0; i < (width-1); i ++)
132 {
133 u32 cur = in[i];
134 u32 next = in[i+1];
135 out->diff[offset+i] =
136 calc_diff(cur,next,0) |
137 calc_diff(cur,next,8) |
138 calc_diff(cur,next,16) |
139 calc_diff(cur,next,24);
140 }
141 out->diff[offset+width-1] = 0;
142}
143
145{
146 if (!(ctx->texConfig & BIT(10)))
147 return;
148
149 if (ctx->flags & C3DiF_ProcTex)
150 {
151 ctx->flags &= ~C3DiF_ProcTex;
152 if (ctx->procTex)
153 GPUCMD_AddIncrementalWrites(GPUREG_TEXUNIT3_PROCTEX0, (u32*)ctx->procTex, 6);
154 }
155 if (ctx->flags & C3DiF_ProcTexLutAll)
156 {
157 int i;
158 for (i = 0; i < 3; i ++)
159 {
160 int j = i ? (i+1) : 0;
161 if (!(ctx->flags & C3DiF_ProcTexLut(i)) || !ctx->procTexLut[i])
162 continue;
163
164 GPUCMD_AddWrite(GPUREG_PROCTEX_LUT, j<<8);
165 GPUCMD_AddWrites(GPUREG_PROCTEX_LUT_DATA0, *ctx->procTexLut[i], 128);
166 }
167 ctx->flags &= ~C3DiF_ProcTexLutAll;
168 }
169 if (ctx->flags & C3DiF_ProcTexColorLut)
170 {
171 ctx->flags &= ~C3DiF_ProcTexColorLut;
172 if (ctx->procTexColorLut)
173 {
174 GPUCMD_AddWrite(GPUREG_PROCTEX_LUT, GPU_LUT_COLOR<<8);
175 GPUCMD_AddWrites(GPUREG_PROCTEX_LUT_DATA0, ctx->procTexColorLut->color, 256);
176 GPUCMD_AddWrite(GPUREG_PROCTEX_LUT, GPU_LUT_COLORDIF<<8);
177 GPUCMD_AddWrites(GPUREG_PROCTEX_LUT_DATA0, ctx->procTexColorLut->diff, 256);
178 }
179 }
180}
181
183{
184 int i;
185 if (!ctx->procTex)
186 return;
187
188 ctx->flags |= C3DiF_ProcTex;
189 if (ctx->procTexColorLut)
191 for (i = 0; i < 3; i ++)
192 if (ctx->procTexLut[i])
193 ctx->flags |= C3DiF_ProcTexLut(i);
194}
@ C3DiF_Active
Definition: internal.h:75
@ C3DiF_ProcTexColorLut
Definition: internal.h:90
@ C3DiF_TexStatus
Definition: internal.h:88
@ C3DiF_ProcTex
Definition: internal.h:89
@ C3DiF_ProcTexLutAll
Definition: internal.h:96
#define C3DiF_ProcTexLut(n)
Definition: internal.h:95
void ProcTexColorLut_Write(C3D_ProcTexColorLut *out, const u32 *in, int offset, int width)
Definition: proctex.c:127
void C3D_ProcTexInit(C3D_ProcTex *pt, int offset, int width)
Definition: proctex.c:3
void C3D_ProcTexColorLutBind(C3D_ProcTexColorLut *lut)
Definition: proctex.c:105
void C3D_ProcTexLutBind(GPU_PROCTEX_LUTID id, C3D_ProcTexLut *lut)
Definition: proctex.c:68
void C3Di_ProcTexUpdate(C3D_Context *ctx)
Definition: proctex.c:144
void C3Di_ProcTexDirty(C3D_Context *ctx)
Definition: proctex.c:182
void ProcTexLut_FromArray(C3D_ProcTexLut *lut, const float in[129])
Definition: proctex.c:93
void C3D_ProcTexLodBias(C3D_ProcTex *pt, float bias)
Definition: proctex.c:32
void C3D_ProcTexBind(int texCoordId, C3D_ProcTex *pt)
Definition: proctex.c:39
void C3D_ProcTexNoiseCoefs(C3D_ProcTex *pt, int mode, float amplitude, float frequency, float phase)
Definition: proctex.c:12
u32 flags
Definition: internal.h:38
u32 texConfig
Definition: internal.h:46
C3D_ProcTexColorLut * procTexColorLut
Definition: internal.h:63
C3D_ProcTexLut * procTexLut[3]
Definition: internal.h:62
C3D_ProcTex * procTex
Definition: internal.h:61