From d8ea37a730ba8ca7f5373c8337111ad463917874 Mon Sep 17 00:00:00 2001 From: Michael MIGLIORE Date: Wed, 20 Nov 2024 09:23:08 +0100 Subject: [PATCH] Subclass GLX (#1722) --- application/testing/CMakeLists.txt | 7 +++- library/src/context.cxx | 5 --- library/src/window_impl.cxx | 23 ++++++++--- vtkext/private/module/CMakeLists.txt | 6 +++ .../private/module/vtkF3DGLXRenderWindow.cxx | 38 +++++++++++++++++++ vtkext/private/module/vtkF3DGLXRenderWindow.h | 25 ++++++++++++ 6 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 vtkext/private/module/vtkF3DGLXRenderWindow.cxx create mode 100644 vtkext/private/module/vtkF3DGLXRenderWindow.h diff --git a/application/testing/CMakeLists.txt b/application/testing/CMakeLists.txt index a938e11ae4..811d8b72a9 100644 --- a/application/testing/CMakeLists.txt +++ b/application/testing/CMakeLists.txt @@ -1,7 +1,7 @@ # F3D Testing function(f3d_test) - cmake_parse_arguments(F3D_TEST "TONE_MAPPING;LONG_TIMEOUT;INTERACTION;INTERACTION_CONFIGURE;NO_BASELINE;NO_RENDER;NO_OUTPUT;WILL_FAIL;NO_DATA_FORCE_RENDER" "NAME;CONFIG;RESOLUTION;THRESHOLD;REGEXP;REGEXP_FAIL;HDRI;RENDERING_BACKEND" "DATA;DEPENDS;ARGS" ${ARGN}) + cmake_parse_arguments(F3D_TEST "TONE_MAPPING;LONG_TIMEOUT;INTERACTION;INTERACTION_CONFIGURE;NO_BASELINE;NO_RENDER;NO_OUTPUT;WILL_FAIL;NO_DATA_FORCE_RENDER" "NAME;CONFIG;RESOLUTION;THRESHOLD;REGEXP;REGEXP_FAIL;HDRI;RENDERING_BACKEND" "DATA;DEPENDS;ENV;ARGS" ${ARGN}) if(F3D_TEST_CONFIG) list(APPEND F3D_TEST_ARGS "--config=${F3D_TEST_CONFIG}") @@ -118,6 +118,7 @@ function(f3d_test) set_tests_properties(f3d::${F3D_TEST_NAME} PROPERTIES FIXTURES_REQUIRED "${_depends_fixtures}") endif() + set(f3d_test_env_vars ${F3D_TEST_ENV}) list(APPEND f3d_test_env_vars "CTEST_F3D_PROGRESS_BAR=1") if (F3D_TEST_NO_DATA_FORCE_RENDER) list(APPEND f3d_test_env_vars "CTEST_F3D_NO_DATA_FORCE_RENDER=1") @@ -1029,7 +1030,9 @@ if(UNIX AND NOT APPLE AND VTK_VERSION VERSION_GREATER_EQUAL 9.3.20240914 AND F3D if(F3D_TESTING_ENABLE_GLX_TESTS) f3d_test(NAME TestRenderingBackendGLX DATA cow.vtp RENDERING_BACKEND glx) - f3d_test(NAME TestRenderingBackendGLXCheckClass DATA cow.vtp RENDERING_BACKEND glx ARGS --verbose REGEXP "vtkXOpenGLRenderWindow" NO_BASELINE) + f3d_test(NAME TestRenderingBackendGLXNoDisplay DATA cow.vtp RENDERING_BACKEND glx ENV "DISPLAY=:7" REGEXP "Cannot create a window" NO_BASELINE) + f3d_test(NAME TestRenderingBackendGLXCheckClass DATA cow.vtp RENDERING_BACKEND glx ARGS --verbose REGEXP "vtkF3DGLXRenderWindow" NO_BASELINE) + f3d_test(NAME TestRenderingBackendLinuxAutoCheckClass DATA cow.vtp ARGS --verbose REGEXP "vtkF3DGLXRenderWindow" NO_BASELINE) endif() f3d_test(NAME TestRenderingBackendWGLFailure DATA cow.vtp RENDERING_BACKEND wgl REGEXP "Cannot use a WGL context on this platform" NO_BASELINE) diff --git a/library/src/context.cxx b/library/src/context.cxx index 4f5b61e321..ec8ca2abf2 100644 --- a/library/src/context.cxx +++ b/library/src/context.cxx @@ -7,10 +7,6 @@ #include #include -#if defined(VTK_USE_X) && VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) -#include -#endif - #if defined(VTK_OPENGL_HAS_EGL) && VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) #include #endif @@ -49,7 +45,6 @@ context::function context::getSymbol(const std::string& lib, const std::string& context::function context::glx() { #if defined(VTK_USE_X) && VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) - gladLoaderLoadGLX(nullptr, 0); // Load core glx functions. return getSymbol("GLX", "glXGetProcAddress"); #else throw loading_exception("Cannot use a GLX context on this platform"); diff --git a/library/src/window_impl.cxx b/library/src/window_impl.cxx index f66ff1666d..bcdce9fec0 100644 --- a/library/src/window_impl.cxx +++ b/library/src/window_impl.cxx @@ -25,7 +25,7 @@ #include #ifdef VTK_USE_X -#include +#include #endif #ifdef _WIN32 @@ -72,7 +72,15 @@ class window_impl::internals #ifdef _WIN32 return vtkSmartPointer::New(); #else - // XXX: At the moment, rely on VTK logic for Linux and macOS +#if defined(VTK_USE_X) + // try GLX + vtkSmartPointer renWin = vtkSmartPointer::New(); + if (renWin) + { + return renWin; + } +#endif + // XXX: At the moment, fallback on VTK logic // It will change in the future when other subclasses are implemented return vtkSmartPointer::New(); #endif @@ -119,8 +127,8 @@ window_impl::window_impl(const options& options, const std::optional& type } else if (type == Type::GLX) { -#if defined(VTK_USE_X) && VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) - this->Internals->RenWin = vtkSmartPointer::New(); +#if defined(VTK_USE_X) + this->Internals->RenWin = vtkSmartPointer::New(); #else throw engine::no_window_exception("Window type is GLX but VTK GLX support is not enabled"); #endif @@ -136,7 +144,10 @@ window_impl::window_impl(const options& options, const std::optional& type this->Internals->RenWin = internals::AutoBackendWindow(); } - assert(this->Internals->RenWin != nullptr); + if (this->Internals->RenWin == nullptr) + { + throw engine::no_window_exception("Cannot create a window"); + } #if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) vtkOpenGLRenderWindow* oglRenWin = vtkOpenGLRenderWindow::SafeDownCast(this->Internals->RenWin); @@ -185,7 +196,7 @@ window_impl::Type window_impl::getType() } #ifdef VTK_USE_X - if (this->Internals->RenWin->IsA("vtkXOpenGLRenderWindow")) + if (this->Internals->RenWin->IsA("vtkF3DGLXRenderWindow")) { return Type::GLX; } diff --git a/vtkext/private/module/CMakeLists.txt b/vtkext/private/module/CMakeLists.txt index 6613c002db..8b298c3662 100644 --- a/vtkext/private/module/CMakeLists.txt +++ b/vtkext/private/module/CMakeLists.txt @@ -66,6 +66,12 @@ if(WIN32) list(APPEND classes vtkF3DWin32OutputWindow vtkF3DWGLRenderWindow) endif() +# In theory the test should be `if (VTK_USE_X)` but this variable is +# only exported starting from VTK 9.4 +if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND NOT ANDROID) + list(APPEND classes vtkF3DGLXRenderWindow) +endif() + if(ANDROID) list(APPEND classes vtkF3DAndroidLogOutputWindow) endif() diff --git a/vtkext/private/module/vtkF3DGLXRenderWindow.cxx b/vtkext/private/module/vtkF3DGLXRenderWindow.cxx new file mode 100644 index 0000000000..dc2802af53 --- /dev/null +++ b/vtkext/private/module/vtkF3DGLXRenderWindow.cxx @@ -0,0 +1,38 @@ +#include +#include + +#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) +#include +#include +#else +#include +#endif + +#include "vtkF3DGLXRenderWindow.h" + +#include + +//------------------------------------------------------------------------------ +vtkF3DGLXRenderWindow::vtkF3DGLXRenderWindow() = default; + +//------------------------------------------------------------------------------ +vtkF3DGLXRenderWindow::~vtkF3DGLXRenderWindow() = default; + +//------------------------------------------------------------------------------ +vtkF3DGLXRenderWindow* vtkF3DGLXRenderWindow::New() +{ + // Check if the X display is available + Display* dpy = XOpenDisplay(nullptr); + if (dpy == nullptr) + { + return nullptr; + } + XCloseDisplay(dpy); + +#if VTK_VERSION_NUMBER >= VTK_VERSION_CHECK(9, 3, 20240914) + // Load core glx functions + gladLoaderLoadGLX(nullptr, 0); +#endif + + VTK_STANDARD_NEW_BODY(vtkF3DGLXRenderWindow); +} diff --git a/vtkext/private/module/vtkF3DGLXRenderWindow.h b/vtkext/private/module/vtkF3DGLXRenderWindow.h new file mode 100644 index 0000000000..0177ff055f --- /dev/null +++ b/vtkext/private/module/vtkF3DGLXRenderWindow.h @@ -0,0 +1,25 @@ +/** + * @class vtkF3DGLXRenderWindow + * @brief GLX context render window + */ + +#ifndef vtkF3DGLXRenderWindow_h +#define vtkF3DGLXRenderWindow_h + +#include "vtkXOpenGLRenderWindow.h" + +class vtkF3DGLXRenderWindow : public vtkXOpenGLRenderWindow +{ +public: + static vtkF3DGLXRenderWindow* New(); + vtkTypeMacro(vtkF3DGLXRenderWindow, vtkXOpenGLRenderWindow); + +protected: + vtkF3DGLXRenderWindow(); + ~vtkF3DGLXRenderWindow() override; + +private: + vtkF3DGLXRenderWindow(const vtkF3DGLXRenderWindow&) = delete; + void operator=(const vtkF3DGLXRenderWindow&) = delete; +}; +#endif // vtkF3DGLXRenderWindow_h