[vtkusers] GTK and VTK - problems galore!

Prabhu Ramachandran prabhu at aero.iitm.ernet.in
Fri Sep 21 02:47:56 EDT 2001


hi,

This is a **long** email.  Please bear with me.  I have tried to cut
irrelavant parts from the mail but have made it verbose so you
understand what has happened thus far.  I also apologize for all the
cross posting.

I am not on the gtk lists so I'd appreciate if you could cc me on
replies and also forward the message through to the gtk lists in case
they are closed to non-subscribers.

Here is some background on the problem.  VTK or the Visualization
ToolKit (http://public.kitware.com) is a high level, open source,
visualization library.  It is very popular and runs atop OpenGL and
makes 3D visualization very easy.  VTK is written in C++ and has
bindings for Python, Tcl and Java.  I believe functional Perl bindings
exist but they aren't part of the standard distribution and AFAIK
aren't used/tested too much.

I use the Python bindings and a year or so ago the only GUI toolkit
that would work with VTK and Python was Tkinter (the Python wrapper
for Tk).  IIRC, sometime last year we found that wxPython
(http://wxpython.org) had a widget (wxVTKRenderWindow) that supported
embedding a VTK Render Window in it.  While testing it out others and
I noticed a few bugs.

   (1) Under UNIX (specifically, IRIX and Linux), there was a lot of
   flicker when one interacted with the widget and moved the objects
   in the vtk window.  This problem did not exist on the Win32 version
   of wxPython.  The UNIX version of wxPython used GTK underneath.  So
   this was basically a problem with double buffering on the widget.
   The problem could be in wxwindows or GTK.

   (2) There was a clipping problem when one zoomed in on the
   visualized objects.

   (3) Some features in the Tkinter based widgets that ship with VTK
   werent implemented in wxVTKRenderWindow.

In an attempt to fix this I rewrote the wxVTKRenderWindow of wxPython
and based the rewrite on the Tkinter widget.  I was able to fix bugs
(2) and (3) but had trouble with bug no. 1.

Now for some background on how the widget was implemented.  To embed
the VTK widget in wxPython in GTK one simply found the XID (one got
the equivalent HWND or something for MSW) and did something like this
in Python:

# Get the XID/HWND
        hdl = self.GetHandle()
# Set this RenderWindow's window id to a pre-existing window.
        self.renderWindow.SetWindowInfo(str(hdl))

Then one bound the right signals to the right call backs etc. etc. to
get a VTK widget embedded in wxPython.

Now, Renaud KERIVEN <keriven at cermics.enpc.fr> had the same flicker
problem with wxWindows for c++ and had a fix for it.  He basically
said that instead of setting the WindowId of the widget one should set
the ParentID of the window.  He said that: "The VTK Renwin becomes
only the child of the window created by wxWindows and thus keeps good
double buffering properties."  I tried this on the the wxWindows VTK
widget (this was with C++) created by David Marshall
<gte552m at prism.gatech.edu> and it worked.  The problem was setting the
parent ID via Python.  There was no method from Python to do this, so
I patched VTK to bind this method and got it committed to the VTK CVS
tree.  Now, I tried setting the ParentInfo from the wxVTKRenderWindow
code in Python.  Like so:

# Get the XID/HWND
        hdl = self.GetHandle()
# Sets the X window id of the window that WILL BE created.
        self.renderWindow.SetParentInfo(str(hdl))

This was necessary *only* for the GTK versions and not for the MSW
version of wxPython.

The flicker went away completely but expose events weren't generated
properly.  This happened with the c++ wxWindows VTK widget also.  So
if you obscured the window partially - sometimes even completely no
expose event was emitted (I checked this by also using xev) and the
VTK rendered scene would not redraw!  Meanwhile when all this was
going on I wrote a widget called vtkGTKRenderWidget.py that basically
embedded a VTK Renderwindow into a pyGTK widget.  Not surprisingly, I
had exactly the same problems i.e. flicker was removed by setting
ParentInfo but expose events were not okay when this was set.  Here is
part of the email I sent on the vtk list way back in March 2001:

  "If I set the ParentId of the vtkRenderWindow using SetParentInfo
  the flicker is removed but now there is a new problem, the window
  does not generate expose events properly.  Therefore, if you put
  another window on top of this window and move the top window the
  embedded vtk window is not redrawn because it doesnt generate an
  expose event.  A resize of the widget however generates an expose
  event.  This happens with both wxPython, the wxVTKWindow c++ class
  and also with my simple GTK + Python class.  If I set the WindowId
  using WindowInfo the expose event works but there is a huge amount
  of flicker as mentioned before.  I ran xev on this and found that as
  expected when the embedded widget is obscured and then un-obscured
  there is no expose event generated but a visibilitynotify event and
  by capturing this and generating a redraw things work fine.

  However, I dont understand why this happens - can any X guru
  enlighten me out here?  This might be a GTK problem too.  My
  version of GTK is 1.2.8."

I didn't receive any tips that helped at all.  Meanwhile I figured out
a way to partially get over this problem in the pyGTK widget: I
basically caught the "visibility_notify_event" (which was emitted
properly) and did a redraw.  Though this made things somewhat better
it still wouldnt generate a redraw when the window was partially
un-obscured.  I wanted to do a similar thing under wxPython and looked
at the events, but there was no visibility notify - only EVT_PAINT and
EVT_ERASE_BACKGROUND exist (both of which dont work).  I posted to the
list about this but no one responded.  So, I gathered that visibility
notify is not present in wxPython. So I was back to square one.  Here
is part of the email I sent subsequently to the wx lists:


  "I decided to try the next hack.  I tested some code out and found
  that if I do EVT_PAINT(self.GetParent(), self.OnPaint), things work
  without problems because the parent emits decent expose events.  But
  obviously this is no good because, AFAIK:

     (1) the parents EVT_PAINT is finished - i.e. if the parent does
     something on EVT_PAINT this call will ensure that the original is
     not called!

     (2) The parent may do an OnPaint that doesnt really influence
     this window.

     (3) Worse, the parent may not be a decent window (could be None).


  So the obvious solution was to create a class that overloads
  wxScrolledWindow (as in the original vtk.py), creates a child window
  inside that and then connect the VTK window ParentID to the parent
  and bind the EVT_PAINT to the child (i.e self).  Sounds dirty but
  works (Please, if you have a better soln. let me know!)."

I translated this hack of mine to the vtkGTKRenderWidget.py code also
and it kind of worked.  I did the following:

class GtkVtkRenderWindowBase (gtk.GtkViewport):
    def __init__ (self, *args):
...
        self.box = gtk.GtkEventBox ()
        self.box.show ()
        self.add (self.box)
...
        self.connect ("realize", self.OnRealize)
        self.connect ("expose_event", self.OnExpose)
        self.box.connect_after ("size_allocate", self.OnConfigure)
        self.box.connect ("button_press_event", self.OnButtonDown)
...

    def OnRealize (self, *args):
        if self.__Created == 0:
            # you can't get the xid without the window being realized.
            self.box.realize ()
            win_id = str (self.box.get_window ().xid)
            try:
                self._RenderWindow.SetParentInfo (win_id)
            except AttributeError:
                self._RenderWindow.SetWindowInfo (win_id)                
...

Where basically I embed an EventBox inside the Viewport and bind
things appropriately.  This kind of worked.  Atleast, there was no
flicker and very little expose related problems.  It was not
completely flawless but much better than before.  Anyway, I use Linux
almost exclusively so with the help of Eric Boix
<frog at creatis.insa-lyon.fr> I got the wxPython widget working
satisfactorily on Windows and Linux.  Meanwhile I committed the pyGTK
VTK Renderwindow code to the VTK cvs tree and the code was was being
used by Dave Reed <dreed at capital.edu> on Solaris and was working sort
of fine.

The story doesnt end here.  All this while, I was running X 4.0.  I
upgraded to X 4.0.2 and I no longer needed the SetParentInfo call!
But in May 2001, David Gobbi <dgobbi at irus.rri.on.ca> suspected that
this whole issue was not an X server bug and more a GTK/wxWindows bug.

   I don't think the flicker was caused by a wierd bug in X, it is
   more likely that the 'bug' lies somewhere in wxWindows and that it
   is clearing the window when it shouldn't.  If XFree86-4.0.2 does a
   better job of queuing commands before flushing them to the video
   card, then the 'clear' probably occurs in the same frameblank
   interval as the Render and therefore you don't see it.  But that
   'clear' should not be happenning at all (or it should occur only in
   the back buffer, and therefore never be seen).

   Also, don't forget that Linux isn't the only UNIX out there!

True enough a few days back I asked Dave Reed to try a version of
vtkGTKRenderWidget without the SetParentInfo on a Solaris box with
gtk-1.2.10 and had very bad problems with the test example cone
appearing dithered and in black and white.  Also there were others
using wxWindows on SGI who had problems earlier.  The folks who ran
into trouble on IRIX are no longer actively using VTK with these
toolkits so I cant confirm much with them.  The current vtkGTK widget
I made with the "box hack" occasionally produces

Gdk-ERROR **: BadWindow (invalid Window parameter)
  serial 110 error_code 3 request_code 4 minor_code 0

The problem now is that clearly what works now is a hack and has some
issues.  There still are expose related issues but they are less
visible than they were before.  All these are based on hacks and arent
good solutions and dont fix the problem entirely either.

All this leads me to one conclusion - there is a bug somewhere in GTK.
I have no clue where it is and dont want to spend any more time on
this whole issue.  

I'm fed up with this problem and wanted the GTK experts to look at it.
As is evident I have spent considerable amount of time on it.  I made
this a long and detailed message so that you have all the information
I can provide.  Dave Reed <dreed at capital.edu> is willing to test stuff
on Linux and Solaris.  I dont mind helping if it doesnt infringe much
on my time. :)

Thanks!
prabhu

p.s. I guess if you have read this far you must be setting some sort
of record for patience!

-- 
There are always alternatives.
		-- Spock, "The Galileo Seven", stardate 2822.3



More information about the vtkusers mailing list