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 struct Attribute {
61 enum class Type : uint8_t {
62 kFloat,
63 kFloat2,
64 kFloat3,
65 kFloat4,
66 kByte4_unorm,
67 };
68
69 enum class Usage : uint8_t {
70 // Raw values passed directly to effect
71 kRaw,
72
73 // sRGB unpremul colors, transformed to destination color space (3 or 4 channels)
74 // Colors are always assumed to be in RGBA order, and are automatically premultiplied.
75 kColor,
76
77 // Local vector, transformed to world (2 or 3 channels)
78 kVector,
79
80 // Normal vector (or any other bivector), transformed to world (2 or 3 channels)
81 kNormalVector,
82
83 // Local position, transformed to world (2 or 3 channels)
84 kPosition,
85 };
86
87 Attribute(Type t = Type::kFloat, Usage u = Usage::kRaw)
88 : fType(t)
89 , fUsage(u) {}
90
91 bool operator==(const Attribute& that) const {
92 return fType == that.fType && fUsage == that.fUsage;
93 }
94 bool operator!=(const Attribute& that) const { return !(*this == that); }
95
96 // Number of channels that will be produced for the SkRuntimeEffect to consume.
97 // May not match the number of channels in fType. For example, kVector Attributes always
98 // produce three channels, even if the input is kFloat2.
99 int channelCount() const;
100 size_t bytesPerVertex() const;
101 bool isValid() const;
102
103 Type fType;
104 Usage fUsage;
105 };
106
107 enum BuilderFlags {
108 kHasTexCoords_BuilderFlag = 1 << 0,
109 kHasColors_BuilderFlag = 1 << 1,
110 };
111 class Builder {
112 public:
113 Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);
114
115 // EXPERIMENTAL -- do not call if you care what happens
116 Builder(VertexMode mode,
117 int vertexCount,
118 int indexCount,
119 const Attribute* attrs,
120 int attrCount);
121
122 bool isValid() const { return fVertices != nullptr; }
123
124 SkPoint* positions();
125 uint16_t* indices(); // returns null if there are no indices
126
127 // if we have texCoords or colors, this will always be null
128 void* customData(); // returns null if there are no custom attributes
129
130 // If we have custom attributes, these will always be null
131 SkPoint* texCoords(); // returns null if there are no texCoords
132 SkColor* colors(); // returns null if there are no colors
133
134 // Detach the built vertices object. After the first call, this will always return null.
135 sk_sp<SkVertices> detach();
136
137 private:
138 Builder(const Desc&);
139
140 void init(const Desc&);
141
142 // holds a partially complete object. only completed in detach()
143 sk_sp<SkVertices> fVertices;
144 // Extra storage for intermediate vertices in the case where the client specifies indexed
145 // triangle fans. These get converted to indexed triangles when the Builder is finalized.
146 std::unique_ptr<uint8_t[]> fIntermediateFanIndices;
147
148 friend class SkVertices;
149 };
150
151 uint32_t uniqueID() const { return fUniqueID; }
152 const SkRect& bounds() const { return fBounds; }
153
154 // returns approximate byte size of the vertices object
155 size_t approximateSize() const;
156
157 /**
158 * Recreate a vertices from a buffer previously created by calling encode().
159 * Returns null if the data is corrupt or the length is incorrect for the contents.
160 */
161 static sk_sp<SkVertices> Decode(const void* buffer, size_t length);
162
163 /**
164 * Pack the vertices object into a byte buffer. This can be used to recreate the vertices
165 * by calling Decode() with the buffer.
166 */
167 sk_sp<SkData> encode() const;
168
169 // Provides access to functions that aren't part of the public API.
170 SkVerticesPriv priv();
171 const SkVerticesPriv priv() const;
172
173private:
174 SkVertices() {}
175
176 friend class SkVerticesPriv;
177
178 // these are needed since we've manually sized our allocation (see Builder::init)
179 friend class SkNVRefCnt<SkVertices>;
180 void operator delete(void* p);
181
182 Sizes getSizes() const;
183
184 // we store this first, to pair with the refcnt in our base-class, so we don't have an
185 // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
186 uint32_t fUniqueID;
187
188 // these point inside our allocation, so none of these can be "freed"
189 SkPoint* fPositions; // [vertexCount]
190 uint16_t* fIndices; // [indexCount] or null
191 void* fCustomData; // [customDataSize * vertexCount] or null
192 SkPoint* fTexs; // [vertexCount] or null
193 SkColor* fColors; // [vertexCount] or null
194
195 SkRect fBounds; // computed to be the union of the fPositions[]
196 int fVertexCount;
197 int fIndexCount;
198
199 Attribute fAttributes[kMaxCustomAttributes];
200 int fAttributeCount;
201
202 VertexMode fMode;
203 // below here is where the actual array data is stored.
204};
205
206#endif
207