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