mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-30 03:10:29 -07:00
buildin opengl info detection
This commit is contained in:
parent
632403781f
commit
bc5ef7e81a
3 changed files with 373 additions and 33 deletions
|
|
@ -9,11 +9,21 @@ OrcaSlicer now includes an automatic graphics backend detection and configuratio
|
|||
|
||||
## Problem Solved
|
||||
|
||||
Previously, users had to manually set environment variables like `GBM_BACKEND=dri` to make the 3D view work properly on systems like Kubuntu 25.04. This was especially problematic for:
|
||||
Previously, users had to manually set environment variables like `GBM_BACKEND=dri` to make the 3D view work properly on systems like Kubuntu 25.04. Additionally, the system relied on external command-line tools for graphics detection. This was especially problematic for:
|
||||
|
||||
- **Wayland sessions** with NVIDIA drivers
|
||||
- **Newer graphics drivers** that require specific configurations
|
||||
- **Different graphics hardware** (NVIDIA, AMD, Intel) requiring different settings
|
||||
- **Containerized environments** (Docker, Flatpak, AppImage) where external tools might not be available
|
||||
- **Systems without mesa-utils packages** installed
|
||||
|
||||
## Improvements in Current Version
|
||||
|
||||
### Direct OpenGL Detection
|
||||
- **No External Dependencies**: Graphics detection now uses direct OpenGL API calls instead of relying on `glxinfo`/`eglinfo` commands
|
||||
- **Container-Friendly**: Works reliably in Docker, Flatpak, and AppImage environments
|
||||
- **Better Performance**: Eliminates subprocess overhead from command execution
|
||||
- **Enhanced Reliability**: Direct API calls are more dependable than parsing command output
|
||||
|
||||
## How It Works
|
||||
|
||||
|
|
@ -25,6 +35,26 @@ The system automatically detects:
|
|||
- **Graphics Driver**: NVIDIA, AMD, Intel, or Mesa
|
||||
- **Driver Version**: For NVIDIA drivers, detects version to apply appropriate settings
|
||||
|
||||
#### Detection Methodology
|
||||
|
||||
The graphics detection uses a multi-tier approach for maximum reliability:
|
||||
|
||||
1. **Direct OpenGL API Calls (Primary)**
|
||||
- Creates minimal OpenGL contexts using GLX (X11) or EGL (Wayland/headless)
|
||||
- Uses `glGetString(GL_VENDOR)` and `glGetString(GL_RENDERER)` directly
|
||||
- Works reliably in containers and restricted environments
|
||||
- No dependency on external command-line tools
|
||||
|
||||
2. **Command-Line Tools (Fallback)**
|
||||
- Uses `glxinfo` and `eglinfo` commands only if direct detection fails
|
||||
- Provides compatibility with older detection methods
|
||||
- Tools are no longer required to be installed
|
||||
|
||||
3. **Hardware-Based Detection (Final Fallback)**
|
||||
- Reads PCI vendor IDs from `/sys/class/drm/`
|
||||
- Uses `nvidia-smi` for NVIDIA-specific detection
|
||||
- Filesystem-based detection methods
|
||||
|
||||
### 2. Smart Configuration
|
||||
|
||||
Based on the detected environment, the system applies optimal settings:
|
||||
|
|
@ -112,13 +142,16 @@ Common log messages:
|
|||
|
||||
The system now includes improved error handling and validation:
|
||||
|
||||
#### Command Execution Errors
|
||||
- `GraphicsBackendManager: Failed to execute command: glxinfo`
|
||||
#### Graphics Detection Errors
|
||||
- `GraphicsBackendManager: Direct OpenGL detection failed, falling back to command-line tools`
|
||||
- `GraphicsBackendManager: Failed to create or make current OpenGL context`
|
||||
- `GraphicsBackendManager: Command failed with status 127: nvidia-smi`
|
||||
- `GraphicsBackendManager: Command returned no output: eglinfo`
|
||||
- `GraphicsBackendManager: glGetString returned null pointers`
|
||||
|
||||
#### Driver Detection Fallbacks
|
||||
- `GraphicsBackendManager: GLX/EGL detection failed, trying glxinfo fallback`
|
||||
#### Driver Detection Methods
|
||||
- `GraphicsBackendManager: Successfully retrieved OpenGL info directly`
|
||||
- `GraphicsBackendManager: Direct OpenGL and GLX/EGL detection failed, trying glxinfo fallback`
|
||||
- `GraphicsBackendManager: Detected NVIDIA driver via glxinfo final fallback`
|
||||
- `GraphicsBackendManager: Detected NVIDIA driver via nvidia-smi fallback`
|
||||
- `GraphicsBackendManager: Failed to detect graphics driver, using Mesa as fallback`
|
||||
|
||||
|
|
@ -134,16 +167,20 @@ The system now includes improved error handling and validation:
|
|||
|
||||
### Troubleshooting Common Issues
|
||||
|
||||
#### 1. Missing System Tools
|
||||
If you see "Failed to execute command" messages, install missing tools:
|
||||
```bash
|
||||
# For Ubuntu/Debian
|
||||
sudo apt install mesa-utils glxinfo
|
||||
#### 1. Graphics Detection Issues
|
||||
The system now uses direct OpenGL API calls as the primary detection method, eliminating the need for external tools in most cases.
|
||||
|
||||
# For Arch Linux
|
||||
sudo pacman -S mesa-utils glxinfo
|
||||
If direct detection fails and you see "glxinfo fallback" messages, you can optionally install tools for debugging:
|
||||
```bash
|
||||
# For Ubuntu/Debian (optional, for debugging only)
|
||||
sudo apt install mesa-utils
|
||||
|
||||
# For Arch Linux (optional, for debugging only)
|
||||
sudo pacman -S mesa-utils
|
||||
```
|
||||
|
||||
**Note**: These tools are no longer required for normal operation as the system uses direct OpenGL API calls.
|
||||
|
||||
#### 2. Driver Detection Failures
|
||||
If driver detection fails, check:
|
||||
```bash
|
||||
|
|
@ -153,7 +190,8 @@ nvidia-smi
|
|||
# Check graphics hardware
|
||||
lspci | grep -i vga
|
||||
|
||||
# Check OpenGL information
|
||||
# Check OpenGL information (the system now does this automatically via API calls)
|
||||
# For manual checking, you can still use:
|
||||
glxinfo | grep "OpenGL vendor"
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,19 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pwd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// Thread safety for OpenGL detection operations
|
||||
std::mutex GraphicsBackendManager::opengl_detection_mutex_;
|
||||
|
||||
GraphicsBackendManager& GraphicsBackendManager::get_instance()
|
||||
{
|
||||
static GraphicsBackendManager instance;
|
||||
|
|
@ -79,7 +87,8 @@ GraphicsBackendManager::GraphicsDriver GraphicsBackendManager::detect_graphics_d
|
|||
return container_driver;
|
||||
}
|
||||
|
||||
// Try to get OpenGL vendor and renderer info
|
||||
// Try to get OpenGL vendor and renderer info using direct OpenGL API calls
|
||||
// This creates minimal OpenGL contexts (GLX/EGL) and uses glGetString() directly
|
||||
std::string glx_info = get_glx_info();
|
||||
std::string egl_info = get_egl_info();
|
||||
|
||||
|
|
@ -124,29 +133,29 @@ GraphicsBackendManager::GraphicsDriver GraphicsBackendManager::detect_graphics_d
|
|||
return GraphicsDriver::Mesa;
|
||||
}
|
||||
|
||||
// Try to run glxinfo as fallback (may not work in containers)
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: GLX/EGL detection failed, trying glxinfo fallback";
|
||||
// Try to run glxinfo as final fallback (may not work in containers)
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: Direct OpenGL and GLX/EGL detection failed, trying glxinfo fallback";
|
||||
std::string glx_output = execute_command("glxinfo 2>/dev/null | grep 'OpenGL vendor\\|OpenGL renderer'");
|
||||
if (!glx_output.empty()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: glxinfo output: " << glx_output.substr(0, 200);
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: glxinfo fallback output: " << glx_output.substr(0, 200);
|
||||
|
||||
if (boost::icontains(glx_output, "nvidia")) {
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected NVIDIA driver via glxinfo fallback";
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected NVIDIA driver via glxinfo final fallback";
|
||||
return GraphicsDriver::NVIDIA;
|
||||
} else if (boost::icontains(glx_output, "amd") || boost::icontains(glx_output, "radeon")) {
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected AMD driver via glxinfo fallback";
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected AMD driver via glxinfo final fallback";
|
||||
return GraphicsDriver::AMD;
|
||||
} else if (boost::icontains(glx_output, "intel")) {
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected Intel driver via glxinfo fallback";
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected Intel driver via glxinfo final fallback";
|
||||
return GraphicsDriver::Intel;
|
||||
} else if (boost::icontains(glx_output, "mesa")) {
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected Mesa driver via glxinfo fallback";
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Detected Mesa driver via glxinfo final fallback";
|
||||
return GraphicsDriver::Mesa;
|
||||
}
|
||||
}
|
||||
|
||||
// Try additional fallback methods
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: glxinfo fallback failed, trying additional methods";
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: All OpenGL detection methods failed, trying hardware-based fallbacks";
|
||||
|
||||
// Check for NVIDIA using nvidia-smi
|
||||
std::string nvidia_check = execute_command("nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -n1");
|
||||
|
|
@ -366,10 +375,259 @@ bool GraphicsBackendManager::is_nvidia_driver_newer_than(int major_version)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to query OpenGL strings and check for errors.
|
||||
*
|
||||
* @param context_type String describing the context type for logging (e.g., "GLX", "EGL")
|
||||
* @return String containing OpenGL vendor, renderer, and version information,
|
||||
* or empty string if detection fails or errors occur
|
||||
*/
|
||||
std::string GraphicsBackendManager::query_opengl_strings(const std::string& context_type)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Query OpenGL information
|
||||
const GLubyte* vendor = glGetString(GL_VENDOR);
|
||||
GLenum error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: OpenGL error after glGetString(GL_VENDOR): " << error;
|
||||
return "";
|
||||
}
|
||||
|
||||
const GLubyte* renderer = glGetString(GL_RENDERER);
|
||||
error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: OpenGL error after glGetString(GL_RENDERER): " << error;
|
||||
return "";
|
||||
}
|
||||
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
error = glGetError();
|
||||
if (error != GL_NO_ERROR) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: OpenGL error after glGetString(GL_VERSION): " << error;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (vendor && renderer && version) {
|
||||
std::string result = "OpenGL vendor string: " + std::string(reinterpret_cast<const char*>(vendor)) + "\n";
|
||||
result += "OpenGL renderer string: " + std::string(reinterpret_cast<const char*>(renderer)) + "\n";
|
||||
result += "OpenGL version string: " + std::string(reinterpret_cast<const char*>(version));
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "GraphicsBackendManager: Successfully retrieved OpenGL info via " << context_type;
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: Vendor: " << reinterpret_cast<const char*>(vendor);
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: Renderer: " << reinterpret_cast<const char*>(renderer);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: glGetString returned null pointers via " << context_type;
|
||||
return "";
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct OpenGL graphics detection using native API calls.
|
||||
*
|
||||
* This function creates minimal OpenGL contexts to query graphics information directly
|
||||
* via OpenGL API calls, eliminating dependency on external tools like glxinfo/eglinfo.
|
||||
*
|
||||
* Detection process:
|
||||
* 1. Try GLX context creation (for X11 environments)
|
||||
* 2. Try EGL context creation (for Wayland/headless environments)
|
||||
* 3. Query glGetString(GL_VENDOR/GL_RENDERER/GL_VERSION)
|
||||
* 4. Clean up all created resources
|
||||
*
|
||||
* Benefits:
|
||||
* - Works reliably in containers (Docker, Flatpak, AppImage)
|
||||
* - No external command dependencies
|
||||
* - Better error handling and logging
|
||||
* - Supports both X11 and Wayland
|
||||
*
|
||||
* @return String containing OpenGL vendor, renderer, and version information,
|
||||
* or empty string if detection fails
|
||||
*/
|
||||
std::string GraphicsBackendManager::get_opengl_info_direct()
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Thread safety: X11 and EGL operations are not thread-safe
|
||||
std::lock_guard<std::mutex> lock(opengl_detection_mutex_);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: Attempting direct OpenGL detection";
|
||||
|
||||
std::string result;
|
||||
Display* display = nullptr;
|
||||
GLXContext context = nullptr;
|
||||
Window window = 0;
|
||||
Colormap colormap = 0;
|
||||
XVisualInfo* visual = nullptr;
|
||||
|
||||
try {
|
||||
// Try X11 first
|
||||
display = XOpenDisplay(nullptr);
|
||||
if (display) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: X11 display opened successfully";
|
||||
|
||||
// Get a visual
|
||||
int screen = DefaultScreen(display);
|
||||
int attribs[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 12,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None
|
||||
};
|
||||
|
||||
visual = glXChooseVisual(display, screen, attribs);
|
||||
if (visual) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: GLX visual chosen successfully";
|
||||
|
||||
// Create a minimal window
|
||||
Window root = RootWindow(display, screen);
|
||||
colormap = XCreateColormap(display, root, visual->visual, AllocNone);
|
||||
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.colormap = colormap;
|
||||
attrs.event_mask = 0;
|
||||
|
||||
window = XCreateWindow(display, root, 0, 0, 1, 1, 0,
|
||||
visual->depth, InputOutput, visual->visual,
|
||||
CWColormap | CWEventMask, &attrs);
|
||||
|
||||
if (window) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: X11 window created successfully";
|
||||
|
||||
// Create OpenGL context
|
||||
context = glXCreateContext(display, visual, nullptr, GL_TRUE);
|
||||
if (context && glXMakeCurrent(display, window, context)) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: OpenGL context created and made current";
|
||||
|
||||
// Query OpenGL information using helper function
|
||||
result = query_opengl_strings("GLX");
|
||||
|
||||
glXMakeCurrent(display, None, nullptr);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to create or make current OpenGL context";
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to create X11 window";
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to choose GLX visual";
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: X11 display not available, trying EGL";
|
||||
|
||||
// Try EGL as fallback (for Wayland or headless)
|
||||
EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (egl_display != EGL_NO_DISPLAY) {
|
||||
EGLint major, minor;
|
||||
if (eglInitialize(egl_display, &major, &minor)) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: EGL initialized successfully";
|
||||
|
||||
EGLint config_attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 8,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
if (eglChooseConfig(egl_display, config_attribs, &config, 1, &num_configs) && num_configs > 0) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: EGL config chosen successfully";
|
||||
|
||||
// Create a pbuffer surface
|
||||
EGLint pbuffer_attribs[] = {
|
||||
EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLSurface surface = eglCreatePbufferSurface(egl_display, config, pbuffer_attribs);
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: EGL pbuffer surface created successfully";
|
||||
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
EGLContext egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, nullptr);
|
||||
|
||||
if (egl_context != EGL_NO_CONTEXT && eglMakeCurrent(egl_display, surface, surface, egl_context)) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: EGL context created and made current";
|
||||
|
||||
// Query OpenGL information using helper function
|
||||
result = query_opengl_strings("EGL");
|
||||
|
||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(egl_display, egl_context);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to create or make current EGL context";
|
||||
}
|
||||
|
||||
eglDestroySurface(egl_display, surface);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to create EGL pbuffer surface";
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to choose EGL config";
|
||||
}
|
||||
|
||||
eglTerminate(egl_display);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Failed to initialize EGL";
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: EGL display not available";
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GraphicsBackendManager: Exception during direct OpenGL detection: " << e.what();
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GraphicsBackendManager: Unknown exception during direct OpenGL detection";
|
||||
}
|
||||
|
||||
// Cleanup X11 resources (fixing resource leaks)
|
||||
if (context) {
|
||||
glXDestroyContext(display, context);
|
||||
}
|
||||
if (window && display) {
|
||||
XDestroyWindow(display, window);
|
||||
}
|
||||
if (colormap && display) {
|
||||
XFreeColormap(display, colormap);
|
||||
}
|
||||
if (visual) {
|
||||
XFree(visual);
|
||||
}
|
||||
if (display) {
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
if (result.empty()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "GraphicsBackendManager: Direct OpenGL detection failed, falling back to command-line tools";
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
BOOST_LOG_TRIVIAL(debug) << "GraphicsBackendManager: Direct OpenGL detection not available on this platform";
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string GraphicsBackendManager::get_glx_info()
|
||||
{
|
||||
// In containers, this might not work or might interfere with initialization
|
||||
// Use safer detection methods first
|
||||
// Primary method: Use direct OpenGL API calls via GLX/EGL contexts
|
||||
// This avoids dependency on external glxinfo command and works better in containers
|
||||
std::string direct_info = get_opengl_info_direct();
|
||||
if (!direct_info.empty()) {
|
||||
return direct_info;
|
||||
}
|
||||
|
||||
// Final fallback: Use glxinfo command if direct detection failed
|
||||
// This may not work in containers or restricted environments
|
||||
if (is_running_in_container()) {
|
||||
return "";
|
||||
}
|
||||
|
|
@ -378,8 +636,15 @@ std::string GraphicsBackendManager::get_glx_info()
|
|||
|
||||
std::string GraphicsBackendManager::get_egl_info()
|
||||
{
|
||||
// In containers, this might not work or might interfere with initialization
|
||||
// Use safer detection methods first
|
||||
// Primary method: Use direct OpenGL API calls via EGL contexts
|
||||
// This avoids dependency on external eglinfo command and works better in containers
|
||||
std::string direct_info = get_opengl_info_direct();
|
||||
if (!direct_info.empty()) {
|
||||
return direct_info;
|
||||
}
|
||||
|
||||
// Final fallback: Use eglinfo command if direct detection failed
|
||||
// This may not work in containers or restricted environments
|
||||
if (is_running_in_container()) {
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,30 @@
|
|||
#define slic3r_GraphicsBackendManager_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
/**
|
||||
* GraphicsBackendManager - Automatic Graphics Backend Detection and Configuration
|
||||
*
|
||||
* This class provides automatic detection of graphics hardware and session types,
|
||||
* and applies optimal OpenGL/graphics configurations for Linux systems.
|
||||
*
|
||||
* Key Features:
|
||||
* - Direct OpenGL API-based detection (no external tool dependencies)
|
||||
* - Support for X11 and Wayland sessions
|
||||
* - NVIDIA, AMD, Intel, and Mesa driver detection
|
||||
* - Container-aware detection (Docker, Flatpak, AppImage)
|
||||
* - Automatic environment variable configuration
|
||||
*
|
||||
* Detection Methods (in order of preference):
|
||||
* 1. Direct OpenGL context creation and glGetString() API calls
|
||||
* 2. Container-aware filesystem detection
|
||||
* 3. Command-line tools (glxinfo/eglinfo) as fallback
|
||||
* 4. Hardware-based detection (PCI vendor IDs, nvidia-smi)
|
||||
*/
|
||||
class GraphicsBackendManager
|
||||
{
|
||||
public:
|
||||
|
|
@ -41,13 +61,23 @@ public:
|
|||
|
||||
static GraphicsBackendManager& get_instance();
|
||||
|
||||
// Detect the current graphics environment
|
||||
/**
|
||||
* Detect the current graphics environment using direct OpenGL API calls.
|
||||
* Primary detection method uses glGetString() via minimal GLX/EGL contexts.
|
||||
* Falls back to filesystem and command-line detection if needed.
|
||||
*/
|
||||
GraphicsConfig detect_graphics_environment();
|
||||
|
||||
// Apply graphics configuration
|
||||
/**
|
||||
* Apply graphics configuration by setting appropriate environment variables.
|
||||
* Validates configuration before applying and logs the applied settings.
|
||||
*/
|
||||
void apply_graphics_config(const GraphicsConfig& config);
|
||||
|
||||
// Get recommended configuration for current system
|
||||
/**
|
||||
* Get recommended configuration for current system based on detected hardware
|
||||
* and session type. Uses direct OpenGL detection for optimal compatibility.
|
||||
*/
|
||||
GraphicsConfig get_recommended_config();
|
||||
|
||||
// Check if current configuration is optimal
|
||||
|
|
@ -65,7 +95,7 @@ private:
|
|||
GraphicsBackendManager(const GraphicsBackendManager&) = delete;
|
||||
GraphicsBackendManager& operator=(const GraphicsBackendManager&) = delete;
|
||||
|
||||
// Helper methods
|
||||
// Detection helper methods
|
||||
SessionType detect_session_type();
|
||||
GraphicsDriver detect_graphics_driver();
|
||||
GraphicsDriver detect_graphics_driver_container_aware();
|
||||
|
|
@ -73,12 +103,19 @@ private:
|
|||
std::string read_file_content(const std::string& filepath);
|
||||
std::string get_nvidia_driver_version();
|
||||
bool is_nvidia_driver_newer_than(int major_version);
|
||||
std::string get_glx_info();
|
||||
std::string get_egl_info();
|
||||
|
||||
// Graphics information retrieval (now uses direct OpenGL API calls as primary method)
|
||||
std::string get_glx_info(); // GLX/X11 graphics info (direct OpenGL + fallback)
|
||||
std::string get_egl_info(); // EGL graphics info (direct OpenGL + fallback)
|
||||
std::string get_opengl_info_direct(); // Direct OpenGL detection via GLX/EGL contexts
|
||||
std::string query_opengl_strings(const std::string& context_type); // Helper to query OpenGL info strings
|
||||
void set_environment_variable(const std::string& name, const std::string& value);
|
||||
void unset_environment_variable(const std::string& name);
|
||||
std::string execute_command(const std::string& command);
|
||||
|
||||
// Thread safety for OpenGL operations
|
||||
static std::mutex opengl_detection_mutex_;
|
||||
|
||||
// Configuration templates
|
||||
GraphicsConfig get_nvidia_wayland_config();
|
||||
GraphicsConfig get_nvidia_x11_config();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue