Comprehensive ctypes-based OpenGL binding for Python providing access to OpenGL, GLU, and GLUT functionality
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive error detection and reporting system for OpenGL operations with Python-specific exceptions, context validation, debugging utilities, and configurable error checking for both development and production environments.
PyOpenGL-specific exception hierarchy providing detailed error information with context and debugging support.
class Error(Exception):
"""
Base exception class for all PyOpenGL errors.
Provides foundation for PyOpenGL exception hierarchy.
"""
class GLError(Error):
"""
OpenGL error with detailed context information.
Attributes:
- err: OpenGL error code (GL_INVALID_ENUM, GL_INVALID_VALUE, etc.)
- result: Function return value
- cArguments: Arguments passed to OpenGL function
- name: Name of OpenGL function that caused error
"""
def __init__(self, err: int, result, cArguments: tuple, name: str):
"""
Create OpenGL error with context.
Parameters:
- err: OpenGL error code from glGetError()
- result: Return value from failed function
- cArguments: Function arguments that caused error
- name: OpenGL function name
"""
@property
def description(self) -> str:
"""Get human-readable error description."""
class GLUError(Error):
"""
GLU library specific error.
Raised by GLU utility functions when operations fail.
"""
class GLUTError(Error):
"""
GLUT library specific error.
Raised by GLUT functions for window management failures.
"""
class NoContext(Error):
"""
Exception raised when OpenGL function called without valid context.
This error indicates that an OpenGL function was called before
creating an OpenGL context or after the context was destroyed.
"""
class CopyError(Error):
"""
Exception raised when array copying would occur with ERROR_ON_COPY=True.
This error helps identify performance issues by preventing
automatic data copying that could impact performance.
"""
class NullFunctionError(Error):
"""
Exception raised when calling undefined OpenGL function.
Occurs when trying to call an OpenGL extension function
that is not available on the current system.
"""Core error detection and validation functions with configurable behavior.
def glGetError() -> int:
"""
Get current OpenGL error state.
Returns:
OpenGL error code:
- GL_NO_ERROR (0): No error
- GL_INVALID_ENUM: Invalid enumeration parameter
- GL_INVALID_VALUE: Invalid value parameter
- GL_INVALID_OPERATION: Invalid operation for current state
- GL_STACK_OVERFLOW: Command would overflow matrix stack
- GL_STACK_UNDERFLOW: Command would underflow matrix stack
- GL_OUT_OF_MEMORY: Not enough memory to execute command
"""
def glCheckError():
"""
Check for OpenGL errors and raise GLError if found.
Convenience function that calls glGetError() and raises
appropriate exception if error detected.
Raises:
GLError: If OpenGL error state is set
"""
def clearError():
"""
Clear all pending OpenGL errors.
Calls glGetError() repeatedly until GL_NO_ERROR returned.
"""OpenGL context checking and validation utilities.
def checkContext():
"""
Validate that OpenGL context is available.
Raises:
NoContext: If no valid OpenGL context is current
"""
def hasContext() -> bool:
"""
Check if OpenGL context is available without raising exception.
Returns:
True if valid OpenGL context exists, False otherwise
"""
# Context checking can be enabled globally
import OpenGL
OpenGL.CONTEXT_CHECKING = True # Check context on every GL callExtension and function availability validation.
def checkExtension(extension_name: str) -> bool:
"""
Check if OpenGL extension is available.
Parameters:
- extension_name: Extension name (e.g., "GL_ARB_vertex_buffer_object")
Returns:
True if extension is supported, False otherwise
"""
def checkFunction(function_name: str) -> bool:
"""
Check if OpenGL function is available.
Parameters:
- function_name: Function name (e.g., "glGenBuffers")
Returns:
True if function is available, False otherwise
"""
def requireExtension(extension_name: str):
"""
Require extension to be available.
Parameters:
- extension_name: Required extension name
Raises:
NullFunctionError: If extension is not available
"""Global error checking and logging configuration for performance and debugging control.
# Global configuration flags
import OpenGL
# Enable/disable error checking (default: True)
OpenGL.ERROR_CHECKING = True
# Enable error logging (default: False)
OpenGL.ERROR_LOGGING = True
# Enable context checking on every call (default: False)
# WARNING: Very slow, only for debugging
OpenGL.CONTEXT_CHECKING = True
# Prevent data copying, raise CopyError instead (default: False)
OpenGL.ERROR_ON_COPY = True
# Enable comprehensive call logging (default: False)
# WARNING: Extremely slow, only for detailed debugging
OpenGL.FULL_LOGGING = True
def setErrorChecking(enabled: bool):
"""
Enable or disable error checking globally.
Parameters:
- enabled: True to enable error checking, False to disable
Note: Disabling error checking can significantly improve performance
but makes debugging much more difficult.
"""Utilities for converting error codes to human-readable descriptions.
def errorString(error_code: int) -> str:
"""
Convert OpenGL error code to descriptive string.
Parameters:
- error_code: OpenGL error code from glGetError()
Returns:
Human-readable error description
"""
# Error code constants and descriptions
ERROR_DESCRIPTIONS = {
GL_NO_ERROR: "No error",
GL_INVALID_ENUM: "Invalid enumeration parameter",
GL_INVALID_VALUE: "Invalid value parameter",
GL_INVALID_OPERATION: "Invalid operation for current state",
GL_STACK_OVERFLOW: "Command would overflow matrix stack",
GL_STACK_UNDERFLOW: "Command would underflow matrix stack",
GL_OUT_OF_MEMORY: "Not enough memory to execute command"
}Advanced debugging and diagnostic tools for development.
def debugCallback(source: int, type: int, id: int, severity: int,
length: int, message: str, userParam):
"""
OpenGL debug callback function for GL_ARB_debug_output.
Parameters:
- source: Message source (GL_DEBUG_SOURCE_API, etc.)
- type: Message type (GL_DEBUG_TYPE_ERROR, etc.)
- id: Message identifier
- severity: Message severity (GL_DEBUG_SEVERITY_HIGH, etc.)
- length: Message length
- message: Debug message string
- userParam: User-provided data
"""
def enableDebugOutput():
"""
Enable OpenGL debug output (requires GL_ARB_debug_output).
Sets up debug callback for detailed error reporting.
"""
class CallTracer:
"""
Utility class for tracing OpenGL function calls.
Logs all OpenGL calls with arguments and return values.
"""
def __init__(self, logger=None):
"""
Parameters:
- logger: Python logger instance, or None for default
"""
def enable(self):
"""Enable call tracing."""
def disable(self):
"""Disable call tracing."""from OpenGL.GL import *
from OpenGL import error
# Enable error checking (default)
import OpenGL
OpenGL.ERROR_CHECKING = True
try:
# OpenGL operations
glEnable(GL_DEPTH_TEST)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# This might cause an error
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0,
GL_RGB, GL_UNSIGNED_BYTE, None)
except error.GLError as e:
print(f"OpenGL Error: {e}")
print(f"Error code: {e.err}")
print(f"Function: {e.name}")
print(f"Arguments: {e.cArguments}")# Disable automatic error checking for performance
OpenGL.ERROR_CHECKING = False
# Manual error checking at critical points
def critical_operation():
glGenTextures(1)
# Check for errors manually
error_code = glGetError()
if error_code != GL_NO_ERROR:
print(f"Error after glGenTextures: {error.errorString(error_code)}")
return False
return Truefrom OpenGL import error
def safe_gl_operation():
try:
# Validate context exists
error.checkContext()
# Proceed with OpenGL operations
glClear(GL_COLOR_BUFFER_BIT)
except error.NoContext:
print("No OpenGL context available!")
return False
except error.GLError as e:
print(f"OpenGL operation failed: {e}")
return False
return Truefrom OpenGL import error
from OpenGL.GL import *
def setup_vertex_buffers():
# Check if VBO extension is available
if not error.checkExtension("GL_ARB_vertex_buffer_object"):
print("VBO extension not available")
return False
try:
# Use VBO functions
buffer_id = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, buffer_id[0])
except error.NullFunctionError:
print("VBO functions not available despite extension support")
return False
return Trueimport OpenGL
import os
# Configure error checking based on environment
if os.environ.get('DEBUG', '').lower() == 'true':
# Development configuration
OpenGL.ERROR_CHECKING = True
OpenGL.ERROR_LOGGING = True
OpenGL.CONTEXT_CHECKING = True
print("Debug mode: Full error checking enabled")
else:
# Production configuration
OpenGL.ERROR_CHECKING = False
OpenGL.ERROR_LOGGING = False
OpenGL.CONTEXT_CHECKING = False
print("Production mode: Error checking disabled for performance")def robust_texture_loading(image_data, width, height):
"""Load texture with error recovery."""
try:
# Generate texture
texture_id = glGenTextures(1)[0]
glBindTexture(GL_TEXTURE_2D, texture_id)
# Attempt to load texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, image_data)
return texture_id
except error.GLError as e:
print(f"Texture loading failed: {e}")
# Cleanup on error
if 'texture_id' in locals():
glDeleteTextures([texture_id])
# Try fallback format
try:
texture_id = glGenTextures(1)[0]
glBindTexture(GL_TEXTURE_2D, texture_id)
# Use simpler format
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
GL_RGB, GL_UNSIGNED_BYTE, [255, 255, 255])
print("Using fallback 1x1 white texture")
return texture_id
except error.GLError:
print("Even fallback texture failed!")
return NoneGL_NO_ERROR: int = 0 # No error
GL_INVALID_ENUM: int = 0x0500 # Invalid enumeration parameter
GL_INVALID_VALUE: int = 0x0501 # Invalid value parameter
GL_INVALID_OPERATION: int = 0x0502 # Invalid operation for current state
GL_STACK_OVERFLOW: int = 0x0503 # Command would overflow matrix stack
GL_STACK_UNDERFLOW: int = 0x0504 # Command would underflow matrix stack
GL_OUT_OF_MEMORY: int = 0x0505 # Not enough memory to execute command# Debug sources
GL_DEBUG_SOURCE_API: int
GL_DEBUG_SOURCE_WINDOW_SYSTEM: int
GL_DEBUG_SOURCE_SHADER_COMPILER: int
GL_DEBUG_SOURCE_THIRD_PARTY: int
GL_DEBUG_SOURCE_APPLICATION: int
GL_DEBUG_SOURCE_OTHER: int
# Debug types
GL_DEBUG_TYPE_ERROR: int
GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: int
GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: int
GL_DEBUG_TYPE_PORTABILITY: int
GL_DEBUG_TYPE_PERFORMANCE: int
GL_DEBUG_TYPE_OTHER: int
# Debug severities
GL_DEBUG_SEVERITY_HIGH: int
GL_DEBUG_SEVERITY_MEDIUM: int
GL_DEBUG_SEVERITY_LOW: intInstall with Tessl CLI
npx tessl i tessl/pypi-pyopengl