[vtkusers] Frame Grabbing from a thread conflicts with OpenGL
Josh Patel
jpatel at cytokinetics.com
Tue Aug 31 14:01:13 EDT 2004
Hi all -
Anyone have a solution to this...
I'm having the same exact problem as Jean-Michel. I'm basically trying
to grab frames from my render window using vtkWindowToImageFilter and
vtkJPEGWriter using a separate thread in python. After the frame-grabber
thread is started, the program crashes with "wglMakeCurrent" errors when
I try to interact with my model.
I'm a complete novice to VTK and OpenGL...but Ian's comments seem to
imply that this can't be done.
Thanks!!
Josh Patel
Cytokinetics, Inc.
####################################################################
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