• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkMesh.h"
12 
13 #ifdef SK_ENABLE_SKSL
14 #include "include/core/SkData.h"
15 #include "src/core/SkSLTypeShared.h"
16 
17 #if defined(SK_GANESH)
18 #include "include/gpu/GrDirectContext.h"
19 #include "include/private/gpu/ganesh/GrTypesPriv.h"
20 #include "src/gpu/ganesh/GrDirectContextPriv.h"
21 #include "src/gpu/ganesh/GrDrawingManager.h"
22 #include "src/gpu/ganesh/GrGpuBuffer.h"
23 #include "src/gpu/ganesh/GrResourceCache.h"
24 #include "src/gpu/ganesh/GrResourceProvider.h"
25 #endif
26 
27 struct SkMeshSpecificationPriv {
28     using Varying   = SkMeshSpecification::Varying;
29     using Attribute = SkMeshSpecification::Attribute;
30     using ColorType = SkMeshSpecification::ColorType;
31 
VaryingsSkMeshSpecificationPriv32     static SkSpan<const Varying> Varyings(const SkMeshSpecification& spec) {
33         return SkSpan(spec.fVaryings);
34     }
35 
VSSkMeshSpecificationPriv36     static const SkSL::Program* VS(const SkMeshSpecification& spec) { return spec.fVS.get(); }
FSSkMeshSpecificationPriv37     static const SkSL::Program* FS(const SkMeshSpecification& spec) { return spec.fFS.get(); }
38 
HashSkMeshSpecificationPriv39     static int Hash(const SkMeshSpecification& spec) { return spec.fHash; }
40 
GetColorTypeSkMeshSpecificationPriv41     static ColorType GetColorType(const SkMeshSpecification& spec) { return spec.fColorType; }
HasColorsSkMeshSpecificationPriv42     static bool HasColors(const SkMeshSpecification& spec) {
43         return GetColorType(spec) != ColorType::kNone;
44     }
45 
ColorSpaceSkMeshSpecificationPriv46     static SkColorSpace* ColorSpace(const SkMeshSpecification& spec) {
47         return spec.fColorSpace.get();
48     }
49 
AlphaTypeSkMeshSpecificationPriv50     static SkAlphaType AlphaType(const SkMeshSpecification& spec) { return spec.fAlphaType; }
51 
VaryingTypeAsSLTypeSkMeshSpecificationPriv52     static SkSLType VaryingTypeAsSLType(Varying::Type type) {
53         switch (type) {
54             case Varying::Type::kFloat:  return SkSLType::kFloat;
55             case Varying::Type::kFloat2: return SkSLType::kFloat2;
56             case Varying::Type::kFloat3: return SkSLType::kFloat3;
57             case Varying::Type::kFloat4: return SkSLType::kFloat4;
58             case Varying::Type::kHalf:   return SkSLType::kHalf;
59             case Varying::Type::kHalf2:  return SkSLType::kHalf2;
60             case Varying::Type::kHalf3:  return SkSLType::kHalf3;
61             case Varying::Type::kHalf4:  return SkSLType::kHalf4;
62         }
63         SkUNREACHABLE;
64     }
65 
66 #if defined(SK_GANESH)
AttrTypeAsVertexAttribTypeSkMeshSpecificationPriv67     static GrVertexAttribType AttrTypeAsVertexAttribType(Attribute::Type type) {
68         switch (type) {
69             case Attribute::Type::kFloat:        return kFloat_GrVertexAttribType;
70             case Attribute::Type::kFloat2:       return kFloat2_GrVertexAttribType;
71             case Attribute::Type::kFloat3:       return kFloat3_GrVertexAttribType;
72             case Attribute::Type::kFloat4:       return kFloat4_GrVertexAttribType;
73             case Attribute::Type::kUByte4_unorm: return kUByte4_norm_GrVertexAttribType;
74         }
75         SkUNREACHABLE;
76     }
77 #endif
78 
AttrTypeAsSLTypeSkMeshSpecificationPriv79     static SkSLType AttrTypeAsSLType(Attribute::Type type) {
80         switch (type) {
81             case Attribute::Type::kFloat:        return SkSLType::kFloat;
82             case Attribute::Type::kFloat2:       return SkSLType::kFloat2;
83             case Attribute::Type::kFloat3:       return SkSLType::kFloat3;
84             case Attribute::Type::kFloat4:       return SkSLType::kFloat4;
85             case Attribute::Type::kUByte4_unorm: return SkSLType::kHalf4;
86         }
87         SkUNREACHABLE;
88     }
89 
PassthroughLocalCoordsVaryingIndexSkMeshSpecificationPriv90     static int PassthroughLocalCoordsVaryingIndex(const SkMeshSpecification& spec) {
91         return spec.fPassthroughLocalCoordsVaryingIndex;
92     }
93 
94     /**
95      * A varying is dead if it is never referenced OR it is only referenced as a passthrough for
96      * local coordinates. In the latter case it's index will returned as
97      * PassthroughLocalCoordsVaryingIndex. Our analysis is not very sophisticated so this is
98      * determined conservatively.
99      */
VaryingIsDeadSkMeshSpecificationPriv100     static bool VaryingIsDead(const SkMeshSpecification& spec, int v) {
101         SkASSERT(v >= 0 && SkToSizeT(v) < spec.fVaryings.size());
102         return (1 << v) & spec.fDeadVaryingMask;
103     }
104 };
105 
106 struct SkMeshPriv {
107     class Buffer {
108     public:
109         virtual ~Buffer() = 0;
110 
111         Buffer() = default;
112         Buffer(const Buffer&) = delete;
113 
114         Buffer& operator=(const Buffer&) = delete;
115 
peekSkMeshPriv116         virtual const void* peek() const { return nullptr; }
117 
118 #if defined(SK_GANESH)
asGpuBufferSkMeshPriv119         virtual sk_sp<const GrGpuBuffer> asGpuBuffer() const { return nullptr; }
120 #endif
121     };
122 
123     class IB : public Buffer, public SkMesh::IndexBuffer  {};
124     class VB : public Buffer, public SkMesh::VertexBuffer {};
125 
126     template <typename Base> class CpuBuffer final : public Base {
127     public:
128         ~CpuBuffer() override = default;
129 
130         static sk_sp<Base> Make(const void* data, size_t size);
131 
peekSkMeshPriv132         const void* peek() const override { return fData->data(); }
133 
sizeSkMeshPriv134         size_t size() const override { return fData->size(); }
135 
136     private:
CpuBufferSkMeshPriv137         CpuBuffer(sk_sp<SkData> data) : fData(std::move(data)) {}
138 
139         bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) override;
140 
141         sk_sp<SkData> fData;
142     };
143 
144     using CpuIndexBuffer  = CpuBuffer<IB>;
145     using CpuVertexBuffer = CpuBuffer<VB>;
146 
147 #if defined(SK_GANESH)
148     template <typename Base, GrGpuBufferType> class GpuBuffer final : public Base {
149     public:
150         GpuBuffer() = default;
151 
152         ~GpuBuffer() override;
153 
154         static sk_sp<Base> Make(GrDirectContext*, const void* data, size_t size);
155 
asGpuBufferSkMeshPriv156         sk_sp<const GrGpuBuffer> asGpuBuffer() const override { return fBuffer; }
157 
sizeSkMeshPriv158         size_t size() const override { return fBuffer->size(); }
159 
160     private:
161         bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) override;
162 
163         sk_sp<GrGpuBuffer> fBuffer;
164         GrDirectContext::DirectContextID fContextID;
165     };
166 
167     using GpuIndexBuffer  = GpuBuffer<IB, GrGpuBufferType::kIndex >;
168     using GpuVertexBuffer = GpuBuffer<VB, GrGpuBufferType::kVertex>;
169 #endif  // defined(SK_GANESH)
170 
171 private:
172 #if defined(SK_GANESH)
173     static bool UpdateGpuBuffer(GrDirectContext*,
174                                 sk_sp<GrGpuBuffer>,
175                                 const void*,
176                                 size_t offset,
177                                 size_t size);
178 #endif
179 };
180 
181 inline SkMeshPriv::Buffer::~Buffer() = default;
182 
Make(const void * data,size_t size)183 template <typename Base> sk_sp<Base> SkMeshPriv::CpuBuffer<Base>::Make(const void* data,
184                                                                        size_t size) {
185     SkASSERT(size);
186     sk_sp<SkData> storage;
187     if (data) {
188         storage = SkData::MakeWithCopy(data, size);
189     } else {
190         storage = SkData::MakeZeroInitialized(size);
191     }
192     return sk_sp<Base>(new CpuBuffer<Base>(std::move(storage)));
193 }
194 
onUpdate(GrDirectContext * dc,const void * data,size_t offset,size_t size)195 template <typename Base> bool SkMeshPriv::CpuBuffer<Base>::onUpdate(GrDirectContext* dc,
196                                                                     const void* data,
197                                                                     size_t offset,
198                                                                     size_t size) {
199     if (dc) {
200         return false;
201     }
202     std::memcpy(SkTAddOffset<void>(fData->writable_data(), offset), data, size);
203     return true;
204 }
205 
206 #if defined(SK_GANESH)
207 
~GpuBuffer()208 template <typename Base, GrGpuBufferType Type> SkMeshPriv::GpuBuffer<Base, Type>::~GpuBuffer() {
209     GrResourceCache::ReturnResourceFromThread(std::move(fBuffer), fContextID);
210 }
211 
212 template <typename Base, GrGpuBufferType Type>
Make(GrDirectContext * dc,const void * data,size_t size)213 sk_sp<Base> SkMeshPriv::GpuBuffer<Base, Type>::Make(GrDirectContext* dc,
214                                                     const void* data,
215                                                     size_t size) {
216     SkASSERT(dc);
217 
218     sk_sp<GrGpuBuffer> buffer = dc->priv().resourceProvider()->createBuffer(
219             size,
220             Type,
221             kStatic_GrAccessPattern,
222             data ? GrResourceProvider::ZeroInit::kNo : GrResourceProvider::ZeroInit::kYes);
223     if (!buffer) {
224         return nullptr;
225     }
226 
227     if (data && !buffer->updateData(data, 0, size, /*preserve=*/false)) {
228         return nullptr;
229     }
230 
231     auto result = new GpuBuffer;
232     result->fBuffer    = std::move(buffer);
233     result->fContextID = dc->directContextID();
234     return sk_sp<Base>(result);
235 }
236 
237 
238 template <typename Base, GrGpuBufferType Type>
onUpdate(GrDirectContext * dc,const void * data,size_t offset,size_t size)239 bool SkMeshPriv::GpuBuffer<Base, Type>::onUpdate(GrDirectContext* dc,
240                                                  const void* data,
241                                                  size_t offset,
242                                                  size_t size) {
243     return UpdateGpuBuffer(dc, fBuffer, data, offset, size);
244 }
245 
246 #endif  // defined(SK_GANESH)
247 
248 #endif  // SK_ENABLE_SKSL
249 
250 #endif
251