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

Side by Side Diff: src/gpu/effects/GrDashingEffect.cpp

Issue 892203003: Dash using vertex attributes for interval and stroke width (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: cleanup Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 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 "GrDashingEffect.h" 8 #include "GrDashingEffect.h"
9 9
10 #include "../GrAARectRenderer.h" 10 #include "../GrAARectRenderer.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 return false; 60 return false;
61 } 61 }
62 62
63 return true; 63 return true;
64 } 64 }
65 65
66 namespace { 66 namespace {
67 struct DashLineVertex { 67 struct DashLineVertex {
68 SkPoint fPos; 68 SkPoint fPos;
69 SkPoint fDashPos; 69 SkPoint fDashPos;
70 SkScalar fIntervalLength;
71 SkRect fRect;
72 };
73 struct DashCircleVertex {
74 SkPoint fPos;
75 SkPoint fDashPos;
76 SkScalar fRadius;
77 SkScalar fCenterX;
78 SkScalar fIntervalLength;
egdaniel 2015/02/03 14:45:59 move fIntervalLength before radius and center to m
70 }; 79 };
71 }; 80 };
72 81
73 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, 82 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale,
74 const SkMatrix& viewMatrix, const SkPoint pts[2]) { 83 const SkMatrix& viewMatrix, const SkPoint pts[2]) {
75 SkVector vecSrc = pts[1] - pts[0]; 84 SkVector vecSrc = pts[1] - pts[0];
76 SkScalar magSrc = vecSrc.length(); 85 SkScalar magSrc = vecSrc.length();
77 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; 86 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0;
78 vecSrc.scale(invSrc); 87 vecSrc.scale(invSrc);
79 88
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 140 }
132 if (*endingInt > info.fIntervals[0]) { 141 if (*endingInt > info.fIntervals[0]) {
133 if (0 == info.fIntervals[0]) { 142 if (0 == info.fIntervals[0]) {
134 *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps) 143 *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps)
135 } 144 }
136 return *endingInt - info.fIntervals[0]; 145 return *endingInt - info.fIntervals[0];
137 } 146 }
138 return 0; 147 return 0;
139 } 148 }
140 149
141 static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx , const SkMatrix& matrix, 150 enum DashCap {
142 SkScalar offset, SkScalar bloat, SkScalar len, SkScalar s troke) { 151 kRound_DashCap,
143 SkScalar startDashX = offset - bloat; 152 kNonRound_DashCap,
144 SkScalar endDashX = offset + len + bloat; 153 };
145 SkScalar startDashY = -stroke - bloat; 154
146 SkScalar endDashY = stroke + bloat; 155 template <typename T>
147 verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY); 156 void setup_dashed_rect_common(const SkRect& rect, const SkMatrix& matrix, T* ver tices, int idx,
148 verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); 157 SkScalar offset, SkScalar bloat, SkScalar len, SkS calar stroke) {
149 verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); 158 SkScalar startDashX = offset - bloat;
150 verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); 159 SkScalar endDashX = offset + len + bloat;
151 verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); 160 SkScalar startDashY = -stroke - bloat;
152 verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); 161 SkScalar endDashY = stroke + bloat;
153 verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); 162 vertices[idx].fDashPos = SkPoint::Make(startDashX , startDashY);
154 verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); 163 vertices[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY);
155 matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4); 164 vertices[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY);
165 vertices[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY);
166
167 vertices[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop);
168 vertices[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom);
169 vertices[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom);
170 vertices[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop);
171
172 matrix.mapPointsWithStride(&vertices[idx].fPos, sizeof(T), 4);
173 }
174
175 static void setup_dashed_rect(const SkRect& rect, void* vertices, int idx,
176 const SkMatrix& matrix, SkScalar offset, SkScalar bloat,
177 SkScalar len, SkScalar stroke, SkScalar startInter val,
178 SkScalar endInterval, SkScalar strokeWidth, DashCa p cap,
179 const size_t vertexStride) {
180 SkScalar intervalLength = startInterval + endInterval;
181
182 if (kRound_DashCap == cap) {
183 SkASSERT(vertexStride == sizeof(DashCircleVertex));
184 DashCircleVertex* verts = reinterpret_cast<DashCircleVertex*>(vertices);
185
186 setup_dashed_rect_common<DashCircleVertex>(rect, matrix, verts, idx, off set, bloat, len,
187 stroke);
188
189 SkScalar radius = SkScalarHalf(strokeWidth) - 0.5f;
190 SkScalar centerX = SkScalarHalf(endInterval);
191 verts[idx].fIntervalLength = intervalLength;
192 verts[idx].fRadius = radius;
193 verts[idx].fCenterX = centerX;
194 verts[idx + 1].fRadius = radius;
bsalomon 2015/02/03 01:02:01 nit, optional.. prolly fewer lines to write this a
195 verts[idx + 1].fCenterX = centerX;
196 verts[idx + 1].fIntervalLength = intervalLength;
197 verts[idx + 2].fRadius = radius;
198 verts[idx + 2].fCenterX = centerX;
199 verts[idx + 2].fIntervalLength = intervalLength;
200 verts[idx + 3].fRadius = radius;
201 verts[idx + 3].fCenterX = centerX;
202 verts[idx + 3].fIntervalLength = intervalLength;
203
204 } else {
205 SkASSERT(kNonRound_DashCap == cap && vertexStride == sizeof(DashLineVert ex));
egdaniel 2015/02/03 14:45:59 is the NonRound assert really needed since we alre
206 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(vertices);
207
208 setup_dashed_rect_common<DashLineVertex>(rect, matrix, verts, idx, offse t, bloat, len,
209 stroke);
210
211 SkScalar halfOffLen = SkScalarHalf(endInterval);
212 SkScalar halfStroke = SkScalarHalf(strokeWidth);
213 verts[idx].fIntervalLength = intervalLength;
214 verts[idx].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f,
egdaniel 2015/02/03 14:45:59 as with Brians comment, probably can loop this. Al
215 halfOffLen + startInterval - 0.5f, halfStroke - 0.5 f);
216 verts[idx + 1].fIntervalLength = intervalLength;
217 verts[idx + 1].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f,
218 halfOffLen + startInterval - 0.5f, halfStroke - 0.5f);
219 verts[idx + 2].fIntervalLength = intervalLength;
220 verts[idx + 2].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f,
221 halfOffLen + startInterval - 0.5f, halfStroke - 0.5f);
222 verts[idx + 3].fIntervalLength = intervalLength;
223 verts[idx + 3].fRect.set(halfOffLen + 0.5f, -halfStroke + 0.5f,
224 halfOffLen + startInterval - 0.5f, halfStroke - 0.5f);
225 }
156 } 226 }
157 227
158 static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& m atrix, 228 static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& m atrix,
159 SkPoint* verts) { 229 SkPoint* verts) {
160 verts[idx] = SkPoint::Make(rect.fLeft, rect.fTop); 230 verts[idx] = SkPoint::Make(rect.fLeft, rect.fTop);
161 verts[idx + 1] = SkPoint::Make(rect.fLeft, rect.fBottom); 231 verts[idx + 1] = SkPoint::Make(rect.fLeft, rect.fBottom);
162 verts[idx + 2] = SkPoint::Make(rect.fRight, rect.fBottom); 232 verts[idx + 2] = SkPoint::Make(rect.fRight, rect.fBottom);
163 verts[idx + 3] = SkPoint::Make(rect.fRight, rect.fTop); 233 verts[idx + 3] = SkPoint::Make(rect.fRight, rect.fTop);
164 matrix.mapPoints(&verts[idx], 4); 234 matrix.mapPoints(&verts[idx], 4);
165 } 235 }
166 236
237
238 /**
239 * An GrGeometryProcessor that renders a dashed line.
240 * This GrGeometryProcessor is meant for dashed lines that only have a single on /off interval pair.
241 * Bounding geometry is rendered and the effect computes coverage based on the f ragment's
242 * position relative to the dashed line.
243 */
244 static GrGeometryProcessor* create_dash_gp(GrColor,
245 GrPrimitiveEdgeType edgeType,
246 DashCap cap,
247 const SkMatrix& localMatrix);
248
167 bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, 249 bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
168 GrPipelineBuilder* pipelineBuilder, GrColor c olor, 250 GrPipelineBuilder* pipelineBuilder, GrColor c olor,
169 const SkMatrix& viewMatrix, const SkPoint pts [2], 251 const SkMatrix& viewMatrix, const SkPoint pts [2],
170 const GrPaint& paint, const GrStrokeInfo& str okeInfo) { 252 const GrPaint& paint, const GrStrokeInfo& str okeInfo) {
171 if (!can_fast_path_dash(pts, strokeInfo, *target, *pipelineBuilder, viewMatr ix)) { 253 if (!can_fast_path_dash(pts, strokeInfo, *target, *pipelineBuilder, viewMatr ix)) {
172 return false; 254 return false;
173 } 255 }
174 256
175 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); 257 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
176 258
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 devIntervals[0] = lineLength; 417 devIntervals[0] = lineLength;
336 } 418 }
337 419
338 // reset to device coordinates 420 // reset to device coordinates
339 SkMatrix invert; 421 SkMatrix invert;
340 if (!viewMatrix.invert(&invert)) { 422 if (!viewMatrix.invert(&invert)) {
341 SkDebugf("Failed to invert\n"); 423 SkDebugf("Failed to invert\n");
342 return false; 424 return false;
343 } 425 }
344 426
427 bool isRoundCap = SkPaint::kRound_Cap == cap;
428 DashCap capType = isRoundCap ? kRound_DashCap : kNonRound_DashCap;
429
345 SkAutoTUnref<const GrGeometryProcessor> gp; 430 SkAutoTUnref<const GrGeometryProcessor> gp;
346 bool fullDash = devIntervals[1] > 0.f || useAA; 431 bool fullDash = devIntervals[1] > 0.f || useAA;
347 if (fullDash) { 432 if (fullDash) {
348 SkPathEffect::DashInfo devInfo; 433 SkPathEffect::DashInfo devInfo;
349 devInfo.fPhase = devPhase; 434 devInfo.fPhase = devPhase;
350 devInfo.fCount = 2; 435 devInfo.fCount = 2;
351 devInfo.fIntervals = devIntervals; 436 devInfo.fIntervals = devIntervals;
352 GrPrimitiveEdgeType edgeType= useAA ? kFillAA_GrProcessorEdgeType : 437 GrPrimitiveEdgeType edgeType = useAA ? kFillAA_GrProcessorEdgeType :
353 kFillBW_GrProcessorEdgeType; 438 kFillBW_GrProcessorEdgeType;
354 bool isRoundCap = SkPaint::kRound_Cap == cap; 439 gp.reset(create_dash_gp(color, edgeType, capType, invert));
355 GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_ DashCap :
356 GrDashingEffect::kNonRou nd_DashCap;
357 gp.reset(GrDashingEffect::Create(color, edgeType, devInfo, strokeWidth, capType, invert));
358 } else { 440 } else {
359 // Set up the vertex data for the line and start/end dashes 441 // Set up the vertex data for the line and start/end dashes
360 gp.reset(GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosit ion_GPType, 442 gp.reset(GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosit ion_GPType,
361 color, 443 color,
362 SkMatrix::I(), 444 SkMatrix::I(),
363 invert)); 445 invert));
364 } 446 }
365 447
366 int totalRectCnt = 0; 448 int totalRectCnt = 0;
367 449
(...skipping 22 matching lines...) Expand all
390 viewMatrix.mapPoints(devicePts, ptsRot, 2); 472 viewMatrix.mapPoints(devicePts, ptsRot, 2);
391 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); 473 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
392 if (hasCap) { 474 if (hasCap) {
393 lineLength += 2.f * halfDevStroke; 475 lineLength += 2.f * halfDevStroke;
394 } 476 }
395 477
396 SkRect bounds; 478 SkRect bounds;
397 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); 479 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY);
398 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); 480 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke);
399 if (fullDash) { 481 if (fullDash) {
400 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic es()); 482 setup_dashed_rect(bounds, geo.vertices(), curVIdx, combinedMatrix, s tartOffset,
401 SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); 483 devBloat, lineLength, halfDevStroke, devIntervals[ 0], devIntervals[1],
402 setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffse t, devBloat, 484 strokeWidth, capType, gp->getVertexStride());
403 lineLength, halfDevStroke);
404 } else { 485 } else {
405 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); 486 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices());
406 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); 487 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
407 setup_dashed_rect_pos(bounds, curVIdx, combinedMatrix, verts); 488 setup_dashed_rect_pos(bounds, curVIdx, combinedMatrix, verts);
408 } 489 }
409 curVIdx += 4; 490 curVIdx += 4;
410 } 491 }
411 492
412 if (hasStartRect) { 493 if (hasStartRect) {
413 SkASSERT(useAA); // so that we know bloatX and bloatY have been set 494 SkASSERT(useAA); // so that we know bloatX and bloatY have been set
414 startRect.outset(bloatX, bloatY); 495 startRect.outset(bloatX, bloatY);
415 if (fullDash) { 496 if (fullDash) {
416 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic es()); 497 setup_dashed_rect(startRect, geo.vertices(), curVIdx, combinedMatrix , startOffset,
417 SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); 498 devBloat, devIntervals[0], halfDevStroke, devInter vals[0],
418 setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOf fset, devBloat, 499 devIntervals[1], strokeWidth, capType, gp->getVert exStride());
419 devIntervals[0], halfDevStroke);
420 } else { 500 } else {
421 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); 501 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices());
422 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); 502 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
423 setup_dashed_rect_pos(startRect, curVIdx, combinedMatrix, verts); 503 setup_dashed_rect_pos(startRect, curVIdx, combinedMatrix, verts);
424 } 504 }
425 505
426 curVIdx += 4; 506 curVIdx += 4;
427 } 507 }
428 508
429 if (hasEndRect) { 509 if (hasEndRect) {
430 SkASSERT(useAA); // so that we know bloatX and bloatY have been set 510 SkASSERT(useAA); // so that we know bloatX and bloatY have been set
431 endRect.outset(bloatX, bloatY); 511 endRect.outset(bloatX, bloatY);
432 if (fullDash) { 512 if (fullDash) {
433 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic es()); 513 setup_dashed_rect(endRect, geo.vertices(), curVIdx, combinedMatrix, startOffset,
434 SkASSERT(gp->getVertexStride() == sizeof(DashLineVertex)); 514 devBloat, devIntervals[0], halfDevStroke, devInter vals[0],
435 setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffs et, devBloat, 515 devIntervals[1], strokeWidth, capType, gp->getVert exStride());
436 devIntervals[0], halfDevStroke);
437 } else { 516 } else {
438 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); 517 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices());
439 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); 518 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
440 setup_dashed_rect_pos(endRect, curVIdx, combinedMatrix, verts); 519 setup_dashed_rect_pos(endRect, curVIdx, combinedMatrix, verts);
441 } 520 }
442 521
443 } 522 }
444 523
445 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); 524 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
446 target->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType , 525 target->drawIndexedInstances(pipelineBuilder, gp, kTriangles_GrPrimitiveType ,
(...skipping 20 matching lines...) Expand all
467 * "dash position" of each vertex. In other words it is the vertex coords (in de vice space) if we 546 * "dash position" of each vertex. In other words it is the vertex coords (in de vice space) if we
468 * transform the line to be horizontal, with the start of line at the origin the n shifted to the 547 * transform the line to be horizontal, with the start of line at the origin the n shifted to the
469 * right by half the off interval. The line then goes in the positive x directio n. 548 * right by half the off interval. The line then goes in the positive x directio n.
470 */ 549 */
471 class DashingCircleEffect : public GrGeometryProcessor { 550 class DashingCircleEffect : public GrGeometryProcessor {
472 public: 551 public:
473 typedef SkPathEffect::DashInfo DashInfo; 552 typedef SkPathEffect::DashInfo DashInfo;
474 553
475 static GrGeometryProcessor* Create(GrColor, 554 static GrGeometryProcessor* Create(GrColor,
476 GrPrimitiveEdgeType edgeType, 555 GrPrimitiveEdgeType edgeType,
477 const DashInfo& info,
478 SkScalar radius,
479 const SkMatrix& localMatrix); 556 const SkMatrix& localMatrix);
480 557
481 virtual ~DashingCircleEffect(); 558 virtual ~DashingCircleEffect();
482 559
483 const char* name() const SK_OVERRIDE { return "DashingCircleEffect"; } 560 const char* name() const SK_OVERRIDE { return "DashingCircleEffect"; }
484 561
485 const Attribute* inPosition() const { return fInPosition; } 562 const Attribute* inPosition() const { return fInPosition; }
486 563
487 const Attribute* inCoord() const { return fInCoord; } 564 const Attribute* inCoord() const { return fInCoord; }
488 565
566 const Attribute* inParams() const { return fInParams; }
567
489 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } 568 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
490 569
491 SkScalar getRadius() const { return fRadius; }
492
493 SkScalar getCenterX() const { return fCenterX; }
494
495 SkScalar getIntervalLength() const { return fIntervalLength; }
496
497 virtual void getGLProcessorKey(const GrBatchTracker&, 570 virtual void getGLProcessorKey(const GrBatchTracker&,
498 const GrGLCaps&, 571 const GrGLCaps&,
499 GrProcessorKeyBuilder* b) const SK_OVERRIDE; 572 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
500 573
501 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker&, 574 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker&,
502 const GrGLCaps&) const SK_O VERRIDE; 575 const GrGLCaps&) const SK_O VERRIDE;
503 576
504 void initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const SK_OVERRIDE; 577 void initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const SK_OVERRIDE;
505 578
506 bool onCanMakeEqual(const GrBatchTracker&, 579 bool onCanMakeEqual(const GrBatchTracker&,
507 const GrGeometryProcessor&, 580 const GrGeometryProcessor&,
508 const GrBatchTracker&) const SK_OVERRIDE; 581 const GrBatchTracker&) const SK_OVERRIDE;
509 582
510 private: 583 private:
511 DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& i nfo, 584 DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const SkMatrix& l ocalMatrix);
512 SkScalar radius, const SkMatrix& localMatrix);
513 585
514 bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE; 586 bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
515 587
516 void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE; 588 void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE;
517 589
518 GrPrimitiveEdgeType fEdgeType; 590 GrPrimitiveEdgeType fEdgeType;
519 const Attribute* fInPosition; 591 const Attribute* fInPosition;
520 const Attribute* fInCoord; 592 const Attribute* fInCoord;
521 SkScalar fIntervalLength; 593 const Attribute* fInParams;
522 SkScalar fRadius;
523 SkScalar fCenterX;
524 594
525 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 595 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
526 596
527 typedef GrGeometryProcessor INHERITED; 597 typedef GrGeometryProcessor INHERITED;
528 }; 598 };
529 599
530 ////////////////////////////////////////////////////////////////////////////// 600 //////////////////////////////////////////////////////////////////////////////
531 601
532 class GLDashingCircleEffect : public GrGLGeometryProcessor { 602 class GLDashingCircleEffect : public GrGLGeometryProcessor {
533 public: 603 public:
(...skipping 25 matching lines...) Expand all
559 fColor = GrColor_ILLEGAL; 629 fColor = GrColor_ILLEGAL;
560 fPrevRadius = SK_ScalarMin; 630 fPrevRadius = SK_ScalarMin;
561 fPrevCenterX = SK_ScalarMin; 631 fPrevCenterX = SK_ScalarMin;
562 fPrevIntervalLength = SK_ScalarMax; 632 fPrevIntervalLength = SK_ScalarMax;
563 } 633 }
564 634
565 void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 635 void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
566 const DashingCircleEffect& dce = args.fGP.cast<DashingCircleEffect>(); 636 const DashingCircleEffect& dce = args.fGP.cast<DashingCircleEffect>();
567 const DashingCircleBatchTracker local = args.fBT.cast<DashingCircleBatchTrac ker>(); 637 const DashingCircleBatchTracker local = args.fBT.cast<DashingCircleBatchTrac ker>();
568 GrGLGPBuilder* pb = args.fPB; 638 GrGLGPBuilder* pb = args.fPB;
569 const char *paramName;
570 // The param uniforms, xyz, refer to circle radius - 0.5, cicles center x co ord, and
571 // the total interval length of the dash.
572 fParamUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibilit y,
573 kVec3f_GrSLType, kDefault_GrSLPrecision ,
574 "params", &paramName);
575
576 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 639 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
577 640
578 // emit attributes 641 // emit attributes
579 vsBuilder->emitAttributes(dce); 642 vsBuilder->emitAttributes(dce);
580 643
581 GrGLVertToFrag v(kVec2f_GrSLType); 644 GrGLVertToFrag coord(kVec2f_GrSLType);
582 args.fPB->addVarying("Coord", &v); 645 args.fPB->addVarying("Coord", &coord);
583 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dce.inCoord()->fName); 646 vsBuilder->codeAppendf("%s = %s;", coord.vsOut(), dce.inCoord()->fName);
647
648 // The param attribute, xyz, refer to circle radius - 0.5, cicles center x c oord, and
egdaniel 2015/02/03 14:45:59 Lets move the interval length to the second parame
649 // the total interval length of the dash.
650 GrGLVertToFrag params(kVec3f_GrSLType);
651 args.fPB->addVarying("Params", &params);
652 vsBuilder->codeAppendf("%s = %s;", params.vsOut(), dce.inParams()->fName);
584 653
585 // Setup pass through color 654 // Setup pass through color
586 this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NU LL, &fColorUniform); 655 this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NU LL, &fColorUniform);
587 656
588 // setup uniform viewMatrix 657 // setup uniform viewMatrix
589 this->addUniformViewMatrix(pb); 658 this->addUniformViewMatrix(pb);
590 659
591 // Setup position 660 // Setup position
592 SetupPosition(vsBuilder, gpArgs, dce.inPosition()->fName, dce.viewMatrix(), this->uViewM()); 661 SetupPosition(vsBuilder, gpArgs, dce.inPosition()->fName, dce.viewMatrix(), this->uViewM());
593 662
594 // emit transforms 663 // emit transforms
595 this->emitTransforms(args.fPB, gpArgs->fPositionVar, dce.inPosition()->fName , dce.localMatrix(), 664 this->emitTransforms(args.fPB, gpArgs->fPositionVar, dce.inPosition()->fName , dce.localMatrix(),
596 args.fTransformsIn, args.fTransformsOut); 665 args.fTransformsIn, args.fTransformsOut);
597 666
598 // transforms all points so that we can compare them to our test circle 667 // transforms all points so that we can compare them to our test circle
599 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 668 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
600 fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s. z;\n", 669 fsBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
601 v.fsIn(), v.fsIn(), paramName, paramName); 670 coord.fsIn(), coord.fsIn(), params.fsIn(), params.fsI n());
602 fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", v.fsIn()); 671 fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", coord. fsIn());
603 fsBuilder->codeAppendf("\t\tvec2 center = vec2(%s.y, 0.0);\n", paramName); 672 fsBuilder->codeAppendf("vec2 center = vec2(%s.y, 0.0);", params.fsIn());
604 fsBuilder->codeAppend("\t\tfloat dist = length(center - fragPosShifted);\n") ; 673 fsBuilder->codeAppend("float dist = length(center - fragPosShifted);");
605 if (GrProcessorEdgeTypeIsAA(dce.getEdgeType())) { 674 if (GrProcessorEdgeTypeIsAA(dce.getEdgeType())) {
606 fsBuilder->codeAppendf("\t\tfloat diff = dist - %s.x;\n", paramName); 675 fsBuilder->codeAppendf("float diff = dist - %s.x;", params.fsIn());
607 fsBuilder->codeAppend("\t\tdiff = 1.0 - diff;\n"); 676 fsBuilder->codeAppend("diff = 1.0 - diff;");
608 fsBuilder->codeAppend("\t\tfloat alpha = clamp(diff, 0.0, 1.0);\n"); 677 fsBuilder->codeAppend("float alpha = clamp(diff, 0.0, 1.0);");
609 } else { 678 } else {
610 fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); 679 fsBuilder->codeAppendf("float alpha = 1.0;");
611 fsBuilder->codeAppendf("\t\talpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;\n", paramName); 680 fsBuilder->codeAppendf("alpha *= dist < %s.x + 0.5 ? 1.0 : 0.0;", param s.fsIn());
612 } 681 }
613 fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); 682 fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
614 } 683 }
615 684
616 void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman, 685 void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman,
617 const GrPrimitiveProcessor& processor, 686 const GrPrimitiveProcessor& processor,
618 const GrBatchTracker& bt) { 687 const GrBatchTracker& bt) {
619 this->setUniformViewMatrix(pdman, processor.viewMatrix()); 688 this->setUniformViewMatrix(pdman, processor.viewMatrix());
620 689
621 const DashingCircleEffect& dce = processor.cast<DashingCircleEffect>();
622 SkScalar radius = dce.getRadius();
623 SkScalar centerX = dce.getCenterX();
624 SkScalar intervalLength = dce.getIntervalLength();
625 if (radius != fPrevRadius || centerX != fPrevCenterX || intervalLength != fP revIntervalLength) {
626 pdman.set3f(fParamUniform, radius - 0.5f, centerX, intervalLength);
627 fPrevRadius = radius;
628 fPrevCenterX = centerX;
629 fPrevIntervalLength = intervalLength;
630 }
631
632 const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>( ); 690 const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>( );
633 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 691 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
634 GrGLfloat c[4]; 692 GrGLfloat c[4];
635 GrColorToRGBAFloat(local.fColor, c); 693 GrColorToRGBAFloat(local.fColor, c);
636 pdman.set4fv(fColorUniform, 1, c); 694 pdman.set4fv(fColorUniform, 1, c);
637 fColor = local.fColor; 695 fColor = local.fColor;
638 } 696 }
639 } 697 }
640 698
641 void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp, 699 void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
642 const GrBatchTracker& bt, 700 const GrBatchTracker& bt,
643 const GrGLCaps&, 701 const GrGLCaps&,
644 GrProcessorKeyBuilder* b) { 702 GrProcessorKeyBuilder* b) {
645 const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>( ); 703 const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>( );
646 const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>(); 704 const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>();
647 uint32_t key = 0; 705 uint32_t key = 0;
648 key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 : 0 x0; 706 key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 : 0 x0;
649 key |= ComputePosKey(gp.viewMatrix()) << 1; 707 key |= ComputePosKey(gp.viewMatrix()) << 1;
650 key |= dce.getEdgeType() << 8; 708 key |= dce.getEdgeType() << 8;
651 b->add32(key << 16 | local.fInputColorType); 709 b->add32(key << 16 | local.fInputColorType);
652 } 710 }
653 711
654 ////////////////////////////////////////////////////////////////////////////// 712 //////////////////////////////////////////////////////////////////////////////
655 713
656 GrGeometryProcessor* DashingCircleEffect::Create(GrColor color, 714 GrGeometryProcessor* DashingCircleEffect::Create(GrColor color,
657 GrPrimitiveEdgeType edgeType, 715 GrPrimitiveEdgeType edgeType,
658 const DashInfo& info,
659 SkScalar radius,
660 const SkMatrix& localMatrix) { 716 const SkMatrix& localMatrix) {
661 if (info.fCount != 2 || info.fIntervals[0] != 0) { 717 return SkNEW_ARGS(DashingCircleEffect, (color, edgeType, localMatrix));
662 return NULL;
663 }
664
665 return SkNEW_ARGS(DashingCircleEffect, (color, edgeType, info, radius, local Matrix));
666 } 718 }
667 719
668 DashingCircleEffect::~DashingCircleEffect() {} 720 DashingCircleEffect::~DashingCircleEffect() {}
669 721
670 void DashingCircleEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* ou t) const { 722 void DashingCircleEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* ou t) const {
671 out->setUnknownSingleComponent(); 723 out->setUnknownSingleComponent();
672 } 724 }
673 725
674 void DashingCircleEffect::getGLProcessorKey(const GrBatchTracker& bt, 726 void DashingCircleEffect::getGLProcessorKey(const GrBatchTracker& bt,
675 const GrGLCaps& caps, 727 const GrGLCaps& caps,
676 GrProcessorKeyBuilder* b) const { 728 GrProcessorKeyBuilder* b) const {
677 GLDashingCircleEffect::GenKey(*this, bt, caps, b); 729 GLDashingCircleEffect::GenKey(*this, bt, caps, b);
678 } 730 }
679 731
680 GrGLPrimitiveProcessor* DashingCircleEffect::createGLInstance(const GrBatchTrack er& bt, 732 GrGLPrimitiveProcessor* DashingCircleEffect::createGLInstance(const GrBatchTrack er& bt,
681 const GrGLCaps&) c onst { 733 const GrGLCaps&) c onst {
682 return SkNEW_ARGS(GLDashingCircleEffect, (*this, bt)); 734 return SkNEW_ARGS(GLDashingCircleEffect, (*this, bt));
683 } 735 }
684 736
685 DashingCircleEffect::DashingCircleEffect(GrColor color, 737 DashingCircleEffect::DashingCircleEffect(GrColor color,
686 GrPrimitiveEdgeType edgeType, 738 GrPrimitiveEdgeType edgeType,
687 const DashInfo& info,
688 SkScalar radius,
689 const SkMatrix& localMatrix) 739 const SkMatrix& localMatrix)
690 : INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) { 740 : INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) {
691 this->initClassID<DashingCircleEffect>(); 741 this->initClassID<DashingCircleEffect>();
692 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertex AttribType)); 742 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertex AttribType));
693 fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec2f_GrVertexAttrib Type)); 743 fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec2f_GrVertexAttrib Type));
694 SkScalar onLen = info.fIntervals[0]; 744 fInParams = &this->addVertexAttrib(Attribute("inParams", kVec3f_GrVertexAttr ibType));
695 SkScalar offLen = info.fIntervals[1];
696 fIntervalLength = onLen + offLen;
697 fRadius = radius;
698 fCenterX = SkScalarHalf(offLen);
699 } 745 }
700 746
701 bool DashingCircleEffect::onIsEqual(const GrGeometryProcessor& other) const { 747 bool DashingCircleEffect::onIsEqual(const GrGeometryProcessor& other) const {
702 const DashingCircleEffect& dce = other.cast<DashingCircleEffect>(); 748 const DashingCircleEffect& dce = other.cast<DashingCircleEffect>();
703 return (fEdgeType == dce.fEdgeType && 749 return fEdgeType == dce.fEdgeType;
704 fIntervalLength == dce.fIntervalLength &&
705 fRadius == dce.fRadius &&
706 fCenterX == dce.fCenterX);
707 } 750 }
708 751
709 void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineI nfo& init) const { 752 void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineI nfo& init) const {
710 DashingCircleBatchTracker* local = bt->cast<DashingCircleBatchTracker>(); 753 DashingCircleBatchTracker* local = bt->cast<DashingCircleBatchTracker>();
711 local->fInputColorType = GetColorInputType(&local->fColor, this->color(), in it, false); 754 local->fInputColorType = GetColorInputType(&local->fColor, this->color(), in it, false);
712 local->fUsesLocalCoords = init.fUsesLocalCoords; 755 local->fUsesLocalCoords = init.fUsesLocalCoords;
713 } 756 }
714 757
715 bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m, 758 bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m,
716 const GrGeometryProcessor& that, 759 const GrGeometryProcessor& that,
717 const GrBatchTracker& t) const { 760 const GrBatchTracker& t) const {
718 const DashingCircleBatchTracker& mine = m.cast<DashingCircleBatchTracker>(); 761 const DashingCircleBatchTracker& mine = m.cast<DashingCircleBatchTracker>();
719 const DashingCircleBatchTracker& theirs = t.cast<DashingCircleBatchTracker>( ); 762 const DashingCircleBatchTracker& theirs = t.cast<DashingCircleBatchTracker>( );
720 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, 763 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
721 that, theirs.fUsesLocalCoords) && 764 that, theirs.fUsesLocalCoords) &&
722 CanCombineOutput(mine.fInputColorType, mine.fColor, 765 CanCombineOutput(mine.fInputColorType, mine.fColor,
723 theirs.fInputColorType, theirs.fColor); 766 theirs.fInputColorType, theirs.fColor);
724 } 767 }
725 768
726 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect); 769 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect);
727 770
728 GrGeometryProcessor* DashingCircleEffect::TestCreate(SkRandom* random, 771 GrGeometryProcessor* DashingCircleEffect::TestCreate(SkRandom* random,
729 GrContext*, 772 GrContext*,
730 const GrDrawTargetCaps& cap s, 773 const GrDrawTargetCaps& cap s,
731 GrTexture*[]) { 774 GrTexture*[]) {
732 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->next ULessThan( 775 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->next ULessThan(
733 kGrProcessorEdgeTypeCnt)); 776 kGrProcessorEdgeTypeCnt));
734 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f);
735 DashInfo info;
736 info.fCount = 2;
737 SkAutoTArray<SkScalar> intervals(info.fCount);
738 info.fIntervals = intervals.get();
739 info.fIntervals[0] = 0;
740 info.fIntervals[1] = random->nextRangeScalar(0, 10.f);
741 info.fPhase = random->nextRangeScalar(0, info.fIntervals[1]);
742
743 return DashingCircleEffect::Create(GrRandomColor(random), 777 return DashingCircleEffect::Create(GrRandomColor(random),
744 edgeType, info, strokeWidth, 778 edgeType, GrProcessorUnitTest::TestMatrix (random));
745 GrProcessorUnitTest::TestMatrix(random));
746 } 779 }
747 780
748 ////////////////////////////////////////////////////////////////////////////// 781 //////////////////////////////////////////////////////////////////////////////
749 782
750 class GLDashingLineEffect; 783 class GLDashingLineEffect;
751 784
752 struct DashingLineBatchTracker { 785 struct DashingLineBatchTracker {
753 GrGPInput fInputColorType; 786 GrGPInput fInputColorType;
754 GrColor fColor; 787 GrColor fColor;
755 bool fUsesLocalCoords; 788 bool fUsesLocalCoords;
756 }; 789 };
757 790
758 /* 791 /*
759 * This effect will draw a dashed line. The width of the dash is given by the st rokeWidth and the 792 * This effect will draw a dashed line. The width of the dash is given by the st rokeWidth and the
760 * length and spacing by the DashInfo. Both of the previous two parameters are i n device space. 793 * length and spacing by the DashInfo. Both of the previous two parameters are i n device space.
761 * This effect also requires the setting of a vec2 vertex attribute for the the four corners of the 794 * This effect also requires the setting of a vec2 vertex attribute for the the four corners of the
762 * bounding rect. This attribute is the "dash position" of each vertex. In other words it is the 795 * bounding rect. This attribute is the "dash position" of each vertex. In other words it is the
763 * vertex coords (in device space) if we transform the line to be horizontal, wi th the start of 796 * vertex coords (in device space) if we transform the line to be horizontal, wi th the start of
764 * line at the origin then shifted to the right by half the off interval. The li ne then goes in the 797 * line at the origin then shifted to the right by half the off interval. The li ne then goes in the
765 * positive x direction. 798 * positive x direction.
766 */ 799 */
767 class DashingLineEffect : public GrGeometryProcessor { 800 class DashingLineEffect : public GrGeometryProcessor {
768 public: 801 public:
769 typedef SkPathEffect::DashInfo DashInfo; 802 typedef SkPathEffect::DashInfo DashInfo;
770 803
771 static GrGeometryProcessor* Create(GrColor, 804 static GrGeometryProcessor* Create(GrColor,
772 GrPrimitiveEdgeType edgeType, 805 GrPrimitiveEdgeType edgeType,
773 const DashInfo& info,
774 SkScalar strokeWidth,
775 const SkMatrix& localMatrix); 806 const SkMatrix& localMatrix);
776 807
777 virtual ~DashingLineEffect(); 808 virtual ~DashingLineEffect();
778 809
779 const char* name() const SK_OVERRIDE { return "DashingEffect"; } 810 const char* name() const SK_OVERRIDE { return "DashingEffect"; }
780 811
781 const Attribute* inPosition() const { return fInPosition; } 812 const Attribute* inPosition() const { return fInPosition; }
782 813
783 const Attribute* inCoord() const { return fInCoord; } 814 const Attribute* inCoord() const { return fInCoord; }
784 815
816 const Attribute* inRect() const { return fInRect; }
817
785 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; } 818 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
786 819
787 const SkRect& getRect() const { return fRect; }
788
789 SkScalar getIntervalLength() const { return fIntervalLength; }
790
791 virtual void getGLProcessorKey(const GrBatchTracker& bt, 820 virtual void getGLProcessorKey(const GrBatchTracker& bt,
792 const GrGLCaps& caps, 821 const GrGLCaps& caps,
793 GrProcessorKeyBuilder* b) const SK_OVERRIDE; 822 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
794 823
795 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt, 824 virtual GrGLPrimitiveProcessor* createGLInstance(const GrBatchTracker& bt,
796 const GrGLCaps&) const SK_O VERRIDE; 825 const GrGLCaps&) const SK_O VERRIDE;
797 826
798 void initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const SK_OVERRIDE; 827 void initBatchTracker(GrBatchTracker* bt, const GrPipelineInfo& init) const SK_OVERRIDE;
799 828
800 bool onCanMakeEqual(const GrBatchTracker&, 829 bool onCanMakeEqual(const GrBatchTracker&,
801 const GrGeometryProcessor&, 830 const GrGeometryProcessor&,
802 const GrBatchTracker&) const SK_OVERRIDE; 831 const GrBatchTracker&) const SK_OVERRIDE;
803 832
804 private: 833 private:
805 DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& inf o, 834 DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const SkMatrix& loc alMatrix);
806 SkScalar strokeWidth, const SkMatrix& localMatrix);
807 835
808 bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE; 836 bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
809 837
810 void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE; 838 void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const SK_OVERRIDE;
811 839
812 GrPrimitiveEdgeType fEdgeType; 840 GrPrimitiveEdgeType fEdgeType;
813 const Attribute* fInPosition; 841 const Attribute* fInPosition;
814 const Attribute* fInCoord; 842 const Attribute* fInCoord;
815 SkRect fRect; 843 const Attribute* fInRect;
816 SkScalar fIntervalLength;
817 844
818 GR_DECLARE_GEOMETRY_PROCESSOR_TEST; 845 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
819 846
820 typedef GrGeometryProcessor INHERITED; 847 typedef GrGeometryProcessor INHERITED;
821 }; 848 };
822 849
823 ////////////////////////////////////////////////////////////////////////////// 850 //////////////////////////////////////////////////////////////////////////////
824 851
825 class GLDashingLineEffect : public GrGLGeometryProcessor { 852 class GLDashingLineEffect : public GrGLGeometryProcessor {
826 public: 853 public:
827 GLDashingLineEffect(const GrGeometryProcessor&, const GrBatchTracker&); 854 GLDashingLineEffect(const GrGeometryProcessor&, const GrBatchTracker&);
828 855
829 void onEmitCode(EmitArgs&, GrGPArgs*) SK_OVERRIDE; 856 void onEmitCode(EmitArgs&, GrGPArgs*) SK_OVERRIDE;
830 857
831 static inline void GenKey(const GrGeometryProcessor&, 858 static inline void GenKey(const GrGeometryProcessor&,
832 const GrBatchTracker&, 859 const GrBatchTracker&,
833 const GrGLCaps&, 860 const GrGLCaps&,
834 GrProcessorKeyBuilder*); 861 GrProcessorKeyBuilder*);
835 862
836 virtual void setData(const GrGLProgramDataManager&, 863 virtual void setData(const GrGLProgramDataManager&,
837 const GrPrimitiveProcessor&, 864 const GrPrimitiveProcessor&,
838 const GrBatchTracker&) SK_OVERRIDE; 865 const GrBatchTracker&) SK_OVERRIDE;
839 866
840 private: 867 private:
841 GrColor fColor; 868 GrColor fColor;
842 UniformHandle fRectUniform;
843 UniformHandle fIntervalUniform;
844 UniformHandle fColorUniform; 869 UniformHandle fColorUniform;
845 SkRect fPrevRect;
846 SkScalar fPrevIntervalLength;
847 typedef GrGLGeometryProcessor INHERITED; 870 typedef GrGLGeometryProcessor INHERITED;
848 }; 871 };
849 872
850 GLDashingLineEffect::GLDashingLineEffect(const GrGeometryProcessor&, 873 GLDashingLineEffect::GLDashingLineEffect(const GrGeometryProcessor&,
851 const GrBatchTracker&) { 874 const GrBatchTracker&) {
852 fColor = GrColor_ILLEGAL; 875 fColor = GrColor_ILLEGAL;
853 fPrevRect.fLeft = SK_ScalarNaN;
854 fPrevIntervalLength = SK_ScalarMax;
855 } 876 }
856 877
857 void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { 878 void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
858 const DashingLineEffect& de = args.fGP.cast<DashingLineEffect>(); 879 const DashingLineEffect& de = args.fGP.cast<DashingLineEffect>();
859 const DashingLineBatchTracker& local = args.fBT.cast<DashingLineBatchTracker >(); 880 const DashingLineBatchTracker& local = args.fBT.cast<DashingLineBatchTracker >();
860 GrGLGPBuilder* pb = args.fPB; 881 GrGLGPBuilder* pb = args.fPB;
861 const char *rectName;
862 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot tom - 0.5),
863 // respectively.
864 fRectUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility ,
865 kVec4f_GrSLType, kDefault_GrSLPrecision,
866 "rect",
867 &rectName);
868 const char *intervalName;
869 // The interval uniform's refers to the total length of the interval (on + o ff)
870 fIntervalUniform = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibi lity,
871 kFloat_GrSLType, kDefault_GrSLPrecis ion,
872 "interval",
873 &intervalName);
874
875 882
876 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder(); 883 GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
877 884
878 // emit attributes 885 // emit attributes
879 vsBuilder->emitAttributes(de); 886 vsBuilder->emitAttributes(de);
880 887
881 GrGLVertToFrag v(kVec2f_GrSLType); 888 // XY, and Z is interval length
egdaniel 2015/02/03 14:45:59 "XY refer to the transformed dash position, and Z.
882 args.fPB->addVarying("Coord", &v); 889 GrGLVertToFrag inCoord(kVec3f_GrSLType);
883 vsBuilder->codeAppendf("%s = %s;", v.vsOut(), de.inCoord()->fName); 890 args.fPB->addVarying("Coord", &inCoord);
891 vsBuilder->codeAppendf("%s = %s;", inCoord.vsOut(), de.inCoord()->fName);
892
893 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot tom - 0.5),
894 // respectively.
895 GrGLVertToFrag inRect(kVec4f_GrSLType);
896 args.fPB->addVarying("Rect", &inRect);
897 vsBuilder->codeAppendf("%s = %s;", inRect.vsOut(), de.inRect()->fName);
884 898
885 // Setup pass through color 899 // Setup pass through color
886 this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NU LL, &fColorUniform); 900 this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NU LL, &fColorUniform);
887 901
888 // setup uniform viewMatrix 902 // setup uniform viewMatrix
889 this->addUniformViewMatrix(pb); 903 this->addUniformViewMatrix(pb);
890 904
891 // Setup position 905 // Setup position
892 SetupPosition(vsBuilder, gpArgs, de.inPosition()->fName, de.viewMatrix(), th is->uViewM()); 906 SetupPosition(vsBuilder, gpArgs, de.inPosition()->fName, de.viewMatrix(), th is->uViewM());
893 907
894 // emit transforms 908 // emit transforms
895 this->emitTransforms(args.fPB, gpArgs->fPositionVar, de.inPosition()->fName, de.localMatrix(), 909 this->emitTransforms(args.fPB, gpArgs->fPositionVar, de.inPosition()->fName, de.localMatrix(),
896 args.fTransformsIn, args.fTransformsOut); 910 args.fTransformsIn, args.fTransformsOut);
897 911
898 // transforms all points so that we can compare them to our test rect 912 // transforms all points so that we can compare them to our test rect
899 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 913 GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
900 fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n ", 914 fsBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
901 v.fsIn(), v.fsIn(), intervalName, intervalName); 915 inCoord.fsIn(), inCoord.fsIn(), inCoord.fsIn(), inCoo rd.fsIn());
902 fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", v.fsIn()); 916 fsBuilder->codeAppendf("vec2 fragPosShifted = vec2(xShifted, %s.y);", inCoor d.fsIn());
903 if (GrProcessorEdgeTypeIsAA(de.getEdgeType())) { 917 if (GrProcessorEdgeTypeIsAA(de.getEdgeType())) {
904 // The amount of coverage removed in x and y by the edges is computed as a pair of negative 918 // The amount of coverage removed in x and y by the edges is computed as a pair of negative
905 // numbers, xSub and ySub. 919 // numbers, xSub and ySub.
906 fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n"); 920 fsBuilder->codeAppend("float xSub, ySub;");
907 fsBuilder->codeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n" , rectName); 921 fsBuilder->codeAppendf("xSub = min(fragPosShifted.x - %s.x, 0.0);", inRe ct.fsIn());
908 fsBuilder->codeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n ", rectName); 922 fsBuilder->codeAppendf("xSub += min(%s.z - fragPosShifted.x, 0.0);", inR ect.fsIn());
909 fsBuilder->codeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n" , rectName); 923 fsBuilder->codeAppendf("ySub = min(fragPosShifted.y - %s.y, 0.0);", inRe ct.fsIn());
910 fsBuilder->codeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n ", rectName); 924 fsBuilder->codeAppendf("ySub += min(%s.w - fragPosShifted.y, 0.0);", inR ect.fsIn());
911 // Now compute coverage in x and y and multiply them to get the fraction of the pixel 925 // Now compute coverage in x and y and multiply them to get the fraction of the pixel
912 // covered. 926 // covered.
913 fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n"); 927 fsBuilder->codeAppendf("float alpha = (1.0 + max(xSub, -1.0)) * (1.0 + m ax(ySub, -1.0));");
914 } else { 928 } else {
915 // Assuming the bounding geometry is tight so no need to check y values 929 // Assuming the bounding geometry is tight so no need to check y values
916 fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n"); 930 fsBuilder->codeAppendf("float alpha = 1.0;");
917 fsBuilder->codeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName); 931 fsBuilder->codeAppendf("alpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;",
918 fsBuilder->codeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName); 932 inRect.fsIn());
933 fsBuilder->codeAppendf("alpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;",
934 inRect.fsIn());
919 } 935 }
920 fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage); 936 fsBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
921 } 937 }
922 938
923 void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman, 939 void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman,
924 const GrPrimitiveProcessor& processor, 940 const GrPrimitiveProcessor& processor,
925 const GrBatchTracker& bt) { 941 const GrBatchTracker& bt) {
926 this->setUniformViewMatrix(pdman, processor.viewMatrix()); 942 this->setUniformViewMatrix(pdman, processor.viewMatrix());
927 943
928 const DashingLineEffect& de = processor.cast<DashingLineEffect>();
929 const SkRect& rect = de.getRect();
930 SkScalar intervalLength = de.getIntervalLength();
931 if (rect != fPrevRect || intervalLength != fPrevIntervalLength) {
932 pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
933 rect.fRight - 0.5f, rect.fBottom - 0.5f);
934 pdman.set1f(fIntervalUniform, intervalLength);
935 fPrevRect = rect;
936 fPrevIntervalLength = intervalLength;
937 }
938
939 const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>(); 944 const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>();
940 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { 945 if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
941 GrGLfloat c[4]; 946 GrGLfloat c[4];
942 GrColorToRGBAFloat(local.fColor, c); 947 GrColorToRGBAFloat(local.fColor, c);
943 pdman.set4fv(fColorUniform, 1, c); 948 pdman.set4fv(fColorUniform, 1, c);
944 fColor = local.fColor; 949 fColor = local.fColor;
945 } 950 }
946 } 951 }
947 952
948 void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp, 953 void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,
949 const GrBatchTracker& bt, 954 const GrBatchTracker& bt,
950 const GrGLCaps&, 955 const GrGLCaps&,
951 GrProcessorKeyBuilder* b) { 956 GrProcessorKeyBuilder* b) {
952 const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>(); 957 const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>();
953 const DashingLineEffect& de = gp.cast<DashingLineEffect>(); 958 const DashingLineEffect& de = gp.cast<DashingLineEffect>();
954 uint32_t key = 0; 959 uint32_t key = 0;
955 key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 : 0 x0; 960 key |= local.fUsesLocalCoords && gp.localMatrix().hasPerspective() ? 0x1 : 0 x0;
956 key |= ComputePosKey(gp.viewMatrix()) << 1; 961 key |= ComputePosKey(gp.viewMatrix()) << 1;
957 key |= de.getEdgeType() << 8; 962 key |= de.getEdgeType() << 8;
958 b->add32(key << 16 | local.fInputColorType); 963 b->add32(key << 16 | local.fInputColorType);
959 } 964 }
960 965
961 ////////////////////////////////////////////////////////////////////////////// 966 //////////////////////////////////////////////////////////////////////////////
962 967
963 GrGeometryProcessor* DashingLineEffect::Create(GrColor color, 968 GrGeometryProcessor* DashingLineEffect::Create(GrColor color,
964 GrPrimitiveEdgeType edgeType, 969 GrPrimitiveEdgeType edgeType,
965 const DashInfo& info,
966 SkScalar strokeWidth,
967 const SkMatrix& localMatrix) { 970 const SkMatrix& localMatrix) {
968 if (info.fCount != 2) { 971 return SkNEW_ARGS(DashingLineEffect, (color, edgeType, localMatrix));
969 return NULL;
970 }
971
972 return SkNEW_ARGS(DashingLineEffect, (color, edgeType, info, strokeWidth, lo calMatrix));
973 } 972 }
974 973
975 DashingLineEffect::~DashingLineEffect() {} 974 DashingLineEffect::~DashingLineEffect() {}
976 975
977 void DashingLineEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const { 976 void DashingLineEffect::onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const {
978 out->setUnknownSingleComponent(); 977 out->setUnknownSingleComponent();
979 } 978 }
980 979
981 void DashingLineEffect::getGLProcessorKey(const GrBatchTracker& bt, 980 void DashingLineEffect::getGLProcessorKey(const GrBatchTracker& bt,
982 const GrGLCaps& caps, 981 const GrGLCaps& caps,
983 GrProcessorKeyBuilder* b) const { 982 GrProcessorKeyBuilder* b) const {
984 GLDashingLineEffect::GenKey(*this, bt, caps, b); 983 GLDashingLineEffect::GenKey(*this, bt, caps, b);
985 } 984 }
986 985
987 GrGLPrimitiveProcessor* DashingLineEffect::createGLInstance(const GrBatchTracker & bt, 986 GrGLPrimitiveProcessor* DashingLineEffect::createGLInstance(const GrBatchTracker & bt,
988 const GrGLCaps&) con st { 987 const GrGLCaps&) con st {
989 return SkNEW_ARGS(GLDashingLineEffect, (*this, bt)); 988 return SkNEW_ARGS(GLDashingLineEffect, (*this, bt));
990 } 989 }
991 990
992 DashingLineEffect::DashingLineEffect(GrColor color, 991 DashingLineEffect::DashingLineEffect(GrColor color,
993 GrPrimitiveEdgeType edgeType, 992 GrPrimitiveEdgeType edgeType,
994 const DashInfo& info,
995 SkScalar strokeWidth,
996 const SkMatrix& localMatrix) 993 const SkMatrix& localMatrix)
997 : INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) { 994 : INHERITED(color, SkMatrix::I(), localMatrix), fEdgeType(edgeType) {
998 this->initClassID<DashingLineEffect>(); 995 this->initClassID<DashingLineEffect>();
999 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertex AttribType)); 996 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertex AttribType));
1000 fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec2f_GrVertexAttrib Type)); 997 fInCoord = &this->addVertexAttrib(Attribute("inCoord", kVec3f_GrVertexAttrib Type));
1001 SkScalar onLen = info.fIntervals[0]; 998 fInRect = &this->addVertexAttrib(Attribute("inRect", kVec4f_GrVertexAttribTy pe));
1002 SkScalar offLen = info.fIntervals[1];
1003 SkScalar halfOffLen = SkScalarHalf(offLen);
1004 SkScalar halfStroke = SkScalarHalf(strokeWidth);
1005 fIntervalLength = onLen + offLen;
1006 fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke);
1007 } 999 }
1008 1000
1009 bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const { 1001 bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const {
1010 const DashingLineEffect& de = other.cast<DashingLineEffect>(); 1002 const DashingLineEffect& de = other.cast<DashingLineEffect>();
1011 return (fEdgeType == de.fEdgeType && 1003 return (fEdgeType == de.fEdgeType/* &&
1012 fRect == de.fRect && 1004 fRect == de.fRect &&
1013 fIntervalLength == de.fIntervalLength); 1005 fIntervalLength == de.fIntervalLength*/);
1014 } 1006 }
1015 1007
1016 void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInf o& init) const { 1008 void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const GrPipelineInf o& init) const {
1017 DashingLineBatchTracker* local = bt->cast<DashingLineBatchTracker>(); 1009 DashingLineBatchTracker* local = bt->cast<DashingLineBatchTracker>();
1018 local->fInputColorType = GetColorInputType(&local->fColor, this->color(), in it, false); 1010 local->fInputColorType = GetColorInputType(&local->fColor, this->color(), in it, false);
1019 local->fUsesLocalCoords = init.fUsesLocalCoords; 1011 local->fUsesLocalCoords = init.fUsesLocalCoords;
1020 } 1012 }
1021 1013
1022 bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m, 1014 bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m,
1023 const GrGeometryProcessor& that, 1015 const GrGeometryProcessor& that,
1024 const GrBatchTracker& t) const { 1016 const GrBatchTracker& t) const {
1025 const DashingLineBatchTracker& mine = m.cast<DashingLineBatchTracker>(); 1017 const DashingLineBatchTracker& mine = m.cast<DashingLineBatchTracker>();
1026 const DashingLineBatchTracker& theirs = t.cast<DashingLineBatchTracker>(); 1018 const DashingLineBatchTracker& theirs = t.cast<DashingLineBatchTracker>();
1027 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, 1019 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords,
1028 that, theirs.fUsesLocalCoords) && 1020 that, theirs.fUsesLocalCoords) &&
1029 CanCombineOutput(mine.fInputColorType, mine.fColor, 1021 CanCombineOutput(mine.fInputColorType, mine.fColor,
1030 theirs.fInputColorType, theirs.fColor); 1022 theirs.fInputColorType, theirs.fColor);
1031 } 1023 }
1032 1024
1033 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect); 1025 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect);
1034 1026
1035 GrGeometryProcessor* DashingLineEffect::TestCreate(SkRandom* random, 1027 GrGeometryProcessor* DashingLineEffect::TestCreate(SkRandom* random,
1036 GrContext*, 1028 GrContext*,
1037 const GrDrawTargetCaps& caps, 1029 const GrDrawTargetCaps& caps,
1038 GrTexture*[]) { 1030 GrTexture*[]) {
1039 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->next ULessThan( 1031 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->next ULessThan(
1040 kGrProcessorEdgeTypeCnt)); 1032 kGrProcessorEdgeTypeCnt));
1041 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f);
1042 DashInfo info;
1043 info.fCount = 2;
1044 SkAutoTArray<SkScalar> intervals(info.fCount);
1045 info.fIntervals = intervals.get();
1046 info.fIntervals[0] = random->nextRangeScalar(0, 10.f);
1047 info.fIntervals[1] = random->nextRangeScalar(0, 10.f);
1048 info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fInterval s[1]);
1049 1033
1050 return DashingLineEffect::Create(GrRandomColor(random), 1034 return DashingLineEffect::Create(GrRandomColor(random),
1051 edgeType, info, strokeWidth, 1035 edgeType, GrProcessorUnitTest::TestMatrix(r andom));
1052 GrProcessorUnitTest::TestMatrix(random));
1053 } 1036 }
1054 1037
1055 ////////////////////////////////////////////////////////////////////////////// 1038 //////////////////////////////////////////////////////////////////////////////
1056 1039
1057 GrGeometryProcessor* GrDashingEffect::Create(GrColor color, 1040 static GrGeometryProcessor* create_dash_gp(GrColor color,
1058 GrPrimitiveEdgeType edgeType, 1041 GrPrimitiveEdgeType edgeType,
1059 const SkPathEffect::DashInfo& info, 1042 DashCap cap,
1060 SkScalar strokeWidth, 1043 const SkMatrix& localMatrix) {
1061 GrDashingEffect::DashCap cap,
1062 const SkMatrix& localMatrix) {
1063 switch (cap) { 1044 switch (cap) {
1064 case GrDashingEffect::kRound_DashCap: 1045 case kRound_DashCap:
1065 return DashingCircleEffect::Create(color, edgeType, info, 1046 return DashingCircleEffect::Create(color, edgeType, localMatrix);
1066 SkScalarHalf(strokeWidth), 1047 case kNonRound_DashCap:
1067 localMatrix); 1048 return DashingLineEffect::Create(color, edgeType, localMatrix);
1068 case GrDashingEffect::kNonRound_DashCap:
1069 return DashingLineEffect::Create(color, edgeType, info, strokeWidth, localMatrix);
1070 default: 1049 default:
1071 SkFAIL("Unexpected dashed cap."); 1050 SkFAIL("Unexpected dashed cap.");
1072 } 1051 }
1073 return NULL; 1052 return NULL;
1074 } 1053 }
OLDNEW
« src/gpu/effects/GrDashingEffect.h ('K') | « src/gpu/effects/GrDashingEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698