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

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: Address comments Created 4 years, 4 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 | « src/gpu/GrOvalRenderer.h ('k') | src/gpu/SkGpuDevice.h » ('j') | 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"
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:
592 // This produces a strange result that this batch doesn't im plement.
593 return nullptr;
594 case SkStrokeRec::kFill_Style:
595 // This supports all fills.
596 break;
597 case SkStrokeRec::kStroke_Style: // fall through
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 SkRect devBounds = SkRect::MakeLTRB(center.fX - outerRadius, center.fY - outerRadius,
574 center.fX + outerRadius, center.fY + outerRadius) 645 center.fX + outerRadius, center.fY + outerRadius);
575 }); 646
647 if (arcParams) {
648 // The shader operates in a space where the circle is translated to be centered at the
649 // origin. Here we compute points on the unit circle at the starting and ending angles.
650 SkPoint startPoint, stopPoint;
651 startPoint.fY = SkScalarSinCos(arcParams->fStartAngleRadians, &start Point.fX);
652 SkScalar endAngle = arcParams->fStartAngleRadians + arcParams->fSwee pAngleRadians;
653 stopPoint.fY = SkScalarSinCos(endAngle, &stopPoint.fX);
654 // Like a fill without useCenter, butt-cap stroke can be implemented by clipping against
655 // radial lines. However, in both cases we have to be careful about the half-circle.
656 // case. In that case the two radial lines are equal and so that edg e gets clipped
657 // twice. Since the shared edge goes through the center we fall back on the useCenter
658 // case.
659 bool useCenter = (arcParams->fUseCenter || isStrokeOnly) &&
660 !SkScalarNearlyEqual(SkScalarAbs(arcParams->fSweepA ngleRadians),
661 SK_ScalarPI);
662 if (useCenter) {
663 SkVector norm0 = {startPoint.fY, -startPoint.fX};
664 SkVector norm1 = {stopPoint.fY, -stopPoint.fX};
665 if (arcParams->fSweepAngleRadians > 0) {
666 norm0.negate();
667 } else {
668 norm1.negate();
669 }
670 batch->fClipPlane = true;
671 if (SkScalarAbs(arcParams->fSweepAngleRadians) > SK_ScalarPI) {
672 batch->fGeoData.emplace_back(Geometry {
673 color,
674 innerRadius,
675 outerRadius,
676 {norm0.fX, norm0.fY, 0.5f},
677 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnused IsectPlane[2]},
678 {norm1.fX, norm1.fY, 0.5f},
679 devBounds
680 });
681 batch->fClipPlaneIsect = false;
682 batch->fClipPlaneUnion = true;
683 } else {
684 batch->fGeoData.emplace_back(Geometry {
685 color,
686 innerRadius,
687 outerRadius,
688 {norm0.fX, norm0.fY, 0.5f},
689 {norm1.fX, norm1.fY, 0.5f},
690 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnused UnionPlane[2]},
691 devBounds
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 devBounds
715 });
716 batch->fClipPlane = true;
717 batch->fClipPlaneIsect = false;
718 batch->fClipPlaneUnion = false;
719 }
720 } else {
721 batch->fGeoData.emplace_back(Geometry {
722 color,
723 innerRadius,
724 outerRadius,
725 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]},
726 {kUnusedIsectPlane[0], kUnusedIsectPlane[1], kUnusedIsectPlane[2 ]},
727 {kUnusedUnionPlane[0], kUnusedUnionPlane[1], kUnusedUnionPlane[2 ]},
728 devBounds
729 });
730 batch->fClipPlane = false;
731 batch->fClipPlaneIsect = false;
732 batch->fClipPlaneUnion = false;
733 }
576 // Use the original radius and stroke radius for the bounds so that it d oes not include the 734 // Use the original radius and stroke radius for the bounds so that it d oes not include the
577 // AA bloat. 735 // AA bloat.
578 radius += halfWidth; 736 radius += halfWidth;
579 this->setBounds({center.fX - radius, center.fY - radius, 737 batch->setBounds({center.fX - radius, center.fY - radius,
580 center.fX + radius, center.fY + radius}, 738 center.fX + radius, center.fY + radius},
581 HasAABloat::kYes, IsZeroArea::kNo); 739 HasAABloat::kYes, IsZeroArea::kNo);
582 fStroked = isStrokeOnly && innerRadius > 0; 740 batch->fStroked = isStrokeOnly && innerRadius > 0;
741 return batch;
583 } 742 }
584 743
585 const char* name() const override { return "CircleBatch"; } 744 const char* name() const override { return "CircleBatch"; }
586 745
587 SkString dumpInfo() const override { 746 SkString dumpInfo() const override {
588 SkString string; 747 SkString string;
589 for (int i = 0; i < fGeoData.count(); ++i) { 748 for (int i = 0; i < fGeoData.count(); ++i) {
590 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," 749 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f],"
591 "InnerRad: %.2f, OuterRad: %.2f\n", 750 "InnerRad: %.2f, OuterRad: %.2f\n",
592 fGeoData[i].fColor, 751 fGeoData[i].fColor,
593 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop, 752 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop,
594 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom, 753 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom,
595 fGeoData[i].fInnerRadius, 754 fGeoData[i].fInnerRadius,
596 fGeoData[i].fOuterRadius); 755 fGeoData[i].fOuterRadius);
597 } 756 }
598 string.append(INHERITED::dumpInfo()); 757 string.append(INHERITED::dumpInfo());
599 return string; 758 return string;
600 } 759 }
601 760
602 void computePipelineOptimizations(GrInitInvariantOutput* color, 761 void computePipelineOptimizations(GrInitInvariantOutput* color,
603 GrInitInvariantOutput* coverage, 762 GrInitInvariantOutput* coverage,
604 GrBatchToXPOverrides* overrides) const ove rride { 763 GrBatchToXPOverrides* overrides) const ove rride {
605 // When this is called on a batch, there is only one geometry bundle 764 // When this is called on a batch, there is only one geometry bundle
606 color->setKnownFourComponents(fGeoData[0].fColor); 765 color->setKnownFourComponents(fGeoData[0].fColor);
607 coverage->setUnknownSingleComponent(); 766 coverage->setUnknownSingleComponent();
608 } 767 }
609 768
610 private: 769 private:
770 CircleBatch() : INHERITED(ClassID()) {}
611 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { 771 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
612 // Handle any overrides that affect our GP. 772 // Handle any overrides that affect our GP.
613 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); 773 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
614 if (!overrides.readsLocalCoords()) { 774 if (!overrides.readsLocalCoords()) {
615 fViewMatrixIfUsingLocalCoords.reset(); 775 fViewMatrixIfUsingLocalCoords.reset();
616 } 776 }
617 } 777 }
618 778
619 void onPrepareDraws(Target* target) const override { 779 void onPrepareDraws(Target* target) const override {
620 SkMatrix localMatrix; 780 SkMatrix localMatrix;
621 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { 781 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
622 return; 782 return;
623 } 783 }
624 784
625 // Setup geometry processor 785 // Setup geometry processor
626 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, localMatrix)); 786 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, fClipPlane,
787 fClipPl aneIsect,
788 fClipPl aneUnion,
789 localMa trix));
790
791 struct CircleVertex {
792 SkPoint fPos;
793 GrColor fColor;
794 SkPoint fOffset;
795 SkScalar fOuterRadius;
796 SkScalar fInnerRadius;
797 // These planes may or may not be present in the vertex buffer.
798 SkScalar fHalfPlanes[3][3];
799 };
627 800
628 int instanceCount = fGeoData.count(); 801 int instanceCount = fGeoData.count();
629 size_t vertexStride = gp->getVertexStride(); 802 size_t vertexStride = gp->getVertexStride();
630 SkASSERT(vertexStride == sizeof(CircleVertex)); 803 SkASSERT(vertexStride == sizeof(CircleVertex) - (fClipPlane ? 0 : 3 * si zeof(SkScalar))
804 - (fClipPlaneIsect? 0 : 3 * sizeof(SkScalar))
805 - (fClipPlaneUnion? 0 : 3 * sizeof(SkScalar)));
631 QuadHelper helper; 806 QuadHelper helper;
632 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , vertexStride, 807 char* vertices = reinterpret_cast<char*>(helper.init(target, vertexStrid e, instanceCount));
633 instan ceCount)); 808 if (!vertices) {
634 if (!verts) {
635 return; 809 return;
636 } 810 }
637 811
638 for (int i = 0; i < instanceCount; i++) { 812 for (int i = 0; i < instanceCount; i++) {
639 const Geometry& geom = fGeoData[i]; 813 const Geometry& geom = fGeoData[i];
640 814
641 GrColor color = geom.fColor; 815 GrColor color = geom.fColor;
642 SkScalar innerRadius = geom.fInnerRadius; 816 SkScalar innerRadius = geom.fInnerRadius;
643 SkScalar outerRadius = geom.fOuterRadius; 817 SkScalar outerRadius = geom.fOuterRadius;
644 818
645 const SkRect& bounds = geom.fDevBounds; 819 const SkRect& bounds = geom.fDevBounds;
820 CircleVertex* v0 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 0)*vertexStride);
821 CircleVertex* v1 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 1)*vertexStride);
822 CircleVertex* v2 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 2)*vertexStride);
823 CircleVertex* v3 = reinterpret_cast<CircleVertex*>(vertices + (4 * i + 3)*vertexStride);
646 824
647 // The inner radius in the vertex data must be specified in normaliz ed space. 825 // The inner radius in the vertex data must be specified in normaliz ed space.
648 innerRadius = innerRadius / outerRadius; 826 innerRadius = innerRadius / outerRadius;
649 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 827 v0->fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
650 verts[0].fColor = color; 828 v0->fColor = color;
651 verts[0].fOffset = SkPoint::Make(-1, -1); 829 v0->fOffset = SkPoint::Make(-1, -1);
652 verts[0].fOuterRadius = outerRadius; 830 v0->fOuterRadius = outerRadius;
653 verts[0].fInnerRadius = innerRadius; 831 v0->fInnerRadius = innerRadius;
654 832
655 verts[1].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 833 v1->fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
656 verts[1].fColor = color; 834 v1->fColor = color;
657 verts[1].fOffset = SkPoint::Make(-1, 1); 835 v1->fOffset = SkPoint::Make(-1, 1);
658 verts[1].fOuterRadius = outerRadius; 836 v1->fOuterRadius = outerRadius;
659 verts[1].fInnerRadius = innerRadius; 837 v1->fInnerRadius = innerRadius;
660 838
661 verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 839 v2->fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
662 verts[2].fColor = color; 840 v2->fColor = color;
663 verts[2].fOffset = SkPoint::Make(1, 1); 841 v2->fOffset = SkPoint::Make(1, 1);
664 verts[2].fOuterRadius = outerRadius; 842 v2->fOuterRadius = outerRadius;
665 verts[2].fInnerRadius = innerRadius; 843 v2->fInnerRadius = innerRadius;
666 844
667 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 845 v3->fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
668 verts[3].fColor = color; 846 v3->fColor = color;
669 verts[3].fOffset = SkPoint::Make(1, -1); 847 v3->fOffset = SkPoint::Make(1, -1);
670 verts[3].fOuterRadius = outerRadius; 848 v3->fOuterRadius = outerRadius;
671 verts[3].fInnerRadius = innerRadius; 849 v3->fInnerRadius = innerRadius;
672 850
673 verts += kVerticesPerQuad; 851 if (fClipPlane) {
852 memcpy(v0->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
853 memcpy(v1->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
854 memcpy(v2->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
855 memcpy(v3->fHalfPlanes[0], geom.fClipPlane, 3 * sizeof(SkScalar) );
856 }
857 int unionIdx = 1;
858 if (fClipPlaneIsect) {
859 memcpy(v0->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
860 memcpy(v1->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
861 memcpy(v2->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
862 memcpy(v3->fHalfPlanes[1], geom.fIsectPlane, 3 * sizeof(SkScalar ));
863 unionIdx = 2;
864 }
865 if (fClipPlaneUnion) {
866 memcpy(v0->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
867 memcpy(v1->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
868 memcpy(v2->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
869 memcpy(v3->fHalfPlanes[unionIdx], geom.fUnionPlane, 3 * sizeof(S kScalar));
870 }
674 } 871 }
675 helper.recordDraw(target, gp); 872 helper.recordDraw(target, gp);
676 } 873 }
677 874
678 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { 875 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
679 CircleBatch* that = t->cast<CircleBatch>(); 876 CircleBatch* that = t->cast<CircleBatch>();
680 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 877 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
681 that->bounds(), caps)) { 878 that->bounds(), caps)) {
682 return false; 879 return false;
683 } 880 }
684 881
685 if (this->fStroked != that->fStroked) { 882 if (this->fStroked != that->fStroked) {
686 return false; 883 return false;
687 } 884 }
688 885
886 // Because we've set up the batches that don't use the planes with noop values
887 // we can just accumulate used planes by later batches.
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 - .01f;
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') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698