5
\$\begingroup\$

I'm trying to integrate two third-party OpenGL rendering pipelines into the same application, namely Cinder's OpenGL API for 3D drawing and backbuffer rendering, and Google Skia's API for 2D drawing. Unfortunately, Skia tends to trigger a lot of GL state changes in general use, and offers no functionality to reset the GL state. To make matters worse, Cinder (GLNext branch) tries to keep an internal record of all of its GL state changes so that they can be easily 'unwound', but bad things can happen if its internal representation becomes different from the actual GL state.

The easiest way to alleviate these problems was to create a new OpenGL context for use exclusively by Skia, performing context switches only when 2D updates were necessary. However, I've noticed some weird behaviours when I'm required to switch context more frequently, like certain draw calls failing or blend states flickering. Everything I've read about GL contexts indicates that they're meant for use in multiple threads or multiple windows. I've also read about context switches failing in certain circumstances? Is there anything terribly wrong with switching context in a single-threaded, single-windowed application?

\$\endgroup\$
2
\$\begingroup\$

From what I understand (there's always room for interpretation and spec-lawyering) of the GL specs there is nothing wrong with switching contexts in a single-threaded single-windowed application.

You have probably hit some driver bugs the manufacturer hasn't tested against.

Try adding glFlush() or glFinish() before your context switch in theory it shouldn't be needed as the documentation for wglMakeCurrent (https://msdn.microsoft.com/en-us/library/windows/desktop/dd374387%28v=vs.85%29.aspx) says:

Before switching to the new rendering context, OpenGL flushes any previous rendering context that was current to the calling thread.

And glxMakeCurrent (https://www.opengl.org/sdk/docs/man2/xhtml/glXMakeCurrent.xml) :

Pending commands to the previous context, if any, are flushed before it is released.

Cinder is open source. I recommend adding your own InvalidateAllCachedStates() function that sets all internal states to impossible values forcing all GL states to be updated on the next Cinder draw call or your own RestoreAllCachedStates() to restore the GL to what Cinder expects.

Another option would be to record and restore all GL states yourself using a large amount of glGet() calls.

And a 3rd one would be to render the 2D to a FrameBufferObject in a separate thread and context and share the FBO texture(s) between the two contexts. But the task priority switching of what process/thread is using the GPU might cause performance issues on some drivers.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.