| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "renderstate/MeshState.h" |
| |
| #include "Program.h" |
| |
| namespace android { |
| namespace uirenderer { |
| |
| MeshState::MeshState() |
| : mCurrentIndicesBuffer(0) |
| , mCurrentPixelBuffer(0) |
| , mCurrentPositionPointer(this) |
| , mCurrentPositionStride(0) |
| , mCurrentTexCoordsPointer(this) |
| , mCurrentTexCoordsStride(0) |
| , mTexCoordsArrayEnabled(false) |
| , mQuadListIndices(0) { |
| glGenBuffers(1, &mUnitQuadBuffer); |
| glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer); |
| glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW); |
| mCurrentBuffer = mUnitQuadBuffer; |
| |
| uint16_t regionIndices[kMaxNumberOfQuads * 6]; |
| for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) { |
| uint16_t quad = i * 4; |
| int index = i * 6; |
| regionIndices[index] = quad; // top-left |
| regionIndices[index + 1] = quad + 1; // top-right |
| regionIndices[index + 2] = quad + 2; // bottom-left |
| regionIndices[index + 3] = quad + 2; // bottom-left |
| regionIndices[index + 4] = quad + 1; // top-right |
| regionIndices[index + 5] = quad + 3; // bottom-right |
| } |
| glGenBuffers(1, &mQuadListIndices); |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices); |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW); |
| mCurrentIndicesBuffer = mQuadListIndices; |
| |
| // position attribute always enabled |
| glEnableVertexAttribArray(Program::kBindingPosition); |
| } |
| |
| MeshState::~MeshState() { |
| glDeleteBuffers(1, &mUnitQuadBuffer); |
| mCurrentBuffer = 0; |
| |
| glDeleteBuffers(1, &mQuadListIndices); |
| mQuadListIndices = 0; |
| } |
| |
| void MeshState::dump() { |
| ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer); |
| ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer); |
| ALOGD("MeshState vertices: vertex data %p, stride %d", mCurrentPositionPointer, |
| mCurrentPositionStride); |
| ALOGD("MeshState texCoord: data %p, stride %d", mCurrentTexCoordsPointer, |
| mCurrentTexCoordsStride); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Buffer Objects |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| void MeshState::bindMeshBuffer(GLuint buffer) { |
| if (mCurrentBuffer != buffer) { |
| glBindBuffer(GL_ARRAY_BUFFER, buffer); |
| mCurrentBuffer = buffer; |
| |
| // buffer has changed, so invalidate cached vertex pos/texcoord pointers |
| resetVertexPointers(); |
| } |
| } |
| |
| void MeshState::unbindMeshBuffer() { |
| return bindMeshBuffer(0); |
| } |
| |
| void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data, |
| GLenum usage) { |
| if (!*buffer) { |
| glGenBuffers(1, buffer); |
| } |
| bindMeshBuffer(*buffer); |
| glBufferData(GL_ARRAY_BUFFER, size, data, usage); |
| } |
| |
| void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, |
| const void* data) { |
| bindMeshBuffer(buffer); |
| glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); |
| } |
| |
| void MeshState::deleteMeshBuffer(GLuint buffer) { |
| if (buffer == mCurrentBuffer) { |
| // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO). |
| // Reflect this in our cached value. |
| mCurrentBuffer = 0; |
| } |
| glDeleteBuffers(1, &buffer); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Vertices |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) { |
| // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack) |
| if (mCurrentBuffer == 0 || vertices != mCurrentPositionPointer || |
| stride != mCurrentPositionStride) { |
| glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices); |
| mCurrentPositionPointer = vertices; |
| mCurrentPositionStride = stride; |
| } |
| } |
| |
| void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) { |
| // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack) |
| if (mCurrentBuffer == 0 || vertices != mCurrentTexCoordsPointer || |
| stride != mCurrentTexCoordsStride) { |
| glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices); |
| mCurrentTexCoordsPointer = vertices; |
| mCurrentTexCoordsStride = stride; |
| } |
| } |
| |
| void MeshState::resetVertexPointers() { |
| mCurrentPositionPointer = this; |
| mCurrentTexCoordsPointer = this; |
| } |
| |
| void MeshState::enableTexCoordsVertexArray() { |
| if (!mTexCoordsArrayEnabled) { |
| glEnableVertexAttribArray(Program::kBindingTexCoords); |
| mCurrentTexCoordsPointer = this; |
| mTexCoordsArrayEnabled = true; |
| } |
| } |
| |
| void MeshState::disableTexCoordsVertexArray() { |
| if (mTexCoordsArrayEnabled) { |
| glDisableVertexAttribArray(Program::kBindingTexCoords); |
| mTexCoordsArrayEnabled = false; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Indices |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| void MeshState::bindIndicesBuffer(const GLuint buffer) { |
| if (mCurrentIndicesBuffer != buffer) { |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); |
| mCurrentIndicesBuffer = buffer; |
| } |
| } |
| |
| void MeshState::unbindIndicesBuffer() { |
| if (mCurrentIndicesBuffer) { |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| mCurrentIndicesBuffer = 0; |
| } |
| } |
| |
| } /* namespace uirenderer */ |
| } /* namespace android */ |