all repos — mgba @ 2d930cbc610b28d82746bbcd121efcd47be47592

mGBA Game Boy Advance Emulator

All: Add option to lock video to integer scaling
Vicki Pfau vi@endrift.com
Fri, 21 Apr 2017 18:13:16 -0700
commit

2d930cbc610b28d82746bbcd121efcd47be47592

parent

69a30f95016a44047d3928b8e5bc1ac4b9a69033

M CHANGESCHANGES

@@ -15,6 +15,7 @@ - Savestates now contain any RTC override data

- Command line ability to override configuration values - Add option to allow preloading the entire ROM before running - GB: Video/audio channel enabling/disabling + - Add option to lock video to integer scaling Bugfixes: - LR35902: Fix core never exiting with certain event patterns - GB Timer: Improve DIV reset behavior
M include/mgba/core/config.hinclude/mgba/core/config.h

@@ -42,6 +42,7 @@ int fullscreen;

int width; int height; bool lockAspectRatio; + bool lockIntegerScaling; bool resampleVideo; bool suspendScreensaver; char* shader;
M src/core/config.csrc/core/config.c

@@ -349,6 +349,9 @@ }

if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) { opts->lockAspectRatio = fakeBool; } + if (_lookupIntValue(config, "lockIntegerScaling", &fakeBool)) { + opts->lockIntegerScaling = fakeBool; + } if (_lookupIntValue(config, "resampleVideo", &fakeBool)) { opts->resampleVideo = fakeBool; }

@@ -396,6 +399,7 @@ ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height);

ConfigurationSetIntValue(&config->defaultsTable, 0, "volume", opts->volume); ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute); ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio); + ConfigurationSetIntValue(&config->defaultsTable, 0, "lockIntegerScaling", opts->lockIntegerScaling); ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo); ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver); }
M src/platform/opengl/gl.csrc/platform/opengl/gl.c

@@ -65,6 +65,10 @@ } else if (w * v->height < h * v->width) {

drawH = w * v->height / v->width; } } + if (v->lockIntegerScaling) { + drawW -= drawW % v->width; + drawH -= drawH % v->height; + } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0, 0, 0, 0);
M src/platform/opengl/gles2.csrc/platform/opengl/gles2.c

@@ -171,6 +171,10 @@ } else if (w * v->height < h * v->width) {

drawH = w * v->height / v->width; } } + if (v->lockIntegerScaling) { + drawW -= drawW % v->width; + drawH -= drawH % v->height; + } glViewport(0, 0, v->width, v->height); glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT);
M src/platform/qt/Display.cppsrc/platform/qt/Display.cpp

@@ -54,6 +54,7 @@

Display::Display(QWidget* parent) : QWidget(parent) , m_lockAspectRatio(false) + , m_lockIntegerScaling(false) , m_filter(false) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

@@ -75,6 +76,10 @@

void Display::lockAspectRatio(bool lock) { m_lockAspectRatio = lock; m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio()); +} + +void Display::lockIntegerScaling(bool lock) { + m_lockIntegerScaling = lock; } void Display::filter(bool filter) {
M src/platform/qt/Display.hsrc/platform/qt/Display.h

@@ -38,6 +38,7 @@ static Display* create(QWidget* parent = nullptr);

static void setDriver(Driver driver) { s_driver = driver; } bool isAspectRatioLocked() const { return m_lockAspectRatio; } + bool isIntegerScalingLocked() const { return m_lockIntegerScaling; } bool isFiltered() const { return m_filter; } virtual bool isDrawing() const = 0;

@@ -55,6 +56,7 @@ virtual void pauseDrawing() = 0;

virtual void unpauseDrawing() = 0; virtual void forceDraw() = 0; virtual void lockAspectRatio(bool lock); + virtual void lockIntegerScaling(bool lock); virtual void filter(bool filter); virtual void framePosted(const uint32_t*) = 0; virtual void setShaders(struct VDir*) = 0;

@@ -74,6 +76,7 @@ static const int MOUSE_DISAPPEAR_TIMER = 1000;

MessagePainter m_messagePainter; bool m_lockAspectRatio; + bool m_lockIntegerScaling; bool m_filter; QTimer m_mouseTimer; };
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -73,6 +73,7 @@ m_drawThread->start();

mCoreSyncSetVideoSync(&m_context->sync, false); lockAspectRatio(isAspectRatioLocked()); + lockIntegerScaling(isIntegerScalingLocked()); filter(isFiltered()); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());

@@ -133,6 +134,13 @@ void DisplayGL::lockAspectRatio(bool lock) {

Display::lockAspectRatio(lock); if (m_drawThread) { QMetaObject::invokeMethod(m_painter, "lockAspectRatio", Q_ARG(bool, lock)); + } +} + +void DisplayGL::lockIntegerScaling(bool lock) { + Display::lockIntegerScaling(lock); + if (m_drawThread) { + QMetaObject::invokeMethod(m_painter, "lockIntegerScaling", Q_ARG(bool, lock)); } }

@@ -285,6 +293,13 @@ }

void PainterGL::lockAspectRatio(bool lock) { m_backend->lockAspectRatio = lock; + if (m_started && !m_active) { + forceDraw(); + } +} + +void PainterGL::lockIntegerScaling(bool lock) { + m_backend->lockIntegerScaling = lock; if (m_started && !m_active) { forceDraw(); }
M src/platform/qt/DisplayGL.hsrc/platform/qt/DisplayGL.h

@@ -55,6 +55,7 @@ void pauseDrawing() override;

void unpauseDrawing() override; void forceDraw() override; void lockAspectRatio(bool lock) override; + void lockIntegerScaling(bool lock) override; void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override;

@@ -96,6 +97,7 @@ void pause();

void unpause(); void resize(const QSize& size); void lockAspectRatio(bool lock); + void lockIntegerScaling(bool lock); void filter(bool filter); void setShaders(struct VDir*);
M src/platform/qt/DisplayQt.cppsrc/platform/qt/DisplayQt.cpp

@@ -30,6 +30,11 @@ Display::lockAspectRatio(lock);

update(); } +void DisplayQt::lockIntegerScaling(bool lock) { + Display::lockIntegerScaling(lock); + update(); +} + void DisplayQt::filter(bool filter) { Display::filter(filter); update();

@@ -65,6 +70,10 @@ ds.setWidth(s.height() * m_width / m_height);

} else if (s.width() * m_height < s.height() * m_width) { ds.setHeight(s.width() * m_height / m_width); } + } + if (isIntegerScalingLocked()) { + ds.setWidth(ds.width() - ds.width() % m_width); + ds.setHeight(ds.height() - ds.height() % m_height); } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds);
M src/platform/qt/DisplayQt.hsrc/platform/qt/DisplayQt.h

@@ -30,6 +30,7 @@ void pauseDrawing() override { m_isDrawing = false; }

void unpauseDrawing() override { m_isDrawing = true; } void forceDraw() override { update(); } void lockAspectRatio(bool lock) override; + void lockIntegerScaling(bool lock) override; void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override {}
M src/platform/qt/SettingsView.cppsrc/platform/qt/SettingsView.cpp

@@ -190,6 +190,7 @@ saveSetting("audioSync", m_ui.audioSync);

saveSetting("frameskip", m_ui.frameskip); saveSetting("fpsTarget", m_ui.fpsTarget); saveSetting("lockAspectRatio", m_ui.lockAspectRatio); + saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling); saveSetting("volume", m_ui.volume); saveSetting("mute", m_ui.mute); saveSetting("rewindEnable", m_ui.rewind);

@@ -270,6 +271,7 @@ loadSetting("audioSync", m_ui.audioSync);

loadSetting("frameskip", m_ui.frameskip); loadSetting("fpsTarget", m_ui.fpsTarget); loadSetting("lockAspectRatio", m_ui.lockAspectRatio); + loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling); loadSetting("volume", m_ui.volume); loadSetting("mute", m_ui.mute); loadSetting("rewindEnable", m_ui.rewind);
M src/platform/qt/SettingsView.uisrc/platform/qt/SettingsView.ui

@@ -7,7 +7,7 @@ <rect>

<x>0</x> <y>0</y> <width>650</width> - <height>450</height> + <height>454</height> </rect> </property> <property name="sizePolicy">

@@ -115,7 +115,7 @@ <widget class="QComboBox" name="audioBufferSize">

<property name="editable"> <bool>true</bool> </property> - <property name="currentText" stdset="0"> + <property name="currentText"> <string>1536</string> </property> <property name="currentIndex">

@@ -181,7 +181,7 @@ <widget class="QComboBox" name="sampleRate">

<property name="editable"> <bool>true</bool> </property> - <property name="currentText" stdset="0"> + <property name="currentText"> <string>44100</string> </property> <property name="currentIndex">

@@ -380,10 +380,17 @@ <string>Lock aspect ratio</string>

</property> </widget> </item> - <item row="11" column="1"> + <item row="12" column="1"> <widget class="QCheckBox" name="resampleVideo"> <property name="text"> <string>Bilinear filtering</string> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QCheckBox" name="lockIntegerScaling"> + <property name="text"> + <string>Force integer scaling</string> </property> </widget> </item>
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -1263,6 +1263,14 @@ m_display->lockAspectRatio(value.toBool());

}, this); m_config->updateOption("lockAspectRatio"); + ConfigOption* lockIntegerScaling = m_config->addOption("lockIntegerScaling"); + lockIntegerScaling->addBoolean(tr("Force integer scaling"), avMenu); + lockIntegerScaling->connect([this](const QVariant& value) { + m_display->lockIntegerScaling(value.toBool()); + m_screenWidget->setLockIntegerScaling(value.toBool()); + }, this); + m_config->updateOption("lockIntegerScaling"); + ConfigOption* resampleVideo = m_config->addOption("resampleVideo"); resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu); resampleVideo->connect([this](const QVariant& value) {

@@ -1637,6 +1645,10 @@ m_aspectWidth = width;

m_aspectHeight = height; } +void WindowBackground::setLockIntegerScaling(bool lock) { + m_lockIntegerScaling = lock; +} + void WindowBackground::paintEvent(QPaintEvent*) { const QPixmap* logo = pixmap(); if (!logo) {

@@ -1651,6 +1663,10 @@ if (ds.width() * m_aspectHeight > ds.height() * m_aspectWidth) {

ds.setWidth(ds.height() * m_aspectWidth / m_aspectHeight); } else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) { ds.setHeight(ds.width() * m_aspectHeight / m_aspectWidth); + } + if (m_lockIntegerScaling) { + ds.setWidth(ds.width() - ds.width() % m_aspectWidth); + ds.setHeight(ds.height() - ds.height() % m_aspectHeight); } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds);
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -210,6 +210,7 @@

void setSizeHint(const QSize& size); virtual QSize sizeHint() const override; void setLockAspectRatio(int width, int height); + void setLockIntegerScaling(bool lock); protected: virtual void paintEvent(QPaintEvent*) override;

@@ -218,6 +219,7 @@ private:

QSize m_sizeHint; int m_aspectWidth; int m_aspectHeight; + bool m_lockIntegerScaling; }; }
M src/platform/video-backend.hsrc/platform/video-backend.h

@@ -35,6 +35,7 @@ unsigned height;

bool filter; bool lockAspectRatio; + bool lockIntegerScaling; }; struct VideoShader {