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:
parent
297d6efe85
commit
b60c5ebf04
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user