The GraphicsContext class
[Introduction]
The OpenTK.Graphics.GraphicsContext is a cross-platform wrapper around an OpenGL context. The context routes your OpenGL commands to the hardware driver for execution - which means you cannot use any OpenGL commands without a valid GraphicsContext.
[Constructors]
OpenTK creates a GraphicsContext automatically as part of the GameWindow and GLControl classes:
- You can specify the desired
GraphicsModeof the context using themodeparameter. UseGraphicsMode.Defaultto set a default, compatible mode or specify the color, depth, stencil and anti-aliasing level manually. - You can specify the OpenGL version you wish to use through the
majorandminorparameters. As per the OpenGL specs, the context will use the highest version that is compatible with the version you specified. The default values are 1 and 0 respectively, resulting in a 2.1 context. - You can request an embedded (ES) context by specifying
GraphicsContextFlags.Embeddedto theflagsparameter. The default value will construct a desktop (regular OpenGL) context. - If you are creating the context manually, you must specify a valid
IWindowInfoinstance to thewindowparameter (see below). This is the default window theGraphicsContextwill draw on and can be modified later using theMakeCurrentmethod.
Examples:
// Creates a 1.0-compatible GraphicsContext with GraphicsMode.Default GameWindow window = new GameWindow(); // Creates a 3.0-compatible GraphicsContext with 32bpp color, 24bpp depth // 8bpp stencil and 4x anti-aliasing. GLControl control = new GLControl(new GraphicsMode(32, 24, 8, 4), 3, 0);
Sometimes, you might wish to create a second context for your application. A typical use case is for background loading of resources. This is very simple to achieve:
// The new context must be created on a new thread // (see remarks section, below) // We need to create a new window for the new context. // Note 1: new windows remain invisible unless you call // INativeWindow.Visible = true or IGameWindow.Run() // Note 2: invisible windows fail the pixel ownership test. // This means that the contents of the front buffer are undefined, i.e. // you cannot use an invisible window for offscreen rendering. // You will need to use a framebuffer object, instead. // Note 3: context sharing will fail if the main context is in use. // Note 4: this code can be used as-is in a GLControl or GameWindow. EventWaitHandle context_ready = new EventWaitHandle(false, EventResetMode.AutoReset); Context.MakeCurrent(null); Thread thread = new Thread(() => { INativeWindow window = new NativeWindow(); IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, window.WindowInfo); context.MakeCurrent(window.WindowInfo); while (window.Exists) { window.ProcessEvents(); // Perform your processing here Thread.Sleep(1); // Limit CPU usage, if necessary } }); thread.IsBackground = true; thread.Start(); context_ready.WaitOne(); MakeCurrent();
If necessary, you can also instantiate a GraphicsContext manually. For this, you will need to provide an amount of platform-specific information, as indicated below:
using OpenTK.Graphics; using OpenTK.Platform; using Config = OpenTK.Configuration; using Utilities = OpenTK.Platform.Utilities; // Create an IWindowInfo for the window we wish to render on. // handle - a Win32, X11 or Carbon window handle // display - the X11 display connection // screen - the X11 screen id // root - the X11 root window // visual - the desired X11 visual for the window IWindowInfo wi = null; if (Config.RunningOnWindows) wi = Utilities.CreateWindowsWindowInfo(handle); else if (Config.RunningOnX11) wi = Utilities.CreateX11WindowInfo(display, screen, handle, root, visual); else if (Config.RunningOnMacOS) wi = Utilities.CreateMacOSCarbonWindowInfo(handle, false, false); // Construct a new IGraphicsContext using the IWindowInfo from above. IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, wi);
Finally, it is possible to instantiate a 'dummy' GraphicsContext for any OpenGL context created outside of OpenTK. This allows you to use OpenTK.Graphics with windows created through SDL or other libraries:
// The 'external' context has to be current on the calling thread: GraphicsContext context = GraphicsContext.CreateDummyContext();
A common use-case is integration of OpenGL 3.x through OpenTK.Graphics into an existing application.
[Remarks]
A single GraphicsContext may be current on a single thread at a time. All OpenGL commands are routed to the context which is current on the calling thread - issuing OpenGL commands from a thread without a current context may result in a GraphicsContextMissingException. This is a safeguard placed by OpenTK: under normal circumstances, you'd get an abrupt and unexplained crash.
[Methods]
- MakeCurrent
You can use the
MakeCurrent()instance method to make a context current on the calling thread. If a context is already current on this thread, it will be replaced and made non-current. A single context may be current on a single thread at any moment - trying to make it current on two or more threads will result in an error. You can make a context non-current by callingMakeCurrent(null)on the correct thread.To retrieve the current context use the
GraphicsContext.CurrentContextstatic property.If you wish to use OpenGL on multiple threads, you can either:
- create one OpenGL context for each thread, or
- use
MakeCurrent()to make move a single context between threads.
Both alternatives can be quite complicated to implement correctly. For this reason, it is usually advisable to restrict all OpenGL commands to a single thread, typically your main application thread, and use asynchronous method calls to invoke OpenGL from different threads. The
GLControlprovides theGLControl.BeginInvoke()method to simplify asynchronous method calls from secondary threads to the mainSystem.Windows.Forms.Applicationthread. TheGameWindowdoes not provide a similar API.To use multiple contexts on a single thread, call MakeCurrent to select the correct context prior to any OpenGL commands. For example, if you have two GLControls on a single form, you must call MakeCurrent() on the correct GLControl for each Load, Resize or Paint event.
GLControl.MakeCurrent()andGameWindow.MakeCurrent()are instance methods that simplify the handling of contexts. - SwapBuffers
OpenTK creates double-buffered contexts by default. Single-buffered contexts are considered deprecated, since they do not work correctly with compositors found on modern operating systems.
A double-buffered context offers two color buffers: a "back" buffer, where all rendering takes place, and a "front" buffer which is displayed to the user. The
SwapBuffers()method "swaps" the front and back buffers and displays the result of the rendering commands to the user. The contents of the new back buffer are undefined after the call toSwapBuffers().The typical rendering process looks similar to this:
// Clear the back buffer. GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Issue rendering commands, like GL.DrawElements // Display the final rendering to the user GraphicsContext.CurrentContext.SwapBuffers();
Note that caching the current context will be more efficient than retrieving it through
GraphicsContext.CurrentContext. For this reason, bothGameWindowandGLControluse a cachedGraphicsContextfor efficiency.
[Stereoscopic rendering]
You can create a GraphicsContext that supports stereoscopic rendering (also known as "quad-buffer stereo"), by setting the stereo parameter to true in the context constructor. GameWindow and GLControl also offer this parameter in their constructors.
Contexts that support quad-buffer stereo distinguish the back and front buffers between "left" and "right" buffer. In other words, the context contains four distinct color buffers (hence the name): back-left, back-right, front-left and front-right. Check out the stereoscopic rendering page for more information ([Todo: add article and link]).
Please note that quad-buffer stereo is typically not supported on consumer video cards. You will need a workstation-class video card, like Ati's FireGL/FirePro or Nvidia's Quadro series, to enable stereo rendering. Trying to enable stereo rendering on consumer video cards will typically result in a context without stereo capabilities.
[Accessing internal information]
GraphicsContext hides an amount of low-level, implementation-specific information behind the IGraphicsContextInternal interface. This information includes the raw context handle, the platform-specific IGraphicsContext implementation and methods to initialize OpenGL entry points (GetAddress() and LoadAll()).
To access this information, cast your GraphicsContext to IGraphicsContextInternal:
IntPtr raw_context_handle = (my_context as IGraphicsContextInternal).Context.Handle; IntPtr function_address = (my_context as IGraphicsContextInternal).GetAddress("glGenFramebufferEXT");
- Printer-friendly version
- Login or register to post comments


Comments
Re: The GraphicsContext class
I tried to use this code to add OpenGL to a current application. I have a GLControl Version which works well, but i can't get this to work. i'm using windows.
this is just 'testcode' to get it running, it doesn't make too much sense.
Mabye anyone has a small working example of creating the graphicscontext manually instead of using GLControl in a WinForms C# Project.
Thanks in advance!
Re: The GraphicsContext class -> solved
Problem solved!
i missed the command before the line where the exception happens.
(m_context as IGraphicsContextInternal).LoadAll();Re: The GraphicsContext class
I'm glad you posted this, as I encountered the same problem. I didn't see any reference to the "LoadAll()" being required anywhere in the documentation - but that certainly made the difference between OpenTK throwing an exception on the first GL.ClearColor command and it succeeding. I'm at a loss to understand why this was necessary (extensions are required for ancient fixed-pipeline operations like GLClear?)
For a C#/Windows/WinForm user attempting to adopt OpenTK, the manual seems to be sparse on examples. I also have been wondering about the state of the sample browser (which appears mostly broken), and various other stale links on this site to partial documentation. Is there a good source to get material that's up-to-date? Is there any material that is specifically for the WinForms user?
That said - when things work, they do work well, and I've been impressed with what I've browsed of the source so far.
Thanks!
Re: The GraphicsContext class
LoadAll() is called automatically when you create a GameWindow/GLControl/GraphicsContext. You only ever need to call this when using an 'external' context, i.e. when you call wglCreateContext et al yourself or through a 3rd-party library.
All OpenGL calls are routed through delegates (even GL1.1 stuff such as GL.Clear()) because each operating system behaves differently in this regard. Treating everything as a (potential) extension is the only way to achieve consistent behavior in the library.
Re: The GraphicsContext class
But, both stormdrums and my code call the OpenTK GraphicsContext ctors, but still required the call to LoadAll() - here's my code from a sample Winform app:
Re: The GraphicsContext class
How do I create and attach a print device context for OpenGL to draw onto?