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",
     69             mCurrentPositionPointer, mCurrentPositionStride);
     70     ALOGD("MeshState texCoord: data %p, stride %d",
     71             mCurrentTexCoordsPointer, 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,
     93         const void* data, 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,
    102         GLsizeiptr size, 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
    123             || vertices != mCurrentPositionPointer
    124             || stride != mCurrentPositionStride) {
    125         glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
    126         mCurrentPositionPointer = vertices;
    127         mCurrentPositionStride = stride;
    128     }
    129 }
    130 
    131 void MeshState::bindTexCoordsVertexPointer(const GLvoid* vertices, GLsizei stride) {
    132     // update tex coords if !current vbo, since vertices may point into mutable memory (e.g. stack)
    133     if (mCurrentBuffer == 0
    134             || vertices != mCurrentTexCoordsPointer
    135             || stride != mCurrentTexCoordsStride) {
    136         glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
    137         mCurrentTexCoordsPointer = vertices;
    138         mCurrentTexCoordsStride = stride;
    139     }
    140 }
    141 
    142 void MeshState::resetVertexPointers() {
    143     mCurrentPositionPointer = this;
    144     mCurrentTexCoordsPointer = this;
    145 }
    146 
    147 void MeshState::enableTexCoordsVertexArray() {
    148     if (!mTexCoordsArrayEnabled) {
    149         glEnableVertexAttribArray(Program::kBindingTexCoords);
    150         mCurrentTexCoordsPointer = this;
    151         mTexCoordsArrayEnabled = true;
    152     }
    153 }
    154 
    155 void MeshState::disableTexCoordsVertexArray() {
    156     if (mTexCoordsArrayEnabled) {
    157         glDisableVertexAttribArray(Program::kBindingTexCoords);
    158         mTexCoordsArrayEnabled = false;
    159     }
    160 }
    161 
    162 ///////////////////////////////////////////////////////////////////////////////
    163 // Indices
    164 ///////////////////////////////////////////////////////////////////////////////
    165 
    166 void MeshState::bindIndicesBuffer(const GLuint buffer) {
    167     if (mCurrentIndicesBuffer != buffer) {
    168         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
    169         mCurrentIndicesBuffer = buffer;
    170     }
    171 }
    172 
    173 void MeshState::unbindIndicesBuffer() {
    174     if (mCurrentIndicesBuffer) {
    175         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    176         mCurrentIndicesBuffer = 0;
    177     }
    178 }
    179 
    180 } /* namespace uirenderer */
    181 } /* namespace android */
    182 
    183