diff --git a/CHANGES b/CHANGES index 21120e626..0a68166af 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: - Debugger: Add CLI "frame", frame advance command - Better audio resampling via FFmpeg - Settings window + - Bilinear resampling option Bugfixes: - Qt: Fix issue with set frame sizes being the wrong height - Qt: Fix emulator crashing when full screen if a game is not running diff --git a/src/gba/gba-config.c b/src/gba/gba-config.c index a59ecc47a..88ff83300 100644 --- a/src/gba/gba-config.c +++ b/src/gba/gba-config.c @@ -199,6 +199,9 @@ void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) { if (_lookupIntValue(config, "lockAspectRatio", &fakeBool)) { opts->lockAspectRatio = fakeBool; } + if (_lookupIntValue(config, "resampleVideo", &fakeBool)) { + opts->resampleVideo = fakeBool; + } _lookupIntValue(config, "fullscreen", &opts->fullscreen); _lookupIntValue(config, "width", &opts->width); @@ -219,6 +222,7 @@ void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* op ConfigurationSetIntValue(&config->defaultsTable, 0, "width", opts->width); ConfigurationSetIntValue(&config->defaultsTable, 0, "height", opts->height); ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio); + ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo); } void GBAConfigFreeOpts(struct GBAOptions* opts) { diff --git a/src/gba/gba-config.h b/src/gba/gba-config.h index 5ed3aa7f0..d07b21981 100644 --- a/src/gba/gba-config.h +++ b/src/gba/gba-config.h @@ -29,6 +29,7 @@ struct GBAOptions { int width; int height; bool lockAspectRatio; + bool resampleVideo; bool videoSync; bool audioSync; diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 82deb155b..5aeffa3c1 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -55,6 +55,7 @@ void Display::startDrawing(const uint32_t* buffer, GBAThread* thread) { m_drawThread->start(QThread::TimeCriticalPriority); lockAspectRatio(m_lockAspectRatio); + filter(m_filter); } void Display::stopDrawing() { @@ -114,6 +115,13 @@ void Display::lockAspectRatio(bool lock) { } } +void Display::filter(bool filter) { + m_filter = filter; + if (m_drawThread) { + QMetaObject::invokeMethod(m_painter, "filter", Qt::QueuedConnection, Q_ARG(bool, filter)); + } +} + #ifdef USE_PNG void Display::screenshot() { GBAThreadInterrupt(m_context); @@ -163,6 +171,18 @@ void Painter::lockAspectRatio(bool lock) { forceDraw(); } +void Painter::filter(bool filter) { + m_filter = filter; + m_gl->makeCurrent(); + if (m_filter) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + m_gl->doneCurrent(); + forceDraw(); +} + void Painter::start() { m_gl->makeCurrent(); glEnable(GL_TEXTURE_2D); @@ -170,7 +190,11 @@ void Painter::start() { glBindTexture(GL_TEXTURE_2D, m_tex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (m_filter) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_INT, 0, _glVertices); diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index f06a81606..746982a45 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -28,6 +28,7 @@ public slots: void unpauseDrawing(); void forceDraw(); void lockAspectRatio(bool lock); + void filter(bool filter); #ifdef USE_PNG void screenshot(); #endif @@ -42,6 +43,7 @@ private: QThread* m_drawThread; GBAThread* m_context; bool m_lockAspectRatio; + bool m_filter; }; class Painter : public QObject { @@ -62,6 +64,7 @@ public slots: void unpause(); void resize(const QSize& size); void lockAspectRatio(bool lock); + void filter(bool filter); private: void performDraw(); @@ -73,6 +76,7 @@ private: QGLWidget* m_gl; QSize m_size; bool m_lockAspectRatio; + bool m_filter; }; } diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 87726e85e..ae837f7af 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -25,6 +25,7 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent) loadSetting("lockAspectRatio", m_ui.lockAspectRatio); loadSetting("rewindBufferInterval", m_ui.rewindInterval); loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); + loadSetting("resampleVideo", m_ui.resampleVideo); connect(m_ui.biosBrowse, SIGNAL(clicked()), this, SLOT(selectBios())); connect(m_ui.buttonBox, SIGNAL(accepted()), this, SLOT(updateConfig())); @@ -46,6 +47,7 @@ void SettingsView::updateConfig() { saveSetting("lockAspectRatio", m_ui.lockAspectRatio); saveSetting("rewindBufferInterval", m_ui.rewindInterval); saveSetting("rewindBufferCapacity", m_ui.rewindCapacity); + saveSetting("resampleVideo", m_ui.resampleVideo); m_controller->write(); emit biosLoaded(m_ui.bios->text()); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 1c0b3c4ca..aea709d89 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -224,9 +224,6 @@ - - false - Resample video diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index c0ad2173d..b6dde5a31 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -138,6 +138,7 @@ void Window::loadConfig() { m_controller->setAudioSync(opts->audioSync); m_controller->setVideoSync(opts->videoSync); m_display->lockAspectRatio(opts->lockAspectRatio); + m_display->filter(opts->resampleVideo); if (opts->bios) { m_controller->loadBIOS(opts->bios); @@ -532,6 +533,11 @@ void Window::setupMenu(QMenuBar* menubar) { lockAspectRatio->connect([this](const QVariant& value) { m_display->lockAspectRatio(value.toBool()); }); m_config->updateOption("lockAspectRatio"); + ConfigOption* resampleVideo = m_config->addOption("resampleVideo"); + resampleVideo->addBoolean(tr("Resample video"), avMenu); + resampleVideo->connect([this](const QVariant& value) { m_display->filter(value.toBool()); }); + m_config->updateOption("resampleVideo"); + QMenu* skipMenu = avMenu->addMenu(tr("Frame&skip")); ConfigOption* skip = m_config->addOption("frameskip"); skip->connect([this](const QVariant& value) { m_controller->setFrameskip(value.toInt()); }); diff --git a/src/platform/sdl/gl-sdl.c b/src/platform/sdl/gl-sdl.c index e6e7e2254..3be076d74 100644 --- a/src/platform/sdl/gl-sdl.c +++ b/src/platform/sdl/gl-sdl.c @@ -64,8 +64,13 @@ bool GBASDLInit(struct SDLSoftwareRenderer* renderer) { glGenTextures(1, &renderer->tex); glBindTexture(GL_TEXTURE_2D, renderer->tex); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (renderer->filter) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } #ifndef _WIN32 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index 5563412dd..c4a6437a9 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -75,6 +75,9 @@ int main(int argc, char** argv) { #endif renderer.ratio = graphicsOpts.multiplier; + renderer.lockAspectRatio = opts.lockAspectRatio; + renderer.filter = opts.resampleVideo; + if (!_GBASDLInit(&renderer)) { freeArguments(&args); GBAConfigFreeOpts(&opts); diff --git a/src/platform/sdl/main.h b/src/platform/sdl/main.h index 74581267c..0066694d1 100644 --- a/src/platform/sdl/main.h +++ b/src/platform/sdl/main.h @@ -48,6 +48,9 @@ struct SDLSoftwareRenderer { int viewportHeight; int ratio; + bool lockAspectRatio; + bool filter; + #ifdef BUILD_GL GLuint tex; #endif