From fd29e9c3ac9380156c4d3a084c8fa9331c4cd412 Mon Sep 17 00:00:00 2001
From: Robert Menzel <menzel@informatik.rwth-aachen.de>
Date: Fri, 19 Aug 2011 17:10:37 +0200
Subject: [PATCH] OpenGL Error check bugfixes & OpenGL header fixes & OpenGL
 version checking

* OpenGL error checking level can now be set via cmake
* OpenGL header configuration works better with external defines via cmake
* OpenGL version gets checked at runtime in the ACGL::init function and complains it the version it was compiled for is not present
---
 include/ACGL/ACGL.hh                     |   5 +-
 include/ACGL/Base/CompileTimeSettings.hh |  24 +++++-
 include/ACGL/OpenGL/GL.hh                | 100 +++++++++++++++++------
 src/ACGL/ACGL.cc                         |  48 ++++++++++-
 4 files changed, 147 insertions(+), 30 deletions(-)

diff --git a/include/ACGL/ACGL.hh b/include/ACGL/ACGL.hh
index e0f973c2..386e555c 100644
--- a/include/ACGL/ACGL.hh
+++ b/include/ACGL/ACGL.hh
@@ -28,8 +28,11 @@ namespace ACGL
  * it will init glew (if used).
  * Call this before calling any OpenGL functions or OpenGL related
  * ACGL stuff.
+ *
+ * Returns false if a critical error occured, in that case the ACGL behavior is
+ * not defined.
  */
-void init(void);
+bool init(void);
     
 };
 
diff --git a/include/ACGL/Base/CompileTimeSettings.hh b/include/ACGL/Base/CompileTimeSettings.hh
index aa95104e..cb5dabcc 100644
--- a/include/ACGL/Base/CompileTimeSettings.hh
+++ b/include/ACGL/Base/CompileTimeSettings.hh
@@ -13,17 +13,17 @@
  * and critical&common in debug build.
  *
  * This can get overwritten with a compile flag define:
- *  -DACGL_CHECK_NO_GL_ERRORS
+ *  -DACGL_ERROR_LEVEL_EC0
  *    No error checking at all
- *  -DACGL_CHECK_CRITICAL_GL_ERRORS
+ *  -DACGL_ERROR_LEVEL_EC1
  *    Places will get checked where errors like out of memory can occur.
  *    This will detect runtime errors which can happen even if the program
  *    is bug free.
  *    Switching this on shouldn't be a performance hit.
- *  -DACGL_CHECK_COMMON_GL_ERRORS
+ *  -DACGL_ERROR_LEVEL_EC2
  *    Problems that happen more often while developing like typos in uniform
  *    names. All placed where strings are used to call OpenGL objects etc.
- *  -DACGL_CHECK_RARE_GL_ERRORS
+ *  -DACGL_ERROR_LEVEL_EC3
  *    Most likely bugs in ACGL itself or wrong usage. If there are strange errors
  *    switch this on to find the reason more quickly. Even normal development
  *    should work without this. Results in a lot of glGetError!
@@ -31,6 +31,22 @@
  * Note that all error levels also include the higher ones (COMMON also adds CRITICAL).
  */
 
+/*
+ * Map CMake generated error-level defines to internally used, more readable defines
+ */
+#ifdef ACGL_ERROR_LEVEL_EC0
+#   define ACGL_CHECK_NO_GL_ERRORS
+#endif
+#ifdef ACGL_ERROR_LEVEL_EC1
+#   define ACGL_CHECK_CRITICAL_GL_ERRORS
+#endif
+#ifdef ACGL_ERROR_LEVEL_EC2
+#   define ACGL_CHECK_COMMON_GL_ERRORS
+#endif
+#ifdef ACGL_ERROR_LEVEL_EC3
+#   define ACGL_CHECK_RARE_GL_ERRORS
+#endif
+
 
 #ifndef ACGL_CHECK_NO_GL_ERRORS
 # ifndef ACGL_CHECK_CRITICAL_GL_ERRORS
diff --git a/include/ACGL/OpenGL/GL.hh b/include/ACGL/OpenGL/GL.hh
index 0aa9361a..4852c56a 100644
--- a/include/ACGL/OpenGL/GL.hh
+++ b/include/ACGL/OpenGL/GL.hh
@@ -13,25 +13,67 @@
  * While these includes are located in a subdirectory of GL/ on most systems,
  * Apple hides them on different locations.
  *
- * This header can get configured via compile-time defines:
  *
- * -DCOMPILE_WITH_QT      : If using ACGL with QT this will also include the qgl.h
- * -DCOMPILED_FOR_OGL     : 20 21 30 31 32 33 40 41
- * -DCOMPILED_FOR_OGL_PROFILE_FULL : full OpenGL profile (>= 2.1)
- * -DCOMPILED_FOR_OGL_PROFILE_CORE : core OpenGL profile (>= 3.2)
- * -DCOMPILED_FOR_OGL_PROFILE_ES   : embedded profile (OpenGL ES 2.0)
- * -DSIMULATE_OGL_ES               : Simulate ES feature set with desktop OGL
- *
- * Not all combinations are valid!
+ * This wrapper can get configured with external defines:
+ * QT_OPENGL_LIB               : include also the QT OpenGL headers and maybe use QT for other
+ *                               graphics related stuff, like image loading for textures.
+ * ACGL_OPENGL_SUPPORT_CORE_41 : (or other versions): basicly ACGL_OPENGL_PROFILE_* and ACGL_OPENGL_VERSION_*
+ *                               combined!
+ * ACGL_OPENGL_PROFILE_CORE    : CORE: only support for CORE functions, demands a CORE OpenGL context
+ *                               FULL: support for CORE and deprecated functions
+ * ACGL_OPENGL_VERSION_41      : (or other versions): minimal OpenGL version that can be assumed to be present.
+ *                               The app can't run on older contexts and will probably terminate at startup.
+ *                               Set this to a low version and it will run on lost machines
+ *                               Set this to a high version and less run-time checks have to be performed to
+ *                               work around missing features (like querying extensions etc).
+ * ACGL_PLATFORM_DESKTOP       : DESKTOP vs. MOBILE plattform = GL vs. GL ES
  */
 
-// TODO: remove and move to cmake:
-#define COMPILE_WITH_QT
+// If there is a demand for a core context, we should include the new core headers as well,
+// sadly, these are not very good supported yet, so this stays commented out for a while :-(
+#ifdef ACGL_OPENGL_PROFILE_CORE
+//#   define ACGL_OPENGL_PROFILE_CORE_HEADER
+#endif
+
+// To compare the OpenGL version number we define a new ACGL_OPENGL_VERSION XY define here
+// analog to ACGL_OPENGL_VERSION_XY
+#ifdef ACGL_OPENGL_VERSION_21
+#   define ACGL_OPENGL_VERSION 21
+#else
+#   ifdef ACGL_OPENGL_VERSION_30
+#      define ACGL_OPENGL_VERSION 30
+#   else
+#       ifdef ACGL_OPENGL_VERSION_31
+#          define ACGL_OPENGL_VERSION 31
+#       else
+#           ifdef ACGL_OPENGL_VERSION_32
+#              define ACGL_OPENGL_VERSION 32
+#           else
+#               ifdef ACGL_OPENGL_VERSION_33
+#                  define ACGL_OPENGL_VERSION 33
+#               else
+#                   ifdef ACGL_OPENGL_VERSION_40
+#                       define ACGL_OPENGL_VERSION 40
+#                   else
+#                       ifdef ACGL_OPENGL_VERSION_41
+#                           define ACGL_OPENGL_VERSION 41
+#                       else
+#                           ifdef ACGL_OPENGL_VERSION_42
+#                               define ACGL_OPENGL_VERSION 42
+#                           else
+//                              failback:
+#                               define ACGL_OPENGL_VERSION_32
+#                               define ACGL_OPENGL_VERSION 32
+#                           endif
+#                       endif
+#                   endif
+#               endif
+#           endif
+#       endif
+#   endif
+#endif
+
 
-// We can try to build against OpenGL core profile or compatibility (core means automatically
-// 3.2 or higher). On MacOS X 10.7 Lion we can choose between 2.1 or 3.2 core, but 3.2
-// compatibility is not an option.
-//#define USE_OPENGL_CORE_PROFILE
 
 // If we're compiling for an Apple system we need this to distinquish between Mac and iOS:
 #ifdef __APPLE__
@@ -42,11 +84,20 @@
 #define USE_GLEW
 
 #if (defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR))
-    #if (TARGET_OS_IPHONE == 1)
-        #define PLATFORM_IOS
-        #define OPENGL_ES
-        #undef USE_GLEW // no glew support on iOS
-    #endif
+#   if (TARGET_OS_IPHONE == 1)
+#       define PLATFORM_IOS
+#       define OPENGL_ES
+#       undef USE_GLEW // no glew support on iOS
+#   endif
+#else
+//  no iOS device...
+#   ifdef ACGL_PLATFORM_MOBILE
+//      ...but mobile:
+//      maybe maemo or android: first one to program for these plattforms should add
+//      the correct includes here!
+#       error UNKNOWN mobile plattform! Dont know what to include!
+#       define OPENGL_ES
+#   endif
 #endif
 
 // we have allways to include glew first!
@@ -71,22 +122,23 @@
         #import <OpenGLES/ES2/glext.h>
     #else
         // Desktop MacOS X:
-        #ifdef USE_OPENGL_CORE_PROFILE
+        #ifdef ACGL_OPENGL_PROFILE_CORE
+//          On MacOS X, all OpenGL versions >=3.2 are core and have to use the new headers:
             #include <GL3/gl3.h>
         #else
             #include <OpenGL/gl.h>
         #endif
     #endif
 #else
-    #ifdef USE_OPENGL_CORE_PROFILE
+    #ifdef ACGL_OPENGL_PROFILE_CORE_HEADER
         #include <GL3/gl3.h>
     #else
         #include <GL/gl.h>
     #endif
 #endif
 
-#ifdef COMPILE_WITH_QT
-    #include <QtOpenGL/qgl.h>
+#ifdef QT_OPENGL_LIB
+#   include <QtOpenGL/qgl.h>
 #endif // USE_QT
 
 #endif // ACGL_OPENGL_GL_HH
diff --git a/src/ACGL/ACGL.cc b/src/ACGL/ACGL.cc
index 292bc719..6e546e8f 100644
--- a/src/ACGL/ACGL.cc
+++ b/src/ACGL/ACGL.cc
@@ -6,13 +6,59 @@
 #include <ACGL/ACGL.hh>
 
 #include <ACGL/OpenGL/GL.hh>
+#include <ACGL/OpenGL/Tools.hh>
+#include <stdlib.h>
 
 namespace ACGL
 {
 
-void init(void)
+bool init(void)
 {
+    //
+    // init GLEW
+    //
+#ifdef USE_GLEW
     glewInit();
+    if (openGLCriticalErrorOccured()) {
+        ACGL::Utils::error() << "could not init GLEW!" << std::endl;
+        return false;
+    }
+#endif
+
+    //
+    // check OpenGL version
+    //
+
+    float openGLVersionF = atof( (const char*) glGetString(GL_VERSION) );
+    GLint openGLmajorVersion;
+    GLint openGLminorVersion;
+
+    if (openGLVersionF < 3.0) {
+        if (openGLVersionF >= 2.1) {
+            openGLmajorVersion = 2;
+            openGLminorVersion = 1;
+        } else {
+            ACGL::Utils::error() << "OpenGL version " << openGLVersionF << " not supported!" << std::endl;
+            return false;
+        }
+    } else {
+        // OpenGL 3.0 is needed for this (saves us float/ascii to int conversion)
+        glGetIntegerv(GL_MAJOR_VERSION, &openGLmajorVersion);
+        glGetIntegerv(GL_MINOR_VERSION, &openGLminorVersion);
+    }
+    if (openGLRareErrorOccured()) {
+        ACGL::Utils::error() << "could not query OpenGL version!" << std::endl;
+        return false;
+    }
+
+    ACGL::Utils::debug() << "OpenGL Version: " << openGLmajorVersion << "." << openGLminorVersion << std::endl;
+
+    uint32_t openGLVersion = (openGLmajorVersion*10 + openGLminorVersion);
+    if (openGLVersion < ACGL_OPENGL_VERSION) {
+       ACGL::Utils::error() << "At compile time an OpenGL context of version " << ACGL_OPENGL_VERSION
+                            << " was requested, but the current context only supports " << openGLVersion << std::endl;
+       return false;
+    }
 }
     
 };
-- 
GitLab