xref: /aosp_15_r20/frameworks/base/libs/hwui/Mesh.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #ifndef MESH_H_
18*d57664e9SAndroid Build Coastguard Worker #define MESH_H_
19*d57664e9SAndroid Build Coastguard Worker 
20*d57664e9SAndroid Build Coastguard Worker #include <SkMesh.h>
21*d57664e9SAndroid Build Coastguard Worker #include <include/gpu/ganesh/GrDirectContext.h>
22*d57664e9SAndroid Build Coastguard Worker #include <include/gpu/ganesh/SkMeshGanesh.h>
23*d57664e9SAndroid Build Coastguard Worker #include <jni.h>
24*d57664e9SAndroid Build Coastguard Worker #include <log/log.h>
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker #include <utility>
27*d57664e9SAndroid Build Coastguard Worker 
28*d57664e9SAndroid Build Coastguard Worker namespace android {
29*d57664e9SAndroid Build Coastguard Worker 
30*d57664e9SAndroid Build Coastguard Worker class MeshUniformBuilder {
31*d57664e9SAndroid Build Coastguard Worker public:
32*d57664e9SAndroid Build Coastguard Worker     struct MeshUniform {
33*d57664e9SAndroid Build Coastguard Worker         template <typename T>
34*d57664e9SAndroid Build Coastguard Worker         std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
35*d57664e9SAndroid Build Coastguard Worker                 const T& val) {
36*d57664e9SAndroid Build Coastguard Worker             if (!fVar) {
37*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Assigning to missing variable");
38*d57664e9SAndroid Build Coastguard Worker             } else if (sizeof(val) != fVar->sizeInBytes()) {
39*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Incorrect value size");
40*d57664e9SAndroid Build Coastguard Worker             } else {
41*d57664e9SAndroid Build Coastguard Worker                 void* dst = reinterpret_cast<void*>(
42*d57664e9SAndroid Build Coastguard Worker                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
43*d57664e9SAndroid Build Coastguard Worker                 memcpy(dst, &val, sizeof(val));
44*d57664e9SAndroid Build Coastguard Worker             }
45*d57664e9SAndroid Build Coastguard Worker         }
46*d57664e9SAndroid Build Coastguard Worker 
47*d57664e9SAndroid Build Coastguard Worker         MeshUniform& operator=(const SkMatrix& val) {
48*d57664e9SAndroid Build Coastguard Worker             if (!fVar) {
49*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Assigning to missing variable");
50*d57664e9SAndroid Build Coastguard Worker             } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
51*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Incorrect value size");
52*d57664e9SAndroid Build Coastguard Worker             } else {
53*d57664e9SAndroid Build Coastguard Worker                 float* data = reinterpret_cast<float*>(
54*d57664e9SAndroid Build Coastguard Worker                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
55*d57664e9SAndroid Build Coastguard Worker                 data[0] = val.get(0);
56*d57664e9SAndroid Build Coastguard Worker                 data[1] = val.get(3);
57*d57664e9SAndroid Build Coastguard Worker                 data[2] = val.get(6);
58*d57664e9SAndroid Build Coastguard Worker                 data[3] = val.get(1);
59*d57664e9SAndroid Build Coastguard Worker                 data[4] = val.get(4);
60*d57664e9SAndroid Build Coastguard Worker                 data[5] = val.get(7);
61*d57664e9SAndroid Build Coastguard Worker                 data[6] = val.get(2);
62*d57664e9SAndroid Build Coastguard Worker                 data[7] = val.get(5);
63*d57664e9SAndroid Build Coastguard Worker                 data[8] = val.get(8);
64*d57664e9SAndroid Build Coastguard Worker             }
65*d57664e9SAndroid Build Coastguard Worker             return *this;
66*d57664e9SAndroid Build Coastguard Worker         }
67*d57664e9SAndroid Build Coastguard Worker 
68*d57664e9SAndroid Build Coastguard Worker         template <typename T>
setMeshUniform69*d57664e9SAndroid Build Coastguard Worker         bool set(const T val[], const int count) {
70*d57664e9SAndroid Build Coastguard Worker             static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
71*d57664e9SAndroid Build Coastguard Worker             if (!fVar) {
72*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Assigning to missing variable");
73*d57664e9SAndroid Build Coastguard Worker                 return false;
74*d57664e9SAndroid Build Coastguard Worker             } else if (sizeof(T) * count != fVar->sizeInBytes()) {
75*d57664e9SAndroid Build Coastguard Worker                 LOG_FATAL("Incorrect value size");
76*d57664e9SAndroid Build Coastguard Worker                 return false;
77*d57664e9SAndroid Build Coastguard Worker             } else {
78*d57664e9SAndroid Build Coastguard Worker                 void* dst = reinterpret_cast<void*>(
79*d57664e9SAndroid Build Coastguard Worker                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
80*d57664e9SAndroid Build Coastguard Worker                 memcpy(dst, val, sizeof(T) * count);
81*d57664e9SAndroid Build Coastguard Worker             }
82*d57664e9SAndroid Build Coastguard Worker             return true;
83*d57664e9SAndroid Build Coastguard Worker         }
84*d57664e9SAndroid Build Coastguard Worker 
85*d57664e9SAndroid Build Coastguard Worker         MeshUniformBuilder* fOwner;
86*d57664e9SAndroid Build Coastguard Worker         const SkRuntimeEffect::Uniform* fVar;
87*d57664e9SAndroid Build Coastguard Worker     };
uniform(std::string_view name)88*d57664e9SAndroid Build Coastguard Worker     MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
89*d57664e9SAndroid Build Coastguard Worker 
MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec)90*d57664e9SAndroid Build Coastguard Worker     explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
91*d57664e9SAndroid Build Coastguard Worker         fMeshSpec = sk_sp(meshSpec);
92*d57664e9SAndroid Build Coastguard Worker         fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
93*d57664e9SAndroid Build Coastguard Worker     }
94*d57664e9SAndroid Build Coastguard Worker 
95*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkData> fUniforms;
96*d57664e9SAndroid Build Coastguard Worker 
97*d57664e9SAndroid Build Coastguard Worker private:
writableUniformData()98*d57664e9SAndroid Build Coastguard Worker     void* writableUniformData() {
99*d57664e9SAndroid Build Coastguard Worker         if (!fUniforms->unique()) {
100*d57664e9SAndroid Build Coastguard Worker             fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
101*d57664e9SAndroid Build Coastguard Worker         }
102*d57664e9SAndroid Build Coastguard Worker         return fUniforms->writable_data();
103*d57664e9SAndroid Build Coastguard Worker     }
104*d57664e9SAndroid Build Coastguard Worker 
105*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkMeshSpecification> fMeshSpec;
106*d57664e9SAndroid Build Coastguard Worker };
107*d57664e9SAndroid Build Coastguard Worker 
108*d57664e9SAndroid Build Coastguard Worker // Storage for CPU and GPU copies of the vertex and index data of a mesh.
109*d57664e9SAndroid Build Coastguard Worker class MeshBufferData {
110*d57664e9SAndroid Build Coastguard Worker public:
MeshBufferData(std::vector<uint8_t> vertexData,int32_t vertexCount,int32_t vertexOffset,std::vector<uint8_t> indexData,int32_t indexCount,int32_t indexOffset)111*d57664e9SAndroid Build Coastguard Worker     MeshBufferData(std::vector<uint8_t> vertexData, int32_t vertexCount, int32_t vertexOffset,
112*d57664e9SAndroid Build Coastguard Worker                    std::vector<uint8_t> indexData, int32_t indexCount, int32_t indexOffset)
113*d57664e9SAndroid Build Coastguard Worker             : mVertexCount(vertexCount)
114*d57664e9SAndroid Build Coastguard Worker             , mVertexOffset(vertexOffset)
115*d57664e9SAndroid Build Coastguard Worker             , mIndexCount(indexCount)
116*d57664e9SAndroid Build Coastguard Worker             , mIndexOffset(indexOffset)
117*d57664e9SAndroid Build Coastguard Worker             , mVertexData(std::move(vertexData))
118*d57664e9SAndroid Build Coastguard Worker             , mIndexData(std::move(indexData)) {}
119*d57664e9SAndroid Build Coastguard Worker 
updateBuffers(GrDirectContext * context)120*d57664e9SAndroid Build Coastguard Worker     void updateBuffers(GrDirectContext* context) const {
121*d57664e9SAndroid Build Coastguard Worker         GrDirectContext::DirectContextID currentId = context == nullptr
122*d57664e9SAndroid Build Coastguard Worker                                                              ? GrDirectContext::DirectContextID()
123*d57664e9SAndroid Build Coastguard Worker                                                              : context->directContextID();
124*d57664e9SAndroid Build Coastguard Worker         if (currentId == mSkiaBuffers.fGenerationId && mSkiaBuffers.fVertexBuffer != nullptr) {
125*d57664e9SAndroid Build Coastguard Worker             // Nothing to update since the Android API does not support partial updates yet.
126*d57664e9SAndroid Build Coastguard Worker             return;
127*d57664e9SAndroid Build Coastguard Worker         }
128*d57664e9SAndroid Build Coastguard Worker 
129*d57664e9SAndroid Build Coastguard Worker         mSkiaBuffers.fVertexBuffer =
130*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__
131*d57664e9SAndroid Build Coastguard Worker                 SkMeshes::MakeVertexBuffer(context, mVertexData.data(), mVertexData.size());
132*d57664e9SAndroid Build Coastguard Worker #else
133*d57664e9SAndroid Build Coastguard Worker                 SkMeshes::MakeVertexBuffer(mVertexData.data(), mVertexData.size());
134*d57664e9SAndroid Build Coastguard Worker #endif
135*d57664e9SAndroid Build Coastguard Worker         if (mIndexCount != 0) {
136*d57664e9SAndroid Build Coastguard Worker             mSkiaBuffers.fIndexBuffer =
137*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__
138*d57664e9SAndroid Build Coastguard Worker                     SkMeshes::MakeIndexBuffer(context, mIndexData.data(), mIndexData.size());
139*d57664e9SAndroid Build Coastguard Worker #else
140*d57664e9SAndroid Build Coastguard Worker                     SkMeshes::MakeIndexBuffer(mIndexData.data(), mIndexData.size());
141*d57664e9SAndroid Build Coastguard Worker #endif
142*d57664e9SAndroid Build Coastguard Worker         }
143*d57664e9SAndroid Build Coastguard Worker         mSkiaBuffers.fGenerationId = currentId;
144*d57664e9SAndroid Build Coastguard Worker     }
145*d57664e9SAndroid Build Coastguard Worker 
vertexBuffer()146*d57664e9SAndroid Build Coastguard Worker     SkMesh::VertexBuffer* vertexBuffer() const { return mSkiaBuffers.fVertexBuffer.get(); }
147*d57664e9SAndroid Build Coastguard Worker 
refVertexBuffer()148*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkMesh::VertexBuffer> refVertexBuffer() const { return mSkiaBuffers.fVertexBuffer; }
vertexCount()149*d57664e9SAndroid Build Coastguard Worker     int32_t vertexCount() const { return mVertexCount; }
vertexOffset()150*d57664e9SAndroid Build Coastguard Worker     int32_t vertexOffset() const { return mVertexOffset; }
151*d57664e9SAndroid Build Coastguard Worker 
refIndexBuffer()152*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkMesh::IndexBuffer> refIndexBuffer() const { return mSkiaBuffers.fIndexBuffer; }
indexCount()153*d57664e9SAndroid Build Coastguard Worker     int32_t indexCount() const { return mIndexCount; }
indexOffset()154*d57664e9SAndroid Build Coastguard Worker     int32_t indexOffset() const { return mIndexOffset; }
155*d57664e9SAndroid Build Coastguard Worker 
vertexData()156*d57664e9SAndroid Build Coastguard Worker     const std::vector<uint8_t>& vertexData() const { return mVertexData; }
indexData()157*d57664e9SAndroid Build Coastguard Worker     const std::vector<uint8_t>& indexData() const { return mIndexData; }
158*d57664e9SAndroid Build Coastguard Worker 
159*d57664e9SAndroid Build Coastguard Worker private:
160*d57664e9SAndroid Build Coastguard Worker     struct CachedSkiaBuffers {
161*d57664e9SAndroid Build Coastguard Worker         sk_sp<SkMesh::VertexBuffer> fVertexBuffer;
162*d57664e9SAndroid Build Coastguard Worker         sk_sp<SkMesh::IndexBuffer> fIndexBuffer;
163*d57664e9SAndroid Build Coastguard Worker         GrDirectContext::DirectContextID fGenerationId = GrDirectContext::DirectContextID();
164*d57664e9SAndroid Build Coastguard Worker     };
165*d57664e9SAndroid Build Coastguard Worker 
166*d57664e9SAndroid Build Coastguard Worker     mutable CachedSkiaBuffers mSkiaBuffers;
167*d57664e9SAndroid Build Coastguard Worker     int32_t mVertexCount = 0;
168*d57664e9SAndroid Build Coastguard Worker     int32_t mVertexOffset = 0;
169*d57664e9SAndroid Build Coastguard Worker     int32_t mIndexCount = 0;
170*d57664e9SAndroid Build Coastguard Worker     int32_t mIndexOffset = 0;
171*d57664e9SAndroid Build Coastguard Worker     std::vector<uint8_t> mVertexData;
172*d57664e9SAndroid Build Coastguard Worker     std::vector<uint8_t> mIndexData;
173*d57664e9SAndroid Build Coastguard Worker };
174*d57664e9SAndroid Build Coastguard Worker 
175*d57664e9SAndroid Build Coastguard Worker class Mesh {
176*d57664e9SAndroid Build Coastguard Worker public:
177*d57664e9SAndroid Build Coastguard Worker     // A snapshot of the mesh for use by the render thread.
178*d57664e9SAndroid Build Coastguard Worker     //
179*d57664e9SAndroid Build Coastguard Worker     // After a snapshot is taken, future uniform changes to the original Mesh will not modify the
180*d57664e9SAndroid Build Coastguard Worker     // uniforms returned by makeSkMesh.
181*d57664e9SAndroid Build Coastguard Worker     class Snapshot {
182*d57664e9SAndroid Build Coastguard Worker     public:
183*d57664e9SAndroid Build Coastguard Worker         Snapshot() = delete;
184*d57664e9SAndroid Build Coastguard Worker         Snapshot(const Snapshot&) = default;
185*d57664e9SAndroid Build Coastguard Worker         Snapshot(Snapshot&&) = default;
186*d57664e9SAndroid Build Coastguard Worker         Snapshot& operator=(const Snapshot&) = default;
187*d57664e9SAndroid Build Coastguard Worker         Snapshot& operator=(Snapshot&&) = default;
188*d57664e9SAndroid Build Coastguard Worker         ~Snapshot() = default;
189*d57664e9SAndroid Build Coastguard Worker 
getSkMesh()190*d57664e9SAndroid Build Coastguard Worker         const SkMesh& getSkMesh() const {
191*d57664e9SAndroid Build Coastguard Worker             SkMesh::VertexBuffer* vertexBuffer = mBufferData->vertexBuffer();
192*d57664e9SAndroid Build Coastguard Worker             LOG_FATAL_IF(vertexBuffer == nullptr,
193*d57664e9SAndroid Build Coastguard Worker                          "Attempt to obtain SkMesh when vertexBuffer has not been created, did you "
194*d57664e9SAndroid Build Coastguard Worker                          "forget to call MeshBufferData::updateBuffers with a GrDirectContext?");
195*d57664e9SAndroid Build Coastguard Worker             if (vertexBuffer != mMesh.vertexBuffer()) mMesh = makeSkMesh();
196*d57664e9SAndroid Build Coastguard Worker             return mMesh;
197*d57664e9SAndroid Build Coastguard Worker         }
198*d57664e9SAndroid Build Coastguard Worker 
199*d57664e9SAndroid Build Coastguard Worker     private:
200*d57664e9SAndroid Build Coastguard Worker         friend class Mesh;
201*d57664e9SAndroid Build Coastguard Worker 
Snapshot(sk_sp<SkMeshSpecification> meshSpec,SkMesh::Mode mode,std::shared_ptr<const MeshBufferData> bufferData,sk_sp<const SkData> uniforms,const SkRect & bounds)202*d57664e9SAndroid Build Coastguard Worker         Snapshot(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode,
203*d57664e9SAndroid Build Coastguard Worker                  std::shared_ptr<const MeshBufferData> bufferData, sk_sp<const SkData> uniforms,
204*d57664e9SAndroid Build Coastguard Worker                  const SkRect& bounds)
205*d57664e9SAndroid Build Coastguard Worker                 : mMeshSpec(std::move(meshSpec))
206*d57664e9SAndroid Build Coastguard Worker                 , mMode(mode)
207*d57664e9SAndroid Build Coastguard Worker                 , mBufferData(std::move(bufferData))
208*d57664e9SAndroid Build Coastguard Worker                 , mUniforms(std::move(uniforms))
209*d57664e9SAndroid Build Coastguard Worker                 , mBounds(bounds) {}
210*d57664e9SAndroid Build Coastguard Worker 
makeSkMesh()211*d57664e9SAndroid Build Coastguard Worker         SkMesh makeSkMesh() const {
212*d57664e9SAndroid Build Coastguard Worker             const MeshBufferData& d = *mBufferData;
213*d57664e9SAndroid Build Coastguard Worker             if (d.indexCount() != 0) {
214*d57664e9SAndroid Build Coastguard Worker                 return SkMesh::MakeIndexed(mMeshSpec, mMode, d.refVertexBuffer(), d.vertexCount(),
215*d57664e9SAndroid Build Coastguard Worker                                            d.vertexOffset(), d.refIndexBuffer(), d.indexCount(),
216*d57664e9SAndroid Build Coastguard Worker                                            d.indexOffset(), mUniforms,
217*d57664e9SAndroid Build Coastguard Worker                                            SkSpan<SkRuntimeEffect::ChildPtr>(), mBounds)
218*d57664e9SAndroid Build Coastguard Worker                         .mesh;
219*d57664e9SAndroid Build Coastguard Worker             }
220*d57664e9SAndroid Build Coastguard Worker             return SkMesh::Make(mMeshSpec, mMode, d.refVertexBuffer(), d.vertexCount(),
221*d57664e9SAndroid Build Coastguard Worker                                 d.vertexOffset(), mUniforms, SkSpan<SkRuntimeEffect::ChildPtr>(),
222*d57664e9SAndroid Build Coastguard Worker                                 mBounds)
223*d57664e9SAndroid Build Coastguard Worker                     .mesh;
224*d57664e9SAndroid Build Coastguard Worker         }
225*d57664e9SAndroid Build Coastguard Worker 
226*d57664e9SAndroid Build Coastguard Worker         mutable SkMesh mMesh;
227*d57664e9SAndroid Build Coastguard Worker         sk_sp<SkMeshSpecification> mMeshSpec;
228*d57664e9SAndroid Build Coastguard Worker         SkMesh::Mode mMode;
229*d57664e9SAndroid Build Coastguard Worker         std::shared_ptr<const MeshBufferData> mBufferData;
230*d57664e9SAndroid Build Coastguard Worker         sk_sp<const SkData> mUniforms;
231*d57664e9SAndroid Build Coastguard Worker         SkRect mBounds;
232*d57664e9SAndroid Build Coastguard Worker     };
233*d57664e9SAndroid Build Coastguard Worker 
Mesh(sk_sp<SkMeshSpecification> meshSpec,SkMesh::Mode mode,std::vector<uint8_t> vertexData,int32_t vertexCount,int32_t vertexOffset,const SkRect & bounds)234*d57664e9SAndroid Build Coastguard Worker     Mesh(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode, std::vector<uint8_t> vertexData,
235*d57664e9SAndroid Build Coastguard Worker          int32_t vertexCount, int32_t vertexOffset, const SkRect& bounds)
236*d57664e9SAndroid Build Coastguard Worker             : Mesh(std::move(meshSpec), mode, std::move(vertexData), vertexCount, vertexOffset,
237*d57664e9SAndroid Build Coastguard Worker                    /* indexData = */ {}, /* indexCount = */ 0, /* indexOffset = */ 0, bounds) {}
238*d57664e9SAndroid Build Coastguard Worker 
Mesh(sk_sp<SkMeshSpecification> meshSpec,SkMesh::Mode mode,std::vector<uint8_t> vertexData,int32_t vertexCount,int32_t vertexOffset,std::vector<uint8_t> indexData,int32_t indexCount,int32_t indexOffset,const SkRect & bounds)239*d57664e9SAndroid Build Coastguard Worker     Mesh(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode, std::vector<uint8_t> vertexData,
240*d57664e9SAndroid Build Coastguard Worker          int32_t vertexCount, int32_t vertexOffset, std::vector<uint8_t> indexData,
241*d57664e9SAndroid Build Coastguard Worker          int32_t indexCount, int32_t indexOffset, const SkRect& bounds)
242*d57664e9SAndroid Build Coastguard Worker             : mMeshSpec(std::move(meshSpec))
243*d57664e9SAndroid Build Coastguard Worker             , mMode(mode)
244*d57664e9SAndroid Build Coastguard Worker             , mBufferData(std::make_shared<MeshBufferData>(std::move(vertexData), vertexCount,
245*d57664e9SAndroid Build Coastguard Worker                                                            vertexOffset, std::move(indexData),
246*d57664e9SAndroid Build Coastguard Worker                                                            indexCount, indexOffset))
247*d57664e9SAndroid Build Coastguard Worker             , mUniformBuilder(mMeshSpec)
248*d57664e9SAndroid Build Coastguard Worker             , mBounds(bounds) {}
249*d57664e9SAndroid Build Coastguard Worker 
250*d57664e9SAndroid Build Coastguard Worker     Mesh(Mesh&&) = default;
251*d57664e9SAndroid Build Coastguard Worker 
252*d57664e9SAndroid Build Coastguard Worker     Mesh& operator=(Mesh&&) = default;
253*d57664e9SAndroid Build Coastguard Worker 
254*d57664e9SAndroid Build Coastguard Worker     [[nodiscard]] std::tuple<bool, SkString> validate();
255*d57664e9SAndroid Build Coastguard Worker 
refBufferData()256*d57664e9SAndroid Build Coastguard Worker     std::shared_ptr<const MeshBufferData> refBufferData() const { return mBufferData; }
257*d57664e9SAndroid Build Coastguard Worker 
takeSnapshot()258*d57664e9SAndroid Build Coastguard Worker     Snapshot takeSnapshot() const {
259*d57664e9SAndroid Build Coastguard Worker         return Snapshot(mMeshSpec, mMode, mBufferData, mUniformBuilder.fUniforms, mBounds);
260*d57664e9SAndroid Build Coastguard Worker     }
261*d57664e9SAndroid Build Coastguard Worker 
uniformBuilder()262*d57664e9SAndroid Build Coastguard Worker     MeshUniformBuilder* uniformBuilder() { return &mUniformBuilder; }
263*d57664e9SAndroid Build Coastguard Worker 
264*d57664e9SAndroid Build Coastguard Worker private:
265*d57664e9SAndroid Build Coastguard Worker     sk_sp<SkMeshSpecification> mMeshSpec;
266*d57664e9SAndroid Build Coastguard Worker     SkMesh::Mode mMode;
267*d57664e9SAndroid Build Coastguard Worker     std::shared_ptr<MeshBufferData> mBufferData;
268*d57664e9SAndroid Build Coastguard Worker     MeshUniformBuilder mUniformBuilder;
269*d57664e9SAndroid Build Coastguard Worker     SkRect mBounds;
270*d57664e9SAndroid Build Coastguard Worker };
271*d57664e9SAndroid Build Coastguard Worker 
272*d57664e9SAndroid Build Coastguard Worker }  // namespace android
273*d57664e9SAndroid Build Coastguard Worker 
274*d57664e9SAndroid Build Coastguard Worker #endif  // MESH_H_
275