Home | History | Annotate | Download | only in instanced
      1 /*
      2  * Copyright 2016 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 gr_instanced_InstancedRenderingTypes_DEFINED
      9 #define gr_instanced_InstancedRenderingTypes_DEFINED
     10 
     11 #include "GrTypes.h"
     12 #include "GrTypesPriv.h"
     13 #include "SkRRect.h"
     14 
     15 namespace gr_instanced {
     16 
     17 /**
     18  * Per-vertex data. These values get fed into normal vertex attribs.
     19  */
     20 struct ShapeVertex {
     21     float     fX, fY;  //!< Shape coordinates.
     22     int32_t   fAttrs;  //!< Shape-specific vertex attributes, if needed.
     23 };
     24 
     25 /**
     26  * Per-instance data. These values get fed into instanced vertex attribs.
     27  */
     28 struct Instance {
     29     uint32_t   fInfo;               //!< Packed info about the instance. See InfoBits.
     30     float      fShapeMatrix2x3[6];  //!< Maps canonical shape coords -> device space coords.
     31     uint32_t   fColor;              //!< Color to be written out by the primitive processor.
     32     float      fLocalRect[4];       //!< Local coords rect that spans [-1, +1] in shape coords.
     33 };
     34 
     35 enum class Attrib : uint8_t {
     36     kShapeCoords,
     37     kVertexAttrs,
     38     kInstanceInfo,
     39     kShapeMatrixX,
     40     kShapeMatrixY,
     41     kColor,
     42     kLocalRect
     43 };
     44 constexpr int kNumAttribs = 1 + (int)Attrib::kLocalRect;
     45 
     46 enum class ShapeType : uint8_t {
     47     kRect,
     48     kOval,
     49     kSimpleRRect,
     50     kNinePatch,
     51     kComplexRRect
     52 };
     53 constexpr int kNumShapeTypes = 1 + (int)ShapeType::kComplexRRect;
     54 
     55 inline static ShapeType GetRRectShapeType(const SkRRect& rrect) {
     56     SkASSERT(rrect.getType() >= SkRRect::kRect_Type &&
     57              rrect.getType() <= SkRRect::kComplex_Type);
     58     return static_cast<ShapeType>(rrect.getType() - 1);
     59 
     60     GR_STATIC_ASSERT((int)ShapeType::kRect == SkRRect::kRect_Type - 1);
     61     GR_STATIC_ASSERT((int)ShapeType::kOval == SkRRect::kOval_Type - 1);
     62     GR_STATIC_ASSERT((int)ShapeType::kSimpleRRect == SkRRect::kSimple_Type - 1);
     63     GR_STATIC_ASSERT((int)ShapeType::kNinePatch == SkRRect::kNinePatch_Type - 1);
     64     GR_STATIC_ASSERT((int)ShapeType::kComplexRRect == SkRRect::kComplex_Type - 1);
     65     GR_STATIC_ASSERT(kNumShapeTypes == SkRRect::kComplex_Type);
     66 }
     67 
     68 enum ShapeFlag {
     69     kRect_ShapeFlag          = (1 << (int)ShapeType::kRect),
     70     kOval_ShapeFlag          = (1 << (int)ShapeType::kOval),
     71     kSimpleRRect_ShapeFlag   = (1 << (int)ShapeType::kSimpleRRect),
     72     kNinePatch_ShapeFlag     = (1 << (int)ShapeType::kNinePatch),
     73     kComplexRRect_ShapeFlag  = (1 << (int)ShapeType::kComplexRRect),
     74 
     75     kRRect_ShapesMask = kSimpleRRect_ShapeFlag | kNinePatch_ShapeFlag | kComplexRRect_ShapeFlag
     76 };
     77 
     78 constexpr uint8_t GetShapeFlag(ShapeType type) { return 1 << (int)type; }
     79 
     80 /**
     81  * Defines what data is stored at which bits in the fInfo field of the instanced data.
     82  */
     83 enum InfoBits {
     84     kShapeType_InfoBit       = 29,
     85     kInnerShapeType_InfoBit  = 27,
     86     kPerspective_InfoBit     = 26,
     87     kLocalMatrix_InfoBit     = 25,
     88     kParamsIdx_InfoBit       =  0
     89 };
     90 
     91 enum InfoMasks {
     92     kShapeType_InfoMask       = 0u - (1 << kShapeType_InfoBit),
     93     kInnerShapeType_InfoMask  = (1 << kShapeType_InfoBit) - (1 << kInnerShapeType_InfoBit),
     94     kPerspective_InfoFlag     = (1 << kPerspective_InfoBit),
     95     kLocalMatrix_InfoFlag     = (1 << kLocalMatrix_InfoBit),
     96     kParamsIdx_InfoMask       = (1 << kLocalMatrix_InfoBit) - 1
     97 };
     98 
     99 GR_STATIC_ASSERT((kNumShapeTypes - 1) <= (uint32_t)kShapeType_InfoMask >> kShapeType_InfoBit);
    100 GR_STATIC_ASSERT((int)ShapeType::kSimpleRRect <=
    101                  kInnerShapeType_InfoMask >> kInnerShapeType_InfoBit);
    102 
    103 /**
    104  * Additional parameters required by some instances (e.g. round rect radii, perspective column,
    105  * local matrix). These are accessed via texel buffer.
    106  */
    107 struct ParamsTexel {
    108     float fX, fY, fZ, fW;
    109 };
    110 
    111 GR_STATIC_ASSERT(0 == offsetof(ParamsTexel, fX));
    112 GR_STATIC_ASSERT(4 * 4 == sizeof(ParamsTexel));
    113 
    114 /**
    115  * Tracks all information needed in order to draw a op of instances. This struct also serves
    116  * as an all-in-one shader key for the op.
    117  */
    118 struct OpInfo {
    119     OpInfo() : fData(0) {}
    120     explicit OpInfo(uint32_t data) : fData(data) {}
    121 
    122     static bool CanCombine(const OpInfo& a, const OpInfo& b);
    123 
    124     bool isSimpleRects() const {
    125         return !((fShapeTypes & ~kRect_ShapeFlag) | fInnerShapeTypes);
    126     }
    127 
    128     GrAAType aaType() const { return static_cast<GrAAType>(fAAType); }
    129     void setAAType(GrAAType aaType) { fAAType = static_cast<uint8_t>(aaType); }
    130 
    131     union {
    132         struct {
    133             uint8_t         fAAType;  // GrAAType
    134             uint8_t         fShapeTypes;
    135             uint8_t         fInnerShapeTypes;
    136             bool            fHasPerspective               : 1;
    137             bool            fHasLocalMatrix               : 1;
    138             bool            fHasParams                    : 1;
    139             bool            fNonSquare                    : 1;
    140             bool            fUsesLocalCoords              : 1;
    141             bool            fCannotTweakAlphaForCoverage  : 1;
    142             bool            fCannotDiscard                : 1;
    143         };
    144         uint32_t fData;
    145     };
    146 };
    147 
    148 inline bool OpInfo::CanCombine(const OpInfo& a, const OpInfo& b) {
    149     if (a.fAAType != b.fAAType) {
    150         return false;
    151     }
    152     if (SkToBool(a.fInnerShapeTypes) != SkToBool(b.fInnerShapeTypes)) {
    153         // GrInstanceProcessor can't currently combine draws with and without inner shapes.
    154         return false;
    155     }
    156     if (a.fCannotDiscard != b.fCannotDiscard) {
    157         // For stencil draws, the use of discard can be a requirement.
    158         return false;
    159     }
    160     return true;
    161 }
    162 
    163 inline OpInfo operator|(const OpInfo& a, const OpInfo& b) {
    164     SkASSERT(OpInfo::CanCombine(a, b));
    165     return OpInfo(a.fData | b.fData);
    166 }
    167 
    168 // This is required since all the data must fit into 32 bits of a shader key.
    169 GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(OpInfo));
    170 GR_STATIC_ASSERT(kNumShapeTypes <= 8);
    171 
    172 struct IndexRange {
    173     bool operator ==(const IndexRange& that) const {
    174         SkASSERT(fStart != that.fStart || fCount == that.fCount);
    175         return fStart == that.fStart;
    176     }
    177     bool operator !=(const IndexRange& that) const { return !(*this == that); }
    178 
    179     bool isEmpty() const { return fCount <= 0; }
    180     int end() { return fStart + fCount; }
    181 
    182     int16_t fStart;
    183     int16_t fCount;
    184 };
    185 
    186 }
    187 
    188 #endif
    189