diff options
-rw-r--r-- | include/core/SkPictureAnalyzer.h | 12 | ||||
-rw-r--r-- | src/core/SkPictureAnalyzer.cpp | 21 | ||||
-rw-r--r-- | src/core/SkPictureCommon.h | 7 | ||||
-rw-r--r-- | tests/PictureTest.cpp | 63 |
4 files changed, 101 insertions, 2 deletions
diff --git a/include/core/SkPictureAnalyzer.h b/include/core/SkPictureAnalyzer.h index fa8cdb1fd1..b7a76cce80 100644 --- a/include/core/SkPictureAnalyzer.h +++ b/include/core/SkPictureAnalyzer.h @@ -9,11 +9,13 @@ #define SkPictureAnalyzer_DEFINED #include "SkRefCnt.h" +#include "SkRegion.h" #include "SkTypes.h" #if SK_SUPPORT_GPU #include "GrContext.h" +class SkPath; class SkPicture; /** \class SkPictureGpuAnalyzer @@ -29,7 +31,15 @@ public: /** * Process the given picture and accumulate its stats. */ - void analyze(const SkPicture*); + void analyzePicture(const SkPicture*); + + // Legacy/transitional alias. + void analyze(const SkPicture* picture) { this->analyzePicture(picture); } + + /** + * Process an explicit clipPath op. + */ + void analyzeClipPath(const SkPath&, SkRegion::Op, bool doAntiAlias); /** * Reset all accumulated stats. diff --git a/src/core/SkPictureAnalyzer.cpp b/src/core/SkPictureAnalyzer.cpp index 0ba420258b..49c4fce779 100644 --- a/src/core/SkPictureAnalyzer.cpp +++ b/src/core/SkPictureAnalyzer.cpp @@ -5,8 +5,11 @@ * found in the LICENSE file. */ +#include "SkPath.h" #include "SkPicture.h" #include "SkPictureAnalyzer.h" +#include "SkPictureCommon.h" +#include "SkRecords.h" #if SK_SUPPORT_GPU @@ -27,7 +30,7 @@ SkPictureGpuAnalyzer::SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture, this->analyze(picture.get()); } -void SkPictureGpuAnalyzer::analyze(const SkPicture* picture) { +void SkPictureGpuAnalyzer::analyzePicture(const SkPicture* picture) { if (!picture || veto_predicate(fNumSlowPaths)) { return; } @@ -35,6 +38,22 @@ void SkPictureGpuAnalyzer::analyze(const SkPicture* picture) { fNumSlowPaths += picture->numSlowPaths(); } +void SkPictureGpuAnalyzer::analyzeClipPath(const SkPath& path, SkRegion::Op op, bool doAntiAlias) { + if (veto_predicate(fNumSlowPaths)) { + return; + } + + const SkRecords::ClipPath clipOp = { + SkIRect::MakeEmpty(), // Willie don't care. + path, + SkRecords::RegionOpAndAA(op, doAntiAlias) + }; + + SkPathCounter counter; + counter(clipOp); + fNumSlowPaths += counter.fNumSlowPathsAndDashEffects; +} + void SkPictureGpuAnalyzer::reset() { fNumSlowPaths = 0; } diff --git a/src/core/SkPictureCommon.h b/src/core/SkPictureCommon.h index 16146be020..1c38b049fa 100644 --- a/src/core/SkPictureCommon.h +++ b/src/core/SkPictureCommon.h @@ -123,6 +123,13 @@ struct SkPathCounter { } } + void operator()(const SkRecords::ClipPath& op) { + // TODO: does the SkRegion op matter? + if (op.opAA.aa && !op.path.isConvex()) { + fNumSlowPathsAndDashEffects++; + } + } + void operator()(const SkRecords::SaveLayer& op) { this->checkPaint(AsPtr(op.paint)); } diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index c71e66309a..0603eb328f 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -135,6 +135,25 @@ static void rand_op(SkCanvas* canvas, SkRandom& rand) { #if SK_SUPPORT_GPU +static SkPath make_convex_path() { + SkPath path; + path.lineTo(100, 0); + path.lineTo(50, 100); + path.close(); + + return path; +} + +static SkPath make_concave_path() { + SkPath path; + path.lineTo(50, 50); + path.lineTo(100, 0); + path.lineTo(50, 100); + path.close(); + + return path; +} + static void test_gpu_veto(skiatest::Reporter* reporter) { SkPictureRecorder recorder; @@ -261,6 +280,34 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { // ... but only when applied to drawPoint() calls REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); + canvas = recorder.beginRecording(100, 100); + { + const SkPath convexClip = make_convex_path(); + const SkPath concaveClip = make_concave_path(); + + for (int i = 0; i < 50; ++i) { + canvas->clipPath(convexClip); + canvas->clipPath(concaveClip); + canvas->clipPath(convexClip, SkRegion::kIntersect_Op, true); + canvas->drawRect(SkRect::MakeWH(100, 100), SkPaint()); + } + } + picture = recorder.finishRecordingAsPicture(); + // Convex clips and non-AA concave clips are fine on the GPU. + REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); + + canvas = recorder.beginRecording(100, 100); + { + const SkPath concaveClip = make_concave_path(); + for (int i = 0; i < 50; ++i) { + canvas->clipPath(concaveClip, SkRegion::kIntersect_Op, true); + canvas->drawRect(SkRect::MakeWH(100, 100), SkPaint()); + } + } + picture = recorder.finishRecordingAsPicture(); + // ... but AA concave clips are not. + REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); + // Nest the previous picture inside a new one. canvas = recorder.beginRecording(100, 100); { @@ -1380,6 +1427,22 @@ DEF_TEST(PictureGpuAnalyzer, r) { analyzer.analyze(nestedVetoPicture.get()); REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization()); + + analyzer.reset(); + + const SkPath convexClip = make_convex_path(); + const SkPath concaveClip = make_concave_path(); + for (int i = 0; i < 50; ++i) { + analyzer.analyzeClipPath(convexClip, SkRegion::kIntersect_Op, false); + analyzer.analyzeClipPath(convexClip, SkRegion::kIntersect_Op, true); + analyzer.analyzeClipPath(concaveClip, SkRegion::kIntersect_Op, false); + } + REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization()); + + for (int i = 0; i < 50; ++i) { + analyzer.analyzeClipPath(concaveClip, SkRegion::kIntersect_Op, true); + } + REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization()); } #endif // SK_SUPPORT_GPU |