Skip to content
Snippets Groups Projects
Commit 04661f4b authored by Jaswant Panchumarti (Kitware)'s avatar Jaswant Panchumarti (Kitware)
Browse files

Enable runtime detection of GLX, EGL and OSMesa for OpenGL context

- closes #18547
- closes #19383
- Use glad instead of glew for loading GL extension functions
because GLEW has trouble using GLX and EGL in the same build.
- Replaces the VTK::glew module with VTK::glad.
- Removed the utility VTK::opengl module because it is unnecessary
after the changes made to vtkOpenGLOptions.cmake
- OpenGL is now loaded at runtime in desktop platforms.
- For mobile and webassembly, when VTK_OPENGL_USE_GLES is ON,
glad finds and links to the OpenGL::GLES3 library.
- Support for OSMesa is always available from VTK. Users must make
sure the libOSMesa.so or osmesa.dll is installed.
- Support for EGL is always available from VTK in Linux and Android.
Users must make sure libEGL is installed.
- On platforms where multiple render window backends are possible, the
vtkOpenGLRenderWindow is made the default factory override and it's
New method implements runtime tests to determine what render windows
can work. It basically constructs the platform implementation render
window, attempts to initialize it and checks whether it was
successfully intialized.
- The X OpenGL render window class was updated to not call abort.
It also print warnings instead of errors when it fails to open X
display. This allows us to safely test support for GLX at runtime.
- The new environment variable VTK_DEFAULT_OPENGL_WINDOW
can optionally be used to force a render window subclass
at runtime. It is useful to debug support for a fallback render
window on different system configuration.
- Remove usage of unnecessary CMake flag VTK_OPENGL_HAS_MESA.
- Since there is no compile time depedency for OSMesa in VTK,
this commit makes VTK act as if it can always use OSMesa,
obviously when the system executing VTK code has osmesa installed.
- ci scripts will be adjusted in next commits
parent 1659b640
No related branches found
No related tags found
No related merge requests found
Showing
with 150 additions and 84 deletions
......@@ -15,12 +15,8 @@ The following variables are provided by this module:
* `VTK_LEGACY_REMOVE`: Whether VTK's deprecated APIs are
compiled out or not.
* `VTK_HAS_VTKm`: If VTK provides VTK-m.
* `VTK_OPENGL_HAS_EGL`: If VTK::opengl uses EGL. Only provided if the
`VTK::opengl` target exists.
* `VTK_OPENGL_HAS_OSMESA`: If VTK::opengl uses OSMESA. Only provided if the
`VTK::opengl` target exists.
* `VTK_USE_X`: If VTK uses X windows. Only provided if the
`VTK::opengl` target exists.
* `VTK_OPENGL_HAS_EGL`: If VTK can use EGL for OpenGL context.
* `VTK_USE_X`: If VTK uses X windows.
* `VTK_PYTHON_VERSION`: The major version of Python used by VTK. Empty if
Python support is not available.
* `VTK_WRAP_PYTHON`: If VTK itself provides Python wrapping. If so, the
......@@ -187,11 +183,8 @@ else ()
unset(Python3_FIND_STRATEGY)
endif ()
if (TARGET VTK::opengl)
set(VTK_OPENGL_HAS_EGL "@VTK_OPENGL_HAS_EGL@")
set(VTK_OPENGL_HAS_OSMESA "@VTK_OPENGL_HAS_OSMESA@")
set(VTK_USE_X "@VTK_USE_X@")
endif ()
set(VTK_OPENGL_HAS_EGL "@VTK_OPENGL_HAS_EGL@")
set(VTK_USE_X "@VTK_USE_X@")
if (TARGET VTK::RenderingVR)
set("${CMAKE_FIND_PACKAGE_NAME}_ENABLE_VR_COLLABORATION" "@VTK_ENABLE_VR_COLLABORATION@")
......
......@@ -35,14 +35,6 @@ endif ()
# being used, we define VTK_OPENGL_HAS_<feature> options. These are not to be
# treated as mutually exclusive.
#-----------------------------------------------------------------------------
# OSMesa variables
#-----------------------------------------------------------------------------
# OpenGL implementation supports OSMesa for creating offscreen context.
option(VTK_OPENGL_HAS_OSMESA
"The OpenGL library being used supports offscreen Mesa (OSMesa)" OFF)
mark_as_advanced(VTK_OPENGL_HAS_OSMESA)
#-----------------------------------------------------------------------------
# GLES variables
#-----------------------------------------------------------------------------
......@@ -53,6 +45,8 @@ if (ANDROID)
set(default_has_egl ON)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
set(VTK_OPENGL_USE_GLES ON)
elseif (UNIX AND NOT APPLE)
set(default_has_egl ON)
else ()
# OpenGLES implementation.
option(VTK_OPENGL_USE_GLES "Use the OpenGL ES API" OFF)
......@@ -62,8 +56,8 @@ endif ()
#-----------------------------------------------------------------------------
# EGL variables
#-----------------------------------------------------------------------------
# OpenGL implementation supports EGL for creating offscreen context.
option(VTK_OPENGL_HAS_EGL "The OpenGL library being used supports EGL" "${default_has_egl}")
# Whether VTK should attempt to use EGL for creating offscreen context.
option(VTK_OPENGL_HAS_EGL "Enable EGL support for creating GPU accelerated offscreen context" "${default_has_egl}")
mark_as_advanced(VTK_OPENGL_HAS_EGL)
set(VTK_DEFAULT_EGL_DEVICE_INDEX "0" CACHE STRING
......@@ -80,19 +74,18 @@ mark_as_advanced(VTK_DEFAULT_RENDER_WINDOW_OFFSCREEN)
#-----------------------------------------------------------------------------
set(vtk_can_do_offscreen FALSE)
set(vtk_can_do_onscreen FALSE)
set(vtk_can_do_headless FALSE)
# VTK OSMesa support is always built on major desktop platforms because it's far cheaper and simpler
# to just build software-only support rather than making `vtkOpenGLRenderWindow` handle situations when
# neither the hardware accelerated on/offscreen backends, nor the software-only backends are available.
set(vtk_can_do_headless TRUE)
if (VTK_USE_WIN32_OPENGL OR VTK_OPENGL_HAS_OSMESA OR VTK_OPENGL_HAS_EGL OR VTK_USE_SDL2)
if (VTK_USE_WIN32_OPENGL OR VTK_OPENGL_HAS_EGL OR VTK_USE_SDL2)
set(vtk_can_do_offscreen TRUE)
endif ()
if (VTK_USE_WIN32_OPENGL OR VTK_USE_COCOA OR VTK_USE_X OR VTK_USE_SDL2) # XXX: See error message below.
set(vtk_can_do_onscreen TRUE)
endif ()
if (VTK_OPENGL_HAS_OSMESA OR VTK_OPENGL_HAS_EGL)
set(vtk_can_do_headless TRUE)
endif ()
# iOS does not use EGL
if (APPLE_IOS)
set(vtk_can_do_offscreen TRUE)
......@@ -109,30 +102,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
endif ()
endif ()
if (NOT vtk_can_do_onscreen AND NOT vtk_can_do_offscreen)
message(FATAL_ERROR
"VTK current build configuration is not satisfiable as it supports neither onscreen "
"nor offscreen rendering. Make sure to set to ON at least one of the following to "
"be able to configure: `VTK_USE_X`, `VTK_USE_COCOA`, `VTK_OPENGL_HAS_OSMESA`, "
"`VTK_OPENGL_HAS_EGL` or `VTK_USE_SDL2`.")
endif ()
if (VTK_OPENGL_HAS_OSMESA AND VTK_OPENGL_HAS_EGL)
message(FATAL_ERROR
"`VTK_OPENGL_HAS_OSMESA` and `VTK_OPENGL_HAS_EGL` option can't be both "
"set to `ON`. The current build configuration is not satisfiable. "
"Please set to `OFF` any of these two.")
endif ()
if (VTK_OPENGL_HAS_OSMESA AND vtk_can_do_onscreen)
message(FATAL_ERROR
"The `VTK_OPENGL_HAS_OSMESA` can't be set to `ON` if any of the following is true: "
"`VTK_USE_WIN32_OPENGL`, `VTK_USE_COCOA` is `ON`, or `VTK_USE_X` is "
"`ON` or `VTK_USE_SDL2` is `ON`. OSMesa does not support on-screen "
"rendering and VTK's OpenGL selection is at build time, so the current "
"build configuration is not satisfiable.")
endif ()
cmake_dependent_option(
VTK_USE_OPENGL_DELAYED_LOAD
"Use delay loading for OpenGL"
......
......@@ -22,7 +22,8 @@ endif ()
if (TARGET VTK::RenderingOpenGL2)
set(has_onscreen OFF)
set(has_offscreen OFF)
set(has_offscreen ON)
list(APPEND vtk_features "rendering-offscreen-osmesa")
if (VTK_USE_X)
list(APPEND vtk_features "rendering-onscreen-x11")
set(has_onscreen ON)
......@@ -35,10 +36,6 @@ if (TARGET VTK::RenderingOpenGL2)
list(APPEND vtk_features "rendering-onscreen-windows")
set(has_onscreen ON)
endif ()
if (VTK_OPENGL_HAS_OSMESA)
list(APPEND vtk_features "rendering-offscreen-osmesa")
set(has_offscreen ON)
endif ()
if (has_onscreen)
list(APPEND vtk_features "rendering-onscreen")
......
......@@ -29,13 +29,9 @@ used by downstream projects in headless, CI-like environments or cloud
application deployments, preventing the need to install any addition system
packages.
To install the **OSMesa variant** from the latest release
```
pip install --extra-index-url https://wheels.vtk.org vtk-osmesa
```
For more information see [here](https://discourse.vtk.org/t/status-update-vtk-python-wheels/11212).
:::{versionchanged} 9.4
As of VTK 9.4, OSMesa and EGL support are included by default in the `vtk` wheels and can be selected at runtime. The `vtk-osmesa` wheels are no longer provided, and it is no longer necessary to install `vtk-osmesa`.
:::
```{note}
conda-forge packages are also [available](https://anaconda.org/conda-forge/vtk) and maintained by the community.
......
......@@ -32,14 +32,13 @@ When generating a wheel, you can modify the distribution name and/or add a
suffix to the wheel version string.
By default, the distribution name is `vtk` though you can add a suffix via the
`VTK_DIST_NAME_SUFFIX` CMake variable (e.g., set `VTK_DIST_NAME_SUFFIX` to
`'osmesa'` to have the distribution name be `vtk_osmesa`). An underscore (`_`)
character is automatically placed between `vtk` and the value
`VTK_DIST_NAME_SUFFIX` CMake variable (e.g., set `VTK_DIST_NAME_SUFFIX`).
An underscore (`_`) character is automatically placed between `vtk` and the value
of `VTK_DIST_NAME_SUFFIX`. Please use `_` characters for further delimination in
the suffix value. Example setting:
```cmake
set(VTK_DIST_NAME_SUFFIX "osmesa" CACHE STRING "")
set(VTK_DIST_NAME_SUFFIX "foo" CACHE STRING "")
```
By default (outside of a CI release build), `dev0` is appended to the version of
......
......@@ -13,6 +13,7 @@ marshalling_hints
object_manager
object_serialization
PythonWrappers
runtime_settings
WrappingTools
migration_guides/index
```
# Runtime settings
## OpenGL
On Linux and Windows, VTK will attempt to detect support for an OpenGL context backend at runtime
and create an appropriate subclass of `vtkOpenGLRenderWindow`. You can override this process by
specifying an environment variable `VTK_DEFAULT_OPENGL_WINDOW`. The possible values
are:
1. `vtkXOpenGLRenderWindow` (Linux; applicable only when `VTK_USE_X` is `ON`, which is the default setting)
2. `vtkWin32OpenGLRenderWindow` (Windows; applicable only when `VTK_USE_WIN32_OPENGL` is `ON`, which is the default setting)
3. `vtkEGLRenderWindow` (applicable only when `VTK_OPENGL_HAS_EGL` is `ON`, which is the default setting)
4. `vtkOSOpenGLRenderWindow` (OSMesa, requires that `osmesa.dll` or `libOSMesa.so` is installed)
Note: VTK does **not** support OSMesa on macOS, iOS, Android and WebAssembly platforms.
......@@ -55,28 +55,44 @@ Less common, but variables which may be of interest to some:
* `VTK_TESTING_WASM_ENGINE_ARGUMENTS` (default ``):
Space separated arguments passed to the wasm runtime executable.
OpenGL-related options:
## OpenGL related build options:
Note that if OpenGL is used, there must be a "sensible" setup. Sanity checks
exist to make sure a broken build is not being made. Essentially:
When OpenGL is used, a valid rendering environment (e.g., X, Cocoa, SDL2, OSMesa, EGL) must be available.
Sanity checks are in place to prevent a broken build.
- at least one rendering environment (X, Cocoa, SDL2, OSMesa, EGL, etc.) must
be available;
- OSMesa and EGL conflict with each other; and
- OSMesa only supports off-screen rendering and is therefore incompatible with
Cocoa, X, and SDL2.
For specific platforms:
* Android: `vtkEGLRenderWindow` is the default.
* macOS: `vtkCocoaRenderWindow` is the default.
* iOS: `vtkIOSRenderWindow` is the default.
* WebAssembly: `vtkWebAssemblyOpenGLRenderWindow` is the default.
Please learn more about how you can influence the render window selection process in [](/advanced/runtime_settings.md#opengl)
## Additional Rendering related build options:
On Linux, the order of render window attempts is:
1. `vtkXOpenGLRenderWindow`
2. `vtkEGLRenderWindow`
3. `vtkOSOpenGLRenderWindow`
On Windows:
* `vtkWin32OpenGLRenderWindow`
* `vtkOSOpenGLRenderWindow`
By default, VTK automatically selects the most appropriate render window class at runtime. This selection process uses the `Initialize` method of the compiled subclass to test whether the chosen setup is valid. If the initialization succeeds, the corresponding render window instance is returned.
The default values of the following CMake `VTK_OPENGL_HAS_*` knobs are already configured so
that the above condition is always met on all supported platforms.
* `VTK_USE_COCOA` (default `ON`; requires macOS): Use Cocoa for
render windows.
* `VTK_USE_X` (default `ON` for Unix-like platforms except macOS,
iOS, and Emscripten, `OFF` otherwise): Use X for render windows.
* `VTK_USE_SDL2` (default `OFF`): Use SDL2 for render windows.
* `VTK_OPENGL_HAS_OSMESA` (default `OFF`): Use to indicate that the
OpenGL library being used supports offscreen Mesa rendering
(OSMesa).
* `VTK_OPENGL_USE_GLES` (default `OFF`; forced `ON` for Android):
Whether to use OpenGL ES API for OpenGL or not.
* `VTK_OPENGL_HAS_EGL` (default `ON` for Android, `OFF` otherwise):
* `VTK_OPENGL_HAS_EGL` (default `ON` for Android and Linux, `OFF` otherwise):
Use to indicate that the OpenGL library being used supports EGL
context management.
* `VTK_DEFAULT_EGL_DEVICE_INDEX` (default `0`; requires
......
......@@ -13,3 +13,7 @@ for more information on using PyVista's wrappings of VTK in Jupyter.
[itkwidgets](https://itkwidgets.readthedocs.io/en/latest) is one example of
a domain-specific Jupyter viewer built on VTK. To try out itkwidgets, check
[this example](https://colab.research.google.com/github/InsightSoftwareConsortium/itkwidgets/blob/main/examples/integrations/vtk/vtkImageData.ipynb).
If you are running the script in a Linux/Windows machine without a display or a GPU, VTK will automatically
select an appropriate OpenGL render window class. Please learn more about how you can influence the
render window selection process in [](/advanced/runtime_settings.md#opengl)
......@@ -60,3 +60,7 @@ That's it ! You may now try some of the
If you are looking for a higher-level interface to VTK in Python, you may want
to explore using [PyVista](https://docs.pyvista.org) as it exposes VTK in a
"Pythonic" manner.
If you are running the script in a Linux/Windows machine without a display or a GPU, VTK will automatically
select an appropriate OpenGL render window class. Please learn more about how you can influence the
render window selection process in [](/advanced/runtime_settings.md#opengl)
# Add support for fallback to EGL or OSMesa in Linux and Windows at runtime
On Linux, VTK will now automatically fallback to `EGL` when there is no X display present or it is not capable of OpenGL.
In case the system is not configured for `EGL`, VTK will fallback to OSMesa. The reason for fallback will be printed to console.
Similarly on Windows, VTK will now automatically fallback to OSMesa if the OpenGL drivers on Windows system are too old i,e do not
support OpenGL 3.2 or higher.
You can learn about the new behavior of the OpenGL build settings in [](https://docs.vtk.org/en/latest/build_instructions/build_settings.html#opengl-related-build-options)
To enable runtime selection, VTK now integrates the modern OpenGL loader library [glad](https://github.com/Dav1dde/glad) as a [third-party project](/developers_guide/git/thirdparty-projects.md), replacing `glew`, which did not support compiling both `GLX` and `EGL` in the same build
If OSMesa is not installed, VTK prints a warning to the console and suggests installing OSMesa.
You can enforce a specific render window by setting the `VTK_DEFAULT_OPENGL_WINDOW` environment variable. See [](https://docs.vtk.org/en/latest/advanced/runtime_settings.html#opengl).
......@@ -20,7 +20,7 @@ PRIVATE_DEPENDS
VTK::CommonDataModel
VTK::CommonExecutionModel
VTK::CommonMath
VTK::glew
VTK::glad
VTK::RenderingCore
TEST_DEPENDS
VTK::CommonSystem
......
......@@ -19,6 +19,7 @@
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLState.h"
//------------------------------------------------------------------------------
......@@ -205,6 +206,22 @@ void QVTKOpenGLNativeWidget::initializeGL()
{
Q_ASSERT(this->RenderWindowAdapter.data() == nullptr);
if (!this->RenderWindow->GetInitialized())
{
auto loadFunc = [](void* userData,
const char* name) -> vtkOpenGLRenderWindow::VTKOpenGLAPIProc {
if (auto* context = reinterpret_cast<QOpenGLContext*>(userData))
{
if (auto* symbol = context->getProcAddress(name))
{
return symbol;
}
}
return nullptr;
};
this->RenderWindow->SetOpenGLSymbolLoader(loadFunc, this->context());
this->RenderWindow->vtkOpenGLRenderWindow::OpenGLInit();
}
auto ostate = this->RenderWindow->GetState();
ostate->Reset();
// By default, Qt sets the depth function to GL_LESS but VTK expects GL_LEQUAL
......
......@@ -192,6 +192,22 @@ void QVTKOpenGLWindow::initializeGL()
{
Q_ASSERT(this->RenderWindowAdapter.data() == nullptr);
if (!this->RenderWindow->GetInitialized())
{
auto loadFunc = [](void* userData,
const char* name) -> vtkOpenGLRenderWindow::VTKOpenGLAPIProc {
if (auto* context = reinterpret_cast<QOpenGLContext*>(userData))
{
if (auto* symbol = context->getProcAddress(name))
{
return symbol;
}
}
return nullptr;
};
this->RenderWindow->SetOpenGLSymbolLoader(loadFunc, this->context());
this->RenderWindow->vtkOpenGLRenderWindow::OpenGLInit();
}
auto ostate = this->RenderWindow->GetState();
ostate->Reset();
// By default, Qt sets the depth function to GL_LESS but VTK expects GL_LEQUAL
......
......@@ -25,7 +25,6 @@ PRIVATE_DEPENDS
VTK::CommonSystem
VTK::FiltersExtraction
VTK::InteractionStyle
VTK::opengl
TEST_DEPENDS
VTK::ChartsCore
VTK::FiltersSources
......
......@@ -18,7 +18,7 @@
#include "vtkVectorOperators.h"
#include <QtWidgets/QWidget>
#include "vtk_glew.h"
#include "vtk_glad.h"
VTK_ABI_NAMESPACE_BEGIN
vtkStandardNewMacro(vtkQWidgetRepresentation);
......
......@@ -166,6 +166,17 @@ public:
vtkWindow->SetMultiSamples(0);
vtkWindow->SetReadyForRendering(false);
vtkWindow->SetFrameBlitModeToNoBlit();
auto loadFunc = [](void*, const char* name) -> vtkOpenGLRenderWindow::VTKOpenGLAPIProc {
if (auto context = QOpenGLContext::currentContext())
{
if (auto* symbol = context->getProcAddress(name))
{
return symbol;
}
}
return nullptr;
};
vtkWindow->SetOpenGLSymbolLoader(loadFunc, nullptr);
vtkNew<QVTKInteractor> iren;
iren->SetRenderWindow(vtkWindow);
vtkNew<vtkInteractorStyleTrackballCamera> style;
......
......@@ -254,6 +254,21 @@ void QQuickVTKRenderWindow::setRenderWindow(vtkGenericOpenGLRenderWindow* renWin
this->m_renderWindow->SetMultiSamples(0);
this->m_renderWindow->SetReadyForRendering(false);
this->m_renderWindow->SetFrameBlitModeToBlitToHardware();
auto loadFunc = [](void*, const char* name) -> vtkOpenGLRenderWindow::VTKOpenGLAPIProc {
if (auto context = QOpenGLContext::currentContext())
{
if (auto* symbol = context->getProcAddress(name))
{
return symbol;
}
}
else
{
vtkGenericWarningMacro(<< "Current opengl context is null!");
}
return nullptr;
};
this->m_renderWindow->SetOpenGLSymbolLoader(loadFunc, nullptr);
vtkNew<QVTKInteractor> iren;
iren->SetRenderWindow(this->m_renderWindow);
......
......@@ -7,7 +7,7 @@ set(CMAKE_AUTORCC ON)
vtk_add_test_cxx(vtkGUISupportQtQuickCxxTests tests
TestQQuickVTKItem_1.cxx
TestQQuickVTKItem_2.cxx
TestQQuickVTKItem_2.cxx,LOOSE_VALID
TestQQuickVTKItem_3.cxx
# VTK_DEPRECATED_IN_9_3_0 applies to these three tests
TestQQuickVTKRenderItem.cxx
......
......@@ -32,4 +32,3 @@ TEST_DEPENDS
VTK::InteractionStyle
VTK::RenderingOpenGL2
VTK::TestingRendering
VTK::opengl
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment