OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrAAFillRectBatch.h" | 8 #include "GrAAFillRectBatch.h" |
9 | 9 |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrColor.h" | 11 #include "GrColor.h" |
12 #include "GrDefaultGeoProcFactory.h" | 12 #include "GrDefaultGeoProcFactory.h" |
13 #include "GrResourceKey.h" | 13 #include "GrResourceKey.h" |
14 #include "GrResourceProvider.h" | 14 #include "GrResourceProvider.h" |
15 #include "GrTypes.h" | 15 #include "GrTypes.h" |
16 #include "SkMatrix.h" | 16 #include "SkMatrix.h" |
17 #include "SkRect.h" | 17 #include "SkRect.h" |
18 | 18 |
19 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); | 19 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); |
20 | 20 |
21 static void set_inset_fan(SkPoint* pts, size_t stride, | 21 static void set_inset_fan(SkPoint* pts, size_t stride, |
22 const SkRect& r, SkScalar dx, SkScalar dy) { | 22 const SkRect& r, SkScalar dx, SkScalar dy) { |
23 pts->setRectFan(r.fLeft + dx, r.fTop + dy, | 23 pts->setRectFan(r.fLeft + dx, r.fTop + dy, |
24 r.fRight - dx, r.fBottom - dy, stride); | 24 r.fRight - dx, r.fBottom - dy, stride); |
25 } | 25 } |
26 | 26 |
27 static const GrGeometryProcessor* create_fill_rect_gp(bool tweakAlphaForCoverage , | 27 template <typename Base> |
robertphillips
2015/08/12 16:31:20
// This compiles b.c. ...
?
| |
28 const SkMatrix& viewMatrix , | 28 class AAFillRectBatch : public Base { |
29 bool usesLocalCoords, | 29 public: |
30 bool coverageIgnored) { | 30 typedef typename Base::Geometry Geometry; |
31 using namespace GrDefaultGeoProcFactory; | |
32 | 31 |
33 Color color(Color::kAttribute_Type); | 32 static AAFillRectBatch* Create() { |
34 Coverage::Type coverageType; | 33 return SkNEW(AAFillRectBatch); |
35 // TODO remove coverage if coverage is ignored | |
36 /*if (coverageIgnored) { | |
37 coverageType = Coverage::kNone_Type; | |
38 } else*/ if (tweakAlphaForCoverage) { | |
39 coverageType = Coverage::kSolid_Type; | |
40 } else { | |
41 coverageType = Coverage::kAttribute_Type; | |
42 } | |
43 Coverage coverage(coverageType); | |
44 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : | |
45 LocalCoords::kUnused_Type); | |
46 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix); | |
47 } | |
48 | |
49 class AAFillRectBatch : public GrBatch { | |
50 public: | |
51 struct Geometry { | |
52 GrColor fColor; | |
53 SkMatrix fViewMatrix; | |
54 SkRect fRect; | |
55 SkRect fDevRect; | |
56 }; | |
57 | |
58 static GrBatch* Create(GrColor color, | |
59 const SkMatrix& viewMatrix, | |
60 const SkRect& rect, | |
61 const SkRect& devRect) { | |
62 return SkNEW_ARGS(AAFillRectBatch, (color, viewMatrix, rect, devRect)); | |
63 } | 34 } |
64 | 35 |
65 const char* name() const override { return "AAFillRectBatch"; } | 36 const char* name() const override { return "AAFillRectBatch"; } |
66 | 37 |
67 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 38 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
68 // When this is called on a batch, there is only one geometry bundle | 39 // When this is called on a batch, there is only one geometry bundle |
69 out->setKnownFourComponents(fGeoData[0].fColor); | 40 out->setKnownFourComponents(fGeoData[0].fColor); |
70 } | 41 } |
71 | 42 |
72 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 43 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
(...skipping 11 matching lines...) Expand all Loading... | |
84 fBatch.fColorIgnored = !opt.readsColor(); | 55 fBatch.fColorIgnored = !opt.readsColor(); |
85 fBatch.fColor = fGeoData[0].fColor; | 56 fBatch.fColor = fGeoData[0].fColor; |
86 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); | 57 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); |
87 fBatch.fCoverageIgnored = !opt.readsCoverage(); | 58 fBatch.fCoverageIgnored = !opt.readsCoverage(); |
88 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); | 59 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); |
89 } | 60 } |
90 | 61 |
91 void generateGeometry(GrBatchTarget* batchTarget) override { | 62 void generateGeometry(GrBatchTarget* batchTarget) override { |
92 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | 63 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); |
93 | 64 |
94 SkAutoTUnref<const GrGeometryProcessor> gp(create_fill_rect_gp(canTweakA lphaForCoverage, | 65 SkAutoTUnref<const GrGeometryProcessor> gp(CreateFillRectGP(canTweakAlph aForCoverage, |
95 this->vie wMatrix(), | 66 this->viewMa trix(), |
96 this->use sLocalCoords(), | 67 this->usesLo calCoords(), |
robertphillips
2015/08/12 16:31:20
rm the 'this->' on the static method ?
| |
97 this->cov erageIgnored())); | 68 this->LocalC oordsType(), |
69 this->covera geIgnored())); | |
98 if (!gp) { | 70 if (!gp) { |
99 SkDebugf("Couldn't create GrGeometryProcessor\n"); | 71 SkDebugf("Couldn't create GrGeometryProcessor\n"); |
100 return; | 72 return; |
101 } | 73 } |
102 | 74 |
103 batchTarget->initDraw(gp, this->pipeline()); | 75 batchTarget->initDraw(gp, this->pipeline()); |
104 | 76 |
105 size_t vertexStride = gp->getVertexStride(); | 77 size_t vertexStride = gp->getVertexStride(); |
robertphillips
2015/08/12 16:31:20
same here ?
| |
106 SkASSERT(canTweakAlphaForCoverage ? | 78 SkASSERT(this->StrideCheck(vertexStride, canTweakAlphaForCoverage, |
107 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | 79 this->usesLocalCoords())); |
108 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr)); | |
109 int instanceCount = fGeoData.count(); | 80 int instanceCount = fGeoData.count(); |
110 | 81 |
111 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer( | 82 SkAutoTUnref<const GrIndexBuffer> indexBuffer(this->getIndexBuffer( |
112 batchTarget->resourceProvider())); | 83 batchTarget->resourceProvider())); |
robertphillips
2015/08/12 16:31:20
Hmm .. a bit surprised we need the "typename Base:
| |
113 InstancedHelper helper; | 84 typename Base::InstancedHelper helper; |
114 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride, | 85 void* vertices = helper.init(batchTarget, kTriangles_GrPrimitiveType, ve rtexStride, |
115 indexBuffer, kVertsPerAAFillRect, kIndicesP erAAFillRect, | 86 indexBuffer, kVertsPerAAFillRect, kIndicesP erAAFillRect, |
116 instanceCount); | 87 instanceCount); |
117 if (!vertices || !indexBuffer) { | 88 if (!vertices || !indexBuffer) { |
118 SkDebugf("Could not allocate vertices\n"); | 89 SkDebugf("Could not allocate vertices\n"); |
119 return; | 90 return; |
120 } | 91 } |
121 | 92 |
122 for (int i = 0; i < instanceCount; i++) { | 93 for (int i = 0; i < instanceCount; i++) { |
123 const Geometry& args = fGeoData[i]; | |
124 this->generateAAFillRectGeometry(vertices, | 94 this->generateAAFillRectGeometry(vertices, |
125 i * kVertsPerAAFillRect * vertexStr ide, | 95 i * kVertsPerAAFillRect * vertexStr ide, |
126 vertexStride, | 96 vertexStride, |
127 args.fColor, | 97 fGeoData[i], |
128 args.fViewMatrix, | |
129 args.fRect, | |
130 args.fDevRect, | |
131 canTweakAlphaForCoverage); | 98 canTweakAlphaForCoverage); |
132 } | 99 } |
133 | 100 |
134 helper.issueDraw(batchTarget); | 101 helper.issueDraw(batchTarget); |
135 } | 102 } |
136 | 103 |
137 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | 104 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
138 | 105 |
106 // to avoid even the initial copy of the struct, we have a getter for the fi rst item which | |
107 // is used to seed the batch with its initial geometry. After seeding, the client should call | |
108 // init() so the Batch can initialize itself | |
robertphillips
2015/08/12 16:31:20
"const Geometry& geometry() const" ?
If not should
| |
109 Geometry& geometry() { return fGeoData[0]; } | |
110 void init() { | |
111 const Geometry& geo = fGeoData[0]; | |
112 this->setBounds(geo.fDevRect); | |
113 } | |
114 | |
115 | |
139 private: | 116 private: |
140 AAFillRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& rec t, | 117 AAFillRectBatch() { |
141 const SkRect& devRect) { | 118 this->template initClassID<Base>(); |
142 this->initClassID<AAFillRectBatch>(); | |
143 Geometry& geometry = fGeoData.push_back(); | |
144 geometry.fRect = rect; | |
145 geometry.fViewMatrix = viewMatrix; | |
146 geometry.fDevRect = devRect; | |
147 geometry.fColor = color; | |
148 | 119 |
149 this->setBounds(geometry.fDevRect); | 120 // Push back an initial geometry |
121 fGeoData.push_back(); | |
150 } | 122 } |
151 | 123 |
152 static const int kNumAAFillRectsInIndexBuffer = 256; | 124 static const int kNumAAFillRectsInIndexBuffer = 256; |
153 static const int kVertsPerAAFillRect = 8; | 125 static const int kVertsPerAAFillRect = 8; |
154 static const int kIndicesPerAAFillRect = 30; | 126 static const int kIndicesPerAAFillRect = 30; |
155 | 127 |
156 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) { | 128 const GrIndexBuffer* getIndexBuffer(GrResourceProvider* resourceProvider) { |
157 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); | 129 GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); |
158 | 130 |
159 static const uint16_t gFillAARectIdx[] = { | 131 static const uint16_t gFillAARectIdx[] = { |
(...skipping 15 matching lines...) Expand all Loading... | |
175 bool colorIgnored() const { return fBatch.fColorIgnored; } | 147 bool colorIgnored() const { return fBatch.fColorIgnored; } |
176 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | 148 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } |
177 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } | 149 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
178 | 150 |
179 bool onCombineIfPossible(GrBatch* t) override { | 151 bool onCombineIfPossible(GrBatch* t) override { |
180 if (!this->pipeline()->isEqual(*t->pipeline())) { | 152 if (!this->pipeline()->isEqual(*t->pipeline())) { |
181 return false; | 153 return false; |
182 } | 154 } |
183 | 155 |
184 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); | 156 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); |
185 | 157 if (!this->onCanCombineLocalCoords(this->viewMatrix(), that->viewMatrix( ), |
186 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | 158 this->usesLocalCoords())) { |
187 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | |
188 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | |
189 // using vertex attributes in these cases, but haven't investigated that | |
190 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) { | |
191 return false; | 159 return false; |
192 } | 160 } |
193 | 161 |
194 if (this->color() != that->color()) { | 162 if (this->color() != that->color()) { |
195 fBatch.fColor = GrColor_ILLEGAL; | 163 fBatch.fColor = GrColor_ILLEGAL; |
196 } | 164 } |
197 | 165 |
198 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to | 166 // In the event of two batches, one who can tweak, one who cannot, we ju st fall back to |
199 // not tweaking | 167 // not tweaking |
200 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { | 168 if (this->canTweakAlphaForCoverage() != that->canTweakAlphaForCoverage() ) { |
201 fBatch.fCanTweakAlphaForCoverage = false; | 169 fBatch.fCanTweakAlphaForCoverage = false; |
202 } | 170 } |
203 | 171 |
204 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | 172 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; |
205 this->joinBounds(that->bounds()); | 173 this->joinBounds(that->bounds()); |
206 return true; | 174 return true; |
207 } | 175 } |
208 | 176 |
209 void generateAAFillRectGeometry(void* vertices, | 177 void generateAAFillRectGeometry(void* vertices, |
210 size_t offset, | 178 size_t offset, |
211 size_t vertexStride, | 179 size_t vertexStride, |
212 GrColor color, | 180 const Geometry& args, |
213 const SkMatrix& viewMatrix, | |
214 const SkRect& rect, | |
215 const SkRect& devRect, | |
216 bool tweakAlphaForCoverage) const { | 181 bool tweakAlphaForCoverage) const { |
217 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | 182 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; |
218 | 183 |
219 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 184 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); |
220 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); | 185 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride); |
221 | 186 |
222 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); | 187 SkScalar inset = SkMinScalar(args.fDevRect.width(), SK_Scalar1); |
223 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); | 188 inset = SK_ScalarHalf * SkMinScalar(inset, args.fDevRect.height()); |
224 | 189 |
225 if (viewMatrix.rectStaysRect()) { | 190 if (args.fViewMatrix.rectStaysRect()) { |
226 set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_Sc alarHalf); | 191 set_inset_fan(fan0Pos, vertexStride, args.fDevRect, -SK_ScalarHalf, -SK_ScalarHalf); |
227 set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset); | 192 set_inset_fan(fan1Pos, vertexStride, args.fDevRect, inset, inset); |
228 } else { | 193 } else { |
229 // compute transformed (1, 0) and (0, 1) vectors | 194 // compute transformed (1, 0) and (0, 1) vectors |
230 SkVector vec[2] = { | 195 SkVector vec[2] = { |
231 { viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY] }, | 196 { args.fViewMatrix[SkMatrix::kMScaleX], args.fViewMatrix[SkMatrix: :kMSkewY] }, |
232 { viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY] } | 197 { args.fViewMatrix[SkMatrix::kMSkewX], args.fViewMatrix[SkMatrix: :kMScaleY] } |
233 }; | 198 }; |
234 | 199 |
235 vec[0].normalize(); | 200 vec[0].normalize(); |
236 vec[0].scale(SK_ScalarHalf); | 201 vec[0].scale(SK_ScalarHalf); |
237 vec[1].normalize(); | 202 vec[1].normalize(); |
238 vec[1].scale(SK_ScalarHalf); | 203 vec[1].scale(SK_ScalarHalf); |
239 | 204 |
240 // create the rotated rect | 205 // create the rotated rect |
241 fan0Pos->setRectFan(rect.fLeft, rect.fTop, | 206 fan0Pos->setRectFan(args.fRect.fLeft, args.fRect.fTop, |
242 rect.fRight, rect.fBottom, vertexStride); | 207 args.fRect.fRight, args.fRect.fBottom, vertexStr ide); |
243 viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); | 208 args.fViewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4); |
244 | 209 |
245 // Now create the inset points and then outset the original | 210 // Now create the inset points and then outset the original |
246 // rotated points | 211 // rotated points |
247 | 212 |
248 // TL | 213 // TL |
249 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = | 214 *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) = |
250 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v ec[1]; | 215 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + v ec[1]; |
251 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[ 1]; | 216 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[ 1]; |
252 // BL | 217 // BL |
253 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = | 218 *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) = |
254 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v ec[1]; | 219 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - v ec[1]; |
255 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[ 1]; | 220 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[ 1]; |
256 // BR | 221 // BR |
257 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = | 222 *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) = |
258 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v ec[1]; | 223 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - v ec[1]; |
259 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[ 1]; | 224 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[ 1]; |
260 // TR | 225 // TR |
261 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = | 226 *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) = |
262 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v ec[1]; | 227 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + v ec[1]; |
263 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[ 1]; | 228 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[ 1]; |
264 } | 229 } |
265 | 230 |
robertphillips
2015/08/12 16:31:20
rm "this->" ?
| |
231 this->PostGenerateHook(verts, vertexStride, fan0Pos, args); | |
232 | |
266 // Make verts point to vertex color and then set all the color and cover age vertex attrs | 233 // Make verts point to vertex color and then set all the color and cover age vertex attrs |
267 // values. | 234 // values. |
268 verts += sizeof(SkPoint); | 235 verts += sizeof(SkPoint); |
269 for (int i = 0; i < 4; ++i) { | 236 for (int i = 0; i < 4; ++i) { |
270 if (tweakAlphaForCoverage) { | 237 if (tweakAlphaForCoverage) { |
271 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | 238 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; |
272 } else { | 239 } else { |
273 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 240 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo lor; |
274 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0; | 241 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrCo lor)) = 0; |
275 } | 242 } |
276 } | 243 } |
277 | 244 |
278 int scale; | 245 int scale; |
279 if (inset < SK_ScalarHalf) { | 246 if (inset < SK_ScalarHalf) { |
280 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ; | 247 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)) ; |
281 SkASSERT(scale >= 0 && scale <= 255); | 248 SkASSERT(scale >= 0 && scale <= 255); |
282 } else { | 249 } else { |
283 scale = 0xff; | 250 scale = 0xff; |
284 } | 251 } |
285 | 252 |
286 verts += 4 * vertexStride; | 253 verts += 4 * vertexStride; |
287 | 254 |
288 float innerCoverage = GrNormalizeByteToFloat(scale); | 255 float innerCoverage = GrNormalizeByteToFloat(scale); |
289 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale ); | 256 GrColor scaledColor = (0xff == scale) ? args.fColor : SkAlphaMulQ(args.f Color, scale); |
290 | 257 |
291 for (int i = 0; i < 4; ++i) { | 258 for (int i = 0; i < 4; ++i) { |
292 if (tweakAlphaForCoverage) { | 259 if (tweakAlphaForCoverage) { |
293 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor; | 260 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledCo lor; |
294 } else { | 261 } else { |
295 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 262 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = args.fCo lor; |
296 *reinterpret_cast<float*>(verts + i * vertexStride + | 263 *reinterpret_cast<float*>(verts + i * vertexStride + |
297 sizeof(GrColor)) = innerCoverage; | 264 sizeof(GrColor)) = innerCoverage; |
298 } | 265 } |
299 } | 266 } |
300 } | 267 } |
301 | 268 |
269 static const GrGeometryProcessor* CreateFillRectGP( | |
270 bool tweakAlphaForCoverage, | |
271 const SkMatrix& viewMatrix, | |
272 bool usesLocalCoords, | |
273 GrDefaultGeoProcFactory::LocalCoords::T ype localCoordsType, | |
274 bool coverageIgnored) { | |
275 using namespace GrDefaultGeoProcFactory; | |
276 | |
277 Color color(Color::kAttribute_Type); | |
278 Coverage::Type coverageType; | |
279 // TODO remove coverage if coverage is ignored | |
280 /*if (coverageIgnored) { | |
281 coverageType = Coverage::kNone_Type; | |
282 } else*/ if (tweakAlphaForCoverage) { | |
283 coverageType = Coverage::kSolid_Type; | |
284 } else { | |
285 coverageType = Coverage::kAttribute_Type; | |
286 } | |
287 Coverage coverage(coverageType); | |
288 | |
289 // We assume the caller has inverted the viewmatrix | |
290 LocalCoords localCoords(usesLocalCoords ? localCoordsType : LocalCoords: :kUnused_Type); | |
291 if (LocalCoords::kHasExplicit_Type == localCoordsType) { | |
292 return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I()); | |
293 } else { | |
294 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix ); | |
295 } | |
296 } | |
297 | |
302 struct BatchTracker { | 298 struct BatchTracker { |
303 GrColor fColor; | 299 GrColor fColor; |
304 bool fUsesLocalCoords; | 300 bool fUsesLocalCoords; |
305 bool fColorIgnored; | 301 bool fColorIgnored; |
306 bool fCoverageIgnored; | 302 bool fCoverageIgnored; |
307 bool fCanTweakAlphaForCoverage; | 303 bool fCanTweakAlphaForCoverage; |
308 }; | 304 }; |
309 | 305 |
310 BatchTracker fBatch; | 306 BatchTracker fBatch; |
311 SkSTArray<1, Geometry, true> fGeoData; | 307 SkSTArray<1, Geometry, true> fGeoData; |
312 }; | 308 }; |
313 | 309 |
robertphillips
2015/08/12 16:31:20
Can we document somewhere what the two base classe
| |
310 class AAFillRectBatchNoLocalMatrixImp : public GrBatch { | |
311 public: | |
312 struct Geometry { | |
313 SkMatrix fViewMatrix; | |
314 SkRect fRect; | |
315 SkRect fDevRect; | |
316 GrColor fColor; | |
317 }; | |
318 | |
319 protected: | |
robertphillips
2015/08/12 16:31:20
Is this supposed to be static ?
| |
320 inline bool onCanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& th eirs, | |
321 bool usesLocalCoords) { | |
322 // We apply the viewmatrix to the rect points on the cpu. However, if t he pipeline uses | |
323 // local coords then we won't be able to batch. We could actually uploa d the viewmatrix | |
324 // using vertex attributes in these cases, but haven't investigated that | |
325 return !usesLocalCoords || mine.cheapEqualTo(theirs); | |
326 } | |
327 | |
328 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | |
329 return GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type; | |
330 } | |
331 | |
332 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov erage, | |
333 bool usesLocalCoords) { | |
robertphillips
2015/08/12 16:31:19
SkASSERT(!usesLocalCoords); ?
joshualitt
2015/08/12 17:07:41
this guy can use local coords but he does so throu
| |
334 return canTweakAlphaForCoverage ? | |
335 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAt tr) : | |
336 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorCo verageAttr); | |
337 } | |
338 | |
339 inline static void PostGenerateHook(intptr_t, size_t, SkPoint*, const Geomet ry&) {} | |
340 }; | |
341 | |
342 class AAFillRectBatchLocalMatrixImp : public GrBatch { | |
343 public: | |
344 struct Geometry { | |
345 SkMatrix fViewMatrix; | |
346 SkMatrix fLocalMatrix; | |
347 SkRect fRect; | |
348 SkRect fDevRect; | |
349 GrColor fColor; | |
350 }; | |
351 | |
352 protected: | |
353 inline bool onCanCombineLocalCoords(const SkMatrix& mine, const SkMatrix& th eirs, | |
354 bool usesLocalCoords) { | |
355 return true; | |
356 } | |
357 | |
358 inline static GrDefaultGeoProcFactory::LocalCoords::Type LocalCoordsType() { | |
359 return GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type; | |
360 } | |
361 | |
362 inline static bool StrideCheck(size_t vertexStride, bool canTweakAlphaForCov erage, | |
363 bool usesLocalCoords) { | |
364 // Whomever created us should not have done so if there are no local coo rds | |
365 SkASSERT(usesLocalCoords); | |
366 return canTweakAlphaForCoverage ? | |
367 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordAttr) : | |
368 vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLo calCoordCoverage); | |
369 } | |
370 | |
371 inline static void PostGenerateHook(intptr_t vertices, size_t vertexStride, | |
372 SkPoint* fan0Pos, const Geometry& args) { | |
373 SkMatrix invViewMatrix; | |
374 if (!args.fViewMatrix.invert(&invViewMatrix)) { | |
375 SkASSERT(false); | |
376 invViewMatrix = SkMatrix::I(); | |
377 } | |
378 SkMatrix localCoordMatrix; | |
379 localCoordMatrix.setConcat(args.fLocalMatrix, invViewMatrix); | |
380 SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(vertices + vertexStride - sizeof(SkPoint)); | |
381 localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8); | |
382 } | |
383 }; | |
384 | |
385 typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalM atrix; | |
386 typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatri x; | |
387 | |
314 namespace GrAAFillRectBatch { | 388 namespace GrAAFillRectBatch { |
315 | 389 |
316 GrBatch* Create(GrColor color, | 390 GrBatch* Create(GrColor color, |
317 const SkMatrix& viewMatrix, | 391 const SkMatrix& viewMatrix, |
318 const SkRect& rect, | 392 const SkRect& rect, |
319 const SkRect& devRect) { | 393 const SkRect& devRect) { |
320 return AAFillRectBatch::Create(color, viewMatrix, rect, devRect); | 394 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create() ; |
395 AAFillRectBatchNoLocalMatrix::Geometry& geo = batch->geometry(); | |
396 geo.fColor = color; | |
397 geo.fViewMatrix = viewMatrix; | |
398 geo.fRect = rect; | |
399 geo.fDevRect = devRect; | |
400 batch->init(); | |
401 return batch; | |
402 } | |
403 | |
404 GrBatch* Create(GrColor color, | |
405 const SkMatrix& viewMatrix, | |
406 const SkMatrix& localMatrix, | |
407 const SkRect& rect, | |
408 const SkRect& devRect) { | |
409 AAFillRectBatchLocalMatrix* batch = AAFillRectBatchLocalMatrix::Create(); | |
410 AAFillRectBatchLocalMatrix::Geometry& geo = batch->geometry(); | |
411 geo.fColor = color; | |
412 geo.fViewMatrix = viewMatrix; | |
413 geo.fLocalMatrix = localMatrix; | |
414 geo.fRect = rect; | |
415 geo.fDevRect = devRect; | |
416 batch->init(); | |
417 return batch; | |
321 } | 418 } |
322 | 419 |
323 }; | 420 }; |
324 | 421 |
325 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 422 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
326 | 423 |
327 #ifdef GR_TEST_UTILS | 424 #ifdef GR_TEST_UTILS |
328 | 425 |
329 #include "GrBatchTest.h" | 426 #include "GrBatchTest.h" |
330 | 427 |
robertphillips
2015/08/12 16:31:20
Seems like we need to test both here.
| |
331 BATCH_TEST_DEFINE(AAFillRectBatch) { | 428 BATCH_TEST_DEFINE(AAFillRectBatch) { |
332 GrColor color = GrRandomColor(random); | 429 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create() ; |
333 SkMatrix viewMatrix = GrTest::TestMatrix(random); | 430 AAFillRectBatchNoLocalMatrix::Geometry& geo = batch->geometry(); |
334 SkRect rect = GrTest::TestRect(random); | 431 geo.fColor = GrRandomColor(random); |
335 SkRect devRect = GrTest::TestRect(random); | 432 geo.fViewMatrix = GrTest::TestMatrix(random); |
336 return AAFillRectBatch::Create(color, viewMatrix, rect, devRect); | 433 geo.fRect = GrTest::TestRect(random); |
434 geo.fDevRect = GrTest::TestRect(random); | |
435 batch->init(); | |
436 return batch; | |
337 } | 437 } |
338 | 438 |
339 #endif | 439 #endif |
OLD | NEW |