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