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 
VertexBuffer()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 
~VertexBuffer()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>
alloc(int vertexCount)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>
allocIndices(int indexCount)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>
copyInto(const VertexBuffer & srcBuffer,float xOffset,float yOffset)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 
getBuffer()124     const void* getBuffer() const { return mBuffer; }
getIndices()125     const void* getIndices() const { return mIndices; }
getBounds()126     const Rect& getBounds() const { return mBounds; }
getVertexCount()127     unsigned int getVertexCount() const { return mVertexCount; }
getSize()128     unsigned int getSize() const { return mByteCount; }
getIndexCount()129     unsigned int getIndexCount() const { return mIndexCount; }
updateIndexCount(unsigned int newCount)130     void updateIndexCount(unsigned int newCount) {
131         mIndexCount = std::min(newCount, mAllocatedIndexCount);
132     }
updateVertexCount(unsigned int newCount)133     void updateVertexCount(unsigned int newCount) {
134         mVertexCount = std::min(newCount, mAllocatedVertexCount);
135     }
getMeshFeatureFlags()136     MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
setMeshFeatureFlags(int flags)137     void setMeshFeatureFlags(int flags) {
138         mMeshFeatureFlags = static_cast<MeshFeatureFlags>(flags);
139     }
140 
setBounds(Rect bounds)141     void setBounds(Rect bounds) { mBounds = bounds; }
142 
143     template <class TYPE>
createDegenerateSeparators(int allocSize)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>
cleanup(void * buffer)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