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 
38     mCurrentBuffer = mUnitQuadBuffer;
39 
40     uint16_t regionIndices[kMaxNumberOfQuads * 6];
41     for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
42         uint16_t quad = i * 4;
43         int index = i * 6;
44         regionIndices[index    ] = quad;       // top-left
45         regionIndices[index + 1] = quad + 1;   // top-right
46         regionIndices[index + 2] = quad + 2;   // bottom-left
47         regionIndices[index + 3] = quad + 2;   // bottom-left
48         regionIndices[index + 4] = quad + 1;   // top-right
49         regionIndices[index + 5] = quad + 3;   // bottom-right
50     }
51     glGenBuffers(1, &mQuadListIndices);
52     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
53     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW);
54     mCurrentIndicesBuffer = mQuadListIndices;
55 
56     // position attribute always enabled
57     glEnableVertexAttribArray(Program::kBindingPosition);
58 }
59 
~MeshState()60 MeshState::~MeshState() {
61     glDeleteBuffers(1, &mUnitQuadBuffer);
62     mCurrentBuffer = 0;
63 
64     glDeleteBuffers(1, &mQuadListIndices);
65     mQuadListIndices = 0;
66 }
67 
dump()68 void MeshState::dump() {
69     ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
70     ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer);
71     ALOGD("MeshState vertices: vertex data %p, stride %d",
72             mCurrentPositionPointer, mCurrentPositionStride);
73     ALOGD("MeshState texCoord: data %p, stride %d",
74             mCurrentTexCoordsPointer, mCurrentTexCoordsStride);
75 }
76 
77 ///////////////////////////////////////////////////////////////////////////////
78 // Buffer Objects
79 ///////////////////////////////////////////////////////////////////////////////
80 
bindMeshBuffer()81 bool MeshState::bindMeshBuffer() {
82     return bindMeshBuffer(mUnitQuadBuffer);
83 }
84 
bindMeshBuffer(GLuint buffer)85 bool MeshState::bindMeshBuffer(GLuint buffer) {
86     if (!buffer) buffer = mUnitQuadBuffer;
87     return bindMeshBufferInternal(buffer);
88 }
89 
unbindMeshBuffer()90 bool MeshState::unbindMeshBuffer() {
91     return bindMeshBufferInternal(0);
92 }
93 
bindMeshBufferInternal(GLuint buffer)94 bool MeshState::bindMeshBufferInternal(GLuint buffer) {
95     if (mCurrentBuffer != buffer) {
96         glBindBuffer(GL_ARRAY_BUFFER, buffer);
97         mCurrentBuffer = buffer;
98         return true;
99     }
100     return false;
101 }
102 
103 ///////////////////////////////////////////////////////////////////////////////
104 // Vertices
105 ///////////////////////////////////////////////////////////////////////////////
106 
bindPositionVertexPointer(bool force,const GLvoid * vertices,GLsizei stride)107 void MeshState::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
108     if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
109         glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
110         mCurrentPositionPointer = vertices;
111         mCurrentPositionStride = stride;
112     }
113 }
114 
bindTexCoordsVertexPointer(bool force,const GLvoid * vertices,GLsizei stride)115 void MeshState::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
116     if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
117         glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
118         mCurrentTexCoordsPointer = vertices;
119         mCurrentTexCoordsStride = stride;
120     }
121 }
122 
resetVertexPointers()123 void MeshState::resetVertexPointers() {
124     mCurrentPositionPointer = this;
125     mCurrentTexCoordsPointer = this;
126 }
127 
resetTexCoordsVertexPointer()128 void MeshState::resetTexCoordsVertexPointer() {
129     mCurrentTexCoordsPointer = this;
130 }
131 
enableTexCoordsVertexArray()132 void MeshState::enableTexCoordsVertexArray() {
133     if (!mTexCoordsArrayEnabled) {
134         glEnableVertexAttribArray(Program::kBindingTexCoords);
135         mCurrentTexCoordsPointer = this;
136         mTexCoordsArrayEnabled = true;
137     }
138 }
139 
disableTexCoordsVertexArray()140 void MeshState::disableTexCoordsVertexArray() {
141     if (mTexCoordsArrayEnabled) {
142         glDisableVertexAttribArray(Program::kBindingTexCoords);
143         mTexCoordsArrayEnabled = false;
144     }
145 }
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 // Indices
149 ///////////////////////////////////////////////////////////////////////////////
150 
bindIndicesBufferInternal(const GLuint buffer)151 bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
152     if (mCurrentIndicesBuffer != buffer) {
153         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
154         mCurrentIndicesBuffer = buffer;
155         return true;
156     }
157     return false;
158 }
159 
bindQuadIndicesBuffer()160 bool MeshState::bindQuadIndicesBuffer() {
161     return bindIndicesBufferInternal(mQuadListIndices);
162 }
163 
unbindIndicesBuffer()164 bool MeshState::unbindIndicesBuffer() {
165     if (mCurrentIndicesBuffer) {
166         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
167         mCurrentIndicesBuffer = 0;
168         return true;
169     }
170     return false;
171 }
172 
173 } /* namespace uirenderer */
174 } /* namespace android */
175 
176