richardjmoss's picture

Obtaining capabilities and initializing OpenGL

Hello,

Recently I received a support request from someone who was trying to run a game I wrote a couple of years ago, but when it started they said they just saw a brown screen. I daresay my code is at fault somewhere, but as I've ran it on a variety of VM's and Windows machines without issue I do wonder if it just might not be.

I wanted to send the user a small app that would use OpenTK to determine the version and capabilities of their system. However, when I tried to write one - just as a standard Windows Forms app, I discovered that attempting to call GL.GetString (or anything else) would throw a null reference exception. Which makes perfect sense if you need to initialize OpenGL first.

If I create a GameWindow object then calling GL.GetString returns something. However, if I dispose of the GameWindow as soon as it's created, then whilst GL.GetString no longer crashes, it returns string.Empty where previously it would have returned a valid value.

My question is two-fold really.

Firstly, is there a convenient method of initializing OpenGL without having to create a GameWindow (I'm not using the GLControl either). Or should I just create the window, ask my questions, then dispose of it afterwards?

Secondly, is there a simple way of detecting what is supported? My game was fairly primitive in how it used OpenGL... 2D textures, GL.DrawArrays, and some primitive drawing using GL.Begin / GL.End - all 1.x stuff as I recall.

I haven't touched the game for a couple of years as I haven't had much time, so it'll take me a while to remember how my engine works and get my head back around OpenGL and how I was (mis)using it.

Thanks;
Richard Moss


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 simplest way to debug your game on the target system is to use apitrace to capture a trace of the OpenGL functions called and the errors they generate. What I usually do is ship my application with a launcher that uses apitrace. The user then uploads the trace so I can analyze or even replay it.

Back to your original question:

Quote:

If I create a GameWindow object then calling GL.GetString returns something. However, if I dispose of the GameWindow as soon as it's created, then whilst GL.GetString no longer crashes, it returns string.Empty where previously it would have returned a valid value.

Calling OpenGL functions without an OpenGL context leads to undefined results. An OpenGL context is created and destroyed alongside the GameWindow, which explains why your OpenGL functions stop working once you destroy the GameWindow.

Quote:

Firstly, is there a convenient method of initializing OpenGL without having to create a GameWindow (I'm not using the GLControl either). Or should I just create the window, ask my questions, then dispose of it afterwards?

No. You need an OpenGL context to call OpenGL functions and you need a window to create an OpenGL context.

The simplest approach is to use GameWindow:

int major;
int minor;
int max_texture_size;
string[] extensions;
 
using (new GameWindow())
{
    var version = GL.GetString(StringName.Version);
    major = Int32.Parse(version[0]);
    minor = Int32.Parse(version[2]);
 
    extensions = GL.GetString(StringName.Extensions).Split(' ');
    max_texture_size = GL.GetInteger(GetPName.MaxTextureSize);
    // Query any other OpenGL capabilities here
}
 
// Now check that the OpenGL capabilities are sufficient for your application
if (!extensions.Contains("GL_ARB_framebuffer_object"))
    throw new NotSupportedException("Missing extension: GL_ARB_framebuffer_object");

GameWindow is built on top of lower-level classes (NativeWindow and GraphicsContext). You could use those, but you would add complexity without gaining anything in performance, so I would recommend simply using GameWindow instead.

Quote:

Secondly, is there a simple way of detecting what is supported? My game was fairly primitive in how it used OpenGL... 2D textures, GL.DrawArrays, and some primitive drawing using GL.Begin / GL.End - all 1.x stuff as I recall.

Yes. OpenTK 1.1+ lists the required version or extension in the documentation tooltip of each OpenGL function. You need to compare the OpenGL version and extension list supported by the current system against the version and extensions required by your game.

Additionally, you need to ensure that your 2d texture size and format are supported on the target system.

The OpenGL Diagnostics sample might be of use here.

richardjmoss's picture

Hello,

Many thanks for the quick reply. I took a quick look at apitrace and that looks like it'll be useful to me.

Also thanks for the background context, I'll stick with the GameWindow then and I've started poking through the diagnostics sample you referenced.

Regards;
Richard Moss