diff --git a/src/config.c b/src/config.c index 46f935f7e..20981885a 100644 --- a/src/config.c +++ b/src/config.c @@ -1725,11 +1725,15 @@ load_gl3_shaders(void) ini_section_t cat = ini_find_section(config, "GL3 Shaders"); char *p; char temp[512]; - int i = 0; + int i = 0, shaders = 0; memset(temp, 0, sizeof(temp)); memset(gl3_shader_file, 0, sizeof(gl3_shader_file)); - for (int i = 0; i < MAX_USER_SHADERS; i++) { + shaders = ini_section_get_int(cat, "shaders", 0); + if (shaders > MAX_USER_SHADERS) + shaders = MAX_USER_SHADERS; + + for (int i = 0; i < shaders; i++) { temp[0] = 0; snprintf(temp, 512, "shader%d", i); p = ini_section_get_string(cat, temp, ""); @@ -2670,8 +2674,12 @@ save_gl3_shaders(void) int shaders = 0, i = 0; for (i = 0; i < MAX_USER_SHADERS; i++) { - if (gl3_shader_file[i][0] == 0) + if (gl3_shader_file[i][0] == 0) { + temp[0] = 0; + snprintf(temp, 512, "shader%d", i); + ini_section_delete_var(cat, temp); break; + } shaders++; } diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index 2ce89f788..3139f410e 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -31,6 +31,7 @@ typedef void *ini_section_t; extern ini_t ini_new(void); extern ini_t ini_read(const char *fn); +extern void ini_strip_quotes(ini_t ini); extern void ini_write(ini_t ini, const char *fn); extern void ini_dump(ini_t ini); extern void ini_close(ini_t ini); @@ -91,7 +92,7 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); -static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); } +static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); diff --git a/src/ini.c b/src/ini.c index 4ea6f6381..b4c905489 100644 --- a/src/ini.c +++ b/src/ini.c @@ -254,9 +254,8 @@ ini_delete_section_if_empty(ini_t ini, ini_section_t section) static section_t * create_section(list_t *head, const char *name) { - section_t *ns = malloc(sizeof(section_t)); + section_t *ns = calloc(1, sizeof(section_t)); - memset(ns, 0x00, sizeof(section_t)); memcpy(ns->name, name, strlen(name) + 1); list_add(&ns->list, head); @@ -279,9 +278,8 @@ ini_find_or_create_section(ini_t ini, const char *name) static entry_t * create_entry(section_t *section, const char *name) { - entry_t *ne = malloc(sizeof(entry_t)); + entry_t *ne = calloc(1, sizeof(entry_t)); - memset(ne, 0x00, sizeof(entry_t)); memcpy(ne->name, name, strlen(name) + 1); list_add(&ne->list, §ion->entry_head); @@ -390,11 +388,8 @@ ini_read(const char *fn) if (fp == NULL) return NULL; - head = malloc(sizeof(list_t)); - memset(head, 0x00, sizeof(list_t)); - - sec = malloc(sizeof(section_t)); - memset(sec, 0x00, sizeof(section_t)); + head = calloc(1, sizeof(list_t)); + sec = calloc(1, sizeof(section_t)); list_add(&sec->list, head); if (bom) @@ -475,7 +470,7 @@ ini_read(const char *fn) d = c; /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); + ne = calloc(1, sizeof(entry_t)); memset(ne, 0x00, sizeof(entry_t)); memcpy(ne->name, ename, 128); wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1); @@ -551,6 +546,43 @@ ini_write(ini_t ini, const char *fn) (void) fclose(fp); } +void +ini_strip_quotes(ini_t ini) +{ + list_t *list = (list_t *) ini; + section_t *sec; + + sec = (section_t *) list->next; + + while (sec != NULL) { + entry_t *ent; + + ent = (entry_t *) sec->entry_head.next; + while (ent != NULL) { + if (ent->name[0] != '\0') { + int i = 0; + if (ent->wdata[0] == L'\"') { + memmove(ent->wdata, &ent->wdata[1], sizeof(ent->wdata) - sizeof(wchar_t)); + } + if (ent->wdata[wcslen(ent->wdata) - 1] == L'\"') { + ent->wdata[wcslen(ent->wdata) - 1] = 0; + } + + if (ent->data[0] == '\"') { + memmove(ent->data, &ent->data[1], sizeof(ent->data) - sizeof(char)); + } + if (ent->data[strlen(ent->data) - 1] == '\"') { + ent->data[strlen(ent->data) - 1] = 0; + } + } + + ent = (entry_t *) ent->list.next; + } + + sec = (section_t *) sec->list.next; + } +} + ini_t ini_new(void) { diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 8a06cbe5a..574aae7b7 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -197,6 +197,7 @@ add_library(ui STATIC qt_openglshadermanagerdialog.hpp qt_openglshadermanagerdialog.cpp qt_openglshadermanagerdialog.ui + qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui ) if(RTMIDI) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index b1a96a312..f43897506 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -255,6 +255,8 @@ glslp_t *glslp_parse(const char *f) { safe_strncpy(s, t + j, sublen); s[511 < sublen ? 511 : sublen] = 0; + if (s[strlen(s) - 1] == ';') s[strlen(s) - 1] = 0; + struct texture *tex = &glslp->textures[glslp->num_textures++]; strcpy(tex->name, s); diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 60e0494fc..7e0cecdeb 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1982,6 +1982,12 @@ MainWindow::changeEvent(QEvent *event) } } +void +MainWindow::reloadAllRenderers() +{ + reload_renderers = true; +} + void MainWindow::on_actionRenderer_options_triggered() { @@ -2000,6 +2006,16 @@ MainWindow::on_actionRenderer_options_triggered() if (renderers[i] && renderers[i]->hasOptions()) renderers[i]->reloadOptions(); } + } else if (reload_renderers && ui->stackedWidget->reloadRendererOption()) { + reload_renderers = false; + ui->stackedWidget->switchRenderer(static_cast(vid_api)); + if (show_second_monitors) { + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) { + ui->stackedWidget->switchRenderer(static_cast(vid_api)); + } + } + } } } } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 25e33d77c..dced698bb 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -32,6 +32,7 @@ public: QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); void checkFullscreenHotkey(); + void reloadAllRenderers(); std::array, 8> renderers; signals: @@ -173,6 +174,9 @@ private: bool fs_on_signal = false; bool fs_off_signal = false; + /* Reload the renderers after closing renderer options dialog. */ + bool reload_renderers = false; + friend class SpecifyDimensions; friend class ProgSettings; friend class RendererCommon; diff --git a/src/qt/qt_openglshaderconfig.cpp b/src/qt/qt_openglshaderconfig.cpp new file mode 100644 index 000000000..25f9d38a8 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.cpp @@ -0,0 +1,85 @@ +#include "qt_openglshaderconfig.hpp" +#include "ui_qt_openglshaderconfig.h" + +#include "qt_mainwindow.hpp" + +extern MainWindow* main_window; + +extern "C" +{ +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/config.h> +} + +OpenGLShaderConfig::OpenGLShaderConfig(QWidget *parent, glslp_t* shader) + : QDialog(parent) + , ui(new Ui::OpenGLShaderConfig) +{ + ui->setupUi(this); + + currentShader = shader; + + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + glslp_read_shader_config(currentShader); + + for (int i = 0; i < currentShader->num_parameters; i++) { + auto spinBox = new QDoubleSpinBox; + spinBox->setObjectName(currentShader->parameters[i].id); + spinBox->setRange(currentShader->parameters[i].min, currentShader->parameters[i].max); + spinBox->setValue(currentShader->parameters[i].value); + spinBox->setSingleStep(currentShader->parameters[i].step); + QFormLayout* layout = (QFormLayout*)ui->scrollAreaWidgetContents->layout(); + layout->addRow(currentShader->parameters[i].description, spinBox); + } +} + +OpenGLShaderConfig::~OpenGLShaderConfig() +{ + delete ui; +} + +void OpenGLShaderConfig::on_buttonBox_clicked(QAbstractButton *button) +{ + if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) { + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + box->setValue(currentShader->parameters[i].default_value); + } + } + } else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { + startblit(); + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + float val = (float)box->value(); + currentShader->parameters[i].value = val; + } + } + glslp_write_shader_config(currentShader); + config_save(); + endblit(); + main_window->reloadAllRenderers(); + } +} + + +void OpenGLShaderConfig::on_OpenGLShaderConfig_accepted() +{ + startblit(); + for (int i = 0; i < currentShader->num_parameters; i++) { + QDoubleSpinBox* box = (QDoubleSpinBox*)this->findChild(QString(currentShader->parameters[i].id)); + if (box) { + float val = (float)box->value(); + currentShader->parameters[i].value = val; + } + } + glslp_write_shader_config(currentShader); + config_save(); + endblit(); + main_window->reloadAllRenderers(); +} + diff --git a/src/qt/qt_openglshaderconfig.hpp b/src/qt/qt_openglshaderconfig.hpp new file mode 100644 index 000000000..f71299d38 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.hpp @@ -0,0 +1,40 @@ +#ifndef QT_OPENGLSHADERCONFIG_HPP +#define QT_OPENGLSHADERCONFIG_HPP + +#include +#include +#include +#include + +#include +#include + +extern "C" +{ +#include <86box/qt-glslp-parser.h> +} + +namespace Ui { +class OpenGLShaderConfig; +} + +class OpenGLShaderConfig : public QDialog { + Q_OBJECT + +public: + explicit OpenGLShaderConfig(QWidget *parent = nullptr, glslp_t* shader = nullptr); + ~OpenGLShaderConfig(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + + void on_OpenGLShaderConfig_accepted(); + +private: + Ui::OpenGLShaderConfig *ui; + glslp_t* currentShader; + + std::map defaultValues; +}; + +#endif // QT_OPENGLSHADERCONFIG_HPP diff --git a/src/qt/qt_openglshaderconfig.ui b/src/qt/qt_openglshaderconfig.ui new file mode 100644 index 000000000..1aebdb6f6 --- /dev/null +++ b/src/qt/qt_openglshaderconfig.ui @@ -0,0 +1,92 @@ + + + OpenGLShaderConfig + + + + 0 + 0 + 400 + 300 + + + + Shader Configuration + + + + QLayout::SizeConstraint::SetMinAndMaxSize + + + + + true + + + + + 0 + 0 + 380 + 250 + + + + + QLayout::SizeConstraint::SetMaximumSize + + + QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow + + + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset + + + + + + + + + buttonBox + accepted() + OpenGLShaderConfig + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + OpenGLShaderConfig + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qt_openglshadermanagerdialog.cpp b/src/qt/qt_openglshadermanagerdialog.cpp index 26f206a0e..08cf94fd7 100644 --- a/src/qt/qt_openglshadermanagerdialog.cpp +++ b/src/qt/qt_openglshadermanagerdialog.cpp @@ -1,6 +1,8 @@ #include "qt_openglshadermanagerdialog.hpp" #include "ui_qt_openglshadermanagerdialog.h" +#include "qt_openglshaderconfig.hpp" + #include #include #include @@ -39,10 +41,21 @@ OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent) } if (ui->shaderListWidget->count()) { ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1); + auto current = ui->shaderListWidget->currentItem(); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + else + ui->buttonConfigure->setEnabled(false); + } else { + ui->buttonConfigure->setEnabled(false); + } } else { ui->buttonRemove->setDisabled(true); ui->buttonMoveUp->setDisabled(true); ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); } } @@ -84,9 +97,16 @@ void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidg ui->buttonRemove->setDisabled(true); ui->buttonMoveUp->setDisabled(true); ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); return; } else { ui->buttonRemove->setDisabled(false); + ui->buttonConfigure->setDisabled(true); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + } } ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); @@ -95,6 +115,22 @@ void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidg void OpenGLShaderManagerDialog::on_shaderListWidget_currentRowChanged(int currentRow) { + auto current = ui->shaderListWidget->currentItem(); + if (current == nullptr) { + ui->buttonRemove->setDisabled(true); + ui->buttonMoveUp->setDisabled(true); + ui->buttonMoveDown->setDisabled(true); + ui->buttonConfigure->setDisabled(true); + return; + } else { + ui->buttonRemove->setDisabled(false); + ui->buttonConfigure->setDisabled(true); + if (current) { + glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong(); + if (shader->num_parameters > 0) + ui->buttonConfigure->setEnabled(true); + } + } ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0); ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1)); } @@ -143,6 +179,8 @@ void OpenGLShaderManagerDialog::on_buttonRemove_clicked() glslp_free((glslp_t*)item->data(Qt::UserRole + 2).toULongLong()); } delete item; + + on_shaderListWidget_currentRowChanged(ui->shaderListWidget->currentRow()); } } @@ -157,3 +195,15 @@ void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted() endblit(); } + +void OpenGLShaderManagerDialog::on_buttonConfigure_clicked() +{ + auto item = ui->shaderListWidget->currentItem(); + if (item) { + glslp_t* shader = (glslp_t*)item->data(Qt::UserRole + 2).toULongLong(); + + auto configDialog = new OpenGLShaderConfig(this, shader); + configDialog->exec(); + } +} + diff --git a/src/qt/qt_openglshadermanagerdialog.hpp b/src/qt/qt_openglshadermanagerdialog.hpp index bac0205cf..b8885e3a3 100644 --- a/src/qt/qt_openglshadermanagerdialog.hpp +++ b/src/qt/qt_openglshadermanagerdialog.hpp @@ -33,6 +33,8 @@ private slots: void on_OpenGLShaderManagerDialog_accepted(); + void on_buttonConfigure_clicked(); + private: Ui::OpenGLShaderManagerDialog *ui; }; diff --git a/src/qt/qt_openglshadermanagerdialog.ui b/src/qt/qt_openglshadermanagerdialog.ui index 2888e106f..f68827436 100644 --- a/src/qt/qt_openglshadermanagerdialog.ui +++ b/src/qt/qt_openglshadermanagerdialog.ui @@ -11,7 +11,7 @@ - Dialog + Shader Manager @@ -59,7 +59,7 @@ - false + true Configure