| 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 |