VertexBuffer.h revision d5e8ade498b41b42874273cbfa375aed7b4d6a08
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
22namespace android {
23namespace uirenderer {
24
25class VertexBuffer {
26public:
27    enum Mode {
28        kStandard = 0,
29        kOnePolyRingShadow = 1,
30        kTwoPolyRingShadow = 2,
31        kIndices = 3
32    };
33
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
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>
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>
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>
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
126    const void* getBuffer() const { return mBuffer; }
127    const void* getIndices() const { return mIndices; }
128    const Rect& getBounds() const { return mBounds; }
129    unsigned int getVertexCount() const { return mVertexCount; }
130    unsigned int getSize() const { return mByteCount; }
131    unsigned int getIndexCount() const { return mIndexCount; }
132    void updateIndexCount(unsigned int newCount)  {
133        mIndexCount = MathUtils::min(newCount, mAllocatedIndexCount);
134    }
135    void updateVertexCount(unsigned int newCount)  {
136        newCount = MathUtils::min(newCount, mAllocatedVertexCount);
137    }
138    Mode getMode() const { return mMode; }
139
140    void setBounds(Rect bounds) { mBounds = bounds; }
141    void setMode(Mode mode) { mMode = mode; }
142
143    template <class TYPE>
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
152private:
153    template <class TYPE>
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