muhkuh's picture

Use OpenTK for GTK# GLWidget


some time ago I tried to use GLWidget. It is a C# only control for GTK# that manages an opengl view and uses OpenTK internally. Because it didn't work properly I started to fix it on all 3 supported platforms (Windows, X11, OSX).

During development stumbled over some issues in OpenTK that I can work around but I think they should be resolved in OpenTK. The issues are caused by the specific situation of using OpenTK in an GTK control.

1. A GTK control doesn't always use the same window during it's lifetime. When a control is realized its window gets created. When the window gets unrealized its window gets destroyed. This is used in docking libraries where windows get reparented. So it is necessary to use the OpenGL context of the control and bind it to another window.

This is currently not easily possible on all platforms.
a) Windows
The Graphics context only calls SetPixelFormat for the window it is created with. So when additional windows are created they don't get set up correctly.

b) MacOS:
When calling MakeCurrent the AglGraphicsContext doesn't care about the window info at all. It just makes the opengl context current. The drawable stays unchanged.

2. OpenTK has the habit of calling XInitThreads in its initialization under X11. This call is used to make multithreaded OpenGL work. The problem with this call is that it has to be the first function in Xlib that is called. Otherwise the behavior is undefined. The problem is that in my control where I use OpenTK it gets initialized at some point I have no control of. When my control is created it is quite certain that there are already some X11 windows created. So when I initialize OpenTK in the ctor the call to XInitThreads causes dubious crashes at different places.
I would have to tell every user of my control to call some static function or initialize OpenTK themselves before they do any X11 calls. This is problematic as is is very unusual for a GTK control to require such things and people tend not to read documentations.

I already submitted bug reports for some of these issues but nobody responded:

May be I'm overlooking something but I really think these issues are relatively easy to fix and I offer to do the coding as I currently have access to all platforms. Could some developer at least drop a single line if this is appreciated? Even tell me if don't care about these issues at all because you think the use case I have is too obscure. This would be totally OK as OpenTK is open source and I can just fork it if I want.


Comment viewing options

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

Both issues are on the pipeline for testing and integration, with emphasis on "testing":

  • Disabling XInitThreads has a huge regression potential, and needs to be tested thoroughly. (The current approach has been tested with up to 100 concurrent windows, something that failed miserably before the addition of XInitThreads. Replacing that with .Net locks has quite far-reaching implications).
  • Get/SetPixelFormat is extremely slow on some hardware/drivers, for some unknown reason. Calling these functions unconditionally in MakeCurrent is not possible (easy to fix) and the side-effects need to be documented. Relaxing MakeCurrent is a simple change with complex side-effects - it's not currently supported for a reason.

I don't expect to be able to investigate this any further before early November, but I'd be glad to contribute if you are willing to lead the investigation.

muhkuh's picture

Hi, glad to hear that you are working on this. Because you stopped commenting on the issues I got the impression that they just get ignored.

  • As far as I know you have to call XInitThreads for multithreaded opengl. There is no way around it. Even if you could handle this by .NET locks inside OpenTK this would still not be save. May be there are other XLib calls in the application that OpenTK doesn't know about. It would be hard to synchronize all this. I'd rather add some option to tell OpenTK not to call XInitThreads. Like calling OpenTK.Toolkit.Init() with a parameter "NoXInitThreads" or "MultiThreaded". This would reduce the regression potential. This is similar to what Qt does.
  • SetPixelFormat is definately slow when it is called the first time. I did never notice that GetPixelFormat is slow but if that's the case it should be avoided. What do you mean by " Relaxing MakeCurrent is a simple change with complex side-effects - it's not currently supported for a reason."? Anyway why not take a different approach by adding a possibility to create a WindowInfo on Win32 by supplying a PixelFormat? This would not break any code and MakeCurrent could stay as it is.
  • Regarding MacOSX: I did notice that MakeCurrent on an AglContext completely ignores the supplied windowinfo. I did work around this by calling SetDrawable via reflection. This seemed to work most of the time but failed occasionally with a "bad drawable" error. I had a look at the agl documentation and noticed that aglSetDrawable is deprecated since and aglSetWindowRef should be used instead. So I called this manually and the problems vanished. I'm still testing this though.

The most pressing point for me is the XInitThreads issue as I have no workaround for this.