Home | History | Annotate | Download | only in renderstate
      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 namespace android {
     21 namespace uirenderer {
     22 
     23 MeshState::MeshState()
     24         : mCurrentIndicesBuffer(0)
     25         , mCurrentPixelBuffer(0)
     26         , mCurrentPositionPointer(this)
     27         , mCurrentPositionStride(0)
     28         , mCurrentTexCoordsPointer(this)
     29         , mCurrentTexCoordsStride(0)
     30         , mTexCoordsArrayEnabled(false)
     31         , mQuadListIndices(0) {
     32     glGenBuffers(1, &mUnitQuadBuffer);
     33     glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
     34     glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);
     35     mCurrentBuffer = mUnitQuadBuffer;
     36 
     37     uint16_t regionIndices[kMaxNumberOfQuads * 6];
     38     for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
     39         uint16_t quad = i * 4;
     40         int index = i * 6;
     41         regionIndices[index] = quad;          // top-left
     42         regionIndices[index + 1] = quad + 1;  // top-right
     43         regionIndices[index + 2] = quad + 2;  // bottom-left
     44         regionIndices[index + 3] = quad + 2;  // bottom-left
     45         regionIndices[index + 4] = quad + 1;  // top-right
     46         regionIndices[index + 5] = quad + 3;  // bottom-right
     47     }
     48     glGenBuffers(1, &mQuadListIndices);
     49     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
     50     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW);
     51     mCurrentIndicesBuffer = mQuadListIndices;
     52 
     53     // position attribute always enabled
     54     glEnableVertexAttribArray(Program::kBindingPosition);
     55 }
     56 
     57 MeshState::~MeshState() {
     58     glDeleteBuffers(1, &mUnitQuadBuffer);
     59     mCurrentBuffer = 0;
     60 
     61     glDeleteBuffers(1, &mQuadListIndices);
     62     mQuadListIndices = 0;
     63 }
     64 
     65 void MeshState::dump() {
     66     ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
     67     ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer);
     68     ALOGD("MeshState vertices: vertex data %p, stride %d", mCurrentPositionPointer,
     69           mCurrentPositionStride);
     70     ALOGD("MeshState texCoord: data %p, stride %d", mCurrentTexCoordsPointer,
     71           mCurrentTexCoordsStride);
     72 }
     73 
     74 ///////////////////////////////////////////////////////////////////////////////
     75 // Buffer Objects
     76 ///////////////////////////////////////////////////////////////////////////////
     77 
     78 void MeshState::bindMeshBuffer(GLuint buffer) {
     79     if (mCurrentBuffer != buffer) {
     80         glBindBuffer(GL_ARRAY_BUFFER, buffer);
     81         mCurrentBuffer = buffer;
     82 
     83         // buffer has changed, so invalidate cached vertex pos/texcoord pointers
     84         resetVertexPointers();
     85     }
     86 }
     87 
     88 void MeshState::unbindMeshBuffer() {
     89     return bindMeshBuffer(0);
     90 }
     91 
     92 void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data,
     93                                       GLenum usage) {
     94     if (!*buffer) {
     95         glGenBuffers(1, buffer);
     96     }
     97     bindMeshBuffer(*buffer);
     98     glBufferData(GL_ARRAY_BUFFER, size, data, usage);
     99 }
    100 
    101 void MeshState::updateMeshBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size,
    102                                         const void* data) {
    103     bindMeshBuffer(buffer);
    104     glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
    105 }
    106 
    107 void MeshState::deleteMeshBuffer(GLuint buffer) {
    108     if (buffer == mCurrentBuffer) {
    109         // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO).
    110         // Reflect this in our cached value.
    111         mCurrentBuffer = 0;
    112     }
    113     glDeleteBuffers(1, &buffer);
    114 }
    115 
    116 ///////////////////////////////////////////////////////////////////////////////
    117 // Vertices
    118 ///////////////////////////////////////////////////////////////////////////////
    119 
    120 void MeshState::bindPositionVertexPointer(const GLvoid* vertices, GLsizei stride) {
    121     // update pos coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
    122     if (mCurrentBuffer == 0 || vertices != mCurrentPositionPointer ||
    123         stride != mCurrentPositionStride) {
    124         glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
    125         mCurrentPositionPointer = vertices;
    126         mCurrentPositionStride = stride;
    127     }
    128 }
    129 
    130 void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) {
    131     // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
    132     if (mCurrentBuffer == 0 || vertices != mCurrentTexCoordsPointer ||
    133         stride != mCurrentTexCoordsStride) {
    134         glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
    135         mCurrentTexCoordsPointer = vertices;
    136         mCurrentTexCoordsStride = stride;
    137     }
    138 }
    139 
    140 void MeshState::resetVertexPointers() {
    141     mCurrentPositionPointer = this;
    142     mCurrentTexCoordsPointer = this;
    143 }
    144 
    145 void MeshState::enableTexCoordsVertexArray() {
    146     if (!mTexCoordsArrayEnabled) {
    147         glEnableVertexAttribArray(Program::kBindingTexCoords);
    148         mCurrentTexCoordsPointer = this;
    149         mTexCoordsArrayEnabled = true;
    150     }
    151 }
    152 
    153 void MeshState::disableTexCoordsVertexArray() {
    154     if (mTexCoordsArrayEnabled) {
    155         glDisableVertexAttribArray(Program::kBindingTexCoords);
    156         mTexCoordsArrayEnabled = false;
    157     }
    158 }
    159 
    160 ///////////////////////////////////////////////////////////////////////////////
    161 // Indices
    162 ///////////////////////////////////////////////////////////////////////////////
    163 
    164 void MeshState::bindIndicesBuffer(const GLuint buffer) {
    165     if (mCurrentIndicesBuffer != buffer) {
    166         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
    167         mCurrentIndicesBuffer = buffer;
    168     }
    169 }
    170 
    171 void MeshState::unbindIndicesBuffer() {
    172     if (mCurrentIndicesBuffer) {
    173         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    174         mCurrentIndicesBuffer = 0;
    175     }
    176 }
    177 
    178 } /* namespace uirenderer */
    179 } /* namespace android */
    180