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#include "include/core/SkVertices.h"
9
10#include "include/core/SkData.h"
11#include "include/private/SkTo.h"
12#include "src/core/SkCanvasPriv.h"
13#include "src/core/SkOpts.h"
14#include "src/core/SkReadBuffer.h"
15#include "src/core/SkSafeMath.h"
16#include "src/core/SkSafeRange.h"
17#include "src/core/SkVerticesPriv.h"
18#include "src/core/SkWriteBuffer.h"
19#include <atomic>
20#include <new>
21
22static int32_t next_id() {
23 static std::atomic<int32_t> nextID{1};
24
25 int32_t id;
26 do {
27 id = nextID++;
28 } while (id == SK_InvalidGenID);
29 return id;
30}
31
32SkVertices::Attribute::Attribute(Type t, Usage u, const char* markerName)
33 : fType(t)
34 , fUsage(u)
35 , fMarkerName(markerName) {
36 fMarkerID = fMarkerName ? SkOpts::hash_fn(fMarkerName, strlen(fMarkerName), 0) : 0;
37 SkASSERT(!fMarkerName || fMarkerID != 0);
38}
39
40int SkVertices::Attribute::channelCount() const {
41 SkASSERT(this->isValid());
42 switch (fUsage) {
43 case Usage::kRaw: break;
44 case Usage::kColor: return 4;
45 case Usage::kVector: return 3;
46 case Usage::kNormalVector: return 3;
47 case Usage::kPosition: return 3;
48 }
49 switch (fType) {
50 case Type::kFloat: return 1;
51 case Type::kFloat2: return 2;
52 case Type::kFloat3: return 3;
53 case Type::kFloat4: return 4;
54 case Type::kByte4_unorm: return 4;
55 }
56 SkUNREACHABLE;
57}
58
59size_t SkVertices::Attribute::bytesPerVertex() const {
60 switch (fType) {
61 case Type::kFloat: return 1 * sizeof(float);
62 case Type::kFloat2: return 2 * sizeof(float);
63 case Type::kFloat3: return 3 * sizeof(float);
64 case Type::kFloat4: return 4 * sizeof(float);
65 case Type::kByte4_unorm: return 4 * sizeof(uint8_t);
66 }
67 SkUNREACHABLE;
68}
69
70bool SkVertices::Attribute::isValid() const {
71 if (fMarkerName && !SkCanvasPriv::ValidateMarker(fMarkerName)) {
72 return false;
73 }
74 switch (fUsage) {
75 case Usage::kRaw:
76 return fMarkerID == 0;
77 case Usage::kColor:
78 return fMarkerID == 0 && (fType == Type::kFloat3 || fType == Type::kFloat4 ||
79 fType == Type::kByte4_unorm);
80 case Usage::kVector:
81 case Usage::kNormalVector:
82 case Usage::kPosition:
83 return fType == Type::kFloat2 || fType == Type::kFloat3;
84 }
85 SkUNREACHABLE;
86}
87
88static size_t custom_data_size(const SkVertices::Attribute* attrs, int attrCount) {
89 size_t size = 0;
90 for (int i = 0; i < attrCount; ++i) {
91 size += attrs[i].bytesPerVertex();
92 }
93 return size;
94}
95
96struct SkVertices::Desc {
97 VertexMode fMode;
98 int fVertexCount,
99 fIndexCount;
100 bool fHasTexs,
101 fHasColors;
102
103 const Attribute* fAttributes;
104 int fAttributeCount;
105
106 void validate() const {
107 SkASSERT(fAttributeCount == 0 || (!fHasTexs && !fHasColors));
108 }
109};
110
111struct SkVertices::Sizes {
112 Sizes(const Desc& desc) {
113 desc.validate();
114
115 SkSafeMath safe;
116
117 fNameSize = 0;
118 for (int i = 0; i < desc.fAttributeCount; ++i) {
119 const Attribute& attr(desc.fAttributes[i]);
120 if (!attr.isValid()) {
121 return;
122 }
123 if (attr.fMarkerName) {
124 fNameSize = safe.add(fNameSize, strlen(attr.fMarkerName) + 1 /*null terminator*/);
125 }
126 }
127 fNameSize = SkAlign4(fNameSize);
128
129 fAttrSize = safe.mul(desc.fAttributeCount, sizeof(Attribute));
130 fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
131 fDSize = safe.mul(custom_data_size(desc.fAttributes, desc.fAttributeCount),
132 desc.fVertexCount);
133 fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
134 fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
135
136 fBuilderTriFanISize = 0;
137 fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
138 if (kTriangleFan_VertexMode == desc.fMode) {
139 int numFanTris = 0;
140 if (desc.fIndexCount) {
141 fBuilderTriFanISize = fISize;
142 numFanTris = desc.fIndexCount - 2;
143 } else {
144 numFanTris = desc.fVertexCount - 2;
145 // By forcing this to become indexed we are adding a constraint to the maximum
146 // number of vertices.
147 if (desc.fVertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
148 sk_bzero(this, sizeof(*this));
149 return;
150 }
151 }
152 if (numFanTris <= 0) {
153 sk_bzero(this, sizeof(*this));
154 return;
155 }
156 fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
157 }
158
159 fTotal = safe.add(sizeof(SkVertices),
160 safe.add(fAttrSize,
161 safe.add(fNameSize,
162 safe.add(fVSize,
163 safe.add(fDSize,
164 safe.add(fTSize,
165 safe.add(fCSize,
166 fISize)))))));
167
168 if (safe.ok()) {
169 fArrays = fVSize + fDSize + fTSize + fCSize + fISize; // just the sum of the arrays
170 } else {
171 sk_bzero(this, sizeof(*this));
172 }
173 }
174
175 bool isValid() const { return fTotal != 0; }
176
177 size_t fTotal = 0; // size of entire SkVertices allocation (obj + arrays)
178 size_t fAttrSize; // size of attributes
179 size_t fNameSize; // size of attribute marker names
180 size_t fArrays; // size of all the data arrays (V + D + T + C + I)
181 size_t fVSize;
182 size_t fDSize; // size of all customData = [customDataSize * fVertexCount]
183 size_t fTSize;
184 size_t fCSize;
185 size_t fISize;
186
187 // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
188 // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
189 size_t fBuilderTriFanISize;
190};
191
192SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
193 uint32_t builderFlags) {
194 bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
195 bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
196 this->init({mode, vertexCount, indexCount, hasTexs, hasColors, nullptr, 0});
197}
198
199SkVertices::Builder::Builder(VertexMode mode,
200 int vertexCount,
201 int indexCount,
202 const SkVertices::Attribute* attrs,
203 int attrCount) {
204 if (attrCount <= 0 || attrCount > kMaxCustomAttributes || !attrs) {
205 return;
206 }
207 this->init({mode, vertexCount, indexCount, false, false, attrs, attrCount});
208}
209
210SkVertices::Builder::Builder(const Desc& desc) {
211 this->init(desc);
212}
213
214void SkVertices::Builder::init(const Desc& desc) {
215 Sizes sizes(desc);
216 if (!sizes.isValid()) {
217 SkASSERT(!this->isValid());
218 return;
219 }
220
221 void* storage = ::operator new (sizes.fTotal);
222 if (sizes.fBuilderTriFanISize) {
223 fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
224 }
225
226 fVertices.reset(new (storage) SkVertices);
227
228 // need to point past the object to store the arrays
229 char* ptr = (char*)storage + sizeof(SkVertices);
230
231 // return the original ptr (or null), but then advance it by size
232 auto advance = [&ptr](size_t size) {
233 char* new_ptr = size ? ptr : nullptr;
234 ptr += size;
235 return new_ptr;
236 };
237
238 fVertices->fAttributes = (Attribute*)advance(sizes.fAttrSize);
239 char* markerNames = advance(sizes.fNameSize);
240
241 // Copy the attributes into our block of memory (immediately after the SkVertices)
242 sk_careful_memcpy(fVertices->fAttributes, desc.fAttributes,
243 desc.fAttributeCount * sizeof(Attribute));
244
245 // Now copy the marker names, and fix up the pointers in our attributes
246 for (int i = 0; i < desc.fAttributeCount; ++i) {
247 Attribute& attr(fVertices->fAttributes[i]);
248 if (attr.fMarkerName) {
249 attr.fMarkerName = strcpy(markerNames, attr.fMarkerName);
250 markerNames += (strlen(markerNames) + 1 /*null terminator*/);
251 }
252 }
253
254 fVertices->fPositions = (SkPoint*) advance(sizes.fVSize);
255 fVertices->fCustomData = (void*) advance(sizes.fDSize);
256 fVertices->fTexs = (SkPoint*) advance(sizes.fTSize);
257 fVertices->fColors = (SkColor*) advance(sizes.fCSize);
258 fVertices->fIndices = (uint16_t*)advance(sizes.fISize);
259
260 fVertices->fVertexCount = desc.fVertexCount;
261 fVertices->fIndexCount = desc.fIndexCount;
262 fVertices->fAttributeCount = desc.fAttributeCount;
263 fVertices->fMode = desc.fMode;
264
265 // We defer assigning fBounds and fUniqueID until detach() is called
266}
267
268sk_sp<SkVertices> SkVertices::Builder::detach() {
269 if (fVertices) {
270 fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
271 if (fVertices->fMode == kTriangleFan_VertexMode) {
272 if (fIntermediateFanIndices.get()) {
273 SkASSERT(fVertices->fIndexCount);
274 auto tempIndices = this->indices();
275 for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
276 fVertices->fIndices[3 * t + 0] = tempIndices[0];
277 fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
278 fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
279 }
280 fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
281 } else {
282 SkASSERT(!fVertices->fIndexCount);
283 for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
284 fVertices->fIndices[3 * t + 0] = 0;
285 fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
286 fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
287 }
288 fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
289 }
290 fVertices->fMode = kTriangles_VertexMode;
291 }
292 fVertices->fUniqueID = next_id();
293 return std::move(fVertices); // this will null fVertices after the return
294 }
295 return nullptr;
296}
297
298SkPoint* SkVertices::Builder::positions() {
299 return fVertices ? const_cast<SkPoint*>(fVertices->fPositions) : nullptr;
300}
301
302void* SkVertices::Builder::customData() {
303 return fVertices ? const_cast<void*>(fVertices->fCustomData) : nullptr;
304}
305
306SkPoint* SkVertices::Builder::texCoords() {
307 return fVertices ? const_cast<SkPoint*>(fVertices->fTexs) : nullptr;
308}
309
310SkColor* SkVertices::Builder::colors() {
311 return fVertices ? const_cast<SkColor*>(fVertices->fColors) : nullptr;
312}
313
314uint16_t* SkVertices::Builder::indices() {
315 if (!fVertices) {
316 return nullptr;
317 }
318 if (fIntermediateFanIndices) {
319 return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
320 }
321 return const_cast<uint16_t*>(fVertices->fIndices);
322}
323
324///////////////////////////////////////////////////////////////////////////////////////////////////
325
326sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
327 const SkPoint pos[], const SkPoint texs[],
328 const SkColor colors[],
329 int indexCount, const uint16_t indices[]) {
330 auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors, nullptr, 0};
331 Builder builder(desc);
332 if (!builder.isValid()) {
333 return nullptr;
334 }
335
336 Sizes sizes(desc);
337 SkASSERT(sizes.isValid());
338 sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
339 sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
340 sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
341 size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
342 sk_careful_memcpy(builder.indices(), indices, isize);
343
344 return builder.detach();
345}
346
347size_t SkVertices::approximateSize() const {
348 return this->getSizes().fTotal;
349}
350
351SkVertices::Sizes SkVertices::getSizes() const {
352 Sizes sizes(
353 {fMode, fVertexCount, fIndexCount, !!fTexs, !!fColors, fAttributes, fAttributeCount});
354 SkASSERT(sizes.isValid());
355 return sizes;
356}
357
358size_t SkVerticesPriv::customDataSize() const {
359 return custom_data_size(fVertices->fAttributes, fVertices->fAttributeCount);
360}
361
362bool SkVerticesPriv::hasUsage(SkVertices::Attribute::Usage u) const {
363 for (int i = 0; i < fVertices->fAttributeCount; ++i) {
364 if (fVertices->fAttributes[i].fUsage == u) {
365 return true;
366 }
367 }
368 return false;
369}
370
371///////////////////////////////////////////////////////////////////////////////////////////////////
372
373// storage = packed | vertex_count | index_count | attr_count
374// | pos[] | custom[] | texs[] | colors[] | indices[]
375
376#define kMode_Mask 0x0FF
377#define kHasTexs_Mask 0x100
378#define kHasColors_Mask 0x200
379
380void SkVerticesPriv::encode(SkWriteBuffer& buffer) const {
381 // packed has room for additional flags in the future
382 uint32_t packed = static_cast<uint32_t>(fVertices->fMode);
383 SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits
384 if (fVertices->fTexs) {
385 packed |= kHasTexs_Mask;
386 }
387 if (fVertices->fColors) {
388 packed |= kHasColors_Mask;
389 }
390
391 SkVertices::Sizes sizes = fVertices->getSizes();
392 SkASSERT(!sizes.fBuilderTriFanISize);
393
394 // Header
395 buffer.writeUInt(packed);
396 buffer.writeInt(fVertices->fVertexCount);
397 buffer.writeInt(fVertices->fIndexCount);
398 buffer.writeInt(fVertices->fAttributeCount);
399
400 // Attribute metadata
401 for (int i = 0; i < fVertices->fAttributeCount; ++i) {
402 buffer.writeInt(static_cast<int>(fVertices->fAttributes[i].fType));
403 buffer.writeInt(static_cast<int>(fVertices->fAttributes[i].fUsage));
404 buffer.writeString(fVertices->fAttributes[i].fMarkerName);
405 }
406
407 // Data arrays
408 buffer.writeByteArray(fVertices->fPositions, sizes.fVSize);
409 buffer.writeByteArray(fVertices->fCustomData, sizes.fDSize);
410 buffer.writeByteArray(fVertices->fTexs, sizes.fTSize);
411 buffer.writeByteArray(fVertices->fColors, sizes.fCSize);
412 // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
413 buffer.writeByteArray(fVertices->fIndices, sizes.fISize);
414}
415
416sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
417 if (buffer.isVersionLT(SkPicturePriv::kVerticesUseReadBuffer_Version)) {
418 // Old versions used an embedded blob that was serialized with SkWriter32/SkReader32.
419 // We don't support loading those, but skip over the vertices to keep the buffer valid.
420 auto data = buffer.readByteArrayAsData();
421 (void)data;
422 return nullptr;
423 }
424
425 auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
426 SkSafeRange safe;
427
428 const uint32_t packed = buffer.readUInt();
429 const int vertexCount = safe.checkGE(buffer.readInt(), 0);
430 const int indexCount = safe.checkGE(buffer.readInt(), 0);
431 const int attrCount = safe.checkGE(buffer.readInt(), 0);
432 const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
433 packed & kMode_Mask, SkVertices::kLast_VertexMode);
434 const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
435 const bool hasColors = SkToBool(packed & kHasColors_Mask);
436
437 if (!safe // Invalid header fields
438 || attrCount > SkVertices::kMaxCustomAttributes // Too many custom attributes?
439 || (attrCount > 0 && (hasTexs || hasColors))) { // Overspecified (incompatible features)
440 return nullptr;
441 }
442
443 SkVertices::Attribute attrs[SkVertices::kMaxCustomAttributes];
444 SkString attrNames[SkVertices::kMaxCustomAttributes];
445 for (int i = 0; i < attrCount; ++i) {
446 auto type = buffer.checkRange(SkVertices::Attribute::Type::kFloat,
447 SkVertices::Attribute::Type::kByte4_unorm);
448 auto usage = buffer.checkRange(SkVertices::Attribute::Usage::kRaw,
449 SkVertices::Attribute::Usage::kPosition);
450 buffer.readString(&attrNames[i]);
451 const char* markerName = attrNames[i].isEmpty() ? nullptr : attrNames[i].c_str();
452 if (markerName && !SkCanvasPriv::ValidateMarker(markerName)) {
453 return nullptr;
454 }
455 attrs[i] = SkVertices::Attribute(type, usage, markerName);
456 }
457
458 // Ensure that all of the attribute metadata was valid before proceeding
459 if (!buffer.isValid()) {
460 return nullptr;
461 }
462
463 const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors,
464 attrCount ? attrs : nullptr, attrCount};
465 SkVertices::Sizes sizes(desc);
466 if (!sizes.isValid()) {
467 return nullptr;
468 }
469
470 SkVertices::Builder builder(desc);
471 if (!builder.isValid()) {
472 return nullptr;
473 }
474
475 buffer.readByteArray(builder.positions(), sizes.fVSize);
476 buffer.readByteArray(builder.customData(), sizes.fDSize);
477 buffer.readByteArray(builder.texCoords(), sizes.fTSize);
478 buffer.readByteArray(builder.colors(), sizes.fCSize);
479 size_t isize = (mode == SkVertices::kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
480 : sizes.fISize;
481 buffer.readByteArray(builder.indices(), isize);
482
483 if (!buffer.isValid()) {
484 return nullptr;
485 }
486
487 if (indexCount > 0) {
488 // validate that the indices are in range
489 const uint16_t* indices = builder.indices();
490 for (int i = 0; i < indexCount; ++i) {
491 if (indices[i] >= (unsigned)vertexCount) {
492 return nullptr;
493 }
494 }
495 }
496
497 return builder.detach();
498 };
499
500 if (auto verts = decode(buffer)) {
501 return verts;
502 }
503 buffer.validate(false);
504 return nullptr;
505}
506
507void SkVertices::operator delete(void* p) {
508 ::operator delete(p);
509}
510