1 | /* |
2 | * Copyright 2017 Google Inc. |
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 SkVertices_DEFINED |
9 | #define SkVertices_DEFINED |
10 | |
11 | #include "include/core/SkColor.h" |
12 | #include "include/core/SkRect.h" |
13 | #include "include/core/SkRefCnt.h" |
14 | |
15 | class SkData; |
16 | struct SkPoint; |
17 | class SkVerticesPriv; |
18 | |
19 | /** |
20 | * An immutable set of vertex data that can be used with SkCanvas::drawVertices. |
21 | */ |
22 | class SK_API SkVertices : public SkNVRefCnt<SkVertices> { |
23 | struct Desc; |
24 | struct Sizes; |
25 | public: |
26 | enum VertexMode { |
27 | kTriangles_VertexMode, |
28 | kTriangleStrip_VertexMode, |
29 | kTriangleFan_VertexMode, |
30 | |
31 | kLast_VertexMode = kTriangleFan_VertexMode, |
32 | }; |
33 | |
34 | /** |
35 | * Create a vertices by copying the specified arrays. texs, colors may be nullptr, |
36 | * and indices is ignored if indexCount == 0. |
37 | */ |
38 | static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount, |
39 | const SkPoint positions[], |
40 | const SkPoint texs[], |
41 | const SkColor colors[], |
42 | int indexCount, |
43 | const uint16_t indices[]); |
44 | |
45 | static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount, |
46 | const SkPoint positions[], |
47 | const SkPoint texs[], |
48 | const SkColor colors[]) { |
49 | return MakeCopy(mode, |
50 | vertexCount, |
51 | positions, |
52 | texs, |
53 | colors, |
54 | 0, |
55 | nullptr); |
56 | } |
57 | |
58 | static constexpr int kMaxCustomAttributes = 8; |
59 | |
60 | /** |
61 | * EXPERIMENTAL - An SkVertices object can be constructed with a custom collection of vertex |
62 | * attributes. Each attribute is described by a single Attribute struct. Type defines the CPU |
63 | * type of the data. Usage determines what transformation (if any) is applied to that data in |
64 | * the vertex shader. For positions or vectors, markerName identifies what matrix is used in |
65 | * the vertex shader to transform the data. Those names should match a named transform on the |
66 | * CTM stack, created by calling SkCanvas::markCTM(). |
67 | * |
68 | * For attributes with a usage of kVector, kNormalVector, or kPosition, a null markerName |
69 | * will transform the attribute by the canvas CTM matrix. |
70 | */ |
71 | struct Attribute { |
72 | enum class Type : uint8_t { |
73 | kFloat, |
74 | kFloat2, |
75 | kFloat3, |
76 | kFloat4, |
77 | kByte4_unorm, |
78 | }; |
79 | |
80 | enum class Usage : uint8_t { |
81 | // Raw values passed directly to effect |
82 | kRaw, |
83 | |
84 | // sRGB unpremul colors, transformed to destination color space (3 or 4 channels) |
85 | // Colors are always assumed to be in RGBA order, and are automatically premultiplied. |
86 | kColor, |
87 | |
88 | // Local vector, transformed via marker (2 or 3 channels) |
89 | kVector, |
90 | |
91 | // Normal vector (or any other bivector), transformed via marker (2 or 3 channels) |
92 | kNormalVector, |
93 | |
94 | // Local position, transformed via marker (2 or 3 channels) |
95 | kPosition, |
96 | }; |
97 | |
98 | /** |
99 | * markerName is not copied by the Attribute, so it must outlive this struct. |
100 | * It is copied when this Attribute is passed to the Builder constructor. |
101 | */ |
102 | Attribute(Type t = Type::kFloat, Usage u = Usage::kRaw, const char* markerName = nullptr); |
103 | |
104 | bool operator==(const Attribute& that) const { |
105 | return fType == that.fType && fUsage == that.fUsage && fMarkerID == that.fMarkerID; |
106 | } |
107 | bool operator!=(const Attribute& that) const { return !(*this == that); } |
108 | |
109 | // Number of channels that will be produced for the SkRuntimeEffect to consume. |
110 | // May not match the number of channels in fType. For example, kVector Attributes always |
111 | // produce three channels, even if the input is kFloat2. |
112 | int channelCount() const; |
113 | size_t bytesPerVertex() const; |
114 | bool isValid() const; |
115 | |
116 | Type fType; |
117 | Usage fUsage; |
118 | uint32_t fMarkerID; |
119 | const char* fMarkerName; // Preserved for serialization and debugging |
120 | }; |
121 | |
122 | enum BuilderFlags { |
123 | kHasTexCoords_BuilderFlag = 1 << 0, |
124 | kHasColors_BuilderFlag = 1 << 1, |
125 | }; |
126 | class Builder { |
127 | public: |
128 | Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags); |
129 | |
130 | // EXPERIMENTAL -- do not call if you care what happens |
131 | Builder(VertexMode mode, |
132 | int vertexCount, |
133 | int indexCount, |
134 | const Attribute* attrs, |
135 | int attrCount); |
136 | |
137 | bool isValid() const { return fVertices != nullptr; } |
138 | |
139 | SkPoint* positions(); |
140 | uint16_t* indices(); // returns null if there are no indices |
141 | |
142 | // if we have texCoords or colors, this will always be null |
143 | void* customData(); // returns null if there are no custom attributes |
144 | |
145 | // If we have custom attributes, these will always be null |
146 | SkPoint* texCoords(); // returns null if there are no texCoords |
147 | SkColor* colors(); // returns null if there are no colors |
148 | |
149 | // Detach the built vertices object. After the first call, this will always return null. |
150 | sk_sp<SkVertices> detach(); |
151 | |
152 | private: |
153 | Builder(const Desc&); |
154 | |
155 | void init(const Desc&); |
156 | |
157 | // holds a partially complete object. only completed in detach() |
158 | sk_sp<SkVertices> fVertices; |
159 | // Extra storage for intermediate vertices in the case where the client specifies indexed |
160 | // triangle fans. These get converted to indexed triangles when the Builder is finalized. |
161 | std::unique_ptr<uint8_t[]> fIntermediateFanIndices; |
162 | |
163 | friend class SkVertices; |
164 | friend class SkVerticesPriv; |
165 | }; |
166 | |
167 | uint32_t uniqueID() const { return fUniqueID; } |
168 | const SkRect& bounds() const { return fBounds; } |
169 | |
170 | // returns approximate byte size of the vertices object |
171 | size_t approximateSize() const; |
172 | |
173 | // Provides access to functions that aren't part of the public API. |
174 | SkVerticesPriv priv(); |
175 | const SkVerticesPriv priv() const; // NOLINT(readability-const-return-type) |
176 | |
177 | private: |
178 | SkVertices() {} |
179 | |
180 | friend class SkVerticesPriv; |
181 | |
182 | // these are needed since we've manually sized our allocation (see Builder::init) |
183 | friend class SkNVRefCnt<SkVertices>; |
184 | void operator delete(void* p); |
185 | |
186 | Sizes getSizes() const; |
187 | |
188 | // we store this first, to pair with the refcnt in our base-class, so we don't have an |
189 | // unnecessary pad between it and the (possibly 8-byte aligned) ptrs. |
190 | uint32_t fUniqueID; |
191 | |
192 | // these point inside our allocation, so none of these can be "freed" |
193 | Attribute* fAttributes; // [attributeCount] or null |
194 | SkPoint* fPositions; // [vertexCount] |
195 | uint16_t* fIndices; // [indexCount] or null |
196 | void* fCustomData; // [customDataSize * vertexCount] or null |
197 | SkPoint* fTexs; // [vertexCount] or null |
198 | SkColor* fColors; // [vertexCount] or null |
199 | |
200 | SkRect fBounds; // computed to be the union of the fPositions[] |
201 | int fVertexCount; |
202 | int fIndexCount; |
203 | int fAttributeCount; |
204 | |
205 | VertexMode fMode; |
206 | // below here is where the actual array data is stored. |
207 | }; |
208 | |
209 | #endif |
210 | |