| """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 |
|
|