Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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;
239 const SkAlphaType fAlphaType;
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 */
406SK_API sk_sp<SkMesh::IndexBuffer> MakeIndexBuffer(const void* data, size_t size);
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 */
421SK_API sk_sp<SkMesh::VertexBuffer> MakeVertexBuffer(const void*, size_t size);
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
#define SK_API
Definition SkAPI.h:35
SkAlphaType
Definition SkAlphaType.h:26
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static constexpr uint16_t kHalf
Type::kYUV Type::kRGBA() int(0.7 *637)
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
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
sk_sp< SkMeshSpecification > refSpec() const
Definition SkMesh.h:347
const char * name
Definition fuchsia.cc:50
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
Point 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
SkBlendMode fMode
Definition xfermodes.cpp:52