зеркало из https://github.com/mozilla/moz-skia.git
First pass at GPU veto
As a short term solution this CL collects information during the recording process for use in suitableForGpuRasterization. BUG=366495 R=bsalomon@google.com, reed@google.com, alokp@chromium.org Author: robertphillips@google.com Review URL: https://codereview.chromium.org/251533004 git-svn-id: http://skia.googlecode.com/svn/trunk@14368 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
d70fa2013a
Коммит
e2cb12a82a
|
@ -365,6 +365,67 @@ private:
|
|||
|
||||
SkAutoTUnref<SkPathHeap> fPathHeap; // reference counted
|
||||
|
||||
// ContentInfo is not serialized! It is intended solely for use
|
||||
// with suitableForGpuRasterization.
|
||||
class ContentInfo {
|
||||
public:
|
||||
ContentInfo() { this->reset(); }
|
||||
|
||||
ContentInfo(const ContentInfo& src) { this->set(src); }
|
||||
|
||||
void set(const ContentInfo& src) {
|
||||
fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
|
||||
fNumAAConcavePaths = src.fNumAAConcavePaths;
|
||||
fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
fNumPaintWithPathEffectUses = 0;
|
||||
fNumAAConcavePaths = 0;
|
||||
fNumAAHairlineConcavePaths = 0;
|
||||
}
|
||||
|
||||
void swap(ContentInfo* other) {
|
||||
SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
|
||||
SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
|
||||
SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
|
||||
}
|
||||
|
||||
// This field is incremented every time a paint with a path effect is
|
||||
// used (i.e., it is not a de-duplicated count)
|
||||
int fNumPaintWithPathEffectUses;
|
||||
// This field is incremented every time an anti-aliased drawPath call is
|
||||
// issued with a concave path
|
||||
int fNumAAConcavePaths;
|
||||
// This field is incremented every time a drawPath call is
|
||||
// issued for a hairline stroked concave path.
|
||||
int fNumAAHairlineConcavePaths;
|
||||
};
|
||||
|
||||
ContentInfo fContentInfo;
|
||||
|
||||
void incPaintWithPathEffectUses() {
|
||||
++fContentInfo.fNumPaintWithPathEffectUses;
|
||||
}
|
||||
int numPaintWithPathEffectUses() const {
|
||||
return fContentInfo.fNumPaintWithPathEffectUses;
|
||||
}
|
||||
|
||||
void incAAConcavePaths() {
|
||||
++fContentInfo.fNumAAConcavePaths;
|
||||
}
|
||||
int numAAConcavePaths() const {
|
||||
return fContentInfo.fNumAAConcavePaths;
|
||||
}
|
||||
|
||||
void incAAHairlineConcavePaths() {
|
||||
++fContentInfo.fNumAAHairlineConcavePaths;
|
||||
SkASSERT(fContentInfo.fNumAAHairlineConcavePaths <= fContentInfo.fNumAAConcavePaths);
|
||||
}
|
||||
int numAAHairlineConcavePaths() const {
|
||||
return fContentInfo.fNumAAHairlineConcavePaths;
|
||||
}
|
||||
|
||||
const SkPath& getPath(int index) const;
|
||||
int addPathToHeap(const SkPath& path);
|
||||
|
||||
|
|
|
@ -122,17 +122,18 @@ static void validateMatrix(const SkMatrix* matrix) {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkPicture::SkPicture() {
|
||||
SkPicture::SkPicture()
|
||||
: fAccelData(NULL) {
|
||||
this->needsNewGenID();
|
||||
fRecord = NULL;
|
||||
fPlayback = NULL;
|
||||
fWidth = fHeight = 0;
|
||||
fAccelData = NULL;
|
||||
}
|
||||
|
||||
SkPicture::SkPicture(const SkPicture& src)
|
||||
: INHERITED()
|
||||
, fAccelData(NULL) {
|
||||
, fAccelData(NULL)
|
||||
, fContentInfo(src.fContentInfo) {
|
||||
this->needsNewGenID();
|
||||
fWidth = src.fWidth;
|
||||
fHeight = src.fHeight;
|
||||
|
@ -207,6 +208,7 @@ void SkPicture::swap(SkPicture& other) {
|
|||
SkTSwap(fWidth, other.fWidth);
|
||||
SkTSwap(fHeight, other.fHeight);
|
||||
fPathHeap.swap(&other.fPathHeap);
|
||||
fContentInfo.swap(&other.fContentInfo);
|
||||
}
|
||||
|
||||
SkPicture* SkPicture::clone() const {
|
||||
|
@ -228,6 +230,7 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
|
|||
clone->fHeight = fHeight;
|
||||
SkSafeSetNull(clone->fRecord);
|
||||
SkDELETE(clone->fPlayback);
|
||||
clone->fContentInfo.set(fContentInfo);
|
||||
|
||||
/* We want to copy the src's playback. However, if that hasn't been built
|
||||
yet, we need to fake a call to endRecording() without actually calling
|
||||
|
@ -271,6 +274,7 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
|
|||
}
|
||||
SkSafeUnref(fAccelData);
|
||||
SkSafeSetNull(fRecord);
|
||||
fContentInfo.reset();
|
||||
|
||||
this->needsNewGenID();
|
||||
|
||||
|
@ -305,6 +309,7 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
|
|||
SkSafeUnref(fAccelData);
|
||||
SkSafeSetNull(fRecord);
|
||||
SkASSERT(NULL == fPathHeap);
|
||||
fContentInfo.reset();
|
||||
|
||||
this->needsNewGenID();
|
||||
|
||||
|
@ -602,8 +607,14 @@ void SkPicture::flatten(SkWriteBuffer& buffer) const {
|
|||
|
||||
#if SK_SUPPORT_GPU
|
||||
bool SkPicture::suitableForGpuRasterization(GrContext* context) const {
|
||||
// Stub for now; never veto GPu rasterization.
|
||||
return true;
|
||||
// TODO: the heuristic used here needs to be refined
|
||||
static const int kNumPaintWithPathEffectUsesTol = 1;
|
||||
static const int kNumAAConcavePaths = 5;
|
||||
|
||||
SkASSERT(this->numAAHairlineConcavePaths() <= this->numAAConcavePaths());
|
||||
|
||||
return this->numPaintWithPathEffectUses() < kNumPaintWithPathEffectUsesTol &&
|
||||
(this->numAAConcavePaths()-this->numAAHairlineConcavePaths()) < kNumAAConcavePaths;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1065,6 +1065,15 @@ void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
|
|||
|
||||
void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
|
||||
if (paint.isAntiAlias() && !path.isConvex()) {
|
||||
fPicture->incAAConcavePaths();
|
||||
|
||||
if (SkPaint::kStroke_Style == paint.getStyle() &&
|
||||
0 == paint.getStrokeWidth()) {
|
||||
fPicture->incAAHairlineConcavePaths();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
|
||||
fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
|
||||
#endif
|
||||
|
@ -1578,6 +1587,10 @@ const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
|
|||
}
|
||||
|
||||
const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
|
||||
if (NULL != paint && NULL != paint->getPathEffect()) {
|
||||
fPicture->incPaintWithPathEffectUses();
|
||||
}
|
||||
|
||||
const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
|
||||
this->addFlatPaint(data);
|
||||
return data;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "SkBitmapDevice.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkDashPathEffect.h"
|
||||
#include "SkData.h"
|
||||
#include "SkDecodingImageGenerator.h"
|
||||
#include "SkError.h"
|
||||
|
@ -694,6 +695,76 @@ static void rand_op(SkCanvas* canvas, SkRandom& rand) {
|
|||
}
|
||||
}
|
||||
|
||||
static void test_gpu_veto(skiatest::Reporter* reporter) {
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
SkCanvas* canvas = recorder.beginRecording(100, 100, NULL, 0);
|
||||
{
|
||||
SkPath path;
|
||||
path.moveTo(0, 0);
|
||||
path.lineTo(50, 50);
|
||||
|
||||
SkScalar intervals[] = { 1.0f, 1.0f };
|
||||
SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, 2, 0));
|
||||
|
||||
SkPaint paint;
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setPathEffect(dash);
|
||||
|
||||
canvas->drawPath(path, paint);
|
||||
}
|
||||
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
|
||||
// path effects currently render an SkPicture undesireable for GPU rendering
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
|
||||
|
||||
canvas = recorder.beginRecording(100, 100, NULL, 0);
|
||||
{
|
||||
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.reset(recorder.endRecording());
|
||||
// A lot of AA concave paths currently render an SkPicture undesireable for GPU rendering
|
||||
REPORTER_ASSERT(reporter, !picture->suitableForGpuRasterization(NULL));
|
||||
|
||||
canvas = recorder.beginRecording(100, 100, NULL, 0);
|
||||
{
|
||||
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.reset(recorder.endRecording());
|
||||
// hairline stroked AA concave paths are fine for GPU rendering
|
||||
REPORTER_ASSERT(reporter, picture->suitableForGpuRasterization(NULL));
|
||||
}
|
||||
|
||||
static void set_canvas_to_save_count_4(SkCanvas* canvas) {
|
||||
canvas->restoreToCount(1);
|
||||
canvas->save();
|
||||
|
@ -1197,6 +1268,7 @@ DEF_TEST(Picture, reporter) {
|
|||
#endif
|
||||
test_unbalanced_save_restores(reporter);
|
||||
test_peephole();
|
||||
test_gpu_veto(reporter);
|
||||
test_gatherpixelrefs(reporter);
|
||||
test_gatherpixelrefsandrects(reporter);
|
||||
test_bitmap_with_encoded_data(reporter);
|
||||
|
|
|
@ -14,6 +14,7 @@ DEFINE_string2(input, i, "", "skp on which to report");
|
|||
DEFINE_bool2(version, v, true, "version");
|
||||
DEFINE_bool2(width, w, true, "width");
|
||||
DEFINE_bool2(height, h, true, "height");
|
||||
DEFINE_bool2(flags, f, true, "flags");
|
||||
DEFINE_bool2(tags, t, true, "tags");
|
||||
DEFINE_bool2(quiet, q, false, "quiet");
|
||||
|
||||
|
@ -64,6 +65,9 @@ int tool_main(int argc, char** argv) {
|
|||
if (FLAGS_height && !FLAGS_quiet) {
|
||||
SkDebugf("Height: %d\n", info.fHeight);
|
||||
}
|
||||
if (FLAGS_flags && !FLAGS_quiet) {
|
||||
SkDebugf("Flags: 0x%x\n", info.fFlags);
|
||||
}
|
||||
|
||||
if (!stream.readBool()) {
|
||||
// If we read true there's a picture playback object flattened
|
||||
|
|
Загрузка…
Ссылка в новой задаче