xref: /aosp_15_r20/frameworks/base/libs/hwui/VertexBuffer.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #ifndef ANDROID_HWUI_VERTEX_BUFFER_H
18*d57664e9SAndroid Build Coastguard Worker #define ANDROID_HWUI_VERTEX_BUFFER_H
19*d57664e9SAndroid Build Coastguard Worker 
20*d57664e9SAndroid Build Coastguard Worker #include <algorithm>
21*d57664e9SAndroid Build Coastguard Worker 
22*d57664e9SAndroid Build Coastguard Worker namespace android {
23*d57664e9SAndroid Build Coastguard Worker namespace uirenderer {
24*d57664e9SAndroid Build Coastguard Worker 
25*d57664e9SAndroid Build Coastguard Worker class VertexBuffer {
26*d57664e9SAndroid Build Coastguard Worker public:
27*d57664e9SAndroid Build Coastguard Worker     enum MeshFeatureFlags {
28*d57664e9SAndroid Build Coastguard Worker         kNone = 0,
29*d57664e9SAndroid Build Coastguard Worker         kAlpha = 1 << 0,
30*d57664e9SAndroid Build Coastguard Worker         kIndices = 1 << 1,
31*d57664e9SAndroid Build Coastguard Worker     };
32*d57664e9SAndroid Build Coastguard Worker 
VertexBuffer()33*d57664e9SAndroid Build Coastguard Worker     VertexBuffer()
34*d57664e9SAndroid Build Coastguard Worker             : mBuffer(nullptr)
35*d57664e9SAndroid Build Coastguard Worker             , mIndices(nullptr)
36*d57664e9SAndroid Build Coastguard Worker             , mVertexCount(0)
37*d57664e9SAndroid Build Coastguard Worker             , mIndexCount(0)
38*d57664e9SAndroid Build Coastguard Worker             , mAllocatedVertexCount(0)
39*d57664e9SAndroid Build Coastguard Worker             , mAllocatedIndexCount(0)
40*d57664e9SAndroid Build Coastguard Worker             , mByteCount(0)
41*d57664e9SAndroid Build Coastguard Worker             , mMeshFeatureFlags(kNone)
42*d57664e9SAndroid Build Coastguard Worker             , mReallocBuffer(nullptr)
43*d57664e9SAndroid Build Coastguard Worker             , mCleanupMethod(nullptr)
44*d57664e9SAndroid Build Coastguard Worker             , mCleanupIndexMethod(nullptr) {}
45*d57664e9SAndroid Build Coastguard Worker 
~VertexBuffer()46*d57664e9SAndroid Build Coastguard Worker     ~VertexBuffer() {
47*d57664e9SAndroid Build Coastguard Worker         if (mCleanupMethod) mCleanupMethod(mBuffer);
48*d57664e9SAndroid Build Coastguard Worker         if (mCleanupIndexMethod) mCleanupIndexMethod(mIndices);
49*d57664e9SAndroid Build Coastguard Worker     }
50*d57664e9SAndroid Build Coastguard Worker 
51*d57664e9SAndroid Build Coastguard Worker     /**
52*d57664e9SAndroid Build Coastguard Worker        This should be the only method used by the Tessellator. Subsequent calls to
53*d57664e9SAndroid Build Coastguard Worker        alloc will allocate space within the first allocation (useful if you want to
54*d57664e9SAndroid Build Coastguard Worker        eventually allocate multiple regions within a single VertexBuffer, such as
55*d57664e9SAndroid Build Coastguard Worker        with PathTessellator::tessellateLines())
56*d57664e9SAndroid Build Coastguard Worker      */
57*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
alloc(int vertexCount)58*d57664e9SAndroid Build Coastguard Worker     TYPE* alloc(int vertexCount) {
59*d57664e9SAndroid Build Coastguard Worker         if (mVertexCount) {
60*d57664e9SAndroid Build Coastguard Worker             TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
61*d57664e9SAndroid Build Coastguard Worker             // already have allocated the buffer, re-allocate space within
62*d57664e9SAndroid Build Coastguard Worker             if (mReallocBuffer != mBuffer) {
63*d57664e9SAndroid Build Coastguard Worker                 // not first re-allocation, leave space for degenerate triangles to separate strips
64*d57664e9SAndroid Build Coastguard Worker                 reallocBuffer += 2;
65*d57664e9SAndroid Build Coastguard Worker             }
66*d57664e9SAndroid Build Coastguard Worker             mReallocBuffer = reallocBuffer + vertexCount;
67*d57664e9SAndroid Build Coastguard Worker             return reallocBuffer;
68*d57664e9SAndroid Build Coastguard Worker         }
69*d57664e9SAndroid Build Coastguard Worker         mAllocatedVertexCount = vertexCount;
70*d57664e9SAndroid Build Coastguard Worker         mVertexCount = vertexCount;
71*d57664e9SAndroid Build Coastguard Worker         mByteCount = mVertexCount * sizeof(TYPE);
72*d57664e9SAndroid Build Coastguard Worker         mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
73*d57664e9SAndroid Build Coastguard Worker 
74*d57664e9SAndroid Build Coastguard Worker         mCleanupMethod = &(cleanup<TYPE>);
75*d57664e9SAndroid Build Coastguard Worker 
76*d57664e9SAndroid Build Coastguard Worker         return (TYPE*)mBuffer;
77*d57664e9SAndroid Build Coastguard Worker     }
78*d57664e9SAndroid Build Coastguard Worker 
79*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
allocIndices(int indexCount)80*d57664e9SAndroid Build Coastguard Worker     TYPE* allocIndices(int indexCount) {
81*d57664e9SAndroid Build Coastguard Worker         mAllocatedIndexCount = indexCount;
82*d57664e9SAndroid Build Coastguard Worker         mIndexCount = indexCount;
83*d57664e9SAndroid Build Coastguard Worker         mIndices = (void*)new TYPE[indexCount];
84*d57664e9SAndroid Build Coastguard Worker 
85*d57664e9SAndroid Build Coastguard Worker         mCleanupIndexMethod = &(cleanup<TYPE>);
86*d57664e9SAndroid Build Coastguard Worker 
87*d57664e9SAndroid Build Coastguard Worker         return (TYPE*)mIndices;
88*d57664e9SAndroid Build Coastguard Worker     }
89*d57664e9SAndroid Build Coastguard Worker 
90*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
copyInto(const VertexBuffer & srcBuffer,float xOffset,float yOffset)91*d57664e9SAndroid Build Coastguard Worker     void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
92*d57664e9SAndroid Build Coastguard Worker         int verticesToCopy = srcBuffer.getVertexCount();
93*d57664e9SAndroid Build Coastguard Worker 
94*d57664e9SAndroid Build Coastguard Worker         TYPE* dst = alloc<TYPE>(verticesToCopy);
95*d57664e9SAndroid Build Coastguard Worker         TYPE* src = (TYPE*)srcBuffer.getBuffer();
96*d57664e9SAndroid Build Coastguard Worker 
97*d57664e9SAndroid Build Coastguard Worker         for (int i = 0; i < verticesToCopy; i++) {
98*d57664e9SAndroid Build Coastguard Worker             TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
99*d57664e9SAndroid Build Coastguard Worker         }
100*d57664e9SAndroid Build Coastguard Worker     }
101*d57664e9SAndroid Build Coastguard Worker 
102*d57664e9SAndroid Build Coastguard Worker     /**
103*d57664e9SAndroid Build Coastguard Worker      * Brute force bounds computation, used only if the producer of this
104*d57664e9SAndroid Build Coastguard Worker      * vertex buffer can't determine bounds more simply/efficiently
105*d57664e9SAndroid Build Coastguard Worker      */
106*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
107*d57664e9SAndroid Build Coastguard Worker     void computeBounds(int vertexCount = 0) {
108*d57664e9SAndroid Build Coastguard Worker         if (!mVertexCount) {
109*d57664e9SAndroid Build Coastguard Worker             mBounds.setEmpty();
110*d57664e9SAndroid Build Coastguard Worker             return;
111*d57664e9SAndroid Build Coastguard Worker         }
112*d57664e9SAndroid Build Coastguard Worker 
113*d57664e9SAndroid Build Coastguard Worker         // default: compute over every vertex
114*d57664e9SAndroid Build Coastguard Worker         if (vertexCount == 0) vertexCount = mVertexCount;
115*d57664e9SAndroid Build Coastguard Worker 
116*d57664e9SAndroid Build Coastguard Worker         TYPE* current = (TYPE*)mBuffer;
117*d57664e9SAndroid Build Coastguard Worker         TYPE* end = current + vertexCount;
118*d57664e9SAndroid Build Coastguard Worker         mBounds.set(current->x, current->y, current->x, current->y);
119*d57664e9SAndroid Build Coastguard Worker         for (; current < end; current++) {
120*d57664e9SAndroid Build Coastguard Worker             mBounds.expandToCover(current->x, current->y);
121*d57664e9SAndroid Build Coastguard Worker         }
122*d57664e9SAndroid Build Coastguard Worker     }
123*d57664e9SAndroid Build Coastguard Worker 
getBuffer()124*d57664e9SAndroid Build Coastguard Worker     const void* getBuffer() const { return mBuffer; }
getIndices()125*d57664e9SAndroid Build Coastguard Worker     const void* getIndices() const { return mIndices; }
getBounds()126*d57664e9SAndroid Build Coastguard Worker     const Rect& getBounds() const { return mBounds; }
getVertexCount()127*d57664e9SAndroid Build Coastguard Worker     unsigned int getVertexCount() const { return mVertexCount; }
getSize()128*d57664e9SAndroid Build Coastguard Worker     unsigned int getSize() const { return mByteCount; }
getIndexCount()129*d57664e9SAndroid Build Coastguard Worker     unsigned int getIndexCount() const { return mIndexCount; }
updateIndexCount(unsigned int newCount)130*d57664e9SAndroid Build Coastguard Worker     void updateIndexCount(unsigned int newCount) {
131*d57664e9SAndroid Build Coastguard Worker         mIndexCount = std::min(newCount, mAllocatedIndexCount);
132*d57664e9SAndroid Build Coastguard Worker     }
updateVertexCount(unsigned int newCount)133*d57664e9SAndroid Build Coastguard Worker     void updateVertexCount(unsigned int newCount) {
134*d57664e9SAndroid Build Coastguard Worker         mVertexCount = std::min(newCount, mAllocatedVertexCount);
135*d57664e9SAndroid Build Coastguard Worker     }
getMeshFeatureFlags()136*d57664e9SAndroid Build Coastguard Worker     MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
setMeshFeatureFlags(int flags)137*d57664e9SAndroid Build Coastguard Worker     void setMeshFeatureFlags(int flags) {
138*d57664e9SAndroid Build Coastguard Worker         mMeshFeatureFlags = static_cast<MeshFeatureFlags>(flags);
139*d57664e9SAndroid Build Coastguard Worker     }
140*d57664e9SAndroid Build Coastguard Worker 
setBounds(Rect bounds)141*d57664e9SAndroid Build Coastguard Worker     void setBounds(Rect bounds) { mBounds = bounds; }
142*d57664e9SAndroid Build Coastguard Worker 
143*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
createDegenerateSeparators(int allocSize)144*d57664e9SAndroid Build Coastguard Worker     void createDegenerateSeparators(int allocSize) {
145*d57664e9SAndroid Build Coastguard Worker         TYPE* end = (TYPE*)mBuffer + mVertexCount;
146*d57664e9SAndroid Build Coastguard Worker         for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
147*d57664e9SAndroid Build Coastguard Worker             memcpy(degen, degen - 1, sizeof(TYPE));
148*d57664e9SAndroid Build Coastguard Worker             memcpy(degen + 1, degen + 2, sizeof(TYPE));
149*d57664e9SAndroid Build Coastguard Worker         }
150*d57664e9SAndroid Build Coastguard Worker     }
151*d57664e9SAndroid Build Coastguard Worker 
152*d57664e9SAndroid Build Coastguard Worker private:
153*d57664e9SAndroid Build Coastguard Worker     template <class TYPE>
cleanup(void * buffer)154*d57664e9SAndroid Build Coastguard Worker     static void cleanup(void* buffer) {
155*d57664e9SAndroid Build Coastguard Worker         delete[](TYPE*) buffer;
156*d57664e9SAndroid Build Coastguard Worker     }
157*d57664e9SAndroid Build Coastguard Worker 
158*d57664e9SAndroid Build Coastguard Worker     Rect mBounds;
159*d57664e9SAndroid Build Coastguard Worker 
160*d57664e9SAndroid Build Coastguard Worker     void* mBuffer;
161*d57664e9SAndroid Build Coastguard Worker     void* mIndices;
162*d57664e9SAndroid Build Coastguard Worker 
163*d57664e9SAndroid Build Coastguard Worker     unsigned int mVertexCount;
164*d57664e9SAndroid Build Coastguard Worker     unsigned int mIndexCount;
165*d57664e9SAndroid Build Coastguard Worker     unsigned int mAllocatedVertexCount;
166*d57664e9SAndroid Build Coastguard Worker     unsigned int mAllocatedIndexCount;
167*d57664e9SAndroid Build Coastguard Worker     unsigned int mByteCount;
168*d57664e9SAndroid Build Coastguard Worker 
169*d57664e9SAndroid Build Coastguard Worker     MeshFeatureFlags mMeshFeatureFlags;
170*d57664e9SAndroid Build Coastguard Worker 
171*d57664e9SAndroid Build Coastguard Worker     void* mReallocBuffer;  // used for multi-allocation
172*d57664e9SAndroid Build Coastguard Worker 
173*d57664e9SAndroid Build Coastguard Worker     void (*mCleanupMethod)(void*);
174*d57664e9SAndroid Build Coastguard Worker     void (*mCleanupIndexMethod)(void*);
175*d57664e9SAndroid Build Coastguard Worker };
176*d57664e9SAndroid Build Coastguard Worker 
177*d57664e9SAndroid Build Coastguard Worker }  // namespace uirenderer
178*d57664e9SAndroid Build Coastguard Worker }  // namespace android
179*d57664e9SAndroid Build Coastguard Worker 
180*d57664e9SAndroid Build Coastguard Worker #endif  // ANDROID_HWUI_VERTEX_BUFFER_H
181