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