From eaaebb19a17d213355e7a70e0cfabe4ba61929d4 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Wed, 15 Mar 2017 12:19:07 -0400 Subject: store vertices arrays inline with object Also unify some of naming (esp. around texCoords) BUG=skia:6366 Change-Id: I5a6793f029cccf0cd0a2c1d180b259ce4eab526f Reviewed-on: https://skia-review.googlesource.com/9705 Commit-Queue: Mike Reed Reviewed-by: Brian Salomon --- src/core/SkVertices.cpp | 267 ++++++++++++++++++++++++------------------------ 1 file changed, 132 insertions(+), 135 deletions(-) (limited to 'src/core') diff --git a/src/core/SkVertices.cpp b/src/core/SkVertices.cpp index 936d70dc09..1980b7ea5c 100644 --- a/src/core/SkVertices.cpp +++ b/src/core/SkVertices.cpp @@ -20,202 +20,199 @@ static int32_t next_id() { return id; } -static size_t compute_arrays_size(int vertexCount, int indexCount, uint32_t builderFlags) { - if (vertexCount < 0 || indexCount < 0) { - return 0; // signal error - } +struct SkVertices::Sizes { + Sizes(int vertexCount, int indexCount, bool hasTexs, bool hasColors) { + int64_t vSize = (int64_t)vertexCount * sizeof(SkPoint); + int64_t tSize = hasTexs ? (int64_t)vertexCount * sizeof(SkPoint) : 0; + int64_t cSize = hasColors ? (int64_t)vertexCount * sizeof(SkColor) : 0; + int64_t iSize = (int64_t)indexCount * sizeof(uint16_t); + + int64_t total = sizeof(SkVertices) + vSize + tSize + cSize + iSize; + if (!sk_64_isS32(total)) { + sk_bzero(this, sizeof(*this)); + } else { + fTotal = SkToSizeT(total); + fVSize = SkToSizeT(vSize); + fTSize = SkToSizeT(tSize); + fCSize = SkToSizeT(cSize); + fISize = SkToSizeT(iSize); + fArrays = fTotal - sizeof(SkVertices); // just the sum of the arrays + } + } + + bool isValid() const { return fTotal != 0; } + + size_t fTotal; // size of entire SkVertices allocation (obj + arrays) + size_t fArrays; // size of all the arrays (V + T + C + I) + size_t fVSize; + size_t fTSize; + size_t fCSize; + size_t fISize; +}; - uint64_t size = vertexCount * sizeof(SkPoint); - if (builderFlags & SkVertices::kHasTexs_Flag) { - size += vertexCount * sizeof(SkPoint); - } - if (builderFlags & SkVertices::kHasColors_Flag) { - size += vertexCount * sizeof(SkColor); - } - size += indexCount * sizeof(uint16_t); - if (!sk_64_isS32(size)) { - return 0; // signal error - } - return (size_t)size; +SkVertices::Builder::Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, + uint32_t builderFlags) { + bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag); + bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag); + this->init(mode, vertexCount, indexCount, + SkVertices::Sizes(vertexCount, indexCount, hasTexs, hasColors)); } SkVertices::Builder::Builder(SkCanvas::VertexMode mode, int vertexCount, int indexCount, - uint32_t flags) { - fPositions = nullptr; // signal that we have nothing to cleanup - fColors = nullptr; - fTexs = nullptr; - fIndices = nullptr; - fVertexCnt = 0; - fIndexCnt = 0; - - size_t size = compute_arrays_size(vertexCount, indexCount, flags); - if (0 == size) { - return; + const SkVertices::Sizes& sizes) { + this->init(mode, vertexCount, indexCount, sizes); +} + +void SkVertices::Builder::init(SkCanvas::VertexMode mode, int vertexCount, int indexCount, + const SkVertices::Sizes& sizes) { + if (!sizes.isValid()) { + return; // fVertices will already be null } - char* ptr = (char*)sk_malloc_throw(sk_64_asS32(size)); + void* storage = ::operator new (sizes.fTotal); + fVertices.reset(new (storage) SkVertices); - fMode = mode; - fVertexCnt = vertexCount; - fIndexCnt = indexCount; - fPositions = (SkPoint*)ptr; // owner - ptr += vertexCount * sizeof(SkPoint); + // need to point past the object to store the arrays + char* ptr = (char*)fVertices.get() + sizeof(SkVertices); - if (flags & kHasTexs_Flag) { - fTexs = (SkPoint*)ptr; - ptr += vertexCount * sizeof(SkPoint); - } - if (flags & kHasColors_Flag) { - fColors = (SkColor*)ptr; - ptr += vertexCount * sizeof(SkColor); - } - if (indexCount) { - fIndices = (uint16_t*)ptr; + fVertices->fPositions = (SkPoint*)ptr; ptr += sizes.fVSize; + fVertices->fTexs = sizes.fTSize ? (SkPoint*)ptr : nullptr; ptr += sizes.fTSize; + fVertices->fColors = sizes.fCSize ? (SkColor*)ptr : nullptr; ptr += sizes.fCSize; + fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr; + fVertices->fVertexCnt = vertexCount; + fVertices->fIndexCnt = indexCount; + fVertices->fMode = mode; + // We defer assigning fBounds and fUniqueID until detach() is called +} + +sk_sp SkVertices::Builder::detach() { + if (fVertices) { + fVertices->fBounds.set(fVertices->fPositions, fVertices->fVertexCnt); + fVertices->fUniqueID = next_id(); + return std::move(fVertices); // this will null fVertices after the return } + return nullptr; } -SkVertices::Builder::~Builder() { - sk_free(fPositions); +int SkVertices::Builder::vertexCount() const { + return fVertices ? fVertices->vertexCount() : 0; } -sk_sp SkVertices::Builder::detach() { - if (!fPositions) { - return nullptr; - } +int SkVertices::Builder::indexCount() const { + return fVertices ? fVertices->indexCount() : 0; +} - SkVertices* obj = new SkVertices; - obj->fPositions = fPositions; // owner of storage, use sk_free - obj->fTexs = fTexs; - obj->fColors = fColors; - obj->fIndices = fIndices; - obj->fBounds.set(fPositions, fVertexCnt); - obj->fUniqueID = next_id(); - obj->fVertexCnt = fVertexCnt; - obj->fIndexCnt = fIndexCnt; - obj->fMode = fMode; +SkPoint* SkVertices::Builder::positions() { + return fVertices ? const_cast(fVertices->positions()) : nullptr; +} - fPositions = nullptr; // so we don't free the memory, now that obj owns it +SkPoint* SkVertices::Builder::texCoords() { + return fVertices ? const_cast(fVertices->texCoords()) : nullptr; +} + +SkColor* SkVertices::Builder::colors() { + return fVertices ? const_cast(fVertices->colors()) : nullptr; +} - return sk_sp(obj); +uint16_t* SkVertices::Builder::indices() { + return fVertices ? const_cast(fVertices->indices()) : nullptr; } +/////////////////////////////////////////////////////////////////////////////////////////////////// + sk_sp SkVertices::MakeCopy(SkCanvas::VertexMode mode, int vertexCount, const SkPoint pos[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[]) { - uint32_t flags = 0; - if (texs) { - flags |= kHasTexs_Flag; - } - if (colors) { - flags |= kHasColors_Flag; - } - Builder builder(mode, vertexCount, indexCount, flags); - if (!builder.isValid()) { + Sizes sizes(vertexCount, indexCount, texs != nullptr, colors != nullptr); + if (!sizes.isValid()) { return nullptr; } - memcpy(builder.positions(), pos, vertexCount * sizeof(SkPoint)); - if (texs) { - memcpy(builder.texCoords(), texs, vertexCount * sizeof(SkPoint)); - } - if (colors) { - memcpy(builder.colors(), colors, vertexCount * sizeof(SkColor)); - } - if (indices) { - memcpy(builder.indices(), indices, indexCount * sizeof(uint16_t)); - } + Builder builder(mode, vertexCount, indexCount, sizes); + SkASSERT(builder.isValid()); + + sk_careful_memcpy(builder.positions(), pos, sizes.fVSize); + sk_careful_memcpy(builder.texCoords(), texs, sizes.fTSize); + sk_careful_memcpy(builder.colors(), colors, sizes.fCSize); + sk_careful_memcpy(builder.indices(), indices, sizes.fISize); + return builder.detach(); } +size_t SkVertices::approximateSize() const { + Sizes sizes(fVertexCnt, fIndexCnt, this->hasTexCoords(), this->hasColors()); + SkASSERT(sizes.isValid()); + return sizeof(SkVertices) + sizes.fArrays; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// -// storage = flags | vertex_count | index_count | pos[] | texs[] | colors[] | indices[] +// storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | indices[] +// = header + arrays #define kMode_Mask 0x0FF #define kHasTexs_Mask 0x100 #define kHasColors_Mask 0x200 +#define kHeaderSize (3 * sizeof(uint32_t)) sk_sp SkVertices::encode() const { - uint32_t flags = static_cast(fMode); - SkASSERT((flags & ~kMode_Mask) == 0); - if (fTexs) { - flags |= kHasTexs_Mask; + // packed has room for addtional flags in the future (e.g. versioning) + uint32_t packed = static_cast(fMode); + SkASSERT((packed & ~kMode_Mask) == 0); // our mode fits in the mask bits + if (this->hasTexCoords()) { + packed |= kHasTexs_Mask; } - if (fColors) { - flags |= kHasColors_Mask; + if (this->hasColors()) { + packed |= kHasColors_Mask; } - size_t size = sizeof(uint32_t) * 3; // flags | verts_count | indices_count - size += fVertexCnt * sizeof(SkPoint); - if (fTexs) { - size += fVertexCnt * sizeof(SkPoint); - } - if (fColors) { - size += fVertexCnt * sizeof(SkColor); - } - size += fIndexCnt * sizeof(uint16_t); + Sizes sizes(fVertexCnt, fIndexCnt, this->hasTexCoords(), this->hasColors()); + SkASSERT(sizes.isValid()); + const size_t size = kHeaderSize + sizes.fArrays; sk_sp data = SkData::MakeUninitialized(size); SkWriter32 writer(data->writable_data(), data->size()); - writer.write32(flags); + writer.write32(packed); writer.write32(fVertexCnt); writer.write32(fIndexCnt); - writer.write(fPositions, fVertexCnt * sizeof(SkPoint)); - if (fTexs) { - writer.write(fTexs, fVertexCnt * sizeof(SkPoint)); - } - if (fColors) { - writer.write(fColors, fVertexCnt * sizeof(SkColor)); - } - writer.write(fIndices, fIndexCnt * sizeof(uint16_t)); + writer.write(fPositions, sizes.fVSize); + writer.write(fTexs, sizes.fTSize); + writer.write(fColors, sizes.fCSize); + writer.write(fIndices, sizes.fISize); return data; } sk_sp SkVertices::Decode(const void* data, size_t length) { - if (length < 3 * sizeof(uint32_t)) { - return nullptr; // buffer too small + if (length < kHeaderSize) { + return nullptr; } SkReader32 reader(data, length); - uint32_t storageFlags = reader.readInt(); - SkCanvas::VertexMode mode = static_cast(storageFlags & kMode_Mask); - int vertexCount = reader.readInt(); - int indexCount = reader.readInt(); - uint32_t builderFlags = 0; - if (storageFlags & kHasTexs_Mask) { - builderFlags |= SkVertices::kHasTexs_Flag; - } - if (storageFlags & kHasColors_Mask) { - builderFlags |= SkVertices::kHasColors_Flag; - } + const uint32_t packed = reader.readInt(); + const int vertexCount = reader.readInt(); + const int indexCount = reader.readInt(); - size_t size = compute_arrays_size(vertexCount, indexCount, builderFlags); - if (0 == size) { + const SkCanvas::VertexMode mode = static_cast(packed & kMode_Mask); + const bool hasTexs = SkToBool(packed & kHasTexs_Mask); + const bool hasColors = SkToBool(packed & kHasColors_Mask); + Sizes sizes(vertexCount, indexCount, hasTexs, hasColors); + if (!sizes.isValid()) { return nullptr; } - - length -= 3 * sizeof(uint32_t); // already read the header - if (length < size) { // buffer too small + if (kHeaderSize + sizes.fArrays != length) { return nullptr; } - Builder builder(mode, vertexCount, indexCount, builderFlags); - if (!builder.isValid()) { - return nullptr; - } + Builder builder(mode, vertexCount, indexCount, sizes); - reader.read(builder.positions(), vertexCount * sizeof(SkPoint)); - if (builderFlags & SkVertices::kHasTexs_Flag) { - reader.read(builder.texCoords(), vertexCount * sizeof(SkPoint)); - } - if (builderFlags & SkVertices::kHasColors_Flag) { - reader.read(builder.colors(), vertexCount * sizeof(SkColor)); - } - reader.read(builder.indices(), indexCount * sizeof(uint16_t)); + reader.read(builder.positions(), sizes.fVSize); + reader.read(builder.texCoords(), sizes.fTSize); + reader.read(builder.colors(), sizes.fCSize); + reader.read(builder.indices(), sizes.fISize); return builder.detach(); } -- cgit v1.2.3