From eafe75783ee0107afbf590f7e38828e95a483e1d Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 11 Jul 2024 16:40:55 +0200 Subject: [PATCH] Gui: Add class Multisample to check supported MSAA modes --- src/Gui/CMakeLists.txt | 2 + src/Gui/Multisample.cpp | 105 ++++++++++++++++++++++++++++++++++++++++ src/Gui/Multisample.h | 70 +++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 src/Gui/Multisample.cpp create mode 100644 src/Gui/Multisample.h diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index f68985438e..12cb574698 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -850,6 +850,7 @@ SET(View3D_CPP_SRCS Flag.cpp GLBuffer.cpp GLPainter.cpp + Multisample.cpp MouseSelection.cpp NavigationStyle.cpp InventorNavigationStyle.cpp @@ -882,6 +883,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..a76d8fb3ed --- /dev/null +++ b/src/Gui/Multisample.cpp @@ -0,0 +1,105 @@ +// 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" + +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); +} + +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; +} diff --git a/src/Gui/Multisample.h b/src/Gui/Multisample.h new file mode 100644 index 0000000000..2c90da75d6 --- /dev/null +++ b/src/Gui/Multisample.h @@ -0,0 +1,70 @@ +// 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); + +private: + QSurfaceFormat format; + QOpenGLContext context; + QOffscreenSurface offscreen; +}; + +} // namespace Gui + +#endif // GUI_MULTISAMPLE_H