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
This commit is contained in:
hendrikw 2014-08-08 10:44:33 -07:00 committed by Commit bot
parent f4078ad1ec
commit afdada2eab
7 changed files with 164 additions and 109 deletions

View File

@ -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',

View File

@ -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);
}

View File

@ -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

View File

@ -670,36 +670,7 @@ const SkPicture::OperationList* SkPictureData::getActiveOps(const SkIRect& query
#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;
return fContentInfo.suitableForGpuRasterization(context, reason, sampleCount);
}
bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char **reason,

View File

@ -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 @@ struct SkPictInfo {
// 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

View File

@ -972,20 +972,14 @@ void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts
#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::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
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::getFlatPaintData(const SkPaint& paint) {
}
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::addRegion(const SkRegion& region) {
}
void SkPictureRecord::addText(const void* text, size_t byteLength) {
fContentInfo.onDrawText();
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
#endif

View File

@ -146,6 +146,7 @@ private:
size_t offset = fWriter.bytesWritten();
this->predrawNotify();
fContentInfo.addOperation();
#ifdef SK_DEBUG_TRACE
SkDebugf("add %s\n", DrawTypeToString(drawType));