196a5c4c7bab6718524de7253da8309143ab48befChris Craik/*
296a5c4c7bab6718524de7253da8309143ab48befChris Craik * Copyright (C) 2015 The Android Open Source Project
396a5c4c7bab6718524de7253da8309143ab48befChris Craik *
496a5c4c7bab6718524de7253da8309143ab48befChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
596a5c4c7bab6718524de7253da8309143ab48befChris Craik * you may not use this file except in compliance with the License.
696a5c4c7bab6718524de7253da8309143ab48befChris Craik * You may obtain a copy of the License at
796a5c4c7bab6718524de7253da8309143ab48befChris Craik *
896a5c4c7bab6718524de7253da8309143ab48befChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
996a5c4c7bab6718524de7253da8309143ab48befChris Craik *
1096a5c4c7bab6718524de7253da8309143ab48befChris Craik * Unless required by applicable law or agreed to in writing, software
1196a5c4c7bab6718524de7253da8309143ab48befChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
1296a5c4c7bab6718524de7253da8309143ab48befChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396a5c4c7bab6718524de7253da8309143ab48befChris Craik * See the License for the specific language governing permissions and
1496a5c4c7bab6718524de7253da8309143ab48befChris Craik * limitations under the License.
1596a5c4c7bab6718524de7253da8309143ab48befChris Craik */
1696a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "renderstate/MeshState.h"
1796a5c4c7bab6718524de7253da8309143ab48befChris Craik
1896a5c4c7bab6718524de7253da8309143ab48befChris Craik#include "Program.h"
1996a5c4c7bab6718524de7253da8309143ab48befChris Craik
2096a5c4c7bab6718524de7253da8309143ab48befChris Craiknamespace android {
2196a5c4c7bab6718524de7253da8309143ab48befChris Craiknamespace uirenderer {
2296a5c4c7bab6718524de7253da8309143ab48befChris Craik
2396a5c4c7bab6718524de7253da8309143ab48befChris CraikMeshState::MeshState()
24117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        : mCurrentIndicesBuffer(0)
25117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        , mCurrentPixelBuffer(0)
26117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        , mCurrentPositionPointer(this)
2796a5c4c7bab6718524de7253da8309143ab48befChris Craik        , mCurrentPositionStride(0)
2896a5c4c7bab6718524de7253da8309143ab48befChris Craik        , mCurrentTexCoordsPointer(this)
2996a5c4c7bab6718524de7253da8309143ab48befChris Craik        , mCurrentTexCoordsStride(0)
30117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        , mTexCoordsArrayEnabled(false)
31117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        , mQuadListIndices(0) {
32031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    glGenBuffers(1, &mUnitQuadBuffer);
33031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
34031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
35031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    mCurrentBuffer = mUnitQuadBuffer;
366c15ffa196fc9b7724c189d833c3435d8db12266Chris Craik
37182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    uint16_t regionIndices[kMaxNumberOfQuads * 6];
382ab95d780b023152556d9f8659de734ec7b55047Chris Craik    for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
392ab95d780b023152556d9f8659de734ec7b55047Chris Craik        uint16_t quad = i * 4;
402ab95d780b023152556d9f8659de734ec7b55047Chris Craik        int index = i * 6;
412ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index    ] = quad;       // top-left
422ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index + 1] = quad + 1;   // top-right
432ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index + 2] = quad + 2;   // bottom-left
442ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index + 3] = quad + 2;   // bottom-left
452ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index + 4] = quad + 1;   // top-right
462ab95d780b023152556d9f8659de734ec7b55047Chris Craik        regionIndices[index + 5] = quad + 3;   // bottom-right
472ab95d780b023152556d9f8659de734ec7b55047Chris Craik    }
482ab95d780b023152556d9f8659de734ec7b55047Chris Craik    glGenBuffers(1, &mQuadListIndices);
492ab95d780b023152556d9f8659de734ec7b55047Chris Craik    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
50182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW);
512ab95d780b023152556d9f8659de734ec7b55047Chris Craik    mCurrentIndicesBuffer = mQuadListIndices;
522ab95d780b023152556d9f8659de734ec7b55047Chris Craik
536c15ffa196fc9b7724c189d833c3435d8db12266Chris Craik    // position attribute always enabled
546c15ffa196fc9b7724c189d833c3435d8db12266Chris Craik    glEnableVertexAttribArray(Program::kBindingPosition);
5596a5c4c7bab6718524de7253da8309143ab48befChris Craik}
5696a5c4c7bab6718524de7253da8309143ab48befChris Craik
5796a5c4c7bab6718524de7253da8309143ab48befChris CraikMeshState::~MeshState() {
58031888744e24b5c7243ac99ec98b78aff5db1c78Chris Craik    glDeleteBuffers(1, &mUnitQuadBuffer);
5996a5c4c7bab6718524de7253da8309143ab48befChris Craik    mCurrentBuffer = 0;
6096a5c4c7bab6718524de7253da8309143ab48befChris Craik
6196a5c4c7bab6718524de7253da8309143ab48befChris Craik    glDeleteBuffers(1, &mQuadListIndices);
6296a5c4c7bab6718524de7253da8309143ab48befChris Craik    mQuadListIndices = 0;
63117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik}
6496a5c4c7bab6718524de7253da8309143ab48befChris Craik
65117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craikvoid MeshState::dump() {
6608fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik    ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
67f27133df2d179c99d6bc1ae644af09e9153a0071Chris Craik    ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer);
6808fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik    ALOGD("MeshState vertices: vertex data %p, stride %d",
6908fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik            mCurrentPositionPointer, mCurrentPositionStride);
7008fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik    ALOGD("MeshState texCoord: data %p, stride %d",
7108fa43fdeb646f56edcd8b33d06ee7d79b203426Chris Craik            mCurrentTexCoordsPointer, mCurrentTexCoordsStride);
7296a5c4c7bab6718524de7253da8309143ab48befChris Craik}
7396a5c4c7bab6718524de7253da8309143ab48befChris Craik
7496a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
7596a5c4c7bab6718524de7253da8309143ab48befChris Craik// Buffer Objects
7696a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
7796a5c4c7bab6718524de7253da8309143ab48befChris Craik
781b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::bindMeshBuffer(GLuint buffer) {
79117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    if (mCurrentBuffer != buffer) {
80117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        glBindBuffer(GL_ARRAY_BUFFER, buffer);
81117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        mCurrentBuffer = buffer;
821b7db4000eabb570697f4c5097588acbfa4df62bChris Craik
831b7db4000eabb570697f4c5097588acbfa4df62bChris Craik        // buffer has changed, so invalidate cached vertex pos/texcoord pointers
841b7db4000eabb570697f4c5097588acbfa4df62bChris Craik        resetVertexPointers();
8596a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
861b7db4000eabb570697f4c5097588acbfa4df62bChris Craik}
871b7db4000eabb570697f4c5097588acbfa4df62bChris Craik
881b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::unbindMeshBuffer() {
891b7db4000eabb570697f4c5097588acbfa4df62bChris Craik    return bindMeshBuffer(0);
9096a5c4c7bab6718524de7253da8309143ab48befChris Craik}
9196a5c4c7bab6718524de7253da8309143ab48befChris Craik
928d2cf943d9c7292e54726399faefdec4a01c084bChris Craikvoid MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
938d2cf943d9c7292e54726399faefdec4a01c084bChris Craik        const void* data, GLenum usage) {
948d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    if (!*buffer) {
958d2cf943d9c7292e54726399faefdec4a01c084bChris Craik        glGenBuffers(1, buffer);
968d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    }
978d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    bindMeshBuffer(*buffer);
988d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    glBufferData(GL_ARRAY_BUFFER, size, data, usage);
998d2cf943d9c7292e54726399faefdec4a01c084bChris Craik}
1008d2cf943d9c7292e54726399faefdec4a01c084bChris Craik
101fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyvvoid MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset,
102fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyv        GLsizeiptr size, const void* data) {
103fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyv    bindMeshBuffer(buffer);
104fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyv    glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
105fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyv}
106fd3744b7d88d0015cfb36be2b485c4b6ba0c1b58sergeyv
1078d2cf943d9c7292e54726399faefdec4a01c084bChris Craikvoid MeshState::deleteMeshBuffer(GLuint buffer) {
1088d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    if (buffer == mCurrentBuffer) {
1098d2cf943d9c7292e54726399faefdec4a01c084bChris Craik        // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO).
1108d2cf943d9c7292e54726399faefdec4a01c084bChris Craik        // Reflect this in our cached value.
1118d2cf943d9c7292e54726399faefdec4a01c084bChris Craik        mCurrentBuffer = 0;
1128d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    }
1138d2cf943d9c7292e54726399faefdec4a01c084bChris Craik    glDeleteBuffers(1, &buffer);
1148d2cf943d9c7292e54726399faefdec4a01c084bChris Craik}
1158d2cf943d9c7292e54726399faefdec4a01c084bChris Craik
11696a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
11796a5c4c7bab6718524de7253da8309143ab48befChris Craik// Vertices
11896a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
11996a5c4c7bab6718524de7253da8309143ab48befChris Craik
1201b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) {
1211b7db4000eabb570697f4c5097588acbfa4df62bChris Craik    // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
1221b7db4000eabb570697f4c5097588acbfa4df62bChris Craik    if (mCurrentBuffer == 0
1231b7db4000eabb570697f4c5097588acbfa4df62bChris Craik            || vertices != mCurrentPositionPointer
1241b7db4000eabb570697f4c5097588acbfa4df62bChris Craik            || stride != mCurrentPositionStride) {
1256c15ffa196fc9b7724c189d833c3435d8db12266Chris Craik        glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
12696a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentPositionPointer = vertices;
12796a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentPositionStride = stride;
12896a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
12996a5c4c7bab6718524de7253da8309143ab48befChris Craik}
13096a5c4c7bab6718524de7253da8309143ab48befChris Craik
1311b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) {
1321b7db4000eabb570697f4c5097588acbfa4df62bChris Craik    // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
1331b7db4000eabb570697f4c5097588acbfa4df62bChris Craik    if (mCurrentBuffer == 0
1341b7db4000eabb570697f4c5097588acbfa4df62bChris Craik            || vertices != mCurrentTexCoordsPointer
1351b7db4000eabb570697f4c5097588acbfa4df62bChris Craik            || stride != mCurrentTexCoordsStride) {
1366c15ffa196fc9b7724c189d833c3435d8db12266Chris Craik        glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
13796a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentTexCoordsPointer = vertices;
13896a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentTexCoordsStride = stride;
13996a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
14096a5c4c7bab6718524de7253da8309143ab48befChris Craik}
14196a5c4c7bab6718524de7253da8309143ab48befChris Craik
14296a5c4c7bab6718524de7253da8309143ab48befChris Craikvoid MeshState::resetVertexPointers() {
14396a5c4c7bab6718524de7253da8309143ab48befChris Craik    mCurrentPositionPointer = this;
14496a5c4c7bab6718524de7253da8309143ab48befChris Craik    mCurrentTexCoordsPointer = this;
14596a5c4c7bab6718524de7253da8309143ab48befChris Craik}
14696a5c4c7bab6718524de7253da8309143ab48befChris Craik
14796a5c4c7bab6718524de7253da8309143ab48befChris Craikvoid MeshState::enableTexCoordsVertexArray() {
14896a5c4c7bab6718524de7253da8309143ab48befChris Craik    if (!mTexCoordsArrayEnabled) {
14996a5c4c7bab6718524de7253da8309143ab48befChris Craik        glEnableVertexAttribArray(Program::kBindingTexCoords);
15096a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentTexCoordsPointer = this;
15196a5c4c7bab6718524de7253da8309143ab48befChris Craik        mTexCoordsArrayEnabled = true;
15296a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
15396a5c4c7bab6718524de7253da8309143ab48befChris Craik}
15496a5c4c7bab6718524de7253da8309143ab48befChris Craik
15596a5c4c7bab6718524de7253da8309143ab48befChris Craikvoid MeshState::disableTexCoordsVertexArray() {
15696a5c4c7bab6718524de7253da8309143ab48befChris Craik    if (mTexCoordsArrayEnabled) {
15796a5c4c7bab6718524de7253da8309143ab48befChris Craik        glDisableVertexAttribArray(Program::kBindingTexCoords);
15896a5c4c7bab6718524de7253da8309143ab48befChris Craik        mTexCoordsArrayEnabled = false;
15996a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
16096a5c4c7bab6718524de7253da8309143ab48befChris Craik}
16196a5c4c7bab6718524de7253da8309143ab48befChris Craik
16296a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
16396a5c4c7bab6718524de7253da8309143ab48befChris Craik// Indices
16496a5c4c7bab6718524de7253da8309143ab48befChris Craik///////////////////////////////////////////////////////////////////////////////
16596a5c4c7bab6718524de7253da8309143ab48befChris Craik
1661b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::bindIndicesBuffer(const GLuint buffer) {
16796a5c4c7bab6718524de7253da8309143ab48befChris Craik    if (mCurrentIndicesBuffer != buffer) {
16896a5c4c7bab6718524de7253da8309143ab48befChris Craik        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
16996a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentIndicesBuffer = buffer;
17096a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
17196a5c4c7bab6718524de7253da8309143ab48befChris Craik}
17296a5c4c7bab6718524de7253da8309143ab48befChris Craik
1731b7db4000eabb570697f4c5097588acbfa4df62bChris Craikvoid MeshState::unbindIndicesBuffer() {
17496a5c4c7bab6718524de7253da8309143ab48befChris Craik    if (mCurrentIndicesBuffer) {
17596a5c4c7bab6718524de7253da8309143ab48befChris Craik        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
17696a5c4c7bab6718524de7253da8309143ab48befChris Craik        mCurrentIndicesBuffer = 0;
17796a5c4c7bab6718524de7253da8309143ab48befChris Craik    }
17896a5c4c7bab6718524de7253da8309143ab48befChris Craik}
17996a5c4c7bab6718524de7253da8309143ab48befChris Craik
18096a5c4c7bab6718524de7253da8309143ab48befChris Craik} /* namespace uirenderer */
18196a5c4c7bab6718524de7253da8309143ab48befChris Craik} /* namespace android */
18296a5c4c7bab6718524de7253da8309143ab48befChris Craik
183