Managing multiple windows and external OpenGL contexts

OpenGL in a standalone application

This paragraph details the relationship between REDsdk and OpenGL, and the way OpenGL contexts are managed by REDsdk when it operates alone in an application. The picture below illustrates the way contexts are created and managed by REDsdk:

OpenGL context management in a standalone REDsdk application

First, REDsdk is a multiple OpenGL contexts application. It uses one separate OpenGL context for each rendering buffer it needs to work with (on-screen windows and off-screen buffers). As you can see in the schema above, there's a default REDsdk OpenGL context. This context is a 'pivot' context that is created during the initialization of the first REDsdk window. All other contexts will share their resources with it on creation, so that we can ensure that REDsdk manages only one pool of shared data for the application.

All RED::IViewpointRenderList objects have their own OpenGL contexts. These contexts can be accessed through RED::IViewpointRenderList::GetOpenGLInfo. Returned values types depend of course on the operating system in use for the application.

Using external OpenGL contexts in an application

As we have seen, a REDsdk window can be initialized so that it uses the OpenGL context of an existing 3rd party application to draw in the context that does not belong to it. This can be achieved by using the RED::WindowRenderInfo class that lets the caller specify the 'hosting' context of a window thanks to: RED::WindowRenderInfo::SetHostingContext. A practical example can be found here: Integration into an existing OpenGL application.

There's no more to say if one window only is used in the application, but in the case of multiple windows, we must be sure that all the contexts in use (by both the hosting application and by REDsdk) are shared. On Windows this is usually not a problem as REDsdk will share all supplied hosting contexts with its default internal OpenGL context. On Linux and MacOS, the problem is a bit different as the sharing context is specified at the context construction time.

On Windows, the context sharing can occur after the context has been created. the wglShareLists call can be used to make sure that all contexts can be shared, if some basic rules are enforced:

// Given 4 contexts A, B, C, D:
wglSharelists( A, B );    // OK
wglShareLists( A, C );    // OK
wglShareLists( C, D );    // OK

// Given 4 contexts A, B, C, D:
wglShareLists( A, B );    // OK
wglShareLists( C, A );    // KO ( A and B are shared, so they can be used only as first argument of wglShareLists ).
wglShareLists( C, B );    // KO

The only tricky part here is to ensure that if a context is already shared with another one it can be only used as the first parameter of wglShareLists. If a call fails, then the opposite call will work unless both parameters are already shared themselves.

On Linux and MacOS, the sharing context is specified at the context construction time. Therefore, the application must ensure that all the contexts it supplies to REDsdk are shared before it sends them to REDsdk. This leads to a different context organization:

Context sharing with application owned contexts, on Linux and MacOS

The first window hosting context supplied to REDsdk will act as the 'pivot' context. All other windows of the application should have their context shared with this one. REDsdk's default context will be initialized by sharing with the first supplied window hosting context. Internal REDsdk VRLs will either use their own proprietary contexts created and shared with the REDsdk default context (the sharing constraints described above don't apply on Linux and MacOS) or will use OpenGL FramebufferObjects (FBOs for short) that rely only on the default REDsdk OpenGL context.