Index: src/gpu/instanced/InstancedRenderingTypes.h |
diff --git a/src/gpu/instanced/InstancedRenderingTypes.h b/src/gpu/instanced/InstancedRenderingTypes.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..97f8946d033309c6357f37074373dc0071c329ad |
--- /dev/null |
+++ b/src/gpu/instanced/InstancedRenderingTypes.h |
@@ -0,0 +1,192 @@ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#ifndef gr_instanced_InstancedRenderingTypes_DEFINED |
+#define gr_instanced_InstancedRenderingTypes_DEFINED |
+ |
+#include "GrTypes.h" |
+#include "SkRRect.h" |
+ |
+namespace gr_instanced { |
+ |
+/** |
+ * Per-vertex data. These values get fed into normal vertex attribs. |
+ */ |
+struct ShapeVertex { |
+ float fX, fY; //!< Shape coordinates. |
+ int32_t fAttrs; //!< Shape-specific vertex attributes, if needed. |
+}; |
+ |
+/** |
+ * Per-instance data. These values get fed into instanced vertex attribs. |
+ */ |
+struct Instance { |
+ uint32_t fInfo; //!< Packed info about the instance. See InfoBits. |
+ float fShapeMatrix2x3[6]; //!< Maps canonical shape coords -> device space coords. |
+ uint32_t fColor; //!< Color to be written out by the primitive processor. |
+ float fLocalRect[4]; //!< Local coords rect that spans [-1, +1] in shape coords. |
+}; |
+ |
+enum class Attrib : uint8_t { |
+ kShapeCoords, |
+ kVertexAttrs, |
+ kInstanceInfo, |
+ kShapeMatrixX, |
+ kShapeMatrixY, |
+ kColor, |
+ kLocalRect |
+}; |
+constexpr int kNumAttribs = 1 + (int)Attrib::kLocalRect; |
+ |
+enum class AntialiasMode : uint8_t { |
+ kNone, |
+ kCoverage, |
+ kMSAA, |
+ kMixedSamples |
+}; |
+constexpr int kNumAntialiasModes = 1 + (int)AntialiasMode::kMixedSamples; |
+ |
+enum class ShapeType : uint8_t { |
+ kRect, |
+ kOval, |
+ kSimpleRRect, |
+ kNinePatch, |
+ kComplexRRect |
+}; |
+constexpr int kNumShapeTypes = 1 + (int)ShapeType::kComplexRRect; |
+ |
+inline static ShapeType GetRRectShapeType(const SkRRect& rrect) { |
+ SkASSERT(rrect.getType() >= SkRRect::kRect_Type && |
+ rrect.getType() <= SkRRect::kComplex_Type); |
+ return static_cast<ShapeType>(rrect.getType() - 1); |
+ |
+ GR_STATIC_ASSERT((int)ShapeType::kRect == SkRRect::kRect_Type - 1); |
+ GR_STATIC_ASSERT((int)ShapeType::kOval == SkRRect::kOval_Type - 1); |
+ GR_STATIC_ASSERT((int)ShapeType::kSimpleRRect == SkRRect::kSimple_Type - 1); |
+ GR_STATIC_ASSERT((int)ShapeType::kNinePatch == SkRRect::kNinePatch_Type - 1); |
+ GR_STATIC_ASSERT((int)ShapeType::kComplexRRect == SkRRect::kComplex_Type - 1); |
+ GR_STATIC_ASSERT(kNumShapeTypes == SkRRect::kComplex_Type); |
+} |
+ |
+enum ShapeFlag { |
+ kRect_ShapeFlag = (1 << (int)ShapeType::kRect), |
+ kOval_ShapeFlag = (1 << (int)ShapeType::kOval), |
+ kSimpleRRect_ShapeFlag = (1 << (int)ShapeType::kSimpleRRect), |
+ kNinePatch_ShapeFlag = (1 << (int)ShapeType::kNinePatch), |
+ kComplexRRect_ShapeFlag = (1 << (int)ShapeType::kComplexRRect), |
+ |
+ kRRect_ShapesMask = kSimpleRRect_ShapeFlag | kNinePatch_ShapeFlag | kComplexRRect_ShapeFlag |
+}; |
+ |
+constexpr uint8_t GetShapeFlag(ShapeType type) { return 1 << (int)type; } |
+ |
+/** |
+ * Defines what data is stored at which bits in the fInfo field of the instanced data. |
+ */ |
+enum InfoBits { |
+ kShapeType_InfoBit = 29, |
+ kInnerShapeType_InfoBit = 27, |
+ kPerspective_InfoBit = 26, |
+ kLocalMatrix_InfoBit = 25, |
+ kParamsIdx_InfoBit = 0 |
+}; |
+ |
+enum InfoMasks { |
+ kShapeType_InfoMask = 0u - (1 << kShapeType_InfoBit), |
+ kInnerShapeType_InfoMask = (1 << kShapeType_InfoBit) - (1 << kInnerShapeType_InfoBit), |
+ kPerspective_InfoFlag = (1 << kPerspective_InfoBit), |
+ kLocalMatrix_InfoFlag = (1 << kLocalMatrix_InfoBit), |
+ kParamsIdx_InfoMask = (1 << kLocalMatrix_InfoBit) - 1 |
+}; |
+ |
+GR_STATIC_ASSERT((kNumShapeTypes - 1) <= (uint32_t)kShapeType_InfoMask >> kShapeType_InfoBit); |
+GR_STATIC_ASSERT((int)ShapeType::kSimpleRRect <= |
+ kInnerShapeType_InfoMask >> kInnerShapeType_InfoBit); |
+ |
+/** |
+ * Additional parameters required by some instances (e.g. round rect radii, perspective column, |
+ * local matrix). These are accessed via texel buffer. |
+ */ |
+struct ParamsTexel { |
+ float fX, fY, fZ, fW; |
+}; |
+ |
+GR_STATIC_ASSERT(0 == offsetof(ParamsTexel, fX)); |
+GR_STATIC_ASSERT(4 * 4 == sizeof(ParamsTexel)); |
+ |
+/** |
+ * Tracks all information needed in order to draw a batch of instances. This struct also serves |
+ * as an all-in-one shader key for the batch. |
+ */ |
+struct BatchInfo { |
+ BatchInfo() : fData(0) {} |
+ explicit BatchInfo(uint32_t data) : fData(data) {} |
+ |
+ static bool CanCombine(const BatchInfo& a, const BatchInfo& b); |
+ |
+ bool isSimpleRects() const { |
+ return !((fShapeTypes & ~kRect_ShapeFlag) | fInnerShapeTypes); |
+ } |
+ |
+ union { |
+ struct { |
+ AntialiasMode fAntialiasMode; |
+ uint8_t fShapeTypes; |
+ uint8_t fInnerShapeTypes; |
+ bool fHasPerspective : 1; |
+ bool fHasLocalMatrix : 1; |
+ bool fHasParams : 1; |
+ bool fNonSquare : 1; |
+ bool fUsesLocalCoords : 1; |
+ bool fCannotTweakAlphaForCoverage : 1; |
+ bool fCannotDiscard : 1; |
+ }; |
+ uint32_t fData; |
+ }; |
+}; |
+ |
+inline bool BatchInfo::CanCombine(const BatchInfo& a, const BatchInfo& b) { |
+ if (a.fAntialiasMode != b.fAntialiasMode) { |
+ return false; |
+ } |
+ if (SkToBool(a.fInnerShapeTypes) != SkToBool(b.fInnerShapeTypes)) { |
+ // GrInstanceProcessor can't currently combine draws with and without inner shapes. |
+ return false; |
+ } |
+ if (a.fCannotDiscard != b.fCannotDiscard) { |
+ // For stencil draws, the use of discard can be a requirement. |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+inline BatchInfo operator|(const BatchInfo& a, const BatchInfo& b) { |
+ SkASSERT(BatchInfo::CanCombine(a, b)); |
+ return BatchInfo(a.fData | b.fData); |
+} |
+ |
+// This is required since all the data must fit into 32 bits of a shader key. |
+GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(BatchInfo)); |
+GR_STATIC_ASSERT(kNumShapeTypes <= 8); |
+ |
+struct IndexRange { |
+ bool operator ==(const IndexRange& that) const { |
+ SkASSERT(fStart != that.fStart || fCount == that.fCount); |
+ return fStart == that.fStart; |
+ } |
+ bool operator !=(const IndexRange& that) const { return !(*this == that); } |
+ |
+ bool isEmpty() const { return fCount <= 0; } |
+ int end() { return fStart + fCount; } |
+ |
+ int16_t fStart; |
+ int16_t fCount; |
+}; |
+ |
+} |
+ |
+#endif |