• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/private/SkVx.h"
13 #include "src/core/SkCanvasPriv.h"
14 #include "src/core/SkOpts.h"
15 #include "src/core/SkReadBuffer.h"
16 #include "src/core/SkSafeMath.h"
17 #include "src/core/SkSafeRange.h"
18 #include "src/core/SkVerticesPriv.h"
19 #include "src/core/SkWriteBuffer.h"
20 
21 #include <algorithm>
22 #include <atomic>
23 #include <cstdint>
24 #include <new>
25 
next_id()26 static int32_t next_id() {
27     static std::atomic<int32_t> nextID{1};
28 
29     int32_t id;
30     do {
31         id = nextID.fetch_add(1, std::memory_order_relaxed);
32     } while (id == SK_InvalidGenID);
33     return id;
34 }
35 
36 struct SkVertices::Desc {
37     VertexMode  fMode;
38     int         fVertexCount,
39                 fIndexCount;
40     bool        fHasTexs,
41                 fHasColors;
42 };
43 
44 struct SkVertices::Sizes {
SizesSkVertices::Sizes45     Sizes(const Desc& desc) {
46         SkSafeMath safe;
47 
48         fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
49         fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
50         fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
51 
52         fBuilderTriFanISize = 0;
53         fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
54         if (kTriangleFan_VertexMode == desc.fMode) {
55             int numFanTris = 0;
56             if (desc.fIndexCount) {
57                 fBuilderTriFanISize = fISize;
58                 numFanTris = desc.fIndexCount - 2;
59             } else {
60                 numFanTris = desc.fVertexCount - 2;
61                 // By forcing this to become indexed we are adding a constraint to the maximum
62                 // number of vertices.
63                 if (desc.fVertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
64                     sk_bzero(this, sizeof(*this));
65                     return;
66                 }
67             }
68             if (numFanTris <= 0) {
69                 sk_bzero(this, sizeof(*this));
70                 return;
71             }
72             fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
73         }
74 
75         fTotal = safe.add(sizeof(SkVertices),
76                  safe.add(fVSize,
77                  safe.add(fTSize,
78                  safe.add(fCSize,
79                           fISize))));
80 
81         if (safe.ok()) {
82             fArrays = fVSize + fTSize + fCSize + fISize;  // just the sum of the arrays
83         } else {
84             sk_bzero(this, sizeof(*this));
85         }
86     }
87 
88     // skia comit change number: 926863
isValidSkVertices::Sizes89     bool isValid() const {
90         SkASSERT(fTotal >= fVSize);
91         return fVSize > 0;
92     }
93 
94     size_t fTotal = 0;  // size of entire SkVertices allocation (obj + arrays)
95     size_t fArrays; // size of all the data arrays (V + D + T + C + I)
96     size_t fVSize;
97     size_t fTSize;
98     size_t fCSize;
99     size_t fISize;
100 
101     // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
102     // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
103     size_t fBuilderTriFanISize;
104 };
105 
Builder(VertexMode mode,int vertexCount,int indexCount,uint32_t builderFlags)106 SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
107                              uint32_t builderFlags) {
108     bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
109     bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
110     this->init({mode, vertexCount, indexCount, hasTexs, hasColors});
111 }
112 
Builder(const Desc & desc)113 SkVertices::Builder::Builder(const Desc& desc) {
114     this->init(desc);
115 }
116 
init(const Desc & desc)117 void SkVertices::Builder::init(const Desc& desc) {
118     Sizes sizes(desc);
119     if (!sizes.isValid()) {
120         SkASSERT(!this->isValid());
121         return;
122     }
123 
124     void* storage = ::operator new (sizes.fTotal);
125     if (sizes.fBuilderTriFanISize) {
126         fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
127     }
128 
129     fVertices.reset(new (storage) SkVertices);
130 
131     // need to point past the object to store the arrays
132     char* ptr = (char*)storage + sizeof(SkVertices);
133 
134     // return the original ptr (or null), but then advance it by size
135     auto advance = [&ptr](size_t size) {
136         char* new_ptr = size ? ptr : nullptr;
137         ptr += size;
138         return new_ptr;
139     };
140 
141     fVertices->fPositions      = (SkPoint*) advance(sizes.fVSize);
142     fVertices->fTexs           = (SkPoint*) advance(sizes.fTSize);
143     fVertices->fColors         = (SkColor*) advance(sizes.fCSize);
144     fVertices->fIndices        = (uint16_t*)advance(sizes.fISize);
145 
146     fVertices->fVertexCount    = desc.fVertexCount;
147     fVertices->fIndexCount     = desc.fIndexCount;
148     fVertices->fMode           = desc.fMode;
149 
150     // We defer assigning fBounds and fUniqueID until detach() is called
151 }
152 
detach()153 sk_sp<SkVertices> SkVertices::Builder::detach() {
154     if (fVertices) {
155         fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
156         if (fVertices->fMode == kTriangleFan_VertexMode) {
157             if (fIntermediateFanIndices) {
158                 SkASSERT(fVertices->fIndexCount);
159                 auto tempIndices = this->indices();
160                 for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
161                     fVertices->fIndices[3 * t + 0] = tempIndices[0];
162                     fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
163                     fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
164                 }
165                 fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
166             } else {
167                 SkASSERT(!fVertices->fIndexCount);
168                 for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
169                     fVertices->fIndices[3 * t + 0] = 0;
170                     fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
171                     fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
172                 }
173                 fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
174             }
175             fVertices->fMode = kTriangles_VertexMode;
176         }
177         fVertices->fUniqueID = next_id();
178         return std::move(fVertices);        // this will null fVertices after the return
179     }
180     return nullptr;
181 }
182 
positions()183 SkPoint* SkVertices::Builder::positions() {
184     return fVertices ? const_cast<SkPoint*>(fVertices->fPositions) : nullptr;
185 }
186 
texCoords()187 SkPoint* SkVertices::Builder::texCoords() {
188     return fVertices ? const_cast<SkPoint*>(fVertices->fTexs) : nullptr;
189 }
190 
colors()191 SkColor* SkVertices::Builder::colors() {
192     return fVertices ? const_cast<SkColor*>(fVertices->fColors) : nullptr;
193 }
194 
indices()195 uint16_t* SkVertices::Builder::indices() {
196     if (!fVertices) {
197         return nullptr;
198     }
199     if (fIntermediateFanIndices) {
200         return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
201     }
202     return const_cast<uint16_t*>(fVertices->fIndices);
203 }
204 
205 ///////////////////////////////////////////////////////////////////////////////////////////////////
206 
MakeCopy(VertexMode mode,int vertexCount,const SkPoint pos[],const SkPoint texs[],const SkColor colors[],int indexCount,const uint16_t indices[])207 sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
208                                        const SkPoint pos[], const SkPoint texs[],
209                                        const SkColor colors[],
210                                        int indexCount, const uint16_t indices[]) {
211     auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors};
212     Builder builder(desc);
213     if (!builder.isValid()) {
214         return nullptr;
215     }
216 
217     Sizes sizes(desc);
218     SkASSERT(sizes.isValid());
219     sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
220     sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
221     sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
222 
223     // skia comit change number: 926863
224     // The builder can update the number of indices.
225     const size_t isize = ((mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
226                                                             : sizes.fISize),
227                 icount = isize / sizeof(uint16_t);
228 
229     // Ensure that indices are valid for the given vertex count.
230     SkASSERT(vertexCount > 0);
231     const uint16_t max_index = SkToU16(vertexCount - 1);
232 
233     size_t i = 0;
234     for (; i + 8 <= icount; i += 8) {
235         const skvx::ushort8 ind8 = skvx::ushort8::Load(indices + i),
236                     clamped_ind8 = skvx::min(ind8, max_index);
237         clamped_ind8.store(builder.indices() + i);
238     }
239     if (i + 4 <= icount) {
240         const skvx::ushort4 ind4 = skvx::ushort4::Load(indices + i),
241                     clamped_ind4 = skvx::min(ind4, max_index);
242         clamped_ind4.store(builder.indices() + i);
243 
244         i += 4;
245     }
246     if (i + 2 <= icount) {
247         const skvx::ushort2 ind2 = skvx::ushort2::Load(indices + i),
248                     clamped_ind2 = skvx::min(ind2, max_index);
249         clamped_ind2.store(builder.indices() + i);
250 
251         i += 2;
252     }
253     if (i < icount) {
254         builder.indices()[i] = std::min(indices[i], max_index);
255         SkDEBUGCODE(i += 1);
256     }
257     SkASSERT(i == icount);
258 
259     return builder.detach();
260 }
261 
approximateSize() const262 size_t SkVertices::approximateSize() const {
263     return this->getSizes().fTotal;
264 }
265 
getSizes() const266 SkVertices::Sizes SkVertices::getSizes() const {
267     Sizes sizes({fMode, fVertexCount, fIndexCount, !!fTexs, !!fColors});
268     SkASSERT(sizes.isValid());
269     return sizes;
270 }
dump(std::string & desc,int depth) const271 void SkVertices::dump(std::string& desc, int depth) const {
272     std::string split(depth, '\t');
273     desc += split + "\n SkVertices:{ \n";
274     desc += split + "\t fUniqueID: " + std::to_string(fUniqueID) + "\n";
275     if (fPositions != nullptr) {
276         fPositions->dump(desc, depth + 1);
277     } else {
278         desc += split + "\t fPositions: nullptr\n";
279     }
280 
281     if (fTexs != nullptr) {
282         fTexs->dump(desc, depth + 1);
283     } else {
284         desc += split + "\t fTexs: nullptr\n";
285     }
286 
287     if (fColors != nullptr) {
288         desc += split + "\t fColors: " + std::to_string(*fColors) + "\n";
289     } else {
290         desc += split + "\t fColors: nullptr\n";
291     }
292 
293     if (fIndices != nullptr) {
294         desc += split + "\t fIndices: " + std::to_string(*fIndices) + "\n";
295     } else {
296         desc += split + "\t fIndices: nullptr\n";
297     }
298 
299     fBounds.dump(desc, depth + 1);
300     desc += split + "\t fVertexCount: " + std::to_string(fVertexCount) + "\n";
301     desc += split + "\t fIndexCount: " + std::to_string(fIndexCount) + "\n";
302     desc += split + "\t fMode: " + std::to_string(static_cast<int>(fMode)) + "\n";
303     desc += split + "}\n";
304 }
305 ///////////////////////////////////////////////////////////////////////////////////////////////////
306 
307 // storage = packed | vertex_count | index_count | attr_count
308 //           | pos[] | custom[] | texs[] | colors[] | indices[]
309 
310 #define kMode_Mask          0x0FF
311 #define kHasTexs_Mask       0x100
312 #define kHasColors_Mask     0x200
313 
encode(SkWriteBuffer & buffer) const314 void SkVerticesPriv::encode(SkWriteBuffer& buffer) const {
315     // packed has room for additional flags in the future
316     uint32_t packed = static_cast<uint32_t>(fVertices->fMode);
317     SkASSERT((packed & ~kMode_Mask) == 0);  // our mode fits in the mask bits
318     if (fVertices->fTexs) {
319         packed |= kHasTexs_Mask;
320     }
321     if (fVertices->fColors) {
322         packed |= kHasColors_Mask;
323     }
324 
325     SkVertices::Sizes sizes = fVertices->getSizes();
326     SkASSERT(!sizes.fBuilderTriFanISize);
327 
328     // Header
329     buffer.writeUInt(packed);
330     buffer.writeInt(fVertices->fVertexCount);
331     buffer.writeInt(fVertices->fIndexCount);
332 
333     // Data arrays
334     buffer.writeByteArray(fVertices->fPositions, sizes.fVSize);
335     buffer.writeByteArray(fVertices->fTexs, sizes.fTSize);
336     buffer.writeByteArray(fVertices->fColors, sizes.fCSize);
337     // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
338     buffer.writeByteArray(fVertices->fIndices, sizes.fISize);
339 }
340 
Decode(SkReadBuffer & buffer)341 sk_sp<SkVertices> SkVerticesPriv::Decode(SkReadBuffer& buffer) {
342     auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
343         SkSafeRange safe;
344         bool hasCustomData = buffer.isVersionLT(SkPicturePriv::kVerticesRemoveCustomData_Version);
345 
346         const uint32_t packed = buffer.readUInt();
347         const int vertexCount = safe.checkGE(buffer.readInt(), 0);
348         const int indexCount = safe.checkGE(buffer.readInt(), 0);
349         const int attrCount = hasCustomData ? safe.checkGE(buffer.readInt(), 0) : 0;
350         const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
351                 packed & kMode_Mask, SkVertices::kLast_VertexMode);
352         const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
353         const bool hasColors = SkToBool(packed & kHasColors_Mask);
354 
355         // Check that the header fields and buffer are valid. If this is data with the experimental
356         // custom attributes feature - we don't support that any more.
357         if (!safe || !buffer.isValid() || attrCount) {
358             return nullptr;
359         }
360 
361         const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
362         SkVertices::Sizes sizes(desc);
363         if (!sizes.isValid()) {
364             return nullptr;
365         }
366 
367         SkVertices::Builder builder(desc);
368         if (!builder.isValid()) {
369             return nullptr;
370         }
371 
372         buffer.readByteArray(builder.positions(), sizes.fVSize);
373         if (hasCustomData) {
374             size_t customDataSize = 0;
375             buffer.skipByteArray(&customDataSize);
376             if (customDataSize != 0) {
377                 return nullptr;
378             }
379         }
380         buffer.readByteArray(builder.texCoords(), sizes.fTSize);
381         buffer.readByteArray(builder.colors(), sizes.fCSize);
382         size_t isize = (mode == SkVertices::kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
383                                                                      : sizes.fISize;
384         buffer.readByteArray(builder.indices(), isize);
385 
386         if (!buffer.isValid()) {
387             return nullptr;
388         }
389 
390         if (indexCount > 0) {
391             // validate that the indices are in range
392             const uint16_t* indices = builder.indices();
393             for (int i = 0; i < indexCount; ++i) {
394                 if (indices[i] >= (unsigned)vertexCount) {
395                     return nullptr;
396                 }
397             }
398         }
399 
400         return builder.detach();
401     };
402 
403     if (auto verts = decode(buffer)) {
404         return verts;
405     }
406     buffer.validate(false);
407     return nullptr;
408 }
409 
operator delete(void * p)410 void SkVertices::operator delete(void* p) {
411     ::operator delete(p);
412 }
413