Add GPU rendering detection

parent 40789eb5
#!/usr/bin/env python3
"""
GPU Acceleration Diagnostic Script for Qt WebEngine
Tests GPU functionality and Qt WebEngine GPU acceleration status
"""
import os
import sys
import subprocess
import logging
from pathlib import Path
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def run_command(cmd, shell=False):
"""Run a command and return output"""
try:
result = subprocess.run(cmd, shell=shell, capture_output=True, text=True, timeout=30)
return result.returncode, result.stdout, result.stderr
except subprocess.TimeoutExpired:
return -1, "", "Command timed out"
except Exception as e:
return -1, "", str(e)
def check_nvidia_gpu():
"""Check NVIDIA GPU status"""
logger.info("=== NVIDIA GPU Status ===")
# Check nvidia-smi
code, stdout, stderr = run_command(["nvidia-smi"])
if code == 0:
logger.info("nvidia-smi output:")
logger.info(stdout)
else:
logger.error(f"nvidia-smi failed: {stderr}")
# Check GPU processes
code, stdout, stderr = run_command(["nvidia-smi", "pmon"])
if code == 0:
logger.info("GPU processes:")
logger.info(stdout)
else:
logger.warning(f"Could not check GPU processes: {stderr}")
def check_opengl():
"""Check OpenGL functionality"""
logger.info("=== OpenGL Status ===")
# Check glxinfo
code, stdout, stderr = run_command(["glxinfo", "|", "head", "-20"], shell=True)
if code == 0:
logger.info("OpenGL info:")
logger.info(stdout)
else:
logger.warning(f"glxinfo failed: {stderr}")
# Check if direct rendering is enabled
code, stdout, stderr = run_command(["glxinfo", "|", "grep", "direct"], shell=True)
if code == 0:
logger.info("Direct rendering status:")
logger.info(stdout)
else:
logger.warning("Could not check direct rendering")
def check_qt_environment():
"""Check Qt environment variables"""
logger.info("=== Qt Environment Variables ===")
qt_vars = [
'QT_QPA_PLATFORM',
'QT_DEBUG_PLUGINS',
'QTWEBENGINE_DISABLE_SANDBOX',
'QTWEBENGINE_CHROMIUM_FLAGS',
'QTWEBENGINE_REMOTE_DEBUGGING',
'LIBGL_ALWAYS_SOFTWARE',
'MESA_GL_VERSION_OVERRIDE',
'DISPLAY',
'XDG_SESSION_TYPE'
]
for var in qt_vars:
value = os.environ.get(var)
if value:
logger.info(f"{var}={value}")
else:
logger.info(f"{var}=<not set>")
def check_qt_webengine_gpu():
"""Check Qt WebEngine GPU acceleration"""
logger.info("=== Qt WebEngine GPU Acceleration Test ===")
# Test Qt WebEngine GPU blacklist
test_flags = [
"--disable-gpu",
"--enable-gpu-rasterization",
"--enable-zero-copy",
"--disable-software-rasterizer"
]
for flag in test_flags:
logger.info(f"Testing with flag: {flag}")
# This would require running a Qt app with these flags
def create_qt_gpu_test():
"""Create a minimal Qt WebEngine GPU test"""
logger.info("=== Creating Qt GPU Test Script ===")
test_script = '''
import sys
import os
from PyQt6.QtWidgets import QApplication
from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtCore import QUrl, QTimer
def test_gpu():
app = QApplication(sys.argv)
# Create WebEngine view
view = QWebEngineView()
# Test HTML with WebGL
html = """
<!DOCTYPE html>
<html>
<head>
<title>GPU Test</title>
</head>
<body>
<h1>Qt WebEngine GPU Test</h1>
<canvas id="glcanvas" width="300" height="300"></canvas>
<script>
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (gl) {
console.log('WebGL is supported');
gl.clearColor(0.0, 1.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
document.body.innerHTML += '<p style="color: green;">WebGL: SUCCESS</p>';
} else {
console.log('WebGL is not supported');
document.body.innerHTML += '<p style="color: red;">WebGL: FAILED</p>';
}
</script>
</body>
</html>
"""
view.setHtml(html)
view.show()
# Check GPU processes after 5 seconds
def check_gpu_processes():
import subprocess
try:
result = subprocess.run(['nvidia-smi', 'pmon'], capture_output=True, text=True)
print("GPU processes during Qt WebEngine test:")
print(result.stdout)
except Exception as e:
print(f"Could not check GPU processes: {e}")
QTimer.singleShot(5000, check_gpu_processes)
return app.exec()
if __name__ == "__main__":
sys.exit(test_gpu())
'''
with open('qt_gpu_test.py', 'w') as f:
f.write(test_script)
logger.info("Created qt_gpu_test.py - run this to test Qt WebEngine GPU acceleration")
def check_qt_plugins():
"""Check Qt plugin availability"""
logger.info("=== Qt Plugins Status ===")
try:
from PyQt6.QtCore import QLibraryInfo
plugins_path = QLibraryInfo.path(QLibraryInfo.LibraryPath.PluginsPath)
logger.info(f"Qt plugins path: {plugins_path}")
if os.path.exists(plugins_path):
# List platform plugins
platform_path = os.path.join(plugins_path, 'platforms')
if os.path.exists(platform_path):
platforms = os.listdir(platform_path)
logger.info(f"Available platform plugins: {platforms}")
else:
logger.warning("No platforms plugin directory found")
else:
logger.error("Qt plugins path does not exist")
except Exception as e:
logger.error(f"Could not check Qt plugins: {e}")
def main():
"""Main diagnostic function"""
logger.info("Starting GPU acceleration diagnostics...")
check_nvidia_gpu()
check_opengl()
check_qt_environment()
check_qt_plugins()
create_qt_gpu_test()
logger.info("=== Diagnostic Complete ===")
logger.info("Run 'python qt_gpu_test.py' to test Qt WebEngine GPU acceleration")
logger.info("Check the output for WebGL support and GPU process monitoring")
if __name__ == "__main__":
main()
\ No newline at end of file
...@@ -650,19 +650,59 @@ class OverlayWebView(QWebEngineView): ...@@ -650,19 +650,59 @@ class OverlayWebView(QWebEngineView):
def setup_web_view(self): def setup_web_view(self):
"""Setup web view with proper transparency for overlay""" """Setup web view with proper transparency for overlay"""
logger.debug("OverlayWebView.setup_web_view() - Starting setup") logger.info("OverlayWebView.setup_web_view() - Starting setup")
# Detect Mesa software rendering # Enhanced GPU detection and logging
import os import os
is_mesa = os.environ.get('LIBGL_ALWAYS_SOFTWARE') == '1' or \ is_mesa = os.environ.get('LIBGL_ALWAYS_SOFTWARE') == '1' or \
os.environ.get('MESA_GL_VERSION_OVERRIDE') is not None os.environ.get('MESA_GL_VERSION_OVERRIDE') is not None
# Log GPU-related environment variables
gpu_env_vars = [
'LIBGL_ALWAYS_SOFTWARE',
'MESA_GL_VERSION_OVERRIDE',
'QTWEBENGINE_CHROMIUM_FLAGS',
'QT_QPA_PLATFORM',
'DISPLAY',
'XDG_SESSION_TYPE'
]
logger.info("=== GPU Environment Check ===")
for var in gpu_env_vars:
value = os.environ.get(var)
logger.info(f"{var}: {value if value else '<not set>'}")
# Check for NVIDIA GPU
try:
import subprocess
result = subprocess.run(['nvidia-smi', '--query-gpu=name,memory.total,memory.used', '--format=csv,noheader,nounits'],
capture_output=True, text=True, timeout=5)
if result.returncode == 0:
logger.info(f"NVIDIA GPU detected: {result.stdout.strip()}")
else:
logger.warning("nvidia-smi not available or failed")
except Exception as e:
logger.warning(f"Could not check NVIDIA GPU: {e}")
# Check OpenGL
try:
result = subprocess.run(['glxinfo', '|', 'grep', '"OpenGL renderer"'], shell=True,
capture_output=True, text=True, timeout=5)
if result.returncode == 0:
logger.info(f"OpenGL renderer: {result.stdout.strip()}")
else:
logger.warning("Could not get OpenGL renderer info")
except Exception as e:
logger.warning(f"Could not check OpenGL: {e}")
logger.info(f"Mesa software rendering detection: {is_mesa}")
# Set transparent background on the web page # Set transparent background on the web page
page = self.page() page = self.page()
if is_mesa: if is_mesa:
# Mesa-specific transparency settings # Mesa-specific transparency settings
logger.debug("Mesa software rendering detected - applying Mesa transparency fixes") logger.info("Applying Mesa software rendering transparency fixes")
page.setBackgroundColor(QColor(0, 0, 0, 1)) # Semi-transparent for Mesa page.setBackgroundColor(QColor(0, 0, 0, 1)) # Semi-transparent for Mesa
# Use CSS-based transparency for Mesa # Use CSS-based transparency for Mesa
page.runJavaScript(""" page.runJavaScript("""
...@@ -671,6 +711,7 @@ class OverlayWebView(QWebEngineView): ...@@ -671,6 +711,7 @@ class OverlayWebView(QWebEngineView):
""") """)
else: else:
# Standard hardware transparency # Standard hardware transparency
logger.info("Applying standard hardware transparency")
page.setBackgroundColor(QColor(0, 0, 0, 0)) # Fully transparent page.setBackgroundColor(QColor(0, 0, 0, 0)) # Fully transparent
# Widget should be visible but allow transparency # Widget should be visible but allow transparency
...@@ -689,7 +730,7 @@ class OverlayWebView(QWebEngineView): ...@@ -689,7 +730,7 @@ class OverlayWebView(QWebEngineView):
} }
""") """)
logger.debug(f"OverlayWebView setup completed - Mesa: {is_mesa}, transparency configured") logger.info(f"OverlayWebView setup completed - Mesa: {is_mesa}, transparency configured")
# Setup WebChannel # Setup WebChannel
self.web_channel = QWebChannel() self.web_channel = QWebChannel()
...@@ -701,6 +742,9 @@ class OverlayWebView(QWebEngineView): ...@@ -701,6 +742,9 @@ class OverlayWebView(QWebEngineView):
self.web_channel.registerObject("overlay", self.overlay_channel) self.web_channel.registerObject("overlay", self.overlay_channel)
page.setWebChannel(self.web_channel) page.setWebChannel(self.web_channel)
# Monitor GPU processes after WebEngine initialization
self._monitor_gpu_processes()
# Console override moved to _enable_debug_console to ensure it runs after page load # Console override moved to _enable_debug_console to ensure it runs after page load
# Note: Console message capturing via WebChannel is now handled by JavaScript overrides # Note: Console message capturing via WebChannel is now handled by JavaScript overrides
...@@ -1192,6 +1236,85 @@ class OverlayWebView(QWebEngineView): ...@@ -1192,6 +1236,85 @@ class OverlayWebView(QWebEngineView):
except Exception as e: except Exception as e:
logger.debug(f"Failed to ensure console override: {e}") logger.debug(f"Failed to ensure console override: {e}")
def _monitor_gpu_processes(self):
"""Async GPU process monitoring for usability checking"""
try:
logger.debug("Starting async GPU process monitoring")
# Use QTimer for non-blocking GPU monitoring
from PyQt6.QtCore import QTimer
def check_gpu_async():
"""Non-blocking GPU process check"""
try:
import subprocess
import os
# Check for GPU processes that might interfere with video playback
gpu_processes = []
# Check for known GPU-intensive processes
processes_to_check = ['chrome', 'chromium', 'firefox', 'opera', 'safari']
for proc_name in processes_to_check:
try:
# Use pgrep or tasklist to check for running processes
if os.name == 'nt': # Windows
result = subprocess.run(['tasklist', '/FI', f'IMAGENAME eq {proc_name}.exe'],
capture_output=True, text=True, timeout=2)
if proc_name.lower() in result.stdout.lower():
gpu_processes.append(proc_name)
else: # Unix-like systems
result = subprocess.run(['pgrep', '-f', proc_name],
capture_output=True, text=True, timeout=2)
if result.returncode == 0:
gpu_processes.append(proc_name)
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
# Commands may not be available, continue
pass
if gpu_processes:
logger.info(f"GPU-intensive processes detected: {', '.join(gpu_processes)}")
logger.warning("Multiple GPU processes may impact video playback performance")
else:
logger.debug("No conflicting GPU processes detected")
# Check GPU memory usage if nvidia-smi is available
try:
nvidia_result = subprocess.run(['nvidia-smi', '--query-gpu=memory.used,memory.total',
'--format=csv,noheader,nounits'],
capture_output=True, text=True, timeout=3)
if nvidia_result.returncode == 0:
lines = nvidia_result.stdout.strip().split('\n')
for i, line in enumerate(lines):
if ',' in line:
used, total = line.split(',')
used = int(used.strip())
total = int(total.strip())
usage_percent = (used / total) * 100 if total > 0 else 0
logger.debug(f"GPU {i} memory usage: {used}MB/{total}MB ({usage_percent:.1f}%)")
if usage_percent > 90:
logger.warning(f"GPU {i} memory usage is very high: {usage_percent:.1f}%")
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
# nvidia-smi not available or failed
pass
except Exception as e:
logger.debug(f"GPU monitoring check failed: {e}")
# Schedule the first check after a delay, then periodically
QTimer.singleShot(2000, check_gpu_async) # First check after 2 seconds
# Set up periodic monitoring every 30 seconds
self._gpu_monitor_timer = QTimer()
self._gpu_monitor_timer.timeout.connect(check_gpu_async)
self._gpu_monitor_timer.start(30000) # 30 seconds
logger.debug("GPU process monitoring scheduled")
except Exception as e:
logger.error(f"Failed to start GPU process monitoring: {e}")
# Removed _on_javaScript_console_message method as console capturing now uses WebChannel # Removed _on_javaScript_console_message method as console capturing now uses WebChannel
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment