0

cc: Merge GatherPixelRefs and AnalyzeInRect

Both GatherPixelRefs and AnalyzeInRect use the same loop,
and a similar canvas to do their work. It makes sense to
merge the two so part of the work is not replicated.


BUG=179552


Review URL: https://chromiumcodereview.appspot.com/12388095

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188879 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
vmpstr@chromium.org
2013-03-18 23:37:39 +00:00
parent cbdd731695
commit 62fa2256d8
6 changed files with 239 additions and 3 deletions

@ -240,6 +240,7 @@ void PicturePileImpl::AnalyzeInRect(const gfx::Rect& content_rect,
analysis->is_transparent = canvas.isTransparent();
analysis->is_solid_color = canvas.getColorIfSolid(&analysis->solid_color);
analysis->is_cheap_to_raster = canvas.isCheap();
canvas.consumeLazyPixelRefs(&analysis->lazy_pixel_refs);
}
PicturePileImpl::Analysis::Analysis() :
@ -248,4 +249,7 @@ PicturePileImpl::Analysis::Analysis() :
is_cheap_to_raster(false) {
}
PicturePileImpl::Analysis::~Analysis() {
}
} // namespace cc

@ -10,6 +10,7 @@
#include "cc/base/cc_export.h"
#include "cc/resources/picture_pile_base.h"
#include "skia/ext/analysis_canvas.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkPicture.h"
@ -43,11 +44,14 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
struct Analysis {
Analysis();
~Analysis();
bool is_solid_color;
bool is_transparent;
bool is_cheap_to_raster;
SkColor solid_color;
skia::AnalysisCanvas::LazyPixelRefList lazy_pixel_refs;
};
void AnalyzeInRect(const gfx::Rect& content_rect,

@ -728,6 +728,9 @@ void TileManager::AnalyzeTile(Tile* tile) {
managed_tile_state.picture_pile_analysis.is_transparent &=
use_color_estimator_;
managed_tile_state.picture_pile_analyzed = true;
managed_tile_state.need_to_gather_pixel_refs = false;
managed_tile_state.pending_pixel_refs.swap(
managed_tile_state.picture_pile_analysis.lazy_pixel_refs);
if (managed_tile_state.picture_pile_analysis.is_solid_color) {
tile->drawing_info().set_solid_color(

@ -7,6 +7,7 @@
#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkDraw.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/src/core/SkRasterClip.h"
#include "ui/gfx/rect_conversions.h"
@ -17,6 +18,10 @@ namespace {
// 25x as long as Z620.
const int gPictureCostThreshold = 1000;
// URI label for a lazily decoded SkPixelRef.
const char kLabelLazyDecoded[] = "lazy";
const int kLabelLazyDecodedLength = 4;
static bool isSolidColorPaint(const SkPaint& paint) {
SkXfermode::Mode xferMode;
@ -111,6 +116,52 @@ void AnalysisDevice::setForceNotTransparent(bool flag) {
isTransparent_ = false;
}
void AnalysisDevice::addPixelRefIfLazy(SkPixelRef* pixelRef) {
if (!pixelRef)
return;
uint32_t genID = pixelRef->getGenerationID();
// If this ID exists (whether it is lazy pixel ref or not),
// we can return early.
std::pair<IdSet::iterator, bool> insertionResult =
existingPixelRefIDs_.insert(genID);
if (!insertionResult.second)
return;
if (pixelRef->getURI() &&
!strncmp(pixelRef->getURI(),
kLabelLazyDecoded,
kLabelLazyDecodedLength)) {
lazyPixelRefs_.push_back(static_cast<skia::LazyPixelRef*>(pixelRef));
}
}
void AnalysisDevice::addBitmap(const SkBitmap& bitmap) {
addPixelRefIfLazy(bitmap.pixelRef());
}
void AnalysisDevice::addBitmapFromPaint(const SkPaint& paint) {
SkShader* shader = paint.getShader();
if (shader) {
SkBitmap bitmap;
// Check whether the shader is a gradient in order to short-circuit
// call to asABitmap to prevent generation of bitmaps from
// gradient shaders, which implement asABitmap.
if (SkShader::kNone_GradientType == shader->asAGradient(NULL) &&
SkShader::kNone_BitmapType != shader->asABitmap(&bitmap, NULL, NULL)) {
addPixelRefIfLazy(bitmap.pixelRef());
}
}
}
void AnalysisDevice::consumeLazyPixelRefs(LazyPixelRefList* pixelRefs) {
DCHECK(pixelRefs);
DCHECK(pixelRefs->empty());
lazyPixelRefs_.swap(*pixelRefs);
existingPixelRefIDs_.clear();
}
void AnalysisDevice::clear(SkColor color) {
++estimatedCost_;
@ -129,6 +180,7 @@ void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) {
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode,
@ -137,6 +189,7 @@ void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
@ -147,7 +200,7 @@ void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
estimatedCost_ += 300;
}
++estimatedCost_;
addBitmapFromPaint(paint);
bool doesCoverCanvas = isFullQuad(draw,
SkRect::MakeWH(width(), height()),
rect);
@ -195,6 +248,7 @@ void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
@ -210,6 +264,7 @@ void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
@ -218,6 +273,7 @@ void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmap(bitmap);
}
void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
@ -225,9 +281,10 @@ void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmap(bitmap);
}
void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&,
void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
const SkRect* srcOrNull, const SkRect& dst,
const SkPaint& paint) {
++estimatedCost_;
@ -236,6 +293,7 @@ void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&,
// but reset solid color to false.
drawRect(draw, dst, paint);
isSolidColor_ = false;
addBitmap(bitmap);
}
@ -244,6 +302,7 @@ void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
@ -254,6 +313,7 @@ void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
@ -262,6 +322,7 @@ void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
#ifdef SK_BUILD_FOR_ANDROID
@ -272,6 +333,7 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
#endif
@ -284,6 +346,7 @@ void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
++estimatedCost_;
isSolidColor_ = false;
isTransparent_ = false;
addBitmapFromPaint(paint);
}
void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y,
@ -323,6 +386,10 @@ int AnalysisCanvas::getEstimatedCost() const {
return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost();
}
void AnalysisCanvas::consumeLazyPixelRefs(LazyPixelRefList* pixelRefs) {
static_cast<AnalysisDevice*>(getDevice())->consumeLazyPixelRefs(pixelRefs);
}
bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op,
bool doAA) {
return INHERITED::clipRect(rect, op, doAA);

@ -5,6 +5,11 @@
#ifndef SKIA_EXT_ANALYSIS_CANVAS_H_
#define SKIA_EXT_ANALYSIS_CANVAS_H_
#include <list>
#include <set>
#include "base/hash_tables.h"
#include "skia/ext/lazy_pixel_ref.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
@ -20,6 +25,8 @@ class AnalysisDevice;
// Play a picture into the canvas, and then check isCheap().
class SK_API AnalysisCanvas : public SkCanvas {
public:
typedef std::list<skia::LazyPixelRef*> LazyPixelRefList;
AnalysisCanvas(AnalysisDevice*);
virtual ~AnalysisCanvas();
@ -28,6 +35,7 @@ class SK_API AnalysisCanvas : public SkCanvas {
bool isCheap() const;
bool getColorIfSolid(SkColor* color) const;
bool isTransparent() const;
void consumeLazyPixelRefs(LazyPixelRefList* pixelRefs);
// Returns the estimated cost of drawing, in arbitrary units.
int getEstimatedCost() const;
@ -59,12 +67,16 @@ class SK_API AnalysisCanvas : public SkCanvas {
class SK_API AnalysisDevice : public SkDevice {
public:
typedef std::list<skia::LazyPixelRef*> LazyPixelRefList;
typedef base::hash_set<uint32_t> IdSet;
AnalysisDevice(const SkBitmap& bm);
virtual ~AnalysisDevice();
int getEstimatedCost() const;
bool getColorIfSolid(SkColor* color) const;
bool isTransparent() const;
void consumeLazyPixelRefs(LazyPixelRefList* pixelRefs);
void setForceNotSolid(bool flag);
void setForceNotTransparent(bool flag);
@ -120,13 +132,20 @@ class SK_API AnalysisDevice : public SkDevice {
int estimatedCost_;
private:
typedef SkDevice INHERITED;
void addPixelRefIfLazy(SkPixelRef* pixelRef);
void addBitmap(const SkBitmap& bitmap);
void addBitmapFromPaint(const SkPaint& paint);
bool isForcedNotSolid_;
bool isForcedNotTransparent_;
bool isSolidColor_;
SkColor color_;
bool isTransparent_;
IdSet existingPixelRefIDs_;
LazyPixelRefList lazyPixelRefs_;
};
} // namespace skia

@ -4,8 +4,8 @@
#include "base/compiler_specific.h"
#include "skia/ext/analysis_canvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkShader.h"
namespace {
@ -20,6 +20,45 @@ void transparentFill(skia::AnalysisCanvas& canvas) {
} // namespace
namespace skia {
class TestPixelRef : public SkPixelRef {
public:
// Pure virtual implementation.
SkFlattenable::Factory getFactory() { return NULL; }
void* onLockPixels(SkColorTable**) { return NULL; }
void onUnlockPixels() {}
};
class TestLazyPixelRef : public LazyPixelRef {
public:
// Pure virtual implementation.
SkFlattenable::Factory getFactory() { return NULL; }
void* onLockPixels(SkColorTable**) { return NULL; }
void onUnlockPixels() {}
bool PrepareToDecode(const PrepareParams& params) { return true; }
void Decode() {}
};
class TestShader : public SkShader {
public:
TestShader(SkBitmap* bitmap)
: bitmap_(bitmap) {
}
SkShader::BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix*, TileMode xy[2]) const {
*bitmap = *bitmap_;
return SkShader::kDefault_BitmapType;
}
// Pure virtual implementation.
void shadeSpan(int x, int y, SkPMColor[], int count) {}
SkFlattenable::Factory getFactory() { return NULL; }
private:
SkBitmap* bitmap_;
};
TEST(AnalysisCanvasTest, EmptyCanvas) {
SkBitmap emptyBitmap;
emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
@ -310,4 +349,104 @@ TEST(AnalysisCanvasTest, SaveLayerRestore) {
EXPECT_FALSE(canvas.isTransparent());
}
TEST(AnalysisCanvasTest, LazyPixelRefs) {
// Set up two lazy and two non-lazy pixel refs and the corresponding bitmaps.
TestLazyPixelRef firstLazyPixelRef;
firstLazyPixelRef.setURI("lazy");
TestLazyPixelRef secondLazyPixelRef;
secondLazyPixelRef.setURI("lazy");
TestPixelRef firstNonLazyPixelRef;
TestPixelRef secondNonLazyPixelRef;
secondNonLazyPixelRef.setURI("notsolazy");
SkBitmap firstLazyBitmap;
firstLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
firstLazyBitmap.setPixelRef(&firstLazyPixelRef);
SkBitmap secondLazyBitmap;
secondLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
secondLazyBitmap.setPixelRef(&secondLazyPixelRef);
SkBitmap firstNonLazyBitmap;
firstNonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
SkBitmap secondNonLazyBitmap;
secondNonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
secondNonLazyBitmap.setPixelRef(&secondNonLazyPixelRef);
// The testcase starts here.
SkBitmap emptyBitmap;
emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
skia::AnalysisDevice device(emptyBitmap);
skia::AnalysisCanvas canvas(&device);
// This should be the first ref.
canvas.drawBitmap(firstLazyBitmap, 0, 0);
// The following will be ignored (non-lazy).
canvas.drawBitmap(firstNonLazyBitmap, 0, 0);
canvas.drawBitmap(firstNonLazyBitmap, 0, 0);
canvas.drawBitmap(secondNonLazyBitmap, 0, 0);
canvas.drawBitmap(secondNonLazyBitmap, 0, 0);
// This one will be ignored (already exists).
canvas.drawBitmap(firstLazyBitmap, 0, 0);
// This should be the second ref.
canvas.drawBitmap(secondLazyBitmap, 0, 0);
std::list<skia::LazyPixelRef*> pixelRefs;
canvas.consumeLazyPixelRefs(&pixelRefs);
// We expect to get only lazy pixel refs and only unique results.
EXPECT_EQ(pixelRefs.size(), 2u);
if (!pixelRefs.empty()) {
EXPECT_EQ(pixelRefs.front(),
static_cast<LazyPixelRef*>(&firstLazyPixelRef));
EXPECT_EQ(pixelRefs.back(),
static_cast<LazyPixelRef*>(&secondLazyPixelRef));
}
}
TEST(AnalysisCanvasTest, PixelRefsFromPaint) {
TestLazyPixelRef lazyPixelRef;
lazyPixelRef.setURI("lazy");
TestPixelRef nonLazyPixelRef;
nonLazyPixelRef.setURI("notsolazy");
SkBitmap lazyBitmap;
lazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
lazyBitmap.setPixelRef(&lazyPixelRef);
SkBitmap nonLazyBitmap;
nonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
nonLazyBitmap.setPixelRef(&nonLazyPixelRef);
TestShader lazyShader(&lazyBitmap);
TestShader nonLazyShader(&nonLazyBitmap);
SkPaint lazyPaint;
lazyPaint.setShader(&lazyShader);
SkPaint nonLazyPaint;
nonLazyPaint.setShader(&nonLazyShader);
SkBitmap emptyBitmap;
emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
skia::AnalysisDevice device(emptyBitmap);
skia::AnalysisCanvas canvas(&device);
canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
std::list<skia::LazyPixelRef*> pixelRefs;
canvas.consumeLazyPixelRefs(&pixelRefs);
// We expect to get only lazy pixel refs and only unique results.
EXPECT_EQ(pixelRefs.size(), 1u);
if (!pixelRefs.empty()) {
EXPECT_EQ(pixelRefs.front(), static_cast<LazyPixelRef*>(&lazyPixelRef));
}
}
} // namespace skia