mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
3DS: Try to fix crash sometimes when quitting game
This commit is contained in:
parent
d00174c680
commit
0d36359615
@ -109,9 +109,10 @@ static void SwitchProgram(void) {
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*---------------------------------------------------------General---------------------------------------------------------*
|
*---------------------------------------------------------General---------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
static C3D_RenderTarget* topTargetLeft;
|
static C3D_RenderTarget topTargetLeft;
|
||||||
static C3D_RenderTarget* topTargetRight;
|
static C3D_RenderTarget topTargetRight;
|
||||||
static C3D_RenderTarget* bottomTarget;
|
static C3D_RenderTarget bottomTarget;
|
||||||
|
static cc_bool createdTopTargetRight;
|
||||||
|
|
||||||
static void AllocShaders(void) {
|
static void AllocShaders(void) {
|
||||||
Shader_Alloc(&shaders[0], coloured_shbin, coloured_shbin_size);
|
Shader_Alloc(&shaders[0], coloured_shbin, coloured_shbin_size);
|
||||||
@ -135,13 +136,13 @@ static void SetDefaultState(void) {
|
|||||||
static void InitCitro3D(void) {
|
static void InitCitro3D(void) {
|
||||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE * 4);
|
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE * 4);
|
||||||
|
|
||||||
topTargetLeft = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24);
|
C3D_RenderTargetCreate(&topTargetLeft, 240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24);
|
||||||
C3D_RenderTargetSetOutput(topTargetLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
C3D_RenderTargetSetOutput(&topTargetLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||||
|
|
||||||
// Even though the bottom screen is 320 pixels wide, we use 400 here so that the same ortho matrix
|
// Even though the bottom screen is 320 pixels wide, we use 400 here so that the same ortho matrix
|
||||||
// can be used for both screens. The output is clipped to the actual screen width, anyway.
|
// can be used for both screens. The output is clipped to the actual screen width, anyway.
|
||||||
bottomTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24);
|
C3D_RenderTargetCreate(&bottomTarget, 240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24);
|
||||||
C3D_RenderTargetSetOutput(bottomTarget, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
C3D_RenderTargetSetOutput(&bottomTarget, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
|
||||||
|
|
||||||
gfxSetDoubleBuffering(GFX_TOP, true);
|
gfxSetDoubleBuffering(GFX_TOP, true);
|
||||||
SetDefaultState();
|
SetDefaultState();
|
||||||
@ -151,6 +152,7 @@ static void InitCitro3D(void) {
|
|||||||
static GfxResourceID white_square;
|
static GfxResourceID white_square;
|
||||||
void Gfx_Create(void) {
|
void Gfx_Create(void) {
|
||||||
if (!Gfx.Created) InitCitro3D();
|
if (!Gfx.Created) InitCitro3D();
|
||||||
|
else C3Di_RenderQueueInit();
|
||||||
|
|
||||||
Gfx.MaxTexWidth = 1024;
|
Gfx.MaxTexWidth = 1024;
|
||||||
Gfx.MaxTexHeight = 1024;
|
Gfx.MaxTexHeight = 1024;
|
||||||
@ -166,6 +168,8 @@ void Gfx_Create(void) {
|
|||||||
|
|
||||||
void Gfx_Free(void) {
|
void Gfx_Free(void) {
|
||||||
Gfx_FreeState();
|
Gfx_FreeState();
|
||||||
|
C3Di_RenderQueueExit();
|
||||||
|
|
||||||
// FreeShaders()
|
// FreeShaders()
|
||||||
// C3D_Fini()
|
// C3D_Fini()
|
||||||
}
|
}
|
||||||
@ -190,7 +194,7 @@ void Gfx_FreeState(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_3DS_SetRenderScreen(enum Screen3DS screen) {
|
void Gfx_3DS_SetRenderScreen(enum Screen3DS screen) {
|
||||||
C3D_FrameDrawOn(screen == TOP_SCREEN ? topTargetLeft : bottomTarget);
|
C3D_FrameDrawOn(screen == TOP_SCREEN ? &topTargetLeft : &bottomTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -217,13 +221,14 @@ void Gfx_Set3DLeft(struct Matrix* proj, struct Matrix* view) {
|
|||||||
void Gfx_Set3DRight(struct Matrix* proj, struct Matrix* view) {
|
void Gfx_Set3DRight(struct Matrix* proj, struct Matrix* view) {
|
||||||
Calc3DProjection(+1, proj);
|
Calc3DProjection(+1, proj);
|
||||||
|
|
||||||
if (!topTargetRight) {
|
if (!createdTopTargetRight) {
|
||||||
topTargetRight = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
|
C3D_RenderTargetCreate(&topTargetRight, 240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24);
|
||||||
C3D_RenderTargetSetOutput(topTargetRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS);
|
C3D_RenderTargetSetOutput(&topTargetRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS);
|
||||||
|
createdTopTargetRight = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
C3D_RenderTargetClear(topTargetRight, C3D_CLEAR_ALL, clear_color, 0);
|
C3D_RenderTargetClear(&topTargetRight, C3D_CLEAR_ALL, clear_color, 0);
|
||||||
C3D_FrameDrawOn(topTargetRight);
|
C3D_FrameDrawOn(&topTargetRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_End3D(struct Matrix* proj, struct Matrix* view) {
|
void Gfx_End3D(struct Matrix* proj, struct Matrix* view) {
|
||||||
@ -532,7 +537,7 @@ void Gfx_BeginFrame(void) {
|
|||||||
if (gfx_vsync) C3D_FrameSync();
|
if (gfx_vsync) C3D_FrameSync();
|
||||||
|
|
||||||
C3D_FrameBegin(0);
|
C3D_FrameBegin(0);
|
||||||
C3D_FrameDrawOn(topTargetLeft);
|
C3D_FrameDrawOn(&topTargetLeft);
|
||||||
|
|
||||||
extern void C3Di_UpdateContext(void);
|
extern void C3Di_UpdateContext(void);
|
||||||
C3Di_UpdateContext();
|
C3Di_UpdateContext();
|
||||||
@ -543,8 +548,8 @@ void Gfx_ClearBuffers(GfxBuffers buffers) {
|
|||||||
if (buffers & GFX_BUFFER_COLOR) targets |= C3D_CLEAR_COLOR;
|
if (buffers & GFX_BUFFER_COLOR) targets |= C3D_CLEAR_COLOR;
|
||||||
if (buffers & GFX_BUFFER_DEPTH) targets |= C3D_CLEAR_DEPTH;
|
if (buffers & GFX_BUFFER_DEPTH) targets |= C3D_CLEAR_DEPTH;
|
||||||
|
|
||||||
C3D_RenderTargetClear(topTargetLeft, targets, clear_color, 0);
|
C3D_RenderTargetClear(&topTargetLeft, targets, clear_color, 0);
|
||||||
C3D_RenderTargetClear(bottomTarget, targets, 0, 0);
|
C3D_RenderTargetClear(&bottomTarget, targets, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_EndFrame(void) {
|
void Gfx_EndFrame(void) {
|
||||||
|
79
third_party/citro3d.c
vendored
79
third_party/citro3d.c
vendored
@ -311,13 +311,9 @@ typedef struct C3D_RenderTarget_tag C3D_RenderTarget;
|
|||||||
|
|
||||||
struct C3D_RenderTarget_tag
|
struct C3D_RenderTarget_tag
|
||||||
{
|
{
|
||||||
C3D_RenderTarget *next, *prev;
|
|
||||||
C3D_FrameBuf frameBuf;
|
C3D_FrameBuf frameBuf;
|
||||||
|
|
||||||
bool used;
|
bool used, linked;
|
||||||
bool ownsColor, ownsDepth;
|
|
||||||
|
|
||||||
bool linked;
|
|
||||||
gfxScreen_t screen;
|
gfxScreen_t screen;
|
||||||
gfx3dSide_t side;
|
gfx3dSide_t side;
|
||||||
u32 transferFlags;
|
u32 transferFlags;
|
||||||
@ -337,7 +333,7 @@ static bool C3D_FrameDrawOn(C3D_RenderTarget* target);
|
|||||||
static void C3D_FrameSplit(u8 flags);
|
static void C3D_FrameSplit(u8 flags);
|
||||||
static void C3D_FrameEnd(u8 flags);
|
static void C3D_FrameEnd(u8 flags);
|
||||||
|
|
||||||
static C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF colorFmt, GPU_DEPTHBUF depthFmt);
|
static void C3D_RenderTargetCreate(C3D_RenderTarget* target, int width, int height, GPU_COLORBUF colorFmt, GPU_DEPTHBUF depthFmt);
|
||||||
static void C3D_RenderTargetDelete(C3D_RenderTarget* target);
|
static void C3D_RenderTargetDelete(C3D_RenderTarget* target);
|
||||||
static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags);
|
static void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags);
|
||||||
|
|
||||||
@ -977,7 +973,6 @@ static void C3D_ImmDrawEnd(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static C3D_RenderTarget *firstTarget, *lastTarget;
|
|
||||||
static C3D_RenderTarget *linkedTarget[3];
|
static C3D_RenderTarget *linkedTarget[3];
|
||||||
|
|
||||||
static bool inFrame, inSafeTransfer;
|
static bool inFrame, inSafeTransfer;
|
||||||
@ -1069,23 +1064,11 @@ static void C3Di_RenderQueueInit(void)
|
|||||||
|
|
||||||
static void C3Di_RenderQueueExit(void)
|
static void C3Di_RenderQueueExit(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
C3D_RenderTarget *a, *next;
|
|
||||||
|
|
||||||
C3Di_WaitAndClearQueue(-1);
|
C3Di_WaitAndClearQueue(-1);
|
||||||
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL);
|
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL);
|
||||||
GX_BindQueue(NULL);
|
GX_BindQueue(NULL);
|
||||||
|
|
||||||
C3Di_RenderQueueDisableVBlank();
|
C3Di_RenderQueueDisableVBlank();
|
||||||
|
|
||||||
for (i = 0; i < 3; i ++)
|
|
||||||
linkedTarget[i] = NULL;
|
|
||||||
|
|
||||||
for (a = firstTarget; a; a = next)
|
|
||||||
{
|
|
||||||
next = a->next;
|
|
||||||
C3Di_RenderTargetDestroy(a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void C3Di_RenderQueueWaitDone(void)
|
static void C3Di_RenderQueueWaitDone(void)
|
||||||
@ -1161,70 +1144,36 @@ static void C3D_FrameEnd(u8 flags)
|
|||||||
gxCmdQueueRun(&ctx->gxQueue);
|
gxCmdQueueRun(&ctx->gxQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static C3D_RenderTarget* C3Di_RenderTargetNew(void)
|
void C3D_RenderTargetCreate(C3D_RenderTarget* target, int width, int height, GPU_COLORBUF colorFmt, GPU_DEPTHBUF depthFmt)
|
||||||
{
|
{
|
||||||
C3D_RenderTarget* target = (C3D_RenderTarget*)malloc(sizeof(C3D_RenderTarget));
|
size_t colorSize = C3D_CalcColorBufSize(width,height,colorFmt);
|
||||||
if (!target) return NULL;
|
|
||||||
memset(target, 0, sizeof(C3D_RenderTarget));
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void C3Di_RenderTargetFinishInit(C3D_RenderTarget* target)
|
|
||||||
{
|
|
||||||
target->prev = lastTarget;
|
|
||||||
target->next = NULL;
|
|
||||||
if (lastTarget)
|
|
||||||
lastTarget->next = target;
|
|
||||||
if (!firstTarget)
|
|
||||||
firstTarget = target;
|
|
||||||
lastTarget = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF colorFmt, GPU_DEPTHBUF depthFmt)
|
|
||||||
{
|
|
||||||
void* depthBuf = NULL;
|
|
||||||
void* colorBuf = vramAlloc(C3D_CalcColorBufSize(width,height,colorFmt));
|
|
||||||
if (!colorBuf) goto _fail0;
|
|
||||||
|
|
||||||
size_t depthSize = C3D_CalcDepthBufSize(width,height,depthFmt);
|
size_t depthSize = C3D_CalcDepthBufSize(width,height,depthFmt);
|
||||||
|
memset(target, 0, sizeof(C3D_RenderTarget));
|
||||||
|
|
||||||
|
void* depthBuf = NULL;
|
||||||
|
void* colorBuf = vramAlloc(colorSize);
|
||||||
|
if (!colorBuf) goto _fail;
|
||||||
|
|
||||||
vramAllocPos vramBank = addrGetVRAMBank(colorBuf);
|
vramAllocPos vramBank = addrGetVRAMBank(colorBuf);
|
||||||
depthBuf = vramAllocAt(depthSize, vramBank ^ VRAM_ALLOC_ANY); // Attempt opposite bank first...
|
depthBuf = vramAllocAt(depthSize, vramBank ^ VRAM_ALLOC_ANY); // Attempt opposite bank first...
|
||||||
if (!depthBuf) depthBuf = vramAllocAt(depthSize, vramBank); // ... if that fails, attempt same bank
|
if (!depthBuf) depthBuf = vramAllocAt(depthSize, vramBank); // ... if that fails, attempt same bank
|
||||||
if (!depthBuf) goto _fail1;
|
if (!depthBuf) goto _fail;
|
||||||
|
|
||||||
C3D_RenderTarget* target = C3Di_RenderTargetNew();
|
|
||||||
if (!target) goto _fail2;
|
|
||||||
|
|
||||||
C3D_FrameBuf* fb = &target->frameBuf;
|
C3D_FrameBuf* fb = &target->frameBuf;
|
||||||
C3D_FrameBufAttrib(fb, width, height, false);
|
C3D_FrameBufAttrib(fb, width, height, false);
|
||||||
C3D_FrameBufColor(fb, colorBuf, colorFmt);
|
C3D_FrameBufColor(fb, colorBuf, colorFmt);
|
||||||
C3D_FrameBufDepth(fb, depthBuf, depthFmt);
|
C3D_FrameBufDepth(fb, depthBuf, depthFmt);
|
||||||
target->ownsDepth = true;
|
return;
|
||||||
target->ownsColor = true;
|
|
||||||
|
|
||||||
C3Di_RenderTargetFinishInit(target);
|
_fail:
|
||||||
return target;
|
|
||||||
|
|
||||||
_fail2:
|
|
||||||
if (depthBuf) vramFree(depthBuf);
|
if (depthBuf) vramFree(depthBuf);
|
||||||
_fail1:
|
if (colorBuf) vramFree(colorBuf);
|
||||||
vramFree(colorBuf);
|
|
||||||
_fail0:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target)
|
static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target)
|
||||||
{
|
{
|
||||||
if (target->ownsColor)
|
|
||||||
vramFree(target->frameBuf.colorBuf);
|
vramFree(target->frameBuf.colorBuf);
|
||||||
if (target->ownsDepth)
|
|
||||||
vramFree(target->frameBuf.depthBuf);
|
vramFree(target->frameBuf.depthBuf);
|
||||||
|
|
||||||
C3D_RenderTarget** prevNext = target->prev ? &target->prev->next : &firstTarget;
|
|
||||||
C3D_RenderTarget** nextPrev = target->next ? &target->next->prev : &lastTarget;
|
|
||||||
*prevNext = target->next;
|
|
||||||
*nextPrev = target->prev;
|
|
||||||
free(target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void C3D_RenderTargetDelete(C3D_RenderTarget* target)
|
static void C3D_RenderTargetDelete(C3D_RenderTarget* target)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user