Tools.cc 6.81 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

Robert Menzel's avatar
Robert Menzel committed
7
#include <ACGL/ACGL.hh>
Robert Menzel's avatar
Robert Menzel committed
8
#include <ACGL/OpenGL/Tools.hh>
9
#include <ACGL/Base/FileHelpers.hh>
10
#include <ACGL/OpenGL/glloaders/extensions.hh>
Robert Menzel's avatar
Robert Menzel committed
11 12

namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
13
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
14

15 16 17 18 19 20 21 22 23 24
GLfloat ACGL_MAX_TEXTURE_MAX_ANISOTROPY = -1.0f;
void initRuntimeDependentLimits()
{
    if ( ACGL_EXT_texture_filter_anisotrophic() ) {
        glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ACGL_MAX_TEXTURE_MAX_ANISOTROPY );
    } else {
        ACGL_MAX_TEXTURE_MAX_ANISOTROPY = 0.0f;
    }
}

25 26 27 28
//
// This is a "private" function that should not be called from outside of this file.
//
// glGetIntegerv(GL_MAJOR_VERSION... and glGetIntegerv(GL_MINOR_VERSION... are great, but
29
// require OpenGL 3.0 and are not supported on ES 2 :-( so the VERSION string has to get parsed...
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
//
// OpenGL spec:
// The VERSION ... strings are laid out as follows:
// <version number><space><vendor-specific information>
//
// OpenGL ES spec:
// The VERSION string is laid out as follows:
// "OpenGL ES N.M vendor-specific information"
//
// both specs:
// The version number is either of the form major_number.minor_number or
// major_number.minor_number.release_number, where the numbers all have one or more digits.
//
uint32_t privateGetOpenGLVersion( int _type )
{
    static uint32_t OGLminor   = 0;
    static uint32_t OGLmajor   = 0;
    static uint32_t OGLversion = 0;

    if (OGLversion == 0) {
        // calculate the version numbers once:
        // NOTE: similar to GLEW we assume here, that the minor and major numbers
        //       only have one digit. We also ignore release numbers. This will fail e.g. for OpenGL 10.0
        const GLubyte* versionString;
54
        openGLRareError(); // clear errors
55 56 57 58 59 60 61 62 63 64 65 66
        versionString = glGetString(GL_VERSION);
        if (openGLRareErrorOccured()) {
            ACGL::Utils::error() << "could not query OpenGL version!" << std::endl;
            return false;
        }

        int positionOfFirstDot = 0;
        while ((versionString[positionOfFirstDot] != '\0') && (versionString[positionOfFirstDot] != '.')) ++positionOfFirstDot;

        OGLmajor = versionString[positionOfFirstDot-1] - '0';
        OGLminor = versionString[positionOfFirstDot+1] - '0';

67 68
        if (OGLmajor > 9) OGLmajor = 0;
        if (OGLminor > 9) OGLminor = 0;
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

        OGLversion = OGLmajor*10 + OGLminor;
    }
    switch (_type) {
        case 0: return OGLminor;
        case 1: return OGLmajor;
        default: return OGLversion;
    };
}

uint32_t getOpenGLMinorVersionNumber()
{
    return privateGetOpenGLVersion( 0 );
}

uint32_t getOpenGLMajorVersionNumber()
{
    return privateGetOpenGLVersion( 1 );
}

uint32_t getOpenGLVersionNumber()
{
    return privateGetOpenGLVersion( 2 );
}

94 95 96 97 98
bool doesSupportGeometryShader()
{
#ifdef ACGL_OPENGL_ES
    return false;
#else
99
    return (ACGL_EXT_geometry_shader4() || ACGL_ARB_geometry_shader4() || (getOpenGLVersionNumber() >= 32));
100 101 102 103 104 105 106 107
#endif
}

bool doesSupportTessellationShader()
{
#ifdef ACGL_OPENGL_ES
    return false;
#else
108
    return ( ACGL_ARB_tessellation_shader() || (getOpenGLVersionNumber() >= 40));
109 110 111
#endif
}

112 113 114 115 116
bool doesSupportComputeShader()
{
#ifdef ACGL_OPENGL_ES
    return false;
#else
117
    return ( ACGL_ARB_compute_shader() || (getOpenGLVersionNumber() >= 43));
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
#endif
}


GLenum getShaderTypeByFileEnding( const std::string _fileName, bool _ignoreUnsupportedShaderTypes )
{
    std::string fileEnding = ACGL::Base::FileHelpers::getFileEnding( _fileName );
    if( fileEnding.size() == 0 ) return GL_INVALID_ENUM;

    GLenum foundType = GL_INVALID_ENUM;

    // guess the shader type:
    for (unsigned int ending = 0; ending < sizeof(sShaderEndings) / sizeof(ShaderEndings); ++ending)
    {
        if ( fileEnding == sShaderEndings[ending].ending )
        {
            foundType = sShaderEndings[ending].type;
            break;
        }
    }

    if (_ignoreUnsupportedShaderTypes) {
        if (foundType == GL_GEOMETRY_SHADER        && !doesSupportGeometryShader()    ) return GL_INVALID_ENUM;
        if (foundType == GL_TESS_CONTROL_SHADER    && !doesSupportTessellationShader()) return GL_INVALID_ENUM;
        if (foundType == GL_TESS_EVALUATION_SHADER && !doesSupportTessellationShader()) return GL_INVALID_ENUM;
        if (foundType == GL_COMPUTE_SHADER         && !doesSupportComputeShader()     ) return GL_INVALID_ENUM;
    }

    return foundType;
}

const GLubyte* acglShaderTypeString( GLenum _shaderType )
{
    if      (_shaderType == GL_VERTEX_SHADER)          { return (GLubyte*) "vertex shader"; }
    else if (_shaderType == GL_TESS_CONTROL_SHADER)    { return (GLubyte*) "tessellation control shader"; }
    else if (_shaderType == GL_TESS_EVALUATION_SHADER) { return (GLubyte*) "tessellation evaluation shader"; }
    else if (_shaderType == GL_GEOMETRY_SHADER)        { return (GLubyte*) "geometry shader"; }
    else if (_shaderType == GL_FRAGMENT_SHADER)        { return (GLubyte*) "fragment shader"; }
    else if (_shaderType == GL_COMPUTE_SHADER)         { return (GLubyte*) "compute shader"; }
    else {
        return (GLubyte*) "unknown shader type";
    }
}

162
const GLubyte* acglErrorString( GLenum _errorCode )
Robert Menzel's avatar
Robert Menzel committed
163
{
Robert Menzel's avatar
Robert Menzel committed
164 165
    // no gluErrorString on iOS, problems on visual studio...
    // Only 3.2+ Core and ES 2.0+ errors belong here:
166 167
    if      (_errorCode == GL_INVALID_ENUM)                  { return (GLubyte*) "GL_INVALID_ENUM"; }
    else if (_errorCode == GL_INVALID_VALUE)                 { return (GLubyte*) "GL_INVALID_VALUE"; }
Robert Menzel's avatar
Robert Menzel committed
168
    else if (_errorCode == GL_INVALID_OPERATION)             { return (GLubyte*) "GL_INVALID_OPERATION"; }
169
    else if (_errorCode == GL_INVALID_FRAMEBUFFER_OPERATION) { return (GLubyte*) "GL_INVALID_FRAMEBUFFER_OPERATION"; }
Robert Menzel's avatar
Robert Menzel committed
170
    else if (_errorCode == GL_OUT_OF_MEMORY)                 { return (GLubyte*) "GL_OUT_OF_MEMORY"; }
171
    else if (_errorCode == GL_NO_ERROR)                      { return (GLubyte*) "GL_NO_ERROR"; }
Robert Menzel's avatar
Robert Menzel committed
172
    else {
173
        return (GLubyte*) "unknown error";
Robert Menzel's avatar
Robert Menzel committed
174 175 176 177 178 179 180
    }
}



GLenum openGLError_( const char *_fileName, const unsigned long _lineNumber )
{
181 182 183 184 185 186 187 188 189
    GLenum currentError = glGetError();
    GLenum lastError    = currentError;

    // OpenGL does not forbit the implementation to stack up more than one error code
    // so we have to check those in a loop:
    while ( currentError != GL_NO_ERROR ) {
        ACGL::Utils::error() << "GL error in file " << _fileName << ":" << _lineNumber << " - " << acglErrorString( currentError ) << std::endl;
        lastError    = currentError;
        currentError = glGetError();
Robert Menzel's avatar
Robert Menzel committed
190 191
    }

192
    return lastError; // returns the last real error (in case there was at least one!)
Robert Menzel's avatar
Robert Menzel committed
193 194 195
}


Robert Menzel's avatar
Robert Menzel committed
196
} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
197 198
} // ACGL