0
# Error Handling
1
2
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.
3
4
## Capabilities
5
6
### Exception Classes
7
8
PyOpenGL-specific exception hierarchy providing detailed error information with context and debugging support.
9
10
```python { .api }
11
class Error(Exception):
12
"""
13
Base exception class for all PyOpenGL errors.
14
Provides foundation for PyOpenGL exception hierarchy.
15
"""
16
17
class GLError(Error):
18
"""
19
OpenGL error with detailed context information.
20
21
Attributes:
22
- err: OpenGL error code (GL_INVALID_ENUM, GL_INVALID_VALUE, etc.)
23
- result: Function return value
24
- cArguments: Arguments passed to OpenGL function
25
- name: Name of OpenGL function that caused error
26
"""
27
28
def __init__(self, err: int, result, cArguments: tuple, name: str):
29
"""
30
Create OpenGL error with context.
31
32
Parameters:
33
- err: OpenGL error code from glGetError()
34
- result: Return value from failed function
35
- cArguments: Function arguments that caused error
36
- name: OpenGL function name
37
"""
38
39
@property
40
def description(self) -> str:
41
"""Get human-readable error description."""
42
43
class GLUError(Error):
44
"""
45
GLU library specific error.
46
Raised by GLU utility functions when operations fail.
47
"""
48
49
class GLUTError(Error):
50
"""
51
GLUT library specific error.
52
Raised by GLUT functions for window management failures.
53
"""
54
55
class NoContext(Error):
56
"""
57
Exception raised when OpenGL function called without valid context.
58
59
This error indicates that an OpenGL function was called before
60
creating an OpenGL context or after the context was destroyed.
61
"""
62
63
class CopyError(Error):
64
"""
65
Exception raised when array copying would occur with ERROR_ON_COPY=True.
66
67
This error helps identify performance issues by preventing
68
automatic data copying that could impact performance.
69
"""
70
71
class NullFunctionError(Error):
72
"""
73
Exception raised when calling undefined OpenGL function.
74
75
Occurs when trying to call an OpenGL extension function
76
that is not available on the current system.
77
"""
78
```
79
80
### Error Checking Functions
81
82
Core error detection and validation functions with configurable behavior.
83
84
```python { .api }
85
def glGetError() -> int:
86
"""
87
Get current OpenGL error state.
88
89
Returns:
90
OpenGL error code:
91
- GL_NO_ERROR (0): No error
92
- GL_INVALID_ENUM: Invalid enumeration parameter
93
- GL_INVALID_VALUE: Invalid value parameter
94
- GL_INVALID_OPERATION: Invalid operation for current state
95
- GL_STACK_OVERFLOW: Command would overflow matrix stack
96
- GL_STACK_UNDERFLOW: Command would underflow matrix stack
97
- GL_OUT_OF_MEMORY: Not enough memory to execute command
98
"""
99
100
def glCheckError():
101
"""
102
Check for OpenGL errors and raise GLError if found.
103
Convenience function that calls glGetError() and raises
104
appropriate exception if error detected.
105
106
Raises:
107
GLError: If OpenGL error state is set
108
"""
109
110
def clearError():
111
"""
112
Clear all pending OpenGL errors.
113
Calls glGetError() repeatedly until GL_NO_ERROR returned.
114
"""
115
```
116
117
### Context Validation
118
119
OpenGL context checking and validation utilities.
120
121
```python { .api }
122
def checkContext():
123
"""
124
Validate that OpenGL context is available.
125
126
Raises:
127
NoContext: If no valid OpenGL context is current
128
"""
129
130
def hasContext() -> bool:
131
"""
132
Check if OpenGL context is available without raising exception.
133
134
Returns:
135
True if valid OpenGL context exists, False otherwise
136
"""
137
138
# Context checking can be enabled globally
139
import OpenGL
140
OpenGL.CONTEXT_CHECKING = True # Check context on every GL call
141
```
142
143
### Function Availability Checking
144
145
Extension and function availability validation.
146
147
```python { .api }
148
def checkExtension(extension_name: str) -> bool:
149
"""
150
Check if OpenGL extension is available.
151
152
Parameters:
153
- extension_name: Extension name (e.g., "GL_ARB_vertex_buffer_object")
154
155
Returns:
156
True if extension is supported, False otherwise
157
"""
158
159
def checkFunction(function_name: str) -> bool:
160
"""
161
Check if OpenGL function is available.
162
163
Parameters:
164
- function_name: Function name (e.g., "glGenBuffers")
165
166
Returns:
167
True if function is available, False otherwise
168
"""
169
170
def requireExtension(extension_name: str):
171
"""
172
Require extension to be available.
173
174
Parameters:
175
- extension_name: Required extension name
176
177
Raises:
178
NullFunctionError: If extension is not available
179
"""
180
```
181
182
### Error Configuration
183
184
Global error checking and logging configuration for performance and debugging control.
185
186
```python { .api }
187
# Global configuration flags
188
import OpenGL
189
190
# Enable/disable error checking (default: True)
191
OpenGL.ERROR_CHECKING = True
192
193
# Enable error logging (default: False)
194
OpenGL.ERROR_LOGGING = True
195
196
# Enable context checking on every call (default: False)
197
# WARNING: Very slow, only for debugging
198
OpenGL.CONTEXT_CHECKING = True
199
200
# Prevent data copying, raise CopyError instead (default: False)
201
OpenGL.ERROR_ON_COPY = True
202
203
# Enable comprehensive call logging (default: False)
204
# WARNING: Extremely slow, only for detailed debugging
205
OpenGL.FULL_LOGGING = True
206
207
def setErrorChecking(enabled: bool):
208
"""
209
Enable or disable error checking globally.
210
211
Parameters:
212
- enabled: True to enable error checking, False to disable
213
214
Note: Disabling error checking can significantly improve performance
215
but makes debugging much more difficult.
216
"""
217
```
218
219
### Error String Conversion
220
221
Utilities for converting error codes to human-readable descriptions.
222
223
```python { .api }
224
def errorString(error_code: int) -> str:
225
"""
226
Convert OpenGL error code to descriptive string.
227
228
Parameters:
229
- error_code: OpenGL error code from glGetError()
230
231
Returns:
232
Human-readable error description
233
"""
234
235
# Error code constants and descriptions
236
ERROR_DESCRIPTIONS = {
237
GL_NO_ERROR: "No error",
238
GL_INVALID_ENUM: "Invalid enumeration parameter",
239
GL_INVALID_VALUE: "Invalid value parameter",
240
GL_INVALID_OPERATION: "Invalid operation for current state",
241
GL_STACK_OVERFLOW: "Command would overflow matrix stack",
242
GL_STACK_UNDERFLOW: "Command would underflow matrix stack",
243
GL_OUT_OF_MEMORY: "Not enough memory to execute command"
244
}
245
```
246
247
### Debugging Utilities
248
249
Advanced debugging and diagnostic tools for development.
250
251
```python { .api }
252
def debugCallback(source: int, type: int, id: int, severity: int,
253
length: int, message: str, userParam):
254
"""
255
OpenGL debug callback function for GL_ARB_debug_output.
256
257
Parameters:
258
- source: Message source (GL_DEBUG_SOURCE_API, etc.)
259
- type: Message type (GL_DEBUG_TYPE_ERROR, etc.)
260
- id: Message identifier
261
- severity: Message severity (GL_DEBUG_SEVERITY_HIGH, etc.)
262
- length: Message length
263
- message: Debug message string
264
- userParam: User-provided data
265
"""
266
267
def enableDebugOutput():
268
"""
269
Enable OpenGL debug output (requires GL_ARB_debug_output).
270
Sets up debug callback for detailed error reporting.
271
"""
272
273
class CallTracer:
274
"""
275
Utility class for tracing OpenGL function calls.
276
Logs all OpenGL calls with arguments and return values.
277
"""
278
279
def __init__(self, logger=None):
280
"""
281
Parameters:
282
- logger: Python logger instance, or None for default
283
"""
284
285
def enable(self):
286
"""Enable call tracing."""
287
288
def disable(self):
289
"""Disable call tracing."""
290
```
291
292
## Usage Examples
293
294
### Basic Error Checking
295
```python
296
from OpenGL.GL import *
297
from OpenGL import error
298
299
# Enable error checking (default)
300
import OpenGL
301
OpenGL.ERROR_CHECKING = True
302
303
try:
304
# OpenGL operations
305
glEnable(GL_DEPTH_TEST)
306
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
307
308
# This might cause an error
309
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0,
310
GL_RGB, GL_UNSIGNED_BYTE, None)
311
312
except error.GLError as e:
313
print(f"OpenGL Error: {e}")
314
print(f"Error code: {e.err}")
315
print(f"Function: {e.name}")
316
print(f"Arguments: {e.cArguments}")
317
```
318
319
### Manual Error Checking
320
```python
321
# Disable automatic error checking for performance
322
OpenGL.ERROR_CHECKING = False
323
324
# Manual error checking at critical points
325
def critical_operation():
326
glGenTextures(1)
327
328
# Check for errors manually
329
error_code = glGetError()
330
if error_code != GL_NO_ERROR:
331
print(f"Error after glGenTextures: {error.errorString(error_code)}")
332
return False
333
334
return True
335
```
336
337
### Context Validation
338
```python
339
from OpenGL import error
340
341
def safe_gl_operation():
342
try:
343
# Validate context exists
344
error.checkContext()
345
346
# Proceed with OpenGL operations
347
glClear(GL_COLOR_BUFFER_BIT)
348
349
except error.NoContext:
350
print("No OpenGL context available!")
351
return False
352
353
except error.GLError as e:
354
print(f"OpenGL operation failed: {e}")
355
return False
356
357
return True
358
```
359
360
### Extension Checking
361
```python
362
from OpenGL import error
363
from OpenGL.GL import *
364
365
def setup_vertex_buffers():
366
# Check if VBO extension is available
367
if not error.checkExtension("GL_ARB_vertex_buffer_object"):
368
print("VBO extension not available")
369
return False
370
371
try:
372
# Use VBO functions
373
buffer_id = glGenBuffers(1)
374
glBindBuffer(GL_ARRAY_BUFFER, buffer_id[0])
375
376
except error.NullFunctionError:
377
print("VBO functions not available despite extension support")
378
return False
379
380
return True
381
```
382
383
### Production vs Development Configuration
384
```python
385
import OpenGL
386
import os
387
388
# Configure error checking based on environment
389
if os.environ.get('DEBUG', '').lower() == 'true':
390
# Development configuration
391
OpenGL.ERROR_CHECKING = True
392
OpenGL.ERROR_LOGGING = True
393
OpenGL.CONTEXT_CHECKING = True
394
print("Debug mode: Full error checking enabled")
395
else:
396
# Production configuration
397
OpenGL.ERROR_CHECKING = False
398
OpenGL.ERROR_LOGGING = False
399
OpenGL.CONTEXT_CHECKING = False
400
print("Production mode: Error checking disabled for performance")
401
```
402
403
### Error Recovery
404
```python
405
def robust_texture_loading(image_data, width, height):
406
"""Load texture with error recovery."""
407
408
try:
409
# Generate texture
410
texture_id = glGenTextures(1)[0]
411
glBindTexture(GL_TEXTURE_2D, texture_id)
412
413
# Attempt to load texture
414
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
415
GL_RGB, GL_UNSIGNED_BYTE, image_data)
416
417
return texture_id
418
419
except error.GLError as e:
420
print(f"Texture loading failed: {e}")
421
422
# Cleanup on error
423
if 'texture_id' in locals():
424
glDeleteTextures([texture_id])
425
426
# Try fallback format
427
try:
428
texture_id = glGenTextures(1)[0]
429
glBindTexture(GL_TEXTURE_2D, texture_id)
430
431
# Use simpler format
432
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
433
GL_RGB, GL_UNSIGNED_BYTE, [255, 255, 255])
434
435
print("Using fallback 1x1 white texture")
436
return texture_id
437
438
except error.GLError:
439
print("Even fallback texture failed!")
440
return None
441
```
442
443
## Constants
444
445
### OpenGL Error Codes
446
```python { .api }
447
GL_NO_ERROR: int = 0 # No error
448
GL_INVALID_ENUM: int = 0x0500 # Invalid enumeration parameter
449
GL_INVALID_VALUE: int = 0x0501 # Invalid value parameter
450
GL_INVALID_OPERATION: int = 0x0502 # Invalid operation for current state
451
GL_STACK_OVERFLOW: int = 0x0503 # Command would overflow matrix stack
452
GL_STACK_UNDERFLOW: int = 0x0504 # Command would underflow matrix stack
453
GL_OUT_OF_MEMORY: int = 0x0505 # Not enough memory to execute command
454
```
455
456
### Debug Output Constants (GL_ARB_debug_output)
457
```python { .api }
458
# Debug sources
459
GL_DEBUG_SOURCE_API: int
460
GL_DEBUG_SOURCE_WINDOW_SYSTEM: int
461
GL_DEBUG_SOURCE_SHADER_COMPILER: int
462
GL_DEBUG_SOURCE_THIRD_PARTY: int
463
GL_DEBUG_SOURCE_APPLICATION: int
464
GL_DEBUG_SOURCE_OTHER: int
465
466
# Debug types
467
GL_DEBUG_TYPE_ERROR: int
468
GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: int
469
GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: int
470
GL_DEBUG_TYPE_PORTABILITY: int
471
GL_DEBUG_TYPE_PERFORMANCE: int
472
GL_DEBUG_TYPE_OTHER: int
473
474
# Debug severities
475
GL_DEBUG_SEVERITY_HIGH: int
476
GL_DEBUG_SEVERITY_MEDIUM: int
477
GL_DEBUG_SEVERITY_LOW: int
478
```