xref: /aosp_15_r20/external/skia/src/core/SkVertices.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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