|
"""Storage of per-context values of various types |
|
|
|
Because OpenGL needs persistent references to the |
|
objects we're constructing to shadow Python objects, |
|
we have to store references to the objects somewhere |
|
|
|
For any given Python GUI library, we can use a weakref |
|
to the library's representation of the GL context to |
|
call the cleanup function. That means some per-GUI |
|
library code in OpenGL (or the library), but it gives |
|
us very natural operations within OpenGL. |
|
|
|
Note: you can entirely disable use of this module by |
|
setting: |
|
|
|
OpenGL.ERROR_ON_COPY = True |
|
OpenGL.STORE_POINTERS = False |
|
|
|
before importing OpenGL functionality. |
|
""" |
|
from OpenGL import platform |
|
import weakref |
|
storedPointers = { |
|
|
|
} |
|
storedWeakPointers = { |
|
|
|
} |
|
STORAGES = [ storedPointers, storedWeakPointers ] |
|
|
|
def getContext( context = None ): |
|
"""Get the context (if passed, just return) |
|
|
|
context -- the context ID, if None, the current context |
|
""" |
|
if context is None: |
|
context = platform.GetCurrentContext() |
|
if context == 0: |
|
from OpenGL import error |
|
raise error.Error( |
|
"""Attempt to retrieve context when no valid context""" |
|
) |
|
return context |
|
def setValue( constant, value, context=None, weak=False ): |
|
"""Set a stored value for the given context |
|
|
|
constant -- Normally a GL constant value, but can be any hashable value |
|
value -- the value to be stored. If weak is true must be |
|
weak-reference-able. If None, then the value will be deleted from |
|
the storage |
|
context -- the context identifier for which we're storing the value |
|
weak -- if true, value will be stored with a weakref |
|
Note: you should always pass the same value for "weak" for a given |
|
constant, otherwise you will create two storages for the constant. |
|
""" |
|
if getattr( value, '_no_cache_', False ): |
|
return |
|
context = getContext( context ) |
|
if weak: |
|
storage = storedWeakPointers |
|
cls = weakref.WeakValueDictionary |
|
else: |
|
storage = storedPointers |
|
cls = dict |
|
current = storage.get( context ) |
|
if current is None: |
|
storage[context] = current = cls() |
|
previous = current.get( constant ) |
|
if value is None: |
|
try: |
|
del current[ constant ] |
|
except (KeyError,TypeError,ValueError) as err: |
|
pass |
|
else: |
|
|
|
|
|
current[ constant ] = value |
|
return previous |
|
def delValue( constant, context=None ): |
|
"""Delete the specified value for the given context |
|
|
|
constant -- Normally a GL constant value, but can be any hashable value |
|
context -- the context identifier for which we're storing the value |
|
""" |
|
context = getContext( context ) |
|
found = False |
|
for storage in STORAGES: |
|
contextStorage = storage.get( context ) |
|
if contextStorage: |
|
try: |
|
del contextStorage[ constant ] |
|
found = True |
|
except KeyError as err: |
|
pass |
|
return found |
|
|
|
def getValue( constant, context = None ): |
|
"""Get a stored value for the given constant |
|
|
|
constant -- unique ID for the type of data being retrieved |
|
context -- the context ID, if None, the current context |
|
""" |
|
context = getContext( context ) |
|
for storage in STORAGES: |
|
contextStorage = storage.get( context ) |
|
if contextStorage: |
|
value = contextStorage.get( constant ) |
|
if value is not None: |
|
return value |
|
return None |
|
|
|
def cleanupContext( context=None ): |
|
"""Cleanup all held pointer objects for the given context |
|
|
|
Warning: this is dangerous, as if you call it before a context |
|
is destroyed you may release memory held by the context and cause |
|
a protection fault when the GL goes to render the scene! |
|
|
|
Normally you will want to get the context ID explicitly and then |
|
register cleanupContext as a weakref callback to your GUI library |
|
Context object with the (now invalid) context ID as parameter. |
|
""" |
|
if context is None: |
|
context = platform.GetCurrentContext() |
|
for storage in STORAGES: |
|
try: |
|
del storedPointers[ context ] |
|
except KeyError as err: |
|
return False |
|
else: |
|
return True |
|
|