Detect if OpenGL is present/works?

BlitzMax Forums/BlitzMax Beginners Area/Detect if OpenGL is present/works?

Grey Alien(Posted 2006) [#1]
Hi, If I'm running a game in DirectX mode and I want to change to OpenGL mode, I'll call EndGraphics, then SetGraphicsDriver GLMax2DDriver() before calling Graphics. However, what happens if the PC doesn't have the correct OpenGL drivers or it fails etc? What is the cleanest way to detect a failure, so that maybe I can show a "Failed" message and go back to DirectX mode?

Many thanks in advance for any advice.


Dreamora(Posted 2006) [#2]
OpenGL can't fail. It will fallback to software on any system.

Which means the user will have quite bad performance unlike he/she has one of those cool 3,2Ghz HT systems with SiS onboard *ggg*


Grey Alien(Posted 2006) [#3]
OK cool, thanks.


GfK(Posted 2006) [#4]
Just a small note of caution...

My Blitzmax game runs very slow on my girlfriend's PC under DX (PC is below spec for the OS (WinXP) let alone running anything on it, but anyway...).

Under GL, it fails completely. I don't have the PC here so I can't investigate further for a couple of weeks.


Grey Alien(Posted 2006) [#5]
that's the sort of thing I meant. I wonder if there's ever a system where it can't drop back to software mode when OpenGL is enabled. Basically I don't users to switch on OpenGL, have the game bomb, and then not be able to get back in without editing an .ini file to change back to DirectX.


ImaginaryHuman(Posted 2006) [#6]
If you do a Try-Catch block around the SetGraphicsDriver() call, and if it throws an exception, it may indicate that OpenGL is not supported in some way.

I don't think there is anything in particular you can do to checks that kind of thing. If you just have a normal level of cautiousness about each step you take to open a display, ie using lots of Try/Catch and `If =Null` type of stuff, then you should be able to detect when something is misbehaving.

One thing I can tell you is that once you have established what should be a display, either using Graphics(), GLGraphics(), SetGraphics() or CanvasGraphics(), if and only if the display opened correctly will OpenGL return valid and useful information, e.g. glGetIntegerv(GL_RED_BITS,Varptr(a)). If for some reason the display did not open right, which will happen if you ask for some buffers that the mode you requested does not support, then anything OpenGL says is useless as it will give you default values back.

What I do is try opening the display then try drawing something to the backbuffer then do a Flip() to make sure it is visible, then set glReadBuffer(GL_FRONT) and use GLReadPixels() to read the area that you drew to to make sure there is some pixel data there, and if there is you know for sure everything opened right and the display is working and the user can see results. When the context did not open and is not working, it won't render or flip the data. One thing to bear in mind is that on some systems 0,0 is topleft, on others it is bottom left, so draw something to both corners and test both corners to be sure. If you get proper pixel data back rather than black (use cls before drawing), then you know OpenGL context is valid and will report correct data, then use glGetIntegerv() to read state from OpenGL - it will be reliable. And you will find that you get some buffers you didn't ask for and you may not get some that you did ask for. You should check all of them to be sure.

Also note that some systems (mac at least) do not support OpenGL in fullscreen mode, due to not enough video ram and other matters. To trap this use a Try/Catch block around the line that opens the display (e.g. CreateGraphics(), Graphics() etc). If it makes an exception the display did not open at all. This may indicate GL is not supported or just that GL can't run in fullscreen. On the Mac you apparently need 16mb videoram to run GL in fullscreen. CreateGraphics() will set the display to fullscreen but will show nothing, and then SetGraphics will make an exception.

Note you also cannot ever be sure that using glDrawBuffer(GL_BACK) will actually draw to the back. On some systems the identification of which buffer is which is totally blind. You also probably cannot draw to the front buffer on some systems, they just wont allow it. Just assume you're on the backbuffer, draw stuff and flip.

Note also that when you open a GL context, it will probably only open in at least 15-bit depth. If your desktop is 8-bit, the GL context may still be 15-bit internally and calls to read the bit depths will tell you so. It is automatically dithered down to 256-colors by the o/s or GL driver when you flip. If you don't have at least 15-bits total for the RGB components, I would close it down and request more bit depth because if you get an index buffer instead of RGBA it'll give you very unpredictable results.

Note also that some systems return 0 as the hertz rate of the display, even within the o/s. You'll have to use a guesstimated software rate in that case.


Grey Alien(Posted 2006) [#7]
AngelDaniel thanks for all that info. Yeah I found out about the 0Hz thing on PCs a little while back. Basically my graphics code first checks GraphicsModeExists then checks the result of Graphics just in case. I was wondering if this line: SetGraphicsDriver GLMax2DDriver() can return any errors, maybe it won't until Graphics is called. Problem is not being able to test it. But I think I will bung a try catch round SetGraphicsDriver just in case, thanks.


Robert Cummings(Posted 2006) [#8]
OpenGL can't fail. It will fallback to software on any system.


WRONG. Blitzmax crashes like hell on the software opengl driver. It just plain BREAKS.


ImaginaryHuman(Posted 2006) [#9]
SetGraphicsDriver wont return any error but it will fail to set the driver if there is some problem, throwing an exception, so you might as well trap it to be on the safe side.


Gabriel(Posted 2006) [#10]
This has been discussed ad nauseum on IndieGamer and other forums, without much in the way of cast iron solutions, so I'm pretty sure you're going to struggle to do this unless you think creatively. Perhaps not the best suggestion, but an example of what I mean by thinking creatively.

After the graphics mode is set but before the game proper begins, write something to your ini/log file. When the game starts up ( and make sure it's not the first time the game has ever been run by putting another flag in your ini file to account for this ) see if that "the game ran ok last time" flag has been set. If not, pop up a dialog telling the user that the game did not shut down properly last time it was run, and would they like to run in "safe" mode. And revert to software rendering in SDL or whatever your backup is. Also, you'd probably want to tell them where they can go to set it back to DX / OGL if they find that the game is running slowly and want to get out of "safe mode" again.

Or perhaps create and destroy a texture as soon as the graphics mode is set and check that they are valid. If not, same as above.

Or perhaps count the time the game was run for. If it closes down in less than 5 seconds, or if there is no record in the ini file that your game shut down properly ( write something to the ini/debug when the game shuts down ) then it must not have run correctly, and you can offer to run in safe mode or whatever.

Just a thought, because I don't think you're ever gonna find a perfect way of detecting it directly.


Robert Cummings(Posted 2006) [#11]
You know, Blitzmax should just return false or null for Graphics() if it can't get any driver working...


ImaginaryHuman(Posted 2006) [#12]
It appears there are no perfect ways of detecting anything to with hardware-related issues - anything to do with driver support, availability, interfacing with the o/s, etc, it's all a bit sketchy, you just have to do what you can and fake it the rest of the time.

The file idea is good, I am using this also to check for previous crashes as a last resort.


Grey Alien(Posted 2006) [#13]
yeah thanks, I might do the file idea, we'll see...