[vtkusers] Frame Grabbing from a thread conflicts with OpenGL

jean-michel.rouet at philips.com jean-michel.rouet at philips.com
Tue Dec 2 05:26:30 EST 2003


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 --->





More information about the vtkusers mailing list