OLD | NEW |
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 "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrBatchTarget.h" | 11 #include "GrBatchTarget.h" |
| 12 #include "GrBatchTest.h" |
12 #include "GrBufferAllocPool.h" | 13 #include "GrBufferAllocPool.h" |
13 #include "GrGeometryProcessor.h" | 14 #include "GrGeometryProcessor.h" |
14 #include "GrContext.h" | 15 #include "GrContext.h" |
15 #include "GrCoordTransform.h" | 16 #include "GrCoordTransform.h" |
16 #include "GrDefaultGeoProcFactory.h" | 17 #include "GrDefaultGeoProcFactory.h" |
17 #include "GrDrawTarget.h" | 18 #include "GrDrawTarget.h" |
18 #include "GrDrawTargetCaps.h" | 19 #include "GrDrawTargetCaps.h" |
19 #include "GrInvariantOutput.h" | 20 #include "GrInvariantOutput.h" |
20 #include "GrProcessor.h" | 21 #include "GrProcessor.h" |
21 #include "GrStrokeInfo.h" | 22 #include "GrStrokeInfo.h" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 SkMatrix fSrcRotInv; | 252 SkMatrix fSrcRotInv; |
252 SkPoint fPtsRot[2]; | 253 SkPoint fPtsRot[2]; |
253 SkScalar fSrcStrokeWidth; | 254 SkScalar fSrcStrokeWidth; |
254 SkScalar fPhase; | 255 SkScalar fPhase; |
255 SkScalar fIntervals[2]; | 256 SkScalar fIntervals[2]; |
256 SkScalar fParallelScale; | 257 SkScalar fParallelScale; |
257 SkScalar fPerpendicularScale; | 258 SkScalar fPerpendicularScale; |
258 SkDEBUGCODE(SkRect fDevBounds;) | 259 SkDEBUGCODE(SkRect fDevBounds;) |
259 }; | 260 }; |
260 | 261 |
261 static GrBatch* Create(const Geometry& geometry, SkPaint::Cap cap, DashAAMod
e aaMode, bool fullDash) { | 262 static GrBatch* Create(const Geometry& geometry, SkPaint::Cap cap, DashAAMod
e aaMode, |
| 263 bool fullDash) { |
262 return SkNEW_ARGS(DashBatch, (geometry, cap, aaMode, fullDash)); | 264 return SkNEW_ARGS(DashBatch, (geometry, cap, aaMode, fullDash)); |
263 } | 265 } |
264 | 266 |
265 const char* name() const override { return "DashBatch"; } | 267 const char* name() const override { return "DashBatch"; } |
266 | 268 |
267 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 269 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
268 // When this is called on a batch, there is only one geometry bundle | 270 // When this is called on a batch, there is only one geometry bundle |
269 out->setKnownFourComponents(fGeoData[0].fColor); | 271 out->setKnownFourComponents(fGeoData[0].fColor); |
270 } | 272 } |
271 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 273 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 bool fFullDash; | 694 bool fFullDash; |
693 }; | 695 }; |
694 | 696 |
695 static const int kVertsPerDash = 4; | 697 static const int kVertsPerDash = 4; |
696 static const int kIndicesPerDash = 6; | 698 static const int kIndicesPerDash = 6; |
697 | 699 |
698 BatchTracker fBatch; | 700 BatchTracker fBatch; |
699 SkSTArray<1, Geometry, true> fGeoData; | 701 SkSTArray<1, Geometry, true> fGeoData; |
700 }; | 702 }; |
701 | 703 |
702 | 704 static GrBatch* create_batch(GrColor color, const SkMatrix& viewMatrix, const Sk
Point pts[2], |
703 bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, | 705 bool useAA, const GrStrokeInfo& strokeInfo, bool ms
aaRT) { |
704 GrPipelineBuilder* pipelineBuilder, GrColor c
olor, | |
705 const SkMatrix& viewMatrix, const SkPoint pts
[2], | |
706 bool useAA, const GrStrokeInfo& strokeInfo) { | |
707 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); | 706 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); |
708 | 707 |
709 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); | 708 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap(); |
710 | 709 |
711 DashBatch::Geometry geometry; | 710 DashBatch::Geometry geometry; |
712 geometry.fSrcStrokeWidth = strokeInfo.getStrokeRec().getWidth(); | 711 geometry.fSrcStrokeWidth = strokeInfo.getStrokeRec().getWidth(); |
713 | 712 |
714 // the phase should be normalized to be [0, sum of all intervals) | 713 // the phase should be normalized to be [0, sum of all intervals) |
715 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv
als[1]); | 714 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv
als[1]); |
716 | 715 |
717 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[
1].fX | 716 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[
1].fX |
718 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { | 717 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { |
719 SkMatrix rotMatrix; | 718 SkMatrix rotMatrix; |
720 align_to_x_axis(pts, &rotMatrix, geometry.fPtsRot); | 719 align_to_x_axis(pts, &rotMatrix, geometry.fPtsRot); |
721 if(!rotMatrix.invert(&geometry.fSrcRotInv)) { | 720 if(!rotMatrix.invert(&geometry.fSrcRotInv)) { |
722 SkDebugf("Failed to create invertible rotation matrix!\n"); | 721 SkDebugf("Failed to create invertible rotation matrix!\n"); |
723 return false; | 722 return NULL; |
724 } | 723 } |
725 } else { | 724 } else { |
726 geometry.fSrcRotInv.reset(); | 725 geometry.fSrcRotInv.reset(); |
727 memcpy(geometry.fPtsRot, pts, 2 * sizeof(SkPoint)); | 726 memcpy(geometry.fPtsRot, pts, 2 * sizeof(SkPoint)); |
728 } | 727 } |
729 | 728 |
730 // Scale corrections of intervals and stroke from view matrix | 729 // Scale corrections of intervals and stroke from view matrix |
731 calc_dash_scaling(&geometry.fParallelScale, &geometry.fPerpendicularScale, v
iewMatrix, | 730 calc_dash_scaling(&geometry.fParallelScale, &geometry.fPerpendicularScale, v
iewMatrix, |
732 geometry.fPtsRot); | 731 geometry.fPtsRot); |
733 | 732 |
734 SkScalar offInterval = info.fIntervals[1] * geometry.fParallelScale; | 733 SkScalar offInterval = info.fIntervals[1] * geometry.fParallelScale; |
735 SkScalar strokeWidth = geometry.fSrcStrokeWidth * geometry.fPerpendicularSca
le; | 734 SkScalar strokeWidth = geometry.fSrcStrokeWidth * geometry.fPerpendicularSca
le; |
736 | 735 |
737 if (SkPaint::kSquare_Cap == cap && 0 != geometry.fSrcStrokeWidth) { | 736 if (SkPaint::kSquare_Cap == cap && 0 != geometry.fSrcStrokeWidth) { |
738 // add cap to on interveal and remove from off interval | 737 // add cap to on interveal and remove from off interval |
739 offInterval -= strokeWidth; | 738 offInterval -= strokeWidth; |
740 } | 739 } |
741 | 740 |
742 DashAAMode aaMode = pipelineBuilder->getRenderTarget()->isMultisampled() ? k
MSAA_DashAAMode : | 741 DashAAMode aaMode = msaaRT ? kMSAA_DashAAMode : |
743 useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode; | 742 useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode; |
744 | 743 |
745 // TODO we can do a real rect call if not using fulldash(ie no off interval,
not using AA) | 744 // TODO we can do a real rect call if not using fulldash(ie no off interval,
not using AA) |
746 bool fullDash = offInterval > 0.f || aaMode != kBW_DashAAMode; | 745 bool fullDash = offInterval > 0.f || aaMode != kBW_DashAAMode; |
747 | 746 |
748 geometry.fColor = color; | 747 geometry.fColor = color; |
749 geometry.fViewMatrix = viewMatrix; | 748 geometry.fViewMatrix = viewMatrix; |
750 geometry.fPhase = info.fPhase; | 749 geometry.fPhase = info.fPhase; |
751 geometry.fIntervals[0] = info.fIntervals[0]; | 750 geometry.fIntervals[0] = info.fIntervals[0]; |
752 geometry.fIntervals[1] = info.fIntervals[1]; | 751 geometry.fIntervals[1] = info.fIntervals[1]; |
753 | 752 |
754 SkAutoTUnref<GrBatch> batch(DashBatch::Create(geometry, cap, aaMode, fullDas
h)); | 753 return DashBatch::Create(geometry, cap, aaMode, fullDash); |
| 754 } |
| 755 |
| 756 bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, |
| 757 GrPipelineBuilder* pipelineBuilder, GrColor c
olor, |
| 758 const SkMatrix& viewMatrix, const SkPoint pts
[2], |
| 759 bool useAA, const GrStrokeInfo& strokeInfo) { |
| 760 SkAutoTUnref<GrBatch> batch(create_batch(color, viewMatrix, pts, useAA, stro
keInfo, |
| 761 pipelineBuilder->getRenderTarget()-
>isMultisampled())); |
| 762 if (!batch) { |
| 763 return false; |
| 764 } |
| 765 |
755 target->drawBatch(pipelineBuilder, batch); | 766 target->drawBatch(pipelineBuilder, batch); |
756 | |
757 return true; | 767 return true; |
758 } | 768 } |
759 | 769 |
760 ////////////////////////////////////////////////////////////////////////////// | 770 ////////////////////////////////////////////////////////////////////////////// |
761 | 771 |
762 class GLDashingCircleEffect; | 772 class GLDashingCircleEffect; |
763 | 773 |
764 struct DashingCircleBatchTracker { | 774 struct DashingCircleBatchTracker { |
765 GrGPInput fInputColorType; | 775 GrGPInput fInputColorType; |
766 GrColor fColor; | 776 GrColor fColor; |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 switch (cap) { | 1283 switch (cap) { |
1274 case kRound_DashCap: | 1284 case kRound_DashCap: |
1275 return DashingCircleEffect::Create(color, dashAAMode, localMatrix); | 1285 return DashingCircleEffect::Create(color, dashAAMode, localMatrix); |
1276 case kNonRound_DashCap: | 1286 case kNonRound_DashCap: |
1277 return DashingLineEffect::Create(color, dashAAMode, localMatrix); | 1287 return DashingLineEffect::Create(color, dashAAMode, localMatrix); |
1278 default: | 1288 default: |
1279 SkFAIL("Unexpected dashed cap."); | 1289 SkFAIL("Unexpected dashed cap."); |
1280 } | 1290 } |
1281 return NULL; | 1291 return NULL; |
1282 } | 1292 } |
| 1293 |
| 1294 ////////////////////////////////////////////////////////////////////////////////
///////////////// |
| 1295 |
| 1296 #ifdef GR_TEST_UTILS |
| 1297 |
| 1298 BATCH_TEST_DEFINE(DashBatch) { |
| 1299 GrColor color = GrRandomColor(random); |
| 1300 SkMatrix viewMatrix = GrTest::TestMatrixPreservesRightAngles(random); |
| 1301 bool useAA = random->nextBool(); |
| 1302 bool msaaRT = random->nextBool(); |
| 1303 |
| 1304 // We can only dash either horizontal or vertical lines |
| 1305 SkPoint pts[2]; |
| 1306 if (random->nextBool()) { |
| 1307 // vertical |
| 1308 pts[0].fX = 1.f; |
| 1309 pts[0].fY = random->nextF() * 10.f; |
| 1310 pts[1].fX = 1.f; |
| 1311 pts[1].fY = random->nextF() * 10.f; |
| 1312 } else { |
| 1313 // horizontal |
| 1314 pts[0].fX = random->nextF() * 10.f; |
| 1315 pts[0].fY = 1.f; |
| 1316 pts[1].fX = random->nextF() * 10.f; |
| 1317 pts[1].fY = 1.f; |
| 1318 } |
| 1319 |
| 1320 // pick random cap |
| 1321 SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::Cap::kCapCoun
t)); |
| 1322 |
| 1323 SkScalar intervals[2]; |
| 1324 |
| 1325 // We can only dash with the following intervals |
| 1326 enum Intervals { |
| 1327 kOpenOpen_Intervals , |
| 1328 kOpenClose_Intervals, |
| 1329 kCloseOpen_Intervals, |
| 1330 }; |
| 1331 |
| 1332 Intervals intervalType = SkPaint::kRound_Cap ? |
| 1333 kOpenClose_Intervals : |
| 1334 Intervals(random->nextULessThan(kCloseOpen_Interval
s + 1)); |
| 1335 static const SkScalar kIntervalMin = 0.1f; |
| 1336 static const SkScalar kIntervalMax = 10.f; |
| 1337 switch (intervalType) { |
| 1338 case kOpenOpen_Intervals: |
| 1339 intervals[0] = random->nextRangeScalar(kIntervalMin, kIntervalMax); |
| 1340 intervals[1] = random->nextRangeScalar(kIntervalMin, kIntervalMax); |
| 1341 break; |
| 1342 case kOpenClose_Intervals: |
| 1343 intervals[0] = 0.f; |
| 1344 intervals[1] = random->nextRangeScalar(kIntervalMin, kIntervalMax); |
| 1345 break; |
| 1346 case kCloseOpen_Intervals: |
| 1347 intervals[0] = random->nextRangeScalar(kIntervalMin, kIntervalMax); |
| 1348 intervals[1] = 0.f; |
| 1349 break; |
| 1350 |
| 1351 } |
| 1352 |
| 1353 // phase is 0 < sum (i0, i1) |
| 1354 SkScalar phase = random->nextRangeScalar(0, intervals[0] + intervals[1]); |
| 1355 |
| 1356 SkPaint p; |
| 1357 p.setStyle(SkPaint::kStroke_Style); |
| 1358 p.setStrokeWidth(SkIntToScalar(1)); |
| 1359 p.setStrokeCap(cap); |
| 1360 |
| 1361 GrStrokeInfo strokeInfo(p); |
| 1362 |
| 1363 SkPathEffect::DashInfo info; |
| 1364 info.fIntervals = intervals; |
| 1365 info.fCount = 2; |
| 1366 info.fPhase = phase; |
| 1367 SkDEBUGCODE(bool success = ) strokeInfo.setDashInfo(info); |
| 1368 SkASSERT(success); |
| 1369 |
| 1370 return create_batch(color, viewMatrix, pts, useAA, strokeInfo, msaaRT); |
| 1371 } |
| 1372 |
| 1373 #endif |
OLD | NEW |