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 namespace android { 21 namespace uirenderer { 22 23 MeshState::MeshState() 24 : mCurrentIndicesBuffer(0) 25 , mCurrentPixelBuffer(0) 26 , mCurrentPositionPointer(this) 27 , mCurrentPositionStride(0) 28 , mCurrentTexCoordsPointer(this) 29 , mCurrentTexCoordsStride(0) 30 , mTexCoordsArrayEnabled(false) 31 , mQuadListIndices(0) { 32 glGenBuffers(1, &mUnitQuadBuffer); 33 glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer); 34 glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW); 35 mCurrentBuffer = mUnitQuadBuffer; 36 37 uint16_t regionIndices[kMaxNumberOfQuads * 6]; 38 for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) { 39 uint16_t quad = i * 4; 40 int index = i * 6; 41 regionIndices[index ] = quad; // top-left 42 regionIndices[index + 1] = quad + 1; // top-right 43 regionIndices[index + 2] = quad + 2; // bottom-left 44 regionIndices[index + 3] = quad + 2; // bottom-left 45 regionIndices[index + 4] = quad + 1; // top-right 46 regionIndices[index + 5] = quad + 3; // bottom-right 47 } 48 glGenBuffers(1, &mQuadListIndices); 49 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices); 50 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW); 51 mCurrentIndicesBuffer = mQuadListIndices; 52 53 // position attribute always enabled 54 glEnableVertexAttribArray(Program::kBindingPosition); 55 } 56 57 MeshState::~MeshState() { 58 glDeleteBuffers(1, &mUnitQuadBuffer); 59 mCurrentBuffer = 0; 60 61 glDeleteBuffers(1, &mQuadListIndices); 62 mQuadListIndices = 0; 63 } 64 65 void MeshState::dump() { 66 ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer); 67 ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer); 68 ALOGD("MeshState vertices: vertex data %p, stride %d", 69 mCurrentPositionPointer, mCurrentPositionStride); 70 ALOGD("MeshState texCoord: data %p, stride %d", 71 mCurrentTexCoordsPointer, mCurrentTexCoordsStride); 72 } 73 74 /////////////////////////////////////////////////////////////////////////////// 75 // Buffer Objects 76 /////////////////////////////////////////////////////////////////////////////// 77 78 void MeshState::bindMeshBuffer(GLuint buffer) { 79 if (mCurrentBuffer != buffer) { 80 glBindBuffer(GL_ARRAY_BUFFER, buffer); 81 mCurrentBuffer = buffer; 82 83 // buffer has changed, so invalidate cached vertex pos/texcoord pointers 84 resetVertexPointers(); 85 } 86 } 87 88 void MeshState::unbindMeshBuffer() { 89 return bindMeshBuffer(0); 90 } 91 92 void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, 93 const void* data, GLenum usage) { 94 if (!*buffer) { 95 glGenBuffers(1, buffer); 96 } 97 bindMeshBuffer(*buffer); 98 glBufferData(GL_ARRAY_BUFFER, size, data, usage); 99 } 100 101 void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset, 102 GLsizeiptr size, const void* data) { 103 bindMeshBuffer(buffer); 104 glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); 105 } 106 107 void MeshState::deleteMeshBuffer(GLuint buffer) { 108 if (buffer == mCurrentBuffer) { 109 // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO). 110 // Reflect this in our cached value. 111 mCurrentBuffer = 0; 112 } 113 glDeleteBuffers(1, &buffer); 114 } 115 116 /////////////////////////////////////////////////////////////////////////////// 117 // Vertices 118 /////////////////////////////////////////////////////////////////////////////// 119 120 void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) { 121 // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack) 122 if (mCurrentBuffer == 0 123 || vertices != mCurrentPositionPointer 124 || stride != mCurrentPositionStride) { 125 glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices); 126 mCurrentPositionPointer = vertices; 127 mCurrentPositionStride = stride; 128 } 129 } 130 131 void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) { 132 // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack) 133 if (mCurrentBuffer == 0 134 || vertices != mCurrentTexCoordsPointer 135 || stride != mCurrentTexCoordsStride) { 136 glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices); 137 mCurrentTexCoordsPointer = vertices; 138 mCurrentTexCoordsStride = stride; 139 } 140 } 141 142 void MeshState::resetVertexPointers() { 143 mCurrentPositionPointer = this; 144 mCurrentTexCoordsPointer = this; 145 } 146 147 void MeshState::enableTexCoordsVertexArray() { 148 if (!mTexCoordsArrayEnabled) { 149 glEnableVertexAttribArray(Program::kBindingTexCoords); 150 mCurrentTexCoordsPointer = this; 151 mTexCoordsArrayEnabled = true; 152 } 153 } 154 155 void MeshState::disableTexCoordsVertexArray() { 156 if (mTexCoordsArrayEnabled) { 157 glDisableVertexAttribArray(Program::kBindingTexCoords); 158 mTexCoordsArrayEnabled = false; 159 } 160 } 161 162 /////////////////////////////////////////////////////////////////////////////// 163 // Indices 164 /////////////////////////////////////////////////////////////////////////////// 165 166 void MeshState::bindIndicesBuffer(const GLuint buffer) { 167 if (mCurrentIndicesBuffer != buffer) { 168 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 169 mCurrentIndicesBuffer = buffer; 170 } 171 } 172 173 void MeshState::unbindIndicesBuffer() { 174 if (mCurrentIndicesBuffer) { 175 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 176 mCurrentIndicesBuffer = 0; 177 } 178 } 179 180 } /* namespace uirenderer */ 181 } /* namespace android */ 182 183