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:
@ -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
|
||||
|
Reference in New Issue
Block a user