Anyone using wxPython's GLCanvas on Linux?

I've just discovered yet another "how can that possibly not work" issue with wxPython + PyOpenGL under RHLinux 8.0, which is making me wonder:

    * Does wxGLCanvas just not work on Linux?
          o Has anyone else really used it (not just running the demos,
            actually used it, doing any of the things decribed below)?
          o Did you discover and work around these problems (described
            below)?
          o Did the problems not show up at all?
    * Is there something wrong with how I'm doing SetCurrent() for the
      context?
          o I'm just calling wxGLCanvas.SetCurrent(), which AFAICS is
            the correct thing to do.

Basically, here are the things that are not working:

    * Display-lists can't be generated, glGenLists always returns 0
    * glInitMultitextureARB returns 0 under wxPython contexts, but 1 for
      GLUT contexts (same machine, same everything else). In other
      words, the extension isn't recognised for wxPython contexts but is
      for GLUT contexts
    * gluBuild2DMipmaps seg-faults under wxPython, works fine under GLUT

The symptoms would all suggest that (Py)OpenGL isn't recognising the current context (display-lists are context-specific, as are extensions and texture-objects), but I can't imagine what would cause such a thing in my code. I've checked, and I'm definitely calling

        wxGLCanvas.SetCurrent(self)

on the wxGLCanvas instance.

So, I'm wondering, am I just the first person to really use the wxPython wxGLCanvas? My testing on Linux has never been particularly extensive, but I can't imagine that anyone really using wxGLCanvas on this platform hasn't noticed such an effect.

Oh, same code, same versions of wxPython and PyOpenGL works fine on Win2K, and as noted above, all the code works fine with the GLUT contexts on Linux (and Win2K).

So, is this an isolated incident, or am I tredding upon new ground here?
Mike

···

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/

Isn't it always the way that you discover more information as soon as you send the last message? Turns out the display-list problem (at least) only shows up in the __init__ method of the wxGLCanvas, display-lists *can* be created from within Paint callbacks. Seems as though there may be a delay in setting up the wxGLCanvas' OpenGL structures so that within the __init__ method there just isn't a useful context to be had.

I'll work more on this, but at the moment I'm planning to seperate out the user-level "OnInit" method so that it's occuring after whatever point it is the OpenGL structures are established. I'm hoping there's an event or the like to signal that point. I'll trim all further updates to PyOpenGL, BTW.

Enjoy all,
Mike

Mike C. Fletcher wrote:
...

The symptoms would all suggest that (Py)OpenGL isn't recognising the current context (display-lists are context-specific, as are extensions and texture-objects),

...

···

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/

Hey Mike,
I have used some OpenGL with wxWindows mostly under Windows but also tested on Linux - and it seems to work with Python (as opposed to C++) also.
I think the point (problem) you are refering to is - _when_ is a "good" time to talk to the context. My understanding is that this is the reason for the:
if not GlIsInited:
     GLinit()
INSIDE of OnPaint [look at any wx-gl example!!] --- that is: I think it is best to do ALL gl-calls INSIDE a OnPaint call [maybe with using flags (like the "GlIsInited" above) quite extensively].

I would appreciate if someone could confirm that - since that always was (and still is, actually) a mystery to me: "Is is risky to to gl-calls outside OnPaint ?"

Thanks - and have fun...
Sebastian Haase

···

On Tue, 03 Jun 2003 00:39:17 -0400 "Mike C. Fletcher" <mcfletch@rogers.com> wrote:

Isn't it always the way that you discover more information as soon as you send the last message? Turns out the display-list problem (at least) only shows up in the __init__ method of the wxGLCanvas, display-lists *can* be created from within Paint callbacks. Seems as though there may be a delay in setting up the wxGLCanvas' OpenGL structures so that within the __init__ method there just isn't a useful context to be had.

I'll work more on this, but at the moment I'm planning to seperate out the user-level "OnInit" method so that it's occuring after whatever point it is the OpenGL structures are established. I'm hoping there's an event or the like to signal that point. I'll trim all further updates to PyOpenGL, BTW.

Enjoy all,
Mike

Mike C. Fletcher wrote:
...

The symptoms would all suggest that (Py)OpenGL isn't recognising the current context (display-lists are context-specific, as are extensions and texture-objects),

...

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

Here's the code that's doing the work:

static gint
gtk_glwindow_realized_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win )
{
    wxGLContext *share= win->m_sharedContext;
    if (share==NULL && win->m_sharedContextOf) share=win->m_sharedContextOf->GetContext();

    win->m_glContext = new wxGLContext( TRUE, win, wxNullPalette, share );

    return FALSE;
}

That is, it looks as though the code to create the wxGLContext (which holds the actual glXCreateContext result which represents the window for OpenGL) only happens in the gtk "window created/realised" callback. Haven't yet determined if this occurs before or after EVT_WINDOW_CREATE is sent, but if I'm reading Robin's post to wxWindows-users, it should be before the EVT_WINDOW_CREATE message arrives. If that's true, then it should be safe to do any OpenGL calls after EVT_WINDOW_CREATE iff the above worked. If I'm reading the code correctly, you'll get an error message-box if it doesn't work.

It's too late to test this tonight, but it seems as though something like this (taken from Robin's post) should work:

def OnInit( self ):
    if wxPlatform == '__WXGTK__':
       EVT_WINDOW_CREATE(self, self._OnInit)
    else:
       #defer _OnInit if on GTK
        self._OnInit()
def _OnInit( self, event = None ):
    doWhatNeedsToBeDoneWithOpenGL()

Thanks for the feedback, and enjoy,
Mike

Sebastian Haase wrote:

Hey Mike,
I have used some OpenGL with wxWindows mostly under Windows but also tested on Linux - and it seems to work with Python (as opposed to C++) also.
I think the point (problem) you are refering to is - _when_ is a "good" time to talk to the context. My understanding is that this is the reason for the:
if not GlIsInited:
    GLinit()
INSIDE of OnPaint [look at any wx-gl example!!] --- that is: I think it is best to do ALL gl-calls INSIDE a OnPaint call [maybe with using flags (like the "GlIsInited" above) quite extensively].

I would appreciate if someone could confirm that - since that always was (and still is, actually) a mystery to me: "Is is risky to to gl-calls outside OnPaint ?"

Thanks - and have fun...
Sebastian Haase

...

···

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/

Mike C. Fletcher wrote:

That is, it looks as though the code to create the wxGLContext (which holds the actual glXCreateContext result which represents the window for OpenGL) only happens in the gtk "window created/realised" callback. Haven't yet determined if this occurs before or after EVT_WINDOW_CREATE is sent, but if I'm reading Robin's post to wxWindows-users, it should be before the EVT_WINDOW_CREATE message arrives. If that's true, then it should be safe to do any OpenGL calls after EVT_WINDOW_CREATE iff the above worked. If I'm reading the code correctly, you'll get an error message-box if it doesn't work.

It's too late to test this tonight, but it seems as though something like this (taken from Robin's post) should work:

def OnInit( self ):
   if wxPlatform == '__WXGTK__':
      EVT_WINDOW_CREATE(self, self._OnInit)
   else:
      #defer _OnInit if on GTK
       self._OnInit()
def _OnInit( self, event = None ):
   doWhatNeedsToBeDoneWithOpenGL()

Yep, that's what I would suggest trying (although the comment is in the wrong branch of the if statement <wink> )

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Mike C. Fletcher wrote:

...

def OnInit( self ):
   if wxPlatform == '__WXGTK__':
      EVT_WINDOW_CREATE(self, self._OnInit)
   else:
      #defer _OnInit if on GTK
       self._OnInit()
def _OnInit( self, event = None ):
   doWhatNeedsToBeDoneWithOpenGL()

Yep, that's what I would suggest trying (although the comment is in the wrong branch of the if statement <wink> )

This doesn't quite work as a final solution. It works as long as you
are only creating one of these windows as a descendant of a new frame,
but when I create new wxGLCanvases and add them to a frame to replace a
previous canvas the EVT_WINDOW_CREATE event doesn't appear to get generated.

I wound up with a kludge where the OnPaint handler is checking for a
flag and calling OnInit if the flag hasn't been set yet. That works,
but it's pretty ugly. (Two work-arounds for the same behaviour, and now
errors in the OnInit method are propagating up the Paint callback's
hierarchy instead of the __init__ method's or even the WindowCreate
handler's callback).

I would guess it would be best to walk up the "parent" hierarchy and see
if our parents are yet realised (on GTK only, of course), and only if
they aren't, do EVT_WINDOW_CREATE, but I can't think of what to do in
the case where they are realised, given that the wxGLCanvas isn't going
to have it's context yet, and we don't seem to get an event to signal
that it has been created.

For the record, here's what I'm doing. It appears to work in most
simple cases, though I'm seeing a few rendering artefacts with the
render-all-test-contexts-in-the-same-frame meta-test (the errors don't
appear in the single-test versions of those same contexts (that may just
be a bug somewhere in my code)):

    def DoInit( self ): # called directly by __init__
        if wxPlatform == '__WXGTK__':
            EVT_WINDOW_CREATE(self, self._OnInitCallback)
        else:
            self._OnInitCallback()
    def _OnInitCallback( self, event=None ):
        if not self.calledDoInit:
            self.calledDoInit = 1
            context.Context.DoInit( self )
    def wxOnPaint(self, event):
        dc = wxPaintDC(self)
        size = self.GetClientSize()
        if not self.calledDoInit:
            context_log.info( """wxOnPaint before initialisation
started""" )
            self._OnInitCallback( )
        self.setCurrent()
        self.ViewPort( size.width, size.height )
        self.unsetCurrent()
        self.triggerRedraw(1)

Enjoy all,
Mike

···

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/