| /* |
| * 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<SkVertices> { |
| 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<SkVertices> MakeCopy(VertexMode mode, int vertexCount, |
| const SkPoint positions[], |
| const SkPoint texs[], |
| const SkColor colors[], |
| int indexCount, |
| const uint16_t indices[]); |
| |
| static sk_sp<SkVertices> 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; |
| |
| /** |
| * EXPERIMENTAL - An SkVertices object can be constructed with a custom collection of vertex |
| * attributes. Each attribute is described by a single Attribute struct. Type defines the CPU |
| * type of the data. Usage determines what transformation (if any) is applied to that data in |
| * the vertex shader. For positions or vectors, markerName identifies what matrix is used in |
| * the vertex shader to transform the data. Those names should match a named transform on the |
| * CTM stack, created by calling SkCanvas::markCTM(). |
| * |
| * For attributes with a usage of kVector, kNormalVector, or kPosition, a null markerName |
| * will transform the attribute by the canvas CTM matrix. |
| */ |
| 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 via marker (2 or 3 channels) |
| kVector, |
| |
| // Normal vector (or any other bivector), transformed via marker (2 or 3 channels) |
| kNormalVector, |
| |
| // Local position, transformed via marker (2 or 3 channels) |
| kPosition, |
| }; |
| |
| /** |
| * markerName is not copied by the Attribute, so it must outlive this struct. |
| * It is copied when this Attribute is passed to the Builder constructor. |
| */ |
| Attribute(Type t = Type::kFloat, Usage u = Usage::kRaw, const char* markerName = nullptr); |
| |
| bool operator==(const Attribute& that) const { |
| return fType == that.fType && fUsage == that.fUsage && fMarkerID == that.fMarkerID; |
| } |
| 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; |
| uint32_t fMarkerID; |
| const char* fMarkerName; // Preserved for serialization and debugging |
| }; |
| |
| 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<SkVertices> detach(); |
| |
| private: |
| Builder(const Desc&); |
| |
| void init(const Desc&); |
| |
| // holds a partially complete object. only completed in detach() |
| sk_sp<SkVertices> 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<uint8_t[]> fIntermediateFanIndices; |
| |
| friend class SkVertices; |
| friend class SkVerticesPriv; |
| }; |
| |
| uint32_t uniqueID() const { return fUniqueID; } |
| const SkRect& bounds() const { return fBounds; } |
| |
| // returns approximate byte size of the vertices object |
| size_t approximateSize() const; |
| |
| // Provides access to functions that aren't part of the public API. |
| SkVerticesPriv priv(); |
| const SkVerticesPriv priv() const; // NOLINT(readability-const-return-type) |
| |
| private: |
| SkVertices() {} |
| |
| friend class SkVerticesPriv; |
| |
| // these are needed since we've manually sized our allocation (see Builder::init) |
| friend class SkNVRefCnt<SkVertices>; |
| 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" |
| Attribute* fAttributes; // [attributeCount] or null |
| 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; |
| int fAttributeCount; |
| |
| VertexMode fMode; |
| // below here is where the actual array data is stored. |
| }; |
| |
| #endif |