xref: /aosp_15_r20/external/skia/src/core/SkMeshPriv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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