Tools.hh 9.5 KB
Newer Older
1 2 3 4 5
/***********************************************************************
 * Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/
Robert Menzel's avatar
Robert Menzel committed
6

7 8 9 10
#ifndef ACGL_OPENGL_TOOLS_HH
#define ACGL_OPENGL_TOOLS_HH

/*
11
 * Some OpenGL related helper functions.
12 13
 * All the error checking functions are in here.
 */
Robert Menzel's avatar
Robert Menzel committed
14 15

#include <ACGL/ACGL.hh>
Robert Menzel's avatar
Robert Menzel committed
16
#include <ACGL/OpenGL/GL.hh>
Robert Menzel's avatar
Robert Menzel committed
17 18

namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
19
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
20

21 22 23 24
//! queries some limits of the runtime which are used in ACGL internally. Client apps should not rely on these values, they are subject to changes. Gets called by ACGL::init()
void initRuntimeDependentLimits();
extern GLfloat ACGL_MAX_TEXTURE_MAX_ANISOTROPY;

Robert Menzel's avatar
Robert Menzel committed
25
//! returns the size in bytes of the common gl types named by there GLenums.
Robert Menzel's avatar
Robert Menzel committed
26 27 28 29
inline GLint getGLTypeSize ( GLenum _type )
{
    switch(_type)
    {
Robert Menzel's avatar
Robert Menzel committed
30 31
        case GL_BYTE:           return sizeof(GLbyte);
        case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
Robert Menzel's avatar
Robert Menzel committed
32 33 34 35 36
        case GL_SHORT:          return sizeof(GLshort);
        case GL_UNSIGNED_SHORT: return sizeof(GLushort);
        case GL_INT:            return sizeof(GLint);
        case GL_UNSIGNED_INT:   return sizeof(GLuint);
        case GL_FLOAT:          return sizeof(GLfloat);
37
#ifndef ACGL_OPENGL_ES
Robert Menzel's avatar
Robert Menzel committed
38
        case GL_DOUBLE:         return sizeof(GLdouble);
39
#endif
Robert Menzel's avatar
Robert Menzel committed
40

41 42 43
        //case GL_INT64_NV:       return sizeof(GLint64);
        //case GL_UNSIGNED_INT64_NV: return sizeof(GLuint64);
        //case GL_HALF_FLOAT:     return sizeof(GLhalf);
Robert Menzel's avatar
Robert Menzel committed
44
        case GL_FIXED:          return 4; // fixed are packed in a 32bit int (see 2.1.2 of the spec.)
Robert Menzel's avatar
Robert Menzel committed
45 46 47 48
    }
    return 0;
}

49 50
inline GLuint getNumberOfChannels( GLenum _format )
{
51
    // GLES formats:
52
    if (_format == GL_ALPHA || _format == GL_DEPTH_COMPONENT) return 1;
53 54
    if (_format == GL_RGB)  return 3;
    if (_format == GL_RGBA) return 4;
55 56 57 58 59 60
#ifdef ACGL_OPENGL_CORE_PROFILE
    // removed from core:
    if (_format == GL_LUMINANCE)  return 1;
    if (_format == GL_LUMINANCE_ALPHA)  return 2;
#endif

61 62 63
#ifndef ACGL_OPENGL_ES
    // additional desktop formats:
    if ( _format == GL_R8I  || _format == GL_R16I  || _format == GL_R32I
64 65
                        || _format == GL_R8UI || _format == GL_R16UI || _format == GL_R32UI
                                              || _format == GL_R16F  || _format == GL_R32F )   return 1;
66
    if (_format == GL_RED_INTEGER || _format == GL_GREEN_INTEGER || _format == GL_BLUE_INTEGER ) return 1;
67 68 69 70 71

    if (_format == GL_RG || _format == GL_RG8I  || _format == GL_RG16I  || _format == GL_RG32I
                         || _format == GL_RG8UI || _format == GL_RG16UI || _format == GL_RG32UI
                                                || _format == GL_RG16F  || _format == GL_RG32F )   return 2;

72
    if (_format == GL_RGB8I  || _format == GL_RGB16I  || _format == GL_RGB32I
73 74 75 76
                          || _format == GL_RGB8UI || _format == GL_RGB16UI || _format == GL_RGB32UI
                                                  || _format == GL_RGB16F  || _format == GL_RGB32F )   return 3;
    if (_format == GL_BGR  || _format == GL_RGB_INTEGER  || _format == GL_BGR_INTEGER)  return 3;

77
    if ( _format == GL_RGBA8I  || _format == GL_RGBA16I  || _format == GL_RGBA32I
78 79 80
                           || _format == GL_RGBA8UI || _format == GL_RGBA16UI || _format == GL_RGBA32UI
                                                    || _format == GL_RGBA16F  || _format == GL_RGBA32F )   return 4;
    if (_format == GL_BGRA || _format == GL_RGBA_INTEGER || _format == GL_BGRA_INTEGER) return 4;
81 82
#endif
    
83 84 85
    return 1; // unknown number of channels, assume 1
}

86 87 88 89 90 91
uint32_t getOpenGLMinorVersionNumber();
uint32_t getOpenGLMajorVersionNumber();

// returns the combined version number as 10*major + minor for easy comparing
uint32_t getOpenGLVersionNumber();

92
// query support for specific shader stages:
93 94
bool doesSupportGeometryShader();
bool doesSupportTessellationShader();
95 96 97
bool doesSupportComputeShader();


98 99
// Define the shader kinds for older and embedded GL versions so the file extension detection
// can work correctly.
100 101 102 103 104 105 106 107 108 109 110
#ifndef GL_GEOMETRY_SHADER
#define GL_GEOMETRY_SHADER 0x8DD9
#endif
#ifndef GL_TESS_CONTROL_SHADER
#define GL_TESS_EVALUATION_SHADER 0x8E87
#define GL_TESS_CONTROL_SHADER 0x8E88
#endif
#ifndef GL_COMPUTE_SHADER
#define GL_COMPUTE_SHADER 0x91B9
#endif

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
struct ShaderEndings
{
    const char *ending;
    GLenum      type;
};
const ShaderEndings sShaderEndings[  ] = {
    {"vsh",  GL_VERTEX_SHADER},
    {"vert", GL_VERTEX_SHADER},
    {"tcsh", GL_TESS_CONTROL_SHADER},
    {"tcs",  GL_TESS_CONTROL_SHADER},
    {"tesh", GL_TESS_EVALUATION_SHADER},
    {"tes",  GL_TESS_EVALUATION_SHADER},
    {"gsh",  GL_GEOMETRY_SHADER},
    {"geo",  GL_GEOMETRY_SHADER},
    {"fsh",  GL_FRAGMENT_SHADER},
    {"frag", GL_FRAGMENT_SHADER},
    {"csh",  GL_COMPUTE_SHADER},
    {"cs",   GL_COMPUTE_SHADER}
};

// returns the GL_TESS_CONTROL_SHADER GL_TESS_EVALUATION_SHADER GL_GEOMETRY_SHADER GL_COMPUTE_SHADER
// GL_VERTEX_SHADER GL_FRAGMENT_SHADER or GL_INVALID_VALUE in case the shadertype was not detected
// if _ignoreUnsupportedShaderTypes is true, types unsupported by the current runtime will return
// an GL_INVALID_ENUM also.
GLenum getShaderTypeByFileEnding( const std::string _fileName, bool _ignoreUnsupportedShaderTypes = true );

// looks up the enum and gives a human readable version
const GLubyte* acglShaderTypeString( GLenum _shaderType );
139

Robert Menzel's avatar
Robert Menzel committed
140 141 142
// for every OpenGL error enum this will return a human readable version of it
// similar to gluErrorString, but that function is not available on all plattforms
// (read: iOS)
143
const GLubyte* acglErrorString( GLenum _errorCode );
Robert Menzel's avatar
Robert Menzel committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

/*
 * This function can be used outside of the ACGL framework to check always(!) for
 * OpenGL errors. It will print the errors and return the error code of the last one.
 * Each OpenGL command can only throw one error, errors can only stack up if this
 * function or glGetError was not called often enough (and some OpenGL implementations
 * will forget old errors if new ones occur).
 */
#define openGLError() openGLError_( __FILE__, __LINE__ )

/*
 * This function is used internally in ACGL - but not directly. It gets called from all
 * other rare/common/critical error checks. The __FILE__ __LINE macros have to be used in
 * those to get the correct values from the caller file, if we would use the macro
 * above we could get the file/line from this file, which isn't helping.
 */
GLenum openGLError_( const char *_fileName, const unsigned long _lineNumber );

/*
 * Inside of ACGL we distinguish between rare, common and critical errors. Each kind can be
 * switched off which turns the function into nothing after compiler optimization. If an
 * error check is turned off it will always behave as if there was no error, even if there
 * is one...
 *
 * Per default a debug build enables critical and common errors, a release build only critical
 * ones.
 *
 * We have two functions for each kind:
 * openGL____Error()        will print error messages and return the last error (or GL_NO_ERROR)
 * openGL____ErrorOccured() will print error messages and retrun true if there was an error
 *
 * The definition of rare/common/critical is a bit fuzzy:
 *
 * critical: Errors which can occur even in a bug-free app, like out-of-memory errors.
 *           These checks are rare, stuff like glCreate calls get checked here.
 *           Tests for critical errors should not impact the performance of the app measurably.
 *
 * common:   
 *           Errors which are quite common while developing. Misuse of the library etc.
 *           Setting uniforms which don't exist or shader compile errors are candidates for
 *           common errors. Places where OpenGL resources are calles by a string etc.
 *
 * rare:     Errors which are so uncommon that we don't even check those ina normal debug build.
 *           Switching these on can impact performance as there can be alot of them. If theres a
 *           OpenGL error somewhere in the code, switch these checks on to find the correct spot.
 *
 * OpenGL error checks that are more complicated than just a glGetError call will be wrapped in the
 * same defines, this can be used in application code as well.
 *
 */
194 195 196 197

inline GLenum openGLErrorDummy()        { return GL_NO_ERROR; }
inline bool   openGLErrorOccuredDummy() { return false; }

Robert Menzel's avatar
Robert Menzel committed
198
#ifdef ACGL_CHECK_CRITICAL_GL_ERRORS
Robert Menzel's avatar
Robert Menzel committed
199 200
# define openGLCriticalError()         ACGL::OpenGL::openGLError_( __FILE__, __LINE__ )
# define openGLCriticalErrorOccured() (ACGL::OpenGL::openGLError_( __FILE__, __LINE__ ) != GL_NO_ERROR)
Robert Menzel's avatar
Robert Menzel committed
201
#else
Robert Menzel's avatar
Robert Menzel committed
202 203
# define openGLCriticalError()         ACGL::OpenGL::openGLErrorDummy()
# define openGLCriticalErrorOccured()  ACGL::OpenGL::openGLErrorOccuredDummy()
Robert Menzel's avatar
Robert Menzel committed
204 205 206
#endif

#ifdef ACGL_CHECK_COMMON_GL_ERRORS
Robert Menzel's avatar
Robert Menzel committed
207 208
# define openGLCommonError()         ACGL::OpenGL::openGLError_( __FILE__, __LINE__ )
# define openGLCommonErrorOccured() (ACGL::OpenGL::openGLError_( __FILE__, __LINE__ ) != GL_NO_ERROR)
Robert Menzel's avatar
Robert Menzel committed
209
#else
Robert Menzel's avatar
Robert Menzel committed
210 211
# define openGLCommonError()         ACGL::OpenGL::openGLErrorDummy()
# define openGLCommonErrorOccured()  ACGL::OpenGL::openGLErrorOccuredDummy()
Robert Menzel's avatar
Robert Menzel committed
212 213 214
#endif

#ifdef ACGL_CHECK_RARE_GL_ERRORS
Robert Menzel's avatar
Robert Menzel committed
215 216
# define openGLRareError()         ACGL::OpenGL::openGLError_( __FILE__, __LINE__ )
# define openGLRareErrorOccured() (ACGL::OpenGL::openGLError_( __FILE__, __LINE__ ) != GL_NO_ERROR)
Robert Menzel's avatar
Robert Menzel committed
217
#else
Robert Menzel's avatar
Robert Menzel committed
218 219
# define openGLRareError()         ACGL::OpenGL::openGLErrorDummy()
# define openGLRareErrorOccured()  ACGL::OpenGL::openGLErrorOccuredDummy()
Robert Menzel's avatar
Robert Menzel committed
220 221
#endif

Robert Menzel's avatar
Robert Menzel committed
222
} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
223 224
} // ACGL

225
#endif // ACGL_OPENGL_TOOLS_HH
Robert Menzel's avatar
Robert Menzel committed
226