GBA: Add bilinear resampling option
@@ -5,6 +5,7 @@ - Add scale presets for up to 6x
- 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
@@ -199,6 +199,9 @@ }
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 @@ ConfigurationSetIntValue(&config->defaultsTable, 0, "fullscreen", opts->fullscreen);
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) {
@@ -29,6 +29,7 @@ int fullscreen;
int width; int height; bool lockAspectRatio; + bool resampleVideo; bool videoSync; bool audioSync;
@@ -55,6 +55,7 @@ connect(m_drawThread, SIGNAL(started()), m_painter, SLOT(start()));
m_drawThread->start(QThread::TimeCriticalPriority); lockAspectRatio(m_lockAspectRatio); + filter(m_filter); } void Display::stopDrawing() {@@ -114,6 +115,13 @@ QMetaObject::invokeMethod(m_painter, "lockAspectRatio", Qt::QueuedConnection, Q_ARG(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 @@ m_lockAspectRatio = 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 @@ glGenTextures(1, &m_tex);
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);
@@ -28,6 +28,7 @@ void pauseDrawing();
void unpauseDrawing(); void forceDraw(); void lockAspectRatio(bool lock); + void filter(bool filter); #ifdef USE_PNG void screenshot(); #endif@@ -42,6 +43,7 @@ Painter* m_painter;
QThread* m_drawThread; GBAThread* m_context; bool m_lockAspectRatio; + bool m_filter; }; class Painter : public QObject {@@ -62,6 +64,7 @@ void pause();
void unpause(); void resize(const QSize& size); void lockAspectRatio(bool lock); + void filter(bool filter); private: void performDraw();@@ -73,6 +76,7 @@ GLuint m_tex;
QGLWidget* m_gl; QSize m_size; bool m_lockAspectRatio; + bool m_filter; }; }
@@ -25,6 +25,7 @@ loadSetting("frameskip", m_ui.frameskip);
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 @@ saveSetting("frameskip", m_ui.frameskip);
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());
@@ -224,9 +224,6 @@ </widget>
</item> <item row="10" column="1"> <widget class="QCheckBox" name="resampleVideo"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>Resample video</string> </property>
@@ -138,6 +138,7 @@ m_controller->setFrameskip(opts->frameskip);
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);@@ -531,6 +532,11 @@ ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio");
lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu); 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");
@@ -64,8 +64,13 @@ renderer->d.outputBufferStride = 256;
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);
@@ -75,6 +75,9 @@ renderer.events.windowUpdated = 0;
#endif renderer.ratio = graphicsOpts.multiplier; + renderer.lockAspectRatio = opts.lockAspectRatio; + renderer.filter = opts.resampleVideo; + if (!_GBASDLInit(&renderer)) { freeArguments(&args); GBAConfigFreeOpts(&opts);
@@ -48,6 +48,9 @@ int viewportWidth;
int viewportHeight; int ratio; + bool lockAspectRatio; + bool filter; + #ifdef BUILD_GL GLuint tex; #endif