Skip to content

GL \ Device Context and GL Context

Luca Piccioni edited this page Apr 19, 2017 · 4 revisions

OpenGL.Net offers raw API that you can use for implementing your own abstraction layer. However, it offers also a set of utilities for creating the appropriate device contexts depending on the platform.

OpenGL.Net does not implement a common window abstraction, letting the user to decide which library should create and manage the system user interface. Normally an UI tool-kits offer some way to get a native window handle (and the relative display handle, if meaningful), representing the attachment to a renderable area. Using the display and window handles, platform APIs allow creation of the device context, which is necessary for creating OpenGL contexts.

Device Context Overview

The DeviceContext abstraction can be thought as a factory of OpenGL contexts. A DeviceContext can be created using one of the following DeviceContext methods:

  • static DeviceContext Create(IntPtr display, IntPtr windowHandle)
  • static DeviceContext Create()
  • static DeviceContext Create(INativePBuffer nativeBuffer)

Basic factory

Device contexts are normally created by native handles offered by the underlying platform API. The method public static DeviceContext Create(IntPtr display, IntPtr windowHandle) should be used when using a native window as rendering destination.

using (DeviceContext device = DeviceContext.Create(display, handle)) {
	device.ChoosePixelFormat(new DevicePixelFormat(24));

	IntPtr ctx = device.CreateContext(IntPtr.Zero);
	if (device.MakeCurrent(ctx) == false)
		throw new InvalidOperationException();
            // ...
}

Windowless Factory

It is possible to create DeviceContext instances that apparently they are not linked to any native window by using static DeviceContext Create(). However, you should be aware that the instances created with this method may be bound to a common native window. The common (and hidden) native window is created at OpenGL.Net initialization time, and kept for offering the device context factory method.

Indeed it's possible to use concurrently multiple device contexts created using this method, but they should be used for off-screen rendering purposes.

using (DeviceContext device = DeviceContext.Create()) {
	// XXX: device.ChoosePixelFormat(new DevicePixelFormat(24)); will throw an exception
	// XXX: device.SetPixelFormat(...); will throw an exception the same

	IntPtr ctx = device.CreateContext(IntPtr.Zero);
	if (device.MakeCurrent(ctx) == false)
		throw new InvalidOperationException();
            // ...
}

}

P-Buffer Factory

Most of the platforms offers a pixel buffer storage which able users to perform off-screen rendering on platform-specific resources, called P-Buffers. The method static DeviceContext Create(INativePBuffer nativeBuffer) can be used for creating DeviceContext instances able to render on the specified INativePBuffer instance.

The appropriate INativePBuffer instance can be created by INativePBuffer CreatePBuffer(DevicePixelFormat pixelFormat, uint width, uint height). Since the P-Buffer pixel format is already determined at construction time, you must not set the DeviceContext pixel format.

Device pixel format

Before creating any GL context, a pixel format must be defined for the device context. You must set the pixel format only if the DeviceContext was created by Create(IntPtr display, IntPtr windowHandle); in the other cases you shouldn't attempt to set any pixel format.

  • DevicePixelFormatCollection PixelsFormats { get; }
  • void ChoosePixelFormat(DevicePixelFormat pixelFormat)
  • void SetPixelFormat(DevicePixelFormat pixelFormat)

GL Context Overview

Once you have the most appropriate DeviceContext implementation, with a pixel format set, you can use it for the creation of OpenGL contexts. Each GL context instance is identified by an IntPtr (that is simply a pointer).

  • IntPtr CreateContext(IntPtr sharedContext)
  • IntPtr CreateContextAttrib(IntPtr sharedContext, int[] attribsList)
  • bool DeleteContext(IntPtr ctx)

The OpenGL context should be managed by the DeviceContext that has created it; the following interface is available:

  • bool MakeCurrent(IntPtr ctx)
  • void SwapBuffers()
  • bool SwapInterval(int interval)