diff options
-rw-r--r-- | gyp/core.gypi | 2 | ||||
-rw-r--r-- | include/core/SkPicture.h | 3 | ||||
-rw-r--r-- | include/core/SkPictureAnalyzer.h | 52 | ||||
-rw-r--r-- | src/core/SkPicture.cpp | 2 | ||||
-rw-r--r-- | src/core/SkPictureAnalyzer.cpp | 50 | ||||
-rw-r--r-- | tests/PictureTest.cpp | 55 | ||||
-rw-r--r-- | tools/gpuveto.cpp | 3 |
7 files changed, 157 insertions, 10 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi index 0face28599..477a9e7108 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -206,6 +206,7 @@ '<(skia_src_path)/core/SkPathRef.cpp', '<(skia_src_path)/core/SkPerspIter.h', '<(skia_src_path)/core/SkPicture.cpp', + '<(skia_src_path)/core/SkPictureAnalyzer.cpp', '<(skia_src_path)/core/SkPictureCommon.h', '<(skia_src_path)/core/SkPictureContentInfo.cpp', '<(skia_src_path)/core/SkPictureContentInfo.h', @@ -385,6 +386,7 @@ '<(skia_include_path)/core/SkPathMeasure.h', '<(skia_include_path)/core/SkPathRef.h', '<(skia_include_path)/core/SkPicture.h', + '<(skia_include_path)/core/SkPictureAnalyzer.h', '<(skia_include_path)/core/SkPictureRecorder.h', '<(skia_include_path)/core/SkPixelRef.h', '<(skia_include_path)/core/SkPoint.h', diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 44a1e5bdb9..eb35ef6366 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -153,8 +153,10 @@ public: static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*); static bool InternalOnly_BufferIsSKP(SkReadBuffer*, SkPictInfo*); +#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO /** Return true if the picture is suitable for rendering on the GPU. */ bool suitableForGpuRasterization(GrContext*, const char** whyNot = NULL) const; +#endif // Sent via SkMessageBus from destructor. struct DeletionMessage { int32_t fUniqueID; }; // TODO: -> uint32_t? @@ -190,6 +192,7 @@ private: friend class SkPictureData; virtual int numSlowPaths() const = 0; + friend class SkPictureGpuAnalyzer; friend struct SkPathCounter; // V35: Store SkRect (rather then width & height) in header diff --git a/include/core/SkPictureAnalyzer.h b/include/core/SkPictureAnalyzer.h new file mode 100644 index 0000000000..fa8cdb1fd1 --- /dev/null +++ b/include/core/SkPictureAnalyzer.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPictureAnalyzer_DEFINED +#define SkPictureAnalyzer_DEFINED + +#include "SkRefCnt.h" +#include "SkTypes.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" + +class SkPicture; + +/** \class SkPictureGpuAnalyzer + + Gathers GPU-related statistics for one or more SkPictures. +*/ +class SK_API SkPictureGpuAnalyzer final : public SkNoncopyable { +public: + explicit SkPictureGpuAnalyzer(sk_sp<GrContextThreadSafeProxy> = nullptr); + explicit SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture, + sk_sp<GrContextThreadSafeProxy> = nullptr); + + /** + * Process the given picture and accumulate its stats. + */ + void analyze(const SkPicture*); + + /** + * Reset all accumulated stats. + */ + void reset(); + + /** + * Returns true if the analyzed pictures are suitable for rendering on the GPU. + */ + bool suitableForGpuRasterization(const char** whyNot = nullptr) const; + +private: + uint32_t fNumSlowPaths; + + typedef SkNoncopyable INHERITED; +}; + +#endif // SK_SUPPORT_GPU + +#endif // SkPictureAnalyzer_DEFINED diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index 94c13950db..4e994559e6 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -219,6 +219,7 @@ void SkPicture::flatten(SkWriteBuffer& buffer) const { } } +#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) const { if (this->numSlowPaths() > 5) { if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; } @@ -226,6 +227,7 @@ bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) con } return true; } +#endif // Global setting to disable security precautions for serialization. void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) { diff --git a/src/core/SkPictureAnalyzer.cpp b/src/core/SkPictureAnalyzer.cpp new file mode 100644 index 0000000000..0ba420258b --- /dev/null +++ b/src/core/SkPictureAnalyzer.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkPicture.h" +#include "SkPictureAnalyzer.h" + +#if SK_SUPPORT_GPU + +namespace { + +inline bool veto_predicate(uint32_t numSlowPaths) { + return numSlowPaths > 5; +} + +} // anonymous namespace + +SkPictureGpuAnalyzer::SkPictureGpuAnalyzer(sk_sp<GrContextThreadSafeProxy> /* unused ATM */) + : fNumSlowPaths(0) { } + +SkPictureGpuAnalyzer::SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture, + sk_sp<GrContextThreadSafeProxy> ctx) + : SkPictureGpuAnalyzer(std::move(ctx)) { + this->analyze(picture.get()); +} + +void SkPictureGpuAnalyzer::analyze(const SkPicture* picture) { + if (!picture || veto_predicate(fNumSlowPaths)) { + return; + } + + fNumSlowPaths += picture->numSlowPaths(); +} + +void SkPictureGpuAnalyzer::reset() { + fNumSlowPaths = 0; +} + +bool SkPictureGpuAnalyzer::suitableForGpuRasterization(const char** whyNot) const { + if(veto_predicate(fNumSlowPaths)) { + if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; } + return false; + } + return true; +} + +#endif // SK_SUPPORT_GPU diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index b7fa1d1d91..c71e66309a 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -20,6 +20,7 @@ #include "SkMD5.h" #include "SkPaint.h" #include "SkPicture.h" +#include "SkPictureAnalyzer.h" #include "SkPictureRecorder.h" #include "SkPictureUtils.h" #include "SkPixelRef.h" @@ -158,7 +159,8 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { // path effects currently render an SkPicture undesireable for GPU rendering const char *reason = nullptr; - REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr, &reason)); + REPORTER_ASSERT(reporter, + !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization(&reason)); REPORTER_ASSERT(reporter, reason); canvas = recorder.beginRecording(100, 100); @@ -181,7 +183,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { } picture = recorder.finishRecordingAsPicture(); // A lot of small AA concave paths should be fine for GPU rendering - REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); canvas = recorder.beginRecording(100, 100); { @@ -203,7 +205,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { } picture = recorder.finishRecordingAsPicture(); // A lot of large AA concave paths currently render an SkPicture undesireable for GPU rendering - REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); canvas = recorder.beginRecording(100, 100); { @@ -227,7 +229,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { } picture = recorder.finishRecordingAsPicture(); // hairline stroked AA concave paths are fine for GPU rendering - REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); canvas = recorder.beginRecording(100, 100); { @@ -243,7 +245,7 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { } picture = recorder.finishRecordingAsPicture(); // fast-path dashed effects are fine for GPU rendering ... - REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); canvas = recorder.beginRecording(100, 100); { @@ -257,18 +259,18 @@ static void test_gpu_veto(skiatest::Reporter* reporter) { } picture = recorder.finishRecordingAsPicture(); // ... but only when applied to drawPoint() calls - REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); // Nest the previous picture inside a new one. canvas = recorder.beginRecording(100, 100); { - canvas->drawPicture(picture.get()); + canvas->drawPicture(picture); } picture = recorder.finishRecordingAsPicture(); - REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(nullptr)); + REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization()); } -#endif +#endif // SK_SUPPORT_GPU static void test_savelayer_extraction(skiatest::Reporter* reporter) { static const int kWidth = 100; @@ -1346,3 +1348,38 @@ DEF_TEST(Picture_preserveCullRect, r) { REPORTER_ASSERT(r, deserializedPicture->cullRect().right() == 3); REPORTER_ASSERT(r, deserializedPicture->cullRect().bottom() == 4); } + +#if SK_SUPPORT_GPU + +DEF_TEST(PictureGpuAnalyzer, r) { + SkPictureRecorder recorder; + + { + SkCanvas* canvas = recorder.beginRecording(10, 10); + SkPaint paint; + SkScalar intervals [] = { 10, 20 }; + paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 25)); + + for (int i = 0; i < 50; ++i) { + canvas->drawRect(SkRect::MakeWH(10, 10), paint); + } + } + sk_sp<SkPicture> vetoPicture(recorder.finishRecordingAsPicture()); + + SkPictureGpuAnalyzer analyzer; + REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization()); + + analyzer.analyze(vetoPicture.get()); + REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization()); + + analyzer.reset(); + REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization()); + + recorder.beginRecording(10, 10)->drawPicture(vetoPicture); + sk_sp<SkPicture> nestedVetoPicture(recorder.finishRecordingAsPicture()); + + analyzer.analyze(nestedVetoPicture.get()); + REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization()); +} + +#endif // SK_SUPPORT_GPU diff --git a/tools/gpuveto.cpp b/tools/gpuveto.cpp index 59b3bef2d9..4672a38b6b 100644 --- a/tools/gpuveto.cpp +++ b/tools/gpuveto.cpp @@ -7,6 +7,7 @@ #include "SkCommandLineFlags.h" #include "SkPicture.h" +#include "SkPictureAnalyzer.h" #include "SkPictureRecorder.h" #include "SkStream.h" @@ -57,7 +58,7 @@ int tool_main(int argc, char** argv) { nullptr, 0)); sk_sp<SkPicture> recorded(recorder.finishRecordingAsPicture()); - if (recorded->suitableForGpuRasterization(nullptr)) { + if (SkPictureGpuAnalyzer(recorded).suitableForGpuRasterization(nullptr)) { SkDebugf("suitable\n"); } else { SkDebugf("unsuitable\n"); |