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 <algorithm>
     21 
     22 namespace android {
     23 namespace uirenderer {
     24 
     25 class VertexBuffer {
     26 public:
     27     enum MeshFeatureFlags {
     28         kNone = 0,
     29         kAlpha = 1 << 0,
     30         kIndices = 1 << 1,
     31     };
     32 
     33     VertexBuffer()
     34             : mBuffer(nullptr)
     35             , mIndices(nullptr)
     36             , mVertexCount(0)
     37             , mIndexCount(0)
     38             , mAllocatedVertexCount(0)
     39             , mAllocatedIndexCount(0)
     40             , mByteCount(0)
     41             , mMeshFeatureFlags(kNone)
     42             , mReallocBuffer(nullptr)
     43             , mCleanupMethod(nullptr)
     44             , mCleanupIndexMethod(nullptr) {}
     45 
     46     ~VertexBuffer() {
     47         if (mCleanupMethod) mCleanupMethod(mBuffer);
     48         if (mCleanupIndexMethod) mCleanupIndexMethod(mIndices);
     49     }
     50 
     51     /**
     52        This should be the only method used by the Tessellator. Subsequent calls to
     53        alloc will allocate space within the first allocation (useful if you want to
     54        eventually allocate multiple regions within a single VertexBuffer, such as
     55        with PathTessellator::tessellateLines())
     56      */
     57     template <class TYPE>
     58     TYPE* alloc(int vertexCount) {
     59         if (mVertexCount) {
     60             TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
     61             // already have allocated the buffer, re-allocate space within
     62             if (mReallocBuffer != mBuffer) {
     63                 // not first re-allocation, leave space for degenerate triangles to separate strips
     64                 reallocBuffer += 2;
     65             }
     66             mReallocBuffer = reallocBuffer + vertexCount;
     67             return reallocBuffer;
     68         }
     69         mAllocatedVertexCount = vertexCount;
     70         mVertexCount = vertexCount;
     71         mByteCount = mVertexCount * sizeof(TYPE);
     72         mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
     73 
     74         mCleanupMethod = &(cleanup<TYPE>);
     75 
     76         return (TYPE*)mBuffer;
     77     }
     78 
     79     template <class TYPE>
     80     TYPE* allocIndices(int indexCount) {
     81         mAllocatedIndexCount = indexCount;
     82         mIndexCount = indexCount;
     83         mIndices = (void*)new TYPE[indexCount];
     84 
     85         mCleanupIndexMethod = &(cleanup<TYPE>);
     86 
     87         return (TYPE*)mIndices;
     88     }
     89 
     90     template <class TYPE>
     91     void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
     92         int verticesToCopy = srcBuffer.getVertexCount();
     93 
     94         TYPE* dst = alloc<TYPE>(verticesToCopy);
     95         TYPE* src = (TYPE*)srcBuffer.getBuffer();
     96 
     97         for (int i = 0; i < verticesToCopy; i++) {
     98             TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
     99         }
    100     }
    101 
    102     /**
    103      * Brute force bounds computation, used only if the producer of this
    104      * vertex buffer can't determine bounds more simply/efficiently
    105      */
    106     template <class TYPE>
    107     void computeBounds(int vertexCount = 0) {
    108         if (!mVertexCount) {
    109             mBounds.setEmpty();
    110             return;
    111         }
    112 
    113         // default: compute over every vertex
    114         if (vertexCount == 0) vertexCount = mVertexCount;
    115 
    116         TYPE* current = (TYPE*)mBuffer;
    117         TYPE* end = current + vertexCount;
    118         mBounds.set(current->x, current->y, current->x, current->y);
    119         for (; current < end; current++) {
    120             mBounds.expandToCover(current->x, current->y);
    121         }
    122     }
    123 
    124     const void* getBuffer() const { return mBuffer; }
    125     const void* getIndices() const { return mIndices; }
    126     const Rect& getBounds() const { return mBounds; }
    127     unsigned int getVertexCount() const { return mVertexCount; }
    128     unsigned int getSize() const { return mByteCount; }
    129     unsigned int getIndexCount() const { return mIndexCount; }
    130     void updateIndexCount(unsigned int newCount) {
    131         mIndexCount = std::min(newCount, mAllocatedIndexCount);
    132     }
    133     void updateVertexCount(unsigned int newCount) {
    134         mVertexCount = std::min(newCount, mAllocatedVertexCount);
    135     }
    136     MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
    137     void setMeshFeatureFlags(int flags) {
    138         mMeshFeatureFlags = static_cast<MeshFeatureFlags>(flags);
    139     }
    140 
    141     void setBounds(Rect bounds) { mBounds = bounds; }
    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     MeshFeatureFlags mMeshFeatureFlags;
    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