3DS: Interframe blending

This commit is contained in:
Vicki Pfau 2019-05-29 15:13:30 -07:00
parent 252b9409b6
commit 456dbc482f
1 changed files with 43 additions and 22 deletions

View File

@ -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 @@ static void _cleanup(void) {
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 @@ static void _gameLoaded(struct mGUIRunner* runner) {
}
}
}
int fakeBool;
if (mCoreConfigGetIntValue(&runner->config, "interframeBlending", &fakeBool)) {
interframeBlending = fakeBool;
}
}
static void _gameUnloaded(struct mGUIRunner* runner) {
@ -404,7 +412,7 @@ static void _gameUnloaded(struct mGUIRunner* runner) {
}
}
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 @@ static void _drawTex(struct mCore* core, bool faded) {
break;
}
ctrActivateTexture(&outputTexture);
u32 color;
if (!faded) {
color = 0xFFFFFFFF;
@ -502,7 +509,12 @@ static void _drawTex(struct mCore* core, bool faded) {
}
}
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;
@ -546,9 +558,14 @@ static void _drawTex(struct mCore* core, bool faded) {
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 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) {
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 @@ static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, un
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 @@ int main() {
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 @@ int main() {
.teardown = 0,
.gameLoaded = _gameLoaded,
.gameUnloaded = _gameUnloaded,
.prepareForFrame = 0,
.prepareForFrame = _prepareForFrame,
.drawFrame = _drawFrame,
.drawScreenshot = _drawScreenshot,
.paused = _gameUnloaded,