Flutter Engine
The Flutter Engine
SkMesh.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkMesh_DEFINED
9#define SkMesh_DEFINED
10
11#include "include/core/SkData.h"
12#include "include/core/SkRect.h"
14#include "include/core/SkSpan.h"
19
20#include <cstddef>
21#include <cstdint>
22#include <memory>
23#include <string_view>
24#include <tuple>
25#include <vector>
26
27class GrDirectContext;
28class SkColorSpace;
29enum SkAlphaType : int;
30
31namespace SkSL { struct Program; }
32
33/**
34 * A specification for custom meshes. Specifies the vertex buffer attributes and stride, the
35 * vertex program that produces a user-defined set of varyings, and a fragment program that ingests
36 * the interpolated varyings and produces local coordinates for shading and optionally a color.
37 *
38 * The varyings must include a float2 named "position". If the passed varyings does not
39 * contain such a varying then one is implicitly added to the final specification and the SkSL
40 * Varyings struct described below. It is an error to have a varying named "position" that has a
41 * type other than float2.
42 *
43 * The provided attributes and varyings are used to create Attributes and Varyings structs in SkSL
44 * that are used by the shaders. Each attribute from the Attribute span becomes a member of the
45 * SkSL Attributes struct and likewise for the varyings.
46 *
47 * The signature of the vertex program must be:
48 * Varyings main(const Attributes).
49 *
50 * The signature of the fragment program must be either:
51 * float2 main(const Varyings)
52 * or
53 * float2 main(const Varyings, out (half4|float4) color)
54 *
55 * where the return value is the local coordinates that will be used to access SkShader. If the
56 * color variant is used, the returned color will be blended with SkPaint's SkShader (or SkPaint
57 * color in absence of a SkShader) using the SkBlender passed to SkCanvas drawMesh(). To use
58 * interpolated local space positions as the shader coordinates, equivalent to how SkPaths are
59 * shaded, return the position field from the Varying struct as the coordinates.
60 *
61 * The vertex and fragment programs may both contain uniforms. Uniforms with the same name are
62 * assumed to be shared between stages. It is an error to specify uniforms in the vertex and
63 * fragment program with the same name but different types, dimensionality, or layouts.
64 */
65class SK_API SkMeshSpecification : public SkNVRefCnt<SkMeshSpecification> {
66public:
67 /** These values are enforced when creating a specification. */
68 static constexpr size_t kMaxStride = 1024;
69 static constexpr size_t kMaxAttributes = 8;
70 static constexpr size_t kStrideAlignment = 4;
71 static constexpr size_t kOffsetAlignment = 4;
72 static constexpr size_t kMaxVaryings = 6;
73
74 struct Attribute {
75 enum class Type : uint32_t { // CPU representation Shader Type
76 kFloat, // float float
77 kFloat2, // two floats float2
78 kFloat3, // three floats float3
79 kFloat4, // four floats float4
80 kUByte4_unorm, // four bytes half4
81
82 kLast = kUByte4_unorm
83 };
85 size_t offset;
87 };
88
89 struct Varying {
90 enum class Type : uint32_t {
91 kFloat, // "float"
92 kFloat2, // "float2"
93 kFloat3, // "float3"
94 kFloat4, // "float4"
95 kHalf, // "half"
96 kHalf2, // "half2"
97 kHalf3, // "half3"
98 kHalf4, // "half4"
99
100 kLast = kHalf4
101 };
104 };
105
108
110
111 struct Result {
114 };
115
116 /**
117 * If successful the return is a specification and an empty error string. Otherwise, it is a
118 * null specification a non-empty error string.
119 *
120 * @param attributes The vertex attributes that will be consumed by 'vs'. Attributes need
121 * not be tightly packed but attribute offsets must be aligned to
122 * kOffsetAlignment and offset + size may not be greater than
123 * 'vertexStride'. At least one attribute is required.
124 * @param vertexStride The offset between successive attribute values. This must be aligned to
125 * kStrideAlignment.
126 * @param varyings The varyings that will be written by 'vs' and read by 'fs'. This may
127 * be empty.
128 * @param vs The vertex shader code that computes a vertex position and the varyings
129 * from the attributes.
130 * @param fs The fragment code that computes a local coordinate and optionally a
131 * color from the varyings. The local coordinate is used to sample
132 * SkShader.
133 * @param cs The colorspace of the color produced by 'fs'. Ignored if 'fs's main()
134 * function does not have a color out param.
135 * @param at The alpha type of the color produced by 'fs'. Ignored if 'fs's main()
136 * function does not have a color out param. Cannot be kUnknown.
137 */
138 static Result Make(SkSpan<const Attribute> attributes,
139 size_t vertexStride,
140 SkSpan<const Varying> varyings,
141 const SkString& vs,
142 const SkString& fs);
143 static Result Make(SkSpan<const Attribute> attributes,
144 size_t vertexStride,
145 SkSpan<const Varying> varyings,
146 const SkString& vs,
147 const SkString& fs,
149 static Result Make(SkSpan<const Attribute> attributes,
150 size_t vertexStride,
151 SkSpan<const Varying> varyings,
152 const SkString& vs,
153 const SkString& fs,
155 SkAlphaType at);
156
157 SkSpan<const Attribute> attributes() const { return SkSpan(fAttributes); }
158
159 /**
160 * Combined size of all 'uniform' variables. When creating a SkMesh with this specification
161 * provide an SkData of this size, containing values for all of those variables. Use uniforms()
162 * to get the offset of each uniform within the SkData.
163 */
164 size_t uniformSize() const;
165
166 /**
167 * Provides info about individual uniforms including the offset into an SkData where each
168 * uniform value should be placed.
169 */
170 SkSpan<const Uniform> uniforms() const { return SkSpan(fUniforms); }
171
172 /** Provides basic info about individual children: names, indices and runtime effect type. */
173 SkSpan<const Child> children() const { return SkSpan(fChildren); }
174
175 /** Returns a pointer to the named child's description, or nullptr if not found. */
176 const Child* findChild(std::string_view name) const;
177
178 /** Returns a pointer to the named uniform variable's description, or nullptr if not found. */
179 const Uniform* findUniform(std::string_view name) const;
180
181 /** Returns a pointer to the named attribute, or nullptr if not found. */
182 const Attribute* findAttribute(std::string_view name) const;
183
184 /** Returns a pointer to the named varying, or nullptr if not found. */
185 const Varying* findVarying(std::string_view name) const;
186
187 size_t stride() const { return fStride; }
188
189 SkColorSpace* colorSpace() const { return fColorSpace.get(); }
190
191private:
193
194 enum class ColorType {
195 kNone,
196 kHalf4,
197 kFloat4,
198 };
199
200 static Result MakeFromSourceWithStructs(SkSpan<const Attribute> attributes,
201 size_t stride,
202 SkSpan<const Varying> varyings,
203 const SkString& vs,
204 const SkString& fs,
206 SkAlphaType at);
207
209 size_t,
211 int passthroughLocalCoordsVaryingIndex,
212 uint32_t deadVaryingMask,
213 std::vector<Uniform> uniforms,
214 std::vector<Child> children,
215 std::unique_ptr<const SkSL::Program>,
216 std::unique_ptr<const SkSL::Program>,
217 ColorType,
220
223
224 SkMeshSpecification& operator=(const SkMeshSpecification&) = delete;
225 SkMeshSpecification& operator=(SkMeshSpecification&&) = delete;
226
227 const std::vector<Attribute> fAttributes;
228 const std::vector<Varying> fVaryings;
229 const std::vector<Uniform> fUniforms;
230 const std::vector<Child> fChildren;
231 const std::unique_ptr<const SkSL::Program> fVS;
232 const std::unique_ptr<const SkSL::Program> fFS;
233 const size_t fStride;
234 uint32_t fHash;
235 const int fPassthroughLocalCoordsVaryingIndex;
236 const uint32_t fDeadVaryingMask;
237 const ColorType fColorType;
238 const sk_sp<SkColorSpace> fColorSpace;
240};
241
242/**
243 * A vertex buffer, a topology, optionally an index buffer, and a compatible SkMeshSpecification.
244 *
245 * The data in the vertex buffer is expected to contain the attributes described by the spec
246 * for vertexCount vertices, beginning at vertexOffset. vertexOffset must be aligned to the
247 * SkMeshSpecification's vertex stride. The size of the buffer must be at least vertexOffset +
248 * spec->stride()*vertexCount (even if vertex attributes contains pad at the end of the stride). If
249 * the specified bounds do not contain all the points output by the spec's vertex program when
250 * applied to the vertices in the custom mesh, then the result is undefined.
251 *
252 * MakeIndexed may be used to create an indexed mesh. indexCount indices are read from the index
253 * buffer at the specified offset, which must be aligned to 2. The indices are always unsigned
254 * 16-bit integers. The index count must be at least 3.
255 *
256 * If Make() is used, the implicit index sequence is 0, 1, 2, 3, ... and vertexCount must be at
257 * least 3.
258 *
259 * Both Make() and MakeIndexed() take a SkData with the uniform values. See
260 * SkMeshSpecification::uniformSize() and SkMeshSpecification::uniforms() for sizing and packing
261 * uniforms into the SkData.
262 */
264public:
265 class IndexBuffer : public SkRefCnt {
266 public:
267 virtual size_t size() const = 0;
268
269 /**
270 * Modifies the data in the IndexBuffer by copying size bytes from data into the buffer
271 * at offset. Fails if offset + size > this->size() or if either offset or size is not
272 * aligned to 4 bytes. The GrDirectContext* must match that used to create the buffer. We
273 * take it as a parameter to emphasize that the context must be used to update the data and
274 * thus the context must be valid for the current thread.
275 */
276 bool update(GrDirectContext*, const void* data, size_t offset, size_t size);
277
278 private:
279 virtual bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) = 0;
280 };
281
282 class VertexBuffer : public SkRefCnt {
283 public:
284 virtual size_t size() const = 0;
285
286 /**
287 * Modifies the data in the IndexBuffer by copying size bytes from data into the buffer
288 * at offset. Fails if offset + size > this->size() or if either offset or size is not
289 * aligned to 4 bytes. The GrDirectContext* must match that used to create the buffer. We
290 * take it as a parameter to emphasize that the context must be used to update the data and
291 * thus the context must be valid for the current thread.
292 */
293 bool update(GrDirectContext*, const void* data, size_t offset, size_t size);
294
295 private:
296 virtual bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) = 0;
297 };
298
301
302 SkMesh(const SkMesh&);
304
307
309
310 struct Result;
311
313
314 /**
315 * Creates a non-indexed SkMesh. The returned SkMesh can be tested for validity using
316 * SkMesh::isValid(). An invalid mesh simply fails to draws if passed to SkCanvas::drawMesh().
317 * If the mesh is invalid the returned string give contain the reason for the failure (e.g. the
318 * vertex buffer was null or uniform data too small).
319 */
321 Mode,
323 size_t vertexCount,
324 size_t vertexOffset,
325 sk_sp<const SkData> uniforms,
326 SkSpan<ChildPtr> children,
327 const SkRect& bounds);
328
329 /**
330 * Creates an indexed SkMesh. The returned SkMesh can be tested for validity using
331 * SkMesh::isValid(). A invalid mesh simply fails to draw if passed to SkCanvas::drawMesh().
332 * If the mesh is invalid the returned string give contain the reason for the failure (e.g. the
333 * index buffer was null or uniform data too small).
334 */
335 static Result MakeIndexed(sk_sp<SkMeshSpecification>,
336 Mode,
338 size_t vertexCount,
339 size_t vertexOffset,
341 size_t indexCount,
342 size_t indexOffset,
343 sk_sp<const SkData> uniforms,
344 SkSpan<ChildPtr> children,
345 const SkRect& bounds);
346
347 sk_sp<SkMeshSpecification> refSpec() const { return fSpec; }
348 SkMeshSpecification* spec() const { return fSpec.get(); }
349
350 Mode mode() const { return fMode; }
351
352 sk_sp<VertexBuffer> refVertexBuffer() const { return fVB; }
353 VertexBuffer* vertexBuffer() const { return fVB.get(); }
354
355 size_t vertexOffset() const { return fVOffset; }
356 size_t vertexCount() const { return fVCount; }
357
358 sk_sp<IndexBuffer> refIndexBuffer() const { return fIB; }
359 IndexBuffer* indexBuffer() const { return fIB.get(); }
360
361 size_t indexOffset() const { return fIOffset; }
362 size_t indexCount() const { return fICount; }
363
364 sk_sp<const SkData> refUniforms() const { return fUniforms; }
365 const SkData* uniforms() const { return fUniforms.get(); }
366
367 SkSpan<const ChildPtr> children() const { return SkSpan(fChildren); }
368
369 SkRect bounds() const { return fBounds; }
370
371 bool isValid() const;
372
373private:
374 std::tuple<bool, SkString> validate() const;
375
377
380
381 sk_sp<const SkData> fUniforms;
383
384 size_t fVOffset = 0; // Must be a multiple of spec->stride()
385 size_t fVCount = 0;
386
387 size_t fIOffset = 0; // Must be a multiple of sizeof(uint16_t)
388 size_t fICount = 0;
389
390 Mode fMode = Mode::kTriangles;
391
393};
394
396
397namespace SkMeshes {
398/**
399 * Makes a CPU-backed index buffer to be used with SkMeshes.
400 *
401 * @param data The data used to populate the buffer, or nullptr to create a zero-
402 * initialized buffer.
403 * @param size Both the size of the data in 'data' and the size of the resulting
404 * buffer, in bytes.
405 */
407
408/**
409 * Makes a copy of an index buffer. The copy will be CPU-backed.
410 */
412
413/**
414 * Makes a CPU-backed vertex buffer to be used with SkMeshes.
415 *
416 * @param data The data used to populate the buffer, or nullptr to create a zero-
417 * initialized buffer.
418 * @param size Both the size of the data in 'data' and the size of the resulting
419 * buffer, in bytes.
420 */
422
423/**
424 * Makes a copy of a vertex buffer. The copy will be CPU-backed.
425 */
427} // namespace SkMeshes
428
429#endif
const SkRect fBounds
SkColorType fColorType
SkAlphaType fAlphaType
#define SK_API
Definition: SkAPI.h:35
SkAlphaType
Definition: SkAlphaType.h:26
SkMeshSpecification::Uniform Uniform
Definition: SkMesh.cpp:66
SkMeshSpecification::Child Child
Definition: SkMesh.cpp:67
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
Definition: SkData.h:25
SkSpan< const Uniform > uniforms() const
Definition: SkMesh.h:170
size_t stride() const
Definition: SkMesh.h:187
SkSpan< const Child > children() const
Definition: SkMesh.h:173
SkSpan< const Attribute > attributes() const
Definition: SkMesh.h:157
SkColorSpace * colorSpace() const
Definition: SkMesh.h:189
virtual size_t size() const =0
virtual bool onUpdate(GrDirectContext *, const void *data, size_t offset, size_t size)=0
virtual size_t size() const =0
virtual bool onUpdate(GrDirectContext *, const void *data, size_t offset, size_t size)=0
Definition: SkMesh.h:263
SkMesh & operator=(const SkMesh &)
SkSpan< const ChildPtr > children() const
Definition: SkMesh.h:367
VertexBuffer * vertexBuffer() const
Definition: SkMesh.h:353
SkMesh & operator=(SkMesh &&)
size_t vertexCount() const
Definition: SkMesh.h:356
sk_sp< IndexBuffer > refIndexBuffer() const
Definition: SkMesh.h:358
SkMesh(const SkMesh &)
SkMesh(SkMesh &&)
size_t vertexOffset() const
Definition: SkMesh.h:355
Mode mode() const
Definition: SkMesh.h:350
sk_sp< VertexBuffer > refVertexBuffer() const
Definition: SkMesh.h:352
IndexBuffer * indexBuffer() const
Definition: SkMesh.h:359
size_t indexCount() const
Definition: SkMesh.h:362
sk_sp< const SkData > refUniforms() const
Definition: SkMesh.h:364
SkRect bounds() const
Definition: SkMesh.h:369
size_t indexOffset() const
Definition: SkMesh.h:361
const SkData * uniforms() const
Definition: SkMesh.h:365
SkMeshSpecification * spec() const
Definition: SkMesh.h:348
Mode
Definition: SkMesh.h:308
sk_sp< SkMeshSpecification > refSpec() const
Definition: SkMesh.h:347
SK_API sk_sp< SkMesh::IndexBuffer > CopyIndexBuffer(const sk_sp< SkMesh::IndexBuffer > &)
Definition: SkMesh.cpp:893
SK_API sk_sp< SkMesh::IndexBuffer > MakeIndexBuffer(const void *data, size_t size)
Definition: SkMesh.cpp:889
SK_API sk_sp< SkMesh::VertexBuffer > MakeVertexBuffer(const void *, size_t size)
Definition: SkMesh.cpp:905
SK_API sk_sp< SkMesh::VertexBuffer > CopyVertexBuffer(const sk_sp< SkMesh::VertexBuffer > &)
Definition: SkMesh.cpp:909
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
Optional< SkRect > bounds
Definition: SkRecords.h:189
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: update.py:1
SeparatedVector2 offset
sk_sp< SkMeshSpecification > specification
Definition: SkMesh.h:112
SkString error
Definition: SkMesh.h:395
SkMesh mesh
Definition: SkMesh.h:395
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
SkBlendMode fMode
Definition: xfermodes.cpp:52