Andrzej KapolkaRemoved unused members.466d99b11 years agoHistory
1111 lines · 35.0 KB · C++
RawDownload
////  GLBackend.cpp//  interface/src/gpu////  Created by Sam Gateau on 10/27/2014.//  Copyright 2014 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//#include "GLBackend.h" #include <QDebug> #include "gpu/Batch.h" using namespace gpu; GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = {    (&::gpu::GLBackend::do_draw),    (&::gpu::GLBackend::do_drawIndexed),    (&::gpu::GLBackend::do_drawInstanced),    (&::gpu::GLBackend::do_drawIndexedInstanced),     (&::gpu::GLBackend::do_setInputFormat),    (&::gpu::GLBackend::do_setInputBuffer),    (&::gpu::GLBackend::do_setIndexBuffer),     (&::gpu::GLBackend::do_setModelTransform),    (&::gpu::GLBackend::do_setViewTransform),    (&::gpu::GLBackend::do_setProjectionTransform),     (&::gpu::GLBackend::do_glEnable),    (&::gpu::GLBackend::do_glDisable),     (&::gpu::GLBackend::do_glEnableClientState),    (&::gpu::GLBackend::do_glDisableClientState),     (&::gpu::GLBackend::do_glCullFace),    (&::gpu::GLBackend::do_glAlphaFunc),     (&::gpu::GLBackend::do_glDepthFunc),    (&::gpu::GLBackend::do_glDepthMask),    (&::gpu::GLBackend::do_glDepthRange),     (&::gpu::GLBackend::do_glBindBuffer),     (&::gpu::GLBackend::do_glBindTexture),    (&::gpu::GLBackend::do_glActiveTexture),     (&::gpu::GLBackend::do_glDrawBuffers),     (&::gpu::GLBackend::do_glUseProgram),    (&::gpu::GLBackend::do_glUniform1f),    (&::gpu::GLBackend::do_glUniform2f),    (&::gpu::GLBackend::do_glUniformMatrix4fv),     (&::gpu::GLBackend::do_glMatrixMode),    (&::gpu::GLBackend::do_glPushMatrix),    (&::gpu::GLBackend::do_glPopMatrix),    (&::gpu::GLBackend::do_glMultMatrixf),    (&::gpu::GLBackend::do_glLoadMatrixf),    (&::gpu::GLBackend::do_glLoadIdentity),    (&::gpu::GLBackend::do_glRotatef),    (&::gpu::GLBackend::do_glScalef),    (&::gpu::GLBackend::do_glTranslatef),     (&::gpu::GLBackend::do_glDrawArrays),    (&::gpu::GLBackend::do_glDrawRangeElements),     (&::gpu::GLBackend::do_glColorPointer),    (&::gpu::GLBackend::do_glNormalPointer),    (&::gpu::GLBackend::do_glTexCoordPointer),    (&::gpu::GLBackend::do_glVertexPointer),     (&::gpu::GLBackend::do_glVertexAttribPointer),    (&::gpu::GLBackend::do_glEnableVertexAttribArray),    (&::gpu::GLBackend::do_glDisableVertexAttribArray),     (&::gpu::GLBackend::do_glColor4f),     (&::gpu::GLBackend::do_glMaterialf),    (&::gpu::GLBackend::do_glMaterialfv),}; static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = {    GL_POINTS,    GL_LINES,    GL_LINE_STRIP,    GL_TRIANGLES,    GL_TRIANGLE_STRIP,    GL_QUADS,}; static const GLenum _elementTypeToGLType[NUM_TYPES]= {    GL_FLOAT,    GL_INT,    GL_UNSIGNED_INT,    GL_HALF_FLOAT,    GL_SHORT,    GL_UNSIGNED_SHORT,    GL_BYTE,    GL_UNSIGNED_BYTE,    GL_FLOAT,    GL_INT,    GL_UNSIGNED_INT,    GL_HALF_FLOAT,    GL_SHORT,    GL_UNSIGNED_SHORT,    GL_BYTE,    GL_UNSIGNED_BYTE};  GLBackend::GLBackend() :    _input(),    _transform(){ } GLBackend::~GLBackend() { } void GLBackend::renderBatch(Batch& batch) {    uint32 numCommands = batch.getCommands().size();    const Batch::Commands::value_type* command = batch.getCommands().data();    const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data();     GLBackend backend;     for (unsigned int i = 0; i < numCommands; i++) {        CommandCall call = _commandCalls[(*command)];        (backend.*(call))(batch, *offset);        command++;        offset++;    }} void GLBackend::checkGLError() {    GLenum error = glGetError();    if (!error) {        return;    }    else {        switch (error) {        case GL_INVALID_ENUM:            qDebug() << "An unacceptable value is specified for an enumerated argument.The offending command is ignored and has no other side effect than to set the error flag.";            break;        case GL_INVALID_VALUE:            qDebug() << "A numeric argument is out of range.The offending command is ignored and has no other side effect than to set the error flag";            break;        case GL_INVALID_OPERATION:            qDebug() << "The specified operation is not allowed in the current state.The offending command is ignored and has no other side effect than to set the error flag..";            break;        case GL_INVALID_FRAMEBUFFER_OPERATION:            qDebug() << "The framebuffer object is not complete.The offending command is ignored and has no other side effect than to set the error flag.";            break;        case GL_OUT_OF_MEMORY:            qDebug() << "There is not enough memory left to execute the command.The state of the GL is undefined, except for the state of the error flags, after this error is recorded.";            break;        case GL_STACK_UNDERFLOW:            qDebug() << "An attempt has been made to perform an operation that would cause an internal stack to underflow.";            break;        case GL_STACK_OVERFLOW:            qDebug() << "An attempt has been made to perform an operation that would cause an internal stack to overflow.";            break;        }    }} //#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError()#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) {    updateInput();    updateTransform();     Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;    GLenum mode = _primitiveToGLmode[primitiveType];    uint32 numVertices = batch._params[paramOffset + 1]._uint;    uint32 startVertex = batch._params[paramOffset + 0]._uint;     glDrawArrays(mode, startVertex, numVertices);    CHECK_GL_ERROR();} void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) {    updateInput();    updateTransform();     Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;    GLenum mode = _primitiveToGLmode[primitiveType];    uint32 numIndices = batch._params[paramOffset + 1]._uint;    uint32 startIndex = batch._params[paramOffset + 0]._uint;     GLenum glType = _elementTypeToGLType[_input._indexBufferType];     glDrawElements(mode, numIndices, glType, reinterpret_cast<GLvoid*>(startIndex + _input._indexBufferOffset));    CHECK_GL_ERROR();} void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) {    CHECK_GL_ERROR();} void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) {    CHECK_GL_ERROR();} void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) {    Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint);     if (format != _input._format) {        _input._format = format;        _input._invalidFormat = true;    }} void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) {    Offset stride = batch._params[paramOffset + 0]._uint;    Offset offset = batch._params[paramOffset + 1]._uint;    BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);    uint32 channel = batch._params[paramOffset + 3]._uint;     if (channel < getNumInputBuffers()) {        _input._buffers[channel] = buffer;        _input._bufferOffsets[channel] = offset;        _input._bufferStrides[channel] = stride;        _input._buffersState.set(channel);    }} #define SUPPORT_LEGACY_OPENGL#if defined(SUPPORT_LEGACY_OPENGL)static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT;static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = {    GL_VERTEX_ARRAY,    GL_NORMAL_ARRAY,    GL_COLOR_ARRAY,    GL_TEXTURE_COORD_ARRAY};#endif void GLBackend::updateInput() {    if (_input._invalidFormat || _input._buffersState.any()) {         if (_input._invalidFormat) {            InputStageState::ActivationCache newActivation;             // Check expected activation            if (_input._format) {                const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();                for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {                    const Stream::Attribute& attrib = (*it).second;                    newActivation.set(attrib._slot);                }            }             // Manage Activation what was and what is expected now            for (unsigned int i = 0; i < newActivation.size(); i++) {                bool newState = newActivation[i];                if (newState != _input._attributeActivation[i]) {#if defined(SUPPORT_LEGACY_OPENGL)                    if (i < NUM_CLASSIC_ATTRIBS) {                        if (newState) {                            glEnableClientState(attributeSlotToClassicAttribName[i]);                        }                        else {                            glDisableClientState(attributeSlotToClassicAttribName[i]);                        }                    } else {#else                     {#endif                        if (newState) {                            glEnableVertexAttribArray(i);                        } else {                            glDisableVertexAttribArray(i);                        }                    }                    CHECK_GL_ERROR();                     _input._attributeActivation.flip(i);                }            }        }         // now we need to bind the buffers and assign the attrib pointers        if (_input._format) {            const Buffers& buffers = _input._buffers;            const Offsets& offsets = _input._bufferOffsets;            const Offsets& strides = _input._bufferStrides;             const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();             for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin();                    channelIt != _input._format->getChannels().end();                    channelIt++) {                const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second;                if ((*channelIt).first < buffers.size()) {                    int bufferNum = (*channelIt).first;                     if (_input._buffersState.test(bufferNum) || _input._invalidFormat) {                        GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));                        glBindBuffer(GL_ARRAY_BUFFER, vbo);                        CHECK_GL_ERROR();                        _input._buffersState[bufferNum] = false;                         for (unsigned int i = 0; i < channel._slots.size(); i++) {                            const Stream::Attribute& attrib = attributes.at(channel._slots[i]);                            GLuint slot = attrib._slot;                            GLuint count = attrib._element.getDimensionCount();                            GLenum type = _elementTypeToGLType[attrib._element.getType()];                            GLuint stride = strides[bufferNum];                            GLuint pointer = attrib._offset + offsets[bufferNum];                            #if defined(SUPPORT_LEGACY_OPENGL)                            if (slot < NUM_CLASSIC_ATTRIBS) {                                switch (slot) {                                case Stream::POSITION:                                    glVertexPointer(count, type, stride, reinterpret_cast<GLvoid*>(pointer));                                    break;                                case Stream::NORMAL:                                    glNormalPointer(type, stride, reinterpret_cast<GLvoid*>(pointer));                                    break;                                case Stream::COLOR:                                    glColorPointer(count, type, stride, reinterpret_cast<GLvoid*>(pointer));                                    break;                                case Stream::TEXCOORD:                                    glTexCoordPointer(count, type, stride, reinterpret_cast<GLvoid*>(pointer));                                     break;                                };                            } else {                            #else                             {                            #endif                                GLboolean isNormalized = attrib._element.isNormalized();                                glVertexAttribPointer(slot, count, type, isNormalized, stride,                                    reinterpret_cast<GLvoid*>(pointer));                            }                            CHECK_GL_ERROR();                        }                    }                }            }        }        // everything format related should be in sync now        _input._invalidFormat = false;    } /* TODO: Fancy version GL4.4    if (_needInputFormatUpdate) {         InputActivationCache newActivation;         // Assign the vertex format required        if (_inputFormat) {            const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes();            for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {                const StreamFormat::Attribute& attrib = (*it).second;                newActivation.set(attrib._slot);                glVertexAttribFormat(                    attrib._slot,                    attrib._element.getDimensionCount(),                    _elementTypeToGLType[attrib._element.getType()],                    attrib._element.isNormalized(),                    attrib._stride);            }            CHECK_GL_ERROR();        }         // Manage Activation what was and what is expected now        for (int i = 0; i < newActivation.size(); i++) {            bool newState = newActivation[i];            if (newState != _inputAttributeActivation[i]) {                if (newState) {                    glEnableVertexAttribArray(i);                } else {                    glDisableVertexAttribArray(i);                }                _inputAttributeActivation.flip(i);            }        }        CHECK_GL_ERROR();         _needInputFormatUpdate = false;    }     if (_needInputStreamUpdate) {        if (_inputStream) {            const Stream::Buffers& buffers = _inputStream->getBuffers();            const Stream::Offsets& offsets = _inputStream->getOffsets();            const Stream::Strides& strides = _inputStream->getStrides();             for (int i = 0; i < buffers.size(); i++) {                GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i]));                glBindVertexBuffer(i, vbo, offsets[i], strides[i]);            }             CHECK_GL_ERROR();        }        _needInputStreamUpdate = false;    }*/}  void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) {    _input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint;    BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint);    _input._indexBufferOffset = batch._params[paramOffset + 0]._uint;    _input._indexBuffer = indexBuffer;    if (indexBuffer) {        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer));    } else {        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    }    CHECK_GL_ERROR();} // Transform Stage void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) {    _transform._model = batch._transforms.get(batch._params[paramOffset]._uint);    _transform._invalidModel = true;} void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) {    _transform._view = batch._transforms.get(batch._params[paramOffset]._uint);    _transform._invalidView = true;} void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) {    _transform._projection = batch._transforms.get(batch._params[paramOffset]._uint);    _transform._invalidProj = true;} void GLBackend::updateTransform() {    if (_transform._invalidProj) {        // TODO: implement the projection matrix assignment to gl state    /*    if (_transform._lastMode != GL_PROJECTION) {            glMatrixMode(GL_PROJECTION);            _transform._lastMode = GL_PROJECTION;        }        CHECK_GL_ERROR();*/    }     if (_transform._invalidModel || _transform._invalidView) {        if (!_transform._model.isIdentity()) {            if (_transform._lastMode != GL_MODELVIEW) {                glMatrixMode(GL_MODELVIEW);                _transform._lastMode = GL_MODELVIEW;            }            Transform::Mat4 modelView;            if (!_transform._view.isIdentity()) {                Transform mvx;                Transform::inverseMult(mvx, _transform._view, _transform._model);                mvx.getMatrix(modelView);            } else {                _transform._model.getMatrix(modelView);            }            glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));        } else {            if (!_transform._view.isIdentity()) {                if (_transform._lastMode != GL_MODELVIEW) {                    glMatrixMode(GL_MODELVIEW);                    _transform._lastMode = GL_MODELVIEW;                }                Transform::Mat4 modelView;                _transform._view.getInverseMatrix(modelView);                glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));            } else {                // TODO: eventually do something about the matrix when neither view nor model is specified?                // glLoadIdentity();            }        }        CHECK_GL_ERROR();         _transform._invalidModel = false;        _transform._invalidView = false;    }} // TODO: As long as we have gl calls explicitely issued from interface// code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API #define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); //#define DO_IT_NOW(call, offset) runLastCommand();#define DO_IT_NOW(call, offset)   void Batch::_glEnable(GLenum cap) {    ADD_COMMAND_GL(glEnable);     _params.push_back(cap); 

Lines 1–500 of 1111.