• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 MESH_H_
18 #define MESH_H_
19 
20 #include <GrDirectContext.h>
21 #include <SkMesh.h>
22 #include <jni.h>
23 #include <log/log.h>
24 
25 #include <utility>
26 
27 class MeshUniformBuilder {
28 public:
29     struct MeshUniform {
30         template <typename T>
31         std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
32                 const T& val) {
33             if (!fVar) {
34                 LOG_FATAL("Assigning to missing variable");
35             } else if (sizeof(val) != fVar->sizeInBytes()) {
36                 LOG_FATAL("Incorrect value size");
37             } else {
38                 void* dst = reinterpret_cast<void*>(
39                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
40                 memcpy(dst, &val, sizeof(val));
41             }
42         }
43 
44         MeshUniform& operator=(const SkMatrix& val) {
45             if (!fVar) {
46                 LOG_FATAL("Assigning to missing variable");
47             } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
48                 LOG_FATAL("Incorrect value size");
49             } else {
50                 float* data = reinterpret_cast<float*>(
51                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
52                 data[0] = val.get(0);
53                 data[1] = val.get(3);
54                 data[2] = val.get(6);
55                 data[3] = val.get(1);
56                 data[4] = val.get(4);
57                 data[5] = val.get(7);
58                 data[6] = val.get(2);
59                 data[7] = val.get(5);
60                 data[8] = val.get(8);
61             }
62             return *this;
63         }
64 
65         template <typename T>
setMeshUniform66         bool set(const T val[], const int count) {
67             static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
68             if (!fVar) {
69                 LOG_FATAL("Assigning to missing variable");
70                 return false;
71             } else if (sizeof(T) * count != fVar->sizeInBytes()) {
72                 LOG_FATAL("Incorrect value size");
73                 return false;
74             } else {
75                 void* dst = reinterpret_cast<void*>(
76                         reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
77                 memcpy(dst, val, sizeof(T) * count);
78             }
79             return true;
80         }
81 
82         MeshUniformBuilder* fOwner;
83         const SkRuntimeEffect::Uniform* fVar;
84     };
uniform(std::string_view name)85     MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
86 
MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec)87     explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
88         fMeshSpec = sk_sp(meshSpec);
89         fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
90     }
91 
92     sk_sp<SkData> fUniforms;
93 
94 private:
writableUniformData()95     void* writableUniformData() {
96         if (!fUniforms->unique()) {
97             fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
98         }
99         return fUniforms->writable_data();
100     }
101 
102     sk_sp<SkMeshSpecification> fMeshSpec;
103 };
104 
105 class Mesh {
106 public:
Mesh(const sk_sp<SkMeshSpecification> & meshSpec,int mode,std::vector<uint8_t> && vertexBufferData,jint vertexCount,jint vertexOffset,std::unique_ptr<MeshUniformBuilder> builder,const SkRect & bounds)107     Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
108          std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
109          std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
110             : mMeshSpec(meshSpec)
111             , mMode(mode)
112             , mVertexBufferData(std::move(vertexBufferData))
113             , mVertexCount(vertexCount)
114             , mVertexOffset(vertexOffset)
115             , mBuilder(std::move(builder))
116             , mBounds(bounds) {}
117 
Mesh(const sk_sp<SkMeshSpecification> & meshSpec,int mode,std::vector<uint8_t> && vertexBufferData,jint vertexCount,jint vertexOffset,std::vector<uint8_t> && indexBuffer,jint indexCount,jint indexOffset,std::unique_ptr<MeshUniformBuilder> builder,const SkRect & bounds)118     Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode,
119          std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset,
120          std::vector<uint8_t>&& indexBuffer, jint indexCount, jint indexOffset,
121          std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
122             : mMeshSpec(meshSpec)
123             , mMode(mode)
124             , mVertexBufferData(std::move(vertexBufferData))
125             , mVertexCount(vertexCount)
126             , mVertexOffset(vertexOffset)
127             , mIndexBufferData(std::move(indexBuffer))
128             , mIndexCount(indexCount)
129             , mIndexOffset(indexOffset)
130             , mBuilder(std::move(builder))
131             , mBounds(bounds) {}
132 
133     Mesh(Mesh&&) = default;
134 
135     Mesh& operator=(Mesh&&) = default;
136 
137     [[nodiscard]] std::tuple<bool, SkString> validate();
138 
updateSkMesh(GrDirectContext * context)139     void updateSkMesh(GrDirectContext* context) const {
140         GrDirectContext::DirectContextID genId = GrDirectContext::DirectContextID();
141         if (context) {
142             genId = context->directContextID();
143         }
144 
145         if (mIsDirty || genId != mGenerationId) {
146             auto vb = SkMesh::MakeVertexBuffer(
147                     context, reinterpret_cast<const void*>(mVertexBufferData.data()),
148                     mVertexBufferData.size());
149             auto meshMode = SkMesh::Mode(mMode);
150             if (!mIndexBufferData.empty()) {
151                 auto ib = SkMesh::MakeIndexBuffer(
152                         context, reinterpret_cast<const void*>(mIndexBufferData.data()),
153                         mIndexBufferData.size());
154                 mMesh = SkMesh::MakeIndexed(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
155                                             ib, mIndexCount, mIndexOffset, mBuilder->fUniforms,
156                                             mBounds)
157                                 .mesh;
158             } else {
159                 mMesh = SkMesh::Make(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
160                                      mBuilder->fUniforms, mBounds)
161                                 .mesh;
162             }
163             mIsDirty = false;
164             mGenerationId = genId;
165         }
166     }
167 
getSkMesh()168     SkMesh& getSkMesh() const {
169         LOG_FATAL_IF(mIsDirty,
170                      "Attempt to obtain SkMesh when Mesh is dirty, did you "
171                      "forget to call updateSkMesh with a GrDirectContext? "
172                      "Defensively creating a CPU mesh");
173         return mMesh;
174     }
175 
markDirty()176     void markDirty() { mIsDirty = true; }
177 
uniformBuilder()178     MeshUniformBuilder* uniformBuilder() { return mBuilder.get(); }
179 
180 private:
181     sk_sp<SkMeshSpecification> mMeshSpec;
182     int mMode = 0;
183 
184     std::vector<uint8_t> mVertexBufferData;
185     size_t mVertexCount = 0;
186     size_t mVertexOffset = 0;
187 
188     std::vector<uint8_t> mIndexBufferData;
189     size_t mIndexCount = 0;
190     size_t mIndexOffset = 0;
191 
192     std::unique_ptr<MeshUniformBuilder> mBuilder;
193     SkRect mBounds{};
194 
195     mutable SkMesh mMesh{};
196     mutable bool mIsDirty = true;
197     mutable GrDirectContext::DirectContextID mGenerationId = GrDirectContext::DirectContextID();
198 };
199 #endif  // MESH_H_
200