// // GL41BackendInput.cpp // libraries/gpu/src/gpu // // Created by Sam Gateau on 3/8/2015. // 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 "GL41Backend.h" using namespace gpu; using namespace gpu::gl41; void GL41Backend::resetInputStage() { Parent::resetInputStage(); glBindBuffer(GL_ARRAY_BUFFER, 0); for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) { glDisableVertexAttribArray(i); glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0); } } void GL41Backend::updateInput() { bool isStereoNow = isStereo(); // track stereo state change potentially happening wihtout changing the input format // this is a rare case requesting to invalid the format #ifdef GPU_STEREO_DRAWCALL_INSTANCED _input._invalidFormat |= (isStereoNow != _input._lastUpdateStereoState); #endif _input._lastUpdateStereoState = isStereoNow; if (_input._invalidFormat || _input._invalidBuffers.any()) { auto format = acquire(_input._format); if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; _stats._ISNumFormatChanges++; // Check expected activation if (format) { for (auto& it : format->getAttributes()) { const Stream::Attribute& attrib = (it).second; uint8_t locationCount = attrib._element.getLocationCount(); for (int i = 0; i < locationCount; ++i) { newActivation.set(attrib._slot + i); } } } // 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 (newState) { glEnableVertexAttribArray(i); } else { glDisableVertexAttribArray(i); } (void)CHECK_GL_ERROR(); _input._attributeActivation.flip(i); } } } // now we need to bind the buffers and assign the attrib pointers if (format) { const auto& buffers = _input._buffers; const auto& offsets = _input._bufferOffsets; const auto& strides = _input._bufferStrides; const auto& attributes = format->getAttributes(); const auto& inputChannels = format->getChannels(); int numInvalids = (int)_input._invalidBuffers.count(); _stats._ISNumInputBufferChanges += numInvalids; GLuint boundVBO = 0; for (auto& channelIt : inputChannels) { const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second; if ((channelIt).first < buffers.size()) { int bufferNum = (channelIt).first; if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) { // GLuint vbo = gpu::GL41Backend::getBufferID((*buffers[bufferNum])); GLuint vbo = _input._bufferVBOs[bufferNum]; if (boundVBO != vbo) { glBindBuffer(GL_ARRAY_BUFFER, vbo); (void)CHECK_GL_ERROR(); boundVBO = vbo; } _input._invalidBuffers[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.getLocationScalarCount(); uint8_t locationCount = attrib._element.getLocationCount(); GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()]; // GLenum perLocationStride = strides[bufferNum]; GLenum perLocationStride = attrib._element.getLocationSize(); GLuint stride = (GLuint)strides[bufferNum]; uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]); GLboolean isNormalized = attrib._element.isNormalized(); for (size_t locNum = 0; locNum < locationCount; ++locNum) { if (attrib._element.isInteger()) { glVertexAttribIPointer(slot + (GLuint)locNum, count, type, stride, reinterpret_cast(pointer + perLocationStride * (GLuint)locNum)); } else { glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride, reinterpret_cast(pointer + perLocationStride * (GLuint)locNum)); } #ifdef GPU_STEREO_DRAWCALL_INSTANCED glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereoNow ? 2 : 1)); #else glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency); #endif } (void)CHECK_GL_ERROR(); } } } } } // everything format related should be in sync now _input._invalidFormat = false; } }