3DS: Interframe blending
Vicki Pfau vi@endrift.com
Wed, 29 May 2019 15:13:30 -0700
1 files changed,
43 insertions(+),
22 deletions(-)
jump to
M
src/platform/3ds/main.c
→
src/platform/3ds/main.c
@@ -89,7 +89,8 @@ static color_t* screenshotBuffer = NULL;
static struct mAVStream stream; static int16_t* audioLeft = 0; static size_t audioPos = 0; -static C3D_Tex outputTexture; +static C3D_Tex outputTexture[2]; +static int activeOutputTexture = 0; static ndspWaveBuf dspBuffer[DSP_BUFFERS]; static int bufferId = 0; static bool frameLimiter = true;@@ -102,6 +103,7 @@ static bool frameStarted = false;
static C3D_RenderTarget* upscaleBuffer; static C3D_Tex upscaleBufferTex; +static bool interframeBlending = false; static aptHookCookie cookie; static bool core2;@@ -150,7 +152,8 @@ C3D_RenderTargetDelete(bottomScreen[0]);
C3D_RenderTargetDelete(bottomScreen[1]); C3D_RenderTargetDelete(upscaleBuffer); C3D_TexDelete(&upscaleBufferTex); - C3D_TexDelete(&outputTexture); + C3D_TexDelete(&outputTexture[0]); + C3D_TexDelete(&outputTexture[1]); C3D_Fini(); gfxExit();@@ -374,6 +377,11 @@ CAMU_Activate(camera.cam);
} } } + + int fakeBool; + if (mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool)) { + interframeBlending = fakeBool; + } } static void _gameUnloaded(struct mGUIRunner* runner) {@@ -404,7 +412,7 @@ break;
} } -static void _drawTex(struct mCore* core, bool faded) { +static void _drawTex(struct mCore* core, bool faded, bool both) { unsigned screen_w, screen_h; switch (screenMode) { case SM_PA_BOTTOM:@@ -466,7 +474,6 @@ ctrSetViewportSize(screen_w, screen_h, false);
break; } - ctrActivateTexture(&outputTexture); u32 color; if (!faded) { color = 0xFFFFFFFF;@@ -502,7 +509,12 @@ break;
} } + ctrActivateTexture(&outputTexture[activeOutputTexture]); ctrAddRectEx(color, x, y, w, h, 0, 0, corew, coreh, 0); + if (both) { + ctrActivateTexture(&outputTexture[activeOutputTexture ^ 1]); + ctrAddRectEx(color & 0x7FFFFFFF, x, y, w, h, 0, 0, corew, coreh, 0); + } ctrFlushBatch(); corew = w;@@ -544,11 +556,16 @@ y = (screen_h - h) / 2;
ctrActivateTexture(&upscaleBufferTex); ctrAddRectEx(0xFFFFFFFF, x, y, w, h, 0, 0, corew, coreh, 0); ctrFlushBatch(); +} + +static void _prepareForFrame(struct mGUIRunner* runner) { + UNUSED(runner); + activeOutputTexture ^= 1; } static void _drawFrame(struct mGUIRunner* runner, bool faded) { UNUSED(runner); - C3D_Tex* tex = &outputTexture; + C3D_Tex* tex = &outputTexture[activeOutputTexture]; GSPGPU_FlushDataCache(outputBuffer, 256 * GBA_VIDEO_VERTICAL_PIXELS * 2); C3D_SyncDisplayTransfer(@@ -563,11 +580,11 @@ blip_clear(runner->core->getAudioChannel(runner->core, 0));
blip_clear(runner->core->getAudioChannel(runner->core, 1)); } - _drawTex(runner->core, faded); + _drawTex(runner->core, faded, interframeBlending); } static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { - C3D_Tex* tex = &outputTexture; + C3D_Tex* tex = &outputTexture[activeOutputTexture]; if (!screenshotBuffer) { screenshotBuffer = linearMemAlign(256 * 224 * sizeof(color_t), 0x80);@@ -586,7 +603,7 @@ GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB565) |
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB565) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_FLIP_VERT(1)); - _drawTex(runner->core, faded); + _drawTex(runner->core, faded, false); } static uint16_t _pollGameInput(struct mGUIRunner* runner) {@@ -804,25 +821,29 @@
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, true); if (!_initGpu()) { - outputTexture.data = 0; + outputTexture[0].data = 0; _cleanup(); return 1; } - if (!C3D_TexInitVRAM(&outputTexture, 256, 256, GPU_RGB565)) { - _cleanup(); - return 1; - } - C3D_TexSetWrap(&outputTexture, GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); - C3D_TexSetFilter(&outputTexture, GPU_NEAREST, GPU_NEAREST); C3D_TexSetFilter(&upscaleBufferTex, GPU_LINEAR, GPU_LINEAR); - void* outputTextureEnd = (u8*)outputTexture.data + 256 * 256 * 2; - // Zero texture data to make sure no garbage around the border interferes with filtering - GX_MemoryFill( - outputTexture.data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER, - NULL, 0, NULL, 0); - gspWaitForPSC0(); + int i; + for (i = 0; i < 2; ++i) { + if (!C3D_TexInitVRAM(&outputTexture[i], 256, 256, GPU_RGB565)) { + _cleanup(); + return 1; + } + C3D_TexSetWrap(&outputTexture[i], GPU_CLAMP_TO_EDGE, GPU_CLAMP_TO_EDGE); + C3D_TexSetFilter(&outputTexture[i], GPU_NEAREST, GPU_NEAREST); + void* outputTextureEnd = (u8*)outputTexture[i].data + 256 * 256 * 2; + + // Zero texture data to make sure no garbage around the border interferes with filtering + GX_MemoryFill( + outputTexture[i].data, 0x0000, outputTextureEnd, GX_FILL_16BIT_DEPTH | GX_FILL_TRIGGER, + NULL, 0, NULL, 0); + gspWaitForPSC0(); + } struct GUIFont* font = GUIFontCreate();@@ -937,7 +958,7 @@ .setup = _setup,
.teardown = 0, .gameLoaded = _gameLoaded, .gameUnloaded = _gameUnloaded, - .prepareForFrame = 0, + .prepareForFrame = _prepareForFrame, .drawFrame = _drawFrame, .drawScreenshot = _drawScreenshot, .paused = _gameUnloaded,