Thread: [PyOpenGL-Users] Help with ARB Extensions on Windows for PyOpenGL 3.0.0a5?
Brought to you by:
mcfletch
From: zaltor <za...@gm...> - 2006-11-28 10:11:15
|
I'm having a bit of a problem loading extensions under Windows and I'm wondering if I'm understanding the semantics of extension modules correctly. If I run the following snippet (modeled after the sample extension snippet in the PyOpenGL for OpenGL Programmers page) from OpenGL.GLUT import * from OpenGL.GL.ARB.shader_objects import * import sys # initialize GLUT argv = glutInit(sys.argv) # create a window, needs to be done before glInitMultitextureARB glutCreateWindow('foo') # see if GL_ARB_multitexture is supported if not glInitShaderObjectsARB(): # it's not supported...panic! print "Help, I'm lost without GL_ARB_shader_objects!" sys.exit(1) # do something with it... print glCreateProgramObjectARB print bool(glCreateProgramObjectARB) on Python 2.5, I get the following result: <OpenGL.platform.glCreateProgramObjectARB object at 0x00F77EB0> False It seems that PyOpenGL is not finding the function pointers for the extension functions. Digging through the raw and platform directories, it seems that function pointers are found using wglGetProcAddress, which, according to the MSDN, returns a OpenGL context-dependent pointer. Specifically: When no current rendering context exists or the function fails, the return value is NULL. Hence, I modified my snippet to the following, by moving the import of the ARB extension module to after I have a context: from OpenGL.GLUT import * import sys # initialize GLUT argv = glutInit(sys.argv) # create a window, needs to be done before glInitMultitextureARB glutCreateWindow('foo') from OpenGL.GL.ARB.shader_objects import * # see if GL_ARB_multitexture is supported if not glInitShaderObjectsARB(): # it's not supported...panic! print "Help, I'm lost without GL_ARB_shader_objects!" sys.exit(1) # do something with it... print glCreateProgramObjectARB print bool(glCreateProgramObjectARB) which results in an output of: <WinFunctionType object at 0x00F7D288> True This time, it seems to have gotten the correct function. I don't think this problem is going to appear on Linux, since glXGetProcAddressARB is supposed to return context-independent function pointers and thus wouldn't have a problem finding these pointers at module import time even when there is no GL context available. So, my question is, what is the correct way to do module import of ARB extension modules? Should they be imported *after* I have gotten an OpenGL context or can they be imported at any time before I want to use the functions? If the former, that would make using QGLWidget a little bit trickier, as I would have to do a module import in the initializeGL() function and then retain the module for the other functions, like paintGL() If the latter, then I think there may be a problem in the auto-generated wrappers in the raw package, since those wrappers grab the function pointers at module-load time instead of glInitXXX time. Thanks for your time. zaltor |
From: Mike C. F. <mcf...@vr...> - 2006-11-28 14:31:38
|
zaltor wrote: > I'm having a bit of a problem loading extensions under Windows and I'm > wondering if I'm understanding the semantics of extension modules > correctly. > > If I run the following snippet (modeled after the sample extension > snippet in the PyOpenGL for OpenGL Programmers page) ... > on Python 2.5, I get the following result: > > <OpenGL.platform.glCreateProgramObjectARB object at 0x00F77EB0> > False > > It seems that PyOpenGL is not finding > the function pointers for the extension functions. Digging through the raw > and platform directories, it seems that function pointers are found using > wglGetProcAddress, which, according to the MSDN, returns a OpenGL > context-dependent pointer. Specifically: > > When no current rendering context exists or the function fails, > the return value is NULL. > > Hence, I modified my snippet to the following, by moving the import of > the ARB extension module to after I have a context: Urgh. Well, I guess that explains the weird code and the "init" functions for the extensions. Going to have to fix that at the PyOpenGL level. Grr. If it's really context-dependent we're going to have to run an extra function for every extension function (since you can have multiple contexts) :( . Wow, that's a sub-optimal design. Someone should yell at the MS programmers. Oh well, Windows, what are you going to do. Ah, if I'm implying correctly from the wglGetProcAddress "man page", it's actually just that the function might not be available on *this* context, so we just have to delay resolution until the first call (or more realistically, do a check for NULL function pointer and if NULL do a wglGetProcAddress to see if we can get a non-null pointer before raising the "function is null" error). Will require that the "null function pointer" objects be capable of replacing themselves (somehow) with the extension function... but then the normal import mechanism pulls them from the module directly... bah. Don't want the overhead of an extra Python function call just to allow for late loading on windows, we want the raw ctypes function pointers whereever possible (for speed). This is going to be a PITA one way or another. Oh well. Thanks for the report, I'll try to look into it this weekend. Have fun, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |
From: Mike C. F. <mcf...@vr...> - 2006-12-02 17:34:16
|
Mike C. Fletcher wrote: ... > Urgh. Well, I guess that explains the weird code and the "init" > functions for the extensions. Going to have to fix that at the PyOpenGL > level. Grr. If it's really context-dependent we're going to have to > run an extra function for every extension function (since you can have > multiple contexts) :( . Wow, that's a sub-optimal design. Someone > should yell at the MS programmers. Oh well, Windows, what are you going > to do. > > Ah, if I'm implying correctly from the wglGetProcAddress "man page", > it's actually just that the function might not be available on *this* > context, so we just have to delay resolution until the first call (or > more realistically, do a check for NULL function pointer and if NULL do > a wglGetProcAddress to see if we can get a non-null pointer before > raising the "function is null" error). Will require that the "null > function pointer" objects be capable of replacing themselves (somehow) > with the extension function... but then the normal import mechanism > pulls them from the module directly... bah. Don't want the overhead of > an extra Python function call just to allow for late loading on windows, > we want the raw ctypes function pointers whereever possible (for > speed). This is going to be a PITA one way or another. Oh well. > > Thanks for the report, I'll try to look into it this weekend. > PyOpenGL 3.x CVS now has what appears to be a fix for this. Basically if there is a NULL pointer for an extension then every time you try to call it, before raising the error it checks to see if the function is available in the current context, if so, it loads the function and then substitutes the __call__ method for the function's call with a staticmethod wrapper (C-coded, so should be moderately fast). There is still a performance penalty, but it should make most operations fairly intuitive. The biggest problem it introduces is that any wrapper code that checks for the boolean truth of an extension function to "see if it is available" is going to think it's not available. That's pretty sub-optimal IMO. Just don't have an elegant solution to it yet. Have fun, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |