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