Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: src/gpu/GrOvalRenderer.cpp

Issue 1764923003: Circle GP/batch housecleaning (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix indent Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 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 "GrOvalRenderer.h" 8 #include "GrOvalRenderer.h"
9 9
10 #include "GrBatchFlushState.h" 10 #include "GrBatchFlushState.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 return m.isSimilarity(); 55 return m.isSimilarity();
56 } 56 }
57 57
58 } 58 }
59 59
60 /////////////////////////////////////////////////////////////////////////////// 60 ///////////////////////////////////////////////////////////////////////////////
61 61
62 /** 62 /**
63 * The output of this effect is a modulation of the input color and coverage for a circle. It 63 * The output of this effect is a modulation of the input color and coverage for a circle. It
64 * operates in a space normalized by the circle radius (outer radius in the case of a stroke) 64 * operates in a space normalized by the circle radius (outer radius in the case of a stroke)
65 * with origin at the circle center. Two vertex attributes are used: 65 * with origin at the circle center. Three vertex attributes are used:
66 * vec2f : position in device space of the bounding geometry vertices 66 * vec2f : position in device space of the bounding geometry vertices
67 * vec4ub: color
67 * vec4f : (p.xy, outerRad, innerRad) 68 * vec4f : (p.xy, outerRad, innerRad)
68 * p is the position in the normalized space. 69 * p is the position in the normalized space.
69 * outerRad is the outerRadius in device space. 70 * outerRad is the outerRadius in device space.
70 * innerRad is the innerRadius in normalized space (ignored if not s troking). 71 * innerRad is the innerRadius in normalized space (ignored if not s troking).
71 */ 72 */
72 73
73 class CircleEdgeEffect : public GrGeometryProcessor { 74 class CircleGeometryProcessor : public GrGeometryProcessor {
74 public: 75 public:
75 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri x& localMatrix, 76 CircleGeometryProcessor(bool stroke, const SkMatrix& localMatrix) : fLocalMa trix(localMatrix){
76 bool usesLocalCoords) { 77 this->initClassID<CircleGeometryProcessor>();
77 return new CircleEdgeEffect(color, stroke, localMatrix, usesLocalCoords) ; 78 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType,
79 kHigh_GrSLPrecision));
80 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
81 fInCircleEdge = &this->addVertexAttrib(Attribute("inCircleEdge",
82 kVec4f_GrVertexAttribTy pe));
83 fStroke = stroke;
78 } 84 }
79 85
80 const Attribute* inPosition() const { return fInPosition; } 86 const Attribute* inPosition() const { return fInPosition; }
81 const Attribute* inColor() const { return fInColor; } 87 const Attribute* inColor() const { return fInColor; }
82 const Attribute* inCircleEdge() const { return fInCircleEdge; } 88 const Attribute* inCircleEdge() const { return fInCircleEdge; }
83 GrColor color() const { return fColor; }
84 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
85 const SkMatrix& localMatrix() const { return fLocalMatrix; } 89 const SkMatrix& localMatrix() const { return fLocalMatrix; }
86 bool usesLocalCoords() const { return fUsesLocalCoords; } 90 virtual ~CircleGeometryProcessor() {}
87 virtual ~CircleEdgeEffect() {}
88 91
89 const char* name() const override { return "CircleEdge"; } 92 const char* name() const override { return "CircleEdge"; }
90 93
91 inline bool isStroked() const { return fStroke; }
92
93 class GLSLProcessor : public GrGLSLGeometryProcessor { 94 class GLSLProcessor : public GrGLSLGeometryProcessor {
94 public: 95 public:
95 GLSLProcessor() {} 96 GLSLProcessor() {}
96 97
97 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 98 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
98 const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>(); 99 const CircleGeometryProcessor& cgp = args.fGP.cast<CircleGeometryPro cessor>();
99 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 100 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
100 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 101 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
101 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 102 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
102 103
103 // emit attributes 104 // emit attributes
104 varyingHandler->emitAttributes(ce); 105 varyingHandler->emitAttributes(cgp);
105 106
106 GrGLSLVertToFrag v(kVec4f_GrSLType); 107 GrGLSLVertToFrag v(kVec4f_GrSLType);
107 varyingHandler->addVarying("CircleEdge", &v); 108 varyingHandler->addVarying("CircleEdge", &v);
108 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->f Name); 109 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), cgp.inCircleEdge()-> fName);
109 110
110 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 111 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
111 // setup pass through color 112 // setup pass through color
112 if (!ce.colorIgnored()) { 113 varyingHandler->addPassThroughAttribute(cgp.inColor(), args.fOutputC olor);
113 varyingHandler->addPassThroughAttribute(ce.inColor(), args.fOutp utColor);
114 }
115 114
116 // Setup position 115 // Setup position
117 this->setupPosition(vertBuilder, gpArgs, ce.inPosition()->fName); 116 this->setupPosition(vertBuilder, gpArgs, cgp.inPosition()->fName);
118 117
119 // emit transforms 118 // emit transforms
120 this->emitTransforms(vertBuilder, 119 this->emitTransforms(vertBuilder,
121 varyingHandler, 120 varyingHandler,
122 uniformHandler, 121 uniformHandler,
123 gpArgs->fPositionVar, 122 gpArgs->fPositionVar,
124 ce.inPosition()->fName, 123 cgp.inPosition()->fName,
125 ce.localMatrix(), 124 cgp.localMatrix(),
126 args.fTransformsIn, 125 args.fTransformsIn,
127 args.fTransformsOut); 126 args.fTransformsOut);
128 127
129 fragBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); 128 fragBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn());
130 fragBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d), 0.0, 1.0);", 129 fragBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d), 0.0, 1.0);",
131 v.fsIn()); 130 v.fsIn());
132 if (ce.isStroked()) { 131 if (cgp.fStroke) {
133 fragBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - % s.w), 0.0, 1.0);", 132 fragBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - % s.w), 0.0, 1.0);",
134 v.fsIn(), v.fsIn()); 133 v.fsIn(), v.fsIn());
135 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); 134 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;");
136 } 135 }
137 136
138 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge); 137 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge);
139 } 138 }
140 139
141 static void GenKey(const GrGeometryProcessor& gp, 140 static void GenKey(const GrGeometryProcessor& gp,
142 const GrGLSLCaps&, 141 const GrGLSLCaps&,
143 GrProcessorKeyBuilder* b) { 142 GrProcessorKeyBuilder* b) {
144 const CircleEdgeEffect& ce = gp.cast<CircleEdgeEffect>(); 143 const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor >();
145 uint16_t key = ce.isStroked() ? 0x1 : 0x0; 144 uint16_t key = cgp.fStroke ? 0x1 : 0x0;
146 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0 x2 : 0x0; 145 key |= cgp.localMatrix().hasPerspective() ? 0x2 : 0x0;
147 key |= ce.colorIgnored() ? 0x4 : 0x0;
148 b->add32(key); 146 b->add32(key);
149 } 147 }
150 148
151 void setData(const GrGLSLProgramDataManager& pdman, 149 void setData(const GrGLSLProgramDataManager& pdman,
152 const GrPrimitiveProcessor& gp) override { 150 const GrPrimitiveProcessor& gp) override {
153 } 151 }
154 152
155 void setTransformData(const GrPrimitiveProcessor& primProc, 153 void setTransformData(const GrPrimitiveProcessor& primProc,
156 const GrGLSLProgramDataManager& pdman, 154 const GrGLSLProgramDataManager& pdman,
157 int index, 155 int index,
158 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override { 156 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override {
159 this->setTransformDataHelper<CircleEdgeEffect>(primProc, pdman, inde x, transforms); 157 this->setTransformDataHelper<CircleGeometryProcessor>(primProc, pdma n, index,
158 transforms);
160 } 159 }
161 160
162 private: 161 private:
163 typedef GrGLSLGeometryProcessor INHERITED; 162 typedef GrGLSLGeometryProcessor INHERITED;
164 }; 163 };
165 164
166 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { 165 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override {
167 GLSLProcessor::GenKey(*this, caps, b); 166 GLSLProcessor::GenKey(*this, caps, b);
168 } 167 }
169 168
170 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de { 169 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de {
171 return new GLSLProcessor(); 170 return new GLSLProcessor();
172 } 171 }
173 172
174 private: 173 private:
175 CircleEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix, bo ol usesLocalCoords) 174 SkMatrix fLocalMatrix;
176 : fColor(color)
177 , fLocalMatrix(localMatrix)
178 , fUsesLocalCoords(usesLocalCoords) {
179 this->initClassID<CircleEdgeEffect>();
180 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType,
181 kHigh_GrSLPrecision));
182 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
183 fInCircleEdge = &this->addVertexAttrib(Attribute("inCircleEdge",
184 kVec4f_GrVertexAttrib Type));
185 fStroke = stroke;
186 }
187
188 GrColor fColor;
189 SkMatrix fLocalMatrix;
190 const Attribute* fInPosition; 175 const Attribute* fInPosition;
191 const Attribute* fInColor; 176 const Attribute* fInColor;
192 const Attribute* fInCircleEdge; 177 const Attribute* fInCircleEdge;
193 bool fStroke; 178 bool fStroke;
194 bool fUsesLocalCoords;
195 179
196 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 180 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
197 181
198 typedef GrGeometryProcessor INHERITED; 182 typedef GrGeometryProcessor INHERITED;
199 }; 183 };
200 184
201 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); 185 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor);
202 186
203 const GrGeometryProcessor* CircleEdgeEffect::TestCreate(GrProcessorTestData* d) { 187 const GrGeometryProcessor* CircleGeometryProcessor::TestCreate(GrProcessorTestDa ta* d) {
204 return CircleEdgeEffect::Create(GrRandomColor(d->fRandom), 188 return new CircleGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatri x(d->fRandom));
205 d->fRandom->nextBool(),
206 GrTest::TestMatrix(d->fRandom),
207 d->fRandom->nextBool());
208 } 189 }
209 190
210 /////////////////////////////////////////////////////////////////////////////// 191 ///////////////////////////////////////////////////////////////////////////////
211 192
212 /** 193 /**
213 * The output of this effect is a modulation of the input color and coverage for an axis-aligned 194 * The output of this effect is a modulation of the input color and coverage for an axis-aligned
214 * ellipse, specified as a 2D offset from center, and the reciprocals of the out er and inner radii, 195 * ellipse, specified as a 2D offset from center, and the reciprocals of the out er and inner radii,
215 * in both x and y directions. 196 * in both x and y directions.
216 * 197 *
217 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. 198 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0.
218 */ 199 */
219 200
220 class EllipseEdgeEffect : public GrGeometryProcessor { 201 class EllipseGeometryProcessor : public GrGeometryProcessor {
221 public: 202 public:
222 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri x& localMatrix, 203 EllipseGeometryProcessor(bool stroke, const SkMatrix& localMatrix)
223 bool usesLocalCoords) { 204 : fLocalMatrix(localMatrix) {
224 return new EllipseEdgeEffect(color, stroke, localMatrix, usesLocalCoords ); 205 this->initClassID<EllipseGeometryProcessor>();
206 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType));
207 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
208 fInEllipseOffset = &this->addVertexAttrib(Attribute("inEllipseOffset",
209 kVec2f_GrVertexAttri bType));
210 fInEllipseRadii = &this->addVertexAttrib(Attribute("inEllipseRadii",
211 kVec4f_GrVertexAttrib Type));
212 fStroke = stroke;
225 } 213 }
226 214
227 virtual ~EllipseEdgeEffect() {} 215 virtual ~EllipseGeometryProcessor() {}
228 216
229 const char* name() const override { return "EllipseEdge"; } 217 const char* name() const override { return "EllipseEdge"; }
230 218
231 const Attribute* inPosition() const { return fInPosition; } 219 const Attribute* inPosition() const { return fInPosition; }
232 const Attribute* inColor() const { return fInColor; } 220 const Attribute* inColor() const { return fInColor; }
233 const Attribute* inEllipseOffset() const { return fInEllipseOffset; } 221 const Attribute* inEllipseOffset() const { return fInEllipseOffset; }
234 const Attribute* inEllipseRadii() const { return fInEllipseRadii; } 222 const Attribute* inEllipseRadii() const { return fInEllipseRadii; }
235 GrColor color() const { return fColor; }
236 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
237 const SkMatrix& localMatrix() const { return fLocalMatrix; } 223 const SkMatrix& localMatrix() const { return fLocalMatrix; }
238 bool usesLocalCoords() const { return fUsesLocalCoords; }
239
240 inline bool isStroked() const { return fStroke; }
241 224
242 class GLSLProcessor : public GrGLSLGeometryProcessor { 225 class GLSLProcessor : public GrGLSLGeometryProcessor {
243 public: 226 public:
244 GLSLProcessor() {} 227 GLSLProcessor() {}
245 228
246 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 229 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
247 const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>(); 230 const EllipseGeometryProcessor& egp = args.fGP.cast<EllipseGeometryP rocessor>();
248 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 231 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
249 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 232 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
250 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 233 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
251 234
252 // emit attributes 235 // emit attributes
253 varyingHandler->emitAttributes(ee); 236 varyingHandler->emitAttributes(egp);
254 237
255 GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType); 238 GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType);
256 varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets); 239 varyingHandler->addVarying("EllipseOffsets", &ellipseOffsets);
257 vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(), 240 vertBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(),
258 ee.inEllipseOffset()->fName); 241 egp.inEllipseOffset()->fName);
259 242
260 GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType); 243 GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType);
261 varyingHandler->addVarying("EllipseRadii", &ellipseRadii); 244 varyingHandler->addVarying("EllipseRadii", &ellipseRadii);
262 vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(), 245 vertBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(),
263 ee.inEllipseRadii()->fName); 246 egp.inEllipseRadii()->fName);
264 247
265 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 248 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
266 // setup pass through color 249 // setup pass through color
267 if (!ee.colorIgnored()) { 250 varyingHandler->addPassThroughAttribute(egp.inColor(), args.fOutputC olor);
268 varyingHandler->addPassThroughAttribute(ee.inColor(), args.fOutp utColor);
269 }
270 251
271 // Setup position 252 // Setup position
272 this->setupPosition(vertBuilder, gpArgs, ee.inPosition()->fName); 253 this->setupPosition(vertBuilder, gpArgs, egp.inPosition()->fName);
273 254
274 // emit transforms 255 // emit transforms
275 this->emitTransforms(vertBuilder, 256 this->emitTransforms(vertBuilder,
276 varyingHandler, 257 varyingHandler,
277 uniformHandler, 258 uniformHandler,
278 gpArgs->fPositionVar, 259 gpArgs->fPositionVar,
279 ee.inPosition()->fName, 260 egp.inPosition()->fName,
280 ee.localMatrix(), 261 egp.localMatrix(),
281 args.fTransformsIn, 262 args.fTransformsIn,
282 args.fTransformsOut); 263 args.fTransformsOut);
283 264
284 // for outer curve 265 // for outer curve
285 fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOff sets.fsIn(), 266 fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOff sets.fsIn(),
286 ellipseRadii.fsIn()); 267 ellipseRadii.fsIn());
287 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset ) - 1.0;"); 268 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset ) - 1.0;");
288 fragBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", elli pseRadii.fsIn()); 269 fragBuilder->codeAppendf("vec2 grad = 2.0*scaledOffset*%s.xy;", elli pseRadii.fsIn());
289 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); 270 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);");
290 271
291 // avoid calling inversesqrt on zero. 272 // avoid calling inversesqrt on zero.
292 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); 273 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
293 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); 274 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);");
294 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0. 0, 1.0);"); 275 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen, 0. 0, 1.0);");
295 276
296 // for inner curve 277 // for inner curve
297 if (ee.isStroked()) { 278 if (egp.fStroke) {
298 fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;", 279 fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;",
299 ellipseOffsets.fsIn(), ellipseRadii.fsI n()); 280 ellipseOffsets.fsIn(), ellipseRadii.fsI n());
300 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); 281 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;");
301 fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", 282 fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;",
302 ellipseRadii.fsIn()); 283 ellipseRadii.fsIn());
303 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));" ); 284 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));" );
304 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);"); 285 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);");
305 } 286 }
306 287
307 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge); 288 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge);
308 } 289 }
309 290
310 static void GenKey(const GrGeometryProcessor& gp, 291 static void GenKey(const GrGeometryProcessor& gp,
311 const GrGLSLCaps&, 292 const GrGLSLCaps&,
312 GrProcessorKeyBuilder* b) { 293 GrProcessorKeyBuilder* b) {
313 const EllipseEdgeEffect& ee = gp.cast<EllipseEdgeEffect>(); 294 const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcess or>();
314 uint16_t key = ee.isStroked() ? 0x1 : 0x0; 295 uint16_t key = egp.fStroke ? 0x1 : 0x0;
315 key |= ee.usesLocalCoords() && ee.localMatrix().hasPerspective() ? 0 x2 : 0x0; 296 key |= egp.localMatrix().hasPerspective() ? 0x2 : 0x0;
316 key |= ee.colorIgnored() ? 0x4 : 0x0;
317 b->add32(key); 297 b->add32(key);
318 } 298 }
319 299
320 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitivePro cessor& gp) override { 300 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitivePro cessor& gp) override {
321 } 301 }
322 302
323 void setTransformData(const GrPrimitiveProcessor& primProc, 303 void setTransformData(const GrPrimitiveProcessor& primProc,
324 const GrGLSLProgramDataManager& pdman, 304 const GrGLSLProgramDataManager& pdman,
325 int index, 305 int index,
326 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override { 306 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override {
327 this->setTransformDataHelper<EllipseEdgeEffect>(primProc, pdman, ind ex, transforms); 307 this->setTransformDataHelper<EllipseGeometryProcessor>(primProc, pdm an, index,
308 transforms);
328 } 309 }
329 310
330 private: 311 private:
331 typedef GrGLSLGeometryProcessor INHERITED; 312 typedef GrGLSLGeometryProcessor INHERITED;
332 }; 313 };
333 314
334 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { 315 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override {
335 GLSLProcessor::GenKey(*this, caps, b); 316 GLSLProcessor::GenKey(*this, caps, b);
336 } 317 }
337 318
338 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de { 319 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de {
339 return new GLSLProcessor(); 320 return new GLSLProcessor();
340 } 321 }
341 322
342 private: 323 private:
343 EllipseEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix,
344 bool usesLocalCoords)
345 : fColor(color)
346 , fLocalMatrix(localMatrix)
347 , fUsesLocalCoords(usesLocalCoords) {
348 this->initClassID<EllipseEdgeEffect>();
349 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType));
350 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
351 fInEllipseOffset = &this->addVertexAttrib(Attribute("inEllipseOffset",
352 kVec2f_GrVertexAttri bType));
353 fInEllipseRadii = &this->addVertexAttrib(Attribute("inEllipseRadii",
354 kVec4f_GrVertexAttrib Type));
355 fStroke = stroke;
356 }
357
358 const Attribute* fInPosition; 324 const Attribute* fInPosition;
359 const Attribute* fInColor; 325 const Attribute* fInColor;
360 const Attribute* fInEllipseOffset; 326 const Attribute* fInEllipseOffset;
361 const Attribute* fInEllipseRadii; 327 const Attribute* fInEllipseRadii;
362 GrColor fColor;
363 SkMatrix fLocalMatrix; 328 SkMatrix fLocalMatrix;
364 bool fStroke; 329 bool fStroke;
365 bool fUsesLocalCoords;
366 330
367 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 331 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
368 332
369 typedef GrGeometryProcessor INHERITED; 333 typedef GrGeometryProcessor INHERITED;
370 }; 334 };
371 335
372 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); 336 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseGeometryProcessor);
373 337
374 const GrGeometryProcessor* EllipseEdgeEffect::TestCreate(GrProcessorTestData* d) { 338 const GrGeometryProcessor* EllipseGeometryProcessor::TestCreate(GrProcessorTestD ata* d) {
375 return EllipseEdgeEffect::Create(GrRandomColor(d->fRandom), 339 return new EllipseGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatr ix(d->fRandom));
376 d->fRandom->nextBool(),
377 GrTest::TestMatrix(d->fRandom),
378 d->fRandom->nextBool());
379 } 340 }
380 341
381 /////////////////////////////////////////////////////////////////////////////// 342 ///////////////////////////////////////////////////////////////////////////////
382 343
383 /** 344 /**
384 * The output of this effect is a modulation of the input color and coverage for an ellipse, 345 * The output of this effect is a modulation of the input color and coverage for an ellipse,
385 * specified as a 2D offset from center for both the outer and inner paths (if s troked). The 346 * specified as a 2D offset from center for both the outer and inner paths (if s troked). The
386 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c orrected by 347 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c orrected by
387 * using differentials. 348 * using differentials.
388 * 349 *
389 * The result is device-independent and can be used with any affine matrix. 350 * The result is device-independent and can be used with any affine matrix.
390 */ 351 */
391 352
392 class DIEllipseEdgeEffect : public GrGeometryProcessor { 353 enum class DIEllipseStyle { kStroke = 0, kHairline, kFill };
354
355 class DIEllipseGeometryProcessor : public GrGeometryProcessor {
393 public: 356 public:
394 enum Mode { kStroke = 0, kHairline, kFill };
395 357
396 static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix , Mode mode, 358 static GrGeometryProcessor* Create(const SkMatrix& viewMatrix, DIEllipseStyl e style) {
Brian Osman 2016/03/07 14:45:45 Any reason to keep the factory method here (vs. Ci
bsalomon 2016/03/07 14:57:39 Nope, just bleariness. Will change.
bsalomon 2016/03/07 15:53:50 Done, brings it to an even 200 net LOC reduction.
397 bool usesLocalCoords) { 359 return new DIEllipseGeometryProcessor (viewMatrix, style);
398 return new DIEllipseEdgeEffect(color, viewMatrix, mode, usesLocalCoords) ;
399 } 360 }
400 361
401 virtual ~DIEllipseEdgeEffect() {} 362 virtual ~DIEllipseGeometryProcessor() {}
402 363
403 const char* name() const override { return "DIEllipseEdge"; } 364 const char* name() const override { return "DIEllipseEdge"; }
404 365
405 const Attribute* inPosition() const { return fInPosition; } 366 const Attribute* inPosition() const { return fInPosition; }
406 const Attribute* inColor() const { return fInColor; } 367 const Attribute* inColor() const { return fInColor; }
407 const Attribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } 368 const Attribute* inEllipseOffsets0() const { return fInEllipseOffsets0; }
408 const Attribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } 369 const Attribute* inEllipseOffsets1() const { return fInEllipseOffsets1; }
409 GrColor color() const { return fColor; }
410 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
411 const SkMatrix& viewMatrix() const { return fViewMatrix; } 370 const SkMatrix& viewMatrix() const { return fViewMatrix; }
412 bool usesLocalCoords() const { return fUsesLocalCoords; } 371
413
414 inline Mode getMode() const { return fMode; }
415
416 class GLSLProcessor : public GrGLSLGeometryProcessor { 372 class GLSLProcessor : public GrGLSLGeometryProcessor {
417 public: 373 public:
418 GLSLProcessor() 374 GLSLProcessor()
419 : fViewMatrix(SkMatrix::InvalidMatrix()) {} 375 : fViewMatrix(SkMatrix::InvalidMatrix()) {}
420 376
421 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 377 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
422 const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>() ; 378 const DIEllipseGeometryProcessor& diegp = args.fGP.cast<DIEllipseGeo metryProcessor>();
423 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 379 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
424 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 380 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
425 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 381 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
426 382
427 // emit attributes 383 // emit attributes
428 varyingHandler->emitAttributes(ee); 384 varyingHandler->emitAttributes(diegp);
429 385
430 GrGLSLVertToFrag offsets0(kVec2f_GrSLType); 386 GrGLSLVertToFrag offsets0(kVec2f_GrSLType);
431 varyingHandler->addVarying("EllipseOffsets0", &offsets0); 387 varyingHandler->addVarying("EllipseOffsets0", &offsets0);
432 vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(), 388 vertBuilder->codeAppendf("%s = %s;", offsets0.vsOut(),
433 ee.inEllipseOffsets0()->fName); 389 diegp.inEllipseOffsets0()->fName);
434 390
435 GrGLSLVertToFrag offsets1(kVec2f_GrSLType); 391 GrGLSLVertToFrag offsets1(kVec2f_GrSLType);
436 varyingHandler->addVarying("EllipseOffsets1", &offsets1); 392 varyingHandler->addVarying("EllipseOffsets1", &offsets1);
437 vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(), 393 vertBuilder->codeAppendf("%s = %s;", offsets1.vsOut(),
438 ee.inEllipseOffsets1()->fName); 394 diegp.inEllipseOffsets1()->fName);
439 395
440 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 396 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
441 // setup pass through color 397 varyingHandler->addPassThroughAttribute(diegp.inColor(), args.fOutpu tColor);
442 if (!ee.colorIgnored()) {
443 varyingHandler->addPassThroughAttribute(ee.inColor(), args.fOutp utColor);
444 }
445 398
446 // Setup position 399 // Setup position
447 this->setupPosition(vertBuilder, 400 this->setupPosition(vertBuilder,
448 uniformHandler, 401 uniformHandler,
449 gpArgs, 402 gpArgs,
450 ee.inPosition()->fName, 403 diegp.inPosition()->fName,
451 ee.viewMatrix(), 404 diegp.viewMatrix(),
452 &fViewMatrixUniform); 405 &fViewMatrixUniform);
453 406
454 // emit transforms 407 // emit transforms
455 this->emitTransforms(vertBuilder, 408 this->emitTransforms(vertBuilder,
456 varyingHandler, 409 varyingHandler,
457 uniformHandler, 410 uniformHandler,
458 gpArgs->fPositionVar, 411 gpArgs->fPositionVar,
459 ee.inPosition()->fName, 412 diegp.inPosition()->fName,
460 args.fTransformsIn, 413 args.fTransformsIn,
461 args.fTransformsOut); 414 args.fTransformsOut);
462 415
463 SkAssertResult(fragBuilder->enableFeature( 416 SkAssertResult(fragBuilder->enableFeature(
464 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeatur e)); 417 GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeatur e));
465 // for outer curve 418 // for outer curve
466 fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn ()); 419 fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn ());
467 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset ) - 1.0;"); 420 fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset ) - 1.0;");
468 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn()); 421 fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s);", offsets0.fsIn());
469 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn()); 422 fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s);", offsets0.fsIn());
470 fragBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s .y*duvdx.y," 423 fragBuilder->codeAppendf("vec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s .y*duvdx.y,"
471 " 2.0*%s.x*duvdy.x + 2.0*%s .y*duvdy.y);", 424 " 2.0*%s.x*duvdy.x + 2.0*%s .y*duvdy.y);",
472 offsets0.fsIn(), offsets0.fsIn(), offsets0. fsIn(), offsets0.fsIn()); 425 offsets0.fsIn(), offsets0.fsIn(), offsets0. fsIn(),
426 offsets0.fsIn());
473 427
474 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);"); 428 fragBuilder->codeAppend("float grad_dot = dot(grad, grad);");
475 // avoid calling inversesqrt on zero. 429 // avoid calling inversesqrt on zero.
476 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); 430 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
477 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);"); 431 fragBuilder->codeAppend("float invlen = inversesqrt(grad_dot);");
478 if (kHairline == ee.getMode()) { 432 if (DIEllipseStyle::kHairline == diegp.fStyle) {
479 // can probably do this with one step 433 // can probably do this with one step
480 fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen , 0.0, 1.0);"); 434 fragBuilder->codeAppend("float edgeAlpha = clamp(1.0-test*invlen , 0.0, 1.0);");
481 fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0 , 1.0);"); 435 fragBuilder->codeAppend("edgeAlpha *= clamp(1.0+test*invlen, 0.0 , 1.0);");
482 } else { 436 } else {
483 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen , 0.0, 1.0);"); 437 fragBuilder->codeAppend("float edgeAlpha = clamp(0.5-test*invlen , 0.0, 1.0);");
484 } 438 }
485 439
486 // for inner curve 440 // for inner curve
487 if (kStroke == ee.getMode()) { 441 if (DIEllipseStyle::kStroke == diegp.fStyle) {
488 fragBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn( )); 442 fragBuilder->codeAppendf("scaledOffset = %s.xy;", offsets1.fsIn( ));
489 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); 443 fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;");
490 fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn()); 444 fragBuilder->codeAppendf("duvdx = dFdx(%s);", offsets1.fsIn());
491 fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn()); 445 fragBuilder->codeAppendf("duvdy = dFdy(%s);", offsets1.fsIn());
492 fragBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s. y*duvdx.y," 446 fragBuilder->codeAppendf("grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s. y*duvdx.y,"
493 " 2.0*%s.x*duvdy.x + 2.0*%s. y*duvdy.y);", 447 " 2.0*%s.x*duvdy.x + 2.0*%s. y*duvdy.y);",
494 offsets1.fsIn(), offsets1.fsIn(), offse ts1.fsIn(), 448 offsets1.fsIn(), offsets1.fsIn(), offse ts1.fsIn(),
495 offsets1.fsIn()); 449 offsets1.fsIn());
496 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));" ); 450 fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));" );
497 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);"); 451 fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0 , 1.0);");
498 } 452 }
499 453
500 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge); 454 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge);
501 } 455 }
502 456
503 static void GenKey(const GrGeometryProcessor& gp, 457 static void GenKey(const GrGeometryProcessor& gp,
504 const GrGLSLCaps&, 458 const GrGLSLCaps&,
505 GrProcessorKeyBuilder* b) { 459 GrProcessorKeyBuilder* b) {
506 const DIEllipseEdgeEffect& ellipseEffect = gp.cast<DIEllipseEdgeEffe ct>(); 460 const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryP rocessor>();
507 uint16_t key = ellipseEffect.getMode(); 461 uint16_t key = static_cast<uint16_t>(diegp.fStyle);
508 key |= ellipseEffect.colorIgnored() << 9; 462 key |= ComputePosKey(diegp.viewMatrix()) << 10;
509 key |= ComputePosKey(ellipseEffect.viewMatrix()) << 10;
510 b->add32(key); 463 b->add32(key);
511 } 464 }
512 465
513 void setData(const GrGLSLProgramDataManager& pdman, 466 void setData(const GrGLSLProgramDataManager& pdman,
514 const GrPrimitiveProcessor& gp) override { 467 const GrPrimitiveProcessor& gp) override {
515 const DIEllipseEdgeEffect& dee = gp.cast<DIEllipseEdgeEffect>(); 468 const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryP rocessor>();
516 469
517 if (!dee.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dee. viewMatrix())) { 470 if (!diegp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(di egp.viewMatrix())) {
518 fViewMatrix = dee.viewMatrix(); 471 fViewMatrix = diegp.viewMatrix();
519 float viewMatrix[3 * 3]; 472 float viewMatrix[3 * 3];
520 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); 473 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
521 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); 474 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
522 } 475 }
523 } 476 }
524 477
525 private: 478 private:
526 SkMatrix fViewMatrix; 479 SkMatrix fViewMatrix;
527 UniformHandle fViewMatrixUniform; 480 UniformHandle fViewMatrixUniform;
528 481
529 typedef GrGLSLGeometryProcessor INHERITED; 482 typedef GrGLSLGeometryProcessor INHERITED;
530 }; 483 };
531 484
532 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { 485 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override {
533 GLSLProcessor::GenKey(*this, caps, b); 486 GLSLProcessor::GenKey(*this, caps, b);
534 } 487 }
535 488
536 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de { 489 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de {
537 return new GLSLProcessor(); 490 return new GLSLProcessor();
538 } 491 }
539 492
540 private: 493 private:
541 DIEllipseEdgeEffect(GrColor color, const SkMatrix& viewMatrix, Mode mode, 494 DIEllipseGeometryProcessor(const SkMatrix& viewMatrix, DIEllipseStyle style)
542 bool usesLocalCoords) 495 : fViewMatrix(viewMatrix) {
543 : fColor(color) 496 this->initClassID<DIEllipseGeometryProcessor>();
544 , fViewMatrix(viewMatrix)
545 , fUsesLocalCoords(usesLocalCoords) {
546 this->initClassID<DIEllipseEdgeEffect>();
547 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType, 497 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVe rtexAttribType,
548 kHigh_GrSLPrecision)); 498 kHigh_GrSLPrecision));
549 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType)); 499 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexA ttribType));
550 fInEllipseOffsets0 = &this->addVertexAttrib(Attribute("inEllipseOffsets0 ", 500 fInEllipseOffsets0 = &this->addVertexAttrib(Attribute("inEllipseOffsets0 ",
551 kVec2f_GrVertexAtt ribType)); 501 kVec2f_GrVertexAtt ribType));
552 fInEllipseOffsets1 = &this->addVertexAttrib(Attribute("inEllipseOffsets1 ", 502 fInEllipseOffsets1 = &this->addVertexAttrib(Attribute("inEllipseOffsets1 ",
553 kVec2f_GrVertexAtt ribType)); 503 kVec2f_GrVertexAtt ribType));
554 fMode = mode; 504 fStyle = style;
555 } 505 }
556 506
557 const Attribute* fInPosition; 507 const Attribute* fInPosition;
558 const Attribute* fInColor; 508 const Attribute* fInColor;
559 const Attribute* fInEllipseOffsets0; 509 const Attribute* fInEllipseOffsets0;
560 const Attribute* fInEllipseOffsets1; 510 const Attribute* fInEllipseOffsets1;
561 GrColor fColor; 511 SkMatrix fViewMatrix;
562 SkMatrix fViewMatrix; 512 DIEllipseStyle fStyle;
563 Mode fMode;
564 bool fUsesLocalCoords;
565 513
566 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 514 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
567 515
568 typedef GrGeometryProcessor INHERITED; 516 typedef GrGeometryProcessor INHERITED;
569 }; 517 };
570 518
571 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); 519 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseGeometryProcessor);
572 520
573 const GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(GrProcessorTestData* d) { 521 const GrGeometryProcessor* DIEllipseGeometryProcessor::TestCreate(GrProcessorTes tData* d) {
574 return DIEllipseEdgeEffect::Create(GrRandomColor(d->fRandom), 522 return DIEllipseGeometryProcessor::Create(GrTest::TestMatrix(d->fRandom),
575 GrTest::TestMatrix(d->fRandom), 523 (DIEllipseStyle)(d->fRandom->nextR angeU(0,2)));
576 (Mode)(d->fRandom->nextRangeU(0,2)),
577 d->fRandom->nextBool());
578 } 524 }
579 525
580 /////////////////////////////////////////////////////////////////////////////// 526 ///////////////////////////////////////////////////////////////////////////////
581 527
582 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color, 528 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color,
583 const SkMatrix& viewMatrix, 529 const SkMatrix& viewMatrix,
584 const SkRect& oval, 530 const SkRect& oval,
585 const SkStrokeRec& stroke, 531 const SkStrokeRec& stroke,
586 GrShaderCaps* shaderCaps) { 532 GrShaderCaps* shaderCaps) {
587 // we can draw circles 533 // we can draw circles
(...skipping 14 matching lines...) Expand all
602 return nullptr; 548 return nullptr;
603 } 549 }
604 550
605 /////////////////////////////////////////////////////////////////////////////// 551 ///////////////////////////////////////////////////////////////////////////////
606 552
607 class CircleBatch : public GrVertexBatch { 553 class CircleBatch : public GrVertexBatch {
608 public: 554 public:
609 DEFINE_BATCH_CLASS_ID 555 DEFINE_BATCH_CLASS_ID
610 556
611 struct Geometry { 557 struct Geometry {
612 SkMatrix fViewMatrix;
613 SkRect fDevBounds; 558 SkRect fDevBounds;
614 SkScalar fInnerRadius; 559 SkScalar fInnerRadius;
615 SkScalar fOuterRadius; 560 SkScalar fOuterRadius;
616 GrColor fColor; 561 GrColor fColor;
617 bool fStroke;
618 }; 562 };
619 563
620 static GrDrawBatch* Create(const Geometry& geometry) { return new CircleBatc h(geometry); } 564 CircleBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool strok ed)
621 565 : INHERITED(ClassID())
566 , fStroked(stroked)
567 , fViewMatrixIfUsingLocalCoords(viewMatrix) {
568 fGeoData.push_back(geometry);
569 this->setBounds(geometry.fDevBounds);
570 }
622 const char* name() const override { return "CircleBatch"; } 571 const char* name() const override { return "CircleBatch"; }
623 572
624 SkString dumpInfo() const override { 573 SkString dumpInfo() const override {
625 SkString string; 574 SkString string;
626 for (int i = 0; i < fGeoData.count(); ++i) { 575 for (int i = 0; i < fGeoData.count(); ++i) {
627 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," 576 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f],"
628 "InnerRad: %.2f, OuterRad: %.2f\n", 577 "InnerRad: %.2f, OuterRad: %.2f\n",
629 fGeoData[i].fColor, 578 fGeoData[i].fColor,
630 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop, 579 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop,
631 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom, 580 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom,
632 fGeoData[i].fInnerRadius, 581 fGeoData[i].fInnerRadius,
633 fGeoData[i].fOuterRadius); 582 fGeoData[i].fOuterRadius);
634 } 583 }
635 string.append(INHERITED::dumpInfo()); 584 string.append(INHERITED::dumpInfo());
636 return string; 585 return string;
637 } 586 }
638 587
639 void computePipelineOptimizations(GrInitInvariantOutput* color, 588 void computePipelineOptimizations(GrInitInvariantOutput* color,
640 GrInitInvariantOutput* coverage, 589 GrInitInvariantOutput* coverage,
641 GrBatchToXPOverrides* overrides) const ove rride { 590 GrBatchToXPOverrides* overrides) const ove rride {
642 // When this is called on a batch, there is only one geometry bundle 591 // When this is called on a batch, there is only one geometry bundle
643 color->setKnownFourComponents(fGeoData[0].fColor); 592 color->setKnownFourComponents(fGeoData[0].fColor);
644 coverage->setUnknownSingleComponent(); 593 coverage->setUnknownSingleComponent();
645 } 594 }
646 595
647 private: 596 private:
648 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 597 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
649 // Handle any color overrides 598 // Handle any overrides that affect our GP.
650 if (!overrides.readsColor()) { 599 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
651 fGeoData[0].fColor = GrColor_ILLEGAL; 600 if (!overrides.readsLocalCoords()) {
601 fViewMatrixIfUsingLocalCoords.reset();
652 } 602 }
653 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
654
655 // setup batch properties
656 fBatch.fColorIgnored = !overrides.readsColor();
657 fBatch.fColor = fGeoData[0].fColor;
658 fBatch.fStroke = fGeoData[0].fStroke;
659 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
660 fBatch.fCoverageIgnored = !overrides.readsCoverage();
661 } 603 }
662 604
663 void onPrepareDraws(Target* target) const override { 605 void onPrepareDraws(Target* target) const override {
664 SkMatrix invert; 606 SkMatrix localMatrix;
665 if (!this->viewMatrix().invert(&invert)) { 607 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
666 return; 608 return;
667 } 609 }
668 610
669 // Setup geometry processor 611 // Setup geometry processor
670 SkAutoTUnref<GrGeometryProcessor> gp(CircleEdgeEffect::Create(this->colo r(), 612 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, localMatrix));
671 this->stro ke(),
672 invert,
673 this->uses LocalCoords()));
674 613
675 target->initDraw(gp, this->pipeline()); 614 target->initDraw(gp, this->pipeline());
676 615
677 int instanceCount = fGeoData.count(); 616 int instanceCount = fGeoData.count();
678 size_t vertexStride = gp->getVertexStride(); 617 size_t vertexStride = gp->getVertexStride();
679 SkASSERT(vertexStride == sizeof(CircleVertex)); 618 SkASSERT(vertexStride == sizeof(CircleVertex));
680 QuadHelper helper; 619 QuadHelper helper;
681 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , vertexStride, 620 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , vertexStride,
682 instan ceCount)); 621 instan ceCount));
683 if (!verts) { 622 if (!verts) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 verts[3].fColor = color; 656 verts[3].fColor = color;
718 verts[3].fOffset = SkPoint::Make(1, -1); 657 verts[3].fOffset = SkPoint::Make(1, -1);
719 verts[3].fOuterRadius = outerRadius; 658 verts[3].fOuterRadius = outerRadius;
720 verts[3].fInnerRadius = innerRadius; 659 verts[3].fInnerRadius = innerRadius;
721 660
722 verts += kVerticesPerQuad; 661 verts += kVerticesPerQuad;
723 } 662 }
724 helper.recordDraw(target); 663 helper.recordDraw(target);
725 } 664 }
726 665
727 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
728
729 CircleBatch(const Geometry& geometry) : INHERITED(ClassID()) {
730 fGeoData.push_back(geometry);
731
732 this->setBounds(geometry.fDevBounds);
733 }
734
735 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 666 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
736 CircleBatch* that = t->cast<CircleBatch>(); 667 CircleBatch* that = t->cast<CircleBatch>();
737 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 668 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
738 that->bounds(), caps)) { 669 that->bounds(), caps)) {
739 return false; 670 return false;
740 } 671 }
741 672
742 if (this->stroke() != that->stroke()) { 673 if (this->fStroked != that->fStroked) {
743 return false; 674 return false;
744 } 675 }
745 676
746 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 677 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
747 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
748 return false; 678 return false;
749 } 679 }
750 680
751 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 681 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
752 this->joinBounds(that->bounds()); 682 this->joinBounds(that->bounds());
753 return true; 683 return true;
754 } 684 }
755 685
756 GrColor color() const { return fBatch.fColor; } 686 bool fStroked;
757 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } 687 SkMatrix fViewMatrixIfUsingLocalCoords;
758 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
759 bool stroke() const { return fBatch.fStroke; }
760
761 struct BatchTracker {
762 GrColor fColor;
763 bool fStroke;
764 bool fUsesLocalCoords;
765 bool fColorIgnored;
766 bool fCoverageIgnored;
767 };
768
769 BatchTracker fBatch;
770 SkSTArray<1, Geometry, true> fGeoData; 688 SkSTArray<1, Geometry, true> fGeoData;
771 689
772 typedef GrVertexBatch INHERITED; 690 typedef GrVertexBatch INHERITED;
773 }; 691 };
774 692
775 static GrDrawBatch* create_circle_batch(GrColor color, 693 static GrDrawBatch* create_circle_batch(GrColor color,
776 const SkMatrix& viewMatrix, 694 const SkMatrix& viewMatrix,
777 const SkRect& circle, 695 const SkRect& circle,
778 const SkStrokeRec& stroke) { 696 const SkStrokeRec& stroke) {
779 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); 697 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
(...skipping 23 matching lines...) Expand all
803 } 721 }
804 722
805 // The radii are outset for two reasons. First, it allows the shader to simp ly perform simpler 723 // The radii are outset for two reasons. First, it allows the shader to simp ly perform simpler
806 // computation because the computed alpha is zero, rather than 50%, at the r adius. 724 // computation because the computed alpha is zero, rather than 50%, at the r adius.
807 // Second, the outer radius is used to compute the verts of the bounding box that is rendered 725 // Second, the outer radius is used to compute the verts of the bounding box that is rendered
808 // and the outset ensures the box will cover all partially covered by the ci rcle. 726 // and the outset ensures the box will cover all partially covered by the ci rcle.
809 outerRadius += SK_ScalarHalf; 727 outerRadius += SK_ScalarHalf;
810 innerRadius -= SK_ScalarHalf; 728 innerRadius -= SK_ScalarHalf;
811 729
812 CircleBatch::Geometry geometry; 730 CircleBatch::Geometry geometry;
813 geometry.fViewMatrix = viewMatrix;
814 geometry.fColor = color; 731 geometry.fColor = color;
815 geometry.fInnerRadius = innerRadius; 732 geometry.fInnerRadius = innerRadius;
816 geometry.fOuterRadius = outerRadius; 733 geometry.fOuterRadius = outerRadius;
817 geometry.fStroke = isStrokeOnly && innerRadius > 0;
818 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, 734 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
819 center.fX + outerRadius, center.fY + outerRadius); 735 center.fX + outerRadius, center.fY + outerRadius);
820 736
821 return CircleBatch::Create(geometry); 737 return new CircleBatch(geometry, viewMatrix, isStrokeOnly && innerRadius > 0 );
822 } 738 }
823 739
824 GrDrawBatch* GrOvalRenderer::CreateCircleBatch(GrColor color, 740 GrDrawBatch* GrOvalRenderer::CreateCircleBatch(GrColor color,
825 const SkMatrix& viewMatrix, 741 const SkMatrix& viewMatrix,
826 const SkRect& circle, 742 const SkRect& circle,
827 const SkStrokeRec& stroke) { 743 const SkStrokeRec& stroke) {
828 return create_circle_batch(color, viewMatrix, circle, stroke); 744 return create_circle_batch(color, viewMatrix, circle, stroke);
829 } 745 }
830 746
831 /////////////////////////////////////////////////////////////////////////////// 747 ///////////////////////////////////////////////////////////////////////////////
832 748
833 class EllipseBatch : public GrVertexBatch { 749 class EllipseBatch : public GrVertexBatch {
834 public: 750 public:
835 DEFINE_BATCH_CLASS_ID 751 DEFINE_BATCH_CLASS_ID
836 752
837 struct Geometry { 753 struct Geometry {
838 SkMatrix fViewMatrix;
839 SkRect fDevBounds; 754 SkRect fDevBounds;
840 SkScalar fXRadius; 755 SkScalar fXRadius;
841 SkScalar fYRadius; 756 SkScalar fYRadius;
842 SkScalar fInnerXRadius; 757 SkScalar fInnerXRadius;
843 SkScalar fInnerYRadius; 758 SkScalar fInnerYRadius;
844 GrColor fColor; 759 GrColor fColor;
845 bool fStroke;
846 }; 760 };
847 761
848 static GrDrawBatch* Create(const Geometry& geometry) { return new EllipseBat ch(geometry); } 762 EllipseBatch(const Geometry& geometry, const SkMatrix& viewMatrix, bool stro ked)
763 : INHERITED(ClassID())
764 , fStroked(stroked)
765 , fViewMatrixIfUsingLocalCoords(viewMatrix) {
766 fGeoData.push_back(geometry);
767 this->setBounds(geometry.fDevBounds);
768 }
849 769
850 const char* name() const override { return "EllipseBatch"; } 770 const char* name() const override { return "EllipseBatch"; }
851 771
852 void computePipelineOptimizations(GrInitInvariantOutput* color, 772 void computePipelineOptimizations(GrInitInvariantOutput* color,
853 GrInitInvariantOutput* coverage, 773 GrInitInvariantOutput* coverage,
854 GrBatchToXPOverrides* overrides) const ove rride { 774 GrBatchToXPOverrides* overrides) const ove rride {
855 // When this is called on a batch, there is only one geometry bundle 775 // When this is called on a batch, there is only one geometry bundle
856 color->setKnownFourComponents(fGeoData[0].fColor); 776 color->setKnownFourComponents(fGeoData[0].fColor);
857 coverage->setUnknownSingleComponent(); 777 coverage->setUnknownSingleComponent();
858 } 778 }
859 779
860 private: 780 private:
861 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 781 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
862 // Handle any color overrides 782 // Handle any overrides that affect our GP.
863 if (!overrides.readsCoverage()) { 783 if (!overrides.readsCoverage()) {
864 fGeoData[0].fColor = GrColor_ILLEGAL; 784 fGeoData[0].fColor = GrColor_ILLEGAL;
865 } 785 }
866 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); 786 if (!overrides.readsLocalCoords()) {
867 787 fViewMatrixIfUsingLocalCoords.reset();
868 // setup batch properties 788 }
869 fBatch.fColorIgnored = !overrides.readsColor();
870 fBatch.fColor = fGeoData[0].fColor;
871 fBatch.fStroke = fGeoData[0].fStroke;
872 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
873 fBatch.fCoverageIgnored = !overrides.readsCoverage();
874 } 789 }
875 790
876 void onPrepareDraws(Target* target) const override { 791 void onPrepareDraws(Target* target) const override {
877 SkMatrix invert; 792 SkMatrix localMatrix;
878 if (!this->viewMatrix().invert(&invert)) { 793 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
879 return; 794 return;
880 } 795 }
881 796
882 // Setup geometry processor 797 // Setup geometry processor
883 SkAutoTUnref<GrGeometryProcessor> gp(EllipseEdgeEffect::Create(this->col or(), 798 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok ed, localMatrix));
884 this->str oke(),
885 invert,
886 this->use sLocalCoords()));
887 799
888 target->initDraw(gp, this->pipeline()); 800 target->initDraw(gp, this->pipeline());
889 801
890 int instanceCount = fGeoData.count(); 802 int instanceCount = fGeoData.count();
891 QuadHelper helper; 803 QuadHelper helper;
892 size_t vertexStride = gp->getVertexStride(); 804 size_t vertexStride = gp->getVertexStride();
893 SkASSERT(vertexStride == sizeof(EllipseVertex)); 805 SkASSERT(vertexStride == sizeof(EllipseVertex));
894 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( 806 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
895 helper.init(target, vertexStride, instanceCount)); 807 helper.init(target, vertexStride, instanceCount));
896 if (!verts) { 808 if (!verts) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 verts[3].fColor = color; 847 verts[3].fColor = color;
936 verts[3].fOffset = SkPoint::Make(xRadius, -yRadius); 848 verts[3].fOffset = SkPoint::Make(xRadius, -yRadius);
937 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 849 verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
938 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip) ; 850 verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip) ;
939 851
940 verts += kVerticesPerQuad; 852 verts += kVerticesPerQuad;
941 } 853 }
942 helper.recordDraw(target); 854 helper.recordDraw(target);
943 } 855 }
944 856
945 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
946
947 EllipseBatch(const Geometry& geometry) : INHERITED(ClassID()) {
948 fGeoData.push_back(geometry);
949
950 this->setBounds(geometry.fDevBounds);
951 }
952
953 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 857 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
954 EllipseBatch* that = t->cast<EllipseBatch>(); 858 EllipseBatch* that = t->cast<EllipseBatch>();
955 859
956 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 860 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
957 that->bounds(), caps)) { 861 that->bounds(), caps)) {
958 return false; 862 return false;
959 } 863 }
960 864
961 if (this->stroke() != that->stroke()) { 865 if (fStroked != that->fStroked) {
962 return false; 866 return false;
963 } 867 }
964 868
965 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 869 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
966 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
967 return false; 870 return false;
968 } 871 }
969 872
970 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 873 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
971 this->joinBounds(that->bounds()); 874 this->joinBounds(that->bounds());
972 return true; 875 return true;
973 } 876 }
974 877
975 GrColor color() const { return fBatch.fColor; }
976 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
977 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
978 bool stroke() const { return fBatch.fStroke; }
979 878
980 struct BatchTracker { 879 bool fStroked;
981 GrColor fColor; 880 SkMatrix fViewMatrixIfUsingLocalCoords;
982 bool fStroke;
983 bool fUsesLocalCoords;
984 bool fColorIgnored;
985 bool fCoverageIgnored;
986 };
987
988 BatchTracker fBatch;
989 SkSTArray<1, Geometry, true> fGeoData; 881 SkSTArray<1, Geometry, true> fGeoData;
990 882
991 typedef GrVertexBatch INHERITED; 883 typedef GrVertexBatch INHERITED;
992 }; 884 };
993 885
994 static GrDrawBatch* create_ellipse_batch(GrColor color, 886 static GrDrawBatch* create_ellipse_batch(GrColor color,
995 const SkMatrix& viewMatrix, 887 const SkMatrix& viewMatrix,
996 const SkRect& ellipse, 888 const SkRect& ellipse,
997 const SkStrokeRec& stroke) { 889 const SkStrokeRec& stroke) {
998 SkASSERT(viewMatrix.rectStaysRect()); 890 SkASSERT(viewMatrix.rectStaysRect());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 yRadius += scaledStroke.fY; 943 yRadius += scaledStroke.fY;
1052 } 944 }
1053 945
1054 // We've extended the outer x radius out half a pixel to antialias. 946 // We've extended the outer x radius out half a pixel to antialias.
1055 // This will also expand the rect so all the pixels will be captured. 947 // This will also expand the rect so all the pixels will be captured.
1056 // TODO: Consider if we should use sqrt(2)/2 instead 948 // TODO: Consider if we should use sqrt(2)/2 instead
1057 xRadius += SK_ScalarHalf; 949 xRadius += SK_ScalarHalf;
1058 yRadius += SK_ScalarHalf; 950 yRadius += SK_ScalarHalf;
1059 951
1060 EllipseBatch::Geometry geometry; 952 EllipseBatch::Geometry geometry;
1061 geometry.fViewMatrix = viewMatrix;
1062 geometry.fColor = color; 953 geometry.fColor = color;
1063 geometry.fXRadius = xRadius; 954 geometry.fXRadius = xRadius;
1064 geometry.fYRadius = yRadius; 955 geometry.fYRadius = yRadius;
1065 geometry.fInnerXRadius = innerXRadius; 956 geometry.fInnerXRadius = innerXRadius;
1066 geometry.fInnerYRadius = innerYRadius; 957 geometry.fInnerYRadius = innerYRadius;
1067 geometry.fStroke = isStrokeOnly && innerXRadius > 0 && innerYRadius > 0;
1068 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRad ius, 958 geometry.fDevBounds = SkRect::MakeLTRB(center.fX - xRadius, center.fY - yRad ius,
1069 center.fX + xRadius, center.fY + yRad ius); 959 center.fX + xRadius, center.fY + yRad ius);
1070 960
1071 return EllipseBatch::Create(geometry); 961 return new EllipseBatch(geometry, viewMatrix,
962 isStrokeOnly && innerXRadius > 0 && innerYRadius > 0 );
1072 } 963 }
1073 964
1074 GrDrawBatch* GrOvalRenderer::CreateEllipseBatch(GrColor color, 965 GrDrawBatch* GrOvalRenderer::CreateEllipseBatch(GrColor color,
1075 const SkMatrix& viewMatrix, 966 const SkMatrix& viewMatrix,
1076 const SkRect& ellipse, 967 const SkRect& ellipse,
1077 const SkStrokeRec& stroke) { 968 const SkStrokeRec& stroke) {
1078 return create_ellipse_batch(color, viewMatrix, ellipse, stroke); 969 return create_ellipse_batch(color, viewMatrix, ellipse, stroke);
1079 } 970 }
1080 971
1081 //////////////////////////////////////////////////////////////////////////////// ///////////////// 972 //////////////////////////////////////////////////////////////////////////////// /////////////////
1082 973
1083 class DIEllipseBatch : public GrVertexBatch { 974 class DIEllipseBatch : public GrVertexBatch {
1084 public: 975 public:
1085 DEFINE_BATCH_CLASS_ID 976 DEFINE_BATCH_CLASS_ID
1086 977
1087 struct Geometry { 978 struct Geometry {
1088 SkMatrix fViewMatrix; 979 SkMatrix fViewMatrix;
1089 SkRect fBounds; 980 SkRect fBounds;
1090 SkScalar fXRadius; 981 SkScalar fXRadius;
1091 SkScalar fYRadius; 982 SkScalar fYRadius;
1092 SkScalar fInnerXRadius; 983 SkScalar fInnerXRadius;
1093 SkScalar fInnerYRadius; 984 SkScalar fInnerYRadius;
1094 SkScalar fGeoDx; 985 SkScalar fGeoDx;
1095 SkScalar fGeoDy; 986 SkScalar fGeoDy;
1096 GrColor fColor; 987 GrColor fColor;
1097 DIEllipseEdgeEffect::Mode fMode; 988 DIEllipseStyle fStyle;
1098 }; 989 };
1099 990
1100 static GrDrawBatch* Create(const Geometry& geometry, const SkRect& bounds) { 991 static GrDrawBatch* Create(const Geometry& geometry, const SkRect& bounds) {
1101 return new DIEllipseBatch(geometry, bounds); 992 return new DIEllipseBatch(geometry, bounds);
1102 } 993 }
1103 994
1104 const char* name() const override { return "DIEllipseBatch"; } 995 const char* name() const override { return "DIEllipseBatch"; }
1105 996
1106 void computePipelineOptimizations(GrInitInvariantOutput* color, 997 void computePipelineOptimizations(GrInitInvariantOutput* color,
1107 GrInitInvariantOutput* coverage, 998 GrInitInvariantOutput* coverage,
1108 GrBatchToXPOverrides* overrides) const ove rride { 999 GrBatchToXPOverrides* overrides) const ove rride {
1109 // When this is called on a batch, there is only one geometry bundle 1000 // When this is called on a batch, there is only one geometry bundle
1110 color->setKnownFourComponents(fGeoData[0].fColor); 1001 color->setKnownFourComponents(fGeoData[0].fColor);
1111 coverage->setUnknownSingleComponent(); 1002 coverage->setUnknownSingleComponent();
1112 } 1003 }
1113 1004
1114 private: 1005 private:
1115 1006
1116 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 1007 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
1117 // Handle any color overrides 1008 // Handle any overrides that affect our GP.
1118 if (!overrides.readsColor()) {
1119 fGeoData[0].fColor = GrColor_ILLEGAL;
1120 }
1121 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); 1009 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1122 1010 fUsesLocalCoords = overrides.readsLocalCoords();
1123 // setup batch properties
1124 fBatch.fColorIgnored = !overrides.readsColor();
1125 fBatch.fColor = fGeoData[0].fColor;
1126 fBatch.fMode = fGeoData[0].fMode;
1127 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
1128 fBatch.fCoverageIgnored = !overrides.readsCoverage();
1129 } 1011 }
1130 1012
1131 void onPrepareDraws(Target* target) const override { 1013 void onPrepareDraws(Target* target) const override {
1132 // Setup geometry processor 1014 // Setup geometry processor
1133 SkAutoTUnref<GrGeometryProcessor> gp(DIEllipseEdgeEffect::Create(this->c olor(), 1015 SkAutoTUnref<GrGeometryProcessor> gp(DIEllipseGeometryProcessor::Create( this->viewMatrix(),
1134 this->v iewMatrix(), 1016 this->style()));
1135 this->m ode(),
1136 this->u sesLocalCoords()));
1137 1017
1138 target->initDraw(gp, this->pipeline()); 1018 target->initDraw(gp, this->pipeline());
1139 1019
1140 int instanceCount = fGeoData.count(); 1020 int instanceCount = fGeoData.count();
1141 size_t vertexStride = gp->getVertexStride(); 1021 size_t vertexStride = gp->getVertexStride();
1142 SkASSERT(vertexStride == sizeof(DIEllipseVertex)); 1022 SkASSERT(vertexStride == sizeof(DIEllipseVertex));
1143 QuadHelper helper; 1023 QuadHelper helper;
1144 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>( 1024 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(
1145 helper.init(target, vertexStride, instanceCount)); 1025 helper.init(target, vertexStride, instanceCount));
1146 if (!verts) { 1026 if (!verts) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 1060
1181 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 1061 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
1182 verts[3].fColor = color; 1062 verts[3].fColor = color;
1183 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offse tDy); 1063 verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offse tDy);
1184 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -inner RatioY - offsetDy); 1064 verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -inner RatioY - offsetDy);
1185 1065
1186 verts += kVerticesPerQuad; 1066 verts += kVerticesPerQuad;
1187 } 1067 }
1188 helper.recordDraw(target); 1068 helper.recordDraw(target);
1189 } 1069 }
1190 1070
1191 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
1192
1193 DIEllipseBatch(const Geometry& geometry, const SkRect& bounds) : INHERITED(C lassID()) { 1071 DIEllipseBatch(const Geometry& geometry, const SkRect& bounds) : INHERITED(C lassID()) {
1194 fGeoData.push_back(geometry); 1072 fGeoData.push_back(geometry);
1195 1073
1196 this->setBounds(bounds); 1074 this->setBounds(bounds);
1197 } 1075 }
1198 1076
1199 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 1077 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
1200 DIEllipseBatch* that = t->cast<DIEllipseBatch>(); 1078 DIEllipseBatch* that = t->cast<DIEllipseBatch>();
1201 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 1079 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
1202 that->bounds(), caps)) { 1080 that->bounds(), caps)) {
1203 return false; 1081 return false;
1204 } 1082 }
1205 1083
1206 if (this->mode() != that->mode()) { 1084 if (this->style() != that->style()) {
1207 return false; 1085 return false;
1208 } 1086 }
1209 1087
1210 // TODO rewrite to allow positioning on CPU 1088 // TODO rewrite to allow positioning on CPU
1211 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 1089 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
1212 return false; 1090 return false;
1213 } 1091 }
1214 1092
1215 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 1093 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
1216 this->joinBounds(that->bounds()); 1094 this->joinBounds(that->bounds());
1217 return true; 1095 return true;
1218 } 1096 }
1219 1097
1220 GrColor color() const { return fBatch.fColor; }
1221 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
1222 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } 1098 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
1223 DIEllipseEdgeEffect::Mode mode() const { return fBatch.fMode; } 1099 DIEllipseStyle style() const { return fGeoData[0].fStyle; }
1224 1100
1225 struct BatchTracker { 1101 bool fUsesLocalCoords;
1226 GrColor fColor;
1227 DIEllipseEdgeEffect::Mode fMode;
1228 bool fUsesLocalCoords;
1229 bool fColorIgnored;
1230 bool fCoverageIgnored;
1231 };
1232
1233 BatchTracker fBatch;
1234 SkSTArray<1, Geometry, true> fGeoData; 1102 SkSTArray<1, Geometry, true> fGeoData;
1235 1103
1236 typedef GrVertexBatch INHERITED; 1104 typedef GrVertexBatch INHERITED;
1237 }; 1105 };
1238 1106
1239 static GrDrawBatch* create_diellipse_batch(GrColor color, 1107 static GrDrawBatch* create_diellipse_batch(GrColor color,
1240 const SkMatrix& viewMatrix, 1108 const SkMatrix& viewMatrix,
1241 const SkRect& ellipse, 1109 const SkRect& ellipse,
1242 const SkStrokeRec& stroke) { 1110 const SkStrokeRec& stroke) {
1243 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); 1111 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
1244 SkScalar xRadius = SkScalarHalf(ellipse.width()); 1112 SkScalar xRadius = SkScalarHalf(ellipse.width());
1245 SkScalar yRadius = SkScalarHalf(ellipse.height()); 1113 SkScalar yRadius = SkScalarHalf(ellipse.height());
1246 1114
1247 SkStrokeRec::Style style = stroke.getStyle(); 1115 SkStrokeRec::Style style = stroke.getStyle();
1248 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? 1116 DIEllipseStyle dieStyle = (SkStrokeRec::kStroke_Style == style) ?
1249 DIEllipseEdgeEffect::kStroke : 1117 DIEllipseStyle::kStroke :
1250 (SkStrokeRec::kHairline_Style == style) ? 1118 (SkStrokeRec::kHairline_Style == style) ?
1251 DIEllipseEdgeEffect::kHairline : DIEllipseEd geEffect::kFill; 1119 DIEllipseStyle::kHairline : DIEllipseSty le::kFill;
1252 1120
1253 SkScalar innerXRadius = 0; 1121 SkScalar innerXRadius = 0;
1254 SkScalar innerYRadius = 0; 1122 SkScalar innerYRadius = 0;
1255 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) { 1123 if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != sty le) {
1256 SkScalar strokeWidth = stroke.getWidth(); 1124 SkScalar strokeWidth = stroke.getWidth();
1257 1125
1258 if (SkScalarNearlyZero(strokeWidth)) { 1126 if (SkScalarNearlyZero(strokeWidth)) {
1259 strokeWidth = SK_ScalarHalf; 1127 strokeWidth = SK_ScalarHalf;
1260 } else { 1128 } else {
1261 strokeWidth *= SK_ScalarHalf; 1129 strokeWidth *= SK_ScalarHalf;
(...skipping 13 matching lines...) Expand all
1275 1143
1276 // set inner radius (if needed) 1144 // set inner radius (if needed)
1277 if (SkStrokeRec::kStroke_Style == style) { 1145 if (SkStrokeRec::kStroke_Style == style) {
1278 innerXRadius = xRadius - strokeWidth; 1146 innerXRadius = xRadius - strokeWidth;
1279 innerYRadius = yRadius - strokeWidth; 1147 innerYRadius = yRadius - strokeWidth;
1280 } 1148 }
1281 1149
1282 xRadius += strokeWidth; 1150 xRadius += strokeWidth;
1283 yRadius += strokeWidth; 1151 yRadius += strokeWidth;
1284 } 1152 }
1285 if (DIEllipseEdgeEffect::kStroke == mode) { 1153 if (DIEllipseStyle::kStroke == dieStyle) {
1286 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt roke : 1154 dieStyle = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseStyle ::kSt roke :
1287 DIEllipseEdgeEffect::kFi ll; 1155 DIEllipseStyle ::kFi ll;
1288 } 1156 }
1289 1157
1290 // This expands the outer rect so that after CTM we end up with a half-pixel border 1158 // This expands the outer rect so that after CTM we end up with a half-pixel border
1291 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; 1159 SkScalar a = viewMatrix[SkMatrix::kMScaleX];
1292 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; 1160 SkScalar b = viewMatrix[SkMatrix::kMSkewX];
1293 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; 1161 SkScalar c = viewMatrix[SkMatrix::kMSkewY];
1294 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; 1162 SkScalar d = viewMatrix[SkMatrix::kMScaleY];
1295 SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c); 1163 SkScalar geoDx = SK_ScalarHalf / SkScalarSqrt(a*a + c*c);
1296 SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d); 1164 SkScalar geoDy = SK_ScalarHalf / SkScalarSqrt(b*b + d*d);
1297 1165
1298 DIEllipseBatch::Geometry geometry; 1166 DIEllipseBatch::Geometry geometry;
1299 geometry.fViewMatrix = viewMatrix; 1167 geometry.fViewMatrix = viewMatrix;
1300 geometry.fColor = color; 1168 geometry.fColor = color;
1301 geometry.fXRadius = xRadius; 1169 geometry.fXRadius = xRadius;
1302 geometry.fYRadius = yRadius; 1170 geometry.fYRadius = yRadius;
1303 geometry.fInnerXRadius = innerXRadius; 1171 geometry.fInnerXRadius = innerXRadius;
1304 geometry.fInnerYRadius = innerYRadius; 1172 geometry.fInnerYRadius = innerYRadius;
1305 geometry.fGeoDx = geoDx; 1173 geometry.fGeoDx = geoDx;
1306 geometry.fGeoDy = geoDy; 1174 geometry.fGeoDy = geoDy;
1307 geometry.fMode = mode; 1175 geometry.fStyle = dieStyle;
1308 geometry.fBounds = SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy, 1176 geometry.fBounds = SkRect::MakeLTRB(center.fX - xRadius - geoDx, center.fY - yRadius - geoDy,
1309 center.fX + xRadius + geoDx, center.fY + yRadius + geoDy); 1177 center.fX + xRadius + geoDx, center.fY + yRadius + geoDy);
1310 1178
1311 SkRect devBounds = geometry.fBounds; 1179 SkRect devBounds = geometry.fBounds;
1312 viewMatrix.mapRect(&devBounds); 1180 viewMatrix.mapRect(&devBounds);
1313 return DIEllipseBatch::Create(geometry, devBounds); 1181 return DIEllipseBatch::Create(geometry, devBounds);
1314 } 1182 }
1315 1183
1316 GrDrawBatch* GrOvalRenderer::CreateDIEllipseBatch(GrColor color, 1184 GrDrawBatch* GrOvalRenderer::CreateDIEllipseBatch(GrColor color,
1317 const SkMatrix& viewMatrix, 1185 const SkMatrix& viewMatrix,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 } 1231 }
1364 } 1232 }
1365 1233
1366 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1234 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1367 1235
1368 class RRectCircleRendererBatch : public GrVertexBatch { 1236 class RRectCircleRendererBatch : public GrVertexBatch {
1369 public: 1237 public:
1370 DEFINE_BATCH_CLASS_ID 1238 DEFINE_BATCH_CLASS_ID
1371 1239
1372 struct Geometry { 1240 struct Geometry {
1373 SkMatrix fViewMatrix;
1374 SkRect fDevBounds; 1241 SkRect fDevBounds;
1375 SkScalar fInnerRadius; 1242 SkScalar fInnerRadius;
1376 SkScalar fOuterRadius; 1243 SkScalar fOuterRadius;
1377 GrColor fColor; 1244 GrColor fColor;
1378 bool fStroke;
1379 }; 1245 };
1380 1246
1381 static GrDrawBatch* Create(const Geometry& geometry) { 1247 RRectCircleRendererBatch(const Geometry& geometry, const SkMatrix& viewMatri x, bool stroked)
1382 return new RRectCircleRendererBatch(geometry); 1248 : INHERITED(ClassID())
1249 , fStroked(stroked)
1250 , fViewMatrixIfUsingLocalCoords(viewMatrix) {
1251 fGeoData.push_back(geometry);
1252
1253 this->setBounds(geometry.fDevBounds);
1383 } 1254 }
1384 1255
1385 const char* name() const override { return "RRectCircleBatch"; } 1256 const char* name() const override { return "RRectCircleBatch"; }
1386 1257
1387 void computePipelineOptimizations(GrInitInvariantOutput* color, 1258 void computePipelineOptimizations(GrInitInvariantOutput* color,
1388 GrInitInvariantOutput* coverage, 1259 GrInitInvariantOutput* coverage,
1389 GrBatchToXPOverrides* overrides) const ove rride { 1260 GrBatchToXPOverrides* overrides) const ove rride {
1390 // When this is called on a batch, there is only one geometry bundle 1261 // When this is called on a batch, there is only one geometry bundle
1391 color->setKnownFourComponents(fGeoData[0].fColor); 1262 color->setKnownFourComponents(fGeoData[0].fColor);
1392 coverage->setUnknownSingleComponent(); 1263 coverage->setUnknownSingleComponent();
1393 } 1264 }
1394 1265
1395 private: 1266 private:
1396 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 1267 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
1397 // Handle any color overrides 1268 // Handle any overrides that affect our GP.
1398 if (!overrides.readsColor()) { 1269 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1399 fGeoData[0].fColor = GrColor_ILLEGAL; 1270 if (!overrides.readsLocalCoords()) {
1271 fViewMatrixIfUsingLocalCoords.reset();
1400 } 1272 }
1401 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1402
1403 // setup batch properties
1404 fBatch.fColorIgnored = !overrides.readsColor();
1405 fBatch.fColor = fGeoData[0].fColor;
1406 fBatch.fStroke = fGeoData[0].fStroke;
1407 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
1408 fBatch.fCoverageIgnored = !overrides.readsCoverage();
1409 } 1273 }
1410 1274
1411 void onPrepareDraws(Target* target) const override { 1275 void onPrepareDraws(Target* target) const override {
1412 // reset to device coordinates 1276 // Invert the view matrix as a local matrix (if any other processors req uire coords).
1413 SkMatrix invert; 1277 SkMatrix localMatrix;
1414 if (!this->viewMatrix().invert(&invert)) { 1278 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
1415 SkDebugf("Failed to invert\n");
1416 return; 1279 return;
1417 } 1280 }
1418 1281
1419 // Setup geometry processor 1282 // Setup geometry processor
1420 SkAutoTUnref<GrGeometryProcessor> gp(CircleEdgeEffect::Create(this->colo r(), 1283 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, localMatrix));
1421 this->stro ke(),
1422 invert,
1423 this->uses LocalCoords()));
1424 1284
1425 target->initDraw(gp, this->pipeline()); 1285 target->initDraw(gp, this->pipeline());
1426 1286
1427 int instanceCount = fGeoData.count(); 1287 int instanceCount = fGeoData.count();
1428 size_t vertexStride = gp->getVertexStride(); 1288 size_t vertexStride = gp->getVertexStride();
1429 SkASSERT(vertexStride == sizeof(CircleVertex)); 1289 SkASSERT(vertexStride == sizeof(CircleVertex));
1430 1290
1431 // drop out the middle quad if we're stroked 1291 // drop out the middle quad if we're stroked
1432 int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndi cesPerRRect; 1292 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect;
1433 SkAutoTUnref<const GrIndexBuffer> indexBuffer( 1293 SkAutoTUnref<const GrIndexBuffer> indexBuffer(
1434 ref_rrect_index_buffer(this->stroke(), target->resourceProvider())); 1294 ref_rrect_index_buffer(fStroked, target->resourceProvider()));
1435 1295
1436 InstancedHelper helper; 1296 InstancedHelper helper;
1437 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , 1297 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target ,
1438 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRRec t, 1298 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRRec t,
1439 indicesPerInstance, instanceCount)); 1299 indicesPerInstance, instanceCount));
1440 if (!verts || !indexBuffer) { 1300 if (!verts || !indexBuffer) {
1441 SkDebugf("Could not allocate vertices\n"); 1301 SkDebugf("Could not allocate vertices\n");
1442 return; 1302 return;
1443 } 1303 }
1444 1304
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1487 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); 1347 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]);
1488 verts->fOuterRadius = outerRadius; 1348 verts->fOuterRadius = outerRadius;
1489 verts->fInnerRadius = innerRadius; 1349 verts->fInnerRadius = innerRadius;
1490 verts++; 1350 verts++;
1491 } 1351 }
1492 } 1352 }
1493 1353
1494 helper.recordDraw(target); 1354 helper.recordDraw(target);
1495 } 1355 }
1496 1356
1497 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
1498
1499 RRectCircleRendererBatch(const Geometry& geometry) : INHERITED(ClassID()) {
1500 fGeoData.push_back(geometry);
1501
1502 this->setBounds(geometry.fDevBounds);
1503 }
1504
1505 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 1357 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
1506 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); 1358 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>();
1507 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 1359 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
1508 that->bounds(), caps)) { 1360 that->bounds(), caps)) {
1509 return false; 1361 return false;
1510 } 1362 }
1511 1363
1512 if (this->stroke() != that->stroke()) { 1364 if (fStroked != that->fStroked) {
1513 return false; 1365 return false;
1514 } 1366 }
1515 1367
1516 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 1368 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
1517 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
1518 return false; 1369 return false;
1519 } 1370 }
1520 1371
1521 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 1372 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
1522 this->joinBounds(that->bounds()); 1373 this->joinBounds(that->bounds());
1523 return true; 1374 return true;
1524 } 1375 }
1525 1376
1526 GrColor color() const { return fBatch.fColor; } 1377 bool fStroked;
1527 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } 1378 SkMatrix fViewMatrixIfUsingLocalCoords;
1528 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
1529 bool stroke() const { return fBatch.fStroke; }
1530
1531 struct BatchTracker {
1532 GrColor fColor;
1533 bool fStroke;
1534 bool fUsesLocalCoords;
1535 bool fColorIgnored;
1536 bool fCoverageIgnored;
1537 };
1538
1539 BatchTracker fBatch;
1540 SkSTArray<1, Geometry, true> fGeoData; 1379 SkSTArray<1, Geometry, true> fGeoData;
1541 1380
1542 typedef GrVertexBatch INHERITED; 1381 typedef GrVertexBatch INHERITED;
1543 }; 1382 };
1544 1383
1545 class RRectEllipseRendererBatch : public GrVertexBatch { 1384 class RRectEllipseRendererBatch : public GrVertexBatch {
1546 public: 1385 public:
1547 DEFINE_BATCH_CLASS_ID 1386 DEFINE_BATCH_CLASS_ID
1548 1387
1549 struct Geometry { 1388 struct Geometry {
1550 SkMatrix fViewMatrix;
1551 SkRect fDevBounds; 1389 SkRect fDevBounds;
1552 SkScalar fXRadius; 1390 SkScalar fXRadius;
1553 SkScalar fYRadius; 1391 SkScalar fYRadius;
1554 SkScalar fInnerXRadius; 1392 SkScalar fInnerXRadius;
1555 SkScalar fInnerYRadius; 1393 SkScalar fInnerYRadius;
1556 GrColor fColor; 1394 GrColor fColor;
1557 bool fStroke;
1558 }; 1395 };
1559 1396
1560 static GrDrawBatch* Create(const Geometry& geometry) { 1397 RRectEllipseRendererBatch(const Geometry& geometry, const SkMatrix& viewMatr ix, bool stroked)
1561 return new RRectEllipseRendererBatch(geometry); 1398 : INHERITED(ClassID())
1399 , fStroked(stroked)
1400 , fViewMatrixIfUsingLocalCoords(viewMatrix) {
1401 fGeoData.push_back(geometry);
1402 this->setBounds(geometry.fDevBounds);
1562 } 1403 }
1563 1404
1564 const char* name() const override { return "RRectEllipseRendererBatch"; } 1405 const char* name() const override { return "RRectEllipseRendererBatch"; }
1565 1406
1566 void computePipelineOptimizations(GrInitInvariantOutput* color, 1407 void computePipelineOptimizations(GrInitInvariantOutput* color,
1567 GrInitInvariantOutput* coverage, 1408 GrInitInvariantOutput* coverage,
1568 GrBatchToXPOverrides* overrides) const ove rride { 1409 GrBatchToXPOverrides* overrides) const ove rride {
1569 // When this is called on a batch, there is only one geometry bundle 1410 // When this is called on a batch, there is only one geometry bundle
1570 color->setKnownFourComponents(fGeoData[0].fColor); 1411 color->setKnownFourComponents(fGeoData[0].fColor);
1571 coverage->setUnknownSingleComponent(); 1412 coverage->setUnknownSingleComponent();
1572 } 1413 }
1573 1414
1574 private: 1415 private:
1575 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 1416 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
1576 // Handle any color overrides 1417 // Handle overrides that affect our GP.
1577 if (!overrides.readsColor()) { 1418 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1578 fGeoData[0].fColor = GrColor_ILLEGAL; 1419 if (!overrides.readsLocalCoords()) {
1420 fViewMatrixIfUsingLocalCoords.reset();
1579 } 1421 }
1580 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
1581
1582 // setup batch properties
1583 fBatch.fColorIgnored = !overrides.readsColor();
1584 fBatch.fColor = fGeoData[0].fColor;
1585 fBatch.fStroke = fGeoData[0].fStroke;
1586 fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
1587 fBatch.fCoverageIgnored = !overrides.readsCoverage();
1588 } 1422 }
1589 1423
1590 void onPrepareDraws(Target* target) const override { 1424 void onPrepareDraws(Target* target) const override {
1591 // reset to device coordinates 1425 SkMatrix localMatrix;
1592 SkMatrix invert; 1426 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
1593 if (!this->viewMatrix().invert(&invert)) {
1594 SkDebugf("Failed to invert\n");
1595 return; 1427 return;
1596 } 1428 }
1597 1429
1598 // Setup geometry processor 1430 // Setup geometry processor
1599 SkAutoTUnref<GrGeometryProcessor> gp(EllipseEdgeEffect::Create(this->col or(), 1431 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok ed, localMatrix));
1600 this->str oke(),
1601 invert,
1602 this->use sLocalCoords()));
1603 1432
1604 target->initDraw(gp, this->pipeline()); 1433 target->initDraw(gp, this->pipeline());
1605 1434
1606 int instanceCount = fGeoData.count(); 1435 int instanceCount = fGeoData.count();
1607 size_t vertexStride = gp->getVertexStride(); 1436 size_t vertexStride = gp->getVertexStride();
1608 SkASSERT(vertexStride == sizeof(EllipseVertex)); 1437 SkASSERT(vertexStride == sizeof(EllipseVertex));
1609 1438
1610 // drop out the middle quad if we're stroked 1439 // drop out the middle quad if we're stroked
1611 int indicesPerInstance = this->stroke() ? kIndicesPerStrokeRRect : kIndi cesPerRRect; 1440 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect;
1612 SkAutoTUnref<const GrIndexBuffer> indexBuffer( 1441 SkAutoTUnref<const GrIndexBuffer> indexBuffer(
1613 ref_rrect_index_buffer(this->stroke(), target->resourceProvider())); 1442 ref_rrect_index_buffer(fStroked, target->resourceProvider()));
1614 1443
1615 InstancedHelper helper; 1444 InstancedHelper helper;
1616 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( 1445 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(
1617 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB uffer, 1446 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB uffer,
1618 kVertsPerRRect, indicesPerInstance, instanceCount)); 1447 kVertsPerRRect, indicesPerInstance, instanceCount));
1619 if (!verts || !indexBuffer) { 1448 if (!verts || !indexBuffer) {
1620 SkDebugf("Could not allocate vertices\n"); 1449 SkDebugf("Could not allocate vertices\n");
1621 return; 1450 return;
1622 } 1451 }
1623 1452
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 verts->fColor = color; 1506 verts->fColor = color;
1678 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 1507 verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]);
1679 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 1508 verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
1680 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadReci p); 1509 verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadReci p);
1681 verts++; 1510 verts++;
1682 } 1511 }
1683 } 1512 }
1684 helper.recordDraw(target); 1513 helper.recordDraw(target);
1685 } 1514 }
1686 1515
1687 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
1688
1689 RRectEllipseRendererBatch(const Geometry& geometry) : INHERITED(ClassID()) {
1690 fGeoData.push_back(geometry);
1691
1692 this->setBounds(geometry.fDevBounds);
1693 }
1694
1695 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 1516 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
1696 RRectEllipseRendererBatch* that = t->cast<RRectEllipseRendererBatch>(); 1517 RRectEllipseRendererBatch* that = t->cast<RRectEllipseRendererBatch>();
1697 1518
1698 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 1519 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
1699 that->bounds(), caps)) { 1520 that->bounds(), caps)) {
1700 return false; 1521 return false;
1701 } 1522 }
1702 1523
1703 if (this->stroke() != that->stroke()) { 1524 if (fStroked != that->fStroked) {
1704 return false; 1525 return false;
1705 } 1526 }
1706 1527
1707 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); 1528 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
1708 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->vi ewMatrix())) {
1709 return false; 1529 return false;
1710 } 1530 }
1711 1531
1712 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 1532 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
1713 this->joinBounds(that->bounds()); 1533 this->joinBounds(that->bounds());
1714 return true; 1534 return true;
1715 } 1535 }
1716 1536
1717 GrColor color() const { return fBatch.fColor; } 1537 bool fStroked;
1718 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } 1538 SkMatrix fViewMatrixIfUsingLocalCoords;
1719 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } 1539 SkSTArray<1, Geometry, true> fGeoData;
1720 bool stroke() const { return fBatch.fStroke; }
1721
1722 struct BatchTracker {
1723 GrColor fColor;
1724 bool fStroke;
1725 bool fUsesLocalCoords;
1726 bool fColorIgnored;
1727 bool fCoverageIgnored;
1728 };
1729
1730 BatchTracker fBatch;
1731 SkSTArray<1, Geometry, true> fGeoData;
1732 1540
1733 typedef GrVertexBatch INHERITED; 1541 typedef GrVertexBatch INHERITED;
1734 }; 1542 };
1735 1543
1736 static GrDrawBatch* create_rrect_batch(GrColor color, 1544 static GrDrawBatch* create_rrect_batch(GrColor color,
1737 const SkMatrix& viewMatrix, 1545 const SkMatrix& viewMatrix,
1738 const SkRRect& rrect, 1546 const SkRRect& rrect,
1739 const SkStrokeRec& stroke) { 1547 const SkStrokeRec& stroke) {
1740 SkASSERT(viewMatrix.rectStaysRect()); 1548 SkASSERT(viewMatrix.rectStaysRect());
1741 SkASSERT(rrect.isSimple()); 1549 SkASSERT(rrect.isSimple());
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 // Second, the outer radius is used to compute the verts of the bounding box that is 1622 // Second, the outer radius is used to compute the verts of the bounding box that is
1815 // rendered and the outset ensures the box will cover all partially cove red by the rrect 1623 // rendered and the outset ensures the box will cover all partially cove red by the rrect
1816 // corners. 1624 // corners.
1817 outerRadius += SK_ScalarHalf; 1625 outerRadius += SK_ScalarHalf;
1818 innerRadius -= SK_ScalarHalf; 1626 innerRadius -= SK_ScalarHalf;
1819 1627
1820 // Expand the rect so all the pixels will be captured. 1628 // Expand the rect so all the pixels will be captured.
1821 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 1629 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1822 1630
1823 RRectCircleRendererBatch::Geometry geometry; 1631 RRectCircleRendererBatch::Geometry geometry;
1824 geometry.fViewMatrix = viewMatrix;
1825 geometry.fColor = color; 1632 geometry.fColor = color;
1826 geometry.fInnerRadius = innerRadius; 1633 geometry.fInnerRadius = innerRadius;
1827 geometry.fOuterRadius = outerRadius; 1634 geometry.fOuterRadius = outerRadius;
1828 geometry.fStroke = isStrokeOnly;
1829 geometry.fDevBounds = bounds; 1635 geometry.fDevBounds = bounds;
1830 1636
1831 return RRectCircleRendererBatch::Create(geometry); 1637 return new RRectCircleRendererBatch(geometry, viewMatrix, isStrokeOnly);
1832 // otherwise we use the ellipse renderer 1638 // otherwise we use the ellipse renderer
1833 } else { 1639 } else {
1834 SkScalar innerXRadius = 0.0f; 1640 SkScalar innerXRadius = 0.0f;
1835 SkScalar innerYRadius = 0.0f; 1641 SkScalar innerYRadius = 0.0f;
1836 if (hasStroke) { 1642 if (hasStroke) {
1837 if (SkScalarNearlyZero(scaledStroke.length())) { 1643 if (SkScalarNearlyZero(scaledStroke.length())) {
1838 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 1644 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
1839 } else { 1645 } else {
1840 scaledStroke.scale(SK_ScalarHalf); 1646 scaledStroke.scale(SK_ScalarHalf);
1841 } 1647 }
(...skipping 20 matching lines...) Expand all
1862 yRadius += scaledStroke.fY; 1668 yRadius += scaledStroke.fY;
1863 bounds.outset(scaledStroke.fX, scaledStroke.fY); 1669 bounds.outset(scaledStroke.fX, scaledStroke.fY);
1864 } 1670 }
1865 1671
1866 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); 1672 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
1867 1673
1868 // Expand the rect so all the pixels will be captured. 1674 // Expand the rect so all the pixels will be captured.
1869 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 1675 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1870 1676
1871 RRectEllipseRendererBatch::Geometry geometry; 1677 RRectEllipseRendererBatch::Geometry geometry;
1872 geometry.fViewMatrix = viewMatrix;
1873 geometry.fColor = color; 1678 geometry.fColor = color;
1874 geometry.fXRadius = xRadius; 1679 geometry.fXRadius = xRadius;
1875 geometry.fYRadius = yRadius; 1680 geometry.fYRadius = yRadius;
1876 geometry.fInnerXRadius = innerXRadius; 1681 geometry.fInnerXRadius = innerXRadius;
1877 geometry.fInnerYRadius = innerYRadius; 1682 geometry.fInnerYRadius = innerYRadius;
1878 geometry.fStroke = isStrokeOnly;
1879 geometry.fDevBounds = bounds; 1683 geometry.fDevBounds = bounds;
1880 1684
1881 return RRectEllipseRendererBatch::Create(geometry); 1685 return new RRectEllipseRendererBatch(geometry, viewMatrix, isStrokeOnly) ;
1882 } 1686 }
1883 } 1687 }
1884 1688
1885 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color, 1689 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color,
1886 const SkMatrix& viewMatrix, 1690 const SkMatrix& viewMatrix,
1887 const SkRRect& rrect, 1691 const SkRRect& rrect,
1888 const SkStrokeRec& stroke, 1692 const SkStrokeRec& stroke,
1889 GrShaderCaps* shaderCaps) { 1693 GrShaderCaps* shaderCaps) {
1890 if (rrect.isOval()) { 1694 if (rrect.isOval()) {
1891 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha derCaps); 1695 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha derCaps);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1924 } 1728 }
1925 1729
1926 DRAW_BATCH_TEST_DEFINE(RRectBatch) { 1730 DRAW_BATCH_TEST_DEFINE(RRectBatch) {
1927 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 1731 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
1928 GrColor color = GrRandomColor(random); 1732 GrColor color = GrRandomColor(random);
1929 const SkRRect& rrect = GrTest::TestRRectSimple(random); 1733 const SkRRect& rrect = GrTest::TestRRectSimple(random);
1930 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); 1734 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom));
1931 } 1735 }
1932 1736
1933 #endif 1737 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698