diff options
Diffstat (limited to 'src/deps/skia/include/core/SkCustomMesh.h')
-rw-r--r-- | src/deps/skia/include/core/SkCustomMesh.h | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/deps/skia/include/core/SkCustomMesh.h b/src/deps/skia/include/core/SkCustomMesh.h new file mode 100644 index 000000000..f9bddf338 --- /dev/null +++ b/src/deps/skia/include/core/SkCustomMesh.h @@ -0,0 +1,202 @@ +/* + * Copyright 2021 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkCustomMesh_DEFINED +#define SkCustomMesh_DEFINED + +#include "include/core/SkTypes.h" + +#ifdef SK_ENABLE_SKSL +#include "include/core/SkColorSpace.h" +#include "include/core/SkImageInfo.h" +#include "include/core/SkRect.h" +#include "include/core/SkRefCnt.h" +#include "include/core/SkSpan.h" +#include "include/core/SkString.h" + +#include <vector> + +namespace SkSL { struct Program; } + +/** + * A specification for custom meshes. Specifies the vertex buffer attributes and stride, the + * vertex program that produces a user-defined set of varyings, a fragment program that ingests + * the interpolated varyings and produces local coordinates and optionally a color. + * + * The signature of the vertex program must be: + * float2 main(Attributes, out Varyings) + * where the return value is a local position that will be transformed by SkCanvas's matrix. + * + * The signature of the fragment program must be either: + * (float2|void) main(Varyings) + * or + * (float2|void) main(Varyings, out (half4|float4) color) + * + * where the return value is the local coordinates that will be used to access SkShader. If the + * return type is void then the interpolated position from vertex shader return is used as the local + * coordinate. If the color variant is used it will be blended with SkShader (or SkPaint color in + * absence of a shader) using the SkBlender provided to the SkCanvas draw call. + */ +class SkCustomMeshSpecification : public SkNVRefCnt<SkCustomMeshSpecification> { +public: + /** These values are enforced when creating a specification. */ + static constexpr size_t kMaxStride = 1024; + static constexpr size_t kMaxAttributes = 8; + static constexpr size_t kStrideAlignment = 4; + static constexpr size_t kOffsetAlignment = 4; + static constexpr size_t kMaxVaryings = 6; + + struct Attribute { + enum class Type : uint32_t { // CPU representation Shader Type + kFloat, // float float + kFloat2, // two floats float2 + kFloat3, // three floats float3 + kFloat4, // four floats float4 + kUByte4_unorm, // four bytes half4 + + kLast = kUByte4_unorm + }; + Type type; + size_t offset; + SkString name; + }; + + struct Varying { + enum class Type : uint32_t { + kFloat, // "float" + kFloat2, // "float2" + kFloat3, // "float3" + kFloat4, // "float4" + kHalf, // "half" + kHalf2, // "half2" + kHalf3, // "half3" + kHalf4, // "half4" + + kLast = kHalf4 + }; + Type type; + SkString name; + }; + + ~SkCustomMeshSpecification(); + + struct Result { + sk_sp<SkCustomMeshSpecification> specification; + SkString error; + }; + + /** + * If successful the return is a specification and an empty error string. Otherwise, it is a + * null specification a non-empty error string. + * + * @param attributes The vertex attributes that will be consumed by 'vs'. Attributes need + * not be tightly packed but attribute offsets must be aligned to + * kOffsetAlignment and offset + size may not be greater than + * 'vertexStride'. At least one attribute is required. + * @param vertexStride The offset between successive attribute values. This must be aligned to + * kStrideAlignment. + * @param varyings The varyings that will be written by 'vs' and read by 'fs'. This may + * be empty. + * @param vs The vertex shader code that computes a vertex position and the varyings + * from the attributes. + * @param fs The fragment code that computes a local coordinate and optionally a + * color from the varyings. The local coordinate is used to sample + * SkShader. + * @param cs The colorspace of the color produced by 'fs'. Ignored if 'fs's main() + * function does not have a color out param. + * @param at The alpha type of the color produced by 'fs'. Ignored if 'fs's main() + * function does not have a color out param. Cannot be kUnknown. + */ + static Result Make(SkSpan<const Attribute> attributes, + size_t vertexStride, + SkSpan<const Varying> varyings, + const SkString& vs, + const SkString& fs, + sk_sp<SkColorSpace> cs = SkColorSpace::MakeSRGB(), + SkAlphaType at = kPremul_SkAlphaType); + + SkSpan<const Attribute> attributes() const { return SkMakeSpan(fAttributes); } + + size_t stride() const { return fStride; } + +private: + friend struct SkCustomMeshSpecificationPriv; + + enum class ColorType { + kNone, + kHalf4, + kFloat4, + }; + + static Result MakeFromSourceWithStructs(SkSpan<const Attribute> attributes, + size_t stride, + SkSpan<const Varying> varyings, + const SkString& vs, + const SkString& fs, + sk_sp<SkColorSpace> cs, + SkAlphaType at); + + SkCustomMeshSpecification(SkSpan<const Attribute>, + size_t, + SkSpan<const Varying>, + std::unique_ptr<SkSL::Program>, + std::unique_ptr<SkSL::Program>, + ColorType, + bool hasLocalCoords, + sk_sp<SkColorSpace>, + SkAlphaType); + + SkCustomMeshSpecification(const SkCustomMeshSpecification&) = delete; + SkCustomMeshSpecification(SkCustomMeshSpecification&&) = delete; + + SkCustomMeshSpecification& operator=(const SkCustomMeshSpecification&) = delete; + SkCustomMeshSpecification& operator=(SkCustomMeshSpecification&&) = delete; + + const std::vector<Attribute> fAttributes; + const std::vector<Varying> fVaryings; + std::unique_ptr<SkSL::Program> fVS; + std::unique_ptr<SkSL::Program> fFS; + size_t fStride; + uint32_t fHash; + ColorType fColorType; + bool fHasLocalCoords; + sk_sp<SkColorSpace> fColorSpace; + SkAlphaType fAlphaType; +}; + +/** + * This is a placeholder object. We will want something that allows the client to incrementally + * update the mesh that can be synchronized with the GPU backend without requiring extra copies. + * + * A buffer of vertices, a topology, optionally indices, and a compatible SkCustomMeshSpecification. + * The data in 'vb' is expected to contain the attributes described in 'spec' for 'vcount' vertices. + * The size of the buffer must be at least spec->stride()*vcount (even if vertex attributes contains + * pad at the end of the stride). If 'bounds' does not contain all points output by 'spec''s vertex + * program when applied to the vertices in 'vb' a draw of the custom mesh produces undefined + * results. + * + * If indices is null then then 'icount' must be <= 0. 'vcount' vertices will be selected from 'vb' + * to create the topology indicated by 'mode'. + * + * If indices is not null then icount must be >= 3. 'vb' will be indexed by 'icount' successive + * values in 'indices' to create the topology indicated by 'mode'. The values in 'indices' must be + * less than 'vcount' + */ +struct SkCustomMesh { + enum class Mode { kTriangles, kTriangleStrip }; + sk_sp<SkCustomMeshSpecification> spec; + Mode mode = Mode::kTriangles; + SkRect bounds = SkRect::MakeEmpty(); + const void* vb = nullptr; + int vcount = 0; + const uint16_t* indices = nullptr; + int icount = 0; +}; + +#endif // SK_ENABLE_SKSL + +#endif |