mirror of https://github.com/mgba-emu/mgba.git
All: Add option to lock video to integer scaling
This commit is contained in:
parent
69a30f9501
commit
2d930cbc61
1
CHANGES
1
CHANGES
|
@ -15,6 +15,7 @@ Features:
|
||||||
- Command line ability to override configuration values
|
- Command line ability to override configuration values
|
||||||
- Add option to allow preloading the entire ROM before running
|
- Add option to allow preloading the entire ROM before running
|
||||||
- GB: Video/audio channel enabling/disabling
|
- GB: Video/audio channel enabling/disabling
|
||||||
|
- Add option to lock video to integer scaling
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- LR35902: Fix core never exiting with certain event patterns
|
- LR35902: Fix core never exiting with certain event patterns
|
||||||
- GB Timer: Improve DIV reset behavior
|
- GB Timer: Improve DIV reset behavior
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct mCoreOptions {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
bool lockAspectRatio;
|
bool lockAspectRatio;
|
||||||
|
bool lockIntegerScaling;
|
||||||
bool resampleVideo;
|
bool resampleVideo;
|
||||||
bool suspendScreensaver;
|
bool suspendScreensaver;
|
||||||
char* shader;
|
char* shader;
|
||||||
|
|
|
@ -349,6 +349,9 @@ void mCoreConfigMap(const struct mCoreConfig* config, struct mCoreOptions* opts)
|
||||||
if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) {
|
if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) {
|
||||||
opts->lockAspectRatio = fakeBool;
|
opts->lockAspectRatio = fakeBool;
|
||||||
}
|
}
|
||||||
|
if (_lookupIntValue(config, "lockIntegerScaling", &fakeBool)) {
|
||||||
|
opts->lockIntegerScaling = fakeBool;
|
||||||
|
}
|
||||||
if (_lookupIntValue(config, "resampleVideo", &fakeBool)) {
|
if (_lookupIntValue(config, "resampleVideo", &fakeBool)) {
|
||||||
opts->resampleVideo = fakeBool;
|
opts->resampleVideo = fakeBool;
|
||||||
}
|
}
|
||||||
|
@ -396,6 +399,7 @@ void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptio
|
||||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "volume", opts->volume);
|
ConfigurationSetIntValue(&config->defaultsTable, 0, "volume", opts->volume);
|
||||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);
|
ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);
|
||||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio);
|
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, "resampleVideo", opts->resampleVideo);
|
||||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver);
|
ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,10 @@ static void mGLContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
|
||||||
drawH = w * v->height / v->width;
|
drawH = w * v->height / v->width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (v->lockIntegerScaling) {
|
||||||
|
drawW -= drawW % v->width;
|
||||||
|
drawH -= drawH % v->height;
|
||||||
|
}
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glClearColor(0, 0, 0, 0);
|
glClearColor(0, 0, 0, 0);
|
||||||
|
|
|
@ -171,6 +171,10 @@ static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h)
|
||||||
drawH = w * v->height / 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);
|
glViewport(0, 0, v->width, v->height);
|
||||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
|
@ -54,6 +54,7 @@ Display* Display::create(QWidget* parent) {
|
||||||
Display::Display(QWidget* parent)
|
Display::Display(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_lockAspectRatio(false)
|
, m_lockAspectRatio(false)
|
||||||
|
, m_lockIntegerScaling(false)
|
||||||
, m_filter(false)
|
, m_filter(false)
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||||
|
@ -77,6 +78,10 @@ void Display::lockAspectRatio(bool lock) {
|
||||||
m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
|
m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Display::lockIntegerScaling(bool lock) {
|
||||||
|
m_lockIntegerScaling = lock;
|
||||||
|
}
|
||||||
|
|
||||||
void Display::filter(bool filter) {
|
void Display::filter(bool filter) {
|
||||||
m_filter = filter;
|
m_filter = filter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
static void setDriver(Driver driver) { s_driver = driver; }
|
static void setDriver(Driver driver) { s_driver = driver; }
|
||||||
|
|
||||||
bool isAspectRatioLocked() const { return m_lockAspectRatio; }
|
bool isAspectRatioLocked() const { return m_lockAspectRatio; }
|
||||||
|
bool isIntegerScalingLocked() const { return m_lockIntegerScaling; }
|
||||||
bool isFiltered() const { return m_filter; }
|
bool isFiltered() const { return m_filter; }
|
||||||
|
|
||||||
virtual bool isDrawing() const = 0;
|
virtual bool isDrawing() const = 0;
|
||||||
|
@ -55,6 +56,7 @@ public slots:
|
||||||
virtual void unpauseDrawing() = 0;
|
virtual void unpauseDrawing() = 0;
|
||||||
virtual void forceDraw() = 0;
|
virtual void forceDraw() = 0;
|
||||||
virtual void lockAspectRatio(bool lock);
|
virtual void lockAspectRatio(bool lock);
|
||||||
|
virtual void lockIntegerScaling(bool lock);
|
||||||
virtual void filter(bool filter);
|
virtual void filter(bool filter);
|
||||||
virtual void framePosted(const uint32_t*) = 0;
|
virtual void framePosted(const uint32_t*) = 0;
|
||||||
virtual void setShaders(struct VDir*) = 0;
|
virtual void setShaders(struct VDir*) = 0;
|
||||||
|
@ -74,6 +76,7 @@ private:
|
||||||
|
|
||||||
MessagePainter m_messagePainter;
|
MessagePainter m_messagePainter;
|
||||||
bool m_lockAspectRatio;
|
bool m_lockAspectRatio;
|
||||||
|
bool m_lockIntegerScaling;
|
||||||
bool m_filter;
|
bool m_filter;
|
||||||
QTimer m_mouseTimer;
|
QTimer m_mouseTimer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,6 +73,7 @@ void DisplayGL::startDrawing(mCoreThread* thread) {
|
||||||
mCoreSyncSetVideoSync(&m_context->sync, false);
|
mCoreSyncSetVideoSync(&m_context->sync, false);
|
||||||
|
|
||||||
lockAspectRatio(isAspectRatioLocked());
|
lockAspectRatio(isAspectRatioLocked());
|
||||||
|
lockIntegerScaling(isIntegerScalingLocked());
|
||||||
filter(isFiltered());
|
filter(isFiltered());
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());
|
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());
|
||||||
|
@ -136,6 +137,13 @@ void DisplayGL::lockAspectRatio(bool lock) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayGL::lockIntegerScaling(bool lock) {
|
||||||
|
Display::lockIntegerScaling(lock);
|
||||||
|
if (m_drawThread) {
|
||||||
|
QMetaObject::invokeMethod(m_painter, "lockIntegerScaling", Q_ARG(bool, lock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayGL::filter(bool filter) {
|
void DisplayGL::filter(bool filter) {
|
||||||
Display::filter(filter);
|
Display::filter(filter);
|
||||||
if (m_drawThread) {
|
if (m_drawThread) {
|
||||||
|
@ -290,6 +298,13 @@ void PainterGL::lockAspectRatio(bool lock) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PainterGL::lockIntegerScaling(bool lock) {
|
||||||
|
m_backend->lockIntegerScaling = lock;
|
||||||
|
if (m_started && !m_active) {
|
||||||
|
forceDraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PainterGL::filter(bool filter) {
|
void PainterGL::filter(bool filter) {
|
||||||
m_backend->filter = filter;
|
m_backend->filter = filter;
|
||||||
if (m_started && !m_active) {
|
if (m_started && !m_active) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ public slots:
|
||||||
void unpauseDrawing() override;
|
void unpauseDrawing() override;
|
||||||
void forceDraw() override;
|
void forceDraw() override;
|
||||||
void lockAspectRatio(bool lock) override;
|
void lockAspectRatio(bool lock) override;
|
||||||
|
void lockIntegerScaling(bool lock) override;
|
||||||
void filter(bool filter) override;
|
void filter(bool filter) override;
|
||||||
void framePosted(const uint32_t*) override;
|
void framePosted(const uint32_t*) override;
|
||||||
void setShaders(struct VDir*) override;
|
void setShaders(struct VDir*) override;
|
||||||
|
@ -96,6 +97,7 @@ public slots:
|
||||||
void unpause();
|
void unpause();
|
||||||
void resize(const QSize& size);
|
void resize(const QSize& size);
|
||||||
void lockAspectRatio(bool lock);
|
void lockAspectRatio(bool lock);
|
||||||
|
void lockIntegerScaling(bool lock);
|
||||||
void filter(bool filter);
|
void filter(bool filter);
|
||||||
|
|
||||||
void setShaders(struct VDir*);
|
void setShaders(struct VDir*);
|
||||||
|
|
|
@ -30,6 +30,11 @@ void DisplayQt::lockAspectRatio(bool lock) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayQt::lockIntegerScaling(bool lock) {
|
||||||
|
Display::lockIntegerScaling(lock);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayQt::filter(bool filter) {
|
void DisplayQt::filter(bool filter) {
|
||||||
Display::filter(filter);
|
Display::filter(filter);
|
||||||
update();
|
update();
|
||||||
|
@ -66,6 +71,10 @@ void DisplayQt::paintEvent(QPaintEvent*) {
|
||||||
ds.setHeight(s.width() * m_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);
|
QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2);
|
||||||
QRect full(origin, ds);
|
QRect full(origin, ds);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
||||||
void unpauseDrawing() override { m_isDrawing = true; }
|
void unpauseDrawing() override { m_isDrawing = true; }
|
||||||
void forceDraw() override { update(); }
|
void forceDraw() override { update(); }
|
||||||
void lockAspectRatio(bool lock) override;
|
void lockAspectRatio(bool lock) override;
|
||||||
|
void lockIntegerScaling(bool lock) override;
|
||||||
void filter(bool filter) override;
|
void filter(bool filter) override;
|
||||||
void framePosted(const uint32_t*) override;
|
void framePosted(const uint32_t*) override;
|
||||||
void setShaders(struct VDir*) override {}
|
void setShaders(struct VDir*) override {}
|
||||||
|
|
|
@ -190,6 +190,7 @@ void SettingsView::updateConfig() {
|
||||||
saveSetting("frameskip", m_ui.frameskip);
|
saveSetting("frameskip", m_ui.frameskip);
|
||||||
saveSetting("fpsTarget", m_ui.fpsTarget);
|
saveSetting("fpsTarget", m_ui.fpsTarget);
|
||||||
saveSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
saveSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
||||||
|
saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling);
|
||||||
saveSetting("volume", m_ui.volume);
|
saveSetting("volume", m_ui.volume);
|
||||||
saveSetting("mute", m_ui.mute);
|
saveSetting("mute", m_ui.mute);
|
||||||
saveSetting("rewindEnable", m_ui.rewind);
|
saveSetting("rewindEnable", m_ui.rewind);
|
||||||
|
@ -270,6 +271,7 @@ void SettingsView::reloadConfig() {
|
||||||
loadSetting("frameskip", m_ui.frameskip);
|
loadSetting("frameskip", m_ui.frameskip);
|
||||||
loadSetting("fpsTarget", m_ui.fpsTarget);
|
loadSetting("fpsTarget", m_ui.fpsTarget);
|
||||||
loadSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
loadSetting("lockAspectRatio", m_ui.lockAspectRatio);
|
||||||
|
loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling);
|
||||||
loadSetting("volume", m_ui.volume);
|
loadSetting("volume", m_ui.volume);
|
||||||
loadSetting("mute", m_ui.mute);
|
loadSetting("mute", m_ui.mute);
|
||||||
loadSetting("rewindEnable", m_ui.rewind);
|
loadSetting("rewindEnable", m_ui.rewind);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>650</width>
|
<width>650</width>
|
||||||
<height>450</height>
|
<height>454</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentText" stdset="0">
|
<property name="currentText">
|
||||||
<string>1536</string>
|
<string>1536</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
|
@ -181,7 +181,7 @@
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentText" stdset="0">
|
<property name="currentText">
|
||||||
<string>44100</string>
|
<string>44100</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
|
@ -380,13 +380,20 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="1">
|
<item row="12" column="1">
|
||||||
<widget class="QCheckBox" name="resampleVideo">
|
<widget class="QCheckBox" name="resampleVideo">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bilinear filtering</string>
|
<string>Bilinear filtering</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QCheckBox" name="lockIntegerScaling">
|
||||||
|
<property name="text">
|
||||||
|
<string>Force integer scaling</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="interface_2">
|
<widget class="QWidget" name="interface_2">
|
||||||
|
|
|
@ -1263,6 +1263,14 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||||
}, this);
|
}, this);
|
||||||
m_config->updateOption("lockAspectRatio");
|
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");
|
ConfigOption* resampleVideo = m_config->addOption("resampleVideo");
|
||||||
resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu);
|
resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu);
|
||||||
resampleVideo->connect([this](const QVariant& value) {
|
resampleVideo->connect([this](const QVariant& value) {
|
||||||
|
@ -1637,6 +1645,10 @@ void WindowBackground::setLockAspectRatio(int width, int height) {
|
||||||
m_aspectHeight = height;
|
m_aspectHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowBackground::setLockIntegerScaling(bool lock) {
|
||||||
|
m_lockIntegerScaling = lock;
|
||||||
|
}
|
||||||
|
|
||||||
void WindowBackground::paintEvent(QPaintEvent*) {
|
void WindowBackground::paintEvent(QPaintEvent*) {
|
||||||
const QPixmap* logo = pixmap();
|
const QPixmap* logo = pixmap();
|
||||||
if (!logo) {
|
if (!logo) {
|
||||||
|
@ -1652,6 +1664,10 @@ void WindowBackground::paintEvent(QPaintEvent*) {
|
||||||
} else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) {
|
} else if (ds.width() * m_aspectHeight < ds.height() * m_aspectWidth) {
|
||||||
ds.setHeight(ds.width() * m_aspectHeight / 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);
|
QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2);
|
||||||
QRect full(origin, ds);
|
QRect full(origin, ds);
|
||||||
painter.drawPixmap(full, *logo);
|
painter.drawPixmap(full, *logo);
|
||||||
|
|
|
@ -210,6 +210,7 @@ public:
|
||||||
void setSizeHint(const QSize& size);
|
void setSizeHint(const QSize& size);
|
||||||
virtual QSize sizeHint() const override;
|
virtual QSize sizeHint() const override;
|
||||||
void setLockAspectRatio(int width, int height);
|
void setLockAspectRatio(int width, int height);
|
||||||
|
void setLockIntegerScaling(bool lock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintEvent(QPaintEvent*) override;
|
virtual void paintEvent(QPaintEvent*) override;
|
||||||
|
@ -218,6 +219,7 @@ private:
|
||||||
QSize m_sizeHint;
|
QSize m_sizeHint;
|
||||||
int m_aspectWidth;
|
int m_aspectWidth;
|
||||||
int m_aspectHeight;
|
int m_aspectHeight;
|
||||||
|
bool m_lockIntegerScaling;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct VideoBackend {
|
||||||
|
|
||||||
bool filter;
|
bool filter;
|
||||||
bool lockAspectRatio;
|
bool lockAspectRatio;
|
||||||
|
bool lockIntegerScaling;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoShader {
|
struct VideoShader {
|
||||||
|
|
Loading…
Reference in New Issue