| /* |
| * 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 "GrTypesPriv.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 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 op of instances. This struct also serves |
| * as an all-in-one shader key for the op. |
| */ |
| struct OpInfo { |
| OpInfo() : fData(0) {} |
| explicit OpInfo(uint32_t data) : fData(data) {} |
| |
| static bool CanCombine(const OpInfo& a, const OpInfo& b); |
| |
| bool isSimpleRects() const { |
| return !((fShapeTypes & ~kRect_ShapeFlag) | fInnerShapeTypes); |
| } |
| |
| GrAAType aaType() const { return static_cast<GrAAType>(fAAType); } |
| void setAAType(GrAAType aaType) { fAAType = static_cast<uint8_t>(aaType); } |
| |
| union { |
| struct { |
| uint8_t fAAType; // GrAAType |
| 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 OpInfo::CanCombine(const OpInfo& a, const OpInfo& b) { |
| if (a.fAAType != b.fAAType) { |
| 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 OpInfo operator|(const OpInfo& a, const OpInfo& b) { |
| SkASSERT(OpInfo::CanCombine(a, b)); |
| return OpInfo(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(OpInfo)); |
| 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 |