All: Add option to lock video to integer scaling

This commit is contained in:
Vicki Pfau 2017-04-21 18:13:16 -07:00
parent 69a30f9501
commit 2d930cbc61
16 changed files with 81 additions and 4 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
} }

View File

@ -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);

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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) {

View File

@ -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*);

View File

@ -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);

View File

@ -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 {}

View File

@ -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);

View File

@ -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">

View File

@ -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);

View File

@ -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;
}; };
} }

View File

@ -35,6 +35,7 @@ struct VideoBackend {
bool filter; bool filter;
bool lockAspectRatio; bool lockAspectRatio;
bool lockIntegerScaling;
}; };
struct VideoShader { struct VideoShader {