[vtkusers] Frame Grabbing from a thread conflicts with OpenGL

Ian Miller MrMiller at shelob.plus.com
Fri Dec 5 04:06:41 EST 2003


Jean-Michel,

I don't have time to look at your code but perhaps you will be
interested in my own recent experience with VTK and a multithreaded
program under Win32.

I inherited this program from another project in the office.  It was
horribly unstable.  After a very close look at it I found that through its
sharing of VTK objects - specifically, a vtkRenderer - between two
threads it was implicitly using the same OpenGL graphics context in
both of them.  This is not allowed.  From the MSDN "OpenGL
'wglMakeCurrent'" page:

"A rendering context can be current to only one thread at a time."

Once I had confined use of the single OpenGL graphics context to
a single thread the program was much more stable.

Does that help?
Ian
----- Original Message ----- 
From: <jean-michel.rouet at philips.com>
To: <vtkusers at vtk.org>
Sent: Tuesday, December 02, 2003 10:26 AM
Subject: [vtkusers] Frame Grabbing from a thread conflicts with OpenGL


> Hi all,
>
> I recently posted a message querying how to grab asynchronously some
> renderWindow images while the renderWindowInteractor is running.
> I told that the thread technique lead to problem (crash of wglMakeCurrent
> somewhere in vtkWin32OpenGLRenderWindow.cxx)
>
> Here is a very short program that demonstrates the problem.
>
> Can anyone having experience with threads in Win32 and VTK try this out.
> Maybe I did silly things while instanciating the threads...
>
>
> <--- cut here --->
> // first include the required header files for the vtk classes we are
> using
> #include "vtkConeSource.h"
> #include "vtkPolyDataMapper.h"
> #include "vtkRenderWindow.h"
> #include "vtkRenderWindowInteractor.h"
> #include "vtkCommand.h"
> #include "vtkCamera.h"
> #include "vtkActor.h"
> #include "vtkRenderer.h"
> #include "vtkMultiThreader.h"
> #include "vtkMutexLock.h"
> #include "vtkWindowToImageFilter.h"
> #include "vtkBMPWriter.h"
>
> // The Thread responsible for grabbing images
> static void *mythread(struct ThreadInfoStruct *data)
> {
>     int activeFlag;
>     int i = 0;
>     char filename[512];
>
>     vtkRenderWindowInteractor *self =
> (vtkRenderWindowInteractor*)(data->UserData);
>     vtkBMPWriter *bmpwriter = vtkBMPWriter::New();
>
>     cout << "starting thread " << data->ThreadID << endl;
>
>     while (1) {
>         data->ActiveFlagLock->Lock();
>         activeFlag = *(data->ActiveFlag);
>         data->ActiveFlagLock->Unlock();
>
>         if (activeFlag == 0)
>             {
>                 cout << "Terminating thread " << data->ThreadID << endl;
>                 return NULL;
>             }
>
>         sprintf (filename, "e:/tmp/image_%03d.bmp", i);
>         cout << "Saving image " << filename << endl;
>
>         // ******************************** ################
> ************************
>         // if enabled, this part crashes into wglMakeCurrent()
>         if (1) {
>             vtkWindowToImageFilter *windowToimage =
> vtkWindowToImageFilter::New();
>             windowToimage->SetInput(self->GetRenderWindow());
>             bmpwriter->SetInput(windowToimage->GetOutput());
>             bmpwriter->SetFileName(filename);
>             bmpwriter->Write();
>             windowToimage->Delete();
>         }
>         // ******************************** ################
> ************************
>
>         Sleep(1000);
>     }
>
>     bmpwriter->Delete();
>     return NULL;
> }
>
> // just a call back to launch or terminate the thread when a key is
> pressed.
> class vtkMyCallback : public vtkCommand
> {
> public:
>   static vtkMyCallback *New()
>     { return new vtkMyCallback; }
>     vtkMultiThreader *control;
>
>     vtkMyCallback() {
>         control = vtkMultiThreader::New();
>         control->SetNumberOfThreads(1);
>         threadId = -1;
>     }
>     ~vtkMyCallback() {
>         if (threadId != -1)
>             control->TerminateThread(threadId);
>         control->Delete();
>     }
>
>   virtual void Execute(vtkObject *caller, unsigned long, void*)
>     {
>       vtkRenderWindowInteractor *iren =
> reinterpret_cast<vtkRenderWindowInteractor*>(caller);
>
>       // now start a thread
>       if (threadId == -1)
>           threadId =
> control->SpawnThread((vtkThreadFunctionType)&mythread, iren);
>       // stop the thread
>       else {
>           control->TerminateThread(threadId);
>           threadId = -1;
>       }
>     }
>
> private:
>     int threadId;
> };
>
>
> int main( int argc, char *argv[] )
> {
>   vtkConeSource *cone = vtkConeSource::New();
>   cone->SetHeight( 3.0 );
>   cone->SetRadius( 1.0 );
>   cone->SetResolution( 10 );
>
>   vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
>   coneMapper->SetInput( cone->GetOutput() );
>   vtkActor *coneActor = vtkActor::New();
>   coneActor->SetMapper( coneMapper );
>
>   vtkRenderer *ren1= vtkRenderer::New();
>   ren1->AddActor( coneActor );
>   ren1->SetBackground( 0.1, 0.2, 0.4 );
>
>   vtkRenderWindow *renWin = vtkRenderWindow::New();
>   renWin->AddRenderer( ren1 );
>   renWin->SetSize( 300, 300 );
>
>   vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
>   iren->SetRenderWindow(renWin);
>   iren->Initialize();
>
>   // add an observer for keypress that will launch t
>   vtkMyCallback *mo1 = vtkMyCallback::New();
>   iren->AddObserver(vtkCommand::KeyPressEvent,mo1);
>   mo1->Delete();
>
>   // start interaction
>   iren->Start();
>
>   //
>   // Free up any objects we created
>   //
>   cone->Delete();
>   coneMapper->Delete();
>   coneActor->Delete();
>   ren1->Delete();
>   renWin->Delete();
>
>   return 0;
> }
> <--- cut here --->
>
>
> _______________________________________________
> This is the private VTK discussion list.
> Please keep messages on-topic. Check the FAQ at:
<http://public.kitware.com/cgi-bin/vtkfaq>
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers




More information about the vtkusers mailing list