citro3d/source/renderbuffer.c

100 lines
2.7 KiB
C

#include "context.h"
static const u8 colorFmtSizes[] = {2,1,0,0,0};
static const u8 depthFmtSizes[] = {0,0,1,2};
static inline u32 calcColorBufSize(u32 width, u32 height, u32 fmt)
{
return width*height*(colorFmtSizes[fmt]+2);
}
static inline u32 calcDepthBufSize(u32 width, u32 height, u32 fmt)
{
return width*height*(depthFmtSizes[fmt]+2);
}
bool C3D_RenderBufInit(C3D_RenderBuf* rb, int width, int height, int colorFmt, int depthFmt)
{
if (rb->colorBuf || rb->depthBuf) return false;
rb->colorFmt = colorFmt;
rb->depthFmt = depthFmt;
rb->width = width;
rb->height = height;
rb->clearColor = rb->clearDepth = 0;
rb->colorBuf = vramAlloc(calcColorBufSize(width, height, colorFmt));
if (!rb->colorBuf) return false;
rb->depthBuf = vramAlloc(calcDepthBufSize(width, height, depthFmt));
if (!rb->depthBuf)
{
vramFree(rb->colorBuf);
rb->colorBuf = NULL;
return false;
}
return true;
}
void C3D_RenderBufClearAsync(C3D_RenderBuf* rb)
{
u32 colorBufSize = calcColorBufSize(rb->width, rb->height, rb->colorFmt);
u32 depthBufSize = calcDepthBufSize(rb->width, rb->height, rb->depthFmt);
GX_SetMemoryFill(NULL,
(u32*)rb->colorBuf, rb->clearColor, (u32*)((u8*)rb->colorBuf+colorBufSize), BIT(0) | ((u32)colorFmtSizes[rb->colorFmt] << 8),
(u32*)rb->depthBuf, rb->clearDepth, (u32*)((u8*)rb->depthBuf+depthBufSize), BIT(0) | ((u32)colorFmtSizes[rb->depthFmt] << 8));
}
void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags)
{
u32 dim = GX_BUFFER_DIM((u32)rb->width, (u32)rb->height);
GX_SetDisplayTransfer(NULL, (u32*)rb->colorBuf, dim, frameBuf, dim, flags);
}
void C3D_RenderBufBind(C3D_RenderBuf* rb)
{
C3D_Context* ctx = C3Di_GetContext();
ctx->flags |= C3DiF_RenderBuf;
ctx->rb = rb;
C3D_SetViewport(0, 0, rb->width, rb->height);
}
void C3Di_RenderBufBind(C3D_RenderBuf* rb)
{
u32 param[4];
param[0] = param[1] = 1;
GPUCMD_AddIncrementalWrites(GPUREG_0110, param, 2);
param[0] = osConvertVirtToPhys((u32)rb->depthBuf) >> 3;
param[1] = osConvertVirtToPhys((u32)rb->colorBuf) >> 3;
param[2] = 0x01000000 | (((u32)(rb->height-1) & 0xFFF) << 12) | (rb->width & 0xFFF);
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 3);
GPUCMD_AddWrite(GPUREG_006E, param[2]); //?
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, rb->depthFmt);
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, ((u32)rb->colorFmt << 16) | colorFmtSizes[rb->colorFmt]);
GPUCMD_AddWrite(GPUREG_011B, 0x00000000); //?
// "Enable depth buffer" (?)
param[0] = param[1] = 0xF;
param[2] = param[3] = 0x2;
GPUCMD_AddIncrementalWrites(GPUREG_0112, param, 4);
}
void C3D_RenderBufDelete(C3D_RenderBuf* rb)
{
if (rb->colorBuf)
{
vramFree(rb->colorBuf);
rb->colorBuf = NULL;
}
if (rb->depthBuf)
{
vramFree(rb->depthBuf);
rb->depthBuf = NULL;
}
}