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
15class SkData;
16struct SkPoint;
17class SkVerticesPriv;
18
19/**
20 * An immutable set of vertex data that can be used with SkCanvas::drawVertices.
21 */
22class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
23 struct Desc;
24 struct Sizes;
25public:
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
177private:
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