murrdpirate's picture

Get ID/handle of current context created by 3rd party COM object

Is there a way that I can obtain the ID/handle of the current OpenGL context, so that I can switch to it using Context.MakeCurrent()?

I need to access the OpenGL context that is created by a 3rd party COM object. The COM object is a graphic window you embed in a windows Form, much like the GLControl feature in OpenTK. The COM object doesn't provide access to its OpenGL resources, the only thing it provides me with is a method called 'Scene.Render,' which just updates the graphics of the embedded window.

Interestingly, I've found that immediately after I call Scene.Render, but before I switch to my own GameWindow context, the COM object's context is still current. So I can call OpenTK commands as normal and draw shapes, load and display textures, and load and run shaders...all within this context. The only issue is that I have to call Scene.Render so that I have access to the context, add my graphics, then call Scene.Render again so that my stuff is shown. Is there a way I can get the ID/handle of the COM object's context once I make it current, and then switch to that context whenever I want?


Comments

Comment viewing options

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

You will need to use a platform-specific API to retrieve the context handle. On windows, this is wglGetCurrentContext.

You can then wrap this context handle in an OpenTK GraphicsContext:

IntPtr external_handle = wglGetCurrentContext();
var external_context = new GraphicsContext(
    new ContextHandle(handle),
    (name) => wglGetProcAddress(name),
    () => new ContextHandle(wglGetCurrentContext));

External contexts allow you to integrate OpenTK with 3rd-party toolkits, such as Qt or SDL. However, they will not allow you to *control* the external context - you will have to use the third party toolkit to do that. For example, calling external_context.MakeCurrent() will have no effect - you must call wglMakeCurrent yourself, either directly or through the third-party COM component.

Technically speaking, OpenTK could co-opt the external context but doing so would expose users to lifecycle issues (the external context might be destroyed behind the back of the GraphicsContext, resulting in a crash.) It is safer to let the third-party component own the context.

murrdpirate's picture

Just want to make sure I'm understanding correctly: in my case I just want to add some textures and such to what the 3rd party context renders, so does that mean I should only use wglGetCurrentContext and wglMakeCurrent? If the 3rd party COM component doesn't offer any control of its context, does that mean creating external_context would offer no further capability?

Thanks very much for the help.

the Fiddler's picture
Quote:

in my case I just want to add some textures and such to what the 3rd party context renders, so does that mean I should only use wglGetCurrentContext and wglMakeCurrent?

The code snippet in my previous post would allow you to do that.

As long as the external context is current, you can inject any GL call using OpenTK. Depending on the design of the COM component, this may be simple or harder to achieve.

Quote:

If the 3rd party COM component doesn't offer any control of its context, does that mean creating external_context would offer no further capability?

That's right, external_context is only used for initializing GL entry points. Everything else remains the responsibility of the external component. This means, for example, that external_context.SwapBuffers() will have no effect.

A lot of this depends on the design of the external component. The ideal case would look something like this:

// 1. Construct Scene COM component
// 2. Contruct GraphicsContext using wglGetCurrentContext()
// 3. Call Scene.Render()
// 4. Inject GL calls
// 5. Call Scene.Present()

If there is no Scene.Present() API, then things suddenly become much more tricky.

Hint: you can use apitrace to log the exact sequence of GL and WGL commands issued by the COM component.