Graphics: PoC integer scaling
This commit is contained in:
parent
a91acbe6ef
commit
fb16c8e6d0
115
src/graphics.cpp
115
src/graphics.cpp
|
@ -477,6 +477,11 @@ struct GraphicsPrivate
|
||||||
TEXFBO frozenScene;
|
TEXFBO frozenScene;
|
||||||
Quad screenQuad;
|
Quad screenQuad;
|
||||||
|
|
||||||
|
Vec2i integerScaleFactor;
|
||||||
|
TEXFBO integerScaleBuffer;
|
||||||
|
bool integerScaleActive;
|
||||||
|
bool integerScaleFixedAspectRatio;
|
||||||
|
|
||||||
/* Global list of all live Disposables
|
/* Global list of all live Disposables
|
||||||
* (disposed on reset) */
|
* (disposed on reset) */
|
||||||
IntruList<Disposable> dispList;
|
IntruList<Disposable> dispList;
|
||||||
|
@ -492,7 +497,10 @@ struct GraphicsPrivate
|
||||||
frameCount(0),
|
frameCount(0),
|
||||||
brightness(255),
|
brightness(255),
|
||||||
fpsLimiter(frameRate),
|
fpsLimiter(frameRate),
|
||||||
frozen(false)
|
frozen(false),
|
||||||
|
integerScaleFactor(0, 0),
|
||||||
|
integerScaleActive(true),
|
||||||
|
integerScaleFixedAspectRatio(rtData->config.fixedAspectRatio)
|
||||||
{
|
{
|
||||||
recalculateScreenSize(rtData);
|
recalculateScreenSize(rtData);
|
||||||
updateScreenResoRatio(rtData);
|
updateScreenResoRatio(rtData);
|
||||||
|
@ -501,6 +509,12 @@ struct GraphicsPrivate
|
||||||
TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
|
TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
|
||||||
TEXFBO::linkFBO(frozenScene);
|
TEXFBO::linkFBO(frozenScene);
|
||||||
|
|
||||||
|
if (integerScaleActive)
|
||||||
|
{
|
||||||
|
integerScaleFactor = Vec2i(1, 1);
|
||||||
|
rebuildIntegerScaleBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
FloatRect screenRect(0, 0, scRes.x, scRes.y);
|
FloatRect screenRect(0, 0, scRes.x, scRes.y);
|
||||||
screenQuad.setTexPosRect(screenRect, screenRect);
|
screenQuad.setTexPosRect(screenRect, screenRect);
|
||||||
|
|
||||||
|
@ -510,6 +524,7 @@ struct GraphicsPrivate
|
||||||
~GraphicsPrivate()
|
~GraphicsPrivate()
|
||||||
{
|
{
|
||||||
TEXFBO::fini(frozenScene);
|
TEXFBO::fini(frozenScene);
|
||||||
|
TEXFBO::fini(integerScaleBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateScreenResoRatio(RGSSThreadData *rtData)
|
void updateScreenResoRatio(RGSSThreadData *rtData)
|
||||||
|
@ -544,15 +559,77 @@ struct GraphicsPrivate
|
||||||
scOffset.y = (winSize.y - scSize.y) / 2.f;
|
scOffset.y = (winSize.y - scSize.y) / 2.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int findHighestFittingScale(int base, int target)
|
||||||
|
{
|
||||||
|
int scale = 1;
|
||||||
|
|
||||||
|
while (base * scale <= target)
|
||||||
|
scale += 1;
|
||||||
|
|
||||||
|
Debug() << base << target << scale - 1;
|
||||||
|
|
||||||
|
return scale - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns whether a new scale was found */
|
||||||
|
bool findHighestIntegerScale()
|
||||||
|
{
|
||||||
|
Vec2i newScale(findHighestFittingScale(scRes.x, winSize.x),
|
||||||
|
findHighestFittingScale(scRes.y, winSize.y));
|
||||||
|
|
||||||
|
if (integerScaleFixedAspectRatio)
|
||||||
|
{
|
||||||
|
/* Limit both factors to the smaller of the two */
|
||||||
|
newScale.x = newScale.y = std::min(newScale.x, newScale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newScale == integerScaleFactor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
integerScaleFactor = newScale;
|
||||||
|
Debug() << "Found new scale:" << newScale.x << newScale.y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebuildIntegerScaleBuffer()
|
||||||
|
{
|
||||||
|
TEXFBO::fini(integerScaleBuffer);
|
||||||
|
TEXFBO::init(integerScaleBuffer);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!integerScaleActive)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (integerScaleFactor.x < 1 || integerScaleFactor.y < 1) // XXX should be < 2, this is for testing only
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void checkResize()
|
void checkResize()
|
||||||
{
|
{
|
||||||
if (threadData->windowSizeMsg.poll(winSize))
|
if (threadData->windowSizeMsg.poll(winSize))
|
||||||
{
|
{
|
||||||
|
/* 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;
|
||||||
|
|
||||||
/* 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);
|
||||||
}
|
}
|
||||||
|
@ -600,7 +677,12 @@ struct GraphicsPrivate
|
||||||
|
|
||||||
void metaBlitBufferFlippedScaled()
|
void metaBlitBufferFlippedScaled()
|
||||||
{
|
{
|
||||||
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y),
|
metaBlitBufferFlippedScaled(scRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void metaBlitBufferFlippedScaled(const Vec2i &sourceSize)
|
||||||
|
{
|
||||||
|
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);
|
threadData->config.smoothScaling);
|
||||||
}
|
}
|
||||||
|
@ -609,11 +691,36 @@ struct GraphicsPrivate
|
||||||
{
|
{
|
||||||
screen.composite();
|
screen.composite();
|
||||||
|
|
||||||
|
if (integerScaleStepApplicable())
|
||||||
|
{
|
||||||
|
assert(integerScaleBuffer.tex != TEX::ID(0));
|
||||||
|
GLMeta::blitBegin(integerScaleBuffer);
|
||||||
|
GLMeta::blitSource(screen.getPP().frontBuffer());
|
||||||
|
|
||||||
|
GLMeta::blitRectangle(IntRect(0, 0, scRes.x, scRes.y),
|
||||||
|
IntRect(0, 0, integerScaleBuffer.width, integerScaleBuffer.height),
|
||||||
|
false);
|
||||||
|
|
||||||
|
GLMeta::blitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
GLMeta::blitBeginScreen(winSize);
|
GLMeta::blitBeginScreen(winSize);
|
||||||
GLMeta::blitSource(screen.getPP().frontBuffer());
|
|
||||||
|
Vec2i sourceSize;
|
||||||
|
|
||||||
|
if (integerScaleActive)
|
||||||
|
{
|
||||||
|
GLMeta::blitSource(integerScaleBuffer);
|
||||||
|
sourceSize = Vec2i(integerScaleBuffer.width, integerScaleBuffer.height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMeta::blitSource(screen.getPP().frontBuffer());
|
||||||
|
sourceSize = scRes;
|
||||||
|
}
|
||||||
|
|
||||||
FBO::clear();
|
FBO::clear();
|
||||||
metaBlitBufferFlippedScaled();
|
metaBlitBufferFlippedScaled(sourceSize);
|
||||||
|
|
||||||
GLMeta::blitEnd();
|
GLMeta::blitEnd();
|
||||||
|
|
||||||
|
|
16
src/main.cpp
16
src/main.cpp
|
@ -41,6 +41,10 @@
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shellscalingapi.h>
|
||||||
|
#include <comdef.h>
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
// Try to force dedicated GPU
|
// Try to force dedicated GPU
|
||||||
|
@ -204,6 +208,16 @@ int main(int argc, char *argv[])
|
||||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||||
// SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
// SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||||
|
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
SetProcessDPIAware();
|
||||||
|
// HRESULT hr = SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
// if (FAILED(hr))
|
||||||
|
// {
|
||||||
|
// _com_error err(hr);
|
||||||
|
// fwprintf(stderr, L"SetProcessDpiAwareness: %s\n", err.ErrorMessage());
|
||||||
|
// }
|
||||||
|
#endif
|
||||||
|
|
||||||
/* initialize SDL first */
|
/* initialize SDL first */
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +290,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Window *win;
|
SDL_Window *win;
|
||||||
Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS;
|
Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||||
|
|
||||||
if (conf.winResizable)
|
if (conf.winResizable)
|
||||||
winFlags |= SDL_WINDOW_RESIZABLE;
|
winFlags |= SDL_WINDOW_RESIZABLE;
|
||||||
|
|
Loading…
Reference in New Issue