1035 lines · 32.1 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_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_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() :     _inputFormat(0),    _inputAttributeActivation(0),    _needInputFormatUpdate(true),     _inputBuffersState(0),    _inputBuffers(_inputBuffersState.size(), BufferPointer(0)),    _inputBufferOffsets(_inputBuffersState.size(), 0),    _inputBufferStrides(_inputBuffersState.size(), 0),     _indexBuffer(0),    _indexBufferOffset(0){ } 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 (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();     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();     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[_indexBufferType];     glDrawElements(mode, numIndices, glType, (GLvoid*)(startIndex + _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 != _inputFormat) {        _inputFormat = format;        _needInputFormatUpdate = 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()) {        _inputBuffers[channel] = buffer;        _inputBufferOffsets[channel] = offset;        _inputBufferStrides[channel] = stride;        _inputBuffersState.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 (_needInputFormatUpdate || _inputBuffersState.any()) {         if (_needInputFormatUpdate) {            InputActivationCache newActivation;             // Check expected activation            if (_inputFormat) {                const Stream::Format::AttributeMap& attributes = _inputFormat->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 (int i = 0; i < newActivation.size(); i++) {                bool newState = newActivation[i];                if (newState != _inputAttributeActivation[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();                     _inputAttributeActivation.flip(i);                }            }        }         // now we need to bind the buffers and assign the attrib pointers        if (_inputFormat) {            const Buffers& buffers = _inputBuffers;            const Offsets& offsets = _inputBufferOffsets;            const Offsets& strides = _inputBufferStrides;             const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes();             for (Stream::Format::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin();                    channelIt != _inputFormat->getChannels().end();                    channelIt++) {                const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second;                if ((*channelIt).first < buffers.size()) {                    int bufferNum = (*channelIt).first;                     if (_inputBuffersState.test(bufferNum) || _needInputFormatUpdate) {                        GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));                        glBindBuffer(GL_ARRAY_BUFFER, vbo);                        CHECK_GL_ERROR();                        _inputBuffersState[bufferNum] = false;                         for (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, (GLvoid*)pointer);                                    break;                                case Stream::NORMAL:                                    glNormalPointer(type, stride, (GLvoid*)pointer);                                    break;                                case Stream::COLOR:                                    glColorPointer(count, type, stride, (GLvoid*)pointer);                                    break;                                case Stream::TEXCOORD:                                    glTexCoordPointer(count, type, stride, (GLvoid*)pointer);                                     break;                                };                            } else {                            #else                             {                            #endif                                GLboolean isNormalized = attrib._element.isNormalized();                                glVertexAttribPointer(slot, count, type, isNormalized, stride, (GLvoid*)pointer);                            }                            CHECK_GL_ERROR();                        }                    }                }            }        }        // everything format related should be in sync now        _needInputFormatUpdate = 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) {    _indexBufferType = (Type) batch._params[paramOffset + 2]._uint;    BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint);    _indexBufferOffset = batch._params[paramOffset + 0]._uint;    _indexBuffer = indexBuffer;    if (indexBuffer) {        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer));    } else {        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    }    CHECK_GL_ERROR();} // 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);     DO_IT_NOW(_glEnable, 1);}void GLBackend::do_glEnable(Batch& batch, uint32 paramOffset) {    glEnable(batch._params[paramOffset]._uint);    CHECK_GL_ERROR();} void Batch::_glDisable(GLenum cap) {    ADD_COMMAND_GL(glDisable);     _params.push_back(cap);     DO_IT_NOW(_glDisable, 1);}void GLBackend::do_glDisable(Batch& batch, uint32 paramOffset) {    glDisable(batch._params[paramOffset]._uint);    CHECK_GL_ERROR();} void Batch::_glEnableClientState(GLenum array) {    ADD_COMMAND_GL(glEnableClientState);     _params.push_back(array);     DO_IT_NOW(_glEnableClientState, 1);}void GLBackend::do_glEnableClientState(Batch& batch, uint32 paramOffset) {    glEnableClientState(batch._params[paramOffset]._uint);    CHECK_GL_ERROR();} void Batch::_glDisableClientState(GLenum array) {    ADD_COMMAND_GL(glDisableClientState);     _params.push_back(array);     DO_IT_NOW(_glDisableClientState, 1);}void GLBackend::do_glDisableClientState(Batch& batch, uint32 paramOffset) {    glDisableClientState(batch._params[paramOffset]._uint);    CHECK_GL_ERROR();} void Batch::_glCullFace(GLenum mode) {    ADD_COMMAND_GL(glCullFace);     _params.push_back(mode);     DO_IT_NOW(_glCullFace, 1);}void GLBackend::do_glCullFace(Batch& batch, uint32 paramOffset) {    glCullFace(batch._params[paramOffset]._uint);    CHECK_GL_ERROR();} void Batch::_glAlphaFunc(GLenum func, GLclampf ref) {    ADD_COMMAND_GL(glAlphaFunc);     _params.push_back(ref);

Lines 1–500 of 1035.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t