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

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

Issue 2259323003: GPU implementation of drawArc. (Closed) Base URL: https://chromium.googlesource.com/skia.git@drawArc
Patch Set: minor Created 4 years, 3 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
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"
11 #include "GrBatchTest.h" 11 #include "GrBatchTest.h"
12 #include "GrGeometryProcessor.h" 12 #include "GrGeometryProcessor.h"
13 #include "GrInvariantOutput.h" 13 #include "GrInvariantOutput.h"
14 #include "GrProcessor.h" 14 #include "GrProcessor.h"
15 #include "GrResourceProvider.h" 15 #include "GrResourceProvider.h"
16 #include "GrStyle.h"
16 #include "SkRRect.h" 17 #include "SkRRect.h"
17 #include "SkStrokeRec.h" 18 #include "SkStrokeRec.h"
18 #include "batches/GrVertexBatch.h" 19 #include "batches/GrVertexBatch.h"
19 #include "glsl/GrGLSLFragmentShaderBuilder.h" 20 #include "glsl/GrGLSLFragmentShaderBuilder.h"
20 #include "glsl/GrGLSLGeometryProcessor.h" 21 #include "glsl/GrGLSLGeometryProcessor.h"
21 #include "glsl/GrGLSLProgramDataManager.h" 22 #include "glsl/GrGLSLProgramDataManager.h"
22 #include "glsl/GrGLSLVarying.h" 23 #include "glsl/GrGLSLVarying.h"
23 #include "glsl/GrGLSLVertexShaderBuilder.h" 24 #include "glsl/GrGLSLVertexShaderBuilder.h"
24 #include "glsl/GrGLSLUniformHandler.h" 25 #include "glsl/GrGLSLUniformHandler.h"
25 #include "glsl/GrGLSLUtil.h" 26 #include "glsl/GrGLSLUtil.h"
26 27
27 // TODO(joshualitt) - Break this file up during GrBatch post implementation clea nup 28 // TODO(joshualitt) - Break this file up during GrBatch post implementation clea nup
28 29
29 namespace { 30 namespace {
30 31
31 struct CircleVertex {
32 SkPoint fPos;
33 GrColor fColor;
34 SkPoint fOffset;
35 SkScalar fOuterRadius;
36 SkScalar fInnerRadius;
37 };
38
39 struct EllipseVertex { 32 struct EllipseVertex {
40 SkPoint fPos; 33 SkPoint fPos;
41 GrColor fColor; 34 GrColor fColor;
42 SkPoint fOffset; 35 SkPoint fOffset;
43 SkPoint fOuterRadii; 36 SkPoint fOuterRadii;
44 SkPoint fInnerRadii; 37 SkPoint fInnerRadii;
45 }; 38 };
46 39
47 struct DIEllipseVertex { 40 struct DIEllipseVertex {
48 SkPoint fPos; 41 SkPoint fPos;
(...skipping 19 matching lines...) Expand all
68 * vec4f : (p.xy, outerRad, innerRad) 61 * vec4f : (p.xy, outerRad, innerRad)
69 * p is the position in the normalized space. 62 * p is the position in the normalized space.
70 * outerRad is the outerRadius in device space. 63 * outerRad is the outerRadius in device space.
71 * innerRad is the innerRadius in normalized space (ignored if not s troking). 64 * innerRad is the innerRadius in normalized space (ignored if not s troking).
72 * If fUsesDistanceVectorField is set in fragment processors in the same program , then 65 * If fUsesDistanceVectorField is set in fragment processors in the same program , then
73 * an additional vertex attribute is available via args.fFragBuilder->distanceVe ctorName(): 66 * an additional vertex attribute is available via args.fFragBuilder->distanceVe ctorName():
74 * vec4f : (v.xy, outerDistance, innerDistance) 67 * vec4f : (v.xy, outerDistance, innerDistance)
75 * v is a normalized vector pointing to the outer edge 68 * v is a normalized vector pointing to the outer edge
76 * outerDistance is the distance to the outer edge, < 0 if we are ou tside of the shape 69 * outerDistance is the distance to the outer edge, < 0 if we are ou tside of the shape
77 * if stroking, innerDistance is the distance to the inner edge, < 0 if outside 70 * if stroking, innerDistance is the distance to the inner edge, < 0 if outside
71 * Additional clip planes are supported for rendering circular arcs. The additio nal planes are
72 * either intersected or unioned together. Up to three planes are supported (an initial plane,
73 * a plane intersected with the initial plane, and a plane unioned with the firs t two). Only two
74 * are useful for any given arc, but having all three in one instance allows bat ching different
75 * types of arcs.
78 */ 76 */
79 77
80 class CircleGeometryProcessor : public GrGeometryProcessor { 78 class CircleGeometryProcessor : public GrGeometryProcessor {
81 public: 79 public:
82 CircleGeometryProcessor(bool stroke, const SkMatrix& localMatrix) : fLocalMa trix(localMatrix){ 80 CircleGeometryProcessor(bool stroke, bool clipPlane, bool isectPlane, bool u nionPlane,
81 const SkMatrix& localMatrix)
82 : fLocalMatrix(localMatrix) {
83 this->initClassID<CircleGeometryProcessor>(); 83 this->initClassID<CircleGeometryProcessor>();
84 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttrib Type, 84 fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttrib Type,
85 kHigh_GrSLPrecision); 85 kHigh_GrSLPrecision);
86 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType) ; 86 fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType) ;
87 fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kVec4f_GrVertexAt tribType); 87 fInCircleEdge = &this->addVertexAttrib("inCircleEdge", kVec4f_GrVertexAt tribType);
88 if (clipPlane) {
89 fInClipPlane = &this->addVertexAttrib("inClipPlane", kVec3f_GrVertex AttribType);
90 } else {
91 fInClipPlane = nullptr;
92 }
93 if (isectPlane) {
94 fInIsectPlane = &this->addVertexAttrib("inIsectPlane", kVec3f_GrVert exAttribType);
95 } else {
96 fInIsectPlane = nullptr;
97 }
98 if (unionPlane) {
99 fInUnionPlane = &this->addVertexAttrib("inUnionPlane", kVec3f_GrVert exAttribType);
100 } else {
101 fInUnionPlane = nullptr;
102 }
88 fStroke = stroke; 103 fStroke = stroke;
89 } 104 }
90 105
91 bool implementsDistanceVector() const override { return true; }; 106 bool implementsDistanceVector() const override { return !fInClipPlane; };
92 107
93 virtual ~CircleGeometryProcessor() {} 108 virtual ~CircleGeometryProcessor() {}
94 109
95 const char* name() const override { return "CircleEdge"; } 110 const char* name() const override { return "CircleEdge"; }
96 111
97 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override { 112 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override {
98 GLSLProcessor::GenKey(*this, caps, b); 113 GLSLProcessor::GenKey(*this, caps, b);
99 } 114 }
100 115
101 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de { 116 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de {
102 return new GLSLProcessor(); 117 return new GLSLProcessor();
103 } 118 }
104 119
105 private: 120 private:
106 class GLSLProcessor : public GrGLSLGeometryProcessor { 121 class GLSLProcessor : public GrGLSLGeometryProcessor {
107 public: 122 public:
108 GLSLProcessor() {} 123 GLSLProcessor() {}
109 124
110 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{ 125 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
111 const CircleGeometryProcessor& cgp = args.fGP.cast<CircleGeometryPro cessor>(); 126 const CircleGeometryProcessor& cgp = args.fGP.cast<CircleGeometryPro cessor>();
112 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder; 127 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
113 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 128 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
114 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 129 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
130 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
115 131
116 // emit attributes 132 // emit attributes
117 varyingHandler->emitAttributes(cgp); 133 varyingHandler->emitAttributes(cgp);
134 fragBuilder->codeAppend("vec4 circleEdge;");
135 varyingHandler->addPassThroughAttribute(cgp.fInCircleEdge, "circleEd ge");
136 if (cgp.fInClipPlane) {
137 fragBuilder->codeAppend("vec3 clipPlane;");
138 varyingHandler->addPassThroughAttribute(cgp.fInClipPlane, "clipP lane");
139 }
140 if (cgp.fInIsectPlane) {
141 SkASSERT(cgp.fInClipPlane);
142 fragBuilder->codeAppend("vec3 isectPlane;");
143 varyingHandler->addPassThroughAttribute(cgp.fInIsectPlane, "isec tPlane");
144 }
145 if (cgp.fInUnionPlane) {
146 SkASSERT(cgp.fInClipPlane);
147 fragBuilder->codeAppend("vec3 unionPlane;");
148 varyingHandler->addPassThroughAttribute(cgp.fInUnionPlane, "unio nPlane");
149 }
118 150
119 GrGLSLVertToFrag v(kVec4f_GrSLType);
120 varyingHandler->addVarying("CircleEdge", &v);
121 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), cgp.fInCircleEdge->f Name);
122
123 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
124 // setup pass through color 151 // setup pass through color
125 varyingHandler->addPassThroughAttribute(cgp.fInColor, args.fOutputCo lor); 152 varyingHandler->addPassThroughAttribute(cgp.fInColor, args.fOutputCo lor);
126 153
127 // Setup position 154 // Setup position
128 this->setupPosition(vertBuilder, gpArgs, cgp.fInPosition->fName); 155 this->setupPosition(vertBuilder, gpArgs, cgp.fInPosition->fName);
129 156
130 // emit transforms 157 // emit transforms
131 this->emitTransforms(vertBuilder, 158 this->emitTransforms(vertBuilder,
132 varyingHandler, 159 varyingHandler,
133 uniformHandler, 160 uniformHandler,
134 gpArgs->fPositionVar, 161 gpArgs->fPositionVar,
135 cgp.fInPosition->fName, 162 cgp.fInPosition->fName,
136 cgp.fLocalMatrix, 163 cgp.fLocalMatrix,
137 args.fTransformsIn, 164 args.fTransformsIn,
138 args.fTransformsOut); 165 args.fTransformsOut);
139 166
140 fragBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn()); 167 fragBuilder->codeAppend("float d = length(circleEdge.xy);");
141 fragBuilder->codeAppendf("float distanceToOuterEdge = %s.z * (1.0 - d);", v.fsIn()); 168 fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);");
142 fragBuilder->codeAppendf("float edgeAlpha = clamp(distanceToOuterEdg e, 0.0, 1.0);"); 169 fragBuilder->codeAppend("float edgeAlpha = clamp(distanceToOuterEdge , 0.0, 1.0);");
143 if (cgp.fStroke) { 170 if (cgp.fStroke) {
144 fragBuilder->codeAppendf("float distanceToInnerEdge = %s.z * (d - %s.w);", 171 fragBuilder->codeAppend("float distanceToInnerEdge = circleEdge. z * (d - circleEdge.w);");
145 v.fsIn(), v.fsIn());
146 fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInne rEdge, 0.0, 1.0);"); 172 fragBuilder->codeAppend("float innerAlpha = clamp(distanceToInne rEdge, 0.0, 1.0);");
147 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;"); 173 fragBuilder->codeAppend("edgeAlpha *= innerAlpha;");
148 } 174 }
149 175
150 if (args.fDistanceVectorName) { 176 if (args.fDistanceVectorName) {
151 const char* innerEdgeDistance = cgp.fStroke ? "distanceToInnerEd ge" : "0.0"; 177 const char* innerEdgeDistance = cgp.fStroke ? "distanceToInnerEd ge" : "0.0";
152 fragBuilder->codeAppend ("if (d == 0.0) {"); // if on the center of the circle 178 fragBuilder->codeAppend ("if (d == 0.0) {"); // if on the center of the circle
153 fragBuilder->codeAppendf(" %s = vec4(1.0, 0.0, distanceToOute rEdge, " 179 fragBuilder->codeAppendf(" %s = vec4(1.0, 0.0, distanceToOute rEdge, "
154 "%s);", // no normalize 180 "%s);", // no normalize
155 args.fDistanceVectorName, innerEdgeDist ance); 181 args.fDistanceVectorName, innerEdgeDist ance);
156 fragBuilder->codeAppend ("} else {"); 182 fragBuilder->codeAppend ("} else {");
157 fragBuilder->codeAppendf(" %s = vec4(normalize(%s.xy), distan ceToOuterEdge, " 183 fragBuilder->codeAppendf(" %s = vec4(normalize(circleEdge.xy) , distanceToOuterEdge, %s);",
158 "%s);", 184 args.fDistanceVectorName, innerEdgeDist ance);
159 args.fDistanceVectorName, v.fsIn(), inn erEdgeDistance);
160 fragBuilder->codeAppend ("}"); 185 fragBuilder->codeAppend ("}");
161 } 186 }
162 187 if (cgp.fInClipPlane) {
188 fragBuilder->codeAppend("float clip = clamp(circleEdge.z * dot(c ircleEdge.xy, clipPlane.xy) + clipPlane.z, 0.0, 1.0);");
189 if (cgp.fInIsectPlane) {
190 fragBuilder->codeAppend("clip *= clamp(circleEdge.z * dot(ci rcleEdge.xy, isectPlane.xy) + isectPlane.z, 0.0, 1.0);");
191 }
192 if (cgp.fInUnionPlane) {
193 fragBuilder->codeAppend("clip += (1-clip)*clamp(circleEdge.z * dot(circleEdge.xy, unionPlane.xy) + unionPlane.z, 0.0, 1.0);");
194 }
195 fragBuilder->codeAppend("edgeAlpha *= clip;");
196 }
163 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge); 197 fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCovera ge);
164 } 198 }
165 199
166 static void GenKey(const GrGeometryProcessor& gp, 200 static void GenKey(const GrGeometryProcessor& gp,
167 const GrGLSLCaps&, 201 const GrGLSLCaps&,
168 GrProcessorKeyBuilder* b) { 202 GrProcessorKeyBuilder* b) {
169 const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor >(); 203 const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor >();
170 uint16_t key = cgp.fStroke ? 0x1 : 0x0; 204 uint16_t key;
171 key |= cgp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0; 205 key = cgp.fStroke ? 0x01 : 0x0;
206 key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0;
207 key |= cgp.fInClipPlane ? 0x04 : 0x0;
208 key |= cgp.fInIsectPlane ? 0x08 : 0x0;
209 key |= cgp.fInUnionPlane ? 0x10 : 0x0;
172 b->add32(key); 210 b->add32(key);
173 } 211 }
174 212
175 void setData(const GrGLSLProgramDataManager& pdman, 213 void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor &) override {}
176 const GrPrimitiveProcessor& gp) override {
177 }
178 214
179 void setTransformData(const GrPrimitiveProcessor& primProc, 215 void setTransformData(const GrPrimitiveProcessor& primProc,
180 const GrGLSLProgramDataManager& pdman, 216 const GrGLSLProgramDataManager& pdman,
181 int index, 217 int index,
182 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override { 218 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override {
183 this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>( ).fLocalMatrix, 219 this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>( ).fLocalMatrix,
184 pdman, index, transforms); 220 pdman, index, transforms);
185 } 221 }
186 222
187 private: 223 private:
188 typedef GrGLSLGeometryProcessor INHERITED; 224 typedef GrGLSLGeometryProcessor INHERITED;
189 }; 225 };
190 226
191 SkMatrix fLocalMatrix; 227 SkMatrix fLocalMatrix;
192 const Attribute* fInPosition; 228 const Attribute* fInPosition;
193 const Attribute* fInColor; 229 const Attribute* fInColor;
194 const Attribute* fInCircleEdge; 230 const Attribute* fInCircleEdge;
231 const Attribute* fInClipPlane;
232 const Attribute* fInIsectPlane;
233 const Attribute* fInUnionPlane;
195 bool fStroke; 234 bool fStroke;
196 235
197 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 236 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
198 237
199 typedef GrGeometryProcessor INHERITED; 238 typedef GrGeometryProcessor INHERITED;
200 }; 239 };
201 240
202 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor); 241 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleGeometryProcessor);
203 242
204 sk_sp<GrGeometryProcessor> CircleGeometryProcessor::TestCreate(GrProcessorTestDa ta* d) { 243 sk_sp<GrGeometryProcessor> CircleGeometryProcessor::TestCreate(GrProcessorTestDa ta* d) {
205 return sk_sp<GrGeometryProcessor>( 244 return sk_sp<GrGeometryProcessor>(
206 new CircleGeometryProcessor(d->fRandom->nextBool(), GrTest::TestMatrix(d ->fRandom))); 245 new CircleGeometryProcessor(d->fRandom->nextBool(), d->fRandom->nextBool (),
246 d->fRandom->nextBool(), d->fRandom->nextBool (),
247 GrTest::TestMatrix(d->fRandom)));
207 } 248 }
208 249
209 /////////////////////////////////////////////////////////////////////////////// 250 ///////////////////////////////////////////////////////////////////////////////
210 251
211 /** 252 /**
212 * The output of this effect is a modulation of the input color and coverage for an axis-aligned 253 * The output of this effect is a modulation of the input color and coverage for an axis-aligned
213 * ellipse, specified as a 2D offset from center, and the reciprocals of the out er and inner radii, 254 * ellipse, specified as a 2D offset from center, and the reciprocals of the out er and inner radii,
214 * in both x and y directions. 255 * in both x and y directions.
215 * 256 *
216 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. 257 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0.
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 new DIEllipseGeometryProcessor(GrTest::TestMatrix(d->fRandom), 563 new DIEllipseGeometryProcessor(GrTest::TestMatrix(d->fRandom),
523 (DIEllipseStyle)(d->fRandom->nextRangeU(0 ,2)))); 564 (DIEllipseStyle)(d->fRandom->nextRangeU(0 ,2))));
524 } 565 }
525 566
526 /////////////////////////////////////////////////////////////////////////////// 567 ///////////////////////////////////////////////////////////////////////////////
527 568
528 class CircleBatch : public GrVertexBatch { 569 class CircleBatch : public GrVertexBatch {
529 public: 570 public:
530 DEFINE_BATCH_CLASS_ID 571 DEFINE_BATCH_CLASS_ID
531 572
532 CircleBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& circle, 573 /** Optional extra params to render a partial arc rather than a full circle. */
533 const SkStrokeRec& stroke) 574 struct ArcParams {
534 : INHERITED(ClassID()) 575 SkScalar fStartAngleRadians;
535 , fViewMatrixIfUsingLocalCoords(viewMatrix) { 576 SkScalar fSweepAngleRadians;
536 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); 577 bool fUseCenter;
578 };
579 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, SkPoin t center,
580 SkScalar radius, const GrStyle& style,
581 const ArcParams* arcParams = nullptr) {
582 SkASSERT(circle_stays_circle(viewMatrix));
583 const SkStrokeRec& stroke = style.strokeRec();
584 if (style.hasPathEffect()) {
585 return nullptr;
586 }
587 SkStrokeRec::Style recStyle = stroke.getStyle();
588 if (arcParams) {
589 // Arc support depends on the style.
590 switch (recStyle) {
591 case SkStrokeRec::kStrokeAndFill_Style:
robertphillips 2016/08/22 19:43:34 results -> result ?
bsalomon 2016/08/22 19:46:40 Done.
592 // This produces a strange results that this batch doesn't i mplement.
593 return nullptr;
594 case SkStrokeRec::kFill_Style:
595 // This supports all fills.
596 break;
robertphillips 2016/08/22 19:43:34 // fall through ?
bsalomon 2016/08/22 19:46:40 Done.
597 case SkStrokeRec::kStroke_Style:
598 case SkStrokeRec::kHairline_Style:
599 // Strokes that don't use the center point are supported wit h butt cap.
600 if (arcParams->fUseCenter || stroke.getCap() != SkPaint::kBu tt_Cap) {
601 return nullptr;
602 }
603 break;
604 }
605 }
606
537 viewMatrix.mapPoints(&center, 1); 607 viewMatrix.mapPoints(&center, 1);
538 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); 608 radius = viewMatrix.mapRadius(radius);
539 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); 609 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth());
540 610
541 SkStrokeRec::Style style = stroke.getStyle(); 611 bool isStrokeOnly = SkStrokeRec::kStroke_Style == recStyle ||
542 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || 612 SkStrokeRec::kHairline_Style == recStyle;
543 SkStrokeRec::kHairline_Style == style; 613 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == re cStyle;
544 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == st yle;
545 614
546 SkScalar innerRadius = 0.0f; 615 SkScalar innerRadius = 0.0f;
547 SkScalar outerRadius = radius; 616 SkScalar outerRadius = radius;
548 SkScalar halfWidth = 0; 617 SkScalar halfWidth = 0;
549 if (hasStroke) { 618 if (hasStroke) {
550 if (SkScalarNearlyZero(strokeWidth)) { 619 if (SkScalarNearlyZero(strokeWidth)) {
551 halfWidth = SK_ScalarHalf; 620 halfWidth = SK_ScalarHalf;
552 } else { 621 } else {
553 halfWidth = SkScalarHalf(strokeWidth); 622 halfWidth = SkScalarHalf(strokeWidth);
554 } 623 }
555 624
556 outerRadius += halfWidth; 625 outerRadius += halfWidth;
557 if (isStrokeOnly) { 626 if (isStrokeOnly) {
558 innerRadius = radius - halfWidth; 627 innerRadius = radius - halfWidth;
559 } 628 }
560 } 629 }
561 630
562 // The radii are outset for two reasons. First, it allows the shader to simply perform 631 // The radii are outset for two reasons. First, it allows the shader to simply perform
563 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. 632 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius.
564 // Second, the outer radius is used to compute the verts of the bounding box that is 633 // Second, the outer radius is used to compute the verts of the bounding box that is
565 // rendered and the outset ensures the box will cover all partially cove red by the circle. 634 // rendered and the outset ensures the box will cover all partially cove red by the circle.
566 outerRadius += SK_ScalarHalf; 635 outerRadius += SK_ScalarHalf;
567 innerRadius -= SK_ScalarHalf; 636 innerRadius -= SK_ScalarHalf;
637 CircleBatch* batch = new CircleBatch();
638 batch->fViewMatrixIfUsingLocalCoords = viewMatrix;
568 639
569 fGeoData.emplace_back(Geometry { 640 // This makes every point fully inside the intersection plane.
570 color, 641 static constexpr SkScalar kUnusedIsectPlane[] = {0.f, 0.f, 1.f};
571 innerRadius, 642 // This makes every point fully outside the union plane.
572 outerRadius, 643 static constexpr SkScalar kUnusedUnionPlane[] = {0.f, 0.f, 0.f};
573 SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius, 644
574 center.fX + outerRadius, center.fY + outerRadius) 645 if (arcParams) {
575 }); 646 // The shader operates in a space where the circle is translated to be centered at the
647 // origin. Here we compute points on the unit circle at the starting and ending angles.
648 SkPoint startPoint, stopPoint;
649 startPoint.fY = SkScalarSinCos(arcParams->fStartAngleRadians, &start Point.fX);
650 SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSwee pAngleRadians;
651 stopPoint.fY = SkScalarSinCos(endAngle, &stopPoint.fX);
652 // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against
653 // radial lines. However, in both cases we have to be careful about the half-circle.
654 // case. In that case the two radial lines are equal and so that edg e gets clipped
655 // twice. Since the shared edge goes through the center we fall back on the useCenter
656 // case.
657 bool useCenter = (arcParams->fUseCenter || isStrokeOnly) &&
658 !SkScalarNearlyEqual(SkScalarAbs(arcParams->fSweepA ngleRadians),
659 SK_ScalarPI);
660 if (useCenter) {
661 SkVector norm0 = {startPoint.fY, -startPoint.fX};
662 SkVector norm1 = {stopPoint.fY, -stopPoint.fX};
663 if (arcParams->fSweepAngleRadians > 0) {
664 norm0.negate();
665 } else {
666 norm1.negate();
667 }
668 batch->fClipPlane = true;
robertphillips 2016/08/22 19:02:52 space before '>' ?
bsalomon 2016/08/22 19:18:27 Done.
669 if (SkScalarAbs(arcParams->fSweepAngleRadians)> SK_ScalarPI) {
670 batch->fGeoData.emplace_back(Geometry {
671 color,
672 innerRadius,
673 outerRadius,
674 {norm0.fX, norm0.fY, 0.5f},
675 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnused IsectPlane[2]},
676 {norm1.fX, norm1.fY, 0.5f},
robertphillips 2016/08/22 19:02:52 I'm not sure if it would be clearer to create a si
bsalomon 2016/08/22 19:18:27 Done.
677 SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
678 center.fX + outerRadius, center.fY + outerRadius)
679 });
680 batch->fClipPlaneIsect = false;
681 batch->fClipPlaneUnion = true;
682 } else {
683 batch->fGeoData.emplace_back(Geometry {
684 color,
685 innerRadius,
686 outerRadius,
687 {norm0.fX, norm0.fY, 0.5f},
688 {norm1.fX, norm1.fY, 0.5f},
689 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnused UnionPlane[2]},
690 SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
691 center.fX + outerRadius, center.fY + outerRadius)
692 });
693 batch->fClipPlaneIsect = true;
694 batch->fClipPlaneUnion = false;
695 }
696 } else {
697 // We clip to a secant of the original circle.
698 startPoint.scale(radius);
699 stopPoint.scale(radius);
700 SkVector norm = {startPoint.fY - stopPoint.fY, stopPoint.fX - st artPoint.fX};
701 norm.normalize();
702 if (arcParams->fSweepAngleRadians > 0) {
703 norm.negate();
704 }
705 SkScalar d = -norm.dot(startPoint) + 0.5f;
706
707 batch->fGeoData.emplace_back(Geometry {
708 color,
709 innerRadius,
710 outerRadius,
711 {norm.fX, norm.fY, d},
712 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsec tPlane[2]},
713 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnio nPlane[2]},
714 SkRect::MakeLTRB(center.fX - outerRadius, center.fY - ou terRadius,
715 center.fX + outerRadius, center.fY + ou terRadius)
716 });
717 batch->fClipPlane = true;
718 batch->fClipPlaneIsect = false;
719 batch->fClipPlaneUnion = false;
720 }
721 } else {
722 batch->fGeoData.emplace_back(Geometry {
723 color,
724 innerRadius,
725 outerRadius,
726 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]},
727 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]},
728 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2 ]},
729 SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadiu s,
730 center.fX + outerRadius, center.fY + outerRadiu s)
731 });
732 batch->fClipPlane = false;
733 batch->fClipPlaneIsect = false;
734 batch->fClipPlaneUnion = false;
735 }
576 // Use the original radius and stroke radius for the bounds so that it d oes not include the 736 // Use the original radius and stroke radius for the bounds so that it d oes not include the
577 // AA bloat. 737 // AA bloat.
578 radius += halfWidth; 738 radius += halfWidth;
robertphillips 2016/08/22 19:02:52 Are these bounds correct? It seems like we should
bsalomon 2016/08/22 19:18:27 See comment above, using original values since the
579 this->setBounds({center.fX - radius, center.fY - radius, 739 batch->setBounds({center.fX - radius, center.fY - radius,
580 center.fX + radius, center.fY + radius}, 740 center.fX + radius, center.fY + radius},
581 HasAABloat::kYes, IsZeroArea::kNo); 741 HasAABloat::kYes, IsZeroArea::kNo);
582 fStroked = isStrokeOnly && innerRadius > 0; 742 batch->fStroked = isStrokeOnly && innerRadius > 0;
743 return batch;
583 } 744 }
584 745
585 const char* name() const override { return "CircleBatch"; } 746 const char* name() const override { return "CircleBatch"; }
586 747
587 SkString dumpInfo() const override { 748 SkString dumpInfo() const override {
588 SkString string; 749 SkString string;
589 for (int i = 0; i < fGeoData.count(); ++i) { 750 for (int i = 0; i < fGeoData.count(); ++i) {
590 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," 751 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f],"
591 "InnerRad: %.2f, OuterRad: %.2f\n", 752 "InnerRad: %.2f, OuterRad: %.2f\n",
592 fGeoData[i].fColor, 753 fGeoData[i].fColor,
593 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop, 754 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop,
594 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom, 755 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom,
595 fGeoData[i].fInnerRadius, 756 fGeoData[i].fInnerRadius,
596 fGeoData[i].fOuterRadius); 757 fGeoData[i].fOuterRadius);
597 } 758 }
598 string.append(INHERITED::dumpInfo()); 759 string.append(INHERITED::dumpInfo());
599 return string; 760 return string;
600 } 761 }
601 762
602 void computePipelineOptimizations(GrInitInvariantOutput* color, 763 void computePipelineOptimizations(GrInitInvariantOutput* color,
603 GrInitInvariantOutput* coverage, 764 GrInitInvariantOutput* coverage,
604 GrBatchToXPOverrides* overrides) const ove rride { 765 GrBatchToXPOverrides* overrides) const ove rride {
605 // When this is called on a batch, there is only one geometry bundle 766 // When this is called on a batch, there is only one geometry bundle
606 color->setKnownFourComponents(fGeoData[0].fColor); 767 color->setKnownFourComponents(fGeoData[0].fColor);
607 coverage->setUnknownSingleComponent(); 768 coverage->setUnknownSingleComponent();
608 } 769 }
609 770
610 private: 771 private:
772 CircleBatch() : INHERITED(ClassID()) {}
611 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 773 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
612 // Handle any overrides that affect our GP. 774 // Handle any overrides that affect our GP.
613 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); 775 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
614 if (!overrides.readsLocalCoords()) { 776 if (!overrides.readsLocalCoords()) {
615 fViewMatrixIfUsingLocalCoords.reset(); 777 fViewMatrixIfUsingLocalCoords.reset();
616 } 778 }
617 } 779 }
618 780
619 void onPrepareDraws(Target* target) const override { 781 void onPrepareDraws(Target* target) const override {
620 SkMatrix localMatrix; 782 SkMatrix localMatrix;
621 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 783 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
622 return; 784 return;
623 } 785 }
624 786
625 // Setup geometry processor 787 // Setup geometry processor
626 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, localMatrix)); 788 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, fClipPlane,
789 fClipPl aneIsect,
790 fClipPl aneUnion,
791 localMa trix));
792
793 struct CircleVertex {
794 SkPoint fPos;
795 GrColor fColor;
796 SkPoint fOffset;
797 SkScalar fOuterRadius;
798 SkScalar fInnerRadius;
799 // These planes may or may not be present in the vertex buffer.
800 SkScalar fHalfPlanes[3][3];
801 };
627 802
628 int instanceCount = fGeoData.count(); 803 int instanceCount = fGeoData.count();
629 size_t vertexStride = gp->getVertexStride(); 804 size_t vertexStride = gp->getVertexStride();
630 SkASSERT(vertexStride == sizeof(CircleVertex)); 805 SkASSERT(vertexStride == sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * si zeof(SkScalar))
806 - (fClipPlaneIsect? 0 : 3 * sizeof(SkScalar))
807 - (fClipPlaneUnion? 0 : 3 * sizeof(SkScalar)));
631 QuadHelper helper; 808 QuadHelper helper;
632 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , vertexStride, 809 char* vertices = reinterpret_cast<char*>(helper.init(target, vertexStrid e, instanceCount));
633 instan ceCount)); 810 if (!vertices) {
634 if (!verts) {
635 return; 811 return;
636 } 812 }
637 813
638 for (int i = 0; i < instanceCount; i++) { 814 for (int i = 0; i < instanceCount; i++) {
639 const Geometry& geom = fGeoData[i]; 815 const Geometry& geom = fGeoData[i];
640 816
641 GrColor color = geom.fColor; 817 GrColor color = geom.fColor;
642 SkScalar innerRadius = geom.fInnerRadius; 818 SkScalar innerRadius = geom.fInnerRadius;
643 SkScalar outerRadius = geom.fOuterRadius; 819 SkScalar outerRadius = geom.fOuterRadius;
644 820
645 const SkRect& bounds = geom.fDevBounds; 821 const SkRect& bounds = geom.fDevBounds;
822 CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 0)*vertexStride);
823 CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 1)*vertexStride);
824 CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 2)*vertexStride);
825 CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 3)*vertexStride);
646 826
647 // The inner radius in the vertex data must be specified in normaliz ed space. 827 // The inner radius in the vertex data must be specified in normaliz ed space.
648 innerRadius = innerRadius / outerRadius; 828 innerRadius = innerRadius / outerRadius;
649 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 829 v0->fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
650 verts[0].fColor = color; 830 v0->fColor = color;
651 verts[0].fOffset = SkPoint::Make(-1, -1); 831 v0->fOffset = SkPoint::Make(-1, -1);
652 verts[0].fOuterRadius = outerRadius; 832 v0->fOuterRadius = outerRadius;
653 verts[0].fInnerRadius = innerRadius; 833 v0->fInnerRadius = innerRadius;
654 834
655 verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 835 v1->fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
656 verts[1].fColor = color; 836 v1->fColor = color;
657 verts[1].fOffset = SkPoint::Make(-1, 1); 837 v1->fOffset = SkPoint::Make(-1, 1);
658 verts[1].fOuterRadius = outerRadius; 838 v1->fOuterRadius = outerRadius;
659 verts[1].fInnerRadius = innerRadius; 839 v1->fInnerRadius = innerRadius;
660 840
661 verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 841 v2->fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
662 verts[2].fColor = color; 842 v2->fColor = color;
663 verts[2].fOffset = SkPoint::Make(1, 1); 843 v2->fOffset = SkPoint::Make(1, 1);
664 verts[2].fOuterRadius = outerRadius; 844 v2->fOuterRadius = outerRadius;
665 verts[2].fInnerRadius = innerRadius; 845 v2->fInnerRadius = innerRadius;
666 846
667 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 847 v3->fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
668 verts[3].fColor = color; 848 v3->fColor = color;
669 verts[3].fOffset = SkPoint::Make(1, -1); 849 v3->fOffset = SkPoint::Make(1, -1);
670 verts[3].fOuterRadius = outerRadius; 850 v3->fOuterRadius = outerRadius;
671 verts[3].fInnerRadius = innerRadius; 851 v3->fInnerRadius = innerRadius;
672 852
673 verts += kVerticesPerQuad; 853 if (fClipPlane) {
854 memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
855 memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
856 memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
857 memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
858 }
859 int unionIdx = 1;
860 if (fClipPlaneIsect) {
861 memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
862 memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
863 memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
864 memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
865 unionIdx = 2;
866 }
867 if (fClipPlaneUnion) {
868 memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
869 memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
870 memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
871 memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
872 }
674 } 873 }
675 helper.recordDraw(target, gp); 874 helper.recordDraw(target, gp);
676 } 875 }
677 876
678 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 877 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
679 CircleBatch* that = t->cast<CircleBatch>(); 878 CircleBatch* that = t->cast<CircleBatch>();
680 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 879 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
681 that->bounds(), caps)) { 880 that->bounds(), caps)) {
682 return false; 881 return false;
683 } 882 }
684 883
685 if (this->fStroked != that->fStroked) { 884 if (this->fStroked != that->fStroked) {
686 return false; 885 return false;
687 } 886 }
688 887
robertphillips 2016/08/22 19:02:52 // Because we've set up the batches that don't use
bsalomon 2016/08/22 19:18:27 Done.
888 fClipPlane |= that->fClipPlane;
889 fClipPlaneIsect |= that->fClipPlaneIsect;
890 fClipPlaneUnion |= that->fClipPlaneUnion;
891
689 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) { 892 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
690 return false; 893 return false;
691 } 894 }
692 895
693 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 896 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
694 this->joinBounds(*that); 897 this->joinBounds(*that);
695 return true; 898 return true;
696 } 899 }
697 900
698 struct Geometry { 901 struct Geometry {
699 GrColor fColor; 902 GrColor fColor;
700 SkScalar fInnerRadius; 903 SkScalar fInnerRadius;
701 SkScalar fOuterRadius; 904 SkScalar fOuterRadius;
702 SkRect fDevBounds; 905 SkScalar fClipPlane[3];
906 SkScalar fIsectPlane[3];
907 SkScalar fUnionPlane[3];
908 SkRect fDevBounds;
703 }; 909 };
704 910
705 bool fStroked; 911 bool fStroked;
912 bool fClipPlane;
913 bool fClipPlaneIsect;
914 bool fClipPlaneUnion;
706 SkMatrix fViewMatrixIfUsingLocalCoords; 915 SkMatrix fViewMatrixIfUsingLocalCoords;
707 SkSTArray<1, Geometry, true> fGeoData; 916 SkSTArray<1, Geometry, true> fGeoData;
708 917
709 typedef GrVertexBatch INHERITED; 918 typedef GrVertexBatch INHERITED;
710 }; 919 };
711 920
712 /////////////////////////////////////////////////////////////////////////////// 921 ///////////////////////////////////////////////////////////////////////////////
713 922
714 class EllipseBatch : public GrVertexBatch { 923 class EllipseBatch : public GrVertexBatch {
715 public: 924 public:
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 } 1445 }
1237 1446
1238 void onPrepareDraws(Target* target) const override { 1447 void onPrepareDraws(Target* target) const override {
1239 // Invert the view matrix as a local matrix (if any other processors req uire coords). 1448 // Invert the view matrix as a local matrix (if any other processors req uire coords).
1240 SkMatrix localMatrix; 1449 SkMatrix localMatrix;
1241 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 1450 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
1242 return; 1451 return;
1243 } 1452 }
1244 1453
1245 // Setup geometry processor 1454 // Setup geometry processor
1246 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, localMatrix)); 1455 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, false, false,
1456 false, localMatrix));
1457
1458 struct CircleVertex {
1459 SkPoint fPos;
1460 GrColor fColor;
1461 SkPoint fOffset;
1462 SkScalar fOuterRadius;
1463 SkScalar fInnerRadius;
1464 // No half plane, we don't use it here.
1465 };
1247 1466
1248 int instanceCount = fGeoData.count(); 1467 int instanceCount = fGeoData.count();
1249 size_t vertexStride = gp->getVertexStride(); 1468 size_t vertexStride = gp->getVertexStride();
1250 SkASSERT(vertexStride == sizeof(CircleVertex)); 1469 SkASSERT(vertexStride == sizeof(CircleVertex));
1251 1470
1252 // drop out the middle quad if we're stroked 1471 // drop out the middle quad if we're stroked
1253 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect; 1472 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect;
1254 SkAutoTUnref<const GrBuffer> indexBuffer( 1473 SkAutoTUnref<const GrBuffer> indexBuffer(
1255 ref_rrect_index_buffer(fStroked, target->resourceProvider())); 1474 ref_rrect_index_buffer(fStroked, target->resourceProvider()));
1256 1475
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1624 return RRectEllipseRendererBatch::Create(color, viewMatrix, bounds, xRad ius, yRadius, 1843 return RRectEllipseRendererBatch::Create(color, viewMatrix, bounds, xRad ius, yRadius,
1625 scaledStroke, isStrokeOnly); 1844 scaledStroke, isStrokeOnly);
1626 1845
1627 } 1846 }
1628 } 1847 }
1629 1848
1630 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color, 1849 GrDrawBatch* GrOvalRenderer::CreateRRectBatch(GrColor color,
1631 const SkMatrix& viewMatrix, 1850 const SkMatrix& viewMatrix,
1632 const SkRRect& rrect, 1851 const SkRRect& rrect,
1633 const SkStrokeRec& stroke, 1852 const SkStrokeRec& stroke,
1634 GrShaderCaps* shaderCaps) { 1853 const GrShaderCaps* shaderCaps) {
1635 if (rrect.isOval()) { 1854 if (rrect.isOval()) {
1636 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha derCaps); 1855 return CreateOvalBatch(color, viewMatrix, rrect.getBounds(), stroke, sha derCaps);
1637 } 1856 }
1638 1857
1639 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { 1858 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) {
1640 return nullptr; 1859 return nullptr;
1641 } 1860 }
1642 1861
1643 return create_rrect_batch(color, viewMatrix, rrect, stroke); 1862 return create_rrect_batch(color, viewMatrix, rrect, stroke);
1644 } 1863 }
1645 1864
1646 /////////////////////////////////////////////////////////////////////////////// 1865 ///////////////////////////////////////////////////////////////////////////////
1647 1866
1648 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color, 1867 GrDrawBatch* GrOvalRenderer::CreateOvalBatch(GrColor color,
1649 const SkMatrix& viewMatrix, 1868 const SkMatrix& viewMatrix,
1650 const SkRect& oval, 1869 const SkRect& oval,
1651 const SkStrokeRec& stroke, 1870 const SkStrokeRec& stroke,
1652 GrShaderCaps* shaderCaps) { 1871 const GrShaderCaps* shaderCaps) {
1653 // we can draw circles 1872 // we can draw circles
1654 if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle( viewMatrix)) { 1873 SkScalar width = oval.width();
1655 return new CircleBatch(color, viewMatrix, oval, stroke); 1874 if (SkScalarNearlyEqual(width, oval.height()) && circle_stays_circle(viewMat rix)) {
1875 SkPoint center = {oval.centerX(), oval.centerY()};
1876 return CircleBatch::Create(color, viewMatrix, center, width / 2.f,
1877 GrStyle(stroke, nullptr));
1656 } 1878 }
1657 1879
1658 // if we have shader derivative support, render as device-independent 1880 // if we have shader derivative support, render as device-independent
1659 if (shaderCaps->shaderDerivativeSupport()) { 1881 if (shaderCaps->shaderDerivativeSupport()) {
1660 return DIEllipseBatch::Create(color, viewMatrix, oval, stroke); 1882 return DIEllipseBatch::Create(color, viewMatrix, oval, stroke);
1661 } 1883 }
1662 1884
1663 // otherwise axis-aligned ellipses only 1885 // otherwise axis-aligned ellipses only
1664 if (viewMatrix.rectStaysRect()) { 1886 if (viewMatrix.rectStaysRect()) {
1665 return EllipseBatch::Create(color, viewMatrix, oval, stroke); 1887 return EllipseBatch::Create(color, viewMatrix, oval, stroke);
1666 } 1888 }
1667 1889
1668 return nullptr; 1890 return nullptr;
1669 } 1891 }
1670 1892
1671 /////////////////////////////////////////////////////////////////////////////// 1893 ///////////////////////////////////////////////////////////////////////////////
1672 1894
1895 GrDrawBatch* GrOvalRenderer::CreateArcBatch(GrColor color,
1896 const SkMatrix& viewMatrix,
1897 const SkRect& oval,
1898 SkScalar startAngle, SkScalar sweepA ngle,
1899 bool useCenter,
1900 const GrStyle& style,
1901 const GrShaderCaps* shaderCaps) {
1902 SkScalar width = oval.width();
1903 if (!SkScalarNearlyEqual(width, oval.height()) || !circle_stays_circle(viewM atrix)) {
1904 return nullptr;
1905 }
1906 SkPoint center = {oval.centerX(), oval.centerY()};
1907 CircleBatch::ArcParams arcParams = {
1908 SkDegreesToRadians(startAngle),
1909 SkDegreesToRadians(sweepAngle),
1910 useCenter
1911 };
1912 return CircleBatch::Create(color, viewMatrix, center, width/2.f, style, &arc Params);
1913 }
1914
1915 ///////////////////////////////////////////////////////////////////////////////
1916
1673 #ifdef GR_TEST_UTILS 1917 #ifdef GR_TEST_UTILS
1674 1918
1675 DRAW_BATCH_TEST_DEFINE(CircleBatch) { 1919 DRAW_BATCH_TEST_DEFINE(CircleBatch) {
1676 SkMatrix viewMatrix = GrTest::TestMatrix(random); 1920 do {
1677 GrColor color = GrRandomColor(random); 1921 SkMatrix viewMatrix = GrTest::TestMatrix(random);
1678 SkRect circle = GrTest::TestSquare(random); 1922 GrColor color = GrRandomColor(random);
1679 return new CircleBatch(color, viewMatrix, circle, GrTest::TestStrokeRec(rand om)); 1923 SkRect circle = GrTest::TestSquare(random);
1924 SkPoint center = {circle.centerX(), circle.centerY()};
1925 SkScalar radius = circle.width() / 2.f;
1926 SkStrokeRec stroke = GrTest::TestStrokeRec(random);
1927 CircleBatch::ArcParams arcParamsTmp;
1928 const CircleBatch::ArcParams* arcParams = nullptr;
1929 if (random->nextBool()) {
1930 arcParamsTmp.fStartAngleRadians = random->nextSScalar1() * SK_Scalar PI * 2;
1931 arcParamsTmp.fStartAngleRadians = random->nextSScalar1() * SK_Scalar PI * 2 - .01;
1932 arcParams = &arcParamsTmp;
1933 }
1934 GrDrawBatch* batch = CircleBatch::Create(color, viewMatrix, center, radi us,
1935 GrStyle(stroke, nullptr), arcPa rams);
1936 if (batch) {
1937 return batch;
1938 }
1939 } while (true);
1680 } 1940 }
1681 1941
1682 DRAW_BATCH_TEST_DEFINE(EllipseBatch) { 1942 DRAW_BATCH_TEST_DEFINE(EllipseBatch) {
1683 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 1943 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
1684 GrColor color = GrRandomColor(random); 1944 GrColor color = GrRandomColor(random);
1685 SkRect ellipse = GrTest::TestSquare(random); 1945 SkRect ellipse = GrTest::TestSquare(random);
1686 return EllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStrokeRe c(random)); 1946 return EllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStrokeRe c(random));
1687 } 1947 }
1688 1948
1689 DRAW_BATCH_TEST_DEFINE(DIEllipseBatch) { 1949 DRAW_BATCH_TEST_DEFINE(DIEllipseBatch) {
1690 SkMatrix viewMatrix = GrTest::TestMatrix(random); 1950 SkMatrix viewMatrix = GrTest::TestMatrix(random);
1691 GrColor color = GrRandomColor(random); 1951 GrColor color = GrRandomColor(random);
1692 SkRect ellipse = GrTest::TestSquare(random); 1952 SkRect ellipse = GrTest::TestSquare(random);
1693 return DIEllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStroke Rec(random)); 1953 return DIEllipseBatch::Create(color, viewMatrix, ellipse, GrTest::TestStroke Rec(random));
1694 } 1954 }
1695 1955
1696 DRAW_BATCH_TEST_DEFINE(RRectBatch) { 1956 DRAW_BATCH_TEST_DEFINE(RRectBatch) {
1697 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); 1957 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random);
1698 GrColor color = GrRandomColor(random); 1958 GrColor color = GrRandomColor(random);
1699 const SkRRect& rrect = GrTest::TestRRectSimple(random); 1959 const SkRRect& rrect = GrTest::TestRRectSimple(random);
1700 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); 1960 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom));
1701 } 1961 }
1702 1962
1703 #endif 1963 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrOvalRenderer.h ('k') | src/gpu/SkGpuDevice.h » ('j') | src/gpu/SkGpuDevice.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698