| 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 | #ifndef SkVertices_DEFINED |
| 9 | #define SkVertices_DEFINED |
| 10 | |
| 11 | #include "include/core/SkColor.h" |
| 12 | #include "include/core/SkRect.h" |
| 13 | #include "include/core/SkRefCnt.h" |
| 14 | |
| 15 | class SkData; |
| 16 | struct SkPoint; |
| 17 | class SkVerticesPriv; |
| 18 | |
| 19 | /** |
| 20 | * An immutable set of vertex data that can be used with SkCanvas::drawVertices. |
| 21 | */ |
| 22 | class SK_API SkVertices : public SkNVRefCnt<SkVertices> { |
| 23 | struct Desc; |
| 24 | struct Sizes; |
| 25 | public: |
| 26 | enum VertexMode { |
| 27 | kTriangles_VertexMode, |
| 28 | kTriangleStrip_VertexMode, |
| 29 | kTriangleFan_VertexMode, |
| 30 | |
| 31 | kLast_VertexMode = kTriangleFan_VertexMode, |
| 32 | }; |
| 33 | |
| 34 | /** |
| 35 | * Create a vertices by copying the specified arrays. texs, colors may be nullptr, |
| 36 | * and indices is ignored if indexCount == 0. |
| 37 | */ |
| 38 | static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount, |
| 39 | const SkPoint positions[], |
| 40 | const SkPoint texs[], |
| 41 | const SkColor colors[], |
| 42 | int indexCount, |
| 43 | const uint16_t indices[]); |
| 44 | |
| 45 | static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount, |
| 46 | const SkPoint positions[], |
| 47 | const SkPoint texs[], |
| 48 | const SkColor colors[]) { |
| 49 | return MakeCopy(mode, |
| 50 | vertexCount, |
| 51 | positions, |
| 52 | texs, |
| 53 | colors, |
| 54 | 0, |
| 55 | nullptr); |
| 56 | } |
| 57 | |
| 58 | static constexpr int kMaxCustomAttributes = 8; |
| 59 | |
| 60 | struct Attribute { |
| 61 | enum class Type : uint8_t { |
| 62 | kFloat, |
| 63 | kFloat2, |
| 64 | kFloat3, |
| 65 | kFloat4, |
| 66 | kByte4_unorm, |
| 67 | }; |
| 68 | |
| 69 | enum class Usage : uint8_t { |
| 70 | // Raw values passed directly to effect |
| 71 | kRaw, |
| 72 | |
| 73 | // sRGB unpremul colors, transformed to destination color space (3 or 4 channels) |
| 74 | // Colors are always assumed to be in RGBA order, and are automatically premultiplied. |
| 75 | kColor, |
| 76 | |
| 77 | // Local vector, transformed to world (2 or 3 channels) |
| 78 | kVector, |
| 79 | |
| 80 | // Normal vector (or any other bivector), transformed to world (2 or 3 channels) |
| 81 | kNormalVector, |
| 82 | |
| 83 | // Local position, transformed to world (2 or 3 channels) |
| 84 | kPosition, |
| 85 | }; |
| 86 | |
| 87 | Attribute(Type t = Type::kFloat, Usage u = Usage::kRaw) |
| 88 | : fType(t) |
| 89 | , fUsage(u) {} |
| 90 | |
| 91 | bool operator==(const Attribute& that) const { |
| 92 | return fType == that.fType && fUsage == that.fUsage; |
| 93 | } |
| 94 | bool operator!=(const Attribute& that) const { return !(*this == that); } |
| 95 | |
| 96 | // Number of channels that will be produced for the SkRuntimeEffect to consume. |
| 97 | // May not match the number of channels in fType. For example, kVector Attributes always |
| 98 | // produce three channels, even if the input is kFloat2. |
| 99 | int channelCount() const; |
| 100 | size_t bytesPerVertex() const; |
| 101 | bool isValid() const; |
| 102 | |
| 103 | Type fType; |
| 104 | Usage fUsage; |
| 105 | }; |
| 106 | |
| 107 | enum BuilderFlags { |
| 108 | kHasTexCoords_BuilderFlag = 1 << 0, |
| 109 | kHasColors_BuilderFlag = 1 << 1, |
| 110 | }; |
| 111 | class Builder { |
| 112 | public: |
| 113 | Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags); |
| 114 | |
| 115 | // EXPERIMENTAL -- do not call if you care what happens |
| 116 | Builder(VertexMode mode, |
| 117 | int vertexCount, |
| 118 | int indexCount, |
| 119 | const Attribute* attrs, |
| 120 | int attrCount); |
| 121 | |
| 122 | bool isValid() const { return fVertices != nullptr; } |
| 123 | |
| 124 | SkPoint* positions(); |
| 125 | uint16_t* indices(); // returns null if there are no indices |
| 126 | |
| 127 | // if we have texCoords or colors, this will always be null |
| 128 | void* customData(); // returns null if there are no custom attributes |
| 129 | |
| 130 | // If we have custom attributes, these will always be null |
| 131 | SkPoint* texCoords(); // returns null if there are no texCoords |
| 132 | SkColor* colors(); // returns null if there are no colors |
| 133 | |
| 134 | // Detach the built vertices object. After the first call, this will always return null. |
| 135 | sk_sp<SkVertices> detach(); |
| 136 | |
| 137 | private: |
| 138 | Builder(const Desc&); |
| 139 | |
| 140 | void init(const Desc&); |
| 141 | |
| 142 | // holds a partially complete object. only completed in detach() |
| 143 | sk_sp<SkVertices> fVertices; |
| 144 | // Extra storage for intermediate vertices in the case where the client specifies indexed |
| 145 | // triangle fans. These get converted to indexed triangles when the Builder is finalized. |
| 146 | std::unique_ptr<uint8_t[]> fIntermediateFanIndices; |
| 147 | |
| 148 | friend class SkVertices; |
| 149 | }; |
| 150 | |
| 151 | uint32_t uniqueID() const { return fUniqueID; } |
| 152 | const SkRect& bounds() const { return fBounds; } |
| 153 | |
| 154 | // returns approximate byte size of the vertices object |
| 155 | size_t approximateSize() const; |
| 156 | |
| 157 | /** |
| 158 | * Recreate a vertices from a buffer previously created by calling encode(). |
| 159 | * Returns null if the data is corrupt or the length is incorrect for the contents. |
| 160 | */ |
| 161 | static sk_sp<SkVertices> Decode(const void* buffer, size_t length); |
| 162 | |
| 163 | /** |
| 164 | * Pack the vertices object into a byte buffer. This can be used to recreate the vertices |
| 165 | * by calling Decode() with the buffer. |
| 166 | */ |
| 167 | sk_sp<SkData> encode() const; |
| 168 | |
| 169 | // Provides access to functions that aren't part of the public API. |
| 170 | SkVerticesPriv priv(); |
| 171 | const SkVerticesPriv priv() const; |
| 172 | |
| 173 | private: |
| 174 | SkVertices() {} |
| 175 | |
| 176 | friend class SkVerticesPriv; |
| 177 | |
| 178 | // these are needed since we've manually sized our allocation (see Builder::init) |
| 179 | friend class SkNVRefCnt<SkVertices>; |
| 180 | void operator delete(void* p); |
| 181 | |
| 182 | Sizes getSizes() const; |
| 183 | |
| 184 | // we store this first, to pair with the refcnt in our base-class, so we don't have an |
| 185 | // unnecessary pad between it and the (possibly 8-byte aligned) ptrs. |
| 186 | uint32_t fUniqueID; |
| 187 | |
| 188 | // these point inside our allocation, so none of these can be "freed" |
| 189 | SkPoint* fPositions; // [vertexCount] |
| 190 | uint16_t* fIndices; // [indexCount] or null |
| 191 | void* fCustomData; // [customDataSize * vertexCount] or null |
| 192 | SkPoint* fTexs; // [vertexCount] or null |
| 193 | SkColor* fColors; // [vertexCount] or null |
| 194 | |
| 195 | SkRect fBounds; // computed to be the union of the fPositions[] |
| 196 | int fVertexCount; |
| 197 | int fIndexCount; |
| 198 | |
| 199 | Attribute fAttributes[kMaxCustomAttributes]; |
| 200 | int fAttributeCount; |
| 201 | |
| 202 | VertexMode fMode; |
| 203 | // below here is where the actual array data is stored. |
| 204 | }; |
| 205 | |
| 206 | #endif |
| 207 | |