From e69c3360f6c5085a49bd33caee098d5708c712aa Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 28 Dec 2015 11:18:03 +0000 Subject: [PATCH] Reorganise GL initialisation. --- OpenRA.Platforms.Default/OpenGL.cs | 209 ++++++++++++++++------------- 1 file changed, 119 insertions(+), 90 deletions(-) diff --git a/OpenRA.Platforms.Default/OpenGL.cs b/OpenRA.Platforms.Default/OpenGL.cs index d23d536881..c65de6aea4 100644 --- a/OpenRA.Platforms.Default/OpenGL.cs +++ b/OpenRA.Platforms.Default/OpenGL.cs @@ -23,6 +23,15 @@ namespace OpenRA.Platforms.Default Justification = "C-style naming is kept for consistency with the underlying native API.")] internal static class OpenGL { + public enum GLFeatures + { + None = 0, + GL2OrGreater = 1, + FramebufferExt = 4, + } + + public static GLFeatures Features { get; private set; } + public const int GL_FALSE = 0; // ClearBufferMask @@ -338,81 +347,99 @@ namespace OpenRA.Platforms.Default public static void Initialize() { - CheckGlVersion(); - - if (SDL.SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object") == SDL.SDL_bool.SDL_FALSE) + // glGetError and glGetString are used in our error handlers + // so we want these to be available early. + try { - OpenGL.WriteGraphicsLog("OpenRA requires the OpenGL extension GL_EXT_framebuffer_object.\n" - + "Please try updating your GPU driver to the latest version provided by the manufacturer."); - throw new InvalidProgramException("Missing OpenGL extension GL_EXT_framebuffer_object. See graphics.log for details."); + glGetError = Bind("glGetError"); + glGetStringInternal = Bind("glGetString"); + } + catch (Exception) + { + throw new InvalidProgramException("Failed to initialize low-level OpenGL bindings. GPU information is not available"); } - glFlush = Bind("glFlush"); - glViewport = Bind("glViewport"); - glClear = Bind("glClear"); - glClearColor = Bind("glClearColor"); - glGetError = Bind("glGetError"); - glGetStringInternal = Bind("glGetString"); - glGetIntegerv = Bind("glGetIntegerv"); - glFinish = Bind("glFinish"); - glCreateProgram = Bind("glCreateProgram"); - glUseProgram = Bind("glUseProgram"); - glGetProgramiv = Bind("glGetProgramiv"); - glCreateShader = Bind("glCreateShader"); - glShaderSource = Bind("glShaderSource"); - glCompileShader = Bind("glCompileShader"); - glGetShaderiv = Bind("glGetShaderiv"); - glAttachShader = Bind("glAttachShader"); - glGetShaderInfoLog = Bind("glGetShaderInfoLog"); - glLinkProgram = Bind("glLinkProgram"); - glGetProgramInfoLog = Bind("glGetProgramInfoLog"); - glGetUniformLocation = Bind("glGetUniformLocation"); - glGetActiveUniform = Bind("glGetActiveUniform"); - glUniform1i = Bind("glUniform1i"); - glUniform1f = Bind("glUniform1f"); - glUniform2f = Bind("glUniform2f"); - glUniform1fv = Bind("glUniform1fv"); - glUniform2fv = Bind("glUniform2fv"); - glUniform3fv = Bind("glUniform3fv"); - glUniform4fv = Bind("glUniform4fv"); - glUniformMatrix4fv = Bind("glUniformMatrix4fv"); - glGenBuffers = Bind("glGenBuffers"); - glBindBuffer = Bind("glBindBuffer"); - glBufferData = Bind("glBufferData"); - glBufferSubData = Bind("glBufferSubData"); - glDeleteBuffers = Bind("glDeleteBuffers"); - glBindAttribLocation = Bind("glBindAttribLocation"); - glVertexAttribPointer = Bind("glVertexAttribPointer"); - glEnableVertexAttribArray = Bind("glEnableVertexAttribArray"); - glDisableVertexAttribArray = Bind("glDisableVertexAttribArray"); - glDrawArrays = Bind("glDrawArrays"); - glEnable = Bind("glEnable"); - glDisable = Bind("glDisable"); - glBlendEquation = Bind("glBlendEquation"); - glBlendFunc = Bind("glBlendFunc"); - glScissor = Bind("glScissor"); - glPushClientAttrib = Bind("glPushClientAttrib"); - glPopClientAttrib = Bind("glPopClientAttrib"); - glPixelStoref = Bind("glPixelStoref"); - glReadPixels = Bind("glReadPixels"); - glGenTextures = Bind("glGenTextures"); - glDeleteTextures = Bind("glDeleteTextures"); - glBindTexture = Bind("glBindTexture"); - glActiveTexture = Bind("glActiveTexture"); - glTexImage2D = Bind("glTexImage2D"); - glGetTexImage = Bind("glGetTexImage"); - glTexParameteri = Bind("glTexParameteri"); - glTexParameterf = Bind("glTexParameterf"); - glGenFramebuffersEXT = Bind("glGenFramebuffersEXT"); - glBindFramebufferEXT = Bind("glBindFramebufferEXT"); - glFramebufferTexture2DEXT = Bind("glFramebufferTexture2DEXT"); - glDeleteFramebuffersEXT = Bind("glDeleteFramebuffersEXT"); - glGenRenderbuffersEXT = Bind("glGenRenderbuffersEXT"); - glBindRenderbufferEXT = Bind("glBindRenderbufferEXT"); - glRenderbufferStorageEXT = Bind("glRenderbufferStorageEXT"); - glDeleteRenderbuffersEXT = Bind("glDeleteRenderbuffersEXT"); - glFramebufferRenderbufferEXT = Bind("glFramebufferRenderbufferEXT"); - glCheckFramebufferStatus = Bind("glCheckFramebufferStatus"); + DetectGLFeatures(); + if (!Features.HasFlag(GLFeatures.GL2OrGreater) || !Features.HasFlag(GLFeatures.FramebufferExt)) + { + WriteGraphicsLog("Unsupported OpenGL version: " + glGetString(OpenGL.GL_VERSION)); + throw new InvalidProgramException("OpenGL Version Error: See graphics.log for details."); + } + else + Console.WriteLine("OpenGL version: " + glGetString(OpenGL.GL_VERSION)); + + try + { + glFlush = Bind("glFlush"); + glViewport = Bind("glViewport"); + glClear = Bind("glClear"); + glClearColor = Bind("glClearColor"); + glGetIntegerv = Bind("glGetIntegerv"); + glFinish = Bind("glFinish"); + glCreateProgram = Bind("glCreateProgram"); + glUseProgram = Bind("glUseProgram"); + glGetProgramiv = Bind("glGetProgramiv"); + glCreateShader = Bind("glCreateShader"); + glShaderSource = Bind("glShaderSource"); + glCompileShader = Bind("glCompileShader"); + glGetShaderiv = Bind("glGetShaderiv"); + glAttachShader = Bind("glAttachShader"); + glGetShaderInfoLog = Bind("glGetShaderInfoLog"); + glLinkProgram = Bind("glLinkProgram"); + glGetProgramInfoLog = Bind("glGetProgramInfoLog"); + glGetUniformLocation = Bind("glGetUniformLocation"); + glGetActiveUniform = Bind("glGetActiveUniform"); + glUniform1i = Bind("glUniform1i"); + glUniform1f = Bind("glUniform1f"); + glUniform2f = Bind("glUniform2f"); + glUniform1fv = Bind("glUniform1fv"); + glUniform2fv = Bind("glUniform2fv"); + glUniform3fv = Bind("glUniform3fv"); + glUniform4fv = Bind("glUniform4fv"); + glUniformMatrix4fv = Bind("glUniformMatrix4fv"); + glGenBuffers = Bind("glGenBuffers"); + glBindBuffer = Bind("glBindBuffer"); + glBufferData = Bind("glBufferData"); + glBufferSubData = Bind("glBufferSubData"); + glDeleteBuffers = Bind("glDeleteBuffers"); + glBindAttribLocation = Bind("glBindAttribLocation"); + glVertexAttribPointer = Bind("glVertexAttribPointer"); + glEnableVertexAttribArray = Bind("glEnableVertexAttribArray"); + glDisableVertexAttribArray = Bind("glDisableVertexAttribArray"); + glDrawArrays = Bind("glDrawArrays"); + glEnable = Bind("glEnable"); + glDisable = Bind("glDisable"); + glBlendEquation = Bind("glBlendEquation"); + glBlendFunc = Bind("glBlendFunc"); + glScissor = Bind("glScissor"); + glPushClientAttrib = Bind("glPushClientAttrib"); + glPopClientAttrib = Bind("glPopClientAttrib"); + glPixelStoref = Bind("glPixelStoref"); + glReadPixels = Bind("glReadPixels"); + glGenTextures = Bind("glGenTextures"); + glDeleteTextures = Bind("glDeleteTextures"); + glBindTexture = Bind("glBindTexture"); + glActiveTexture = Bind("glActiveTexture"); + glTexImage2D = Bind("glTexImage2D"); + glGetTexImage = Bind("glGetTexImage"); + glTexParameteri = Bind("glTexParameteri"); + glTexParameterf = Bind("glTexParameterf"); + glGenFramebuffersEXT = Bind("glGenFramebuffersEXT"); + glBindFramebufferEXT = Bind("glBindFramebufferEXT"); + glFramebufferTexture2DEXT = Bind("glFramebufferTexture2DEXT"); + glDeleteFramebuffersEXT = Bind("glDeleteFramebuffersEXT"); + glGenRenderbuffersEXT = Bind("glGenRenderbuffersEXT"); + glBindRenderbufferEXT = Bind("glBindRenderbufferEXT"); + glRenderbufferStorageEXT = Bind("glRenderbufferStorageEXT"); + glDeleteRenderbuffersEXT = Bind("glDeleteRenderbuffersEXT"); + glFramebufferRenderbufferEXT = Bind("glFramebufferRenderbufferEXT"); + glCheckFramebufferStatus = Bind("glCheckFramebufferStatus"); + } + catch (Exception e) + { + OpenGL.WriteGraphicsLog("Failed to initialize OpenGL bindings.\nInner exception was: {0}".F(e)); + throw new InvalidProgramException("Failed to initialize OpenGL. See graphics.log for details."); + } } static T Bind(string name) @@ -420,27 +447,29 @@ namespace OpenRA.Platforms.Default return (T)(object)Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress(name), typeof(T)); } - static void CheckGlVersion() + public static void DetectGLFeatures() { - var versionString = OpenGL.glGetString(OpenGL.GL_VERSION); - var version = versionString.Contains(" ") ? versionString.Split(' ')[0].Split('.') : versionString.Split('.'); - - var major = 0; - if (version.Length > 0) - int.TryParse(version[0], out major); - - var minor = 0; - if (version.Length > 1) - int.TryParse(version[1], out minor); - - Console.WriteLine("Detected OpenGL version: {0}.{1}".F(major, minor)); - if (major < 2) + try { - OpenGL.WriteGraphicsLog("OpenRA requires OpenGL version 2.0 or greater and detected {0}.{1}".F(major, minor)); - throw new InvalidProgramException("OpenGL Version Error: See graphics.log for details."); - } + var versionString = glGetString(OpenGL.GL_VERSION); + var version = versionString.Contains(" ") ? versionString.Split(' ')[0].Split('.') : versionString.Split('.'); - CheckGlError(); + var major = 0; + if (version.Length > 0) + int.TryParse(version[0], out major); + + var minor = 0; + if (version.Length > 1) + int.TryParse(version[1], out minor); + + if (major >= 2 && minor >= 0) + Features |= GLFeatures.GL2OrGreater; + + var hasFramebufferExt = SDL.SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object") == SDL.SDL_bool.SDL_TRUE; + if (hasFramebufferExt) + Features |= GLFeatures.FramebufferExt; + } + catch (Exception) { } } public static void CheckGLError()