remove unused willPlayBackBitmaps from picture

and SkPictureAnalyzer

Bug: skia:
Change-Id: I394eca648234b1a69e6f9a0a88c407366a33d079
Reviewed-on: https://skia-review.googlesource.com/87791
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Reed 2017-12-20 15:03:08 -05:00 committed by Skia Commit-Bot
parent 297d6efe85
commit b60c5ebf04
13 changed files with 2 additions and 689 deletions

View File

@ -216,7 +216,6 @@ skia_core_sources = [
"$_src/core/SkPathPriv.h",
"$_src/core/SkPathRef.cpp",
"$_src/core/SkPicture.cpp",
"$_src/core/SkPictureAnalyzer.cpp",
"$_src/core/SkPictureCommon.h",
"$_src/core/SkPictureContentInfo.cpp",
"$_src/core/SkPictureContentInfo.h",
@ -408,7 +407,6 @@ skia_core_sources = [
"$_include/core/SkPathEffect.h",
"$_include/core/SkPathMeasure.h",
"$_include/core/SkPicture.h",
"$_include/core/SkPictureAnalyzer.h",
"$_include/core/SkPictureRecorder.h",
"$_include/core/SkPixelRef.h",
"$_include/core/SkPoint.h",

View File

@ -115,12 +115,6 @@ public:
*/
void flatten(SkWriteBuffer&) const;
/**
* Returns true if any bitmaps may be produced when this SkPicture
* is replayed.
*/
virtual bool willPlayBackBitmaps() const = 0;
/** Return the approximate number of operations in this picture. This
* number may be greater or less than the number of SkCanvas calls
* recorded: some calls may be recorded as more than one operation, or some
@ -131,11 +125,6 @@ public:
/** Returns the approximate byte size of this picture, not including large ref'd objects. */
virtual size_t approximateBytesUsed() const = 0;
#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
/** Return true if the picture is suitable for rendering on the GPU. */
bool suitableForGpuRasterization(GrContext*, const char** whyNot = nullptr) const;
#endif
// Returns NULL if this is not an SkBigPicture.
virtual const SkBigPicture* asSkBigPicture() const { return nullptr; }
@ -164,8 +153,6 @@ private:
static bool BufferIsSKP(SkReadBuffer*, SkPictInfo*);
friend bool SkPicture_StreamIsSKP(SkStream*, SkPictInfo*);
virtual int numSlowPaths() const = 0;
friend class SkPictureGpuAnalyzer;
friend struct SkPathCounter;
// V35: Store SkRect (rather then width & height) in header

View File

@ -8,59 +8,6 @@
#ifndef SkPictureAnalyzer_DEFINED
#define SkPictureAnalyzer_DEFINED
#include "SkCanvas.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
#include "SkTypes.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
class SkPath;
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 analyzePicture(const SkPicture*);
/**
* Process an explicit clipPath op.
*/
void analyzeClipPath(const SkPath&, SkClipOp, bool doAntiAlias);
/**
* 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;
/**
* Returns the number of commands which are slow to draw on the GPU, capped at the predicate
* max.
*/
uint32_t numSlowGpuCommands() { return fNumSlowPaths; }
private:
uint32_t fNumSlowPaths;
typedef SkNoncopyable INHERITED;
};
#endif // SK_SUPPORT_GPU
// This class is gone -- please remove sites that want to include it
#endif // SkPictureAnalyzer_DEFINED

View File

@ -53,14 +53,7 @@ void SkBigPicture::partialPlayback(SkCanvas* canvas,
initialCTM);
}
const SkBigPicture::Analysis& SkBigPicture::analysis() const {
fAnalysisOnce([this] { fAnalysis.init(*fRecord); });
return fAnalysis;
}
SkRect SkBigPicture::cullRect() const { return fCullRect; }
bool SkBigPicture::willPlayBackBitmaps() const { return this->analysis().fWillPlaybackBitmaps; }
int SkBigPicture::numSlowPaths() const { return this->analysis().fNumSlowPathsAndDashEffects; }
int SkBigPicture::approximateOpCount() const { return fRecord->count(); }
size_t SkBigPicture::approximateBytesUsed() const {
size_t bytes = sizeof(*this) + fRecord->bytesUsed() + fApproxBytesUsedBySubPictures;
@ -76,17 +69,3 @@ SkPicture const* const* SkBigPicture::drawablePicts() const {
return fDrawablePicts ? fDrawablePicts->begin() : nullptr;
}
void SkBigPicture::Analysis::init(const SkRecord& record) {
TRACE_EVENT0("skia", TRACE_FUNC);
SkBitmapHunter bitmap;
SkPathCounter path;
bool hasBitmap = false;
for (int i = 0; i < record.count(); i++) {
hasBitmap = hasBitmap || record.visit(i, bitmap);
record.visit(i, path);
}
fWillPlaybackBitmaps = hasBitmap;
fNumSlowPathsAndDashEffects = SkTMin<int>(path.fNumSlowPathsAndDashEffects, 255);
}

View File

@ -43,7 +43,6 @@ public:
// SkPicture overrides
void playback(SkCanvas*, AbortCallback*) const override;
SkRect cullRect() const override;
bool willPlayBackBitmaps() const override;
int approximateOpCount() const override;
size_t approximateBytesUsed() const override;
const SkBigPicture* asSkBigPicture() const override { return this; }
@ -58,24 +57,11 @@ public:
const SkRecord* record() const { return fRecord.get(); }
private:
struct Analysis {
void init(const SkRecord&);
bool suitableForGpuRasterization(const char** reason) const;
uint8_t fNumSlowPathsAndDashEffects;
bool fWillPlaybackBitmaps : 1;
};
int numSlowPaths() const override;
const Analysis& analysis() const;
int drawableCount() const;
SkPicture const* const* drawablePicts() const;
const SkRect fCullRect;
const size_t fApproxBytesUsedBySubPictures;
mutable SkOnce fAnalysisOnce;
mutable Analysis fAnalysis;
sk_sp<const SkRecord> fRecord;
std::unique_ptr<const SnapshotArray> fDrawablePicts;
sk_sp<const SkBBoxHierarchy> fBBH;

View File

@ -23,8 +23,6 @@ public:
size_t approximateBytesUsed() const override { return sizeof(*this); }
int approximateOpCount() const override { return 0; }
SkRect cullRect() const override { return SkRect::MakeEmpty(); }
int numSlowPaths() const override { return 0; }
bool willPlayBackBitmaps() const override { return false; }
};
// Calculate conservative bounds for each type of draw op that can be its own mini picture.
@ -58,12 +56,6 @@ public:
size_t approximateBytesUsed() const override { return sizeof(*this); }
int approximateOpCount() const override { return 1; }
SkRect cullRect() const override { return fCull; }
bool willPlayBackBitmaps() const override { return SkBitmapHunter()(fOp); }
int numSlowPaths() const override {
SkPathCounter counter;
counter(fOp);
return counter.fNumSlowPathsAndDashEffects;
}
private:
SkRect fCull;

View File

@ -335,16 +335,6 @@ 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)."; }
return false;
}
return true;
}
#endif
// Global setting to disable security precautions for serialization.
bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
return g_AllPictureIOSecurityPrecautionsEnabled;

View File

@ -1,65 +0,0 @@
/*
* 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 "SkPath.h"
#include "SkPicture.h"
#include "SkPictureAnalyzer.h"
#include "SkPictureCommon.h"
#include "SkRecords.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->analyzePicture(picture.get());
}
void SkPictureGpuAnalyzer::analyzePicture(const SkPicture* picture) {
if (!picture) {
return;
}
fNumSlowPaths += picture->numSlowPaths();
}
void SkPictureGpuAnalyzer::analyzeClipPath(const SkPath& path, SkClipOp op, bool doAntiAlias) {
const SkRecords::ClipPath clipOp = {
SkIRect::MakeEmpty(), // Willie don't care.
path,
SkRecords::ClipOpAndAA(op, doAntiAlias)
};
SkPathCounter counter;
counter(clipOp);
fNumSlowPaths += counter.fNumSlowPathsAndDashEffects;
}
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

View File

@ -4,12 +4,12 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPictureCommon_DEFINED
#define SkPictureCommon_DEFINED
// Some shared code used by both SkBigPicture and SkMiniPicture.
// SkTextHunter -- SkRecord visitor that returns true when the op draws text.
// SkBitmapHunter -- SkRecord visitor that returns true when the op draws a bitmap or image.
// SkPathCounter -- SkRecord visitor that counts paths that draw slowly on the GPU.
#include "SkPathEffect.h"
@ -17,58 +17,6 @@
#include "SkShader.h"
#include "SkTLogic.h"
// N.B. This name is slightly historical: hunting season is now open for SkImages too.
struct SkBitmapHunter {
// Some ops have a paint, some have an optional paint. Either way, get back a pointer.
static const SkPaint* AsPtr(const SkPaint& p) { return &p; }
static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; }
// Main entry for visitor:
// If the op is a DrawPicture, recurse.
// If the op has a bitmap or image directly, return true.
// If the op has a paint and the paint has a bitmap, return true.
// Otherwise, return false.
bool operator()(const SkRecords::DrawPicture& op) { return op.picture->willPlayBackBitmaps(); }
bool operator()(const SkRecords::DrawDrawable&) { /*TODO*/ return false; }
template <typename T>
bool operator()(const T& op) { return CheckBitmap(op); }
// If the op is tagged as having an image, return true.
template <typename T>
static SK_WHEN(T::kTags & SkRecords::kHasImage_Tag, bool) CheckBitmap(const T&) {
return true;
}
// If not, look for one in its paint (if it has a paint).
template <typename T>
static SK_WHEN(!(T::kTags & SkRecords::kHasImage_Tag), bool) CheckBitmap(const T& op) {
return CheckPaint(op);
}
// Most draws-type ops have paints.
template <typename T>
static SK_WHEN(T::kTags & SkRecords::kHasPaint_Tag, bool) CheckPaint(const T& op) {
return PaintHasBitmap(AsPtr(op.paint));
}
template <typename T>
static SK_WHEN(!(T::kTags & SkRecords::kHasPaint_Tag), bool) CheckPaint(const T&) {
return false;
}
private:
static bool PaintHasBitmap(const SkPaint* paint) {
if (paint) {
const SkShader* shader = paint->getShader();
if (shader && shader->isAImage()) {
return true;
}
}
return false;
}
};
// TODO: might be nicer to have operator() return an int (the number of slow paths) ?
struct SkPathCounter {
// Some ops have a paint, some have an optional paint. Either way, get back a pointer.
@ -77,11 +25,6 @@ struct SkPathCounter {
SkPathCounter() : fNumSlowPathsAndDashEffects(0) {}
// Recurse into nested pictures.
void operator()(const SkRecords::DrawPicture& op) {
fNumSlowPathsAndDashEffects += op.picture->numSlowPaths();
}
void checkPaint(const SkPaint* paint) {
if (paint && paint->getPathEffect()) {
// Initially assume it's slow.

View File

@ -152,18 +152,6 @@ SkPictureData::~SkPictureData() {
delete fFactoryPlayback;
}
bool SkPictureData::containsBitmaps() const {
if (fBitmapImageCount > 0 || fImageCount > 0) {
return true;
}
for (int i = 0; i < fPictureCount; ++i) {
if (fPictureRefs[i]->willPlayBackBitmaps()) {
return true;
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

View File

@ -88,8 +88,6 @@ public:
void serialize(SkWStream*, const SkSerialProcs&, SkRefCntSet*) const;
void flatten(SkWriteBuffer&) const;
bool containsBitmaps() const;
bool hasText() const { return fContentInfo.hasText(); }
int opCount() const { return fContentInfo.numOperations(); }

View File

@ -19,7 +19,6 @@
#include "SkMD5.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkPictureAnalyzer.h"
#include "SkPictureRecorder.h"
#include "SkPixelRef.h"
#include "SkMiniRecorder.h"
@ -43,50 +42,6 @@ static void make_bm(SkBitmap* bm, int w, int h, SkColor color, bool immutable) {
}
}
// For a while willPlayBackBitmaps() ignored SkImages and just looked for SkBitmaps.
static void test_images_are_found_by_willPlayBackBitmaps(skiatest::Reporter* reporter) {
// We just need _some_ SkImage
const SkPMColor pixel = 0;
const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
sk_sp<SkImage> image(SkImage::MakeRasterCopy(SkPixmap(info, &pixel, sizeof(pixel))));
SkPictureRecorder recorder;
recorder.beginRecording(100,100)->drawImage(image, 0,0);
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps());
}
/* Hit a few SkPicture::Analysis cases not handled elsewhere. */
static void test_analysis(skiatest::Reporter* reporter) {
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(100, 100);
{
canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ());
}
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps());
canvas = recorder.beginRecording(100, 100);
{
SkPaint paint;
// CreateBitmapShader is too smart for us; an empty (or 1x1) bitmap shader
// gets optimized into a non-bitmap form, so we create a 2x2 bitmap here.
SkBitmap bitmap;
bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2));
bitmap.eraseColor(SK_ColorBLUE);
*(bitmap.getAddr32(0, 0)) = SK_ColorGREEN;
paint.setShader(SkShader::MakeBitmapShader(bitmap, SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode));
REPORTER_ASSERT(reporter, paint.getShader()->isAImage());
canvas->drawRect(SkRect::MakeWH(10, 10), paint);
}
REPORTER_ASSERT(reporter, recorder.finishRecordingAsPicture()->willPlayBackBitmaps());
}
#ifdef SK_DEBUG
// Ensure that deleting an empty SkPicture does not assert. Asserts only fire
// in debug mode, so only run in debug mode.
@ -130,192 +85,6 @@ 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;
SkCanvas* canvas = recorder.beginRecording(100, 100);
{
SkPath path;
path.moveTo(0, 0);
path.lineTo(50, 50);
SkScalar intervals[] = { 1.0f, 1.0f };
sk_sp<SkPathEffect> dash(SkDashPathEffect::Make(intervals, 2, 0));
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setPathEffect(dash);
for (int i = 0; i < 50; ++i) {
canvas->drawPath(path, paint);
}
}
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
// path effects currently render an SkPicture undesireable for GPU rendering
const char *reason = nullptr;
REPORTER_ASSERT(reporter,
!SkPictureGpuAnalyzer(picture).suitableForGpuRasterization(&reason));
REPORTER_ASSERT(reporter, reason);
canvas = recorder.beginRecording(100, 100);
{
SkPath path;
path.moveTo(0, 0);
path.lineTo(0, 50);
path.lineTo(25, 25);
path.lineTo(50, 50);
path.lineTo(50, 0);
path.close();
REPORTER_ASSERT(reporter, !path.isConvex());
SkPaint paint;
paint.setAntiAlias(true);
for (int i = 0; i < 50; ++i) {
canvas->drawPath(path, paint);
}
}
picture = recorder.finishRecordingAsPicture();
// A lot of small AA concave paths should be fine for GPU rendering
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
canvas = recorder.beginRecording(100, 100);
{
SkPath path;
path.moveTo(0, 0);
path.lineTo(0, 100);
path.lineTo(50, 50);
path.lineTo(100, 100);
path.lineTo(100, 0);
path.close();
REPORTER_ASSERT(reporter, !path.isConvex());
SkPaint paint;
paint.setAntiAlias(true);
for (int i = 0; i < 50; ++i) {
canvas->drawPath(path, paint);
}
}
picture = recorder.finishRecordingAsPicture();
// A lot of large AA concave paths currently render an SkPicture undesireable for GPU rendering
REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
canvas = recorder.beginRecording(100, 100);
{
SkPath path;
path.moveTo(0, 0);
path.lineTo(0, 50);
path.lineTo(25, 25);
path.lineTo(50, 50);
path.lineTo(50, 0);
path.close();
REPORTER_ASSERT(reporter, !path.isConvex());
SkPaint paint;
paint.setAntiAlias(true);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(0);
for (int i = 0; i < 50; ++i) {
canvas->drawPath(path, paint);
}
}
picture = recorder.finishRecordingAsPicture();
// hairline stroked AA concave paths are fine for GPU rendering
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
canvas = recorder.beginRecording(100, 100);
{
SkPaint paint;
SkScalar intervals [] = { 10, 20 };
paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 25));
SkPoint points [2] = { { 0, 0 }, { 100, 0 } };
for (int i = 0; i < 50; ++i) {
canvas->drawPoints(SkCanvas::kLines_PointMode, 2, points, paint);
}
}
picture = recorder.finishRecordingAsPicture();
// fast-path dashed effects are fine for GPU rendering ...
REPORTER_ASSERT(reporter, SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
canvas = recorder.beginRecording(100, 100);
{
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);
}
}
picture = recorder.finishRecordingAsPicture();
// ... 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, kIntersect_SkClipOp, 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, kIntersect_SkClipOp, 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);
{
canvas->drawPicture(picture);
}
picture = recorder.finishRecordingAsPicture();
REPORTER_ASSERT(reporter, !SkPictureGpuAnalyzer(picture).suitableForGpuRasterization());
}
#endif // SK_SUPPORT_GPU
static void set_canvas_to_save_count_4(SkCanvas* canvas) {
canvas->restoreToCount(1);
canvas->save();
@ -452,36 +221,6 @@ DEF_TEST(PictureRecorder_replay, reporter) {
check_save_state(reporter, copy.get(), 2, 1, 3);
}
// (partially) check leakage of draw ops
{
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(10, 10);
SkRect r = SkRect::MakeWH(5, 5);
SkPaint p;
canvas->drawRect(r, p);
sk_sp<SkPicture> copy(SkPictureRecorderReplayTester::Copy(&recorder));
REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());
SkBitmap bm;
make_bm(&bm, 10, 10, SK_ColorRED, true);
r.offset(5.0f, 5.0f);
canvas->drawBitmapRect(bm, r, nullptr);
sk_sp<SkPicture> final(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, final->willPlayBackBitmaps());
REPORTER_ASSERT(reporter, copy->uniqueID() != final->uniqueID());
// The snapshot shouldn't pick up any operations added after it was made
REPORTER_ASSERT(reporter, !copy->willPlayBackBitmaps());
}
// Recreate the Android partialReplay test case
{
SkPictureRecorder recorder;
@ -782,48 +521,6 @@ static void test_clip_expansion(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, testCanvas.getClipCount() == 2);
}
static void test_hierarchical(skiatest::Reporter* reporter) {
SkBitmap bm;
make_bm(&bm, 10, 10, SK_ColorRED, true);
SkPictureRecorder recorder;
recorder.beginRecording(10, 10);
sk_sp<SkPicture> childPlain(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0
recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
sk_sp<SkPicture> childWithBitmap(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawPicture(childPlain);
sk_sp<SkPicture> parentPP(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawPicture(childWithBitmap);
sk_sp<SkPicture> parentPWB(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(childPlain);
sk_sp<SkPicture> parentWBP(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(childWithBitmap);
sk_sp<SkPicture> parentWBWB(recorder.finishRecordingAsPicture());
REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2
}
}
static void test_gen_id(skiatest::Reporter* reporter) {
SkPictureRecorder recorder;
@ -864,14 +561,8 @@ DEF_TEST(Picture, reporter) {
#endif
test_unbalanced_save_restores(reporter);
test_peephole();
#if SK_SUPPORT_GPU
test_gpu_veto(reporter);
#endif
test_images_are_found_by_willPlayBackBitmaps(reporter);
test_analysis(reporter);
test_clip_bound_opt(reporter);
test_clip_expansion(reporter);
test_hierarchical(reporter);
test_gen_id(reporter);
test_cull_rect_reset(reporter);
}
@ -1084,56 +775,6 @@ DEF_TEST(Picture_preserveCullRect, r) {
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.analyzePicture(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.analyzePicture(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, kIntersect_SkClipOp, false);
analyzer.analyzeClipPath(convexClip, kIntersect_SkClipOp, true);
analyzer.analyzeClipPath(concaveClip, kIntersect_SkClipOp, false);
}
REPORTER_ASSERT(r, analyzer.suitableForGpuRasterization());
for (int i = 0; i < 50; ++i) {
analyzer.analyzeClipPath(concaveClip, kIntersect_SkClipOp, true);
}
REPORTER_ASSERT(r, !analyzer.suitableForGpuRasterization());
}
#endif // SK_SUPPORT_GPU
// If we record bounded ops into a picture with a big cull and calculate the
// bounds of those ops, we should trim down the picture cull to the ops' bounds.

View File

@ -1,71 +0,0 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCommandLineFlags.h"
#include "SkPicture.h"
#include "SkPictureAnalyzer.h"
#include "SkPictureRecorder.h"
#include "SkStream.h"
DEFINE_string2(readFile, r, "", "skp file to process.");
DEFINE_bool2(quiet, q, false, "quiet");
// This tool just loads a single skp, replays into a new SkPicture (to
// regenerate the GPU-specific tracking information) and reports
// the value of the suitableForGpuRasterization method.
// Return codes:
static const int kSuccess = 0;
static const int kError = 1;
int main(int argc, char** argv) {
#if SK_SUPPORT_GPU
SkCommandLineFlags::SetUsage("Reports on an skp file's suitability for GPU rasterization");
SkCommandLineFlags::Parse(argc, argv);
if (FLAGS_readFile.count() != 1) {
if (!FLAGS_quiet) {
SkDebugf("Missing input file\n");
}
return kError;
}
SkFILEStream inputStream(FLAGS_readFile[0]);
if (!inputStream.isValid()) {
if (!FLAGS_quiet) {
SkDebugf("Couldn't open file\n");
}
return kError;
}
sk_sp<SkPicture> picture(SkPicture::MakeFromStream(&inputStream));
if (nullptr == picture) {
if (!FLAGS_quiet) {
SkDebugf("Could not read the SkPicture\n");
}
return kError;
}
// The SkPicture tracking information is only generated during recording
// an isn't serialized. Replay the picture to regenerated the tracking data.
SkPictureRecorder recorder;
picture->playback(recorder.beginRecording(picture->cullRect().width(),
picture->cullRect().height(),
nullptr, 0));
sk_sp<SkPicture> recorded(recorder.finishRecordingAsPicture());
if (SkPictureGpuAnalyzer(recorded).suitableForGpuRasterization(nullptr)) {
SkDebugf("suitable\n");
} else {
SkDebugf("unsuitable\n");
}
return kSuccess;
#else
SkDebugf("gpuveto is only useful when GPU rendering is enabled\n");
return kError;
#endif
}