/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkVertices_DEFINED #define SkVertices_DEFINED #include "include/core/SkColor.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" class SkData; struct SkPoint; class SkVerticesPriv; /** * An immutable set of vertex data that can be used with SkCanvas::drawVertices. */ class SK_API SkVertices : public SkNVRefCnt { struct Desc; struct Sizes; public: enum VertexMode { kTriangles_VertexMode, kTriangleStrip_VertexMode, kTriangleFan_VertexMode, kLast_VertexMode = kTriangleFan_VertexMode, }; /** * Create a vertices by copying the specified arrays. texs, colors may be nullptr, * and indices is ignored if indexCount == 0. */ static sk_sp MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[]); static sk_sp MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[]) { return MakeCopy(mode, vertexCount, positions, texs, colors, 0, nullptr); } static constexpr int kMaxCustomAttributes = 8; struct Attribute { enum class Type : uint8_t { kFloat, kFloat2, kFloat3, kFloat4, kByte4_unorm, }; enum class Usage : uint8_t { // Raw values passed directly to effect kRaw, // sRGB unpremul colors, transformed to destination color space (3 or 4 channels) // Colors are always assumed to be in RGBA order, and are automatically premultiplied. kColor, // Local vector, transformed to world (2 or 3 channels) kVector, // Normal vector (or any other bivector), transformed to world (2 or 3 channels) kNormalVector, // Local position, transformed to world (2 or 3 channels) kPosition, }; Attribute(Type t = Type::kFloat, Usage u = Usage::kRaw) : fType(t) , fUsage(u) {} bool operator==(const Attribute& that) const { return fType == that.fType && fUsage == that.fUsage; } bool operator!=(const Attribute& that) const { return !(*this == that); } // Number of channels that will be produced for the SkRuntimeEffect to consume. // May not match the number of channels in fType. For example, kVector Attributes always // produce three channels, even if the input is kFloat2. int channelCount() const; size_t bytesPerVertex() const; bool isValid() const; Type fType; Usage fUsage; }; enum BuilderFlags { kHasTexCoords_BuilderFlag = 1 << 0, kHasColors_BuilderFlag = 1 << 1, }; class Builder { public: Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags); // EXPERIMENTAL -- do not call if you care what happens Builder(VertexMode mode, int vertexCount, int indexCount, const Attribute* attrs, int attrCount); bool isValid() const { return fVertices != nullptr; } SkPoint* positions(); uint16_t* indices(); // returns null if there are no indices // if we have texCoords or colors, this will always be null void* customData(); // returns null if there are no custom attributes // If we have custom attributes, these will always be null SkPoint* texCoords(); // returns null if there are no texCoords SkColor* colors(); // returns null if there are no colors // Detach the built vertices object. After the first call, this will always return null. sk_sp detach(); private: Builder(const Desc&); void init(const Desc&); // holds a partially complete object. only completed in detach() sk_sp fVertices; // Extra storage for intermediate vertices in the case where the client specifies indexed // triangle fans. These get converted to indexed triangles when the Builder is finalized. std::unique_ptr fIntermediateFanIndices; friend class SkVertices; }; uint32_t uniqueID() const { return fUniqueID; } const SkRect& bounds() const { return fBounds; } // returns approximate byte size of the vertices object size_t approximateSize() const; /** * Recreate a vertices from a buffer previously created by calling encode(). * Returns null if the data is corrupt or the length is incorrect for the contents. */ static sk_sp Decode(const void* buffer, size_t length); /** * Pack the vertices object into a byte buffer. This can be used to recreate the vertices * by calling Decode() with the buffer. */ sk_sp encode() const; // Provides access to functions that aren't part of the public API. SkVerticesPriv priv(); const SkVerticesPriv priv() const; private: SkVertices() {} friend class SkVerticesPriv; // these are needed since we've manually sized our allocation (see Builder::init) friend class SkNVRefCnt; void operator delete(void* p); 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; // these point inside our allocation, so none of these can be "freed" SkPoint* fPositions; // [vertexCount] uint16_t* fIndices; // [indexCount] or null void* fCustomData; // [customDataSize * vertexCount] or null SkPoint* fTexs; // [vertexCount] or null SkColor* fColors; // [vertexCount] or null SkRect fBounds; // computed to be the union of the fPositions[] int fVertexCount; int fIndexCount; Attribute fAttributes[kMaxCustomAttributes]; int fAttributeCount; VertexMode fMode; // below here is where the actual array data is stored. }; #endif