Reorganize vertices internals, in prep for extending with per-vertex-data

Bug: skia:9984
Change-Id: I50f9bd126ab27895db2a2c6dd4d078b8d6c98b15
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274940
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-03-04 09:48:08 -05:00 committed by Skia Commit-Bot
parent d71548adfb
commit ee9ce59346
2 changed files with 69 additions and 63 deletions

View File

@ -18,6 +18,8 @@
* An immutable set of vertex data that can be used with SkCanvas::drawVertices.
*/
class SK_API SkVertices : public SkNVRefCnt<SkVertices> {
struct Desc;
struct Sizes;
public:
// DEPRECATED -- remove when we've updated canvas virtuals to not mention bones
struct Bone { float values[6]; };
@ -57,8 +59,6 @@ public:
isVolatile);
}
struct Sizes;
enum BuilderFlags {
kHasTexCoords_BuilderFlag = 1 << 0,
kHasColors_BuilderFlag = 1 << 1,
@ -83,9 +83,9 @@ public:
sk_sp<SkVertices> detach();
private:
Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
Builder(const Desc&);
void init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
void init(const Desc&);
// holds a partially complete object. only completed in detach()
sk_sp<SkVertices> fVertices;
@ -104,12 +104,12 @@ public:
bool hasTexCoords() const { return SkToBool(this->texCoords()); }
bool hasIndices() const { return SkToBool(this->indices()); }
int vertexCount() const { return fVertexCnt; }
int vertexCount() const { return fVertexCount; }
const SkPoint* positions() const { return fPositions; }
const SkPoint* texCoords() const { return fTexs; }
const SkColor* colors() const { return fColors; }
int indexCount() const { return fIndexCnt; }
int indexCount() const { return fIndexCount; }
const uint16_t* indices() const { return fIndices; }
bool isVolatile() const { return fIsVolatile; }
@ -139,6 +139,8 @@ private:
static sk_sp<SkVertices> Alloc(int vCount, int iCount, uint32_t builderFlags,
size_t* arraySize);
Sizes getSizes() const;
// we store this first, to pair with the refcnt in our base-class, so we don't have an
// unnecessary pad between it and the (possibly 8-byte aligned) ptrs.
uint32_t fUniqueID;
@ -150,8 +152,8 @@ private:
uint16_t* fIndices;
SkRect fBounds; // computed to be the union of the fPositions[]
int fVertexCnt;
int fIndexCnt;
int fVertexCount;
int fIndexCount;
bool fIsVolatile;

View File

@ -27,27 +27,35 @@ static int32_t next_id() {
return id;
}
struct SkVertices::Desc {
VertexMode fMode;
int fVertexCount,
fIndexCount;
bool fHasTexs,
fHasColors,
fIsVolatile;
};
struct SkVertices::Sizes {
Sizes(SkVertices::VertexMode mode, int vertexCount, int indexCount, bool hasTexs,
bool hasColors) {
Sizes(const Desc& desc) {
SkSafeMath safe;
fVSize = safe.mul(vertexCount, sizeof(SkPoint));
fTSize = hasTexs ? safe.mul(vertexCount, sizeof(SkPoint)) : 0;
fCSize = hasColors ? safe.mul(vertexCount, sizeof(SkColor)) : 0;
fVSize = safe.mul(desc.fVertexCount, sizeof(SkPoint));
fTSize = desc.fHasTexs ? safe.mul(desc.fVertexCount, sizeof(SkPoint)) : 0;
fCSize = desc.fHasColors ? safe.mul(desc.fVertexCount, sizeof(SkColor)) : 0;
fBuilderTriFanISize = 0;
fISize = safe.mul(indexCount, sizeof(uint16_t));
if (kTriangleFan_VertexMode == mode) {
fISize = safe.mul(desc.fIndexCount, sizeof(uint16_t));
if (kTriangleFan_VertexMode == desc.fMode) {
int numFanTris = 0;
if (indexCount) {
if (desc.fIndexCount) {
fBuilderTriFanISize = fISize;
numFanTris = indexCount - 2;
numFanTris = desc.fIndexCount - 2;
} else {
numFanTris = vertexCount - 2;
numFanTris = desc.fVertexCount - 2;
// By forcing this to become indexed we are adding a constraint to the maximum
// number of vertices.
if (vertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
if (desc.fVertexCount > (SkTo<int>(UINT16_MAX) + 1)) {
sk_bzero(this, sizeof(*this));
return;
}
@ -91,19 +99,18 @@ SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
bool isVolatile = !SkToBool(builderFlags & SkVertices::kIsNonVolatile_BuilderFlag);
this->init(mode, vertexCount, indexCount, isVolatile,
SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors));
this->init({mode, vertexCount, indexCount, hasTexs, hasColors, isVolatile});
}
SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
const SkVertices::Sizes& sizes) {
this->init(mode, vertexCount, indexCount, isVolatile, sizes);
SkVertices::Builder::Builder(const Desc& desc) {
this->init(desc);
}
void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
const SkVertices::Sizes& sizes) {
void SkVertices::Builder::init(const Desc& desc) {
Sizes sizes(desc);
if (!sizes.isValid()) {
return; // fVertices will already be null
SkASSERT(!this->isValid());
return;
}
void* storage = ::operator new (sizes.fTotal);
@ -120,35 +127,35 @@ void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount,
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->fIsVolatile = isVolatile;
fVertices->fMode = mode;
fVertices->fVertexCount = desc.fVertexCount;
fVertices->fIndexCount = desc.fIndexCount;
fVertices->fIsVolatile = desc.fIsVolatile;
fVertices->fMode = desc.fMode;
// We defer assigning fBounds and fUniqueID until detach() is called
}
sk_sp<SkVertices> SkVertices::Builder::detach() {
if (fVertices) {
fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCnt);
fVertices->fBounds.setBounds(fVertices->fPositions, fVertices->fVertexCount);
if (fVertices->fMode == kTriangleFan_VertexMode) {
if (fIntermediateFanIndices.get()) {
SkASSERT(fVertices->fIndexCnt);
SkASSERT(fVertices->fIndexCount);
auto tempIndices = this->indices();
for (int t = 0; t < fVertices->fIndexCnt - 2; ++t) {
for (int t = 0; t < fVertices->fIndexCount - 2; ++t) {
fVertices->fIndices[3 * t + 0] = tempIndices[0];
fVertices->fIndices[3 * t + 1] = tempIndices[t + 1];
fVertices->fIndices[3 * t + 2] = tempIndices[t + 2];
}
fVertices->fIndexCnt = 3 * (fVertices->fIndexCnt - 2);
fVertices->fIndexCount = 3 * (fVertices->fIndexCount - 2);
} else {
SkASSERT(!fVertices->fIndexCnt);
for (int t = 0; t < fVertices->fVertexCnt - 2; ++t) {
SkASSERT(!fVertices->fIndexCount);
for (int t = 0; t < fVertices->fVertexCount - 2; ++t) {
fVertices->fIndices[3 * t + 0] = 0;
fVertices->fIndices[3 * t + 1] = SkToU16(t + 1);
fVertices->fIndices[3 * t + 2] = SkToU16(t + 2);
}
fVertices->fIndexCnt = 3 * (fVertices->fVertexCnt - 2);
fVertices->fIndexCount = 3 * (fVertices->fVertexCount - 2);
}
fVertices->fMode = kTriangles_VertexMode;
}
@ -199,18 +206,14 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
const SkColor colors[],
int indexCount, const uint16_t indices[],
bool isVolatile) {
Sizes sizes(mode,
vertexCount,
indexCount,
texs != nullptr,
colors != nullptr);
if (!sizes.isValid()) {
auto desc = Desc{mode, vertexCount, indexCount, !!texs, !!colors, isVolatile};
Builder builder(desc);
if (!builder.isValid()) {
return nullptr;
}
Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
SkASSERT(builder.isValid());
Sizes sizes(desc);
SkASSERT(sizes.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);
@ -221,13 +224,15 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
}
size_t SkVertices::approximateSize() const {
Sizes sizes(fMode,
fVertexCnt,
fIndexCnt,
this->hasTexCoords(),
this->hasColors());
return sizeof(SkVertices) + this->getSizes().fArrays;
}
SkVertices::Sizes SkVertices::getSizes() const {
Sizes sizes({
fMode, fVertexCount, fIndexCount, this->hasTexCoords(), this->hasColors(), fIsVolatile
});
SkASSERT(sizes.isValid());
return sizeof(SkVertices) + sizes.fArrays;
return sizes;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -269,12 +274,7 @@ sk_sp<SkData> SkVertices::encode() const {
}
packed |= kCurrent_Version << kVersion_Shift;
Sizes sizes(fMode,
fVertexCnt,
fIndexCnt,
this->hasTexCoords(),
this->hasColors());
SkASSERT(sizes.isValid());
Sizes sizes = this->getSizes();
SkASSERT(!sizes.fBuilderTriFanISize);
// need to force alignment to 4 for SkWriter32 -- will pad w/ 0s as needed
const size_t size = SkAlign4(kHeaderSize + sizes.fArrays);
@ -283,8 +283,8 @@ sk_sp<SkData> SkVertices::encode() const {
SkWriter32 writer(data->writable_data(), data->size());
writer.write32(packed);
writer.write32(fVertexCnt);
writer.write32(fIndexCnt);
writer.write32(fVertexCount);
writer.write32(fIndexCount);
writer.write(fPositions, sizes.fVSize);
writer.write(fTexs, sizes.fTSize);
writer.write(fColors, sizes.fCSize);
@ -315,7 +315,8 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
const bool hasColors = SkToBool(packed & kHasColors_Mask);
const bool hasBones = (version <= kOriginal_Version) && SkToBool(packed & kHasBones_Mask_V0);
const bool isVolatile = !SkToBool(packed & kIsNonVolatile_Mask);
Sizes sizes(mode, vertexCount, indexCount, hasTexs, hasColors);
const Desc desc{mode, vertexCount, indexCount, hasTexs, hasColors, isVolatile};
Sizes sizes(desc);
if (!sizes.isValid()) {
return nullptr;
}
@ -324,7 +325,10 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
return nullptr;
}
Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
Builder builder(desc);
if (!builder.isValid()) {
return nullptr;
}
SkSafeMath safe_math;
reader.read(builder.positions(), sizes.fVSize);