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 #include "include/core/SkVertices.h"
8
9 #include "include/core/SkTypes.h"
10 #include "include/private/base/SkMalloc.h"
11 #include "include/private/base/SkTo.h"
12 #include "src/base/SkSafeMath.h"
13 #include "src/core/SkPicturePriv.h"
14 #include "src/core/SkReadBuffer.h"
15 #include "src/core/SkSafeRange.h"
16 #include "src/core/SkVerticesPriv.h"
17 #include "src/core/SkWriteBuffer.h"
18
19 #include <atomic>
20 #include <new>
21 #include <utility>
22
next_id()23 static uint32_t next_id() {
24 static std::atomic<uint32_t> nextID{1};
25
26 uint32_t id;
27 do {
28 id = nextID.fetch_add(1, std::memory_order_relaxed);
29 } while (id == SK_InvalidGenID);
30 return id;
31 }
32
33 struct SkVertices::Desc {
34 VertexMode fMode;
35 int fVertexCount,
36 fIndexCount;
37 bool fHasTexs,
38 fHasColors;
39 };
40
41 struct SkVertices::Sizes {
SizesSkVertices::Sizes42 Sizes(const Desc& desc) {
43 SkSafeMath safe;
44
45 fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
46 fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
47 fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
48
49 fBuilderTriFanISize = 0;
50 fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
51 if (kTriangleFan_VertexMode == desc.fMode) {
52 int numFanTris = 0;
53 if (desc.fIndexCount) {
54 fBuilderTriFanISize = fISize;
55 numFanTris = desc.fIndexCount - 2;
56 } else {
57 numFanTris = desc.fVertexCount - 2;
58 // By forcing this to become indexed we are adding a constraint to the maximum
59 // number of vertices.
60 if (desc.fVertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
61 sk_bzero(this, sizeof(*this));
62 return;
63 }
64 }
65 if (numFanTris <= 0) {
66 sk_bzero(this, sizeof(*this));
67 return;
68 }
69 fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
70 }
71
72 fTotal = safe.add(sizeof(SkVertices),
73 safe.add(fVSize,
74 safe.add(fTSize,
75 safe.add(fCSize,
76 fISize))));
77
78 if (safe.ok()) {
79 fArrays = fVSize + fTSize + fCSize + fISize; // just the sum of the arrays
80 } else {
81 sk_bzero(this, sizeof(*this));
82 }
83 }
84
isValidSkVertices::Sizes85 bool isValid() const { return fTotal != 0; }
86
87 size_t fTotal = 0; // size of entire SkVertices allocation (obj + arrays)
88 size_t fArrays; // size of all the data arrays (V + D + T + C + I)
89 size_t fVSize;
90 size_t fTSize;
91 size_t fCSize;
92 size_t fISize;
93
94 // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
95 // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
96 size_t fBuilderTriFanISize;
97 };
98
Builder(VertexMode mode,int vertexCount,int indexCount,uint32_t builderFlags)99 SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
100 uint32_t builderFlags) {
101 bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
102 bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
103 this->init({mode, vertexCount, indexCount, hasTexs, hasColors});
104 }
105
Builder(const Desc & desc)106 SkVertices::Builder::Builder(const Desc& desc) {
107 this->init(desc);
108 }
109
init(const Desc & desc)110 void SkVertices::Builder::init(const Desc& desc) {
111 Sizes sizes(desc);
112 if (!sizes.isValid()) {
113 SkASSERT(!this->isValid());
114 return;
115 }
116
117 void* storage = ::operator new (sizes.fTotal);
118 if (sizes.fBuilderTriFanISize) {
119 fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
120 }
121
122 fVertices.reset(new (storage) SkVertices);
123
124 // need to point past the object to store the arrays
125 char* ptr = (char*)storage + sizeof(SkVertices);
126
127 // return the original ptr (or null), but then advance it by size
128 auto advance = [&ptr](size_t size) {
129 char* new_ptr = size ? ptr : nullptr;
130 ptr += size;
131 return new_ptr;
132 };
133
134 fVertices->fPositions = (SkPoint*) advance(sizes.fVSize);
135 fVertices->fTexs = (SkPoint*) advance(sizes.fTSize);
136 fVertices->fColors = (SkColor*) advance(sizes.fCSize);
137 fVertices->fIndices = (uint16_t*)advance(sizes.fISize);
138
139 fVertices->fVertexCount = desc.fVertexCount;
140 fVertices->fIndexCount = desc.fIndexCount;
141 fVertices->fMode = desc.fMode;
142
143 // We defer assigning fBounds and fUniqueID until detach() is called
144 }
145
detach()146 sk_sp<SkVertices> SkVertices::Builder::detach() {
147 if (fVertices) {
148 fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
149 if (fVertices->fMode == kTriangleFan_VertexMode) {
150 if (fIntermediateFanIndices) {
151 SkASSERT(fVertices->fIndexCount);
152 auto tempIndices = this->indices();
153 for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
154 fVertices->fIndices[3 * t + 0] = tempIndices[0];
155 fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
156 fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
157 }
158 fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
159 } else {
160 SkASSERT(!fVertices->fIndexCount);
161 for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
162 fVertices->fIndices[3 * t + 0] = 0;
163 fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
164 fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
165 }
166 fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
167 }
168 fVertices->fMode = kTriangles_VertexMode;
169 }
170 fVertices->fUniqueID = next_id();
171 return std::move(fVertices); // this will null fVertices after the return
172 }
173 return nullptr;
174 }
175
positions()176 SkPoint* SkVertices::Builder::positions() {
177 return fVertices ? const_cast<SkPoint*>(fVertices->fPositions) : nullptr;
178 }
179
texCoords()180 SkPoint* SkVertices::Builder::texCoords() {
181 return fVertices ? const_cast<SkPoint*>(fVertices->fTexs) : nullptr;
182 }
183
colors()184 SkColor* SkVertices::Builder::colors() {
185 return fVertices ? const_cast<SkColor*>(fVertices->fColors) : nullptr;
186 }
187
indices()188 uint16_t* SkVertices::Builder::indices() {
189 if (!fVertices) {
190 return nullptr;
191 }
192 if (fIntermediateFanIndices) {
193 return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
194 }
195 return const_cast<uint16_t*>(fVertices->fIndices);
196 }
197
198 ///////////////////////////////////////////////////////////////////////////////////////////////////
199
MakeCopy(VertexMode mode,int vertexCount,const SkPoint pos[],const SkPoint texs[],const SkColor colors[],int indexCount,const uint16_t indices[])200 sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
201 const SkPoint pos[], const SkPoint texs[],
202 const SkColor colors[],
203 int indexCount, const uint16_t indices[]) {
204 auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors};
205 Builder builder(desc);
206 if (!builder.isValid()) {
207 return nullptr;
208 }
209
210 Sizes sizes(desc);
211 SkASSERT(sizes.isValid());
212 sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
213 sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
214 sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
215 size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
216 sk_careful_memcpy(builder.indices(), indices, isize);
217
218 return builder.detach();
219 }
220
approximateSize() const221 size_t SkVertices::approximateSize() const {
222 return this->getSizes().fTotal;
223 }
224
getSizes() const225 SkVertices::Sizes SkVertices::getSizes() const {
226 Sizes sizes({fMode, fVertexCount, fIndexCount, !!fTexs, !!fColors});
227 SkASSERT(sizes.isValid());
228 return sizes;
229 }
230
231 ///////////////////////////////////////////////////////////////////////////////////////////////////
232
233 // storage = packed | vertex_count | index_count | attr_count
234 // | pos[] | custom[] | texs[] | colors[] | indices[]
235
236 #define kMode_Mask 0x0FF
237 #define kHasTexs_Mask 0x100
238 #define kHasColors_Mask 0x200
239
encode(SkWriteBuffer & buffer) const240 void SkVerticesPriv::encode(SkWriteBuffer& buffer) const {
241 // packed has room for additional flags in the future
242 uint32_t packed = static_cast<uint32_t>(fVertices->fMode);
243 SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits
244 if (fVertices->fTexs) {
245 packed |= kHasTexs_Mask;
246 }
247 if (fVertices->fColors) {
248 packed |= kHasColors_Mask;
249 }
250
251 SkVertices::Sizes sizes = fVertices->getSizes();
252 SkASSERT(!sizes.fBuilderTriFanISize);
253
254 // Header
255 buffer.writeUInt(packed);
256 buffer.writeInt(fVertices->fVertexCount);
257 buffer.writeInt(fVertices->fIndexCount);
258
259 // Data arrays
260 buffer.writeByteArray(fVertices->fPositions, sizes.fVSize);
261 buffer.writeByteArray(fVertices->fTexs, sizes.fTSize);
262 buffer.writeByteArray(fVertices->fColors, sizes.fCSize);
263 // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
264 buffer.writeByteArray(fVertices->fIndices, sizes.fISize);
265 }
266
Decode(SkReadBuffer & buffer)267 sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
268 auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
269 SkSafeRange safe;
270 bool hasCustomData = buffer.isVersionLT(SkPicturePriv::kVerticesRemoveCustomData_Version);
271
272 const uint32_t packed = buffer.readUInt();
273 const int vertexCount = safe.checkGE(buffer.readInt(), 0);
274 const int indexCount = safe.checkGE(buffer.readInt(), 0);
275 const int attrCount = hasCustomData ? safe.checkGE(buffer.readInt(), 0) : 0;
276 const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
277 packed & kMode_Mask, SkVertices::kLast_VertexMode);
278 const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
279 const bool hasColors = SkToBool(packed & kHasColors_Mask);
280
281 // Check that the header fields and buffer are valid. If this is data with the experimental
282 // custom attributes feature - we don't support that any more.
283 // We also don't support serialized triangle-fan data. We stopped writing that long ago,
284 // so it should never appear in valid encoded data.
285 if (!safe || !buffer.isValid() || attrCount ||
286 mode == SkVertices::kTriangleFan_VertexMode) {
287 return nullptr;
288 }
289
290 const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
291 SkVertices::Sizes sizes(desc);
292 if (!sizes.isValid() || sizes.fArrays > buffer.available()) {
293 return nullptr;
294 }
295
296 SkVertices::Builder builder(desc);
297 if (!builder.isValid()) {
298 return nullptr;
299 }
300
301 buffer.readByteArray(builder.positions(), sizes.fVSize);
302 if (hasCustomData) {
303 size_t customDataSize = 0;
304 buffer.skipByteArray(&customDataSize);
305 if (customDataSize != 0) {
306 return nullptr;
307 }
308 }
309 buffer.readByteArray(builder.texCoords(), sizes.fTSize);
310 buffer.readByteArray(builder.colors(), sizes.fCSize);
311 buffer.readByteArray(builder.indices(), sizes.fISize);
312
313 if (!buffer.isValid()) {
314 return nullptr;
315 }
316
317 if (indexCount > 0) {
318 // validate that the indices are in range
319 const uint16_t* indices = builder.indices();
320 for (int i = 0; i < indexCount; ++i) {
321 if (indices[i] >= (unsigned)vertexCount) {
322 return nullptr;
323 }
324 }
325 }
326
327 return builder.detach();
328 };
329
330 if (auto verts = decode(buffer)) {
331 return verts;
332 }
333 buffer.validate(false);
334 return nullptr;
335 }
336
operator delete(void * p)337 void SkVertices::operator delete(void* p) {
338 ::operator delete(p);
339 }
340