mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2024-10-28 11:19:36 +01:00
Allow independent upscale/downscale interpolation methods
This commit is contained in:
parent
d4c20d7720
commit
ebcb0e2486
7 changed files with 98 additions and 56 deletions
|
@ -89,8 +89,15 @@
|
|||
// "smoothScaling": 0,
|
||||
|
||||
|
||||
// Apply smooth interpolation when game screen
|
||||
// is downscaled (same values as smoothScaling)
|
||||
// (default: 0)
|
||||
//
|
||||
// "smoothScalingDown": 0,
|
||||
|
||||
|
||||
// Apply mipmap interpolation when game screen
|
||||
// is downscaled
|
||||
// is downscaled (requires "smoothScalingDown": 1)
|
||||
// (default: false)
|
||||
//
|
||||
// "smoothScalingMipmaps": false,
|
||||
|
|
|
@ -135,6 +135,7 @@ void Config::read(int argc, char *argv[]) {
|
|||
{"fullscreen", false},
|
||||
{"fixedAspectRatio", true},
|
||||
{"smoothScaling", 0},
|
||||
{"smoothScalingDown", 0},
|
||||
{"smoothScalingMipmaps", false},
|
||||
{"bicubicSharpness", 100},
|
||||
#ifdef MKXPZ_SSL
|
||||
|
@ -270,6 +271,7 @@ try { exp } catch (...) {}
|
|||
SET_OPT(fullscreen, boolean);
|
||||
SET_OPT(fixedAspectRatio, boolean);
|
||||
SET_OPT(smoothScaling, integer);
|
||||
SET_OPT(smoothScalingDown, integer);
|
||||
SET_OPT(smoothScalingMipmaps, boolean);
|
||||
SET_OPT(bicubicSharpness, integer);
|
||||
#ifdef MKXPZ_SSL
|
||||
|
|
|
@ -44,6 +44,7 @@ struct Config {
|
|||
bool fullscreen;
|
||||
bool fixedAspectRatio;
|
||||
int smoothScaling;
|
||||
int smoothScalingDown;
|
||||
bool smoothScalingMipmaps;
|
||||
int bicubicSharpness;
|
||||
#ifdef MKXPZ_SSL
|
||||
|
|
|
@ -140,7 +140,7 @@ void vaoUnbind(VAO &vao)
|
|||
|
||||
#define HAVE_NATIVE_BLIT gl.BlitFramebuffer
|
||||
|
||||
bool blitScaleIsOne(TEXFBO &target, bool targetPreferHires, const IntRect &targetRect, TEXFBO &source, const IntRect &sourceRect)
|
||||
int blitScaleIsSpecial(TEXFBO &target, bool targetPreferHires, const IntRect &targetRect, TEXFBO &source, const IntRect &sourceRect)
|
||||
{
|
||||
int targetWidth = targetRect.w;
|
||||
int targetHeight = targetRect.h;
|
||||
|
@ -166,10 +166,33 @@ bool blitScaleIsOne(TEXFBO &target, bool targetPreferHires, const IntRect &targe
|
|||
sourceHeight /= source.height;
|
||||
}
|
||||
|
||||
return targetWidth == sourceWidth && targetHeight == sourceHeight;
|
||||
if (targetWidth == sourceWidth && targetHeight == sourceHeight)
|
||||
{
|
||||
return SameScale;
|
||||
}
|
||||
|
||||
if (targetWidth < sourceWidth && targetHeight < sourceHeight)
|
||||
{
|
||||
return DownScale;
|
||||
}
|
||||
|
||||
return UpScale;
|
||||
}
|
||||
|
||||
static void _blitBegin(FBO::ID fbo, const Vec2i &size, bool scaleIsOne)
|
||||
int smoothScalingMethod(int scaleIsSpecial)
|
||||
{
|
||||
switch (scaleIsSpecial)
|
||||
{
|
||||
case SameScale:
|
||||
return NearestNeighbor;
|
||||
case DownScale:
|
||||
return shState->config().smoothScalingDown;
|
||||
}
|
||||
|
||||
return shState->config().smoothScaling;
|
||||
}
|
||||
|
||||
static void _blitBegin(FBO::ID fbo, const Vec2i &size, int scaleIsSpecial)
|
||||
{
|
||||
if (HAVE_NATIVE_BLIT)
|
||||
{
|
||||
|
@ -181,7 +204,7 @@ static void _blitBegin(FBO::ID fbo, const Vec2i &size, bool scaleIsOne)
|
|||
FBO::bind(fbo);
|
||||
glState.viewport.pushSet(IntRect(0, 0, size.x, size.y));
|
||||
|
||||
switch (scaleIsOne ? NearestNeighbor : shState->config().smoothScaling)
|
||||
switch (smoothScalingMethod(scaleIsSpecial))
|
||||
{
|
||||
case Bicubic:
|
||||
{
|
||||
|
@ -239,7 +262,7 @@ int blitSrcWidthHires = 1;
|
|||
int blitSrcHeightLores = 1;
|
||||
int blitSrcHeightHires = 1;
|
||||
|
||||
void blitBegin(TEXFBO &target, bool preferHires, bool scaleIsOne)
|
||||
void blitBegin(TEXFBO &target, bool preferHires, int scaleIsSpecial)
|
||||
{
|
||||
blitDstWidthLores = target.width;
|
||||
blitDstHeightLores = target.height;
|
||||
|
@ -247,26 +270,26 @@ void blitBegin(TEXFBO &target, bool preferHires, bool scaleIsOne)
|
|||
if (preferHires && target.selfHires != nullptr) {
|
||||
blitDstWidthHires = target.selfHires->width;
|
||||
blitDstHeightHires = target.selfHires->height;
|
||||
_blitBegin(target.selfHires->fbo, Vec2i(target.selfHires->width, target.selfHires->height), scaleIsOne);
|
||||
_blitBegin(target.selfHires->fbo, Vec2i(target.selfHires->width, target.selfHires->height), scaleIsSpecial);
|
||||
}
|
||||
else {
|
||||
blitDstWidthHires = blitDstWidthLores;
|
||||
blitDstHeightHires = blitDstHeightLores;
|
||||
_blitBegin(target.fbo, Vec2i(target.width, target.height), scaleIsOne);
|
||||
_blitBegin(target.fbo, Vec2i(target.width, target.height), scaleIsSpecial);
|
||||
}
|
||||
}
|
||||
|
||||
void blitBeginScreen(const Vec2i &size, bool scaleIsOne)
|
||||
void blitBeginScreen(const Vec2i &size, int scaleIsSpecial)
|
||||
{
|
||||
blitDstWidthLores = 1;
|
||||
blitDstWidthHires = 1;
|
||||
blitDstHeightLores = 1;
|
||||
blitDstHeightHires = 1;
|
||||
|
||||
_blitBegin(FBO::ID(0), size, scaleIsOne);
|
||||
_blitBegin(FBO::ID(0), size, scaleIsSpecial);
|
||||
}
|
||||
|
||||
void blitSource(TEXFBO &source, bool scaleIsOne)
|
||||
void blitSource(TEXFBO &source, int scaleIsSpecial)
|
||||
{
|
||||
blitSrcWidthLores = source.width;
|
||||
blitSrcHeightLores = source.height;
|
||||
|
@ -285,7 +308,7 @@ void blitSource(TEXFBO &source, bool scaleIsOne)
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (scaleIsOne ? NearestNeighbor : shState->config().smoothScaling)
|
||||
switch (smoothScalingMethod(scaleIsSpecial))
|
||||
{
|
||||
case Bicubic:
|
||||
{
|
||||
|
|
|
@ -65,10 +65,11 @@ void vaoBind(VAO &vao);
|
|||
void vaoUnbind(VAO &vao);
|
||||
|
||||
/* EXT_framebuffer_blit */
|
||||
bool blitScaleIsOne(TEXFBO &target, bool targetPreferHires, const IntRect &targetRect, TEXFBO &source, const IntRect &sourceRect);
|
||||
void blitBegin(TEXFBO &target, bool preferHires = false, bool scaleIsOne = false);
|
||||
void blitBeginScreen(const Vec2i &size, bool scaleIsOne = false);
|
||||
void blitSource(TEXFBO &source, bool scaleIsOne = false);
|
||||
int blitScaleIsSpecial(TEXFBO &target, bool targetPreferHires, const IntRect &targetRect, TEXFBO &source, const IntRect &sourceRect);
|
||||
int smoothScalingMethod(int scaleIsSpecial);
|
||||
void blitBegin(TEXFBO &target, bool preferHires = false, int scaleIsOne = 0);
|
||||
void blitBeginScreen(const Vec2i &size, int scaleIsOne = 0);
|
||||
void blitSource(TEXFBO &source, int scaleIsOne = 0);
|
||||
void blitRectangle(const IntRect &src, const Vec2i &dstPos);
|
||||
void blitRectangle(const IntRect &src, const IntRect &dst,
|
||||
bool smooth = false);
|
||||
|
|
|
@ -543,10 +543,10 @@ public:
|
|||
* be turned on, so turn it off temporarily */
|
||||
glState.scissorTest.pushSet(false);
|
||||
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(pp.frontBuffer(), false, geometry.rect, pp.backBuffer(), geometry.rect);
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(pp.frontBuffer(), false, geometry.rect, pp.backBuffer(), geometry.rect);
|
||||
|
||||
GLMeta::blitBegin(pp.frontBuffer(), false, scaleIsOne);
|
||||
GLMeta::blitSource(pp.backBuffer(), scaleIsOne);
|
||||
GLMeta::blitBegin(pp.frontBuffer(), false, scaleIsSpecial);
|
||||
GLMeta::blitSource(pp.backBuffer(), scaleIsSpecial);
|
||||
GLMeta::blitRectangle(geometry.rect, Vec2i());
|
||||
GLMeta::blitEnd();
|
||||
|
||||
|
@ -1011,29 +1011,29 @@ struct GraphicsPrivate {
|
|||
void compositeToBufferScaled(TEXFBO &buffer, int destWidth, int destHeight) {
|
||||
screen.composite();
|
||||
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(buffer, false, IntRect(0, 0, destWidth, destHeight), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(buffer, false, IntRect(0, 0, destWidth, destHeight), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
|
||||
GLMeta::blitBegin(buffer, false, scaleIsOne);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsOne);
|
||||
GLMeta::blitBegin(buffer, false, scaleIsSpecial);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsSpecial);
|
||||
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y), IntRect(0, 0, destWidth, destHeight));
|
||||
GLMeta::blitEnd();
|
||||
}
|
||||
|
||||
void metaBlitBufferFlippedScaled() {
|
||||
metaBlitBufferFlippedScaled(scRes);
|
||||
void metaBlitBufferFlippedScaled(int scaleIsSpecial) {
|
||||
metaBlitBufferFlippedScaled(scRes, scaleIsSpecial);
|
||||
GLMeta::blitRectangle(
|
||||
IntRect(0, 0, scRes.x, scRes.y),
|
||||
IntRect(scOffset.x,
|
||||
(scSize.y + scOffset.y),
|
||||
scSize.x,
|
||||
-scSize.y),
|
||||
threadData->config.smoothScaling == Bilinear);
|
||||
GLMeta::smoothScalingMethod(scaleIsSpecial) == Bilinear);
|
||||
}
|
||||
|
||||
void metaBlitBufferFlippedScaled(const Vec2i &sourceSize, bool forceNearestNeighbor=false) {
|
||||
void metaBlitBufferFlippedScaled(const Vec2i &sourceSize, int scaleIsSpecial, bool forceNearestNeighbor=false) {
|
||||
GLMeta::blitRectangle(IntRect(0, 0, sourceSize.x, sourceSize.y),
|
||||
IntRect(scOffset.x, scSize.y+scOffset.y, scSize.x, -scSize.y),
|
||||
!forceNearestNeighbor && threadData->config.smoothScaling == Bilinear);
|
||||
!forceNearestNeighbor && GLMeta::smoothScalingMethod(scaleIsSpecial) == Bilinear);
|
||||
}
|
||||
|
||||
void redrawScreen() {
|
||||
|
@ -1042,13 +1042,13 @@ struct GraphicsPrivate {
|
|||
// maybe unspaghetti this later
|
||||
if (integerScaleStepApplicable() && !integerLastMileScaling)
|
||||
{
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(integerScaleBuffer, false, IntRect(0, 0, scSize.x, scSize.y), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(integerScaleBuffer, false, IntRect(0, 0, scSize.x, scSize.y), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
|
||||
GLMeta::blitBeginScreen(winSize, scaleIsOne);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsOne);
|
||||
GLMeta::blitBeginScreen(winSize, scaleIsSpecial);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsSpecial);
|
||||
|
||||
FBO::clear();
|
||||
metaBlitBufferFlippedScaled(scRes, true);
|
||||
metaBlitBufferFlippedScaled(scRes, scaleIsSpecial, true);
|
||||
GLMeta::blitEnd();
|
||||
|
||||
swapGLBuffer();
|
||||
|
@ -1057,11 +1057,11 @@ struct GraphicsPrivate {
|
|||
|
||||
if (integerScaleStepApplicable())
|
||||
{
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(integerScaleBuffer, false, IntRect(0, 0, integerScaleBuffer.width, integerScaleBuffer.height), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(integerScaleBuffer, false, IntRect(0, 0, integerScaleBuffer.width, integerScaleBuffer.height), screen.getPP().frontBuffer(), IntRect(0, 0, scRes.x, scRes.y));
|
||||
|
||||
assert(integerScaleBuffer.tex != TEX::ID(0));
|
||||
GLMeta::blitBegin(integerScaleBuffer, false, scaleIsOne);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsOne);
|
||||
GLMeta::blitBegin(integerScaleBuffer, false, scaleIsSpecial);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsSpecial);
|
||||
|
||||
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y),
|
||||
IntRect(0, 0, integerScaleBuffer.width, integerScaleBuffer.height),
|
||||
|
@ -1082,22 +1082,22 @@ struct GraphicsPrivate {
|
|||
sourceSize = scRes;
|
||||
}
|
||||
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(integerScaleBuffer, false, IntRect(0, 0, scSize.x, scSize.y), integerScaleActive ? integerScaleBuffer : screen.getPP().frontBuffer(), IntRect(0, 0, sourceSize.x, sourceSize.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(integerScaleBuffer, false, IntRect(0, 0, scSize.x, scSize.y), integerScaleActive ? integerScaleBuffer : screen.getPP().frontBuffer(), IntRect(0, 0, sourceSize.x, sourceSize.y));
|
||||
|
||||
GLMeta::blitBeginScreen(winSize, scaleIsOne);
|
||||
//GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsOne);
|
||||
GLMeta::blitBeginScreen(winSize, scaleIsSpecial);
|
||||
//GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsSpecial);
|
||||
|
||||
if (integerScaleActive)
|
||||
{
|
||||
GLMeta::blitSource(integerScaleBuffer, scaleIsOne);
|
||||
GLMeta::blitSource(integerScaleBuffer, scaleIsSpecial);
|
||||
}
|
||||
else
|
||||
{
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsOne);
|
||||
GLMeta::blitSource(screen.getPP().frontBuffer(), scaleIsSpecial);
|
||||
}
|
||||
|
||||
FBO::clear();
|
||||
metaBlitBufferFlippedScaled(sourceSize);
|
||||
metaBlitBufferFlippedScaled(sourceSize, scaleIsSpecial);
|
||||
|
||||
GLMeta::blitEnd();
|
||||
|
||||
|
@ -1327,11 +1327,11 @@ void Graphics::transition(int duration, const char *filename, int vague) {
|
|||
FBO::unbind();
|
||||
FBO::clear();
|
||||
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), transBuffer, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), transBuffer, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
|
||||
GLMeta::blitBeginScreen(Vec2i(p->winSize), scaleIsOne);
|
||||
GLMeta::blitSource(transBuffer, scaleIsOne);
|
||||
p->metaBlitBufferFlippedScaled();
|
||||
GLMeta::blitBeginScreen(Vec2i(p->winSize), scaleIsSpecial);
|
||||
GLMeta::blitSource(transBuffer, scaleIsSpecial);
|
||||
p->metaBlitBufferFlippedScaled(scaleIsSpecial);
|
||||
GLMeta::blitEnd();
|
||||
|
||||
p->swapGLBuffer();
|
||||
|
@ -1388,13 +1388,13 @@ void Graphics::fadeout(int duration) {
|
|||
setBrightness(diff + (curr / duration) * i);
|
||||
|
||||
if (p->frozen) {
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), p->frozenScene, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), p->frozenScene, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
|
||||
GLMeta::blitBeginScreen(p->scSize, scaleIsOne);
|
||||
GLMeta::blitSource(p->frozenScene, scaleIsOne);
|
||||
GLMeta::blitBeginScreen(p->scSize, scaleIsSpecial);
|
||||
GLMeta::blitSource(p->frozenScene, scaleIsSpecial);
|
||||
|
||||
FBO::clear();
|
||||
p->metaBlitBufferFlippedScaled();
|
||||
p->metaBlitBufferFlippedScaled(scaleIsSpecial);
|
||||
|
||||
GLMeta::blitEnd();
|
||||
|
||||
|
@ -1415,13 +1415,13 @@ void Graphics::fadein(int duration) {
|
|||
setBrightness(curr + (diff / duration) * i);
|
||||
|
||||
if (p->frozen) {
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), p->frozenScene, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), p->frozenScene, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
|
||||
GLMeta::blitBeginScreen(p->scSize, scaleIsOne);
|
||||
GLMeta::blitSource(p->frozenScene, scaleIsOne);
|
||||
GLMeta::blitBeginScreen(p->scSize, scaleIsSpecial);
|
||||
GLMeta::blitSource(p->frozenScene, scaleIsSpecial);
|
||||
|
||||
FBO::clear();
|
||||
p->metaBlitBufferFlippedScaled();
|
||||
p->metaBlitBufferFlippedScaled(scaleIsSpecial);
|
||||
|
||||
GLMeta::blitEnd();
|
||||
|
||||
|
@ -1726,10 +1726,10 @@ void Graphics::repaintWait(const AtomicFlag &exitCond, bool checkReset) {
|
|||
/* Repaint the screen with the last good frame we drew */
|
||||
TEXFBO &lastFrame = p->screen.getPP().frontBuffer();
|
||||
|
||||
bool scaleIsOne = GLMeta::blitScaleIsOne(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), lastFrame, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
int scaleIsSpecial = GLMeta::blitScaleIsSpecial(p->integerScaleBuffer, false, IntRect(0, 0, p->scSize.x, p->scSize.y), lastFrame, IntRect(0, 0, p->scRes.x, p->scRes.y));
|
||||
|
||||
GLMeta::blitBeginScreen(p->winSize, scaleIsOne);
|
||||
GLMeta::blitSource(lastFrame, scaleIsOne);
|
||||
GLMeta::blitBeginScreen(p->winSize, scaleIsSpecial);
|
||||
GLMeta::blitSource(lastFrame, scaleIsSpecial);
|
||||
|
||||
while (!exitCond) {
|
||||
shState->checkShutdown();
|
||||
|
@ -1738,7 +1738,7 @@ void Graphics::repaintWait(const AtomicFlag &exitCond, bool checkReset) {
|
|||
shState->checkReset();
|
||||
|
||||
FBO::clear();
|
||||
p->metaBlitBufferFlippedScaled();
|
||||
p->metaBlitBufferFlippedScaled(scaleIsSpecial);
|
||||
SDL_GL_SwapWindow(p->threadData->window);
|
||||
p->fpsLimiter.delay();
|
||||
|
||||
|
|
|
@ -211,6 +211,14 @@ enum InterpolationMethod
|
|||
#endif
|
||||
};
|
||||
|
||||
enum SpecialScale
|
||||
{
|
||||
// If the X and Y scales would yield different results, it's considered UpScale.
|
||||
UpScale = 0,
|
||||
SameScale = 1,
|
||||
DownScale = 2,
|
||||
};
|
||||
|
||||
/* For internal use.
|
||||
* All drawable classes have properties of one or more of the above
|
||||
* types, which in an interpreted environment act as independent
|
||||
|
|
Loading…
Reference in a new issue