From 8dbef1f0e33cec18552573c1e907588b98a1b0ee Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 1 Sep 2016 00:11:07 -0700 Subject: [PATCH] Wii: Add pixelated resample filter --- CHANGES | 1 + src/platform/wii/main.c | 75 +++++++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index 4e47c1898..3891bb31e 100644 --- a/CHANGES +++ b/CHANGES @@ -86,6 +86,7 @@ Misc: - PSP2: Stop underclocking when menuing - GUI: Increase scrolling speed - Qt: Rearchitect game closing codepath + - Wii: Add pixelated resample filter 0.4.1: (2016-07-11) Bugfixes: diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index a5a65b7a0..45247da4b 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -42,7 +42,8 @@ static enum ScreenMode { static enum FilterMode { FM_NEAREST, - FM_LINEAR, + FM_LINEAR_1x, + FM_LINEAR_2x, FM_MAX } filterMode = FM_NEAREST; @@ -73,7 +74,6 @@ static void _drawEnd(void); static uint32_t _pollInput(const struct mInputMap*); static enum GUICursorState _pollCursor(unsigned* x, unsigned* y); static void _guiPrepare(void); -static void _guiFinish(void); static void _setup(struct mGUIRunner* runner); static void _gameLoaded(struct mGUIRunner* runner); @@ -97,6 +97,8 @@ static float guiScale = GUI_SCALE; static Mtx model, view, modelview; static uint16_t* texmem; static GXTexObj tex; +static uint16_t* rescaleTexmem; +static GXTexObj rescaleTex; static int32_t tiltX; static int32_t tiltY; static int32_t gyroZ; @@ -279,6 +281,10 @@ int main(int argc, char* argv[]) { texmem = memalign(32, 256 * 256 * BYTES_PER_PIXEL); memset(texmem, 0, 256 * 256 * BYTES_PER_PIXEL); GX_InitTexObj(&tex, texmem, 256, 256, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); + rescaleTexmem = memalign(32, 512 * 512 * BYTES_PER_PIXEL); + memset(rescaleTexmem, 0, 512 * 512 * BYTES_PER_PIXEL); + GX_InitTexObj(&rescaleTex, rescaleTexmem, 512, 512, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); + GX_InitTexObjFilterMode(&rescaleTex, GX_LINEAR, GX_LINEAR); VIDEO_SetPostRetraceCallback(_retraceCallback); @@ -300,7 +306,7 @@ int main(int argc, char* argv[]) { _drawStart, _drawEnd, _pollInput, _pollCursor, 0, - _guiPrepare, _guiFinish, + _guiPrepare, 0, GUI_PARAMS_TRAIL }, @@ -443,9 +449,10 @@ int main(int argc, char* argv[]) { .state = 0, .validStates = (const char*[]) { "Pixelated", - "Resampled", + "Bilinear (smoother)", + "Bilinear (pixelated)", }, - .nStates = 2 + .nStates = 3 } }, .nConfigExtra = 3, @@ -502,6 +509,8 @@ int main(int argc, char* argv[]) { mGUIDeinit(&runner); free(fifo); + free(texmem); + free(rescaleTexmem); free(outputBuffer); GUIFontDestroy(font); @@ -628,14 +637,6 @@ void _guiPrepare(void) { _reproj2(vmode->fbWidth * guiScale * wAdjust, vmode->efbHeight * guiScale * hAdjust); } -void _guiFinish(void) { - if (screenMode == SM_PA) { - _reproj(corew * scaleFactor, coreh * scaleFactor); - } else { - _reproj2(corew, coreh); - } -} - void _setup(struct mGUIRunner* runner) { runner->core->setRotation(runner->core, &rotation); runner->core->setRumble(runner->core, &rumble); @@ -733,15 +734,15 @@ void _unpaused(struct mGUIRunner* runner) { filterMode = mode; switch (mode) { case FM_NEAREST: + case FM_LINEAR_2x: default: GX_InitTexObjFilterMode(&tex, GX_NEAR, GX_NEAR); break; - case FM_LINEAR: + case FM_LINEAR_1x: GX_InitTexObjFilterMode(&tex, GX_LINEAR, GX_LINEAR); break; } } - _guiFinish(); } void _drawFrame(struct mGUIRunner* runner, bool faded) { @@ -788,10 +789,46 @@ void _drawFrame(struct mGUIRunner* runner, bool faded) { GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); s16 vertSize = 256; + + if (filterMode == FM_LINEAR_2x) { + Mtx44 proj; + guOrtho(proj, 0, vmode->efbHeight, 0, vmode->fbWidth, 0, 300); + GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC); + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + GX_Position2s16(0, 512); + GX_Color1u32(0xFFFFFFFF); + GX_TexCoord2s16(0, 1); + + GX_Position2s16(512, 512); + GX_Color1u32(0xFFFFFFFF); + GX_TexCoord2s16(1, 1); + + GX_Position2s16(512, 0); + GX_Color1u32(0xFFFFFFFF); + GX_TexCoord2s16(1, 0); + + GX_Position2s16(0, 0); + GX_Color1u32(0xFFFFFFFF); + GX_TexCoord2s16(0, 0); + GX_End(); + + GX_SetTexCopySrc(0, 0, 512, 512); + GX_SetTexCopyDst(512, 512, GX_TF_RGB565, GX_FALSE); + GX_CopyTex(rescaleTexmem, GX_TRUE); + GX_LoadTexObj(&rescaleTex, GX_TEXMAP0); + } + if (screenMode == SM_PA) { vertSize *= scaleFactor; } + if (screenMode == SM_PA) { + _reproj(corew * scaleFactor, coreh * scaleFactor); + } else { + _reproj2(corew, coreh); + } + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position2s16(0, vertSize); GX_Color1u32(color); @@ -854,17 +891,13 @@ void _incrementScreenMode(struct mGUIRunner* runner) { filterMode = (mode >> 1) % FM_MAX; mCoreConfigSetUIntValue(&runner->config, "screenMode", screenMode); mCoreConfigSetUIntValue(&runner->config, "filter", filterMode); - if (screenMode == SM_PA) { - _reproj(corew * scaleFactor, coreh * scaleFactor); - } else { - _reproj2(corew, coreh); - } switch (filterMode) { case FM_NEAREST: + case FM_LINEAR_2x: default: GX_InitTexObjFilterMode(&tex, GX_NEAR, GX_NEAR); break; - case FM_LINEAR: + case FM_LINEAR_1x: GX_InitTexObjFilterMode(&tex, GX_LINEAR, GX_LINEAR); break; }