blob: 50c09c85f8370e15bfe06cb0eb4eaa3bc4640fa0 [file] [log] [blame]
Chris Craik96a5c4c2015-01-27 15:46:35 -08001/*
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 : mCurrentPositionPointer(this)
27 , mCurrentPositionStride(0)
28 , mCurrentTexCoordsPointer(this)
29 , mCurrentTexCoordsStride(0)
30 , mTexCoordsArrayEnabled(false) {
31
Chris Craik03188872015-02-02 18:39:33 -080032 glGenBuffers(1, &mUnitQuadBuffer);
33 glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
34 glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
Chris Craik96a5c4c2015-01-27 15:46:35 -080035
Chris Craik03188872015-02-02 18:39:33 -080036 mCurrentBuffer = mUnitQuadBuffer;
Chris Craik96a5c4c2015-01-27 15:46:35 -080037 mCurrentIndicesBuffer = 0;
38 mCurrentPixelBuffer = 0;
39
40 mQuadListIndices = 0;
41 mShadowStripsIndices = 0;
Chris Craik6c15ffa2015-02-02 13:50:55 -080042
43 // position attribute always enabled
44 glEnableVertexAttribArray(Program::kBindingPosition);
Chris Craik96a5c4c2015-01-27 15:46:35 -080045}
46
47MeshState::~MeshState() {
Chris Craik03188872015-02-02 18:39:33 -080048 glDeleteBuffers(1, &mUnitQuadBuffer);
Chris Craik96a5c4c2015-01-27 15:46:35 -080049 mCurrentBuffer = 0;
50
51 glDeleteBuffers(1, &mQuadListIndices);
52 mQuadListIndices = 0;
53
54 glDeleteBuffers(1, &mShadowStripsIndices);
55 mShadowStripsIndices = 0;
56}
57
58///////////////////////////////////////////////////////////////////////////////
59// Buffer Objects
60///////////////////////////////////////////////////////////////////////////////
61
62bool MeshState::bindMeshBuffer() {
Chris Craik03188872015-02-02 18:39:33 -080063 return bindMeshBuffer(mUnitQuadBuffer);
Chris Craik96a5c4c2015-01-27 15:46:35 -080064}
65
66bool MeshState::bindMeshBuffer(GLuint buffer) {
Chris Craik03188872015-02-02 18:39:33 -080067 if (!buffer) buffer = mUnitQuadBuffer;
Chris Craik96a5c4c2015-01-27 15:46:35 -080068 if (mCurrentBuffer != buffer) {
69 glBindBuffer(GL_ARRAY_BUFFER, buffer);
70 mCurrentBuffer = buffer;
71 return true;
72 }
73 return false;
74}
75
76bool MeshState::unbindMeshBuffer() {
77 if (mCurrentBuffer) {
78 glBindBuffer(GL_ARRAY_BUFFER, 0);
79 mCurrentBuffer = 0;
80 return true;
81 }
82 return false;
83}
84
85///////////////////////////////////////////////////////////////////////////////
86// Vertices
87///////////////////////////////////////////////////////////////////////////////
88
Chris Craik6c15ffa2015-02-02 13:50:55 -080089void MeshState::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
Chris Craik96a5c4c2015-01-27 15:46:35 -080090 if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
Chris Craik6c15ffa2015-02-02 13:50:55 -080091 glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
Chris Craik96a5c4c2015-01-27 15:46:35 -080092 mCurrentPositionPointer = vertices;
93 mCurrentPositionStride = stride;
94 }
95}
96
Chris Craik6c15ffa2015-02-02 13:50:55 -080097void MeshState::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
Chris Craik96a5c4c2015-01-27 15:46:35 -080098 if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
Chris Craik6c15ffa2015-02-02 13:50:55 -080099 glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
Chris Craik96a5c4c2015-01-27 15:46:35 -0800100 mCurrentTexCoordsPointer = vertices;
101 mCurrentTexCoordsStride = stride;
102 }
103}
104
105void MeshState::resetVertexPointers() {
106 mCurrentPositionPointer = this;
107 mCurrentTexCoordsPointer = this;
108}
109
110void MeshState::resetTexCoordsVertexPointer() {
111 mCurrentTexCoordsPointer = this;
112}
113
114void MeshState::enableTexCoordsVertexArray() {
115 if (!mTexCoordsArrayEnabled) {
116 glEnableVertexAttribArray(Program::kBindingTexCoords);
117 mCurrentTexCoordsPointer = this;
118 mTexCoordsArrayEnabled = true;
119 }
120}
121
122void MeshState::disableTexCoordsVertexArray() {
123 if (mTexCoordsArrayEnabled) {
124 glDisableVertexAttribArray(Program::kBindingTexCoords);
125 mTexCoordsArrayEnabled = false;
126 }
127}
128
129///////////////////////////////////////////////////////////////////////////////
130// Indices
131///////////////////////////////////////////////////////////////////////////////
132
133bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
134 if (mCurrentIndicesBuffer != buffer) {
135 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
136 mCurrentIndicesBuffer = buffer;
137 return true;
138 }
139 return false;
140}
141
142bool MeshState::bindQuadIndicesBuffer() {
143 if (!mQuadListIndices) {
144 std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]);
145 for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
146 uint16_t quad = i * 4;
147 int index = i * 6;
148 regionIndices[index ] = quad; // top-left
149 regionIndices[index + 1] = quad + 1; // top-right
150 regionIndices[index + 2] = quad + 2; // bottom-left
151 regionIndices[index + 3] = quad + 2; // bottom-left
152 regionIndices[index + 4] = quad + 1; // top-right
153 regionIndices[index + 5] = quad + 3; // bottom-right
154 }
155
156 glGenBuffers(1, &mQuadListIndices);
157 bool force = bindIndicesBufferInternal(mQuadListIndices);
158 glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t),
159 regionIndices.get(), GL_STATIC_DRAW);
160 return force;
161 }
162
163 return bindIndicesBufferInternal(mQuadListIndices);
164}
165
166bool MeshState::bindShadowIndicesBuffer() {
167 if (!mShadowStripsIndices) {
168 std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
169 ShadowTessellator::generateShadowIndices(shadowIndices.get());
170 glGenBuffers(1, &mShadowStripsIndices);
171 bool force = bindIndicesBufferInternal(mShadowStripsIndices);
172 glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
173 shadowIndices.get(), GL_STATIC_DRAW);
174 return force;
175 }
176
177 return bindIndicesBufferInternal(mShadowStripsIndices);
178}
179
180bool MeshState::unbindIndicesBuffer() {
181 if (mCurrentIndicesBuffer) {
182 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
183 mCurrentIndicesBuffer = 0;
184 return true;
185 }
186 return false;
187}
188
189} /* namespace uirenderer */
190} /* namespace android */
191