Qt: Shader loading and unloading
@@ -53,6 +53,7 @@ virtual void lockAspectRatio(bool lock);
virtual void filter(bool filter); virtual void framePosted(const uint32_t*) = 0; virtual void setShaders(struct VDir*) = 0; + virtual void clearShaders() = 0; void showMessage(const QString& message);@@ -61,7 +62,6 @@ virtual void resizeEvent(QResizeEvent*) override;
virtual void mouseMoveEvent(QMouseEvent*) override; MessagePainter* messagePainter() { return &m_messagePainter; } - private: static Driver s_driver;
@@ -148,7 +148,15 @@ }
} void DisplayGL::setShaders(struct VDir* shaders) { - QMetaObject::invokeMethod(m_painter, "setShaders", Q_ARG(struct VDir*, shaders)); + if (m_drawThread) { + QMetaObject::invokeMethod(m_painter, "setShaders", Qt::BlockingQueuedConnection, Q_ARG(struct VDir*, shaders)); + } else { + m_painter->setShaders(shaders); + } +} + +void DisplayGL::clearShaders() { + QMetaObject::invokeMethod(m_painter, "clearShaders"); } void DisplayGL::resizeEvent(QResizeEvent* event) {@@ -385,6 +393,23 @@ }
GBAGLES2ShaderLoad(&m_shader, dir); if (m_started) { GBAGLES2ShaderAttach(reinterpret_cast<GBAGLES2Context*>(m_backend), static_cast<GBAGLES2Shader*>(m_shader.passes), m_shader.nPasses); + } + m_gl->doneCurrent(); +#endif +} + +void PainterGL::clearShaders() { + if (!supportsShaders()) { + return; + } +#if !defined(_WIN32) || defined(USE_EPOXY) + m_gl->makeCurrent(); +#if defined(_WIN32) && defined(USE_EPOXY) + epoxy_handle_external_wglMakeCurrent(); +#endif + if (m_shader.passes) { + GBAGLES2ShaderDetach(reinterpret_cast<GBAGLES2Context*>(m_backend)); + GBAGLES2ShaderFree(&m_shader); } m_gl->doneCurrent(); #endif
@@ -59,6 +59,7 @@ void lockAspectRatio(bool lock) override;
void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override; + void clearShaders() override; protected: virtual void paintEvent(QPaintEvent*) override {}@@ -99,6 +100,7 @@ void lockAspectRatio(bool lock);
void filter(bool filter); void setShaders(struct VDir*); + void clearShaders(); VideoShader* shaders(); private:
@@ -35,6 +35,7 @@ void lockAspectRatio(bool lock) override;
void filter(bool filter) override; void framePosted(const uint32_t*) override; void setShaders(struct VDir*) override {} + void clearShaders() override {} protected: virtual void paintEvent(QPaintEvent*) override;
@@ -6,6 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ShaderSelector.h" #include "Display.h" +#include "GBAApp.h" +#include "VFileDevice.h" #include <QCheckBox> #include <QDoubleSpinBox>@@ -30,6 +32,9 @@ {
m_ui.setupUi(this); refreshShaders(); + + connect(m_ui.load, SIGNAL(clicked()), this, SLOT(selectShader())); + connect(m_ui.unload, SIGNAL(clicked()), this, SLOT(clearShader())); } ShaderSelector::~ShaderSelector() {@@ -47,15 +52,58 @@ delete page;
} } +void ShaderSelector::selectShader() { + QFileDialog *dialog = GBAApp::app()->getOpenFileDialog(nullptr, tr("Load shader"), tr("%1 Shader (%.shader)").arg(projectName)); + dialog->setFileMode(QFileDialog::Directory); + dialog->exec(); + QStringList names = dialog->selectedFiles(); + if (names.count() == 1) { + loadShader(names[0]); + } + delete dialog; + refreshShaders(); +} + +void ShaderSelector::loadShader(const QString& path) { + VDir* shader = VFileDevice::openDir(path); + if (!shader) { + shader = VFileDevice::openArchive(path); + } + if (!shader) { + return; + } + m_display->setShaders(shader); + shader->close(shader); + // TODO: Config +} + +void ShaderSelector::clearShader() { + m_display->clearShaders(); + refreshShaders(); + // TODO: Config +} + void ShaderSelector::refreshShaders() { clear(); m_shaders = m_display->shaders(); if (!m_shaders) { return; } - m_ui.shaderName->setText(m_shaders->name); - m_ui.description->setText(m_shaders->description); - m_ui.author->setText(tr("by %1").arg(m_shaders->author)); + if (m_shaders->name) { + m_ui.shaderName->setText(m_shaders->name); + } else { + m_ui.shaderName->setText(tr("No shader loaded")); + } + if (m_shaders->description) { + m_ui.description->setText(m_shaders->description); + } else { + m_ui.description->clear(); + } + if (m_shaders->author) { + m_ui.author->setText(tr("by %1").arg(m_shaders->author)); + } else { + m_ui.author->clear(); + } #if !defined(_WIN32) || defined(USE_EPOXY) GBAGLES2Shader* shaders = static_cast<GBAGLES2Shader*>(m_shaders->passes);@@ -124,6 +172,7 @@ f->setAccelerated(true);
settings->addWidget(f, y, x); connect(f, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [value](double v) { *value = v; + // TODO: Config }); }@@ -139,5 +188,6 @@ i->setAccelerated(true);
settings->addWidget(i, y, x); connect(i, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [value](int v) { *value = v; + // TODO: Config }); }
@@ -28,6 +28,11 @@ public slots:
void refreshShaders(); void clear(); +private slots: + void selectShader(); + void loadShader(const QString& path); + void clearShader(); + private: void addUniform(QGridLayout*, float* value, float min, float max, int y, int x); void addUniform(QGridLayout*, int* value, int min, int max, int y, int x);
@@ -6,8 +6,8 @@ <property name="geometry">
<rect> <x>0</x> <y>0</y> - <width>400</width> - <height>300</height> + <width>378</width> + <height>350</height> </rect> </property> <property name="windowTitle">@@ -32,7 +32,7 @@ </item>
<item> <widget class="QLabel" name="shaderName"> <property name="text"> - <string>TextLabel</string> + <string>Name</string> </property> <property name="alignment"> <set>Qt::AlignCenter</set>@@ -42,7 +42,7 @@ </item>
<item> <widget class="QLabel" name="author"> <property name="text"> - <string>TextLabel</string> + <string>Author</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>@@ -59,7 +59,7 @@ <italic>true</italic>
</font> </property> <property name="text"> - <string>TextLabel</string> + <string>Description</string> </property> <property name="wordWrap"> <bool>true</bool>@@ -79,6 +79,24 @@ <property name="currentIndex">
<number>-1</number> </property> </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="unload"> + <property name="text"> + <string>Unload Shader</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="load"> + <property name="text"> + <string>Load New Shader</string> + </property> + </widget> + </item> + </layout> </item> <item> <widget class="QDialogButtonBox" name="buttonBox">
@@ -26,6 +26,13 @@ qint64 VFileDevice::size() const {
return m_vf->size(m_vf); } -VFile* VFileDevice::open(QString path, int mode) { +VFile* VFileDevice::open(const QString& path, int mode) { return VFileOpen(path.toUtf8().constData(), mode); } + +VDir* VFileDevice::openDir(const QString& path) { + return VDirOpen(path.toUtf8().constData()); +} +VDir* VFileDevice::openArchive(const QString& path) { + return VDirOpenArchive(path.toUtf8().constData()); +}
@@ -20,7 +20,9 @@
public: VFileDevice(VFile* vf, QObject* parent = nullptr); - static VFile* open(QString path, int mode); + static VFile* open(const QString& path, int mode); + static VDir* openDir(const QString& path); + static VDir* openArchive(const QString& path); protected: virtual qint64 readData(char* data, qint64 maxSize) override;