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