jcornwall's picture

GLControl unload

According to the documentation it is necessary to use the containing form of a GLControl's Load event to determine when the OpenGL context is available for use.

Is there an equivalent event which can tell me when the OpenGL context is about to be destroyed? I delegate most rendering to a secondary thread (with GLControl.MakeCurrent()) and need to know at which point the thread should be terminated.



Comment viewing options

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

I don't know the answer to this... Maybe there is some unload event in the form or glcontrol?

Just out of curiosity: why are you rendering from a secondary thread..? I try to keep rendering/event handling in the same thread, to avoid complicating things.

jcornwall's picture

I've been searching for an unload event of some sort, but haven't turned up anything in GLControl or the Form yet. It might require some closer inspection of GLControl's code to determine the point at which the context is destroyed.

Rendering from a second thread certainly complicates things somewhat. I chose that design because my rendering is push rather than pull; that is I don't redraw as fast as the display will allow but instead synchronise rendering to an external data source. My understanding of the Form design is that it's intended for callback rendering. It would probably be unwise to hold that thread until new data is ready to draw.

the Fiddler's picture

There's no explicit Unload event at the moment - the context is unloaded/destroyed when the GLControl is disposed. It might be a good idea to add one, in the spirit of GameWindow.Unload. I don't know if a ContextDestroyed event would be useful, though.

objarni's picture

My understanding of the Form design is that it's intended for callback rendering. It would probably be unwise to hold that thread until new data is ready to draw.

Yes, doing any long computations inside event handlers is unwise, because it will make the application unresponsive. If I have long computations to do, I place them in either Background workers (simple to use) or Threads (more cumbersome to use, but higher performance / less memory footprint).

Could you explain in a little bit more detail what you are up to? What do you mean by a design influenced by push rather than pull?

jcornwall's picture

Thanks for the info, Fiddler.

Sure, I can explain a little more. I'm writing a client application for a networked TV server and chose OpenGL because it integrated better with UIs than SDL. The rendering component waits for frames to be received from the decoder (which in turns waits on the network) and renders them with appropriate synchronisation delays. It also handles repaint and resize requests posted from the Application thread (to avoid context switches).

The renderer could be waiting long periods of time between updates so it would be inappropriate to wait in the UI thread. An extreme case would be paused video, which only requires occasional repainting. This is push rendering in the sense that rendering is driven by the arrival of new frames. Pull rendering would be redrawing and updating the video regularly, e.g. on a tick basis or in Application.Idle, which is more common in graphics applications.

This fits a little more naturally with my application and, aside from the context destruction issue, works quite well.

objarni's picture

I see.

Pardon my ignorance, but why not keep your dependencies to just Windows.Forms instead of Windows.Forms+OpenTK? I mean, I cannot really see how 3d h/w acceleration fits into your application? If all you are doing is blitting video frames upon arrival, given you have a Panel named panel1 on a Windows.Form, all you could do is this:

using(Graphics g = panel1.CreateGraphics())
  g.DrawImage(...); // scaled to panel size of course

.. with all network/thread synchronization-communication left out.

What am I missing?

jcornwall's picture

I do scaling and YCbCr to RGB conversion in OpenGL pixel shaders.

Compositing with overlays will likely be useful down the line, too.

objarni's picture


(Mind note to myself : maybe I should start thinking of 3d h/w accelerators more as "cpu offloaders/work horses" since they can do so much more than perspective correct projection of textured triangles these days.. heh)

protongun's picture

I have also been delegating my rendering to a seperate thread (for several reasons: need multiple instances of the GLControl on a form, so rendering all those on the UI thread might be too much. Also, for running my application on XP which has a simple stack window manager as opposed to a Composition Window Manager (Vista+), I need to enable VSync, which effectively blocks the rendering thread until the CPU context queue can accept further GL command (ie. until the next vertical refresh). (I've noticed the block either occurs on SwapBuffers or the GL command immediately following it). Therefore, rendering multiple display controls on one thread with Vsync enabled is not feasible. I also find appealing the conceptual simplicity of having one thread per GLControl, which own's the control's context. The UI thread is then simply responsible for pumping messages to the rendering threads, which process the message and perform appropriate rendering operations.

Anyhow, I also needed to signal the rendering threads to gracefully exit when the form containing the GLControl was closed.

The GLControl.Disposed event was exactly what I needed.