diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 03d28da2c8..93fd4262a0 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -848,6 +848,7 @@ SET(View3D_CPP_SRCS Flag.cpp GLBuffer.cpp GLPainter.cpp + Multisample.cpp MouseSelection.cpp NavigationStyle.cpp InventorNavigationStyle.cpp @@ -880,6 +881,7 @@ SET(View3D_SRCS Flag.h GLBuffer.h GLPainter.h + Multisample.h MouseSelection.h NavigationStyle.h GestureNavigationStyle.h diff --git a/src/Gui/Multisample.cpp b/src/Gui/Multisample.cpp new file mode 100644 index 0000000000..b00f5d2620 --- /dev/null +++ b/src/Gui/Multisample.cpp @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#endif + +#include "Multisample.h" +#include +#include + +using namespace Gui; + +// clang-format off +static constexpr auto numMSAA {6}; +static constexpr auto idStr {0}; +static constexpr auto idEnum {1}; +static constexpr auto idMSAA {2}; +static constexpr std::array, numMSAA> textMSAA {{ + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "None"), AntiAliasing::None, 0}, + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "Line Smoothing"), AntiAliasing::MSAA1x, 1}, + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "MSAA 2x"), AntiAliasing::MSAA2x, 2}, + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "MSAA 4x"), AntiAliasing::MSAA4x, 4}, + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "MSAA 6x"), AntiAliasing::MSAA6x, 6}, + {QT_TRANSLATE_NOOP("Gui::Dialog::DlgSettings3DView", "MSAA 8x"), AntiAliasing::MSAA8x, 8}, +}}; +// clang-format on + +Multisample::Multisample() +{ + context.setFormat(format); + context.create(); + offscreen.setFormat(format); + offscreen.create(); + context.makeCurrent(&offscreen); +} + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +bool Multisample::testSamples(int num) const +{ + // This is always true + if (num == 0 || num == 1) { + return true; + } + + QOpenGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QOpenGLFramebufferObject::Depth); + fboFormat.setSamples(num); + QOpenGLFramebufferObject fbo(100, 100, fboFormat); // NOLINT + return fbo.format().samples() == num; +} + +std::vector> Multisample::supported() const +{ + std::vector> modes; + std::for_each(textMSAA.begin(), textMSAA.end(), [&modes, this](const auto& mode) { + if (testSamples(std::get(mode))) { + const char* context = "Gui::Dialog::DlgSettings3DView"; + QString str = QCoreApplication::translate(context, std::get(mode).data()); + modes.emplace_back(str, std::get(mode)); + } + }); + return modes; +} + +int Multisample::toSamples(AntiAliasing msaa) +{ + auto it = std::find_if(textMSAA.begin(), textMSAA.end(), [msaa](const auto& mode) { + return std::get(mode) == msaa; + }); + if (it != textMSAA.end()) { + return std::get(*it); + } + return 0; +} + +AntiAliasing Multisample::toAntiAliasing(int samples) +{ + auto it = std::find_if(textMSAA.begin(), textMSAA.end(), [samples](const auto& mode) { + return std::get(mode) == samples; + }); + if (it != textMSAA.end()) { + return std::get(*it); + } + return AntiAliasing::None; +} + +AntiAliasing Multisample::readMSAAFromSettings() +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/View"); + return AntiAliasing(hGrp->GetInt("AntiAliasing", int(Gui::AntiAliasing::None))); +} + +void Multisample::writeMSAAToSettings(AntiAliasing msaa) +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/View"); + hGrp->SetInt("AntiAliasing", long(msaa)); +} diff --git a/src/Gui/Multisample.h b/src/Gui/Multisample.h new file mode 100644 index 0000000000..359e20df5a --- /dev/null +++ b/src/Gui/Multisample.h @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2024 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef GUI_MULTISAMPLE_H +#define GUI_MULTISAMPLE_H + +#include +#include +#include +#include +#include +#include + +namespace Gui +{ + +/** @name Anti-Aliasing modes of the rendered 3D scene + * Specifies Anti-Aliasing (AA) method + * - Smoothing enables OpenGL line and vertex smoothing (basically deprecated) + * - MSAA is hardware multi sampling (with 2, 4, 6 or 8 passes), a quite common and efficient AA technique + */ +//@{ +enum class AntiAliasing { + None = 0, + MSAA1x = 1, + MSAA2x = 2, + MSAA4x = 3, + MSAA6x = 5, + MSAA8x = 4 +}; +//@} + +class GuiExport Multisample +{ +public: + Multisample(); + bool testSamples(int num) const; + std::vector> supported() const; + static int toSamples(AntiAliasing msaa); + static AntiAliasing toAntiAliasing(int samples); + static AntiAliasing readMSAAFromSettings(); + static void writeMSAAToSettings(AntiAliasing msaa); + +private: + QSurfaceFormat format; + QOpenGLContext context; + QOffscreenSurface offscreen; +}; + +} // namespace Gui + +#endif // GUI_MULTISAMPLE_H diff --git a/src/Gui/PreferencePages/DlgSettings3DView.ui b/src/Gui/PreferencePages/DlgSettings3DView.ui index 0854dd66a5..bac76fd636 100644 --- a/src/Gui/PreferencePages/DlgSettings3DView.ui +++ b/src/Gui/PreferencePages/DlgSettings3DView.ui @@ -265,7 +265,7 @@ but slower response to any scene changes. - + 120 @@ -275,12 +275,6 @@ but slower response to any scene changes. What kind of multisample anti-aliasing is used - - AntiAliasing - - - View - diff --git a/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp b/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp index 9fc095a637..47775784ba 100644 --- a/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp +++ b/src/Gui/PreferencePages/DlgSettings3DViewImp.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "DlgSettings3DViewImp.h" @@ -97,88 +98,35 @@ void DlgSettings3DViewImp::loadSettings() loadMarkerSize(); } -namespace { -class GLFormatCheck { -public: - GLFormatCheck() { - context.setFormat(format); - context.create(); - offscreen.setFormat(format); - offscreen.create(); - context.makeCurrent(&offscreen); - } - - bool testSamples(int num) { - QOpenGLFramebufferObjectFormat fboFormat; - fboFormat.setAttachment(QOpenGLFramebufferObject::Depth); - fboFormat.setSamples(num); - QOpenGLFramebufferObject fbo(100, 100, fboFormat); // NOLINT - return fbo.format().samples() == num; - } - -private: - QSurfaceFormat format; - QOpenGLContext context; - QOffscreenSurface offscreen; -}; -} - void DlgSettings3DViewImp::addAntiAliasing() { - QString none = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "None"); - QString line = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "Line Smoothing"); - QString msaa2x = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "MSAA 2x"); - QString msaa4x = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "MSAA 4x"); - QString msaa6x = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "MSAA 6x"); - QString msaa8x = QCoreApplication::translate("Gui::Dialog::DlgSettings3DView", "MSAA 8x"); ui->comboAliasing->clear(); - ui->comboAliasing->addItem(none, int(Gui::View3DInventorViewer::None)); - ui->comboAliasing->addItem(line, int(Gui::View3DInventorViewer::Smoothing)); // Do the samples checks only once - static std::vector> modes; + static std::vector> modes; static bool formatCheck = true; if (formatCheck) { formatCheck = false; - GLFormatCheck check; - // NOLINTBEGIN - if (check.testSamples(2)) { - modes.emplace_back(msaa2x, int(Gui::View3DInventorViewer::MSAA2x)); - } - if (check.testSamples(4)) { - modes.emplace_back(msaa4x, int(Gui::View3DInventorViewer::MSAA4x)); - } - if (check.testSamples(6)) { - modes.emplace_back(msaa6x, int(Gui::View3DInventorViewer::MSAA6x)); - } - if (check.testSamples(8)) { - modes.emplace_back(msaa8x, int(Gui::View3DInventorViewer::MSAA8x)); - } - // NOLINTEND + Multisample check; + modes = check.supported(); } for (const auto& it : modes) { - ui->comboAliasing->addItem(it.first, it.second); + ui->comboAliasing->addItem(it.first, int(it.second)); } } void DlgSettings3DViewImp::saveAntiAliasing() { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View"); - int index = ui->comboAliasing->currentIndex(); int aliasing = ui->comboAliasing->itemData(index).toInt(); - hGrp->SetInt("AntiAliasing", aliasing); + Multisample::writeMSAAToSettings(static_cast(aliasing)); } void DlgSettings3DViewImp::loadAntiAliasing() { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View"); - - int aliasing = int(hGrp->GetInt("AntiAliasing", int(Gui::View3DInventorViewer::None))); + int aliasing = int(Multisample::readMSAAFromSettings()); int index = ui->comboAliasing->findData(aliasing); if (index != -1) { ui->comboAliasing->setCurrentIndex(index); diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index d7020b280a..d168c25f55 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -95,6 +95,7 @@ #include "Document.h" #include "GLPainter.h" #include "MainWindow.h" +#include "Multisample.h" #include "NaviCube.h" #include "NavigationStyle.h" #include "Selection.h" @@ -1965,25 +1966,8 @@ void View3DInventorViewer::clearGraphicsItems() int View3DInventorViewer::getNumSamples() { - long samples = App::GetApplication().GetParameterGroupByPath - ("User parameter:BaseApp/Preferences/View")->GetInt("AntiAliasing", 0); - - // NOLINTBEGIN - switch (samples) { - case View3DInventorViewer::MSAA2x: - return 2; - case View3DInventorViewer::MSAA4x: - return 4; - case View3DInventorViewer::MSAA6x: - return 6; - case View3DInventorViewer::MSAA8x: - return 8; - case View3DInventorViewer::Smoothing: - return 1; - default: - return 0; - } - // NOLINTEND + Gui::AntiAliasing msaa = Multisample::readMSAAFromSettings(); + return Multisample::toSamples(msaa); } GLenum View3DInventorViewer::getInternalTextureFormat() diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 5d0e2597ab..3e581c73f3 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -110,22 +110,6 @@ public: }; //@} - /** @name Anti-Aliasing modes of the rendered 3D scene - * Specifies Anti-Aliasing (AA) method - * - Smoothing enables OpenGL line and vertex smoothing (basically deprecated) - * - MSAA is hardware multi sampling (with 2, 4 or 8 passes), a quite common and efficient AA technique - */ - //@{ - enum AntiAliasing { - None = 0, - Smoothing = 1, - MSAA2x = 2, - MSAA4x = 3, - MSAA6x = 5, - MSAA8x = 4 - }; - //@} - /** @name Render mode */ //@{