From 572c1ea2d309ede4e0b754db520a43a1dcfc7ef5 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 00:47:10 -0400 Subject: [PATCH 1/6] Qt: initial shader parameter support --- intl/msg_hash_ja.h | 2 + intl/msg_hash_us.h | 2 + msg_hash.h | 1 + ui/drivers/qt/ui_qt_window.cpp | 243 +++++++++++++++++++++++++++++++++ ui/drivers/ui_qt.cpp | 2 + ui/drivers/ui_qt.h | 8 ++ 6 files changed, 258 insertions(+) diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index 6612b1adba..73b6cf9f35 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -3500,6 +3500,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW, "表示(&V)") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_CLOSED_DOCKS, "閉じたドック") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS, + "シェーダーのパラメータ") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS, "設定(&O)...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 3eb0d97ea1..0590f8d60d 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3756,6 +3756,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW, "&View") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_CLOSED_DOCKS, "Closed Docks") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS, + "Shader Parameters") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS, "&Options...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS, diff --git a/msg_hash.h b/msg_hash.h index 8c75461637..1a6f5c78f0 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1886,6 +1886,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW, MENU_ENUM_LABEL_VALUE_QT_MENU_SEARCH_CLEAR, MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_CLOSED_DOCKS, + MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS, MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS, MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS, MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_GEOMETRY, diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index d8c8d40ad3..5ef4ed8e18 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "../ui_qt.h" #include "ui_qt_load_core_window.h" @@ -927,6 +928,7 @@ MainWindow::MainWindow(QWidget *parent) : ,m_allPlaylistsGridMaxCount(0) ,m_playlistEntryDialog(NULL) ,m_statusMessageElapsedTimer() + ,m_shaderParamsDialog(NULL) ,m_networkManager(new QNetworkAccessManager(this)) ,m_updateProgressDialog(new QProgressDialog()) ,m_updateFile() @@ -1214,6 +1216,247 @@ void MainWindow::removeUpdateTempFiles() } } +void MainWindow::onShaderParamsClicked() +{ + QFormLayout *form = new QFormLayout(); + video_shader_ctx_t shader_info; + unsigned i; + + video_shader_driver_get_current_shader(&shader_info); + + if (!shader_info.data || shader_info.data->num_parameters > GFX_MAX_PARAMETERS) + return; + + /* shader might have changed, so re-create the entire window */ + if (m_shaderParamsDialog) + delete m_shaderParamsDialog; + + m_shaderParamsDialog = new QDialog(); + m_shaderParamsDialog->setLayout(form); + m_shaderParamsDialog->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS)); + + for (i = 0; i < shader_info.data->num_parameters; i++) + { + struct video_shader_parameter *param = &shader_info.data->parameters[i]; + QString desc = param->desc; + + if ((param->minimum == 0.0) + && (param->maximum + == (param->minimum + + param->step))) + { + /* option is basically a bool, so use a checkbox */ + QCheckBox *checkBox = new QCheckBox(m_shaderParamsDialog); + checkBox->setChecked(param->current == param->maximum ? true : false); + checkBox->setProperty("param", QVariant::fromValue(param)); + + connect(checkBox, SIGNAL(clicked()), this, SLOT(onShaderParamCheckBoxClicked())); + + form->addRow(desc, checkBox); + } + else + { + QDoubleSpinBox *doubleSpinBox = NULL; + QSpinBox *spinBox = NULL; + QHBoxLayout *box = new QHBoxLayout(); + QSlider *slider = new QSlider(Qt::Horizontal, m_shaderParamsDialog); + double value = lerp(param->minimum, param->maximum, 0, 100, param->current); + double intpart = 0; + bool stepIsFractional = modf(param->step, &intpart); + + slider->setRange(0, 100); + slider->setSingleStep(1); + slider->setValue(value); + slider->setProperty("param", QVariant::fromValue(param)); + + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int))); + + box->addWidget(slider); + + if (stepIsFractional) + { + doubleSpinBox = new QDoubleSpinBox(m_shaderParamsDialog); + doubleSpinBox->setRange(param->minimum, param->maximum); + doubleSpinBox->setSingleStep(param->step); + doubleSpinBox->setValue(param->current); + doubleSpinBox->setProperty("slider", QVariant::fromValue(slider)); + slider->setProperty("doubleSpinBox", QVariant::fromValue(doubleSpinBox)); + + connect(doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onShaderParamDoubleSpinBoxValueChanged(double))); + + box->addWidget(doubleSpinBox); + } + else + { + spinBox = new QSpinBox(m_shaderParamsDialog); + spinBox->setRange(param->minimum, param->maximum); + spinBox->setSingleStep(param->step); + spinBox->setValue(param->current); + spinBox->setProperty("slider", QVariant::fromValue(slider)); + slider->setProperty("spinBox", QVariant::fromValue(spinBox)); + + connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSpinBoxValueChanged(int))); + + box->addWidget(spinBox); + } + + form->addRow(desc, box); + } + } + + m_shaderParamsDialog->resize(720, 480); + m_shaderParamsDialog->show(); +} + +void MainWindow::onShaderParamCheckBoxClicked() +{ + QCheckBox *checkBox = qobject_cast(sender()); + QVariant paramVariant; + struct video_shader_parameter *param = NULL; + + if (!checkBox) + return; + + paramVariant = checkBox->property("param"); + + if (paramVariant.isValid()) + { + param = paramVariant.value(); + + if (param) + param->current = (checkBox->isChecked() ? param->maximum : param->minimum); + } +} + +void MainWindow::onShaderParamSliderValueChanged(int value) +{ + QVariant spinBoxVariant; + QVariant paramVariant; + QSlider *slider = qobject_cast(sender()); + struct video_shader_parameter *param = NULL; + double newValue = 0.0; + + if (!slider) + return; + + spinBoxVariant = slider->property("spinBox"); + + if (spinBoxVariant.isValid()) + { + QSpinBox *spinBox = spinBoxVariant.value(); + + if (!spinBox) + return; + + spinBox->blockSignals(true); + spinBox->setValue(slider->value()); + spinBox->blockSignals(false); + } + else + { + QVariant doubleSpinBoxVariant = slider->property("doubleSpinBox"); + QDoubleSpinBox *doubleSpinBox = doubleSpinBoxVariant.value(); + + if (!doubleSpinBox) + return; + + doubleSpinBox->blockSignals(true); + doubleSpinBox->setValue(slider->value()); + doubleSpinBox->blockSignals(false); + } + + paramVariant = slider->property("param"); + + if (paramVariant.isValid()) + { + param = paramVariant.value(); + + if (param) + { + newValue = lerp(0, 100, param->minimum, param->maximum, slider->value()); + param->current = newValue; + } + } +} + +void MainWindow::onShaderParamSpinBoxValueChanged(int value) +{ + QSpinBox *spinBox = qobject_cast(sender()); + QVariant sliderVariant; + QVariant paramVariant; + QSlider *slider = NULL; + struct video_shader_parameter *param = NULL; + double newValue = 0.0; + + if (!spinBox) + return; + + sliderVariant = spinBox->property("slider"); + + if (!sliderVariant.isValid()) + return; + + slider = sliderVariant.value(); + + if (!slider) + return; + + paramVariant = slider->property("param"); + + if (paramVariant.isValid()) + { + param = paramVariant.value(); + + if (param) + { + param->current = value; + newValue = lerp(param->minimum, param->maximum, 0, 100, param->current); + slider->blockSignals(true); + slider->setValue(newValue); + slider->blockSignals(false); + } + } +} + +void MainWindow::onShaderParamDoubleSpinBoxValueChanged(double value) +{ + QDoubleSpinBox *doubleSpinBox = qobject_cast(sender()); + QVariant sliderVariant; + QVariant paramVariant; + QSlider *slider = NULL; + struct video_shader_parameter *param = NULL; + double newValue = 0.0; + + if (!doubleSpinBox) + return; + + sliderVariant = doubleSpinBox->property("slider"); + + if (!sliderVariant.isValid()) + return; + + slider = sliderVariant.value(); + + if (!slider) + return; + + paramVariant = slider->property("param"); + + if (paramVariant.isValid()) + { + param = paramVariant.value(); + + if (param) + { + param->current = value; + newValue = lerp(param->minimum, param->maximum, 0, 100, param->current); + slider->blockSignals(true); + slider->setValue(newValue); + slider->blockSignals(false); + } + } +} + void MainWindow::onPlaylistFilesDropped(QStringList files) { addFilesToPlaylist(files); diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index 690635a4aa..7fcace03e0 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -321,6 +321,8 @@ static void* ui_companion_qt_init(void) QObject::connect(viewClosedDocksMenu, SIGNAL(aboutToShow()), mainwindow, SLOT(onViewClosedDocksAboutToShow())); + viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS), mainwindow, SLOT(onShaderParamsClicked())); + viewMenu->addSeparator(); viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS), mainwindow, SLOT(onIconViewClicked())); viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_LIST), mainwindow, SLOT(onListViewClicked())); diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 628ae62d31..50943d2a6c 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -42,6 +42,7 @@ extern "C" { #include #include #include "../ui_companion_driver.h" +#include "../../gfx/video_driver.h" } class QApplication; @@ -433,6 +434,7 @@ private slots: void onGridItemDoubleClicked(); void onGridItemClicked(ThumbnailWidget *thumbnailWidget = NULL); void onPlaylistFilesDropped(QStringList files); + void onShaderParamsClicked(); void onUpdateNetworkError(QNetworkReply::NetworkError code); void onUpdateNetworkSslErrors(const QList &errors); void onRetroArchUpdateDownloadFinished(); @@ -441,6 +443,10 @@ private slots: void onUpdateDownloadCanceled(); void onShowErrorMessage(QString msg); void onContributorsClicked(); + void onShaderParamCheckBoxClicked(); + void onShaderParamSliderValueChanged(int value); + void onShaderParamSpinBoxValueChanged(int value); + void onShaderParamDoubleSpinBoxValueChanged(double value); int onExtractArchive(QString path); private: @@ -514,6 +520,7 @@ private: int m_allPlaylistsGridMaxCount; PlaylistEntryDialog *m_playlistEntryDialog; QElapsedTimer m_statusMessageElapsedTimer; + QDialog *m_shaderParamsDialog; QNetworkAccessManager *m_networkManager; QProgressDialog *m_updateProgressDialog; QFile m_updateFile; @@ -526,6 +533,7 @@ protected: Q_DECLARE_METATYPE(ThumbnailWidget) Q_DECLARE_METATYPE(QPointer) +Q_DECLARE_METATYPE(struct video_shader_parameter*) RETRO_BEGIN_DECLS From 6de438435054635220f82e2fd2cec1c4c8536f9e Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 18:42:23 -0400 Subject: [PATCH 2/6] glsl: don't clear the shader source --- gfx/drivers_shader/shader_glsl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gfx/drivers_shader/shader_glsl.c b/gfx/drivers_shader/shader_glsl.c index 8d8dbb4590..784cf41c7f 100644 --- a/gfx/drivers_shader/shader_glsl.c +++ b/gfx/drivers_shader/shader_glsl.c @@ -539,8 +539,6 @@ static bool gl_glsl_compile_programs( return false; } - *pass->source.path = '\0'; - vertex = pass->source.string.vertex; fragment = pass->source.string.fragment; From 4a86d298105542e540b55c8b7ecf05c7077ccdeb Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 18:44:19 -0400 Subject: [PATCH 3/6] shaders: fix memory leak --- gfx/video_shader_parse.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 00d96ece1d..36d0460180 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -155,6 +155,7 @@ static bool video_shader_parse_pass(config_file_t *conf, strlcpy(pass->source.path, tmp_str, sizeof(pass->source.path)); else strlcpy(pass->source.path, tmp_path, sizeof(pass->source.path)); + free(tmp_path); /* Smooth */ @@ -208,7 +209,10 @@ static bool video_shader_parse_pass(config_file_t *conf, config_get_array(conf, scale_name_buf, scale_type_y, sizeof(scale_type_y)); if (!*scale_type && !*scale_type_x && !*scale_type_y) + { + free(tmp_str); return true; + } if (*scale_type) { @@ -253,6 +257,7 @@ static bool video_shader_parse_pass(config_file_t *conf, } snprintf(attr_name_buf, sizeof(attr_name_buf), "scale%u", i); + if (scale->type_x == RARCH_SCALE_ABSOLUTE) { if (config_get_int(conf, attr_name_buf, &iattr)) @@ -277,6 +282,7 @@ static bool video_shader_parse_pass(config_file_t *conf, } snprintf(attr_name_buf, sizeof(attr_name_buf), "scale%u", i); + if (scale->type_y == RARCH_SCALE_ABSOLUTE) { if (config_get_int(conf, attr_name_buf, &iattr)) @@ -500,9 +506,9 @@ bool video_shader_resolve_parameters(config_file_t *conf, continue; #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) - /* First try to use the more robust slang + /* First try to use the more robust slang * implementation to support #includes. */ - /* FIXME: The check for slang can be removed + /* FIXME: The check for slang can be removed * if it's sufficiently tested for * GLSL/Cg as well, it should be the same implementation. */ if (string_is_equal(path_get_extension(path), "slang") && @@ -632,7 +638,7 @@ static bool video_shader_parse_imports(config_file_t *conf, var->type = RARCH_STATE_TRANSITION_PREV; else if (string_is_equal(semantic, "python")) var->type = RARCH_STATE_PYTHON; - else + else { RARCH_ERR("Invalid semantic.\n"); goto error; @@ -752,11 +758,14 @@ bool video_shader_read_conf_cgp(config_file_t *conf, if (!video_shader_parse_pass(conf, &shader->pass[i], i)) { if (file_list) + { string_list_free(file_list); + file_list = NULL; + } return false; } - if (settings->bools.video_shader_watch_files) + if (settings->bools.video_shader_watch_files && file_list) string_list_append(file_list, shader->pass[i].source.path, attr); } @@ -770,7 +779,8 @@ bool video_shader_read_conf_cgp(config_file_t *conf, frontend_driver_watch_path_for_changes(file_list, flags, &file_change_data); - string_list_free(file_list); + if (file_list) + string_list_free(file_list); } if (!video_shader_parse_textures(conf, shader)) @@ -1130,7 +1140,7 @@ enum rarch_shader_type video_shader_get_type_from_ext( case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: { - struct retro_hw_render_callback *hwr = + struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); if (hwr) { @@ -1162,7 +1172,7 @@ enum rarch_shader_type video_shader_get_type_from_ext( case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: { - struct retro_hw_render_callback *hwr = + struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); if (hwr) { @@ -1227,7 +1237,7 @@ enum rarch_shader_type video_shader_get_type_from_ext( } } if ( - string_is_equal_case_insensitive(ext, "slangp") + string_is_equal_case_insensitive(ext, "slangp") ) { *is_preset = true; From 560149857b78d56094efeb8fb6f9363e2fb8ccce Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 18:46:32 -0400 Subject: [PATCH 4/6] shaders: track the pass for each parameter --- gfx/video_shader_parse.c | 6 ++++-- gfx/video_shader_parse.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 36d0460180..001f8ba055 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -545,9 +545,11 @@ bool video_shader_resolve_parameters(config_file_t *conf, if (ret == 5) param->step = 0.1f * (param->maximum - param->minimum); - RARCH_LOG("Found #pragma parameter %s (%s) %f %f %f %f\n", + param->pass = i; + + RARCH_LOG("Found #pragma parameter %s (%s) %f %f %f %f in pass %d\n", param->desc, param->id, param->initial, - param->minimum, param->maximum, param->step); + param->minimum, param->maximum, param->step, param->pass); param->current = param->initial; shader->num_parameters++; diff --git a/gfx/video_shader_parse.h b/gfx/video_shader_parse.h index cb76a23a85..744c7c9ab2 100644 --- a/gfx/video_shader_parse.h +++ b/gfx/video_shader_parse.h @@ -105,6 +105,7 @@ struct video_shader_parameter float initial; float maximum; float step; + int pass; }; struct video_shader_pass From 553394c266322e19c17f2a59785eb9b55ccb109e Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 21:38:45 -0400 Subject: [PATCH 5/6] Qt: fix setting of spinbox values when modifying shader parameter sliders --- ui/drivers/qt/ui_qt_window.cpp | 49 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 5ef4ed8e18..0cd1a7b4ce 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -1340,31 +1340,6 @@ void MainWindow::onShaderParamSliderValueChanged(int value) return; spinBoxVariant = slider->property("spinBox"); - - if (spinBoxVariant.isValid()) - { - QSpinBox *spinBox = spinBoxVariant.value(); - - if (!spinBox) - return; - - spinBox->blockSignals(true); - spinBox->setValue(slider->value()); - spinBox->blockSignals(false); - } - else - { - QVariant doubleSpinBoxVariant = slider->property("doubleSpinBox"); - QDoubleSpinBox *doubleSpinBox = doubleSpinBoxVariant.value(); - - if (!doubleSpinBox) - return; - - doubleSpinBox->blockSignals(true); - doubleSpinBox->setValue(slider->value()); - doubleSpinBox->blockSignals(false); - } - paramVariant = slider->property("param"); if (paramVariant.isValid()) @@ -1377,6 +1352,30 @@ void MainWindow::onShaderParamSliderValueChanged(int value) param->current = newValue; } } + + if (spinBoxVariant.isValid()) + { + QSpinBox *spinBox = spinBoxVariant.value(); + + if (!spinBox) + return; + + spinBox->blockSignals(true); + spinBox->setValue(newValue); + spinBox->blockSignals(false); + } + else + { + QVariant doubleSpinBoxVariant = slider->property("doubleSpinBox"); + QDoubleSpinBox *doubleSpinBox = doubleSpinBoxVariant.value(); + + if (!doubleSpinBox) + return; + + doubleSpinBox->blockSignals(true); + doubleSpinBox->setValue(newValue); + doubleSpinBox->blockSignals(false); + } } void MainWindow::onShaderParamSpinBoxValueChanged(int value) From 341cf633997ee2c7827d2d0f144ce1f29171dbcb Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 14 Aug 2018 21:38:52 -0400 Subject: [PATCH 6/6] Qt: show shader pass in parameters window, reload shader params when shader is reloaded --- command.c | 8 +- command.h | 2 + gfx/video_driver.c | 45 +++++---- gfx/video_shader_parse.c | 3 + griffin/griffin_cpp.cpp | 1 + ui/drivers/qt/ui_qt_window.cpp | 180 ++++++++++++++++++++++----------- ui/drivers/ui_qt.cpp | 16 ++- ui/drivers/ui_qt.h | 17 +++- ui/ui_companion_driver.c | 4 + 9 files changed, 192 insertions(+), 84 deletions(-) diff --git a/command.c b/command.c index 18ca322b53..4ccc4f5f6f 100644 --- a/command.c +++ b/command.c @@ -1336,8 +1336,8 @@ static void command_event_restore_default_shader_preset(void) static void command_event_restore_remaps(void) { - if (rarch_ctl(RARCH_CTL_IS_REMAPS_CORE_ACTIVE, NULL) || - rarch_ctl(RARCH_CTL_IS_REMAPS_CONTENT_DIR_ACTIVE, NULL) || + if (rarch_ctl(RARCH_CTL_IS_REMAPS_CORE_ACTIVE, NULL) || + rarch_ctl(RARCH_CTL_IS_REMAPS_CONTENT_DIR_ACTIVE, NULL) || rarch_ctl(RARCH_CTL_IS_REMAPS_GAME_ACTIVE, NULL)) input_remapping_set_defaults(true); } @@ -2441,10 +2441,14 @@ TODO: Add a setting for these tweaks */ if (!command_event_save_core_config()) return false; break; + case CMD_EVENT_SHADER_PRESET_LOADED: + ui_companion_event_command(cmd); + break; case CMD_EVENT_SHADERS_APPLY_CHANGES: #ifdef HAVE_MENU menu_shader_manager_apply_changes(); #endif + ui_companion_event_command(cmd); break; case CMD_EVENT_PAUSE_CHECKS: { diff --git a/command.h b/command.h index 6b50d6f3eb..1a7e84fac7 100644 --- a/command.h +++ b/command.h @@ -158,6 +158,8 @@ enum event_command CMD_EVENT_MENU_REFRESH, /* Applies shader changes. */ CMD_EVENT_SHADERS_APPLY_CHANGES, + /* A new shader preset has been loaded */ + CMD_EVENT_SHADER_PRESET_LOADED, /* Initializes shader directory. */ CMD_EVENT_SHADER_DIR_INIT, /* Deinitializes shader directory. */ diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 3a38c46eed..3fa843eefa 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -1641,7 +1641,7 @@ bool video_driver_is_stub_frame(void) bool video_driver_supports_recording(void) { settings_t *settings = config_get_ptr(); - return settings->bools.video_gpu_record + return settings->bools.video_gpu_record && current_video->read_viewport; } @@ -1668,7 +1668,7 @@ void video_driver_set_viewport_config(void) { struct retro_game_geometry *geom = &video_driver_av_info.geometry; - if (geom->aspect_ratio > 0.0f && + if (geom->aspect_ratio > 0.0f && settings->bools.video_aspect_ratio_auto) aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio; else @@ -1898,7 +1898,7 @@ void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bo } else if (device_aspect > desired_aspect) { - delta = (desired_aspect / device_aspect - 1.0f) + delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; vp->x = (int)roundf(vp->full_width * (0.5f - delta)); vp->width = (unsigned)roundf(2.0f * vp->full_width * delta); @@ -1909,7 +1909,7 @@ void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bo { vp->x = 0; vp->width = vp->full_width; - delta = (device_aspect / desired_aspect - 1.0f) + delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; vp->y = (int)roundf(vp->full_height * (0.5f - delta)); vp->height = (unsigned)roundf(2.0f * vp->full_height * delta); @@ -2324,7 +2324,7 @@ void video_viewport_get_scaled_integer(struct video_viewport *vp, unsigned base_width; /* Use system reported sizes as these define the * geometry for the "normal" case. */ - unsigned base_height = + unsigned base_height = video_driver_av_info.geometry.base_height; if (base_height == 0) @@ -2631,9 +2631,9 @@ void video_driver_frame(const void *data, unsigned width, /* Display the FPS, with a higher priority. */ if (video_info.fps_show) runloop_msg_queue_push(video_info.fps_text, 2, 1, true); - - /* trigger set resolution*/ - if (video_info.crt_switch_resolution) + + /* trigger set resolution*/ + if (video_info.crt_switch_resolution) { video_driver_crt_switching_active = true; @@ -2646,9 +2646,9 @@ void video_driver_frame(const void *data, unsigned width, crt_switch_res_core(width, height, video_driver_core_hz); } else if (!video_info.crt_switch_resolution) - video_driver_crt_switching_active = false; - - /* trigger set resolution*/ + video_driver_crt_switching_active = false; + + /* trigger set resolution*/ } void video_driver_display_type_set(enum rarch_display_type type) @@ -2741,8 +2741,8 @@ void video_driver_build_info(video_frame_info_t *video_info) settings = config_get_ptr(); custom_vp = &settings->video_viewport_custom; video_info->refresh_rate = settings->floats.video_refresh_rate; - video_info->crt_switch_resolution = settings->bools.crt_switch_resolution; - video_info->crt_switch_resolution_super = settings->uints.crt_switch_resolution_super; + video_info->crt_switch_resolution = settings->bools.crt_switch_resolution; + video_info->crt_switch_resolution_super = settings->uints.crt_switch_resolution_super; video_info->black_frame_insertion = settings->bools.video_black_frame_insertion; video_info->hard_sync = settings->bools.video_hard_sync; video_info->hard_sync_frames = settings->uints.video_hard_sync_frames; @@ -2873,13 +2873,13 @@ bool video_driver_translate_coord_viewport( return false; if (mouse_x >= 0 && mouse_x <= norm_full_vp_width) - scaled_screen_x = ((2 * mouse_x * 0x7fff) + scaled_screen_x = ((2 * mouse_x * 0x7fff) / norm_full_vp_width) - 0x7fff; else scaled_screen_x = -0x8000; /* OOB */ if (mouse_y >= 0 && mouse_y <= norm_full_vp_height) - scaled_screen_y = ((2 * mouse_y * 0x7fff) + scaled_screen_y = ((2 * mouse_y * 0x7fff) / norm_full_vp_height) - 0x7fff; else scaled_screen_y = -0x8000; /* OOB */ @@ -2888,13 +2888,13 @@ bool video_driver_translate_coord_viewport( mouse_y -= vp->y; if (mouse_x >= 0 && mouse_x <= norm_vp_width) - scaled_x = ((2 * mouse_x * 0x7fff) + scaled_x = ((2 * mouse_x * 0x7fff) / norm_vp_width) - 0x7fff; else scaled_x = -0x8000; /* OOB */ if (mouse_y >= 0 && mouse_y <= norm_vp_height) - scaled_y = ((2 * mouse_y * 0x7fff) + scaled_y = ((2 * mouse_y * 0x7fff) / norm_vp_height) - 0x7fff; else scaled_y = -0x8000; /* OOB */ @@ -2920,7 +2920,7 @@ void video_driver_get_status(uint64_t *frame_count, bool * is_alive, bool *is_focused) { *frame_count = video_driver_frame_count; - *is_alive = current_video ? + *is_alive = current_video ? current_video->alive(video_driver_data) : true; *is_focused = video_driver_cb_has_focus(); } @@ -3002,7 +3002,7 @@ bool video_context_driver_find_next_driver(void) * * Initialize graphics context driver. * - * Returns: graphics context driver if successfully initialized, + * Returns: graphics context driver if successfully initialized, * otherwise NULL. **/ static const gfx_ctx_driver_t *video_context_driver_init( @@ -3238,7 +3238,7 @@ bool video_context_driver_get_refresh_rate(float *refresh_rate) return false; if (refresh_rate) - *refresh_rate = + *refresh_rate = current_video_context.get_refresh_rate(video_context_data); return true; @@ -3247,7 +3247,7 @@ bool video_context_driver_get_refresh_rate(float *refresh_rate) bool video_context_driver_input_driver(gfx_ctx_input_t *inp) { settings_t *settings = config_get_ptr(); - const char *joypad_name = settings ? + const char *joypad_name = settings ? settings->arrays.input_joypad_driver : NULL; if (!current_video_context.input_driver) @@ -3518,6 +3518,9 @@ bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader) bool video_shader_driver_direct_get_current_shader( video_shader_ctx_t *shader) { + if (!current_shader) + return false; + shader->data = current_shader->get_current_shader(current_shader_data); return true; diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 001f8ba055..005a9d64fb 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -35,6 +35,7 @@ #include "../verbosity.h" #include "../configuration.h" #include "../frontend/frontend_driver.h" +#include "../command.h" #include "video_driver.h" #include "video_shader_parse.h" @@ -785,6 +786,8 @@ bool video_shader_read_conf_cgp(config_file_t *conf, string_list_free(file_list); } + command_event(CMD_EVENT_SHADER_PRESET_LOADED, NULL); + if (!video_shader_parse_textures(conf, shader)) return false; diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index 970ac5cffe..17aae41d3d 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -41,6 +41,7 @@ UI #include "../ui/drivers/qt/ui_qt_browser_window.cpp" #include "../ui/drivers/qt/ui_qt_msg_window.cpp" #include "../ui/drivers/qt/ui_qt_application.cpp" +#include "../ui/drivers/qt/flowlayout.cpp" #endif /*============================================================ diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index 0cd1a7b4ce..6c2b63156a 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -203,6 +203,22 @@ static void setElidedText(QLabel *label, QWidget *clipWidget, int padding, const const QPixmap getInvader(); +ShaderParamsDialog::ShaderParamsDialog(QWidget *parent) : + QDialog(parent) +{ +} + +ShaderParamsDialog::~ShaderParamsDialog() +{ +} + +void ShaderParamsDialog::closeEvent(QCloseEvent *event) +{ + QDialog::closeEvent(event); + + emit closed(); +} + GridItem::GridItem() : QObject() ,widget(NULL) @@ -928,7 +944,7 @@ MainWindow::MainWindow(QWidget *parent) : ,m_allPlaylistsGridMaxCount(0) ,m_playlistEntryDialog(NULL) ,m_statusMessageElapsedTimer() - ,m_shaderParamsDialog(NULL) + ,m_shaderParamsDialog() ,m_networkManager(new QNetworkAccessManager(this)) ,m_updateProgressDialog(new QProgressDialog()) ,m_updateFile() @@ -1152,7 +1168,10 @@ MainWindow::MainWindow(QWidget *parent) : /* make sure these use an auto connection so it will be queued if called from a different thread (some facilities in RA log messages from other threads) */ connect(this, SIGNAL(gotLogMessage(const QString&)), this, SLOT(onGotLogMessage(const QString&)), Qt::AutoConnection); connect(this, SIGNAL(gotStatusMessage(QString,unsigned,unsigned,bool)), this, SLOT(onGotStatusMessage(QString,unsigned,unsigned,bool)), Qt::AutoConnection); - connect(this, SIGNAL(gotReloadPlaylists()), this, SLOT(onGotReloadPlaylists())); + connect(this, SIGNAL(gotReloadPlaylists()), this, SLOT(onGotReloadPlaylists()), Qt::AutoConnection); + connect(this, SIGNAL(gotReloadShaderParams()), this, SLOT(onGotReloadShaderParams()), Qt::AutoConnection); + + /* these are always queued */ connect(this, SIGNAL(showErrorMessageDeferred(QString)), this, SLOT(onShowErrorMessage(QString)), Qt::QueuedConnection); connect(this, SIGNAL(extractArchiveDeferred(QString)), this, SLOT(onExtractArchive(QString)), Qt::QueuedConnection); @@ -1218,9 +1237,11 @@ void MainWindow::removeUpdateTempFiles() void MainWindow::onShaderParamsClicked() { - QFormLayout *form = new QFormLayout(); video_shader_ctx_t shader_info; unsigned i; + int last_pass = -1; + QFormLayout *last_form = NULL; + QGroupBox *last_group = NULL; video_shader_driver_get_current_shader(&shader_info); @@ -1231,77 +1252,109 @@ void MainWindow::onShaderParamsClicked() if (m_shaderParamsDialog) delete m_shaderParamsDialog; - m_shaderParamsDialog = new QDialog(); - m_shaderParamsDialog->setLayout(form); + m_shaderParamsDialog = new ShaderParamsDialog(); + m_shaderParamsDialog->setLayout(new QVBoxLayout()); m_shaderParamsDialog->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS)); - for (i = 0; i < shader_info.data->num_parameters; i++) + connect(m_shaderParamsDialog, SIGNAL(closed()), m_shaderParamsDialog, SLOT(deleteLater())); + + if (shader_info.data->num_parameters == 0) { - struct video_shader_parameter *param = &shader_info.data->parameters[i]; - QString desc = param->desc; + QLabel *label = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS), m_shaderParamsDialog); + label->setAlignment(Qt::AlignCenter); - if ((param->minimum == 0.0) - && (param->maximum - == (param->minimum - + param->step))) + m_shaderParamsDialog->layout()->addWidget(label); + } + else + { + /* NOTE: We assume that parameters are always grouped in order by the pass number, e.g., all parameters for pass 0 come first, then params for pass 1, etc. */ + for (i = 0; i < shader_info.data->num_parameters; i++) { - /* option is basically a bool, so use a checkbox */ - QCheckBox *checkBox = new QCheckBox(m_shaderParamsDialog); - checkBox->setChecked(param->current == param->maximum ? true : false); - checkBox->setProperty("param", QVariant::fromValue(param)); + struct video_shader_parameter *param = &shader_info.data->parameters[i]; + QString desc = param->desc; + QFormLayout *form = last_form; - connect(checkBox, SIGNAL(clicked()), this, SLOT(onShaderParamCheckBoxClicked())); - - form->addRow(desc, checkBox); - } - else - { - QDoubleSpinBox *doubleSpinBox = NULL; - QSpinBox *spinBox = NULL; - QHBoxLayout *box = new QHBoxLayout(); - QSlider *slider = new QSlider(Qt::Horizontal, m_shaderParamsDialog); - double value = lerp(param->minimum, param->maximum, 0, 100, param->current); - double intpart = 0; - bool stepIsFractional = modf(param->step, &intpart); - - slider->setRange(0, 100); - slider->setSingleStep(1); - slider->setValue(value); - slider->setProperty("param", QVariant::fromValue(param)); - - connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int))); - - box->addWidget(slider); - - if (stepIsFractional) + if (param->pass > last_pass) { - doubleSpinBox = new QDoubleSpinBox(m_shaderParamsDialog); - doubleSpinBox->setRange(param->minimum, param->maximum); - doubleSpinBox->setSingleStep(param->step); - doubleSpinBox->setValue(param->current); - doubleSpinBox->setProperty("slider", QVariant::fromValue(slider)); - slider->setProperty("doubleSpinBox", QVariant::fromValue(doubleSpinBox)); + QGroupBox *groupBox = NULL; + QFileInfo fileInfo(shader_info.data->pass[param->pass].source.path); + QString shaderBasename = fileInfo.completeBaseName(); - connect(doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onShaderParamDoubleSpinBoxValueChanged(double))); + form = new QFormLayout(); + groupBox = new QGroupBox(shaderBasename); + groupBox->setLayout(form); - box->addWidget(doubleSpinBox); + m_shaderParamsDialog->layout()->addWidget(groupBox); + + last_form = form; + last_pass = param->pass; + } + + if ((param->minimum == 0.0) + && (param->maximum + == (param->minimum + + param->step))) + { + /* option is basically a bool, so use a checkbox */ + QCheckBox *checkBox = new QCheckBox(m_shaderParamsDialog); + checkBox->setChecked(param->current == param->maximum ? true : false); + checkBox->setProperty("param", QVariant::fromValue(param)); + + connect(checkBox, SIGNAL(clicked()), this, SLOT(onShaderParamCheckBoxClicked())); + + form->addRow(desc, checkBox); } else { - spinBox = new QSpinBox(m_shaderParamsDialog); - spinBox->setRange(param->minimum, param->maximum); - spinBox->setSingleStep(param->step); - spinBox->setValue(param->current); - spinBox->setProperty("slider", QVariant::fromValue(slider)); - slider->setProperty("spinBox", QVariant::fromValue(spinBox)); + QDoubleSpinBox *doubleSpinBox = NULL; + QSpinBox *spinBox = NULL; + QHBoxLayout *box = new QHBoxLayout(); + QSlider *slider = new QSlider(Qt::Horizontal, m_shaderParamsDialog); + double value = lerp(param->minimum, param->maximum, 0, 100, param->current); + double intpart = 0; + bool stepIsFractional = modf(param->step, &intpart); - connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSpinBoxValueChanged(int))); + slider->setRange(0, 100); + slider->setSingleStep(1); + slider->setValue(value); + slider->setProperty("param", QVariant::fromValue(param)); - box->addWidget(spinBox); + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int))); + + box->addWidget(slider); + + if (stepIsFractional) + { + doubleSpinBox = new QDoubleSpinBox(m_shaderParamsDialog); + doubleSpinBox->setRange(param->minimum, param->maximum); + doubleSpinBox->setSingleStep(param->step); + doubleSpinBox->setValue(param->current); + doubleSpinBox->setProperty("slider", QVariant::fromValue(slider)); + slider->setProperty("doubleSpinBox", QVariant::fromValue(doubleSpinBox)); + + connect(doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onShaderParamDoubleSpinBoxValueChanged(double))); + + box->addWidget(doubleSpinBox); + } + else + { + spinBox = new QSpinBox(m_shaderParamsDialog); + spinBox->setRange(param->minimum, param->maximum); + spinBox->setSingleStep(param->step); + spinBox->setValue(param->current); + spinBox->setProperty("slider", QVariant::fromValue(slider)); + slider->setProperty("spinBox", QVariant::fromValue(spinBox)); + + connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSpinBoxValueChanged(int))); + + box->addWidget(spinBox); + } + + form->addRow(desc, box); } - - form->addRow(desc, box); } + + m_shaderParamsDialog->layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); } m_shaderParamsDialog->resize(720, 480); @@ -2456,6 +2509,17 @@ void MainWindow::onGotStatusMessage(QString msg, unsigned priority, unsigned dur } } +void MainWindow::deferReloadShaderParams() +{ + emit gotReloadShaderParams(); +} + +void MainWindow::onGotReloadShaderParams() +{ + if (m_shaderParamsDialog && m_shaderParamsDialog->isVisible()) + onShaderParamsClicked(); +} + void MainWindow::deferReloadPlaylists() { emit gotReloadPlaylists(); diff --git a/ui/drivers/ui_qt.cpp b/ui/drivers/ui_qt.cpp index 7fcace03e0..4e679cfeae 100644 --- a/ui/drivers/ui_qt.cpp +++ b/ui/drivers/ui_qt.cpp @@ -623,11 +623,23 @@ static void ui_companion_qt_toggle(void *data, bool force) static void ui_companion_qt_event_command(void *data, enum event_command cmd) { ui_companion_qt_t *handle = (ui_companion_qt_t*)data; - - (void)cmd; + ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window; if (!handle) return; + + switch (cmd) + { + case CMD_EVENT_SHADERS_APPLY_CHANGES: + /* PRESET_LOADED already fires in more situations than APPLY_CHANGES, use that for reloading the params window */ + break; + case CMD_EVENT_SHADER_PRESET_LOADED: + RARCH_LOG("[Qt]: Reloading shader parameters.\n"); + win_handle->qtWindow->deferReloadShaderParams(); + break; + default: + break; + } } static void ui_companion_qt_notify_list_pushed(void *data, file_list_t *list, diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index 50943d2a6c..98519dcdf8 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -250,6 +250,18 @@ private: QSpinBox *m_allPlaylistsGridMaxCountSpinBox; }; +class ShaderParamsDialog : public QDialog +{ + Q_OBJECT +public: + ShaderParamsDialog(QWidget *parent = 0); + ~ShaderParamsDialog(); +signals: + void closed(); +protected: + void closeEvent(QCloseEvent *event); +}; + class CoreInfoLabel : public QLabel { Q_OBJECT @@ -365,6 +377,7 @@ signals: void gotLogMessage(const QString &msg); void gotStatusMessage(QString msg, unsigned priority, unsigned duration, bool flush); void gotReloadPlaylists(); + void gotReloadShaderParams(); void showErrorMessageDeferred(QString msg); void extractArchiveDeferred(QString path); @@ -393,6 +406,7 @@ public slots: void reloadPlaylists(); void deferReloadPlaylists(); void onGotReloadPlaylists(); + void onGotReloadShaderParams(); void showWelcomeScreen(); void onIconViewClicked(); void onListViewClicked(); @@ -403,6 +417,7 @@ public slots: void showDocs(); void updateRetroArchNightly(); void onUpdateRetroArchFinished(bool success); + void deferReloadShaderParams(); private slots: void onLoadCoreClicked(const QStringList &extensionFilters = QStringList()); @@ -520,7 +535,7 @@ private: int m_allPlaylistsGridMaxCount; PlaylistEntryDialog *m_playlistEntryDialog; QElapsedTimer m_statusMessageElapsedTimer; - QDialog *m_shaderParamsDialog; + QPointer m_shaderParamsDialog; QNetworkAccessManager *m_networkManager; QProgressDialog *m_updateProgressDialog; QFile m_updateFile; diff --git a/ui/ui_companion_driver.c b/ui/ui_companion_driver.c index 0133e1a56a..a866b6749b 100644 --- a/ui/ui_companion_driver.c +++ b/ui/ui_companion_driver.c @@ -103,6 +103,10 @@ void ui_companion_event_command(enum event_command action) if (ui && ui->event_command) ui->event_command(ui_companion_data, action); +#ifdef HAVE_QT + if (ui_companion_qt.toggle && qt_is_inited) + ui_companion_qt.event_command(ui_companion_qt_data, action); +#endif } void ui_companion_driver_deinit(void)