155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui/*
255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Copyright (C) 2012 The Android Open Source Project
355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Licensed under the Apache License, Version 2.0 (the "License");
555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * you may not use this file except in compliance with the License.
655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * You may obtain a copy of the License at
755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *      http://www.apache.org/licenses/LICENSE-2.0
955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui *
1055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * Unless required by applicable law or agreed to in writing, software
1155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * distributed under the License is distributed on an "AS IS" BASIS,
1255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * See the License for the specific language governing permissions and
1455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui * limitations under the License.
1555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui */
1655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
1755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#ifndef ANDROID_HWUI_VERTEX_BUFFER_H
1855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#define ANDROID_HWUI_VERTEX_BUFFER_H
1955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
209db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik#include <algorithm>
2155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
2255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace android {
2355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuinamespace uirenderer {
2455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
2555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuiclass VertexBuffer {
2655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuipublic:
27117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    enum MeshFeatureFlags {
28117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        kNone = 0,
29117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        kAlpha = 1 << 0,
30117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        kIndices = 1 << 1,
3105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    };
3205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
3305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    VertexBuffer()
34e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            : mBuffer(nullptr)
35e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            , mIndices(nullptr)
3605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            , mVertexCount(0)
37d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            , mIndexCount(0)
38d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            , mAllocatedVertexCount(0)
39d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui            , mAllocatedIndexCount(0)
4005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik            , mByteCount(0)
41117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik            , mMeshFeatureFlags(kNone)
42e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            , mReallocBuffer(nullptr)
43e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            , mCleanupMethod(nullptr)
44e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            , mCleanupIndexMethod(nullptr)
4555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    {}
4655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
4755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    ~VertexBuffer() {
4855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        if (mCleanupMethod) mCleanupMethod(mBuffer);
49d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        if (mCleanupIndexMethod) mCleanupIndexMethod(mIndices);
5055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
5155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
5255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    /**
5355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui       This should be the only method used by the Tessellator. Subsequent calls to
5455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui       alloc will allocate space within the first allocation (useful if you want to
5555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui       eventually allocate multiple regions within a single VertexBuffer, such as
5605f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik       with PathTessellator::tessellateLines())
5755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui     */
5855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    template <class TYPE>
5955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    TYPE* alloc(int vertexCount) {
6055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        if (mVertexCount) {
6155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
6255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            // already have allocated the buffer, re-allocate space within
6355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            if (mReallocBuffer != mBuffer) {
6455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui                // not first re-allocation, leave space for degenerate triangles to separate strips
6555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui                reallocBuffer += 2;
6655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            }
6755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            mReallocBuffer = reallocBuffer + vertexCount;
6855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            return reallocBuffer;
6955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        }
70d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        mAllocatedVertexCount = vertexCount;
7155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        mVertexCount = vertexCount;
7205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        mByteCount = mVertexCount * sizeof(TYPE);
7355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
74c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik
7555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        mCleanupMethod = &(cleanup<TYPE>);
7655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
7755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        return (TYPE*)mBuffer;
7855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
7955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
8055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    template <class TYPE>
81d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    TYPE* allocIndices(int indexCount) {
82d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        mAllocatedIndexCount = indexCount;
83d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        mIndexCount = indexCount;
84d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        mIndices = (void*)new TYPE[indexCount];
85d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
86d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        mCleanupIndexMethod = &(cleanup<TYPE>);
87d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
88d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui        return (TYPE*)mIndices;
89d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
90d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
91d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    template <class TYPE>
9255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
9355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        int verticesToCopy = srcBuffer.getVertexCount();
9455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
9555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        TYPE* dst = alloc<TYPE>(verticesToCopy);
9655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        TYPE* src = (TYPE*)srcBuffer.getBuffer();
9755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
9855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        for (int i = 0; i < verticesToCopy; i++) {
9955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
10055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        }
10155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
10255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
103c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik    /**
104c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik     * Brute force bounds computation, used only if the producer of this
105c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik     * vertex buffer can't determine bounds more simply/efficiently
106c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik     */
107c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik    template <class TYPE>
1089a89bc6524620c87c7a321433470c668e2b95d69Chris Craik    void computeBounds(int vertexCount = 0) {
109c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        if (!mVertexCount) {
110c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik            mBounds.setEmpty();
111c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik            return;
112c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        }
1139a89bc6524620c87c7a321433470c668e2b95d69Chris Craik
1149a89bc6524620c87c7a321433470c668e2b95d69Chris Craik        // default: compute over every vertex
1159a89bc6524620c87c7a321433470c668e2b95d69Chris Craik        if (vertexCount == 0) vertexCount = mVertexCount;
1169a89bc6524620c87c7a321433470c668e2b95d69Chris Craik
117c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        TYPE* current = (TYPE*)mBuffer;
1189a89bc6524620c87c7a321433470c668e2b95d69Chris Craik        TYPE* end = current + vertexCount;
119c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        mBounds.set(current->x, current->y, current->x, current->y);
120c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        for (; current < end; current++) {
12115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            mBounds.expandToCover(current->x, current->y);
122c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik        }
123c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik    }
124c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik
12555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    const void* getBuffer() const { return mBuffer; }
126d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    const void* getIndices() const { return mIndices; }
12705f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    const Rect& getBounds() const { return mBounds; }
12855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    unsigned int getVertexCount() const { return mVertexCount; }
12905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    unsigned int getSize() const { return mByteCount; }
130d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    unsigned int getIndexCount() const { return mIndexCount; }
131d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    void updateIndexCount(unsigned int newCount)  {
1329db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik        mIndexCount = std::min(newCount, mAllocatedIndexCount);
133d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
134d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    void updateVertexCount(unsigned int newCount)  {
1359db58c031f8ffa102a6d585cb585bed3bdb911a9Chris Craik        mVertexCount = std::min(newCount, mAllocatedVertexCount);
136d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    }
137117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    MeshFeatureFlags getMeshFeatureFlags() const { return mMeshFeatureFlags; }
138117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    void setMeshFeatureFlags(int flags) {
139117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik        mMeshFeatureFlags = static_cast<MeshFeatureFlags>(flags);
140117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    }
14105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
14205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    void setBounds(Rect bounds) { mBounds = bounds; }
14355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
14455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    template <class TYPE>
14555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    void createDegenerateSeparators(int allocSize) {
14655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        TYPE* end = (TYPE*)mBuffer + mVertexCount;
14755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
14855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            memcpy(degen, degen - 1, sizeof(TYPE));
14955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui            memcpy(degen + 1, degen + 2, sizeof(TYPE));
15055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        }
15155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
15255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
15355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghuiprivate:
15455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    template <class TYPE>
15555bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    static void cleanup(void* buffer) {
15655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui        delete[] (TYPE*)buffer;
15755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    }
15855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
15905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    Rect mBounds;
160d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
16155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    void* mBuffer;
162d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    void* mIndices;
163d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
16455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    unsigned int mVertexCount;
165d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    unsigned int mIndexCount;
166d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    unsigned int mAllocatedVertexCount;
167d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    unsigned int mAllocatedIndexCount;
16805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    unsigned int mByteCount;
169d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui
170117bdbcfa3e8306dad21e7e01fa71b00cdfa7265Chris Craik    MeshFeatureFlags mMeshFeatureFlags;
17155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
17255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    void* mReallocBuffer; // used for multi-allocation
17355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
17455bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui    void (*mCleanupMethod)(void*);
175d5e8ade498b41b42874273cbfa375aed7b4d6a08ztenghui    void (*mCleanupIndexMethod)(void*);
17655bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui};
17755bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
17855bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace uirenderer
17955bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui}; // namespace android
18055bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui
18155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui#endif // ANDROID_HWUI_VERTEX_BUFFER_H
182