blob: a3a3989535ee6b8960dd27ee353d46835bbbeef6 [file] [log] [blame]
Mike Reed97eb4fe2017-03-14 12:04:16 -04001/*
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
Hal Canaryfdcfb8b2018-06-13 09:42:32 -04008#include "SkVertices.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -04009
10#include "SkAtomics.h"
Mike Reedbdce9c22017-03-14 14:10:54 -040011#include "SkData.h"
12#include "SkReader32.h"
Mike Reedf00faa32018-01-09 13:30:54 -050013#include "SkSafeMath.h"
Mike Reed165fa632018-01-23 11:50:25 -050014#include "SkSafeRange.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040015#include "SkTo.h"
Mike Reedbdce9c22017-03-14 14:10:54 -040016#include "SkWriter32.h"
Mike Klein79aea6a2018-06-11 10:45:26 -040017#include <new>
Mike Reedbdce9c22017-03-14 14:10:54 -040018
Mike Reed9a8065d2017-03-14 21:05:17 -040019static int32_t gNextID = 1;
20static int32_t next_id() {
21 int32_t id;
22 do {
23 id = sk_atomic_inc(&gNextID);
24 } while (id == SK_InvalidGenID);
25 return id;
26}
27
Mike Reedaa9e3322017-03-16 14:38:48 -040028struct SkVertices::Sizes {
Brian Salomoncccafe82018-04-28 16:13:08 -040029 Sizes(SkVertices::VertexMode mode, int vertexCount, int indexCount, bool hasTexs,
Ruiqi Maof5101492018-06-29 14:32:21 -040030 bool hasColors, bool hasBones) {
Mike Reedf00faa32018-01-09 13:30:54 -050031 SkSafeMath safe;
Mike Reedaa9e3322017-03-16 14:38:48 -040032
Mike Reedf00faa32018-01-09 13:30:54 -050033 fVSize = safe.mul(vertexCount, sizeof(SkPoint));
34 fTSize = hasTexs ? safe.mul(vertexCount, sizeof(SkPoint)) : 0;
35 fCSize = hasColors ? safe.mul(vertexCount, sizeof(SkColor)) : 0;
Ruiqi Maof5101492018-06-29 14:32:21 -040036 fBISize = hasBones ? safe.mul(vertexCount, sizeof(BoneIndices)) : 0;
37 fBWSize = hasBones ? safe.mul(vertexCount, sizeof(BoneWeights)) : 0;
Brian Salomoncccafe82018-04-28 16:13:08 -040038
39 fBuilderTriFanISize = 0;
Mike Reedf00faa32018-01-09 13:30:54 -050040 fISize = safe.mul(indexCount, sizeof(uint16_t));
Brian Salomoncccafe82018-04-28 16:13:08 -040041 if (kTriangleFan_VertexMode == mode) {
42 int numFanTris = 0;
43 if (indexCount) {
44 fBuilderTriFanISize = fISize;
45 numFanTris = indexCount - 2;
46 } else {
47 numFanTris = vertexCount - 2;
48 // By forcing this to become indexed we are adding a constraint to the maximum
49 // number of vertices.
Ben Wagnerdde9b522018-06-15 16:19:56 -040050 if (vertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
Brian Salomoncccafe82018-04-28 16:13:08 -040051 sk_bzero(this, sizeof(*this));
52 return;
53 }
54 }
55 if (numFanTris <= 0) {
56 sk_bzero(this, sizeof(*this));
57 return;
58 }
59 fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
60 }
61
Mike Reedf00faa32018-01-09 13:30:54 -050062 fTotal = safe.add(sizeof(SkVertices),
63 safe.add(fVSize,
64 safe.add(fTSize,
65 safe.add(fCSize,
Ruiqi Maof5101492018-06-29 14:32:21 -040066 safe.add(fBISize,
67 safe.add(fBWSize,
68 fISize))))));
Mike Reedf00faa32018-01-09 13:30:54 -050069
70 if (safe.ok()) {
Mike Reedaa9e3322017-03-16 14:38:48 -040071 fArrays = fTotal - sizeof(SkVertices); // just the sum of the arrays
Mike Reedf00faa32018-01-09 13:30:54 -050072 } else {
73 sk_bzero(this, sizeof(*this));
Mike Reedaa9e3322017-03-16 14:38:48 -040074 }
Mike Reedbdce9c22017-03-14 14:10:54 -040075 }
76
Mike Reedaa9e3322017-03-16 14:38:48 -040077 bool isValid() const { return fTotal != 0; }
78
79 size_t fTotal; // size of entire SkVertices allocation (obj + arrays)
Ruiqi Maof5101492018-06-29 14:32:21 -040080 size_t fArrays; // size of all the arrays (V + T + C + BI + BW + I)
Mike Reedaa9e3322017-03-16 14:38:48 -040081 size_t fVSize;
82 size_t fTSize;
83 size_t fCSize;
Ruiqi Maof5101492018-06-29 14:32:21 -040084 size_t fBISize;
85 size_t fBWSize;
Mike Reedaa9e3322017-03-16 14:38:48 -040086 size_t fISize;
Brian Salomoncccafe82018-04-28 16:13:08 -040087
88 // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
89 // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
90 size_t fBuilderTriFanISize;
Mike Reedaa9e3322017-03-16 14:38:48 -040091};
92
Mike Reed887cdf12017-04-03 11:11:09 -040093SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
Mike Reedaa9e3322017-03-16 14:38:48 -040094 uint32_t builderFlags) {
95 bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
96 bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
Ruiqi Maof5101492018-06-29 14:32:21 -040097 bool hasBones = SkToBool(builderFlags & SkVertices::kHasBones_BuilderFlag);
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -040098 bool isVolatile = !SkToBool(builderFlags & SkVertices::kIsNonVolatile_BuilderFlag);
99 this->init(mode, vertexCount, indexCount, isVolatile,
Ruiqi Maof5101492018-06-29 14:32:21 -0400100 SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones));
Mike Reedbdce9c22017-03-14 14:10:54 -0400101}
Mike Reed97eb4fe2017-03-14 12:04:16 -0400102
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400103SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
Mike Reedaa9e3322017-03-16 14:38:48 -0400104 const SkVertices::Sizes& sizes) {
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400105 this->init(mode, vertexCount, indexCount, isVolatile, sizes);
Mike Reed0c492cf2017-03-16 16:44:25 +0000106}
107
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400108void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
Mike Reedaa9e3322017-03-16 14:38:48 -0400109 const SkVertices::Sizes& sizes) {
110 if (!sizes.isValid()) {
111 return; // fVertices will already be null
112 }
113
114 void* storage = ::operator new (sizes.fTotal);
Brian Salomoncccafe82018-04-28 16:13:08 -0400115 if (sizes.fBuilderTriFanISize) {
116 fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
117 }
118
Mike Reedaa9e3322017-03-16 14:38:48 -0400119 fVertices.reset(new (storage) SkVertices);
120
121 // need to point past the object to store the arrays
122 char* ptr = (char*)storage + sizeof(SkVertices);
123
Ruiqi Maof5101492018-06-29 14:32:21 -0400124 fVertices->fPositions = (SkPoint*)ptr; ptr += sizes.fVSize;
125 fVertices->fTexs = sizes.fTSize ? (SkPoint*)ptr : nullptr; ptr += sizes.fTSize;
126 fVertices->fColors = sizes.fCSize ? (SkColor*)ptr : nullptr; ptr += sizes.fCSize;
127 fVertices->fBoneIndices = sizes.fBISize ? (BoneIndices*) ptr : nullptr; ptr += sizes.fBISize;
128 fVertices->fBoneWeights = sizes.fBWSize ? (BoneWeights*) ptr : nullptr; ptr += sizes.fBWSize;
Mike Reedaa9e3322017-03-16 14:38:48 -0400129 fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr;
130 fVertices->fVertexCnt = vertexCount;
131 fVertices->fIndexCnt = indexCount;
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400132 fVertices->fIsVolatile = isVolatile;
Mike Reedaa9e3322017-03-16 14:38:48 -0400133 fVertices->fMode = mode;
Ruiqi Maof5101492018-06-29 14:32:21 -0400134
Mike Reedaa9e3322017-03-16 14:38:48 -0400135 // We defer assigning fBounds and fUniqueID until detach() is called
Mike Reed97eb4fe2017-03-14 12:04:16 -0400136}
137
138sk_sp<SkVertices> SkVertices::Builder::detach() {
Mike Reedaa9e3322017-03-16 14:38:48 -0400139 if (fVertices) {
140 fVertices->fBounds.set(fVertices->fPositions, fVertices->fVertexCnt);
Brian Salomoncccafe82018-04-28 16:13:08 -0400141 if (fVertices->fMode == kTriangleFan_VertexMode) {
142 if (fIntermediateFanIndices.get()) {
143 SkASSERT(fVertices->fIndexCnt);
144 auto tempIndices = this->indices();
145 for (int t = 0; t < fVertices->fIndexCnt - 2; ++t) {
146 fVertices->fIndices[3 * t + 0] = tempIndices[0];
147 fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
148 fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
149 }
150 fVertices->fIndexCnt = 3 * (fVertices->fIndexCnt - 2);
151 } else {
152 SkASSERT(!fVertices->fIndexCnt);
153 for (int t = 0; t < fVertices->fVertexCnt - 2; ++t) {
154 fVertices->fIndices[3 * t + 0] = 0;
155 fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
156 fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
157 }
158 fVertices->fIndexCnt = 3 * (fVertices->fVertexCnt - 2);
159 }
160 fVertices->fMode = kTriangles_VertexMode;
161 }
Mike Reedaa9e3322017-03-16 14:38:48 -0400162 fVertices->fUniqueID = next_id();
163 return std::move(fVertices); // this will null fVertices after the return
Mike Reed97eb4fe2017-03-14 12:04:16 -0400164 }
Mike Reedaa9e3322017-03-16 14:38:48 -0400165 return nullptr;
Mike Reed7d9f9e32017-03-15 18:35:07 +0000166}
167
Mike Reedaa9e3322017-03-16 14:38:48 -0400168int SkVertices::Builder::vertexCount() const {
169 return fVertices ? fVertices->vertexCount() : 0;
170}
171
172int SkVertices::Builder::indexCount() const {
173 return fVertices ? fVertices->indexCount() : 0;
174}
175
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400176bool SkVertices::Builder::isVolatile() const {
177 return fVertices ? fVertices->isVolatile() : true;
178}
179
Mike Reedaa9e3322017-03-16 14:38:48 -0400180SkPoint* SkVertices::Builder::positions() {
181 return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr;
182}
183
184SkPoint* SkVertices::Builder::texCoords() {
185 return fVertices ? const_cast<SkPoint*>(fVertices->texCoords()) : nullptr;
186}
187
188SkColor* SkVertices::Builder::colors() {
189 return fVertices ? const_cast<SkColor*>(fVertices->colors()) : nullptr;
190}
191
Ruiqi Maof5101492018-06-29 14:32:21 -0400192SkVertices::BoneIndices* SkVertices::Builder::boneIndices() {
193 return fVertices ? const_cast<BoneIndices*>(fVertices->boneIndices()) : nullptr;
194}
195
196SkVertices::BoneWeights* SkVertices::Builder::boneWeights() {
197 return fVertices ? const_cast<BoneWeights*>(fVertices->boneWeights()) : nullptr;
198}
199
Mike Reedaa9e3322017-03-16 14:38:48 -0400200uint16_t* SkVertices::Builder::indices() {
Brian Salomoncccafe82018-04-28 16:13:08 -0400201 if (!fVertices) {
202 return nullptr;
203 }
204 if (fIntermediateFanIndices) {
205 return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
206 }
207 return const_cast<uint16_t*>(fVertices->indices());
Mike Reedaa9e3322017-03-16 14:38:48 -0400208}
209
Ruiqi Maoc97a3392018-08-15 10:44:19 -0400210/** Makes a copy of the SkVertices and applies a set of bones, then returns the deformed
211 vertices.
212
213 @param bones The bones to apply.
214 @param boneCount The number of bones.
215 @return The transformed SkVertices.
216*/
217sk_sp<SkVertices> SkVertices::applyBones(const SkVertices::Bone bones[], int boneCount) const {
218 // If there aren't any bones, then nothing changes.
219 // We don't check if the SkVertices object has bone indices/weights because there is the case
220 // where the object can have no indices/weights but still have a world transform applied.
221 if (!bones || !boneCount) {
222 return sk_ref_sp(this);
223 }
224 SkASSERT(boneCount >= 1);
225
226 // Copy the SkVertices.
227 sk_sp<SkVertices> copy = SkVertices::MakeCopy(this->mode(),
228 this->vertexCount(),
229 this->positions(),
230 this->texCoords(),
231 this->colors(),
232 nullptr,
233 nullptr,
234 this->indexCount(),
235 this->indices());
236
237 // Transform the positions.
238 for (int i = 0; i < this->vertexCount(); i++) {
239 SkPoint& position = copy->fPositions[i];
240
241 // Apply the world transform.
242 position = bones[0].mapPoint(position);
243
244 // Apply the bone deformations.
245 if (boneCount > 1) {
246 SkASSERT(this->boneIndices());
247 SkASSERT(this->boneWeights());
248
249 SkPoint result = SkPoint::Make(0.0f, 0.0f);
250 const SkVertices::BoneIndices& indices = this->boneIndices()[i];
251 const SkVertices::BoneWeights& weights = this->boneWeights()[i];
252 for (int j = 0; j < 4; j++) {
253 int index = indices[j];
254 float weight = weights[j];
255 if (index == 0 || weight == 0.0f) {
256 continue;
257 }
258 SkASSERT(index < boneCount);
259
260 // result += M * v * w.
261 result += bones[index].mapPoint(position) * weight;
262 }
263 position = result;
264 }
265 }
266
267 // Recalculate the bounds.
268 copy->fBounds.set(copy->fPositions, copy->fVertexCnt);
269
270 return copy;
271}
272
Mike Reedaa9e3322017-03-16 14:38:48 -0400273///////////////////////////////////////////////////////////////////////////////////////////////////
274
Mike Reed887cdf12017-04-03 11:11:09 -0400275sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
Mike Reed97eb4fe2017-03-14 12:04:16 -0400276 const SkPoint pos[], const SkPoint texs[],
Ruiqi Maof5101492018-06-29 14:32:21 -0400277 const SkColor colors[],
278 const BoneIndices boneIndices[],
279 const BoneWeights boneWeights[],
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400280 int indexCount, const uint16_t indices[],
281 bool isVolatile) {
Ruiqi Maof5101492018-06-29 14:32:21 -0400282 SkASSERT((!boneIndices && !boneWeights) || (boneIndices && boneWeights));
283 Sizes sizes(mode,
284 vertexCount,
285 indexCount,
286 texs != nullptr,
287 colors != nullptr,
288 boneIndices != nullptr);
Mike Reedaa9e3322017-03-16 14:38:48 -0400289 if (!sizes.isValid()) {
Mike Reed97eb4fe2017-03-14 12:04:16 -0400290 return nullptr;
291 }
292
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400293 Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
Mike Reedaa9e3322017-03-16 14:38:48 -0400294 SkASSERT(builder.isValid());
295
296 sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
297 sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
298 sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
Ruiqi Maof5101492018-06-29 14:32:21 -0400299 sk_careful_memcpy(builder.boneIndices(), boneIndices, sizes.fBISize);
300 sk_careful_memcpy(builder.boneWeights(), boneWeights, sizes.fBWSize);
Brian Salomoncccafe82018-04-28 16:13:08 -0400301 size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
302 sk_careful_memcpy(builder.indices(), indices, isize);
Mike Reedaa9e3322017-03-16 14:38:48 -0400303
Mike Reed97eb4fe2017-03-14 12:04:16 -0400304 return builder.detach();
305}
Mike Reedbdce9c22017-03-14 14:10:54 -0400306
Mike Reedaa9e3322017-03-16 14:38:48 -0400307size_t SkVertices::approximateSize() const {
Ruiqi Maof5101492018-06-29 14:32:21 -0400308 Sizes sizes(fMode,
309 fVertexCnt,
310 fIndexCnt,
311 this->hasTexCoords(),
312 this->hasColors(),
313 this->hasBones());
Mike Reedaa9e3322017-03-16 14:38:48 -0400314 SkASSERT(sizes.isValid());
315 return sizeof(SkVertices) + sizes.fArrays;
316}
317
Mike Reedbdce9c22017-03-14 14:10:54 -0400318///////////////////////////////////////////////////////////////////////////////////////////////////
319
Ruiqi Maoc05aa7d2018-07-03 21:18:07 +0000320// storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | boneIndices[] |
321// boneWeights[] | indices[]
Mike Reedaa9e3322017-03-16 14:38:48 -0400322// = header + arrays
Mike Reedbdce9c22017-03-14 14:10:54 -0400323
324#define kMode_Mask 0x0FF
325#define kHasTexs_Mask 0x100
326#define kHasColors_Mask 0x200
Ruiqi Maof5101492018-06-29 14:32:21 -0400327#define kHasBones_Mask 0x400
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400328#define kIsNonVolatile_Mask 0x800
Ruiqi Maoc05aa7d2018-07-03 21:18:07 +0000329#define kHeaderSize (3 * sizeof(uint32_t))
Mike Reedbdce9c22017-03-14 14:10:54 -0400330
331sk_sp<SkData> SkVertices::encode() const {
Mike Reedaa9e3322017-03-16 14:38:48 -0400332 // packed has room for addtional flags in the future (e.g. versioning)
333 uint32_t packed = static_cast<uint32_t>(fMode);
334 SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits
335 if (this->hasTexCoords()) {
336 packed |= kHasTexs_Mask;
Mike Reedbdce9c22017-03-14 14:10:54 -0400337 }
Mike Reedaa9e3322017-03-16 14:38:48 -0400338 if (this->hasColors()) {
339 packed |= kHasColors_Mask;
Mike Reedbdce9c22017-03-14 14:10:54 -0400340 }
Ruiqi Maof5101492018-06-29 14:32:21 -0400341 if (this->hasBones()) {
342 packed |= kHasBones_Mask;
343 }
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400344 if (!this->isVolatile()) {
345 packed |= kIsNonVolatile_Mask;
346 }
Mike Reedbdce9c22017-03-14 14:10:54 -0400347
Ruiqi Maof5101492018-06-29 14:32:21 -0400348 Sizes sizes(fMode,
349 fVertexCnt,
350 fIndexCnt,
351 this->hasTexCoords(),
352 this->hasColors(),
353 this->hasBones());
Mike Reedaa9e3322017-03-16 14:38:48 -0400354 SkASSERT(sizes.isValid());
Brian Salomoncccafe82018-04-28 16:13:08 -0400355 SkASSERT(!sizes.fBuilderTriFanISize);
Mike Reed6ff6af92017-04-05 17:05:16 -0400356 // need to force alignment to 4 for SkWriter32 -- will pad w/ 0s as needed
357 const size_t size = SkAlign4(kHeaderSize + sizes.fArrays);
Mike Reedbdce9c22017-03-14 14:10:54 -0400358
359 sk_sp<SkData> data = SkData::MakeUninitialized(size);
360 SkWriter32 writer(data->writable_data(), data->size());
361
Mike Reedaa9e3322017-03-16 14:38:48 -0400362 writer.write32(packed);
Mike Reedbdce9c22017-03-14 14:10:54 -0400363 writer.write32(fVertexCnt);
364 writer.write32(fIndexCnt);
Mike Reedaa9e3322017-03-16 14:38:48 -0400365 writer.write(fPositions, sizes.fVSize);
366 writer.write(fTexs, sizes.fTSize);
367 writer.write(fColors, sizes.fCSize);
Ruiqi Maof5101492018-06-29 14:32:21 -0400368 writer.write(fBoneIndices, sizes.fBISize);
369 writer.write(fBoneWeights, sizes.fBWSize);
Mike Reed6ff6af92017-04-05 17:05:16 -0400370 // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
371 writer.writePad(fIndices, sizes.fISize);
Mike Reedbdce9c22017-03-14 14:10:54 -0400372
373 return data;
374}
375
376sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
Mike Reedaa9e3322017-03-16 14:38:48 -0400377 if (length < kHeaderSize) {
378 return nullptr;
Mike Reedbdce9c22017-03-14 14:10:54 -0400379 }
380
381 SkReader32 reader(data, length);
Mike Reed165fa632018-01-23 11:50:25 -0500382 SkSafeRange safe;
Mike Reedbdce9c22017-03-14 14:10:54 -0400383
Mike Reedaa9e3322017-03-16 14:38:48 -0400384 const uint32_t packed = reader.readInt();
Mike Reedd2bc6202018-02-01 10:48:59 -0500385 const int vertexCount = safe.checkGE(reader.readInt(), 0);
386 const int indexCount = safe.checkGE(reader.readInt(), 0);
Mike Reed165fa632018-01-23 11:50:25 -0500387 const VertexMode mode = safe.checkLE<VertexMode>(packed & kMode_Mask,
388 SkVertices::kLast_VertexMode);
Mike Reedd2bc6202018-02-01 10:48:59 -0500389 if (!safe) {
390 return nullptr;
391 }
Mike Reedaa9e3322017-03-16 14:38:48 -0400392 const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
393 const bool hasColors = SkToBool(packed & kHasColors_Mask);
Ruiqi Maof5101492018-06-29 14:32:21 -0400394 const bool hasBones = SkToBool(packed & kHasBones_Mask);
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400395 const bool isVolatile = !SkToBool(packed & kIsNonVolatile_Mask);
Ruiqi Maof5101492018-06-29 14:32:21 -0400396 Sizes sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones);
Mike Reedd2bc6202018-02-01 10:48:59 -0500397 if (!sizes.isValid()) {
Mike Reedaa9e3322017-03-16 14:38:48 -0400398 return nullptr;
399 }
Mike Reed6ff6af92017-04-05 17:05:16 -0400400 // logically we can be only 2-byte aligned, but our buffer is always 4-byte aligned
401 if (SkAlign4(kHeaderSize + sizes.fArrays) != length) {
Mike Reedbdce9c22017-03-14 14:10:54 -0400402 return nullptr;
403 }
404
Ruiqi Mao9a6e42f2018-07-09 14:16:56 -0400405 Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
Mike Reedbdce9c22017-03-14 14:10:54 -0400406
Mike Reedaa9e3322017-03-16 14:38:48 -0400407 reader.read(builder.positions(), sizes.fVSize);
408 reader.read(builder.texCoords(), sizes.fTSize);
409 reader.read(builder.colors(), sizes.fCSize);
Ruiqi Maof5101492018-06-29 14:32:21 -0400410 reader.read(builder.boneIndices(), sizes.fBISize);
411 reader.read(builder.boneWeights(), sizes.fBWSize);
Brian Salomoncccafe82018-04-28 16:13:08 -0400412 size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
413 reader.read(builder.indices(), isize);
Mike Reedd2bc6202018-02-01 10:48:59 -0500414 if (indexCount > 0) {
415 // validate that the indicies are in range
416 SkASSERT(indexCount == builder.indexCount());
417 const uint16_t* indices = builder.indices();
418 for (int i = 0; i < indexCount; ++i) {
419 if (indices[i] >= (unsigned)vertexCount) {
420 return nullptr;
421 }
422 }
423 }
Mike Reedbdce9c22017-03-14 14:10:54 -0400424 return builder.detach();
425}
Yong-Hwan Baek701a3ca2018-04-20 21:44:43 +0900426
427void SkVertices::operator delete(void* p)
428{
429 ::operator delete(p);
430}