1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include "renderstate/MeshState.h" 17 18#include "Program.h" 19 20#include "ShadowTessellator.h" 21 22namespace android { 23namespace uirenderer { 24 25MeshState::MeshState() 26 : mCurrentIndicesBuffer(0) 27 , mCurrentPixelBuffer(0) 28 , mCurrentPositionPointer(this) 29 , mCurrentPositionStride(0) 30 , mCurrentTexCoordsPointer(this) 31 , mCurrentTexCoordsStride(0) 32 , mTexCoordsArrayEnabled(false) 33 , mQuadListIndices(0) { 34 glGenBuffers(1, &mUnitQuadBuffer); 35 glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer); 36 glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW); 37 mCurrentBuffer = mUnitQuadBuffer; 38 39 uint16_t regionIndices[kMaxNumberOfQuads * 6]; 40 for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) { 41 uint16_t quad = i * 4; 42 int index = i * 6; 43 regionIndices[index ] = quad; // top-left 44 regionIndices[index + 1] = quad + 1; // top-right 45 regionIndices[index + 2] = quad + 2; // bottom-left 46 regionIndices[index + 3] = quad + 2; // bottom-left 47 regionIndices[index + 4] = quad + 1; // top-right 48 regionIndices[index + 5] = quad + 3; // bottom-right 49 } 50 glGenBuffers(1, &mQuadListIndices); 51 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices); 52 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW); 53 mCurrentIndicesBuffer = mQuadListIndices; 54 55 // position attribute always enabled 56 glEnableVertexAttribArray(Program::kBindingPosition); 57} 58 59MeshState::~MeshState() { 60 glDeleteBuffers(1, &mUnitQuadBuffer); 61 mCurrentBuffer = 0; 62 63 glDeleteBuffers(1, &mQuadListIndices); 64 mQuadListIndices = 0; 65} 66 67void MeshState::dump() { 68 ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer); 69 ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer); 70 ALOGD("MeshState vertices: vertex data %p, stride %d", 71 mCurrentPositionPointer, mCurrentPositionStride); 72 ALOGD("MeshState texCoord: data %p, stride %d", 73 mCurrentTexCoordsPointer, mCurrentTexCoordsStride); 74} 75 76/////////////////////////////////////////////////////////////////////////////// 77// Buffer Objects 78/////////////////////////////////////////////////////////////////////////////// 79 80void MeshState::bindMeshBuffer(GLuint buffer) { 81 if (mCurrentBuffer != buffer) { 82 glBindBuffer(GL_ARRAY_BUFFER, buffer); 83 mCurrentBuffer = buffer; 84 85 // buffer has changed, so invalidate cached vertex pos/texcoord pointers 86 resetVertexPointers(); 87 } 88} 89 90void MeshState::unbindMeshBuffer() { 91 return bindMeshBuffer(0); 92} 93 94void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, 95 const void* data, GLenum usage) { 96 if (!*buffer) { 97 glGenBuffers(1, buffer); 98 } 99 bindMeshBuffer(*buffer); 100 glBufferData(GL_ARRAY_BUFFER, size, data, usage); 101} 102 103void MeshState::deleteMeshBuffer(GLuint buffer) { 104 if (buffer == mCurrentBuffer) { 105 // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO). 106 // Reflect this in our cached value. 107 mCurrentBuffer = 0; 108 } 109 glDeleteBuffers(1, &buffer); 110} 111 112/////////////////////////////////////////////////////////////////////////////// 113// Vertices 114/////////////////////////////////////////////////////////////////////////////// 115 116void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) { 117 // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack) 118 if (mCurrentBuffer == 0 119 || vertices != mCurrentPositionPointer 120 || stride != mCurrentPositionStride) { 121 glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices); 122 mCurrentPositionPointer = vertices; 123 mCurrentPositionStride = stride; 124 } 125} 126 127void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) { 128 // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack) 129 if (mCurrentBuffer == 0 130 || vertices != mCurrentTexCoordsPointer 131 || stride != mCurrentTexCoordsStride) { 132 glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices); 133 mCurrentTexCoordsPointer = vertices; 134 mCurrentTexCoordsStride = stride; 135 } 136} 137 138void MeshState::resetVertexPointers() { 139 mCurrentPositionPointer = this; 140 mCurrentTexCoordsPointer = this; 141} 142 143void MeshState::enableTexCoordsVertexArray() { 144 if (!mTexCoordsArrayEnabled) { 145 glEnableVertexAttribArray(Program::kBindingTexCoords); 146 mCurrentTexCoordsPointer = this; 147 mTexCoordsArrayEnabled = true; 148 } 149} 150 151void MeshState::disableTexCoordsVertexArray() { 152 if (mTexCoordsArrayEnabled) { 153 glDisableVertexAttribArray(Program::kBindingTexCoords); 154 mTexCoordsArrayEnabled = false; 155 } 156} 157 158/////////////////////////////////////////////////////////////////////////////// 159// Indices 160/////////////////////////////////////////////////////////////////////////////// 161 162void MeshState::bindIndicesBuffer(const GLuint buffer) { 163 if (mCurrentIndicesBuffer != buffer) { 164 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 165 mCurrentIndicesBuffer = buffer; 166 } 167} 168 169void MeshState::unbindIndicesBuffer() { 170 if (mCurrentIndicesBuffer) { 171 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 172 mCurrentIndicesBuffer = 0; 173 } 174} 175 176} /* namespace uirenderer */ 177} /* namespace android */ 178 179