Add lastMileScaling, fix bugs, and expose options to MRI

This commit is contained in:
Amaryllis Kulla 2021-10-27 19:20:34 +02:00
parent fb16c8e6d0
commit bfe889f00a
6 changed files with 130 additions and 24 deletions

View File

@ -203,6 +203,9 @@ DEF_GRA_PROP_B(Fullscreen)
DEF_GRA_PROP_B(ShowCursor) DEF_GRA_PROP_B(ShowCursor)
DEF_GRA_PROP_B(FixedAspectRatio) 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) \ #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( FrameCount, "frame_count" );
INIT_GRA_PROP_BIND( FixedAspectRatio, "fixed_aspect_ratio" ); 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) if (rgssVer >= 2)
{ {

View File

@ -150,6 +150,30 @@
# maxTextureSize=0 # 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' # Set the base path of the game to '/path/to/game'
# (default: executable directory) # (default: executable directory)
# #

View File

@ -170,6 +170,8 @@ void Config::read(int argc, char *argv[])
PO_DESC(subImageFix, bool, false) \ PO_DESC(subImageFix, bool, false) \
PO_DESC(enableBlitting, bool, true) \ PO_DESC(enableBlitting, bool, true) \
PO_DESC(maxTextureSize, int, 0) \ PO_DESC(maxTextureSize, int, 0) \
PO_DESC(integerScaling.active, bool, false) \
PO_DESC(integerScaling.lastMileScaling, bool, true) \
PO_DESC(gameFolder, std::string, ".") \ PO_DESC(gameFolder, std::string, ".") \
PO_DESC(anyAltToggleFS, bool, false) \ PO_DESC(anyAltToggleFS, bool, false) \
PO_DESC(enableReset, bool, true) \ PO_DESC(enableReset, bool, true) \

View File

@ -59,6 +59,12 @@ struct Config
bool enableBlitting; bool enableBlitting;
int maxTextureSize; int maxTextureSize;
struct
{
bool active;
bool lastMileScaling;
} integerScaling;
std::string gameFolder; std::string gameFolder;
bool anyAltToggleFS; bool anyAltToggleFS;
bool enableReset; bool enableReset;

View File

@ -480,7 +480,7 @@ struct GraphicsPrivate
Vec2i integerScaleFactor; Vec2i integerScaleFactor;
TEXFBO integerScaleBuffer; TEXFBO integerScaleBuffer;
bool integerScaleActive; bool integerScaleActive;
bool integerScaleFixedAspectRatio; bool integerLastMileScaling;
/* Global list of all live Disposables /* Global list of all live Disposables
* (disposed on reset) */ * (disposed on reset) */
@ -499,22 +499,22 @@ struct GraphicsPrivate
fpsLimiter(frameRate), fpsLimiter(frameRate),
frozen(false), frozen(false),
integerScaleFactor(0, 0), integerScaleFactor(0, 0),
integerScaleActive(true), integerScaleActive(rtData->config.integerScaling.active),
integerScaleFixedAspectRatio(rtData->config.fixedAspectRatio) integerLastMileScaling(rtData->config.integerScaling.lastMileScaling)
{ {
recalculateScreenSize(rtData);
updateScreenResoRatio(rtData);
TEXFBO::init(frozenScene);
TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
TEXFBO::linkFBO(frozenScene);
if (integerScaleActive) if (integerScaleActive)
{ {
integerScaleFactor = Vec2i(1, 1); integerScaleFactor = Vec2i(1, 1);
rebuildIntegerScaleBuffer(); 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); FloatRect screenRect(0, 0, scRes.x, scRes.y);
screenQuad.setTexPosRect(screenRect, screenRect); screenQuad.setTexPosRect(screenRect, screenRect);
@ -537,16 +537,28 @@ struct GraphicsPrivate
} }
/* Enforces fixed aspect ratio, if desired */ /* Enforces fixed aspect ratio, if desired */
void recalculateScreenSize(RGSSThreadData *rtData) void recalculateScreenSize(bool fixedAspectRatio)
{ {
scSize = winSize; scSize = winSize;
if (!rtData->config.fixedAspectRatio) if (!fixedAspectRatio && integerLastMileScaling)
{ {
scOffset = Vec2i(0, 0); scOffset = Vec2i(0, 0);
return; 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 resRatio = (float) scRes.x / scRes.y;
float winRatio = (float) winSize.x / winSize.y; float winRatio = (float) winSize.x / winSize.y;
@ -577,7 +589,7 @@ struct GraphicsPrivate
Vec2i newScale(findHighestFittingScale(scRes.x, winSize.x), Vec2i newScale(findHighestFittingScale(scRes.x, winSize.x),
findHighestFittingScale(scRes.y, winSize.y)); findHighestFittingScale(scRes.y, winSize.y));
if (integerScaleFixedAspectRatio) if (threadData->config.fixedAspectRatio)
{ {
/* Limit both factors to the smaller of the two */ /* Limit both factors to the smaller of the two */
newScale.x = newScale.y = std::min(newScale.x, newScale.y); newScale.x = newScale.y = std::min(newScale.x, newScale.y);
@ -587,7 +599,6 @@ struct GraphicsPrivate
return false; return false;
integerScaleFactor = newScale; integerScaleFactor = newScale;
Debug() << "Found new scale:" << newScale.x << newScale.y;
return true; return true;
} }
@ -598,8 +609,6 @@ struct GraphicsPrivate
TEXFBO::allocEmpty(integerScaleBuffer, scRes.x * integerScaleFactor.x, TEXFBO::allocEmpty(integerScaleBuffer, scRes.x * integerScaleFactor.x,
scRes.y * integerScaleFactor.y); scRes.y * integerScaleFactor.y);
TEXFBO::linkFBO(integerScaleBuffer); TEXFBO::linkFBO(integerScaleBuffer);
Debug() << "New buffer size:" << integerScaleBuffer.width << integerScaleBuffer.height;
} }
bool integerScaleStepApplicable() const bool integerScaleStepApplicable() const
@ -619,17 +628,18 @@ struct GraphicsPrivate
{ {
/* Query the acutal size in pixels, not units */ /* Query the acutal size in pixels, not units */
SDL_GL_GetDrawableSize(threadData->window, &winSize.x, &winSize.y); 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 */ /* some GL drivers change the viewport on window resize */
glState.viewport.refresh(); glState.viewport.refresh();
recalculateScreenSize(threadData); recalculateScreenSize(threadData);
updateScreenResoRatio(threadData); updateScreenResoRatio(threadData);
if (integerScaleActive)
if (findHighestIntegerScale())
rebuildIntegerScaleBuffer();
SDL_Rect screen = { scOffset.x, scOffset.y, scSize.x, scSize.y }; SDL_Rect screen = { scOffset.x, scOffset.y, scSize.x, scSize.y };
threadData->ethread->notifyGameScreenChange(screen); threadData->ethread->notifyGameScreenChange(screen);
} }
@ -680,17 +690,31 @@ struct GraphicsPrivate
metaBlitBufferFlippedScaled(scRes); metaBlitBufferFlippedScaled(scRes);
} }
void metaBlitBufferFlippedScaled(const Vec2i &sourceSize) void metaBlitBufferFlippedScaled(const Vec2i &sourceSize, bool forceNearestNeighbour = false)
{ {
GLMeta::blitRectangle(IntRect(0, 0, sourceSize.x, sourceSize.y), GLMeta::blitRectangle(IntRect(0, 0, sourceSize.x, sourceSize.y),
IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y), IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y),
threadData->config.smoothScaling); !forceNearestNeighbour && threadData->config.smoothScaling);
} }
void redrawScreen() void redrawScreen()
{ {
screen.composite(); 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()) if (integerScaleStepApplicable())
{ {
assert(integerScaleBuffer.tex != TEX::ID(0)); assert(integerScaleBuffer.tex != TEX::ID(0));
@ -1133,7 +1157,48 @@ bool Graphics::getFixedAspectRatio() const
void Graphics::setFixedAspectRatio(bool value) void Graphics::setFixedAspectRatio(bool value)
{ {
shState->config().fixedAspectRatio = 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); p->updateScreenResoRatio(p->threadData);
} }

View File

@ -63,6 +63,9 @@ public:
DECL_ATTR( ShowCursor, bool ) DECL_ATTR( ShowCursor, bool )
DECL_ATTR( FixedAspectRatio, bool ) DECL_ATTR( FixedAspectRatio, bool )
DECL_ATTR( SmoothScaling, bool )
DECL_ATTR( IntegerScaling, bool )
DECL_ATTR( LastMileScaling, bool )
/* <internal> */ /* <internal> */
Scene *getScreen() const; Scene *getScreen() const;