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