Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2012 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 
     17 #ifndef ANDROID_HWUI_VERTEX_BUFFER_H
     18 #define ANDROID_HWUI_VERTEX_BUFFER_H
     19 
     20 #include "utils/MathUtils.h"
     21 
     22 namespace android {
     23 namespace uirenderer {
     24 
     25 class VertexBuffer {
     26 public:
     27     enum Mode {
     28         kStandard = 0,
     29         kOnePolyRingShadow = 1,
     30         kTwoPolyRingShadow = 2,
     31         kIndices = 3
     32     };
     33 
     34     VertexBuffer()
     35             : mBuffer(0)
     36             , mIndices(0)
     37             , mVertexCount(0)
     38             , mIndexCount(0)
     39             , mAllocatedVertexCount(0)
     40             , mAllocatedIndexCount(0)
     41             , mByteCount(0)
     42             , mMode(kStandard)
     43             , mReallocBuffer(0)
     44             , mCleanupMethod(NULL)
     45             , mCleanupIndexMethod(NULL)
     46     {}
     47 
     48     ~VertexBuffer() {
     49         if (mCleanupMethod) mCleanupMethod(mBuffer);
     50         if (mCleanupIndexMethod) mCleanupIndexMethod(mIndices);
     51     }
     52 
     53     /**
     54        This should be the only method used by the Tessellator. Subsequent calls to
     55        alloc will allocate space within the first allocation (useful if you want to
     56        eventually allocate multiple regions within a single VertexBuffer, such as
     57        with PathTessellator::tessellateLines())
     58      */
     59     template <class TYPE>
     60     TYPE* alloc(int vertexCount) {
     61         if (mVertexCount) {
     62             TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
     63             // already have allocated the buffer, re-allocate space within
     64             if (mReallocBuffer != mBuffer) {
     65                 // not first re-allocation, leave space for degenerate triangles to separate strips
     66                 reallocBuffer += 2;
     67             }
     68             mReallocBuffer = reallocBuffer + vertexCount;
     69             return reallocBuffer;
     70         }
     71         mAllocatedVertexCount = vertexCount;
     72         mVertexCount = vertexCount;
     73         mByteCount = mVertexCount * sizeof(TYPE);
     74         mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
     75 
     76         mCleanupMethod = &(cleanup<TYPE>);
     77 
     78         return (TYPE*)mBuffer;
     79     }
     80 
     81     template <class TYPE>
     82     TYPE* allocIndices(int indexCount) {
     83         mAllocatedIndexCount = indexCount;
     84         mIndexCount = indexCount;
     85         mIndices = (void*)new TYPE[indexCount];
     86 
     87         mCleanupIndexMethod = &(cleanup<TYPE>);
     88 
     89         return (TYPE*)mIndices;
     90     }
     91 
     92     template <class TYPE>
     93     void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
     94         int verticesToCopy = srcBuffer.getVertexCount();
     95 
     96         TYPE* dst = alloc<TYPE>(verticesToCopy);
     97         TYPE* src = (TYPE*)srcBuffer.getBuffer();
     98 
     99         for (int i = 0; i < verticesToCopy; i++) {
    100             TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
    101         }
    102     }
    103 
    104     /**
    105      * Brute force bounds computation, used only if the producer of this
    106      * vertex buffer can't determine bounds more simply/efficiently
    107      */
    108     template <class TYPE>
    109     void computeBounds(int vertexCount = 0) {
    110         if (!mVertexCount) {
    111             mBounds.setEmpty();
    112             return;
    113         }
    114 
    115         // default: compute over every vertex
    116         if (vertexCount == 0) vertexCount = mVertexCount;
    117 
    118         TYPE* current = (TYPE*)mBuffer;
    119         TYPE* end = current + vertexCount;
    120         mBounds.set(current->x, current->y, current->x, current->y);
    121         for (; current < end; current++) {
    122             mBounds.expandToCoverVertex(current->x, current->y);
    123         }
    124     }
    125 
    126     const void* getBuffer() const { return mBuffer; }
    127     const void* getIndices() const { return mIndices; }
    128     const Rect& getBounds() const { return mBounds; }
    129     unsigned int getVertexCount() const { return mVertexCount; }
    130     unsigned int getSize() const { return mByteCount; }
    131     unsigned int getIndexCount() const { return mIndexCount; }
    132     void updateIndexCount(unsigned int newCount)  {
    133         mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
    134     }
    135     void updateVertexCount(unsigned int newCount)  {
    136         mVertexCount = MathUtils::min(newCount, mAllocatedVertexCount);
    137     }
    138     Mode getMode() const { return mMode; }
    139 
    140     void setBounds(Rect bounds) { mBounds = bounds; }
    141     void setMode(Mode mode) { mMode = mode; }
    142 
    143     template <class TYPE>
    144     void createDegenerateSeparators(int allocSize) {
    145         TYPE* end = (TYPE*)mBuffer + mVertexCount;
    146         for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
    147             memcpy(degen, degen - 1, sizeof(TYPE));
    148             memcpy(degen + 1, degen + 2, sizeof(TYPE));
    149         }
    150     }
    151 
    152 private:
    153     template <class TYPE>
    154     static void cleanup(void* buffer) {
    155         delete[] (TYPE*)buffer;
    156     }
    157 
    158     Rect mBounds;
    159 
    160     void* mBuffer;
    161     void* mIndices;
    162 
    163     unsigned int mVertexCount;
    164     unsigned int mIndexCount;
    165     unsigned int mAllocatedVertexCount;
    166     unsigned int mAllocatedIndexCount;
    167     unsigned int mByteCount;
    168 
    169     Mode mMode;
    170 
    171     void* mReallocBuffer; // used for multi-allocation
    172 
    173     void (*mCleanupMethod)(void*);
    174     void (*mCleanupIndexMethod)(void*);
    175 };
    176 
    177 }; // namespace uirenderer
    178 }; // namespace android
    179 
    180 #endif // ANDROID_HWUI_VERTEX_BUFFER_H
    181