OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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(¢er, 1); | 607 viewMatrix.mapPoints(¢er, 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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |