[go: nahoru, domu]

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