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", mCurrentPositionPointer, 69 mCurrentPositionStride); 70 ALOGD("MeshState texCoord: data %p, stride %d", mCurrentTexCoordsPointer, 71 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, const void* data, 93 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, GLsizeiptr size, 102 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 || vertices != mCurrentPositionPointer || 123 stride != mCurrentPositionStride) { 124 glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices); 125 mCurrentPositionPointer = vertices; 126 mCurrentPositionStride = stride; 127 } 128 } 129 130 void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) { 131 // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack) 132 if (mCurrentBuffer == 0 || vertices != mCurrentTexCoordsPointer || 133 stride != mCurrentTexCoordsStride) { 134 glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices); 135 mCurrentTexCoordsPointer = vertices; 136 mCurrentTexCoordsStride = stride; 137 } 138 } 139 140 void MeshState::resetVertexPointers() { 141 mCurrentPositionPointer = this; 142 mCurrentTexCoordsPointer = this; 143 } 144 145 void MeshState::enableTexCoordsVertexArray() { 146 if (!mTexCoordsArrayEnabled) { 147 glEnableVertexAttribArray(Program::kBindingTexCoords); 148 mCurrentTexCoordsPointer = this; 149 mTexCoordsArrayEnabled = true; 150 } 151 } 152 153 void MeshState::disableTexCoordsVertexArray() { 154 if (mTexCoordsArrayEnabled) { 155 glDisableVertexAttribArray(Program::kBindingTexCoords); 156 mTexCoordsArrayEnabled = false; 157 } 158 } 159 160 /////////////////////////////////////////////////////////////////////////////// 161 // Indices 162 /////////////////////////////////////////////////////////////////////////////// 163 164 void MeshState::bindIndicesBuffer(const GLuint buffer) { 165 if (mCurrentIndicesBuffer != buffer) { 166 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 167 mCurrentIndicesBuffer = buffer; 168 } 169 } 170 171 void MeshState::unbindIndicesBuffer() { 172 if (mCurrentIndicesBuffer) { 173 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 174 mCurrentIndicesBuffer = 0; 175 } 176 } 177 178 } /* namespace uirenderer */ 179 } /* namespace android */ 180