Home | History | Annotate | Download | only in core
      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