Moved SkPictureContentInfo into its own file. It now tracks the number of skia
operations (maybe, I'm not 100% sure I'm doing this right yet) and the number
of text draws. I also moved some of the gpu logic out of SkPictureRecord and
into SkPictureContentInfo,
http://code.google.com/p/chromium/issues/detail?id=396908
http://code.google.com/p/chromium/issues/detail?id=397198
http://code.google.com/p/chromium/issues/detail?id=399728
BUG=396908
R=nduca@chromium.org, mtklein@chromium.org, robertphillips@google.com, mtklein@google.com
Author: hendrikw@chromium.org
Review URL: https://codereview.chromium.org/435093003
diff --git a/gyp/core.gypi b/gyp/core.gypi
index da43a05..60d7859 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -130,6 +130,8 @@
'<(skia_src_path)/core/SkPathMeasure.cpp',
'<(skia_src_path)/core/SkPathRef.cpp',
'<(skia_src_path)/core/SkPicture.cpp',
+ '<(skia_src_path)/core/SkPictureContentInfo.cpp',
+ '<(skia_src_path)/core/SkPictureContentInfo.h',
'<(skia_src_path)/core/SkPictureData.cpp',
'<(skia_src_path)/core/SkPictureData.h',
'<(skia_src_path)/core/SkPictureFlat.cpp',
diff --git a/src/core/SkPictureContentInfo.cpp b/src/core/SkPictureContentInfo.cpp
new file mode 100644
index 0000000..8185d85
--- /dev/null
+++ b/src/core/SkPictureContentInfo.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "SkPaint.h"
+#include "SkPathEffect.h"
+#include "SkPictureContentInfo.h"
+
+bool SkPictureContentInfo::suitableForGpuRasterization(GrContext* context, const char **reason,
+ int sampleCount) const {
+ // TODO: the heuristic used here needs to be refined
+ static const int kNumPaintWithPathEffectUsesTol = 1;
+ static const int kNumAAConcavePaths = 5;
+
+ SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
+
+ int numNonDashedPathEffects = fNumPaintWithPathEffectUses -
+ fNumFastPathDashEffects;
+
+ bool suitableForDash = (0 == fNumPaintWithPathEffectUses) ||
+ (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
+ && 0 == sampleCount);
+
+ bool ret = suitableForDash &&
+ (fNumAAConcavePaths - fNumAAHairlineConcavePaths)
+ < kNumAAConcavePaths;
+ if (!ret && NULL != reason) {
+ if (!suitableForDash) {
+ if (0 != sampleCount) {
+ *reason = "Can't use multisample on dash effect.";
+ } else {
+ *reason = "Too many non dashed path effects.";
+ }
+ } else if ((fNumAAConcavePaths - fNumAAHairlineConcavePaths)
+ >= kNumAAConcavePaths) {
+ *reason = "Too many anti-aliased concave paths.";
+ } else {
+ *reason = "Unknown reason for GPU unsuitability.";
+ }
+ }
+ return ret;
+}
+
+void SkPictureContentInfo::onDrawPoints(size_t count, const SkPaint& paint) {
+ if (paint.getPathEffect() != NULL) {
+ SkPathEffect::DashInfo info;
+ SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
+ if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
+ SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
+ ++fNumFastPathDashEffects;
+ }
+ }
+}
+
+void SkPictureContentInfo::onDrawPath(const SkPath& path, const SkPaint& paint) {
+ if (paint.isAntiAlias() && !path.isConvex()) {
+ ++fNumAAConcavePaths;
+
+ if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
+ ++fNumAAHairlineConcavePaths;
+ }
+ }
+}
+
+void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) {
+ if (NULL != paint && NULL != paint->getPathEffect()) {
+ ++fNumPaintWithPathEffectUses;
+ }
+}
+
+void SkPictureContentInfo::set(const SkPictureContentInfo& src) {
+ fNumOperations = src.fNumOperations;
+ fNumTexts = src.fNumTexts;
+ fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
+ fNumFastPathDashEffects = src.fNumFastPathDashEffects;
+ fNumAAConcavePaths = src.fNumAAConcavePaths;
+ fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
+}
+
+void SkPictureContentInfo::reset() {
+ fNumOperations = 0;
+ fNumTexts = 0;
+ fNumPaintWithPathEffectUses = 0;
+ fNumFastPathDashEffects = 0;
+ fNumAAConcavePaths = 0;
+ fNumAAHairlineConcavePaths = 0;
+}
+
+void SkPictureContentInfo::swap(SkPictureContentInfo* other) {
+ SkTSwap(fNumOperations, other->fNumOperations);
+ SkTSwap(fNumTexts, other->fNumTexts);
+ SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
+ SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
+ SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
+ SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
+}
diff --git a/src/core/SkPictureContentInfo.h b/src/core/SkPictureContentInfo.h
new file mode 100644
index 0000000..cfeedcf
--- /dev/null
+++ b/src/core/SkPictureContentInfo.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureContentInfo_DEFINED
+#define SkPictureContentInfo_DEFINED
+
+class GrContext;
+
+class SkPictureContentInfo {
+public:
+ SkPictureContentInfo() { this->reset(); }
+ SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); }
+
+ int numOperations() const { return fNumOperations; }
+ bool hasText() const { return fNumTexts > 0; }
+ bool suitableForGpuRasterization(GrContext* context, const char **reason,
+ int sampleCount) const;
+
+ void addOperation() { ++fNumOperations; }
+
+ void onDrawPoints(size_t count, const SkPaint& paint);
+ void onDrawPath(const SkPath& path, const SkPaint& paint);
+ void onAddPaintPtr(const SkPaint* paint);
+ void onDrawText() { ++fNumTexts; }
+
+ void set(const SkPictureContentInfo& src);
+ void reset();
+ void swap(SkPictureContentInfo* other);
+
+private:
+ // Raw count of operations in the picture
+ int fNumOperations;
+ // Count of all forms of drawText
+ int fNumTexts;
+
+ // 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 a paint with a path effect that is
+ // dashed, we are drawing a line, and we can use the gpu fast path
+ int fNumFastPathDashEffects;
+ // 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;
+};
+
+#endif
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 1553462..123c414 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -669,37 +669,8 @@
#if SK_SUPPORT_GPU
bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
- int sampleCount) const {
- // TODO: the heuristic used here needs to be refined
- static const int kNumPaintWithPathEffectUsesTol = 1;
- static const int kNumAAConcavePaths = 5;
-
- SkASSERT(fContentInfo.numAAHairlineConcavePaths() <= fContentInfo.numAAConcavePaths());
-
- int numNonDashedPathEffects = fContentInfo.numPaintWithPathEffectUses() -
- fContentInfo.numFastPathDashEffects();
-
- bool suitableForDash = (0 == fContentInfo.numPaintWithPathEffectUses()) ||
- (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
- && 0 == sampleCount);
-
- bool ret = suitableForDash &&
- (fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
- < kNumAAConcavePaths;
- if (!ret && NULL != reason) {
- if (!suitableForDash) {
- if (0 != sampleCount) {
- *reason = "Can't use multisample on dash effect.";
- } else {
- *reason = "Too many non dashed path effects.";
- }
- } else if ((fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
- >= kNumAAConcavePaths)
- *reason = "Too many anti-aliased concave paths.";
- else
- *reason = "Unknown reason for GPU unsuitability.";
- }
- return ret;
+ int sampleCount) const {
+ return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
}
bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,
diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h
index 6ea0b18..c1cfba3 100644
--- a/src/core/SkPictureData.h
+++ b/src/core/SkPictureData.h
@@ -11,6 +11,7 @@
#include "SkBitmap.h"
#include "SkPathHeap.h"
#include "SkPicture.h"
+#include "SkPictureContentInfo.h"
#include "SkPictureFlat.h"
#include "SkPictureStateTree.h"
@@ -55,65 +56,6 @@
// Always write this guy last (with no length field afterwards)
#define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
-// SkPictureContentInfo is not serialized! It is intended solely for use
-// with suitableForGpuRasterization.
-class SkPictureContentInfo {
-public:
- SkPictureContentInfo() { this->reset(); }
-
- SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); }
-
- void set(const SkPictureContentInfo& src) {
- fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
- fNumFastPathDashEffects = src.fNumFastPathDashEffects;
- fNumAAConcavePaths = src.fNumAAConcavePaths;
- fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
- }
-
- void reset() {
- fNumPaintWithPathEffectUses = 0;
- fNumFastPathDashEffects = 0;
- fNumAAConcavePaths = 0;
- fNumAAHairlineConcavePaths = 0;
- }
-
- void swap(SkPictureContentInfo* other) {
- SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
- SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
- SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
- SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
- }
-
- void incPaintWithPathEffectUses() { ++fNumPaintWithPathEffectUses; }
- int numPaintWithPathEffectUses() const { return fNumPaintWithPathEffectUses; }
-
- void incFastPathDashEffects() { ++fNumFastPathDashEffects; }
- int numFastPathDashEffects() const { return fNumFastPathDashEffects; }
-
- void incAAConcavePaths() { ++fNumAAConcavePaths; }
- int numAAConcavePaths() const { return fNumAAConcavePaths; }
-
- void incAAHairlineConcavePaths() {
- ++fNumAAHairlineConcavePaths;
- SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
- }
- int numAAHairlineConcavePaths() const { return fNumAAHairlineConcavePaths; }
-
-private:
- // 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 a paint with a path effect that is
- // dashed, we are drawing a line, and we can use the gpu fast path
- int fNumFastPathDashEffects;
- // 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;
-};
-
#ifdef SK_SUPPORT_LEGACY_PICTURE_CLONE
/**
* Container for data that is needed to deep copy a SkPicture. The container
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 72c537b..31a66ab 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -972,20 +972,14 @@
#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
#endif
+ fContentInfo.onDrawPoints(count, paint);
// op + paint index + mode + count + point data
size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.bytesWritten());
this->addPaint(paint);
- if (paint.getPathEffect() != NULL) {
- SkPathEffect::DashInfo info;
- SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
- if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
- SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
- fContentInfo.incFastPathDashEffects();
- }
- }
+
this->addInt(mode);
this->addInt(SkToInt(count));
fWriter.writeMul4(pts, count * sizeof(SkPoint));
@@ -1062,14 +1056,7 @@
void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
- if (paint.isAntiAlias() && !path.isConvex()) {
- fContentInfo.incAAConcavePaths();
-
- if (SkPaint::kStroke_Style == paint.getStyle() &&
- 0 == paint.getStrokeWidth()) {
- fContentInfo.incAAHairlineConcavePaths();
- }
- }
+ fContentInfo.onDrawPath(path, paint);
#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
@@ -1600,9 +1587,7 @@
}
const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
- if (NULL != paint && NULL != paint->getPathEffect()) {
- fContentInfo.incPaintWithPathEffectUses();
- }
+ fContentInfo.onAddPaintPtr(paint);
const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
this->addFlatPaint(data);
@@ -1704,6 +1689,7 @@
}
void SkPictureRecord::addText(const void* text, size_t byteLength) {
+ fContentInfo.onDrawText();
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
#endif
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 140558d..57e6008 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -146,6 +146,7 @@
size_t offset = fWriter.bytesWritten();
this->predrawNotify();
+ fContentInfo.addOperation();
#ifdef SK_DEBUG_TRACE
SkDebugf("add %s\n", DrawTypeToString(drawType));