From bfe889f00af74d6cec397f1bf794d7bf62275f73 Mon Sep 17 00:00:00 2001 From: Amaryllis Kulla Date: Wed, 27 Oct 2021 19:20:34 +0200 Subject: [PATCH] Add lastMileScaling, fix bugs, and expose options to MRI --- binding-mri/graphics-binding.cpp | 6 ++ mkxp.conf.sample | 24 +++++++ src/config.cpp | 2 + src/config.h | 6 ++ src/graphics.cpp | 113 ++++++++++++++++++++++++------- src/graphics.h | 3 + 6 files changed, 130 insertions(+), 24 deletions(-) diff --git a/binding-mri/graphics-binding.cpp b/binding-mri/graphics-binding.cpp index 25cf25b..aa58102 100644 --- a/binding-mri/graphics-binding.cpp +++ b/binding-mri/graphics-binding.cpp @@ -203,6 +203,9 @@ DEF_GRA_PROP_B(Fullscreen) DEF_GRA_PROP_B(ShowCursor) DEF_GRA_PROP_B(FixedAspectRatio) +DEF_GRA_PROP_B(SmoothScaling) +DEF_GRA_PROP_B(IntegerScaling) +DEF_GRA_PROP_B(LastMileScaling) #define INIT_GRA_PROP_BIND(PropName, prop_name_s) \ { \ @@ -225,6 +228,9 @@ void graphicsBindingInit() INIT_GRA_PROP_BIND( FrameCount, "frame_count" ); INIT_GRA_PROP_BIND( FixedAspectRatio, "fixed_aspect_ratio" ); + INIT_GRA_PROP_BIND( SmoothScaling, "smooth_scaling" ); + INIT_GRA_PROP_BIND( IntegerScaling, "integer_scaling" ); + INIT_GRA_PROP_BIND( LastMileScaling, "last_mile_scaling" ); if (rgssVer >= 2) { diff --git a/mkxp.conf.sample b/mkxp.conf.sample index 9863eaf..ad1686f 100644 --- a/mkxp.conf.sample +++ b/mkxp.conf.sample @@ -150,6 +150,30 @@ # maxTextureSize=0 +# Scale up the game screen by an integer amount, +# as large as the current window size allows, before +# doing any last additional scalings to fill part or +# all of the remaining window space (or none at all +# if lastMileScaling is disabled). +# If fixedAspectRatio is disabled, the integer scale +# factors in horizontal and vertical direction can differ +# depending on how much space is available, otherwise +# they are forced to the smaller of the two. +# (default: disabled) +# +# integerScaling.active = false + + +# When integer scaling is enabled, this option controls +# whether the scaled game screen is further scaled +# (with linear interpolation when smoothScaling is enabled) +# to fill the rest of the game window. +# Note that this option still respects fixedAspectRatio. +# (default: enabled) +# +# integerScaling.lastMileScaling = true + + # Set the base path of the game to '/path/to/game' # (default: executable directory) # diff --git a/src/config.cpp b/src/config.cpp index 9742f9c..aee2517 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -170,6 +170,8 @@ void Config::read(int argc, char *argv[]) PO_DESC(subImageFix, bool, false) \ PO_DESC(enableBlitting, bool, true) \ PO_DESC(maxTextureSize, int, 0) \ + PO_DESC(integerScaling.active, bool, false) \ + PO_DESC(integerScaling.lastMileScaling, bool, true) \ PO_DESC(gameFolder, std::string, ".") \ PO_DESC(anyAltToggleFS, bool, false) \ PO_DESC(enableReset, bool, true) \ diff --git a/src/config.h b/src/config.h index 967e1b0..2925a99 100644 --- a/src/config.h +++ b/src/config.h @@ -59,6 +59,12 @@ struct Config bool enableBlitting; int maxTextureSize; + struct + { + bool active; + bool lastMileScaling; + } integerScaling; + std::string gameFolder; bool anyAltToggleFS; bool enableReset; diff --git a/src/graphics.cpp b/src/graphics.cpp index 3ed6f6f..5e2c2f8 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -480,7 +480,7 @@ struct GraphicsPrivate Vec2i integerScaleFactor; TEXFBO integerScaleBuffer; bool integerScaleActive; - bool integerScaleFixedAspectRatio; + bool integerLastMileScaling; /* Global list of all live Disposables * (disposed on reset) */ @@ -499,22 +499,22 @@ struct GraphicsPrivate fpsLimiter(frameRate), frozen(false), integerScaleFactor(0, 0), - integerScaleActive(true), - integerScaleFixedAspectRatio(rtData->config.fixedAspectRatio) + integerScaleActive(rtData->config.integerScaling.active), + integerLastMileScaling(rtData->config.integerScaling.lastMileScaling) { - recalculateScreenSize(rtData); - updateScreenResoRatio(rtData); - - TEXFBO::init(frozenScene); - TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y); - TEXFBO::linkFBO(frozenScene); - if (integerScaleActive) { integerScaleFactor = Vec2i(1, 1); rebuildIntegerScaleBuffer(); } + recalculateScreenSize(rtData->config.fixedAspectRatio); + updateScreenResoRatio(rtData); + + TEXFBO::init(frozenScene); + TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y); + TEXFBO::linkFBO(frozenScene); + FloatRect screenRect(0, 0, scRes.x, scRes.y); screenQuad.setTexPosRect(screenRect, screenRect); @@ -537,16 +537,28 @@ struct GraphicsPrivate } /* Enforces fixed aspect ratio, if desired */ - void recalculateScreenSize(RGSSThreadData *rtData) + void recalculateScreenSize(bool fixedAspectRatio) { scSize = winSize; - if (!rtData->config.fixedAspectRatio) + if (!fixedAspectRatio && integerLastMileScaling) { scOffset = Vec2i(0, 0); return; } + /* Last mile scaling disabled: just center the integer scale buffer + * inside the window space */ + if (integerScaleActive && !integerLastMileScaling) + { + scOffset.x = (winSize.x - scRes.x * integerScaleFactor.x) / 2; + scOffset.y = (winSize.y - scRes.y * integerScaleFactor.y) / 2; + + scSize = Vec2i(scRes.x * integerScaleFactor.x, scRes.y * integerScaleFactor.y); + Debug() << scOffset.x << scOffset.y << winSize.x << winSize.y << integerScaleFactor.x << integerScaleFactor.y; + return; + } + float resRatio = (float) scRes.x / scRes.y; float winRatio = (float) winSize.x / winSize.y; @@ -577,7 +589,7 @@ struct GraphicsPrivate Vec2i newScale(findHighestFittingScale(scRes.x, winSize.x), findHighestFittingScale(scRes.y, winSize.y)); - if (integerScaleFixedAspectRatio) + if (threadData->config.fixedAspectRatio) { /* Limit both factors to the smaller of the two */ newScale.x = newScale.y = std::min(newScale.x, newScale.y); @@ -587,7 +599,6 @@ struct GraphicsPrivate return false; integerScaleFactor = newScale; - Debug() << "Found new scale:" << newScale.x << newScale.y; return true; } @@ -598,8 +609,6 @@ struct GraphicsPrivate TEXFBO::allocEmpty(integerScaleBuffer, scRes.x * integerScaleFactor.x, scRes.y * integerScaleFactor.y); TEXFBO::linkFBO(integerScaleBuffer); - - Debug() << "New buffer size:" << integerScaleBuffer.width << integerScaleBuffer.height; } bool integerScaleStepApplicable() const @@ -619,17 +628,18 @@ struct GraphicsPrivate { /* Query the acutal size in pixels, not units */ SDL_GL_GetDrawableSize(threadData->window, &winSize.x, &winSize.y); - Debug() << "Reported GL drawable size:" << winSize.x << winSize.y; + + /* Make sure integer buffers are rebuilt before screen offsets are + * calculated so we have the final allocated buffer size ready */ + if (integerScaleActive) + if (findHighestIntegerScale()) + rebuildIntegerScaleBuffer(); /* some GL drivers change the viewport on window resize */ glState.viewport.refresh(); recalculateScreenSize(threadData); updateScreenResoRatio(threadData); - if (integerScaleActive) - if (findHighestIntegerScale()) - rebuildIntegerScaleBuffer(); - SDL_Rect screen = { scOffset.x, scOffset.y, scSize.x, scSize.y }; threadData->ethread->notifyGameScreenChange(screen); } @@ -680,17 +690,31 @@ struct GraphicsPrivate metaBlitBufferFlippedScaled(scRes); } - void metaBlitBufferFlippedScaled(const Vec2i &sourceSize) + void metaBlitBufferFlippedScaled(const Vec2i &sourceSize, bool forceNearestNeighbour = false) { GLMeta::blitRectangle(IntRect(0, 0, sourceSize.x, sourceSize.y), IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y), - threadData->config.smoothScaling); + !forceNearestNeighbour && threadData->config.smoothScaling); } void redrawScreen() { screen.composite(); + // maybe unspaghetti this later + if (integerScaleStepApplicable() && !integerLastMileScaling) + { + GLMeta::blitBeginScreen(winSize); + GLMeta::blitSource(screen.getPP().frontBuffer()); + + FBO::clear(); + metaBlitBufferFlippedScaled(scRes, true); + GLMeta::blitEnd(); + + swapGLBuffer(); + return; + } + if (integerScaleStepApplicable()) { assert(integerScaleBuffer.tex != TEX::ID(0)); @@ -1133,7 +1157,48 @@ bool Graphics::getFixedAspectRatio() const void Graphics::setFixedAspectRatio(bool value) { shState->config().fixedAspectRatio = value; - p->recalculateScreenSize(p->threadData); + p->findHighestIntegerScale(); + p->recalculateScreenSize(p->threadData->config.fixedAspectRatio); + p->updateScreenResoRatio(p->threadData); +} + +bool Graphics::getSmoothScaling() const +{ + // Same deal as with fixed aspect ratio + return shState->config().smoothScaling; +} + +void Graphics::setSmoothScaling(bool value) +{ + shState->config().smoothScaling = value; +} + +bool Graphics::getIntegerScaling() const +{ + return p->integerScaleActive; +} + +void Graphics::setIntegerScaling(bool value) +{ + p->integerScaleActive = value; + + p->findHighestIntegerScale(); + p->rebuildIntegerScaleBuffer(); + + p->recalculateScreenSize(p->threadData->config.fixedAspectRatio); + p->updateScreenResoRatio(p->threadData); +} + +bool Graphics::getLastMileScaling() const +{ + return p->integerLastMileScaling; +} + +void Graphics::setLastMileScaling(bool value) +{ + p->integerLastMileScaling = value; + + p->recalculateScreenSize(p->threadData->config.fixedAspectRatio); p->updateScreenResoRatio(p->threadData); } diff --git a/src/graphics.h b/src/graphics.h index 546932f..940875d 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -63,6 +63,9 @@ public: DECL_ATTR( ShowCursor, bool ) DECL_ATTR( FixedAspectRatio, bool ) + DECL_ATTR( SmoothScaling, bool ) + DECL_ATTR( IntegerScaling, bool ) + DECL_ATTR( LastMileScaling, bool ) /* */ Scene *getScreen() const;