• 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 "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 
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     if (buffer.isVersionLT(SkPicturePriv::kVerticesUseReadBuffer_Version)) {
268         // Old versions used an embedded blob that was serialized with SkWriter32/SkReader32.
269         // We don't support loading those, but skip over the vertices to keep the buffer valid.
270         auto data = buffer.readByteArrayAsData();
271         (void)data;
272         return nullptr;
273     }
274 
275     auto decode = [](SkReadBuffer& buffer) -> sk_sp<SkVertices> {
276         SkSafeRange safe;
277         bool hasCustomData = buffer.isVersionLT(SkPicturePriv::kVerticesRemoveCustomData_Version);
278 
279         const uint32_t packed = buffer.readUInt();
280         const int vertexCount = safe.checkGE(buffer.readInt(), 0);
281         const int indexCount = safe.checkGE(buffer.readInt(), 0);
282         const int attrCount = hasCustomData ? safe.checkGE(buffer.readInt(), 0) : 0;
283         const SkVertices::VertexMode mode = safe.checkLE<SkVertices::VertexMode>(
284                 packed & kMode_Mask, SkVertices::kLast_VertexMode);
285         const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
286         const bool hasColors = SkToBool(packed & kHasColors_Mask);
287 
288         // Check that the header fields and buffer are valid. If this is data with the experimental
289         // custom attributes feature - we don't support that any more.
290         if (!safe || !buffer.isValid() || attrCount) {
291             return nullptr;
292         }
293 
294         const SkVertices::Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors};
295         SkVertices::Sizes sizes(desc);
296         if (!sizes.isValid()) {
297             return nullptr;
298         }
299 
300         SkVertices::Builder builder(desc);
301         if (!builder.isValid()) {
302             return nullptr;
303         }
304 
305         buffer.readByteArray(builder.positions(), sizes.fVSize);
306         if (hasCustomData) {
307             size_t customDataSize = 0;
308             buffer.skipByteArray(&customDataSize);
309             if (customDataSize != 0) {
310                 return nullptr;
311             }
312         }
313         buffer.readByteArray(builder.texCoords(), sizes.fTSize);
314         buffer.readByteArray(builder.colors(), sizes.fCSize);
315         size_t isize = (mode == SkVertices::kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize
316                                                                      : sizes.fISize;
317         buffer.readByteArray(builder.indices(), isize);
318 
319         if (!buffer.isValid()) {
320             return nullptr;
321         }
322 
323         if (indexCount > 0) {
324             // validate that the indices are in range
325             const uint16_t* indices = builder.indices();
326             for (int i = 0; i < indexCount; ++i) {
327                 if (indices[i] >= (unsigned)vertexCount) {
328                     return nullptr;
329                 }
330             }
331         }
332 
333         return builder.detach();
334     };
335 
336     if (auto verts = decode(buffer)) {
337         return verts;
338     }
339     buffer.validate(false);
340     return nullptr;
341 }
342 
operator delete(void * p)343 void SkVertices::operator delete(void* p) {
344     ::operator delete(p);
345 }
346