From 5c1d037fa2829b1e5338003296eb153be325c71c Mon Sep 17 00:00:00 2001 From: fincs Date: Tue, 14 Feb 2017 18:24:57 +0100 Subject: [PATCH] Introduce framebuffer (light renderbuffer) infrastructure --- include/c3d/framebuffer.h | 56 +++++++++++++++++++++++++++++++++++++++ include/citro3d.h | 1 + source/base.c | 10 +++---- source/framebuffer.c | 55 ++++++++++++++++++++++++++++++++++++++ source/internal.h | 18 ++++++++++--- source/renderbuffer.c | 41 +++++++++------------------- source/texture.c | 10 ------- 7 files changed, 143 insertions(+), 48 deletions(-) create mode 100644 include/c3d/framebuffer.h create mode 100644 source/framebuffer.c diff --git a/include/c3d/framebuffer.h b/include/c3d/framebuffer.h new file mode 100644 index 0000000..07caad0 --- /dev/null +++ b/include/c3d/framebuffer.h @@ -0,0 +1,56 @@ +#pragma once +#include "texture.h" + +typedef struct +{ + void* colorBuf; + void* depthBuf; + u16 width; + u16 height; + GPU_COLORBUF colorFmt; + GPU_DEPTHBUF depthFmt; + bool block32; + u8 colorMask : 4; + u8 depthMask : 4; +} C3D_FrameBuf; + +C3D_FrameBuf* C3D_GetFrameBuf(void); +void C3D_SetFrameBuf(C3D_FrameBuf* fb); +void C3D_FrameBufTex(C3D_FrameBuf* fb, C3D_Tex* tex, GPU_TEXFACE face, int level); + +static inline void C3D_FrameBufAttrib(C3D_FrameBuf* fb, u16 width, u16 height, bool block32) +{ + fb->width = width; + fb->height = height; + fb->block32 = block32; +} + +static inline void C3D_FrameBufColor(C3D_FrameBuf* fb, void* buf, GPU_COLORBUF fmt) +{ + if (buf) + { + fb->colorBuf = buf; + fb->colorFmt = fmt; + fb->colorMask = 0xF; + } else + { + fb->colorBuf = NULL; + fb->colorFmt = GPU_RB_RGBA8; + fb->colorMask = 0; + } +} + +static inline void C3D_FrameBufDepth(C3D_FrameBuf* fb, void* buf, GPU_DEPTHBUF fmt) +{ + if (buf) + { + fb->depthBuf = buf; + fb->depthFmt = fmt; + fb->depthMask = fmt == GPU_RB_DEPTH24_STENCIL8 ? 0x3 : 0x2; + } else + { + fb->depthBuf = NULL; + fb->depthFmt = GPU_RB_DEPTH24; + fb->depthMask = 0; + } +} diff --git a/include/citro3d.h b/include/citro3d.h index a7df27d..ca1bbd5 100644 --- a/include/citro3d.h +++ b/include/citro3d.h @@ -24,6 +24,7 @@ extern "C" { #include "c3d/light.h" #include "c3d/lightlut.h" +#include "c3d/framebuffer.h" #include "c3d/renderbuffer.h" #include "c3d/renderqueue.h" diff --git a/source/base.c b/source/base.c index a62802b..5dfcf53 100644 --- a/source/base.c +++ b/source/base.c @@ -21,7 +21,7 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param) } case APTHOOK_ONRESTORE: { - ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_RenderBuf + ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_FrameBuf | C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode | C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv; @@ -55,7 +55,7 @@ bool C3D_Init(size_t cmdBufSize) GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0); - ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_Effect | C3DiF_TexAll; + ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_Effect | C3DiF_TexStatus | C3DiF_TexAll; ctx->renderQueueExit = NULL; // TODO: replace with direct struct access @@ -120,16 +120,16 @@ void C3Di_UpdateContext(void) ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode); } - if (ctx->flags & C3DiF_RenderBuf) + if (ctx->flags & C3DiF_FrameBuf) { - ctx->flags &= ~C3DiF_RenderBuf; + ctx->flags &= ~C3DiF_FrameBuf; if (ctx->flags & C3DiF_DrawUsed) { ctx->flags &= ~C3DiF_DrawUsed; GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_FLUSH, 1); GPUCMD_AddWrite(GPUREG_EARLYDEPTH_CLEAR, 1); } - C3Di_RenderBufBind(ctx->rb); + C3Di_FrameBufBind(&ctx->fb); } if (ctx->flags & C3DiF_Viewport) diff --git a/source/framebuffer.c b/source/framebuffer.c new file mode 100644 index 0000000..a28e164 --- /dev/null +++ b/source/framebuffer.c @@ -0,0 +1,55 @@ +#include "internal.h" + +C3D_FrameBuf* C3D_GetFrameBuf(void) +{ + C3D_Context* ctx = C3Di_GetContext(); + + if (!(ctx->flags & C3DiF_Active)) + return NULL; + + ctx->flags |= C3DiF_FrameBuf; + return &ctx->fb; +} + +void C3D_SetFrameBuf(C3D_FrameBuf* fb) +{ + C3D_Context* ctx = C3Di_GetContext(); + + if (!(ctx->flags & C3DiF_Active)) + return; + + if (fb != &ctx->fb) + memcpy(&ctx->fb, fb, sizeof(*fb)); + ctx->flags |= C3DiF_FrameBuf; +} + +void C3D_FrameBufTex(C3D_FrameBuf* fb, C3D_Tex* tex, GPU_TEXFACE face, int level) +{ + C3D_FrameBufAttrib(fb, tex->width, tex->height, false); + C3D_FrameBufColor(fb, C3D_TexGetImagePtr(tex, + C3Di_TexIs2D(tex) ? tex->data : tex->cube->data[face], level, NULL), + (GPU_COLORBUF)tex->fmt); +} + +void C3Di_FrameBufBind(C3D_FrameBuf* fb) +{ + static const u8 colorFmtSizes[] = {2,1,0,0,0}; + u32 param[4] = { 0, 0, 0, 0 }; + + GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 1); + + param[0] = osConvertVirtToPhys(fb->depthBuf) >> 3; + param[1] = osConvertVirtToPhys(fb->colorBuf) >> 3; + param[2] = 0x01000000 | (((u32)(fb->height-1) & 0xFFF) << 12) | (fb->width & 0xFFF); + GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 3); + + GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, param[2]); + GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, fb->depthFmt); + GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, colorFmtSizes[fb->colorFmt] | ((u32)fb->colorFmt << 16)); + GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, fb->block32 ? 1 : 0); + + // Enable or disable color/depth buffers + param[0] = param[1] = fb->colorBuf ? fb->colorMask : 0; + param[2] = param[3] = fb->depthBuf ? fb->depthMask : 0; + GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, param, 4); +} diff --git a/source/internal.h b/source/internal.h index 1be24c1..66d802e 100644 --- a/source/internal.h +++ b/source/internal.h @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #define C3D_UNUSED __attribute__((unused)) @@ -43,7 +43,7 @@ typedef struct u32 texEnvBuf, texEnvBufClr; - C3D_RenderBuf* rb; + C3D_FrameBuf fb; u32 viewport[5]; u32 scissor[3]; @@ -62,7 +62,7 @@ enum C3DiF_AttrInfo = BIT(2), C3DiF_BufInfo = BIT(3), C3DiF_Effect = BIT(4), - C3DiF_RenderBuf = BIT(5), + C3DiF_FrameBuf = BIT(5), C3DiF_Viewport = BIT(6), C3DiF_Scissor = BIT(7), C3DiF_Program = BIT(8), @@ -84,13 +84,23 @@ static inline C3D_Context* C3Di_GetContext(void) return &__C3D_Context; } +static inline bool typeIsCube(GPU_TEXTURE_MODE_PARAM type) +{ + return type == GPU_TEX_CUBE_MAP || type == GPU_TEX_SHADOW_CUBE; +} + +static inline bool C3Di_TexIs2D(C3D_Tex* tex) +{ + return !typeIsCube(C3D_TexGetType(tex)); +} + void C3Di_UpdateContext(void); void C3Di_AttrInfoBind(C3D_AttrInfo* info); void C3Di_BufInfoBind(C3D_BufInfo* info); +void C3Di_FrameBufBind(C3D_FrameBuf* fb); void C3Di_TexEnvBind(int id, C3D_TexEnv* env); void C3Di_SetTex(GPU_TEXUNIT unit, C3D_Tex* tex); void C3Di_EffectBind(C3D_Effect* effect); -void C3Di_RenderBufBind(C3D_RenderBuf* rb); void C3Di_LightMtlBlend(C3D_Light* light); diff --git a/source/renderbuffer.c b/source/renderbuffer.c index 1d919dc..dc748f5 100644 --- a/source/renderbuffer.c +++ b/source/renderbuffer.c @@ -1,5 +1,6 @@ #include "internal.h" #include +#include static const u8 colorFmtSizes[] = {2,1,0,0,0}; static const u8 depthFmtSizes[] = {0,0,1,2}; @@ -16,11 +17,6 @@ static inline u16 getDepthBufFillFlag(int fmt) return BIT(0) | ((u32)depthFmtSizes[fmt] << 8); } -static inline u32 getColorBufFormatReg(int fmt) -{ - return (fmt << 16) | colorFmtSizes[fmt]; -} - static inline GPU_TEXCOLOR colorFmtFromDepthFmt(int fmt) { switch (fmt) @@ -76,33 +72,20 @@ void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags) void C3D_RenderBufBind(C3D_RenderBuf* rb) { C3D_Context* ctx = C3Di_GetContext(); - ctx->flags |= C3DiF_RenderBuf; - ctx->rb = rb; + C3D_FrameBuf* fb = &ctx->fb; + ctx->flags |= C3DiF_FrameBuf; + fb->colorBuf = rb->colorBuf.data; + fb->depthBuf = rb->depthBuf.data; + fb->width = rb->colorBuf.width; + fb->height = rb->colorBuf.height; + fb->colorFmt = (GPU_COLORBUF)rb->colorBuf.fmt; + fb->depthFmt = rb->depthFmt >= 0 ? (GPU_DEPTHBUF)rb->depthFmt : GPU_RB_DEPTH16; + fb->block32 = false; + fb->colorMask = 0xF; + fb->depthMask = 0x2; C3D_SetViewport(0, 0, rb->colorBuf.width, rb->colorBuf.height); } -void C3Di_RenderBufBind(C3D_RenderBuf* rb) -{ - u32 param[4] = { 0, 0, 0, 0 }; - - GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_INVALIDATE, 1); - - param[0] = osConvertVirtToPhys(rb->depthBuf.data) >> 3; - param[1] = osConvertVirtToPhys(rb->colorBuf.data) >> 3; - param[2] = 0x01000000 | (((u32)(rb->colorBuf.height-1) & 0xFFF) << 12) | (rb->colorBuf.width & 0xFFF); - GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 3); - - GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, param[2]); - GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, rb->depthFmt >= 0 ? rb->depthFmt : GPU_RB_DEPTH16); - GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, getColorBufFormatReg(rb->colorBuf.fmt)); - GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); //? - - // Enable or disable color/depth buffers - param[0] = param[1] = rb->colorBuf.data ? 0xF : 0; - param[2] = param[3] = rb->depthBuf.data ? 0x2 : 0; - GPUCMD_AddIncrementalWrites(GPUREG_COLORBUFFER_READ, param, 4); -} - void C3D_RenderBufDelete(C3D_RenderBuf* rb) { C3D_TexDelete(&rb->colorBuf); diff --git a/source/texture.c b/source/texture.c index 4e33e07..edd27a1 100644 --- a/source/texture.c +++ b/source/texture.c @@ -30,16 +30,6 @@ static inline size_t fmtSize(GPU_TEXCOLOR fmt) } } -static inline bool typeIsCube(GPU_TEXTURE_MODE_PARAM type) -{ - return type == GPU_TEX_CUBE_MAP || type == GPU_TEX_SHADOW_CUBE; -} - -static inline bool C3Di_TexIs2D(C3D_Tex* tex) -{ - return !typeIsCube(C3D_TexGetType(tex)); -} - static inline bool addrIsVRAM(const void* addr) { u32 vaddr = (u32)addr;