rajaron's picture

Failed to swap buffers for context 196608 current. Error: 6

I have a UserControl in a .NET Windows Form that includes a GLControl for processing raw video from disk. I have the import working fine with the UserControl in the main UI. However, once the import is started, the user can't interrupt the process. To allow that, I am trying to do the import loop in a background thread of the UserControl using the methods below. And it all works fine, except that when it completes, and I try calling Demosaic(1) from a Next button below the UserControl, then I get the following error when it tries to do the GLControl.SwapBuffers() at the end of the rendering:

Failed to swap buffers for context 196608 current. Error: 6

From other messages in this forum, I found that Error 6 means "invalid handle". It seems that the
glControl1.Context.MakeCurrent(null);
at the end of the loop in the background thread is not returning the GraphicsContext to the main UI thread. How to resolve this error?

public void Import(int fCount)
{
    this.frameCount = fCount;
    Thread tImport;
    tImport = new Thread(new ThreadStart(DoWork));
    tImport.IsBackground = true;
    glControl1.Context.MakeCurrent(null);
    tImport.Start();
}
 
private void DoWork()
{
        // Make the GLControl Graphics Context current on this background thread
        glControl1.MakeCurrent();
 
        SdFrame theFrame;
        for (int frameNumber = 0; frameNumber < frameCount; frameNumber++)
        {
            // Read the frame from disk
            theFrame = sdReader.GetFrame(frameNumber, caseId);
 
            // Demosaic according to the selected algorithm using OpenTK
            // - loads raw image as a texture and applies shaders to demosaic
            this.Demosaic(theFrame);
 
            // Save the image
            // - GrabScreenshot from the framebuffer as a Bitmap and then save
            SaveImage(this.Image, theFrame.DateTaken);
        }
 
        // Make the GLControl GraphicsContext current on the main thread
        glControl1.Context.MakeCurrent(null);
}

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Once you call glControl1.Context.MakeCurrent(null) the context will not be current on any thread, resulting in the error you see. Once you main the context non-current on the background thread, you need to call glControl1.MakeCurrent() on the main UI thread to restore the context.

The rules are (relatively) simple:

  1. An OpenGL context can only be current on a single thread. A context that is not current on any thread is considered non-current.
  2. To issue OpenGL commands on a given thread, you need a current context on that thread.
  3. MakeCurrent() makes a non-current context current on the thread it is issued on. It is an error to call MakeCurrent() on a context that is current on a different thread (that context must be made non-current first).
  4. MakeCurrent(null) makes the context of the current thread non-current. You must use MakeCurrent() to make that context current again.
rajaron's picture

Thank you for the clarification on the context switching rules. I added the glControl1.MakeCurrent() on completion of the background thread, and it worked like a charm!