Citro3d
Loading...
Searching...
No Matches
base.c
Go to the documentation of this file.
1#include "internal.h"
2#include <stdlib.h>
3#include <c3d/base.h>
4#include <c3d/effect.h>
5#include <c3d/uniforms.h>
6
8
9static aptHookCookie hookCookie;
10
11__attribute__((weak)) void C3Di_LightEnvUpdate(C3D_LightEnv* env)
12{
13 (void)env;
14}
15
16__attribute__((weak)) void C3Di_LightEnvDirty(C3D_LightEnv* env)
17{
18 (void)env;
19}
20
22{
23 (void)ctx;
24}
25
27{
28 (void)ctx;
29}
30
32{
33 (void)ctx;
34}
35
36static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
37{
38 C3D_Context* ctx = C3Di_GetContext();
39
40 switch (hookType)
41 {
42 case APTHOOK_ONSUSPEND:
43 {
46 break;
47 }
48 case APTHOOK_ONRESTORE:
49 {
54
55 C3Di_DirtyUniforms(GPU_VERTEX_SHADER);
56 C3Di_DirtyUniforms(GPU_GEOMETRY_SHADER);
57
60
61 C3D_LightEnv* env = ctx->lightEnv;
62 if (ctx->fogLut)
63 ctx->flags |= C3DiF_FogLut;
64 if (ctx->gasLut)
65 ctx->flags |= C3DiF_GasLut;
66 if (env)
69 break;
70 }
71 default:
72 break;
73 }
74}
75
76bool C3D_Init(size_t cmdBufSize)
77{
78 int i;
79 C3D_Context* ctx = C3Di_GetContext();
80
81 if (ctx->flags & C3DiF_Active)
82 return false;
83
84 cmdBufSize = (cmdBufSize + 0xF) &~ 0xF; // 0x10-byte align
85 ctx->cmdBufSize = cmdBufSize/4;
86 ctx->cmdBuf = (u32*)linearAlloc(cmdBufSize);
87 ctx->cmdBufUsage = 0;
88 if (!ctx->cmdBuf)
89 return false;
90
91 ctx->gxQueue.maxEntries = 32;
92 ctx->gxQueue.entries = (gxCmdEntry_s*)malloc(ctx->gxQueue.maxEntries*sizeof(gxCmdEntry_s));
93 if (!ctx->gxQueue.entries)
94 {
95 linearFree(ctx->cmdBuf);
96 return false;
97 }
98
100
101 // TODO: replace with direct struct access
102 C3D_DepthMap(true, -1.0f, 0.0f);
103 C3D_CullFace(GPU_CULL_BACK_CCW);
104 C3D_StencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
105 C3D_StencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
107 C3D_EarlyDepthTest(false, GPU_EARLYDEPTH_GREATER, 0);
108 C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
109 C3D_AlphaTest(false, GPU_ALWAYS, 0x00);
110 C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
111 C3D_FragOpMode(GPU_FRAGOPMODE_GL);
112 C3D_FragOpShadow(0.0, 1.0);
113
114 ctx->texConfig = BIT(12);
115 ctx->texShadow = BIT(0);
116 ctx->texEnvBuf = 0;
117 ctx->texEnvBufClr = 0xFFFFFFFF;
118 ctx->fogClr = 0;
119 ctx->fogLut = NULL;
120
121 for (i = 0; i < 3; i ++)
122 ctx->tex[i] = NULL;
123
124 for (i = 0; i < 6; i ++)
125 C3D_TexEnvInit(&ctx->texEnv[i]);
126
127 ctx->fixedAttribDirty = 0;
128 ctx->fixedAttribEverDirty = 0;
129
131 aptHook(&hookCookie, C3Di_AptEventHook, NULL);
132
133 return true;
134}
135
136void C3D_SetViewport(u32 x, u32 y, u32 w, u32 h)
137{
138 C3D_Context* ctx = C3Di_GetContext();
140 ctx->viewport[0] = f32tof24(w / 2.0f);
141 ctx->viewport[1] = f32tof31(2.0f / w) << 1;
142 ctx->viewport[2] = f32tof24(h / 2.0f);
143 ctx->viewport[3] = f32tof31(2.0f / h) << 1;
144 ctx->viewport[4] = (y << 16) | (x & 0xFFFF);
145 ctx->scissor[0] = GPU_SCISSOR_DISABLE;
146}
147
148void C3D_SetScissor(GPU_SCISSORMODE mode, u32 left, u32 top, u32 right, u32 bottom)
149{
150 C3D_Context* ctx = C3Di_GetContext();
151 ctx->flags |= C3DiF_Scissor;
152 ctx->scissor[0] = mode;
153 if (mode == GPU_SCISSOR_DISABLE) return;
154 ctx->scissor[1] = (top << 16) | (left & 0xFFFF);
155 ctx->scissor[2] = ((bottom-1) << 16) | ((right-1) & 0xFFFF);
156}
157
159{
160 int i;
161 C3D_Context* ctx = C3Di_GetContext();
162
163 if (ctx->flags & C3DiF_FrameBuf)
164 {
165 ctx->flags &= ~C3DiF_FrameBuf;
166 if (ctx->flags & C3DiF_DrawUsed)
167 {
168 ctx->flags &= ~C3DiF_DrawUsed;
169 GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 1);
170 GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 1);
171 }
172 C3Di_FrameBufBind(&ctx->fb);
173 }
174
175 if (ctx->flags & C3DiF_Viewport)
176 {
177 ctx->flags &= ~C3DiF_Viewport;
178 GPUCMD_AddIncrementalWrites(GPUREG_VIEWPORT_WIDTH, ctx->viewport, 4);
179 GPUCMD_AddWrite(GPUREG_VIEWPORT_XY, ctx->viewport[4]);
180 }
181
182 if (ctx->flags & C3DiF_Scissor)
183 {
184 ctx->flags &= ~C3DiF_Scissor;
185 GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, ctx->scissor, 3);
186 }
187
188 if (ctx->flags & C3DiF_Program)
189 {
190 shaderProgramConfigure(ctx->program, (ctx->flags & C3DiF_VshCode) != 0, (ctx->flags & C3DiF_GshCode) != 0);
192 }
193
194 if (ctx->flags & C3DiF_AttrInfo)
195 {
196 ctx->flags &= ~C3DiF_AttrInfo;
198 }
199
200 if (ctx->flags & C3DiF_BufInfo)
201 {
202 ctx->flags &= ~C3DiF_BufInfo;
204 }
205
206 if (ctx->flags & C3DiF_Effect)
207 {
208 ctx->flags &= ~C3DiF_Effect;
209 C3Di_EffectBind(&ctx->effect);
210 }
211
212 if (ctx->flags & C3DiF_TexAll)
213 {
214 u32 units = 0;
215 for (i = 0; i < 3; i ++)
216 {
217 if (ctx->tex[i])
218 {
219 units |= BIT(i);
220 if (ctx->flags & C3DiF_Tex(i))
221 C3Di_SetTex(i, ctx->tex[i]);
222 }
223 }
224
225 // Enable texture units and clear texture cache
226 ctx->texConfig &= ~7;
227 ctx->texConfig |= units | BIT(16);
228 ctx->flags &= ~C3DiF_TexAll;
229 ctx->flags |= C3DiF_TexStatus;
230 }
231
232 if (ctx->flags & C3DiF_TexStatus)
233 {
234 ctx->flags &= ~C3DiF_TexStatus;
235 GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0xB, ctx->texConfig);
236 // Clear texture cache if requested *after* configuring texture units
237 if (ctx->texConfig & BIT(16))
238 {
239 ctx->texConfig &= ~BIT(16);
240 GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0x4, BIT(16));
241 }
242 GPUCMD_AddWrite(GPUREG_TEXUNIT0_SHADOW, ctx->texShadow);
243 }
244
247
248 if (ctx->flags & C3DiF_TexEnvBuf)
249 {
250 ctx->flags &= ~C3DiF_TexEnvBuf;
251 GPUCMD_AddMaskedWrite(GPUREG_TEXENV_UPDATE_BUFFER, 0x7, ctx->texEnvBuf);
252 GPUCMD_AddWrite(GPUREG_TEXENV_BUFFER_COLOR, ctx->texEnvBufClr);
253 GPUCMD_AddWrite(GPUREG_FOG_COLOR, ctx->fogClr);
254 }
255
256 if ((ctx->flags & C3DiF_FogLut) && (ctx->texEnvBuf&7) != GPU_NO_FOG)
257 {
258 ctx->flags &= ~C3DiF_FogLut;
259 if (ctx->fogLut)
260 {
261 GPUCMD_AddWrite(GPUREG_FOG_LUT_INDEX, 0);
262 GPUCMD_AddWrites(GPUREG_FOG_LUT_DATA0, ctx->fogLut->data, 128);
263 }
264 }
265
266 if ((ctx->texEnvBuf&7) == GPU_GAS)
267 C3Di_GasUpdate(ctx);
268
269 if (ctx->flags & C3DiF_TexEnvAll)
270 {
271 for (i = 0; i < 6; i ++)
272 {
273 if (!(ctx->flags & C3DiF_TexEnv(i))) continue;
274 C3Di_TexEnvBind(i, &ctx->texEnv[i]);
275 }
276 ctx->flags &= ~C3DiF_TexEnvAll;
277 }
278
279 C3D_LightEnv* env = ctx->lightEnv;
280
281 if (ctx->flags & C3DiF_LightEnv)
282 {
283 u32 enable = env != NULL;
284 GPUCMD_AddWrite(GPUREG_LIGHTING_ENABLE0, enable);
285 GPUCMD_AddWrite(GPUREG_LIGHTING_ENABLE1, !enable);
286 ctx->flags &= ~C3DiF_LightEnv;
287 }
288
289 if (env)
291
292 if (ctx->fixedAttribDirty)
293 {
294 for (i = 0; i < 12; i ++)
295 {
296 if (!(ctx->fixedAttribDirty & BIT(i))) continue;
297 C3D_FVec* v = &ctx->fixedAttribs[i];
298
299 GPUCMD_AddWrite(GPUREG_FIXEDATTRIB_INDEX, i);
300 C3D_ImmSendAttrib(v->x, v->y, v->z, v->w);
301 }
302 ctx->fixedAttribDirty = 0;
303 }
304
305 C3D_UpdateUniforms(GPU_VERTEX_SHADER);
306 C3D_UpdateUniforms(GPU_GEOMETRY_SHADER);
307}
308
309bool C3Di_SplitFrame(u32** pBuf, u32* pSize)
310{
311 C3D_Context* ctx = C3Di_GetContext();
312
313 if (!gpuCmdBufOffset)
314 return false; // Nothing was drawn
315
316 if (ctx->flags & C3DiF_DrawUsed)
317 {
318 ctx->flags &= ~C3DiF_DrawUsed;
319 GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 1);
320 GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 1);
321 GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 1);
322 }
323
324 GPUCMD_Split(pBuf, pSize);
325 u32 totalCmdBufSize = *pBuf + *pSize - ctx->cmdBuf;
326 ctx->cmdBufUsage = (float)totalCmdBufSize / ctx->cmdBufSize;
327 return true;
328}
329
331{
332 return C3Di_GetContext()->cmdBufUsage;
333}
334
335void C3D_Fini(void)
336{
337 C3D_Context* ctx = C3Di_GetContext();
338
339 if (!(ctx->flags & C3DiF_Active))
340 return;
341
342 aptUnhook(&hookCookie);
344 free(ctx->gxQueue.entries);
345 linearFree(ctx->cmdBuf);
346 ctx->flags = 0;
347}
348
349void C3D_BindProgram(shaderProgram_s* program)
350{
351 C3D_Context* ctx = C3Di_GetContext();
352
353 if (!(ctx->flags & C3DiF_Active))
354 return;
355
356 shaderProgram_s* oldProg = ctx->program;
357 shaderInstance_s* newGsh = program->geometryShader;
358 if (oldProg != program)
359 {
360 ctx->program = program;
362
363 if (!oldProg)
365 else
366 {
367 shaderInstance_s* oldGsh = oldProg->geometryShader;
368
369 DVLP_s* oldProgV = oldProg->vertexShader->dvle->dvlp;
370 DVLP_s* oldProgG = oldGsh ? oldGsh->dvle->dvlp : oldProgV;
371
372 DVLP_s* newProgV = program->vertexShader->dvle->dvlp;
373 DVLP_s* newProgG = newGsh ? newGsh->dvle->dvlp : newProgV;
374
375 if (oldProgV != newProgV || (!newGsh && oldProgG != newProgG))
376 ctx->flags |= C3DiF_VshCode;
377 if (oldProgG != newProgG || (newProgG==oldProgV && newProgG->codeSize >= 512))
378 ctx->flags |= C3DiF_GshCode;
379 }
380 }
381
382 C3Di_LoadShaderUniforms(program->vertexShader);
383 if (newGsh)
385 else
386 C3Di_ClearShaderUniforms(GPU_GEOMETRY_SHADER);
387}
388
390{
391 if (id < 0 || id >= 12)
392 return NULL;
393
394 C3D_Context* ctx = C3Di_GetContext();
395
396 if (!(ctx->flags & C3DiF_Active))
397 return NULL;
398
399 ctx->fixedAttribDirty |= BIT(id);
400 ctx->fixedAttribEverDirty |= BIT(id);
401 return &ctx->fixedAttribs[id];
402}
void C3Di_AttrInfoBind(C3D_AttrInfo *info)
Definition: attribs.c:59
bool C3Di_SplitFrame(u32 **pBuf, u32 *pSize)
Definition: base.c:309
void C3D_BindProgram(shaderProgram_s *program)
Definition: base.c:349
void C3Di_UpdateContext(void)
Definition: base.c:158
C3D_Context __C3D_Context
Definition: base.c:7
C3D_FVec * C3D_FixedAttribGetWritePtr(int id)
Definition: base.c:389
void C3D_SetScissor(GPU_SCISSORMODE mode, u32 left, u32 top, u32 right, u32 bottom)
Definition: base.c:148
bool C3D_Init(size_t cmdBufSize)
Definition: base.c:76
float C3D_GetCmdBufUsage(void)
Definition: base.c:330
void C3D_Fini(void)
Definition: base.c:335
void C3D_SetViewport(u32 x, u32 y, u32 w, u32 h)
Definition: base.c:136
__attribute__((weak))
Definition: base.c:11
void C3Di_BufInfoBind(C3D_BufInfo *info)
Definition: buffers.c:49
void C3D_DepthMap(bool bIsZBuffer, float zScale, float zOffset)
Definition: effect.c:10
void C3D_AlphaTest(bool enable, GPU_TESTFUNC function, int ref)
Definition: effect.c:56
void C3Di_EffectBind(C3D_Effect *e)
Definition: effect.c:90
void C3D_CullFace(GPU_CULLMODE mode)
Definition: effect.c:18
void C3D_FragOpMode(GPU_FRAGOPMODE mode)
Definition: effect.c:77
void C3D_StencilTest(bool enable, GPU_TESTFUNC function, int ref, int inputMask, int writeMask)
Definition: effect.c:24
void C3D_FragOpShadow(float scale, float bias)
Definition: effect.c:84
void C3D_StencilOp(GPU_STENCILOP sfail, GPU_STENCILOP dfail, GPU_STENCILOP pass)
Definition: effect.c:30
void C3D_AlphaBlend(GPU_BLENDEQUATION colorEq, GPU_BLENDEQUATION alphaEq, GPU_BLENDFACTOR srcClr, GPU_BLENDFACTOR dstClr, GPU_BLENDFACTOR srcAlpha, GPU_BLENDFACTOR dstAlpha)
Definition: effect.c:62
void C3D_BlendingColor(u32 color)
Definition: effect.c:36
void C3D_DepthTest(bool enable, GPU_TESTFUNC function, GPU_WRITEMASK writemask)
Definition: effect.c:50
void C3D_EarlyDepthTest(bool enable, GPU_EARLYDEPTHFUNC function, u32 ref)
Definition: effect.c:42
void C3Di_FrameBufBind(C3D_FrameBuf *fb)
Definition: framebuffer.c:49
void C3Di_GasUpdate(C3D_Context *ctx)
Definition: gas.c:153
void C3D_ImmSendAttrib(float x, float y, float z, float w)
Definition: immediate.c:28
@ C3DiF_Gas
Definition: internal.h:92
@ C3DiF_AttrInfo
Definition: internal.h:77
@ C3DiF_TexAll
Definition: internal.h:98
@ C3DiF_Scissor
Definition: internal.h:82
@ C3DiF_VshCode
Definition: internal.h:86
@ C3DiF_Effect
Definition: internal.h:79
@ C3DiF_Viewport
Definition: internal.h:81
@ C3DiF_Active
Definition: internal.h:75
@ C3DiF_GshCode
Definition: internal.h:87
@ C3DiF_TexEnvBuf
Definition: internal.h:84
@ C3DiF_FogLut
Definition: internal.h:91
@ C3DiF_ProcTexColorLut
Definition: internal.h:90
@ C3DiF_LightEnv
Definition: internal.h:85
@ C3DiF_DrawUsed
Definition: internal.h:76
@ C3DiF_TexStatus
Definition: internal.h:88
@ C3DiF_BufInfo
Definition: internal.h:78
@ C3DiF_ProcTex
Definition: internal.h:89
@ C3DiF_FrameBuf
Definition: internal.h:80
@ C3DiF_GasLut
Definition: internal.h:93
@ C3DiF_ProcTexLutAll
Definition: internal.h:96
@ C3DiF_Program
Definition: internal.h:83
@ C3DiF_TexEnvAll
Definition: internal.h:100
void C3Di_RenderQueueInit(void)
Definition: renderqueue.c:114
void C3Di_DirtyUniforms(GPU_SHADER_TYPE type)
Definition: uniforms.c:87
#define C3DiF_Tex(n)
Definition: internal.h:97
void C3Di_LoadShaderUniforms(shaderInstance_s *si)
Definition: uniforms.c:99
#define C3DiF_TexEnv(n)
Definition: internal.h:99
void C3Di_RenderQueueDisableVBlank(void)
Definition: renderqueue.c:108
void C3Di_RenderQueueEnableVBlank(void)
Definition: renderqueue.c:102
void C3Di_RenderQueueWaitDone(void)
Definition: renderqueue.c:146
#define C3D_UNUSED
Definition: internal.h:10
void C3Di_SetTex(int unit, C3D_Tex *tex)
Definition: texture.c:265
void C3Di_RenderQueueExit(void)
Definition: renderqueue.c:125
void C3Di_TexEnvBind(int id, C3D_TexEnv *env)
Definition: texenv.c:40
@ C3DiG_BeginAcc
Definition: internal.h:105
@ C3DiG_RenderStage
Definition: internal.h:108
@ C3DiG_AccStage
Definition: internal.h:106
void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type)
Definition: uniforms.c:129
void C3Di_LightEnvDirty(C3D_LightEnv *env)
Definition: lightenv.c:134
void C3Di_LightEnvUpdate(C3D_LightEnv *env)
Definition: lightenv.c:52
void C3Di_ProcTexUpdate(C3D_Context *ctx)
Definition: proctex.c:144
void C3Di_ProcTexDirty(C3D_Context *ctx)
Definition: proctex.c:182
C3D_FVec fixedAttribs[12]
Definition: internal.h:70
u32 flags
Definition: internal.h:38
C3D_BufInfo bufInfo
Definition: internal.h:42
u16 fixedAttribDirty
Definition: internal.h:69
u32 * cmdBuf
Definition: internal.h:34
u32 texConfig
Definition: internal.h:46
u32 gasFlags
Definition: internal.h:58
u16 fixedAttribEverDirty
Definition: internal.h:69
C3D_Tex * tex[3]
Definition: internal.h:48
gxCmdQueue_s gxQueue
Definition: internal.h:33
u32 texEnvBuf
Definition: internal.h:51
u32 scissor[3]
Definition: internal.h:67
C3D_AttrInfo attrInfo
Definition: internal.h:41
C3D_TexEnv texEnv[6]
Definition: internal.h:49
C3D_GasLut * gasLut
Definition: internal.h:59
shaderProgram_s * program
Definition: internal.h:39
u32 fogClr
Definition: internal.h:52
u32 viewport[5]
Definition: internal.h:66
C3D_FogLut * fogLut
Definition: internal.h:53
float cmdBufUsage
Definition: internal.h:36
C3D_Effect effect
Definition: internal.h:43
u32 texShadow
Definition: internal.h:47
C3D_LightEnv * lightEnv
Definition: internal.h:44
size_t cmdBufSize
Definition: internal.h:35
u32 texEnvBufClr
Definition: internal.h:51
C3D_FrameBuf fb
Definition: internal.h:65
void C3D_UpdateUniforms(GPU_SHADER_TYPE type)
Definition: uniforms.c:22