146 lines · 3.6 KB · C
RawDownload
#ifndef __interface__OpenGlSupport__
#define __interface__OpenGlSupport__

#include "InterfaceConfig.h"
#include "Log.h"

// 
// Macro to log OpenGl errors.
// Example: oglLog( glPushMatrix() );
//
#define oGlLog(stmt) \
    stmt; \
    { \
        GLenum e = glGetError(); \
        if (e != GL_NO_ERROR) { \
            printLog(__FILE__ ":"  oGlLog_stringize(__LINE__) \
                     " [OpenGL] %s\n", gluErrorString(e)); \
        } \
    } \
    (void) 0

#define oGlLog_stringize(x) oGlLog_stringize_i(x)
#define oGlLog_stringize_i(x) # x

// 
// Encapsulation of the otherwise lengthy call sequence to compile
// and link shading pipelines.
//
class OGlProgram {

    GLuint _hndProg;

public:

    OGlProgram() : _hndProg(0) { }

    ~OGlProgram() { if (_hndProg != 0u) { glDeleteProgram(_hndProg); } }

    // no copy/assign
    OGlProgram(OGlProgram const&); // = delete;
    OGlProgram& operator=(OGlProgram const&); // = delete;

#if 0 // let's keep this commented, for now (C++11)

    OGlProgram(OGlProgram&& disposable) : _hndProg(disposable._hndProg) {

        disposable._hndProg = 0;
    }

    OGlProgram& operator=(OGlProgram&& disposable) {

        GLuint tmp = _hndProg;
        _hndProg = disposable._hndProg;
        disposable._hndProg = tmp;
    }
#endif

    // 
    // Activates the executable for rendering.
    // Shaders must be added and linked before this will work.
    // 
    void activate() const {

        if (_hndProg != 0u) {

            oGlLog( glUseProgram(_hndProg) );
        }
    }

    // 
    // Adds a shader to the program.
    // 
    bool addShader(GLenum type, GLchar const* cString) { 

        return addShader(type, 1, & cString);        
    }

    // 
    // Adds a shader to the program and logs to stderr.
    // 
    bool addShader(GLenum type, GLsizei nStrings, GLchar const** strings) {

        if (! _hndProg && !! glCreateProgram) { 

            _hndProg = glCreateProgram();
        }
        if (! _hndProg) { return false; }

        GLuint s = glCreateShader(type);
        glShaderSource(s, nStrings, strings, 0l);
        glCompileShader(s);
        GLint status; 
        glGetShaderiv(s, GL_COMPILE_STATUS, & status);
        if (status != 0)
            glAttachShader(_hndProg, s);
#ifdef NDEBUG // always fetch log in debug mode
        else
#endif
            fetchLog(s, glGetShaderiv, glGetShaderInfoLog);
        glDeleteShader(s);
        return !! status;
    }

    // 
    // Links the program and logs to stderr.
    // 
    bool link() {

        if (! _hndProg) { return false; }

        glLinkProgram(_hndProg);
        GLint status; 
        glGetProgramiv(_hndProg, GL_LINK_STATUS, & status);
#ifndef NDEBUG // always fetch log in debug mode
        fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog);
#endif
        if (status == 0) {
#ifdef NDEBUG // only on error in release mode
            fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog);
#endif
            glDeleteProgram(_hndProg);
            _hndProg = 0u;
            return false;

        } else {

            return true;
        }
    }

private:

    template< typename ParamFunc, typename GetLogFunc >
    void fetchLog(GLint handle, ParamFunc getParam, GetLogFunc getLog) {
        GLint logLength = 0;
        getParam(handle, GL_INFO_LOG_LENGTH, &logLength);
        if (!! logLength) {
            GLchar* message = new GLchar[logLength];
            getLog(handle, logLength, 0l, message);
            printLog("%s\n", message);
            delete[] message;
        }
    }
};

#endif