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