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 "SkAtomics.h" 9 #include "SkVertices.h" 10 #include "SkData.h" 11 #include "SkReader32.h" 12 #include "SkWriter32.h" 13 14 static int32_t gNextID = 1; 15 static int32_t next_id() { 16 int32_t id; 17 do { 18 id = sk_atomic_inc(&gNextID); 19 } while (id == SK_InvalidGenID); 20 return id; 21 } 22 23 struct SkVertices::Sizes { 24 Sizes(int vertexCount, int indexCount, bool hasTexs, bool hasColors) { 25 int64_t vSize = (int64_t)vertexCount * sizeof(SkPoint); 26 int64_t tSize = hasTexs ? (int64_t)vertexCount * sizeof(SkPoint) : 0; 27 int64_t cSize = hasColors ? (int64_t)vertexCount * sizeof(SkColor) : 0; 28 int64_t iSize = (int64_t)indexCount * sizeof(uint16_t); 29 30 int64_t total = sizeof(SkVertices) + vSize + tSize + cSize + iSize; 31 if (!sk_64_isS32(total)) { 32 sk_bzero(this, sizeof(*this)); 33 } else { 34 fTotal = SkToSizeT(total); 35 fVSize = SkToSizeT(vSize); 36 fTSize = SkToSizeT(tSize); 37 fCSize = SkToSizeT(cSize); 38 fISize = SkToSizeT(iSize); 39 fArrays = fTotal - sizeof(SkVertices); // just the sum of the arrays 40 } 41 } 42 43 bool isValid() const { return fTotal != 0; } 44 45 size_t fTotal; // size of entire SkVertices allocation (obj + arrays) 46 size_t fArrays; // size of all the arrays (V + T + C + I) 47 size_t fVSize; 48 size_t fTSize; 49 size_t fCSize; 50 size_t fISize; 51 }; 52 53 SkVertices::Builder::Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, 54 uint32_t builderFlags) { 55 bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag); 56 bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag); 57 this->init(mode, vertexCount, indexCount, 58 SkVertices::Sizes(vertexCount, indexCount, hasTexs, hasColors)); 59 } 60 61 SkVertices::Builder::Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, 62 const SkVertices::Sizes& sizes) { 63 this->init(mode, vertexCount, indexCount, sizes); 64 } 65 66 void SkVertices::Builder::init(SkCanvas::VertexMode mode, int vertexCount, int indexCount, 67 const SkVertices::Sizes& sizes) { 68 if (!sizes.isValid()) { 69 return; // fVertices will already be null 70 } 71 72 void* storage = ::operator new (sizes.fTotal); 73 fVertices.reset(new (storage) SkVertices); 74 75 // need to point past the object to store the arrays 76 char* ptr = (char*)storage + sizeof(SkVertices); 77 78 fVertices->fPositions = (SkPoint*)ptr; ptr += sizes.fVSize; 79 fVertices->fTexs = sizes.fTSize ? (SkPoint*)ptr : nullptr; ptr += sizes.fTSize; 80 fVertices->fColors = sizes.fCSize ? (SkColor*)ptr : nullptr; ptr += sizes.fCSize; 81 fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr; 82 fVertices->fVertexCnt = vertexCount; 83 fVertices->fIndexCnt = indexCount; 84 fVertices->fMode = mode; 85 // We defer assigning fBounds and fUniqueID until detach() is called 86 } 87 88 sk_sp<SkVertices> SkVertices::Builder::detach() { 89 if (fVertices) { 90 fVertices->fBounds.set(fVertices->fPositions, fVertices->fVertexCnt); 91 fVertices->fUniqueID = next_id(); 92 return std::move(fVertices); // this will null fVertices after the return 93 } 94 return nullptr; 95 } 96 97 int SkVertices::Builder::vertexCount() const { 98 return fVertices ? fVertices->vertexCount() : 0; 99 } 100 101 int SkVertices::Builder::indexCount() const { 102 return fVertices ? fVertices->indexCount() : 0; 103 } 104 105 SkPoint* SkVertices::Builder::positions() { 106 return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr; 107 } 108 109 SkPoint* SkVertices::Builder::texCoords() { 110 return fVertices ? const_cast<SkPoint*>(fVertices->texCoords()) : nullptr; 111 } 112 113 SkColor* SkVertices::Builder::colors() { 114 return fVertices ? const_cast<SkColor*>(fVertices->colors()) : nullptr; 115 } 116 117 uint16_t* SkVertices::Builder::indices() { 118 return fVertices ? const_cast<uint16_t*>(fVertices->indices()) : nullptr; 119 } 120 121 /////////////////////////////////////////////////////////////////////////////////////////////////// 122 123 sk_sp<SkVertices> SkVertices::MakeCopy(SkCanvas::VertexMode mode, int vertexCount, 124 const SkPoint pos[], const SkPoint texs[], 125 const SkColor colors[], int indexCount, 126 const uint16_t indices[]) { 127 Sizes sizes(vertexCount, indexCount, texs != nullptr, colors != nullptr); 128 if (!sizes.isValid()) { 129 return nullptr; 130 } 131 132 Builder builder(mode, vertexCount, indexCount, sizes); 133 SkASSERT(builder.isValid()); 134 135 sk_careful_memcpy(builder.positions(), pos, sizes.fVSize); 136 sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize); 137 sk_careful_memcpy(builder.colors(), colors, sizes.fCSize); 138 sk_careful_memcpy(builder.indices(), indices, sizes.fISize); 139 140 return builder.detach(); 141 } 142 143 size_t SkVertices::approximateSize() const { 144 Sizes sizes(fVertexCnt, fIndexCnt, this->hasTexCoords(), this->hasColors()); 145 SkASSERT(sizes.isValid()); 146 return sizeof(SkVertices) + sizes.fArrays; 147 } 148 149 /////////////////////////////////////////////////////////////////////////////////////////////////// 150 151 // storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | indices[] 152 // = header + arrays 153 154 #define kMode_Mask 0x0FF 155 #define kHasTexs_Mask 0x100 156 #define kHasColors_Mask 0x200 157 #define kHeaderSize (3 * sizeof(uint32_t)) 158 159 sk_sp<SkData> SkVertices::encode() const { 160 // packed has room for addtional flags in the future (e.g. versioning) 161 uint32_t packed = static_cast<uint32_t>(fMode); 162 SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits 163 if (this->hasTexCoords()) { 164 packed |= kHasTexs_Mask; 165 } 166 if (this->hasColors()) { 167 packed |= kHasColors_Mask; 168 } 169 170 Sizes sizes(fVertexCnt, fIndexCnt, this->hasTexCoords(), this->hasColors()); 171 SkASSERT(sizes.isValid()); 172 const size_t size = kHeaderSize + sizes.fArrays; 173 174 sk_sp<SkData> data = SkData::MakeUninitialized(size); 175 SkWriter32 writer(data->writable_data(), data->size()); 176 177 writer.write32(packed); 178 writer.write32(fVertexCnt); 179 writer.write32(fIndexCnt); 180 writer.write(fPositions, sizes.fVSize); 181 writer.write(fTexs, sizes.fTSize); 182 writer.write(fColors, sizes.fCSize); 183 writer.write(fIndices, sizes.fISize); 184 185 return data; 186 } 187 188 sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) { 189 if (length < kHeaderSize) { 190 return nullptr; 191 } 192 193 SkReader32 reader(data, length); 194 195 const uint32_t packed = reader.readInt(); 196 const int vertexCount = reader.readInt(); 197 const int indexCount = reader.readInt(); 198 199 const SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(packed & kMode_Mask); 200 const bool hasTexs = SkToBool(packed & kHasTexs_Mask); 201 const bool hasColors = SkToBool(packed & kHasColors_Mask); 202 Sizes sizes(vertexCount, indexCount, hasTexs, hasColors); 203 if (!sizes.isValid()) { 204 return nullptr; 205 } 206 if (kHeaderSize + sizes.fArrays != length) { 207 return nullptr; 208 } 209 210 Builder builder(mode, vertexCount, indexCount, sizes); 211 212 reader.read(builder.positions(), sizes.fVSize); 213 reader.read(builder.texCoords(), sizes.fTSize); 214 reader.read(builder.colors(), sizes.fCSize); 215 reader.read(builder.indices(), sizes.fISize); 216 217 return builder.detach(); 218 } 219