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 SkMeshPriv_DEFINED
9 #define SkMeshPriv_DEFINED
10
11 #include "include/core/SkData.h"
12 #include "include/core/SkMesh.h"
13 #include "src/core/SkSLTypeShared.h"
14
15 struct SkMeshSpecificationPriv {
16 using Varying = SkMeshSpecification::Varying;
17 using Attribute = SkMeshSpecification::Attribute;
18 using ColorType = SkMeshSpecification::ColorType;
19
VaryingsSkMeshSpecificationPriv20 static SkSpan<const Varying> Varyings(const SkMeshSpecification& spec) {
21 return SkSpan(spec.fVaryings);
22 }
23
VSSkMeshSpecificationPriv24 static const SkSL::Program* VS(const SkMeshSpecification& spec) { return spec.fVS.get(); }
FSSkMeshSpecificationPriv25 static const SkSL::Program* FS(const SkMeshSpecification& spec) { return spec.fFS.get(); }
26
HashSkMeshSpecificationPriv27 static int Hash(const SkMeshSpecification& spec) { return spec.fHash; }
28
GetColorTypeSkMeshSpecificationPriv29 static ColorType GetColorType(const SkMeshSpecification& spec) { return spec.fColorType; }
HasColorsSkMeshSpecificationPriv30 static bool HasColors(const SkMeshSpecification& spec) {
31 return GetColorType(spec) != ColorType::kNone;
32 }
33
ColorSpaceSkMeshSpecificationPriv34 static SkColorSpace* ColorSpace(const SkMeshSpecification& spec) {
35 return spec.fColorSpace.get();
36 }
37
AlphaTypeSkMeshSpecificationPriv38 static SkAlphaType AlphaType(const SkMeshSpecification& spec) { return spec.fAlphaType; }
39
VaryingTypeAsSLTypeSkMeshSpecificationPriv40 static SkSLType VaryingTypeAsSLType(Varying::Type type) {
41 switch (type) {
42 case Varying::Type::kFloat: return SkSLType::kFloat;
43 case Varying::Type::kFloat2: return SkSLType::kFloat2;
44 case Varying::Type::kFloat3: return SkSLType::kFloat3;
45 case Varying::Type::kFloat4: return SkSLType::kFloat4;
46 case Varying::Type::kHalf: return SkSLType::kHalf;
47 case Varying::Type::kHalf2: return SkSLType::kHalf2;
48 case Varying::Type::kHalf3: return SkSLType::kHalf3;
49 case Varying::Type::kHalf4: return SkSLType::kHalf4;
50 }
51 SkUNREACHABLE;
52 }
53
AttrTypeAsSLTypeSkMeshSpecificationPriv54 static SkSLType AttrTypeAsSLType(Attribute::Type type) {
55 switch (type) {
56 case Attribute::Type::kFloat: return SkSLType::kFloat;
57 case Attribute::Type::kFloat2: return SkSLType::kFloat2;
58 case Attribute::Type::kFloat3: return SkSLType::kFloat3;
59 case Attribute::Type::kFloat4: return SkSLType::kFloat4;
60 case Attribute::Type::kUByte4_unorm: return SkSLType::kHalf4;
61 }
62 SkUNREACHABLE;
63 }
64
PassthroughLocalCoordsVaryingIndexSkMeshSpecificationPriv65 static int PassthroughLocalCoordsVaryingIndex(const SkMeshSpecification& spec) {
66 return spec.fPassthroughLocalCoordsVaryingIndex;
67 }
68
69 /**
70 * A varying is dead if it is never referenced OR it is only referenced as a passthrough for
71 * local coordinates. In the latter case, its index will returned as
72 * PassthroughLocalCoordsVaryingIndex. Our analysis is not very sophisticated so this is
73 * determined conservatively.
74 */
VaryingIsDeadSkMeshSpecificationPriv75 static bool VaryingIsDead(const SkMeshSpecification& spec, int v) {
76 SkASSERT(v >= 0 && SkToSizeT(v) < spec.fVaryings.size());
77 return (1 << v) & spec.fDeadVaryingMask;
78 }
79 };
80
81 namespace SkMeshPriv {
82 class Buffer {
83 public:
84 virtual ~Buffer() = 0;
85
86 Buffer() = default;
87 Buffer(const Buffer&) = delete;
88
89 Buffer& operator=(const Buffer&) = delete;
90
peek()91 virtual const void* peek() const { return nullptr; }
92
isGaneshBacked()93 virtual bool isGaneshBacked() const { return false; }
94 };
95
96 class IB : public Buffer, public SkMesh::IndexBuffer {};
97 class VB : public Buffer, public SkMesh::VertexBuffer {};
98
99 template <typename Base> class CpuBuffer final : public Base {
100 public:
101 ~CpuBuffer() override = default;
102
103 static sk_sp<Base> Make(const void* data, size_t size);
104
peek()105 const void* peek() const override { return fData->data(); }
106
size()107 size_t size() const override { return fData->size(); }
108
109 private:
CpuBuffer(sk_sp<SkData> data)110 CpuBuffer(sk_sp<SkData> data) : fData(std::move(data)) {}
111
112 bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) override;
113
114 sk_sp<SkData> fData;
115 };
116
117 using CpuIndexBuffer = CpuBuffer<IB>;
118 using CpuVertexBuffer = CpuBuffer<VB>;
119 } // namespace SkMeshPriv
120
121 inline SkMeshPriv::Buffer::~Buffer() = default;
122
Make(const void * data,size_t size)123 template <typename Base> sk_sp<Base> SkMeshPriv::CpuBuffer<Base>::Make(const void* data,
124 size_t size) {
125 SkASSERT(size);
126 sk_sp<SkData> storage;
127 if (data) {
128 storage = SkData::MakeWithCopy(data, size);
129 } else {
130 storage = SkData::MakeZeroInitialized(size);
131 }
132 return sk_sp<Base>(new CpuBuffer<Base>(std::move(storage)));
133 }
134
onUpdate(GrDirectContext * dc,const void * data,size_t offset,size_t size)135 template <typename Base> bool SkMeshPriv::CpuBuffer<Base>::onUpdate(GrDirectContext* dc,
136 const void* data,
137 size_t offset,
138 size_t size) {
139 if (dc) {
140 return false;
141 }
142 std::memcpy(SkTAddOffset<void>(fData->writable_data(), offset), data, size);
143 return true;
144 }
145
146 #endif
147