Add context managers to PyOpenGL?

Playing a bit with Python context managers for PyOpenGL.  Considering adding them pervasively, likely with a configuration flag. (idea is from Florian's gletools)...

  • OpenGL.arrays.VBO -- make a context manager itself (this is already implemented)
  • OpenGL.GL.compileShader -- make the shader int returned a context manager (implemented)

Those two I consider non-controversial, as they are already non-standard entry points, and the "thing" really is a context manager, you want to do things "with" it.  More pause-inducing:

  • glEnable*/glDisable* -- return context manager reversing the boolean logic, including e.g. glEnableClient* glEnableVertexAttrib*, etc.
  • glPush* -- return context manager doing a pop of the same
  • glBegin* -- return context manager doing glEnd*, glBeginQuery and the like included
  • glEnable*Pointer -- essentially just glEnableVertexAttrib, really

Those operations would (necessarily) become slower, since they'd wind up in Python (or I guess I could code a Cython accelerator)... they're going to be more complex no matter how I handle it.

Then there's a whole suite of operations that are state-setters where you normally want to work with the context and then reset to default or some application-specific value:

  • gl*Mask
  • glCullFace
  • glDepthRange
Those ones I'm very hesitant about, what would you have as the __exit__, is it the default, or the previous value?  Previous value makes the most sense, but it would also require a glGet* operation, which would be very performance-intrusive.

The thing is, at least for *my* code I can't really see myself using the contexts for any but the lowest-level of operations.  The scenegraph winds up with e.g. the texture, shader and VBO enabling in totally different modules, where they are all independent of one another.  When I consider adding this intrusive a feature with the thought "but I'll likely seldom use it myself" I start to wonder if I really want to add it, or if it should be in a higher-level library.


  1. jfpacker

    jfpacker on 08/11/2009 7:53 p.m. #

    This is not a feature that should be in PyOpenGL. I agree that PyOpenGL should be python-like, however, when I'm using a python API that's just supposed to give me access to a C API while making it easier to use in Python I don't want extra overhead at the API level. I think you're right about keeping context managers to a higher level library. If you want to create context managers I suggest creating a higher-level addon for them such as you did with arrays.VBO so that they don't interfere with code that only uses the GL package. ie: don't do this for anything in OpenGL.GL.*

    I say this because I like the Python access and don't want to use the raw APIs as you provide in OpenGL.raw.* but also don't want unnecessary bloat of the OpenGL.GL.* packages.

    I, for one, would actually add context managers to my own higher level library. That way, I know what I'm getting and it's exactly tailored to how I'm going to use it.

  2. nes

    nes on 08/12/2009 10:43 a.m. #

    IMO use context managers conservatively where they are clearly convenient and keep the status quo with the rest. There is no need to push shiny language features into everything.

  3. Mike C. Fletcher

    Mike C. Fletcher on 08/12/2009 11:09 a.m. #

    Thanks, your comments have reinforced my unease to the point that I'm not going to add these features pervasively.

  4. Florian

    Florian on 08/12/2009 5:48 p.m. #

    I don't think that PyOpenGL should be context manager based. However I do think it wouldn't harm to have some pyopengl.contexts or somesuch for those that want to use them.

    Also, doing scene graph stuff and doing contexts are two pretty different things, I'm not sure they mix well. I like working with contexts rather then scene-graphs because they allow me to plug together a pipeline on the fly without having to throw around a lot of opengl calls manually.

  5. Aaron Digulla

    Aaron Digulla on 09/28/2009 10:22 a.m. #

    I suggest to wrap the context switching code in a guard which gets only activated when something is changed in the context (i.e. a setter is called).

    When this happens, there are these ways to proceed:

    - Don't do anything (current way)
    - Remember the original value and restore it on exit
    - Create a new context, copy all settings and restore the context on exit

    I think it would be great if you'd offer support for a with-statement for the context, so it would be simple to say when a context restore should happen (and where you can configure how that restore should work).

Comments are closed.


Pingbacks are closed.