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