its's picture

Initialize the GraphicsContext object with the external OpenGL rendering context

Hello.

I'm trying to initialize the GraphicsContext object with the external OpenGL rendering context.
The external context is created at outside of OpenTK.
(in OpenTK 1.0 RC1, Windows7, VS2008)

I had tried these codes to create dummy GraphicsContext object,
but, all of them failed with "NullReferenceException".

GraphicsContext context = GraphicsContext.CreateDummyContext();
IntPtr hRC;// The Handle of the external OpenGL rendering context.
OpenTK.ContextHandle otkContextHandle = new OpenTK.ContextHandle( hRC );
GraphicsContext context = GraphicsContext.CreateDummyContext( otkContextHandle );
((IGraphicsContextInternal)context).LoadAll(); // this throws NullReferenceException
IntPtr hRC;// The Handle of the external OpenGL rendering context.
GraphicsContext context = new GraphicsContext(
    new OpenTK.ContextHandle( hRC ),
    OpenTK.Platform.Utilities.CreateWindowsWindowInfo( IntPtr.Zero ) );
OpenTK.Graphics.OpenGL.GL.LoadAll();

I debugged the soucecode of OpenTK(1.0 RC1), and found that
the "Null" of the NullReferenceException is
internal static GetCurrentContextDelegate GetCurrentContext
in GraphicsCOntext class,
at GraphicsContext.cs line 256.

This "GetCurrentContext" field seems to be initialized only at the constructor
"GraphicsContext(GraphicsMode, IWindowInfo, int, int, GraphicsContextFlags)",
but,
OpenTK.Graphics.OpenGL.GL.LoadAll(),
GraphicsContext.CreateDummyContext(),
GraphicsContext.CreateDummyContext(IntPtr),
and constructor GraphicsContext(OpenTK.ContextHandle,IWindowInfo)
doesn't call this.

So, I thik,
if initialize with external context,
the GetCurrentContext field is always null and
the NullReferenceException will be always thrown.

... is this a bug?
or is there any other way to initialize with external context?

thanks.


Comments

Comment viewing options

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

This is indeed a bug, thanks for tracing it down. I'm working on a fix.

the Fiddler's picture

This should be a viable workaround until the fix is released:

IntPtr hRC;// The Handle of the external OpenGL rendering context.
GraphicsContext context = new GraphicsContext(
    new OpenTK.ContextHandle( hRC ),
    OpenTK.Platform.Utilities.CreateWindowsWindowInfo( IntPtr.Zero ) );
 
(context as IGraphicsContextInternal).Implementation.LoadAll();

However, please note that OpenTK.Platform.Utilities.CreateWindowsWindowInfo( IntPtr.Zero ) may have unintended consequences. If you know the external window handle, it will be safer to pass that instead of IntPtr.Zero.

the Fiddler's picture

Update: I have committed a fix to svn r2700 (branches/1.0). It would help if you could download that and see if it works correctly now.

Checkout instructions here: http://www.opentk.com/project/svn (just change the address from /trunk to /branches/1.0).

its's picture

Thanks for the quick responce and bug fix!
I will try it.

its's picture

In svn r2700 (branches/1.0),

IntPtr hRC;// The Handle of the external OpenGL rendering context.
GraphicsContext context = new GraphicsContext(
    new OpenTK.ContextHandle( hRC ),
    OpenTK.Platform.Utilities.CreateWindowsWindowInfo( IntPtr.Zero ) );

This code works correctly, and the entry points of OpenGL functions are loaded sucsessfully.

But,

GraphicsContext context = GraphicsContext.CreateDummyContext();

This throws InvalidOperationException with the message "No GraphicsContext is current on the calling thread.".

And,

IntPtr hRC;// The Handle of the external OpenGL rendering context.
OpenTK.ContextHandle otkContextHandle = new OpenTK.ContextHandle( hRC );
GraphicsContext context = GraphicsContext.CreateDummyContext( otkContextHandle );
(context as IGraphicsContextInternal).Implementation.LoadAll();

(context as IGraphicsContextInternal).Implementation.LoadAll();
This code does nothing, and no entry points are loaded.

the Fiddler's picture

The render context must be current in order to load entry points. The first approach calls MakeCurrent() which does this for you. The second approach doesn't (it's a dummy GraphicsContext, meaning functions like MakeCurrent() or SwapBuffers() won't do anything) and leaves this responsibility to you. CreateDummyContext() will try to detect if a current context exists in the calling thread (and fail if it doesn't find anything), while CreateDummyContext(ContextHandle) will trust you implicitly (hey, I'll use this context handle but you need to make sure it's current before trying to use OpenGL - this includes loading the entry points).

In other words, create the external context and make it current before calling CreateDummyContext() or LoadAll().

Edit: LoadAll() throws a GraphicsContextMissing exception when called without a current context. The fact that it doesn't throw when using a dummy context is a bug (I'm working on it).

its's picture

OK,
but in my code, I called Makecurrent() berfore creating dummy context, and wglGetCurrentContext() returns the handle of the valid extarnal context.

I had tried this

externalContext.MakeCurrent();
IntPtr hRC = wglGetCurrentContext();
OpenTK.ContextHandle hc = new OpenTK.ContextHandle( hRC );
GraphicsContext context = GraphicsContext.CreateDummyContext( hc );
(context as IGraphicsContextInternal).Implementation.LoadAll();

In this code, (context as IGraphicsContextInternal). Implementation was a OpenTK.Platform.Dummy.DummyGLContext objet, and DummyGLContext.LoadAll() did nothing.

externalContext.MakeCurrent();
IntPtr hRC = wglGetCurrentContext();
GraphicsContext context = GraphicsContext.CreateDummyContext();

This throws InvalidOperationException "No GraphicsContext is current on the calling thread.".

Looking the source code of CreateDummyContext() (GraphicsContext.cs), it checks GraphicsContext.available_contexts field, but it seems not to ditect current context...