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