SkVertices.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. #include "include/core/SkData.h"
  9. #include "include/private/SkTo.h"
  10. #include "src/core/SkReader32.h"
  11. #include "src/core/SkSafeMath.h"
  12. #include "src/core/SkSafeRange.h"
  13. #include "src/core/SkWriter32.h"
  14. #include <atomic>
  15. #include <new>
  16. static int32_t next_id() {
  17. static std::atomic<int32_t> nextID{1};
  18. int32_t id;
  19. do {
  20. id = nextID++;
  21. } while (id == SK_InvalidGenID);
  22. return id;
  23. }
  24. struct SkVertices::Sizes {
  25. Sizes(SkVertices::VertexMode mode, int vertexCount, int indexCount, bool hasTexs,
  26. bool hasColors, bool hasBones) {
  27. SkSafeMath safe;
  28. fVSize = safe.mul(vertexCount, sizeof(SkPoint));
  29. fTSize = hasTexs ? safe.mul(vertexCount, sizeof(SkPoint)) : 0;
  30. fCSize = hasColors ? safe.mul(vertexCount, sizeof(SkColor)) : 0;
  31. fBISize = hasBones ? safe.mul(vertexCount, sizeof(BoneIndices)) : 0;
  32. fBWSize = hasBones ? safe.mul(vertexCount, sizeof(BoneWeights)) : 0;
  33. fBuilderTriFanISize = 0;
  34. fISize = safe.mul(indexCount, sizeof(uint16_t));
  35. if (kTriangleFan_VertexMode == mode) {
  36. int numFanTris = 0;
  37. if (indexCount) {
  38. fBuilderTriFanISize = fISize;
  39. numFanTris = indexCount - 2;
  40. } else {
  41. numFanTris = vertexCount - 2;
  42. // By forcing this to become indexed we are adding a constraint to the maximum
  43. // number of vertices.
  44. if (vertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
  45. sk_bzero(this, sizeof(*this));
  46. return;
  47. }
  48. }
  49. if (numFanTris <= 0) {
  50. sk_bzero(this, sizeof(*this));
  51. return;
  52. }
  53. fISize = safe.mul(numFanTris, 3 * sizeof(uint16_t));
  54. }
  55. fTotal = safe.add(sizeof(SkVertices),
  56. safe.add(fVSize,
  57. safe.add(fTSize,
  58. safe.add(fCSize,
  59. safe.add(fBISize,
  60. safe.add(fBWSize,
  61. fISize))))));
  62. if (safe.ok()) {
  63. fArrays = fTotal - sizeof(SkVertices); // just the sum of the arrays
  64. } else {
  65. sk_bzero(this, sizeof(*this));
  66. }
  67. }
  68. bool isValid() const { return fTotal != 0; }
  69. size_t fTotal; // size of entire SkVertices allocation (obj + arrays)
  70. size_t fArrays; // size of all the arrays (V + T + C + BI + BW + I)
  71. size_t fVSize;
  72. size_t fTSize;
  73. size_t fCSize;
  74. size_t fBISize;
  75. size_t fBWSize;
  76. size_t fISize;
  77. // For indexed tri-fans this is the number of amount of space fo indices needed in the builder
  78. // before conversion to indexed triangles (or zero if not indexed or not a triangle fan).
  79. size_t fBuilderTriFanISize;
  80. };
  81. SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
  82. uint32_t builderFlags) {
  83. bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
  84. bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
  85. bool hasBones = SkToBool(builderFlags & SkVertices::kHasBones_BuilderFlag);
  86. bool isVolatile = !SkToBool(builderFlags & SkVertices::kIsNonVolatile_BuilderFlag);
  87. this->init(mode, vertexCount, indexCount, isVolatile,
  88. SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones));
  89. }
  90. SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
  91. const SkVertices::Sizes& sizes) {
  92. this->init(mode, vertexCount, indexCount, isVolatile, sizes);
  93. }
  94. void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
  95. const SkVertices::Sizes& sizes) {
  96. if (!sizes.isValid()) {
  97. return; // fVertices will already be null
  98. }
  99. void* storage = ::operator new (sizes.fTotal);
  100. if (sizes.fBuilderTriFanISize) {
  101. fIntermediateFanIndices.reset(new uint8_t[sizes.fBuilderTriFanISize]);
  102. }
  103. fVertices.reset(new (storage) SkVertices);
  104. // need to point past the object to store the arrays
  105. char* ptr = (char*)storage + sizeof(SkVertices);
  106. fVertices->fPositions = (SkPoint*)ptr; ptr += sizes.fVSize;
  107. fVertices->fTexs = sizes.fTSize ? (SkPoint*)ptr : nullptr; ptr += sizes.fTSize;
  108. fVertices->fColors = sizes.fCSize ? (SkColor*)ptr : nullptr; ptr += sizes.fCSize;
  109. fVertices->fBoneIndices = sizes.fBISize ? (BoneIndices*) ptr : nullptr; ptr += sizes.fBISize;
  110. fVertices->fBoneWeights = sizes.fBWSize ? (BoneWeights*) ptr : nullptr; ptr += sizes.fBWSize;
  111. fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr;
  112. fVertices->fVertexCnt = vertexCount;
  113. fVertices->fIndexCnt = indexCount;
  114. fVertices->fIsVolatile = isVolatile;
  115. fVertices->fMode = mode;
  116. // We defer assigning fBounds and fUniqueID until detach() is called
  117. }
  118. sk_sp<SkVertices> SkVertices::Builder::detach() {
  119. if (fVertices) {
  120. fVertices->fBounds.set(fVertices->fPositions, fVertices->fVertexCnt);
  121. if (fVertices->fMode == kTriangleFan_VertexMode) {
  122. if (fIntermediateFanIndices.get()) {
  123. SkASSERT(fVertices->fIndexCnt);
  124. auto tempIndices = this->indices();
  125. for (int t = 0; t < fVertices->fIndexCnt - 2; ++t) {
  126. fVertices->fIndices[3 * t + 0] = tempIndices[0];
  127. fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
  128. fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
  129. }
  130. fVertices->fIndexCnt = 3 * (fVertices->fIndexCnt - 2);
  131. } else {
  132. SkASSERT(!fVertices->fIndexCnt);
  133. for (int t = 0; t < fVertices->fVertexCnt - 2; ++t) {
  134. fVertices->fIndices[3 * t + 0] = 0;
  135. fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
  136. fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
  137. }
  138. fVertices->fIndexCnt = 3 * (fVertices->fVertexCnt - 2);
  139. }
  140. fVertices->fMode = kTriangles_VertexMode;
  141. }
  142. fVertices->fUniqueID = next_id();
  143. return std::move(fVertices); // this will null fVertices after the return
  144. }
  145. return nullptr;
  146. }
  147. int SkVertices::Builder::vertexCount() const {
  148. return fVertices ? fVertices->vertexCount() : 0;
  149. }
  150. int SkVertices::Builder::indexCount() const {
  151. return fVertices ? fVertices->indexCount() : 0;
  152. }
  153. bool SkVertices::Builder::isVolatile() const {
  154. return fVertices ? fVertices->isVolatile() : true;
  155. }
  156. SkPoint* SkVertices::Builder::positions() {
  157. return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr;
  158. }
  159. SkPoint* SkVertices::Builder::texCoords() {
  160. return fVertices ? const_cast<SkPoint*>(fVertices->texCoords()) : nullptr;
  161. }
  162. SkColor* SkVertices::Builder::colors() {
  163. return fVertices ? const_cast<SkColor*>(fVertices->colors()) : nullptr;
  164. }
  165. SkVertices::BoneIndices* SkVertices::Builder::boneIndices() {
  166. return fVertices ? const_cast<BoneIndices*>(fVertices->boneIndices()) : nullptr;
  167. }
  168. SkVertices::BoneWeights* SkVertices::Builder::boneWeights() {
  169. return fVertices ? const_cast<BoneWeights*>(fVertices->boneWeights()) : nullptr;
  170. }
  171. uint16_t* SkVertices::Builder::indices() {
  172. if (!fVertices) {
  173. return nullptr;
  174. }
  175. if (fIntermediateFanIndices) {
  176. return reinterpret_cast<uint16_t*>(fIntermediateFanIndices.get());
  177. }
  178. return const_cast<uint16_t*>(fVertices->indices());
  179. }
  180. /** Makes a copy of the SkVertices and applies a set of bones, then returns the deformed
  181. vertices.
  182. @param bones The bones to apply.
  183. @param boneCount The number of bones.
  184. @return The transformed SkVertices.
  185. */
  186. sk_sp<SkVertices> SkVertices::applyBones(const SkVertices::Bone bones[], int boneCount) const {
  187. // If there aren't any bones, then nothing changes.
  188. // We don't check if the SkVertices object has bone indices/weights because there is the case
  189. // where the object can have no indices/weights but still have a world transform applied.
  190. if (!bones || !boneCount) {
  191. return sk_ref_sp(this);
  192. }
  193. SkASSERT(boneCount >= 1);
  194. // Copy the SkVertices.
  195. sk_sp<SkVertices> copy = SkVertices::MakeCopy(this->mode(),
  196. this->vertexCount(),
  197. this->positions(),
  198. this->texCoords(),
  199. this->colors(),
  200. nullptr,
  201. nullptr,
  202. this->indexCount(),
  203. this->indices());
  204. // Transform the positions.
  205. for (int i = 0; i < this->vertexCount(); i++) {
  206. SkPoint& position = copy->fPositions[i];
  207. // Apply the world transform.
  208. position = bones[0].mapPoint(position);
  209. // Apply the bone deformations.
  210. if (boneCount > 1) {
  211. SkASSERT(this->boneIndices());
  212. SkASSERT(this->boneWeights());
  213. SkPoint result = SkPoint::Make(0.0f, 0.0f);
  214. const SkVertices::BoneIndices& indices = this->boneIndices()[i];
  215. const SkVertices::BoneWeights& weights = this->boneWeights()[i];
  216. for (int j = 0; j < 4; j++) {
  217. int index = indices[j];
  218. float weight = weights[j];
  219. if (index == 0 || weight == 0.0f) {
  220. continue;
  221. }
  222. SkASSERT(index < boneCount);
  223. // result += M * v * w.
  224. result += bones[index].mapPoint(position) * weight;
  225. }
  226. position = result;
  227. }
  228. }
  229. // Recalculate the bounds.
  230. copy->fBounds.set(copy->fPositions, copy->fVertexCnt);
  231. return copy;
  232. }
  233. ///////////////////////////////////////////////////////////////////////////////////////////////////
  234. sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
  235. const SkPoint pos[], const SkPoint texs[],
  236. const SkColor colors[],
  237. const BoneIndices boneIndices[],
  238. const BoneWeights boneWeights[],
  239. int indexCount, const uint16_t indices[],
  240. bool isVolatile) {
  241. SkASSERT((!boneIndices && !boneWeights) || (boneIndices && boneWeights));
  242. Sizes sizes(mode,
  243. vertexCount,
  244. indexCount,
  245. texs != nullptr,
  246. colors != nullptr,
  247. boneIndices != nullptr);
  248. if (!sizes.isValid()) {
  249. return nullptr;
  250. }
  251. Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
  252. SkASSERT(builder.isValid());
  253. sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
  254. sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize);
  255. sk_careful_memcpy(builder.colors(), colors, sizes.fCSize);
  256. sk_careful_memcpy(builder.boneIndices(), boneIndices, sizes.fBISize);
  257. sk_careful_memcpy(builder.boneWeights(), boneWeights, sizes.fBWSize);
  258. size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
  259. sk_careful_memcpy(builder.indices(), indices, isize);
  260. return builder.detach();
  261. }
  262. size_t SkVertices::approximateSize() const {
  263. Sizes sizes(fMode,
  264. fVertexCnt,
  265. fIndexCnt,
  266. this->hasTexCoords(),
  267. this->hasColors(),
  268. this->hasBones());
  269. SkASSERT(sizes.isValid());
  270. return sizeof(SkVertices) + sizes.fArrays;
  271. }
  272. ///////////////////////////////////////////////////////////////////////////////////////////////////
  273. // storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | boneIndices[] |
  274. // boneWeights[] | indices[]
  275. // = header + arrays
  276. #define kMode_Mask 0x0FF
  277. #define kHasTexs_Mask 0x100
  278. #define kHasColors_Mask 0x200
  279. #define kHasBones_Mask 0x400
  280. #define kIsNonVolatile_Mask 0x800
  281. #define kHeaderSize (3 * sizeof(uint32_t))
  282. sk_sp<SkData> SkVertices::encode() const {
  283. // packed has room for addtional flags in the future (e.g. versioning)
  284. uint32_t packed = static_cast<uint32_t>(fMode);
  285. SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits
  286. if (this->hasTexCoords()) {
  287. packed |= kHasTexs_Mask;
  288. }
  289. if (this->hasColors()) {
  290. packed |= kHasColors_Mask;
  291. }
  292. if (this->hasBones()) {
  293. packed |= kHasBones_Mask;
  294. }
  295. if (!this->isVolatile()) {
  296. packed |= kIsNonVolatile_Mask;
  297. }
  298. Sizes sizes(fMode,
  299. fVertexCnt,
  300. fIndexCnt,
  301. this->hasTexCoords(),
  302. this->hasColors(),
  303. this->hasBones());
  304. SkASSERT(sizes.isValid());
  305. SkASSERT(!sizes.fBuilderTriFanISize);
  306. // need to force alignment to 4 for SkWriter32 -- will pad w/ 0s as needed
  307. const size_t size = SkAlign4(kHeaderSize + sizes.fArrays);
  308. sk_sp<SkData> data = SkData::MakeUninitialized(size);
  309. SkWriter32 writer(data->writable_data(), data->size());
  310. writer.write32(packed);
  311. writer.write32(fVertexCnt);
  312. writer.write32(fIndexCnt);
  313. writer.write(fPositions, sizes.fVSize);
  314. writer.write(fTexs, sizes.fTSize);
  315. writer.write(fColors, sizes.fCSize);
  316. writer.write(fBoneIndices, sizes.fBISize);
  317. writer.write(fBoneWeights, sizes.fBWSize);
  318. // if index-count is odd, we won't be 4-bytes aligned, so we call the pad version
  319. writer.writePad(fIndices, sizes.fISize);
  320. return data;
  321. }
  322. sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
  323. if (length < kHeaderSize) {
  324. return nullptr;
  325. }
  326. SkReader32 reader(data, length);
  327. SkSafeRange safe;
  328. const uint32_t packed = reader.readInt();
  329. const int vertexCount = safe.checkGE(reader.readInt(), 0);
  330. const int indexCount = safe.checkGE(reader.readInt(), 0);
  331. const VertexMode mode = safe.checkLE<VertexMode>(packed & kMode_Mask,
  332. SkVertices::kLast_VertexMode);
  333. if (!safe) {
  334. return nullptr;
  335. }
  336. const bool hasTexs = SkToBool(packed & kHasTexs_Mask);
  337. const bool hasColors = SkToBool(packed & kHasColors_Mask);
  338. const bool hasBones = SkToBool(packed & kHasBones_Mask);
  339. const bool isVolatile = !SkToBool(packed & kIsNonVolatile_Mask);
  340. Sizes sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones);
  341. if (!sizes.isValid()) {
  342. return nullptr;
  343. }
  344. // logically we can be only 2-byte aligned, but our buffer is always 4-byte aligned
  345. if (SkAlign4(kHeaderSize + sizes.fArrays) != length) {
  346. return nullptr;
  347. }
  348. Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
  349. reader.read(builder.positions(), sizes.fVSize);
  350. reader.read(builder.texCoords(), sizes.fTSize);
  351. reader.read(builder.colors(), sizes.fCSize);
  352. reader.read(builder.boneIndices(), sizes.fBISize);
  353. reader.read(builder.boneWeights(), sizes.fBWSize);
  354. size_t isize = (mode == kTriangleFan_VertexMode) ? sizes.fBuilderTriFanISize : sizes.fISize;
  355. reader.read(builder.indices(), isize);
  356. if (indexCount > 0) {
  357. // validate that the indicies are in range
  358. SkASSERT(indexCount == builder.indexCount());
  359. const uint16_t* indices = builder.indices();
  360. for (int i = 0; i < indexCount; ++i) {
  361. if (indices[i] >= (unsigned)vertexCount) {
  362. return nullptr;
  363. }
  364. }
  365. }
  366. return builder.detach();
  367. }
  368. void SkVertices::operator delete(void* p)
  369. {
  370. ::operator delete(p);
  371. }