From 10c4e51b47ef31023c779e63b978a26be7e42f11 Mon Sep 17 00:00:00 2001 From: Antoine C Date: Sat, 11 May 2024 19:24:19 +0100 Subject: [PATCH] Add waveform option detection and change UI --- src/preferences/dialog/dlgprefwaveform.cpp | 172 +++-- src/preferences/dialog/dlgprefwaveform.h | 11 +- src/preferences/dialog/dlgprefwaveformdlg.ui | 640 +++++++++--------- .../allshader/waveformrendererrgb.cpp | 8 +- .../allshader/waveformrenderersignalbase.h | 1 + src/waveform/waveformwidgetfactory.cpp | 80 ++- src/waveform/waveformwidgetfactory.h | 44 +- .../allshader/filteredwaveformwidget.cpp | 1 + .../allshader/filteredwaveformwidget.h | 4 + .../widgets/allshader/hsvwaveformwidget.h | 4 + .../widgets/allshader/rgbwaveformwidget.h | 3 + .../widgets/allshader/simplewaveformwidget.h | 4 + 12 files changed, 567 insertions(+), 405 deletions(-) diff --git a/src/preferences/dialog/dlgprefwaveform.cpp b/src/preferences/dialog/dlgprefwaveform.cpp index 0cf510c11c5..e6c8777f4e8 100644 --- a/src/preferences/dialog/dlgprefwaveform.cpp +++ b/src/preferences/dialog/dlgprefwaveform.cpp @@ -8,37 +8,28 @@ #include "waveform/renderers/waveformwidgetrenderer.h" #include "waveform/waveformwidgetfactory.h" +#ifdef MIXXX_USE_QOPENGL +#include "waveform/renderers/allshader/waveformrenderersignalbase.h" +#define IMPL_SLOT_WAVEFORM_OPTION(opt) \ + void DlgPrefWaveform::slotSetWaveformOption##opt(bool checked) { \ + int currentOption = m_pConfig->getValue( \ + ConfigKey("[Waveform]", "waveform_options"), \ + allshader::WaveformRendererSignalBase::None); \ + m_pConfig->setValue(ConfigKey("[Waveform]", "waveform_options"), \ + checked ? currentOption | \ + allshader::WaveformRendererSignalBase::opt \ + : currentOption ^ \ + allshader::WaveformRendererSignalBase::opt); \ + auto type = static_cast( \ + waveformTypeComboBox->currentData().toInt()); \ + auto* factory = WaveformWidgetFactory::instance(); \ + factory->setWidgetTypeFromHandle( \ + factory->findHandleIndexFromType(type), true); \ + } +#endif + namespace { constexpr WaveformWidgetType::Type kDefaultWaveform = WaveformWidgetType::RGB; -const QList kWaveformWithOnlyAcceleration = { - WaveformWidgetType::Simple, - WaveformWidgetType::Stacked}; -const QList kWaveformWithoutAcceleration = { - WaveformWidgetType::VSyncTest, - WaveformWidgetType::Empty}; -const QList kWaveformWithSplitSignalSupport = { - WaveformWidgetType::RGB}; - -void setAccelerationCheckboxProperty(WaveformWidgetType::Type type, QCheckBox* checkbox) { - checkbox->blockSignals(true); - if (kWaveformWithOnlyAcceleration.contains(type)) { - checkbox->setEnabled(false); - checkbox->setChecked(true); - } else if (kWaveformWithoutAcceleration.contains(type)) { - checkbox->setEnabled(false); - checkbox->setChecked(false); - } else { - checkbox->setEnabled(true); - } - checkbox->blockSignals(false); -} -void updateStereoSplitVisibility(WaveformWidgetType::Type type, - bool isAccelerationEnabled, - QCheckBox* checkbox) { - checkbox->blockSignals(true); - checkbox->setVisible(isAccelerationEnabled && kWaveformWithSplitSignalSupport.contains(type)); - checkbox->blockSignals(false); -} } // anonymous namespace DlgPrefWaveform::DlgPrefWaveform( @@ -62,6 +53,9 @@ DlgPrefWaveform::DlgPrefWaveform( // update the combobox. QVector types = factory->getAvailableTypes(); for (int i = 0; i < types.size(); ++i) { + if (types[i].getType() == WaveformWidgetType::Empty) { + continue; + } waveformTypeComboBox->addItem(types[i].getDisplayName(), types[i].getType()); } // Sort the combobox items alphabetically @@ -121,6 +115,11 @@ DlgPrefWaveform::DlgPrefWaveform( beatGridAlphaSlider, &QSlider::setValue); + connect(useWaveformCheckBox, + &QCheckBox::clicked, + this, + &DlgPrefWaveform::slotSetWaveformEnabled); + connect(waveformTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, @@ -133,7 +132,11 @@ DlgPrefWaveform::DlgPrefWaveform( connect(splitLeftRightCheckBox, &QCheckBox::clicked, this, - &DlgPrefWaveform::slotSetWaveformSplitSignal); + &DlgPrefWaveform::slotSetWaveformOptionSplitStereoSignal); + connect(highDetailsCheckBox, + &QCheckBox::clicked, + this, + &DlgPrefWaveform::slotSetWaveformOptionHighDetails); connect(defaultZoomComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, @@ -210,7 +213,7 @@ void DlgPrefWaveform::slotUpdate() { useAccelerationCheckBox->setEnabled(true); isAccelerationEnabled = m_pConfig->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - WaveformWidgetBackend::AllShader) != + factory->preferredBackend()) != WaveformWidgetBackend::None; useAccelerationCheckBox->setChecked(isAccelerationEnabled); } else { @@ -229,8 +232,11 @@ void DlgPrefWaveform::slotUpdate() { ConfigKey("[Waveform]", "split_stereo_signal"), false)); - setAccelerationCheckboxProperty(factory->getType(), useAccelerationCheckBox); - updateStereoSplitVisibility(factory->getType(), isAccelerationEnabled, splitLeftRightCheckBox); + bool useWaveform = m_pConfig->getValue(ConfigKey("[Waveform]", "enabled"), true); + useWaveformCheckBox->setChecked(useWaveform); + updateWaveformAcceleration(); + updateWaveformOption(); + waveformTypeComboBox->setEnabled(useWaveform); updateEnableUntilMark(); frameRateSpinBox->setValue(factory->getFrameRate()); @@ -342,16 +348,31 @@ void DlgPrefWaveform::slotSetWaveformType(int index) { auto* factory = WaveformWidgetFactory::instance(); factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type)); - setAccelerationCheckboxProperty(factory->getType(), useAccelerationCheckBox); + updateWaveformAcceleration(); bool isAccelerationEnabled = m_pConfig->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - WaveformWidgetBackend::AllShader) != + factory->preferredBackend()) != WaveformWidgetBackend::None; useAccelerationCheckBox->setChecked(isAccelerationEnabled); - updateStereoSplitVisibility(factory->getType(), isAccelerationEnabled, splitLeftRightCheckBox); + updateWaveformOption(); updateEnableUntilMark(); } +void DlgPrefWaveform::slotSetWaveformEnabled(bool checked) { + m_pConfig->setValue(ConfigKey("[Waveform]", "enabled"), checked); + auto* factory = WaveformWidgetFactory::instance(); + if (!checked) { + factory->setWidgetTypeFromHandle( + factory->findHandleIndexFromType(WaveformWidgetType::Empty), + true); + } else { + auto type = static_cast( + waveformTypeComboBox->currentData().toInt()); + factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); + } + slotUpdate(); +} + void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { if (checked) { m_pConfig->setValue(ConfigKey("[Waveform]", "use_hardware_acceleration"), @@ -369,28 +390,91 @@ void DlgPrefWaveform::slotSetWaveformAcceleration(bool checked) { auto type = static_cast(waveformTypeComboBox->currentData().toInt()); auto* factory = WaveformWidgetFactory::instance(); factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); - updateStereoSplitVisibility(type, checked, splitLeftRightCheckBox); - + updateWaveformOption(); updateEnableUntilMark(); } -void DlgPrefWaveform::slotSetWaveformSplitSignal(bool checked) { - m_pConfig->setValue(ConfigKey("[Waveform]", "split_stereo_signal"), - checked); +#ifdef MIXXX_USE_QOPENGL +IMPL_SLOT_WAVEFORM_OPTION(SplitStereoSignal) +IMPL_SLOT_WAVEFORM_OPTION(HighDetails) +#endif + +void DlgPrefWaveform::updateWaveformAcceleration() { auto type = static_cast(waveformTypeComboBox->currentData().toInt()); auto* factory = WaveformWidgetFactory::instance(); - factory->setWidgetTypeFromHandle(factory->findHandleIndexFromType(type), true); + int handleIdx = factory->findHandleIndexFromType(type); + + bool supportAcceleration = false, supportSoftware = true, + useWaveform = + m_pConfig->getValue(ConfigKey("[Waveform]", "enabled"), true); + if (handleIdx != -1) { + const auto& handle = factory->getAvailableTypes()[handleIdx]; + supportAcceleration = handle.supportAcceleration(); + supportSoftware = handle.supportSoftware(); + } + WaveformWidgetBackend::Backend backend = m_pConfig->getValue( + ConfigKey("[Waveform]", "use_hardware_acceleration"), + factory->preferredBackend()); + + useAccelerationCheckBox->blockSignals(true); + + if (supportSoftware ^ supportAcceleration) { + useAccelerationCheckBox->setChecked(!supportSoftware || supportAcceleration); + } else { + useAccelerationCheckBox->setChecked(backend != WaveformWidgetBackend::None); + } + + useAccelerationCheckBox->setEnabled(supportAcceleration && supportSoftware && useWaveform); + + useAccelerationCheckBox->blockSignals(false); +} +void DlgPrefWaveform::updateWaveformOption() { + WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); + int supportedOption = allshader::WaveformRendererSignalBase::None; + int currentOption = m_pConfig->getValue( + ConfigKey("[Waveform]", "waveform_options"), + allshader::WaveformRendererSignalBase::None); + WaveformWidgetBackend::Backend backend = m_pConfig->getValue( + ConfigKey("[Waveform]", "use_hardware_acceleration"), + factory->preferredBackend()); + bool useWaveform = m_pConfig->getValue(ConfigKey("[Waveform]", "enabled"), true); + + auto type = static_cast(waveformTypeComboBox->currentData().toInt()); + int handleIdx = factory->findHandleIndexFromType(type); + + if (handleIdx != -1) { + supportedOption = factory->getAvailableTypes()[handleIdx].supportedOptions(backend); + } + + splitLeftRightCheckBox->blockSignals(true); + highDetailsCheckBox->blockSignals(true); + + splitLeftRightCheckBox->setEnabled(useWaveform && + supportedOption & + allshader::WaveformRendererSignalBase::SplitStereoSignal); + highDetailsCheckBox->setEnabled(useWaveform && + supportedOption & + allshader::WaveformRendererSignalBase::HighDetails); + splitLeftRightCheckBox->setChecked(splitLeftRightCheckBox->isEnabled() && + currentOption & + allshader::WaveformRendererSignalBase::SplitStereoSignal); + highDetailsCheckBox->setChecked(highDetailsCheckBox->isEnabled() && + currentOption & allshader::WaveformRendererSignalBase::HighDetails); + + splitLeftRightCheckBox->blockSignals(false); + highDetailsCheckBox->blockSignals(false); } void DlgPrefWaveform::updateEnableUntilMark() { #ifndef MIXXX_USE_QOPENGL const bool enabled = false; #else + WaveformWidgetFactory* factory = WaveformWidgetFactory::instance(); const bool enabled = WaveformWidgetFactory::instance()->widgetTypeSupportsUntilMark() && m_pConfig->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - WaveformWidgetBackend::AllShader) != + factory->preferredBackend()) != WaveformWidgetBackend::None; #endif untilMarkShowBeatsCheckBox->setEnabled(enabled); @@ -403,7 +487,7 @@ void DlgPrefWaveform::updateEnableUntilMark() { } void DlgPrefWaveform::slotSetWaveformOverviewType(int index) { - m_pConfig->set(ConfigKey("[Waveform]","WaveformOverviewType"), ConfigValue(index)); + m_pConfig->set(ConfigKey("[Waveform]", "WaveformOverviewType"), ConfigValue(index)); emit reloadUserInterface(); } diff --git a/src/preferences/dialog/dlgprefwaveform.h b/src/preferences/dialog/dlgprefwaveform.h index 4b2ad36805f..b199dd811c0 100644 --- a/src/preferences/dialog/dlgprefwaveform.h +++ b/src/preferences/dialog/dlgprefwaveform.h @@ -5,6 +5,9 @@ #include "preferences/dialog/dlgpreferencepage.h" #include "preferences/dialog/ui_dlgprefwaveformdlg.h" #include "preferences/usersettings.h" +#ifdef MIXXX_USE_QOPENGL +#define DECL_SLOT_WAVEFORM_OPTION(opt) void slotSetWaveformOption##opt(bool checked) +#endif class Library; @@ -26,8 +29,12 @@ class DlgPrefWaveform : public DlgPreferencePage, public Ui::DlgPrefWaveformDlg private slots: void slotSetFrameRate(int frameRate); void slotSetWaveformType(int index); + void slotSetWaveformEnabled(bool checked); void slotSetWaveformAcceleration(bool checked); - void slotSetWaveformSplitSignal(bool checked); +#ifdef MIXXX_USE_QOPENGL + DECL_SLOT_WAVEFORM_OPTION(SplitStereoSignal); + DECL_SLOT_WAVEFORM_OPTION(HighDetails); +#endif void slotSetWaveformOverviewType(int index); void slotSetDefaultZoom(int index); void slotSetZoomSynchronization(bool checked); @@ -52,6 +59,8 @@ class DlgPrefWaveform : public DlgPreferencePage, public Ui::DlgPrefWaveformDlg void calculateCachedWaveformDiskUsage(); void notifyRebootNecessary(); void updateEnableUntilMark(); + void updateWaveformOption(); + void updateWaveformAcceleration(); UserSettingsPointer m_pConfig; std::shared_ptr m_pLibrary; diff --git a/src/preferences/dialog/dlgprefwaveformdlg.ui b/src/preferences/dialog/dlgprefwaveformdlg.ui index bab82472265..931b446d12a 100644 --- a/src/preferences/dialog/dlgprefwaveformdlg.ui +++ b/src/preferences/dialog/dlgprefwaveformdlg.ui @@ -16,126 +16,26 @@ - - - - Synchronize zoom level across all waveform displays. - - - Synchronize zoom level across all waveforms - - - - - - - This functionality requires waveform acceleration "(GLSL)". - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Set amount of opacity on beat grid lines. - - - % - - - 100 - - - 90 - - - - - - - Font size - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - untilMarkTextPointSizeSpinBox - - - - - + + - - + + - - fps - - - 10 - - - 60 - - - 30 - - - - - - - Placement - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - untilMarkAlignComboBox - - - - - - - - 0 - 0 - - - - - - - Waveform type - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - waveformTypeComboBox + + 6 - - - - - Frame rate + Beat grid opacity Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - frameRateSlider - - + @@ -163,65 +63,81 @@ - - - - - - The waveform shows the waveform envelope of the track near the current playback position. -Select from different types of displays for the waveform, which differ primarily in the level of detail shown in the waveform. + + + + Default zoom level + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + defaultZoomComboBox + + + + + + + + + Clear Cached Waveforms - - - - Qt::Horizontal - - - QSizePolicy::Maximum + + + + Mixxx caches the waveforms of your tracks on disk the first time you load a track. This reduces CPU usage when you are playing live but requires extra disk space. - - - 20 - 20 - + + true - + - - + + - + 0 0 - Use acceleration + PLACEHOLDER FOR DISK USAGE + + + true + + + + + + + Enable waveform caching + + + + + + + Generate waveforms when analyzing library - - + + - Caching + Play marker hints - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - Play marker position + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + OpenGL status @@ -275,84 +191,178 @@ Select from different types of displays for the waveform, which differ primarily - - - - - - Clear Cached Waveforms - - - - - - - Mixxx caches the waveforms of your tracks on disk the first time you load a track. This reduces CPU usage when you are playing live but requires extra disk space. - - - true - - - - - - - - 0 - 0 - - - - PLACEHOLDER FOR DISK USAGE - - - true - - - - - - - Enable waveform caching - - - - - - - Generate waveforms when analyzing library - - - - + + + + Caching + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + - - + + + + End of track warning + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + endOfTrackWarningTimeSlider + + + + + + + Play marker position + + + + + + + Visual gain + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + allVisualGain + + + + + + + This functionality requires waveform acceleration "(GLSL)". + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - + Synchronize zoom level across all waveform displays. + + + Synchronize zoom level across all waveforms + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + 0 + + + 60 + + 30 + + + Qt::Horizontal + + + + + - Waveform overview type + Font size + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + untilMarkTextPointSizeSpinBox - - + + - - - - 6 + The waveform overview shows the waveform envelope of the entire track. +Select from different types of displays for the waveform overview, which differ primarily in the level of detail shown in the waveform. + + + + - Beat grid opacity + Frame rate Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + frameRateSlider + + + + + + + Time until next marker + + + + + + + Highlight the waveforms when the last seconds of a track remains. + + + seconds + + + 0 + + + 60 + + + 30 + + + + + + + Beats until next marker + - + @@ -484,38 +494,14 @@ Select from different types of displays for the waveform, which differ primarily - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Moves the play marker position on the waveforms to the left, right or center (default). - - - 0 - - - 100 - - - 50 - - - Qt::Horizontal + + + + Stereo coloration - + 100 @@ -528,30 +514,32 @@ Select from different types of displays for the waveform, which differ primarily - - - - Time until next marker + + + + Set amount of opacity on beat grid lines. - - - - - - Normalize waveform overview + + % + + + 100 + + + 90 - - + + - Highlight the waveforms when the last seconds of a track remains. + - seconds + fps - 0 + 10 60 @@ -561,40 +549,49 @@ Select from different types of displays for the waveform, which differ primarily - - - - Play marker hints + + + + + 0 + 0 + - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + - - - - - Default zoom level + Waveform type Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - defaultZoomComboBox + waveformTypeComboBox - + - Beats until next marker + Normalize waveform overview - - + + + + Placement + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + untilMarkAlignComboBox + + - + @@ -613,34 +610,21 @@ Select from different types of displays for the waveform, which differ primarily - - - - Visual gain - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - allVisualGain - - - - - - End of track warning - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + - - endOfTrackWarningTimeSlider + + Waveform overview type - - + + + + + 0 @@ -653,48 +637,78 @@ Select from different types of displays for the waveform, which differ primarily 16777215 + + Moves the play marker position on the waveforms to the left, right or center (default). + 0 - 60 + 100 - 30 + 50 Qt::Horizontal - - - - The waveform overview shows the waveform envelope of the entire track. -Select from different types of displays for the waveform overview, which differ primarily in the level of detail shown in the waveform. + + + + Enabled - - + + + + + + The waveform shows the waveform envelope of the track near the current playback position. +Select from different types of displays for the waveform, which differ primarily in the level of detail shown in the waveform. + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Use acceleration + + + + + + + - Split the left and right channel + High details - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/src/waveform/renderers/allshader/waveformrendererrgb.cpp b/src/waveform/renderers/allshader/waveformrendererrgb.cpp index 1460394e602..d987cf70bfd 100644 --- a/src/waveform/renderers/allshader/waveformrendererrgb.cpp +++ b/src/waveform/renderers/allshader/waveformrendererrgb.cpp @@ -150,11 +150,11 @@ void WaveformRendererRGB::paintGL() { } float maxAllChn[2]{static_cast(u8maxAllChn[0]), static_cast(u8maxAllChn[1])}; + // In case we don't render individual color per channel, all the + // signal information is in the first field of each array. If + // this is the split render, we only render the left channel + // anyway. for (int chn = 0; - // In case we don't render individual color per channel, all the - // signal information is in the first field of each array. If - // this is the split render, we only render the left channel - // anyway. chn < (splitLeftRight && !m_isSlipRenderer ? 2 : 1); chn++) { // Cast to float diff --git a/src/waveform/renderers/allshader/waveformrenderersignalbase.h b/src/waveform/renderers/allshader/waveformrenderersignalbase.h index d6d1cedafee..b3fca0d672f 100644 --- a/src/waveform/renderers/allshader/waveformrenderersignalbase.h +++ b/src/waveform/renderers/allshader/waveformrenderersignalbase.h @@ -18,6 +18,7 @@ class allshader::WaveformRendererSignalBase : public ::WaveformRendererSignalBas enum Options { None = 0, SplitStereoSignal = 0x1, + HighDetails = 0x2, }; static constexpr float m_maxValue{static_cast(std::numeric_limits::max())}; diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp index e55d3ac8e84..8cb14a1ccd3 100644 --- a/src/waveform/waveformwidgetfactory.cpp +++ b/src/waveform/waveformwidgetfactory.cpp @@ -555,6 +555,7 @@ bool WaveformWidgetFactory::setWidgetType( *pCurrentType = isAcceptable ? type : WaveformWidgetType::Empty; if (m_config) { m_configType = *pCurrentType; + // TODO do not set "Empty"? m_config->setValue( ConfigKey("[Waveform]", "WaveformType"), *pCurrentType); } @@ -864,6 +865,7 @@ void WaveformWidgetFactory::slotFrameSwapped() { void WaveformWidgetFactory::evaluateWidgets() { m_waveformWidgetHandles.clear(); QHash> collectedHandles; + QHash supportedOptions; for (int type = WaveformWidgetType::Empty; type < WaveformWidgetType::Count_WaveformWidgetType; type++) { @@ -926,6 +928,8 @@ void WaveformWidgetFactory::evaluateWidgets() { setWaveformVarsByType.operator()(); #ifdef MIXXX_USE_QOPENGL setWaveformVarsByType.operator()(); + supportedOptions[static_cast(type)] = + allshader::SimpleWaveformWidget::supportedOptions(); #else setWaveformVarsByType.operator()(); #endif @@ -942,6 +946,8 @@ void WaveformWidgetFactory::evaluateWidgets() { setWaveformVarsByType.operator()(); #ifdef MIXXX_USE_QOPENGL setWaveformVarsByType.operator()(); + supportedOptions[static_cast(type)] = + allshader::FilteredWaveformWidget::supportedOptions(); #else setWaveformVarsByType.operator()(); #endif @@ -965,6 +971,8 @@ void WaveformWidgetFactory::evaluateWidgets() { #endif #ifdef MIXXX_USE_QOPENGL setWaveformVarsByType.operator()(); + supportedOptions[static_cast(type)] = + allshader::RGBWaveformWidget::supportedOptions(); #else setWaveformVarsByType.operator()(); #endif @@ -979,6 +987,8 @@ void WaveformWidgetFactory::evaluateWidgets() { #endif #ifdef MIXXX_USE_QOPENGL setWaveformVarsByType.operator()(); + supportedOptions[static_cast(type)] = + allshader::HSVWaveformWidget::supportedOptions(); #else setWaveformVarsByType.operator()(); #endif @@ -1002,7 +1012,12 @@ void WaveformWidgetFactory::evaluateWidgets() { auto& type = handleIter.key(); auto& backends = handleIter.value(); #endif - m_waveformWidgetHandles.push_back(WaveformWidgetAbstractHandle(type, backends)); + m_waveformWidgetHandles.push_back(WaveformWidgetAbstractHandle(type, backends +#ifdef MIXXX_USE_QOPENGL + , + supportedOptions.value(type, allshader::WaveformRendererSignalBase::None) +#endif + )); } } @@ -1015,14 +1030,7 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createFilteredWaveformWidget( // complains come back, we can convert this safely to a backend eventually. int backend = m_config->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - isOpenGlAvailable() || isOpenGlesAvailable() - ? -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - : WaveformWidgetBackend::None); + preferredBackend()); switch (backend) { case WaveformWidgetBackend::GL: @@ -1049,14 +1057,7 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createHSVWaveformWidget(WWaveform // complains come back, we can convert this safely to a backend eventually. int backend = m_config->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - isOpenGlAvailable() || isOpenGlesAvailable() - ? -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - : WaveformWidgetBackend::None); + preferredBackend()); switch (backend) { #ifdef MIXXX_USE_QOPENGL @@ -1076,14 +1077,7 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createRGBWaveformWidget(WWaveform // complains come back, we can convert this safely to a backend eventually. int backend = m_config->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - isOpenGlAvailable() || isOpenGlesAvailable() - ? -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - : WaveformWidgetBackend::None); + preferredBackend()); switch (backend) { case WaveformWidgetBackend::GL: @@ -1092,11 +1086,9 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createRGBWaveformWidget(WWaveform return new GLSLRGBWaveformWidget(viewer->getGroup(), viewer); #ifdef MIXXX_USE_QOPENGL case WaveformWidgetBackend::AllShader: { - int options = allshader::WaveformRendererSignalBase::None; - if (m_config->getValue( - ConfigKey("[Waveform]", "split_stereo_signal"), false)) { - options |= allshader::WaveformRendererSignalBase::SplitStereoSignal; - } + int options = + m_config->getValue(ConfigKey("[Waveform]", "waveform_options"), + allshader::WaveformRendererSignalBase::None); return new allshader::RGBWaveformWidget(viewer->getGroup(), viewer, options); } #else @@ -1121,14 +1113,7 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createSimpleWaveformWidget(WWavef // complains come back, we can convert this safely to a backend eventually. int backend = m_config->getValue( ConfigKey("[Waveform]", "use_hardware_acceleration"), - isOpenGlAvailable() || isOpenGlesAvailable() - ? -#ifdef MIXXX_USE_QOPENGL - WaveformWidgetBackend::AllShader -#else - WaveformWidgetBackend::GL -#endif - : WaveformWidgetBackend::None); + preferredBackend()); switch (backend) { #ifdef MIXXX_USE_QOPENGL @@ -1262,14 +1247,27 @@ WaveformWidgetType::Type WaveformWidgetFactory::findTypeFromHandleIndex(int inde } int WaveformWidgetFactory::findHandleIndexFromType(WaveformWidgetType::Type type) { - int index = -1; for (int i = 0; i < m_waveformWidgetHandles.size(); i++) { const WaveformWidgetAbstractHandle& handle = m_waveformWidgetHandles[i]; if (handle.m_type == type) { - index = i; + return i; } } - return index; + return -1; +} + +WaveformWidgetBackend::Backend WaveformWidgetFactory::preferredBackend() const { +#ifdef MIXXX_USE_QOPENGL + if (m_openGlAvailable || m_openGlesAvailable) { + return WaveformWidgetBackend::AllShader; + } +#endif + if (m_openGlAvailable && m_openGLShaderAvailable) { + return WaveformWidgetBackend::GLSL; + } else if (m_openGlAvailable) { + return WaveformWidgetBackend::GL; + } + return WaveformWidgetBackend::None; } // Static diff --git a/src/waveform/waveformwidgetfactory.h b/src/waveform/waveformwidgetfactory.h index 98fcecb16c2..40bc26f5465 100644 --- a/src/waveform/waveformwidgetfactory.h +++ b/src/waveform/waveformwidgetfactory.h @@ -23,20 +23,58 @@ class WaveformWidgetAbstractHandle { public: WaveformWidgetAbstractHandle(); WaveformWidgetAbstractHandle(WaveformWidgetType::Type type, - QList backends) - : m_type(type), m_backends(std::move(backends)) { + QList backends +#ifdef MIXXX_USE_QOPENGL + , + int supportedOptions +#endif + ) + : m_type(type), m_backends(std::move(backends)) +#ifdef MIXXX_USE_QOPENGL + , + m_supportedOption(supportedOptions) +#endif + { } WaveformWidgetType::Type getType() const { return m_type;} const QList& getBackend() const { return m_backends; } + bool supportAcceleration() const { + for (auto backend : m_backends) { + if (backend == WaveformWidgetBackend::GL || + backend == WaveformWidgetBackend::GLSL +#ifdef MIXXX_USE_QOPENGL + || backend == WaveformWidgetBackend::AllShader +#endif + ) { + return true; + } + } + return false; + } + bool supportSoftware() const { + return m_backends.contains(WaveformWidgetBackend::None); + } + + int supportedOptions(WaveformWidgetBackend::Backend backend) const { +#ifdef MIXXX_USE_QOPENGL + return backend == WaveformWidgetBackend::AllShader ? m_supportedOption : 0; +#else + return 0; +#endif + } QString getDisplayName() const; private: WaveformWidgetType::Type m_type; QList m_backends; +#ifdef MIXXX_USE_QOPENGL + // Only relevant for Allshader (accelerated) backend. Other backends don't implement options + int m_supportedOption; +#endif friend class WaveformWidgetFactory; }; @@ -91,6 +129,8 @@ class WaveformWidgetFactory : public QObject, public Singleton