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
22 namespace android {
23 namespace uirenderer {
24
MeshState()25 MeshState::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
~MeshState()59 MeshState::~MeshState() {
60 glDeleteBuffers(1, &mUnitQuadBuffer);
61 mCurrentBuffer = 0;
62
63 glDeleteBuffers(1, &mQuadListIndices);
64 mQuadListIndices = 0;
65 }
66
dump()67 void 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
bindMeshBuffer(GLuint buffer)80 void 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
unbindMeshBuffer()90 void MeshState::unbindMeshBuffer() {
91 return bindMeshBuffer(0);
92 }
93
genOrUpdateMeshBuffer(GLuint * buffer,GLsizeiptr size,const void * data,GLenum usage)94 void 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
deleteMeshBuffer(GLuint buffer)103 void 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
bindPositionVertexPointer(const GLvoid * vertices,GLsizei stride)116 void 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
bindTexCoordsVertexPointer(const GLvoid * vertices,GLsizei stride)127 void 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
resetVertexPointers()138 void MeshState::resetVertexPointers() {
139 mCurrentPositionPointer = this;
140 mCurrentTexCoordsPointer = this;
141 }
142
enableTexCoordsVertexArray()143 void MeshState::enableTexCoordsVertexArray() {
144 if (!mTexCoordsArrayEnabled) {
145 glEnableVertexAttribArray(Program::kBindingTexCoords);
146 mCurrentTexCoordsPointer = this;
147 mTexCoordsArrayEnabled = true;
148 }
149 }
150
disableTexCoordsVertexArray()151 void MeshState::disableTexCoordsVertexArray() {
152 if (mTexCoordsArrayEnabled) {
153 glDisableVertexAttribArray(Program::kBindingTexCoords);
154 mTexCoordsArrayEnabled = false;
155 }
156 }
157
158 ///////////////////////////////////////////////////////////////////////////////
159 // Indices
160 ///////////////////////////////////////////////////////////////////////////////
161
bindIndicesBuffer(const GLuint buffer)162 void MeshState::bindIndicesBuffer(const GLuint buffer) {
163 if (mCurrentIndicesBuffer != buffer) {
164 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
165 mCurrentIndicesBuffer = buffer;
166 }
167 }
168
unbindIndicesBuffer()169 void 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