[vtkusers] C++ example (was Re: X Error of failed request: GLXBadDrawable)

Mathieu Malaterre mathieu.malaterre at gmail.com
Mon Jun 30 07:44:17 EDT 2008


Ok, if anyone is interested in the problem. Here is a very easy way to
reproduce it (*). At least on my X11-debian box it crash at index=450.
So in summary:

1. vtkRenderWindow::Finalize is indeed doing what it claims
2. if a vtkRenderWindowInteractor is associated with the
vtkRenderWindow, then the finalize is -somehow- not working anymore

(*)
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

int main()
{
  vtkSphereSource *sphere = vtkSphereSource::New();
  vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
  sphereMapper->SetInput(sphere->GetOutput());

  vtkActor* sphereActor = vtkActor::New();
  sphereActor->SetMapper(sphereMapper);

  vtkRenderer *ren = vtkRenderer::New();
  ren->AddActor(sphereActor);

  // Create a dummy rwi that will serve as reference DisplayId
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  renWin->AddRenderer(ren);
  iren->SetRenderWindow(renWin);
  iren->Initialize();
  iren->Start();
  // at this point the user is supposed to 'q' quit the mainloop

  const int nrenwin = 1000;
  vtkRenderWindowInteractor * list[nrenwin];
  vtkRenderWindow * list1[nrenwin];
  for(int i = 0; i < nrenwin; ++i)
    {
    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    vtkRenderWindow *renWin1 = vtkRenderWindow::New();
    // Work-around for Max Xlib:
    renWin1->SetDisplayId( renWin->GetGenericDisplayId() );
    //iren->SetRenderWindow( renWin1 ); // If uncomment it stops working
    list[i] = iren;
    list1[i] = renWin1;
    renWin1->AddRenderer(ren);
    renWin1->Render();
    renWin1->Finalize();
    std::cout << i << std::endl;
    }
  // All vtk-pointers are still in memory, but we passed the opengl
hardcoded limit :)
  for(int i = 0; i < nrenwin; ++i)
    {
    list[i]->Delete();
    list1[i]->Delete();
    }

  iren->Delete();
  renWin->Delete();
  ren->Delete();
  sphereActor->Delete();
  sphereMapper->Delete();
  sphere->Delete();

  return 0;
}

On Fri, Jun 27, 2008 at 4:24 PM, Mathieu Malaterre
<mathieu.malaterre at gmail.com> wrote:
> Hum... I have reduced the sample even more (using only VTK class) and
> I cannot reproduce the bug I am seeing from python+wx:
>
> #include "vtkSphereSource.h"
> #include "vtkPolyDataMapper.h"
> #include "vtkActor.h"
> #include "vtkRenderer.h"
> #include "vtkRenderWindow.h"
> #include "vtkRenderWindowInteractor.h"
>
> int main()
> {
>  vtkSphereSource *sphere = vtkSphereSource::New();
>  vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
>  sphereMapper->SetInput(sphere->GetOutput());
>
>  vtkActor* sphereActor = vtkActor::New();
>  sphereActor->SetMapper(sphereMapper);
>
>  vtkRenderer *ren = vtkRenderer::New();
>  ren->AddActor(sphereActor);
>
>  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
>  vtkRenderWindow *renWin = vtkRenderWindow::New();
>  renWin->AddRenderer(ren);
>  iren->SetRenderWindow(renWin);
>  iren->Initialize();
>  iren->Start();
>
>  const int nrenwin = 500;
>  vtkRenderWindow * list[nrenwin];
>  for(int i = 0; i < nrenwin; ++i)
>    {
>    vtkRenderWindow *renWin1 = vtkRenderWindow::New();
>    list[i] = renWin1;
>    // Work-around for Max Xlib:
>    renWin1->SetDisplayId( renWin->GetGenericDisplayId() );
>    renWin1->AddRenderer(ren);
>    renWin1->Render();
>    renWin1->Finalize();
>    std::cout << i << std::endl;
>    }
>  for(int i = 0; i < nrenwin; ++i)
>    {
>    list[i]->Delete();
>    }
>
>  iren->Delete();
>  renWin->Delete();
>  ren->Delete();
>  sphereActor->Delete();
>  sphereMapper->Delete();
>  sphere->Delete();
>
>  return 0;
> }
>
> On Fri, Jun 27, 2008 at 3:45 PM, Mathieu Malaterre
> <mathieu.malaterre at gmail.com> wrote:
>> Here is a short wx example to demonstrate the issue:
>>
>> 1. You can hit the X limit pretty easily replacing
>> wxVTKRenderWindowInteractor with wxVTKRenderWindow (in which case each
>> renderwindow will creates its own X Display)
>>
>> 2. The issue I can still not work around can be reproduced using the
>> following python-wx script (*). Even using the complicated (ref Charl
>> Boath) finalization scheme it seems that something is not getting
>> clean up here. Could an opengl guru recommend a way to track down the
>> opengl call that might be leaked ?
>>
>>
>> Basically all I am doing is create enough widget on the first notebook
>> page, so that when user click on page 2:
>> -> I get rid of all widget from page 1
>> -> all widget defined on page 2 are getting created until we hit the
>> hardcoded limit
>>
>> Thanks !
>> -Mathieu
>> Ps: you might have to tweak grid=(15,15) for your particular opengl driver
>>
>> (*)
>> import wx
>>
>> from vtk import *
>> # important to use wxVTKRenderWindowInteractor here since it implement
>> the wx.GetXDisplay() trick
>> from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
>>
>>
>> class Page(wx.Panel):
>>    def __init__(self, parent):
>>        wx.Panel.__init__(self, parent)
>>        grid=(15,15)
>>        sizer = wx.GridSizer(rows=grid[0], cols=grid[1], hgap=1, vgap=1)
>>        n = grid[0]*grid[1]
>>
>>        sphere = vtkSphereSource()
>>        sphereMapper = vtkPolyDataMapper()
>>        sphereMapper.SetInput(sphere.GetOutput())
>>
>>        sphereActor = vtkActor()
>>        sphereActor.SetMapper(sphereMapper)
>>
>>        self._wlist=[]
>>        for i in range(0,n):
>>          ren = vtkRenderer()
>>          ren.AddActor(sphereActor)
>>          renWin = wxVTKRenderWindowInteractor(self,-1, size=(10,10))
>>          self._wlist.append( renWin )
>>          renWin.GetRenderWindow().AddRenderer(ren)
>>          sizer.Add( renWin, 1, wx.EXPAND)
>>
>>        self.SetSizer(sizer)
>>
>> class MainFrame(wx.Frame):
>>    def __init__(self):
>>        wx.Frame.__init__(self, None, title="Simple Notebook Example")
>>
>>        p = wx.Panel(self)
>>        nb = wx.Notebook(p)
>>        nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED,  self.MyPageChanged,id=nb.GetId())
>>
>>        self._page1 = Page(nb)
>>        self._page2 = Page(nb)
>>
>>        nb.AddPage(self._page1, "Page 1")
>>        nb.AddPage(self._page2, "Page 2")
>>
>>        sizer = wx.BoxSizer()
>>        sizer.Add(nb, 1, wx.EXPAND)
>>        p.SetSizer(sizer)
>>
>>    def MyPageChanged(self,event=None):
>>        # We should first Finalize the old ones:
>>        print event.GetOldSelection()
>>        if event.GetOldSelection() == 0:
>>          for w in self._page1._wlist:
>>            renderers = w.GetRenderWindow().GetRenderers()
>>            numRenderers = renderers.GetNumberOfItems()
>>            renderers.InitTraversal()
>>            for i in range(0,numRenderers):
>>              w.GetRenderWindow().RemoveRenderer(renderers.GetNextItem())
>>            w.GetRenderWindow().Finalize()
>>            w.SetRenderWindow(None)
>>            del w
>>
>>        event.Skip()
>>
>> if __name__ == "__main__":
>>    app = wx.App()
>>    MainFrame().Show()
>>    app.MainLoop()
>>
>>
>> On Thu, Jun 26, 2008 at 4:55 PM, Mathieu Malaterre
>> <mathieu.malaterre at gmail.com> wrote:
>>> Hello there,
>>>
>>>   I am currently stuck on the following problem: when creating a lot
>>> of vtkRenderWindow (vtkXOpenGLRenderWindow in my case), there are two
>>> issues:
>>>
>>> 1. X has a limited number of Display. And you get an error like that:
>>>
>>> ...
>>> Xlib: connection to ":0.0" refused by server
>>> Xlib: Maximum number of clients reached
>>> ERROR: In /home/mmalaterre/Projects/VTK52/Rendering/vtkXOpenGLRenderWindow.cxx,
>>> line 1592
>>> vtkXOpenGLRenderWindow (0x2494140): bad X server connection. DISPLAY=:0
>>> ...
>>>
>>>  This can easily be worked around by reusing the same DisplayId for
>>> all your vtkRenderWindow (see SetDisplayId/GetDisplayId).
>>>
>>> 2. Once you get pass the first problem, it seem that OpenGL (or nvidia
>>> implementation in my case) has also a limited number of available
>>> context. So when creating a lot of vtkRenderWindow you get:
>>>
>>> ...
>>> The error was 'GLXBadDrawable'.
>>>  (Details: serial 403 error_code 158 request_code 143 minor_code 5)
>>>  (Note to programmers: normally, X errors are reported asynchronously;
>>>   that is, you will receive the error a while after causing it.
>>>   To debug your program, run it with the --sync command line
>>>   option to change this behavior. You can then get a meaningful
>>>   backtrace from your debugger if you break on the gdk_x_error() function.)
>>> ...
>>>
>>>  I have not been able to work around this issue. Has anyone deal with
>>> this before ? Is there a solution or at least a work around ?
>>>
>>> Thanks for suggestions !
>>> --
>>> Mathieu
>>> Ps: at least on my machine it seems opengl context are leaked even
>>> after the process was aborted, I cannot even start glxinfo anymore:
>>>
>>>
>>> $ glxinfo
>>> name of display: :0.0
>>> X Error of failed request:  GLXBadDrawable
>>>  Major opcode of failed request:  143 (GLX)
>>>  Minor opcode of failed request:  5 (X_GLXMakeCurrent)
>>>  Serial number of failed request:  18
>>>  Current serial number in output stream:  18
>>>
>>
>>
>>
>> --
>> Mathieu
>>
>
>
>
> --
> Mathieu
>



-- 
Mathieu



More information about the vtkusers mailing list