pontifikas's picture

Tao+OpenTK compatibility issue?

I have an application in Tao and I want to move to OpenTK.
I'm using Tao functions to set up my OpenGL screen and OpenTK for rendering commands. I summon my Device-Rendering Contexts and Pixel Formats. So far so good.
The moment I issue the first opengl command, any command I tried so far, I get an exception of "object reference is not set to an instance of an object ".
Now I know OpenTK claims compatibility with Tao so I assume that there is something I'm doing wrong.
The procedure for creating-binding contexts work correctly because I didn't change them and they throw no exception.

Any suggestions?
Thanks a lot.


Comments

Comment viewing options

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

The OpenGL command that throws the exception, does it come from OpenTK.Graphics.OpenGL or from Tao.OpenGl? Can you please post the stacktrace for the exception? How are you initializing the context (is this SimpleOpenGlControl)? Which OS?

I have compiled and ran a number of Tao projects using OpenTK.Compatibility without issues, so I know for a fact that it work. Maybe your code is exposing a bug in the SimpleOpenGlControl implementation (Tao.OpenGl is 100% identical, so I don't think the issue comes from there) or maybe it's something else entirely. I'm afraid I cannot offer more specific suggestions without more information on the problem.

pontifikas's picture

Here is the Stack Trace though I'm afraid is not very useful
System.NullReferenceException: Object reference not set to an instance of an object.
at OpenTK.Graphics.OpenGL.GL.ClearColor(Single red, Single green, Single blue, Single alpha)
at EMBOSS_TK.Engine3D.InitializeGraphics_GL(IntPtr[] handles) in C:\Users\pontifikas\Documents\EMBOSS_TK\Classes\Engine3D.cs:line 931

As you can see the opengl functions are definitely OpenTK.
Although, you mentioned OpenTK.Compatibility. I'm using Tao.Platform.Windows for creating the contexts. Could that be the problem.
If yes, under which namespace do the Tao Functions lay because I have included OpenTK.Compatibility and I cannot find the functions anywhere

pontifikas's picture

Ah! I forgot
Device Context Initialization:

 try
            {
                this.H_DC[0] = User.GetDC(Handles[0]);
                this.H_DC[1] = User.GetDC(Handles[1]);
                ScreenHandles[0] = Handles[0];
                ScreenHandles[1] = Handles[1];
                result = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

Rendering Context

 try
            {
                this.H_RC = Wgl.wglCreateContext(this.H_DC[0]);
                //check to see if context was created
                if (H_RC == IntPtr.Zero)
                {
                    throw new Exception("ERROR!Rendering Context Could not be created");
                }
 
                if (!Wgl.wglMakeCurrent(this.H_DC[0], this.H_RC))
                {
                    throw new Exception("ERROR!Rendering Context Could not be activated");
                }
                result = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

I'm using 2 display windows which share the same content (Same Rendering Context). They are Panel class and their Handle is what I use.

the Fiddler's picture

It seems that you are not using any of the OpenTK.Compatibility APIs right now. OpenTK.Compatibility provides access to exactly four Tao classes: Tao.OpenGl.Gl, Tao.OpenGl.Glu, Tao.OpenAl.Al and an improved version of Tao.Platform.Windows.SimpleOpenGlControl. It does not provide access to Gdi, User, Wgl or other platform-specific code (you can keep using Tao.Platform.Windows.dll for those, it won't cause any problems).

The issue here is that OpenTK.Graphics.OpenGL requires some additional initialization compared to Tao.OpenGl. This is normally handled internally by OpenTK, but since you are creating the context manually things are a little more complicated.

I'm afraid that 0.9.9-2b does not expose the necessary APIs to initialize OpenTK.Graphics.OpenGL externally (I'll try to fix that for 0.9.9-3), so the only solution right now is to construct the render context through OpenTK:

using OpenTK.Graphics;
using OpenTK.Platform;
using Utilities = OpenTK.Platform.Utilities;
 
IWindowInfo[] panels = new IWindowInfo[]
{
    Utilities.CreateWindowsWindowInfo(Handles[0]),
    Utilities.CreateWindowsWindowInfo(Handles[1]),
};
 
IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, panels[0]);

This code completely replaces Tao.Platform.Windows.dll - there's no need to access Wgl directly any more.

context.VSync = true;
context.MakeCurrent(panels[1]); // or panels[0]
context.SwapBuffers();

As an additional benefit, you can now use fullscreen antialiasing (modify the GraphicsMode parameter), access OpenTK.Graphics.OpenGL or even add support for non-windows platforms easily, should the need ever arise.

Edit: you are generally free to mix Tao dlls with OpenTK. The only complication is that OpenTK.Graphics.OpenGL must be initialized correctly before using it.

pontifikas's picture

From the code you give I deduce that IWindowInfo is sth like Rendering context and IGraphicsContext is the device context (I try to find an analogy between Tao and TK so I wont get lost).
MakeCurrent makes either panels[0] or [1] current. But why IGraphicsContext has a property IsCurrent!!!
Or should I create 2 IGraphicsContext one for each panel, and call MakeCurrent(PanelInfo)?

the Fiddler's picture
  • IWindowInfo is a wrapper around the window handle, device context and other platform-specific information.
  • IGraphicsContext is the render context (i.e. it encapsulates Wgl).
  • IsCurrent returns true if the IGraphicsContext is current on the calling thread. As far as OpenGL is concerned, it doesn't matter which panel it is current on - it just needs *something* to draw on. Check the GraphicsContext documentation for more information.
  • You'd have to create each context on a different thread for this to work. You'd get slightly better performance as you wouldn't have to call MakeCurrent all the time, but you'd have to deal with threading issues.