Commit 1d801997 authored by enne@chromium.org's avatar enne@chromium.org

Revert of https://codereview.chromium.org/63443003/

Reason for revert: Caused a 30% rasterization regression

TBR=reveman@chromium.org,senorblanco@chromium.org,vangelis@google.com,reed@google.com
BUG=310796,332137

Review URL: https://codereview.chromium.org/126343003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243466 0039d316-1c4b-4281-b951-d872f2087c98
parent ec4a71c1
...@@ -97,6 +97,8 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { ...@@ -97,6 +97,8 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
PicturePileImpl::Analysis analysis; PicturePileImpl::Analysis analysis;
base::TimeTicks start = Now(); base::TimeTicks start = Now();
picture_pile->AnalyzeInRect(
content_rect, contents_scale, &analysis, NULL);
picture_pile->RasterToBitmap(&canvas, content_rect, contents_scale, NULL); picture_pile->RasterToBitmap(&canvas, content_rect, contents_scale, NULL);
base::TimeTicks end = Now(); base::TimeTicks end = Now();
base::TimeDelta duration = end - start; base::TimeDelta duration = end - start;
......
...@@ -47,6 +47,7 @@ ImplThreadRenderingStats::AsTraceableData() const { ...@@ -47,6 +47,7 @@ ImplThreadRenderingStats::AsTraceableData() const {
void ImplThreadRenderingStats::Add(const ImplThreadRenderingStats& other) { void ImplThreadRenderingStats::Add(const ImplThreadRenderingStats& other) {
frame_count += other.frame_count; frame_count += other.frame_count;
rasterize_time += other.rasterize_time; rasterize_time += other.rasterize_time;
analysis_time += other.analysis_time;
rasterized_pixel_count += other.rasterized_pixel_count; rasterized_pixel_count += other.rasterized_pixel_count;
} }
...@@ -61,8 +62,11 @@ void RenderingStats::EnumerateFields(Enumerator* enumerator) const { ...@@ -61,8 +62,11 @@ void RenderingStats::EnumerateFields(Enumerator* enumerator) const {
main_stats.record_time.InSecondsF()); main_stats.record_time.InSecondsF());
enumerator->AddInt64("recordedPixelCount", enumerator->AddInt64("recordedPixelCount",
main_stats.recorded_pixel_count); main_stats.recorded_pixel_count);
// Combine rasterization and analysis time as a precursor to combining
// them in the same step internally.
enumerator->AddDouble("rasterizeTime", enumerator->AddDouble("rasterizeTime",
impl_stats.rasterize_time.InSecondsF()); impl_stats.rasterize_time.InSecondsF() +
impl_stats.analysis_time.InSecondsF());
enumerator->AddInt64("rasterizedPixelCount", enumerator->AddInt64("rasterizedPixelCount",
impl_stats.rasterized_pixel_count); impl_stats.rasterized_pixel_count);
} }
......
...@@ -49,6 +49,7 @@ struct CC_EXPORT ImplThreadRenderingStats { ...@@ -49,6 +49,7 @@ struct CC_EXPORT ImplThreadRenderingStats {
int64 frame_count; int64 frame_count;
base::TimeDelta rasterize_time; base::TimeDelta rasterize_time;
base::TimeDelta analysis_time;
int64 rasterized_pixel_count; int64 rasterized_pixel_count;
ImplThreadRenderingStats(); ImplThreadRenderingStats();
......
...@@ -99,4 +99,13 @@ void RenderingStatsInstrumentation::AddRaster(base::TimeDelta duration, ...@@ -99,4 +99,13 @@ void RenderingStatsInstrumentation::AddRaster(base::TimeDelta duration,
impl_stats_.rasterized_pixel_count += pixels; impl_stats_.rasterized_pixel_count += pixels;
} }
void RenderingStatsInstrumentation::AddAnalysis(base::TimeDelta duration,
int64 pixels) {
if (!record_rendering_stats_)
return;
base::AutoLock scoped_lock(lock_);
impl_stats_.analysis_time += duration;
}
} // namespace cc } // namespace cc
...@@ -52,6 +52,7 @@ class CC_EXPORT RenderingStatsInstrumentation { ...@@ -52,6 +52,7 @@ class CC_EXPORT RenderingStatsInstrumentation {
void AddPaint(base::TimeDelta duration, int64 pixels); void AddPaint(base::TimeDelta duration, int64 pixels);
void AddRecord(base::TimeDelta duration, int64 pixels); void AddRecord(base::TimeDelta duration, int64 pixels);
void AddRaster(base::TimeDelta duration, int64 pixels); void AddRaster(base::TimeDelta duration, int64 pixels);
void AddAnalysis(base::TimeDelta duration, int64 pixels);
protected: protected:
RenderingStatsInstrumentation(); RenderingStatsInstrumentation();
......
...@@ -298,6 +298,7 @@ void Picture::GatherPixelRefs( ...@@ -298,6 +298,7 @@ void Picture::GatherPixelRefs(
int Picture::Raster( int Picture::Raster(
SkCanvas* canvas, SkCanvas* canvas,
SkDrawPictureCallback* callback,
const Region& negated_content_region, const Region& negated_content_region,
float contents_scale) { float contents_scale) {
TRACE_EVENT_BEGIN1( TRACE_EVENT_BEGIN1(
...@@ -315,7 +316,7 @@ int Picture::Raster( ...@@ -315,7 +316,7 @@ int Picture::Raster(
canvas->scale(contents_scale, contents_scale); canvas->scale(contents_scale, contents_scale);
canvas->translate(layer_rect_.x(), layer_rect_.y()); canvas->translate(layer_rect_.x(), layer_rect_.y());
picture_->draw(canvas); picture_->draw(canvas, callback);
SkIRect bounds; SkIRect bounds;
canvas->getClipDeviceBounds(&bounds); canvas->getClipDeviceBounds(&bounds);
canvas->restore(); canvas->restore();
......
...@@ -71,6 +71,7 @@ class CC_EXPORT Picture ...@@ -71,6 +71,7 @@ class CC_EXPORT Picture
// Apply this scale and raster the negated region into the canvas. See comment // Apply this scale and raster the negated region into the canvas. See comment
// in PicturePileImpl::RasterCommon for explanation on negated content region. // in PicturePileImpl::RasterCommon for explanation on negated content region.
int Raster(SkCanvas* canvas, int Raster(SkCanvas* canvas,
SkDrawPictureCallback* callback,
const Region& negated_content_region, const Region& negated_content_region,
float contents_scale); float contents_scale);
......
...@@ -74,9 +74,20 @@ void PicturePileImpl::RasterDirect( ...@@ -74,9 +74,20 @@ void PicturePileImpl::RasterDirect(
float contents_scale, float contents_scale,
RenderingStatsInstrumentation* rendering_stats_instrumentation) { RenderingStatsInstrumentation* rendering_stats_instrumentation) {
RasterCommon(canvas, RasterCommon(canvas,
NULL,
canvas_rect, canvas_rect,
contents_scale, contents_scale,
rendering_stats_instrumentation); rendering_stats_instrumentation,
false);
}
void PicturePileImpl::RasterForAnalysis(
skia::AnalysisCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
RenderingStatsInstrumentation* stats_instrumentation) {
RasterCommon(
canvas, canvas, canvas_rect, contents_scale, stats_instrumentation, true);
} }
void PicturePileImpl::RasterToBitmap( void PicturePileImpl::RasterToBitmap(
...@@ -127,9 +138,11 @@ void PicturePileImpl::RasterToBitmap( ...@@ -127,9 +138,11 @@ void PicturePileImpl::RasterToBitmap(
} }
RasterCommon(canvas, RasterCommon(canvas,
NULL,
canvas_rect, canvas_rect,
contents_scale, contents_scale,
rendering_stats_instrumentation); rendering_stats_instrumentation,
false);
} }
void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect, void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect,
...@@ -193,9 +206,11 @@ void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect, ...@@ -193,9 +206,11 @@ void PicturePileImpl::CoalesceRasters(gfx::Rect canvas_rect,
void PicturePileImpl::RasterCommon( void PicturePileImpl::RasterCommon(
SkCanvas* canvas, SkCanvas* canvas,
SkDrawPictureCallback* callback,
gfx::Rect canvas_rect, gfx::Rect canvas_rect,
float contents_scale, float contents_scale,
RenderingStatsInstrumentation* rendering_stats_instrumentation) { RenderingStatsInstrumentation* rendering_stats_instrumentation,
bool is_analysis) {
DCHECK(contents_scale >= min_contents_scale_); DCHECK(contents_scale >= min_contents_scale_);
canvas->translate(-canvas_rect.x(), -canvas_rect.y()); canvas->translate(-canvas_rect.x(), -canvas_rect.y());
...@@ -241,7 +256,7 @@ void PicturePileImpl::RasterCommon( ...@@ -241,7 +256,7 @@ void PicturePileImpl::RasterCommon(
start_time = rendering_stats_instrumentation->StartRecording(); start_time = rendering_stats_instrumentation->StartRecording();
rasterized_pixel_count = picture->Raster( rasterized_pixel_count = picture->Raster(
canvas, negated_clip_region, contents_scale); canvas, callback, negated_clip_region, contents_scale);
if (rendering_stats_instrumentation) { if (rendering_stats_instrumentation) {
base::TimeDelta duration = base::TimeDelta duration =
...@@ -251,8 +266,13 @@ void PicturePileImpl::RasterCommon( ...@@ -251,8 +266,13 @@ void PicturePileImpl::RasterCommon(
} }
if (rendering_stats_instrumentation) { if (rendering_stats_instrumentation) {
rendering_stats_instrumentation->AddRaster(best_duration, if (is_analysis) {
rasterized_pixel_count); rendering_stats_instrumentation->AddAnalysis(best_duration,
rasterized_pixel_count);
} else {
rendering_stats_instrumentation->AddRaster(best_duration,
rasterized_pixel_count);
}
} }
} }
...@@ -288,6 +308,39 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { ...@@ -288,6 +308,39 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() {
return picture; return picture;
} }
void PicturePileImpl::AnalyzeInRect(
gfx::Rect content_rect,
float contents_scale,
PicturePileImpl::Analysis* analysis) {
AnalyzeInRect(content_rect, contents_scale, analysis, NULL);
}
void PicturePileImpl::AnalyzeInRect(
gfx::Rect content_rect,
float contents_scale,
PicturePileImpl::Analysis* analysis,
RenderingStatsInstrumentation* stats_instrumentation) {
DCHECK(analysis);
TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect");
gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
content_rect, 1.0f / contents_scale);
layer_rect.Intersect(gfx::Rect(tiling_.total_size()));
SkBitmap empty_bitmap;
empty_bitmap.setConfig(SkBitmap::kNo_Config,
layer_rect.width(),
layer_rect.height());
skia::AnalysisDevice device(empty_bitmap);
skia::AnalysisCanvas canvas(&device);
RasterForAnalysis(&canvas, layer_rect, 1.0f, stats_instrumentation);
analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
analysis->has_text = canvas.HasText();
}
PicturePileImpl::Analysis::Analysis() PicturePileImpl::Analysis::Analysis()
: is_solid_color(false), : is_solid_color(false),
has_text(false) { has_text(false) {
...@@ -344,19 +397,6 @@ void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() { ...@@ -344,19 +397,6 @@ void PicturePileImpl::PixelRefIterator::AdvanceToTilePictureWithPixelRefs() {
} }
} }
gfx::Rect PicturePileImpl::AnalysisRectForRaster(gfx::Rect content_rect,
float contents_scale) const {
// Bound the analysis rect to just the pile content.
gfx::Rect content_bounds(
gfx::ScaleToEnclosingRect(gfx::Rect(size()), contents_scale));
gfx::Rect analysis_rect(content_rect);
analysis_rect.Intersect(content_bounds);
// Move to canvas space.
analysis_rect.set_origin(gfx::Point());
return analysis_rect;
}
void PicturePileImpl::DidBeginTracing() { void PicturePileImpl::DidBeginTracing() {
gfx::Rect layer_rect(tiling_.total_size()); gfx::Rect layer_rect(tiling_.total_size());
std::set<void*> processed_pictures; std::set<void*> processed_pictures;
......
...@@ -52,6 +52,14 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { ...@@ -52,6 +52,14 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
float contents_scale, float contents_scale,
RenderingStatsInstrumentation* stats_instrumentation); RenderingStatsInstrumentation* stats_instrumentation);
// Called when analyzing a tile. We can use AnalysisCanvas as
// SkDrawPictureCallback, which allows us to early out from analysis.
void RasterForAnalysis(
skia::AnalysisCanvas* canvas,
gfx::Rect canvas_rect,
float contents_scale,
RenderingStatsInstrumentation* stats_instrumentation);
skia::RefPtr<SkPicture> GetFlattenedPicture(); skia::RefPtr<SkPicture> GetFlattenedPicture();
struct CC_EXPORT Analysis { struct CC_EXPORT Analysis {
...@@ -63,6 +71,15 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { ...@@ -63,6 +71,15 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
SkColor solid_color; SkColor solid_color;
}; };
void AnalyzeInRect(gfx::Rect content_rect,
float contents_scale,
Analysis* analysis);
void AnalyzeInRect(gfx::Rect content_rect,
float contents_scale,
Analysis* analysis,
RenderingStatsInstrumentation* stats_instrumentation);
class CC_EXPORT PixelRefIterator { class CC_EXPORT PixelRefIterator {
public: public:
PixelRefIterator(gfx::Rect content_rect, PixelRefIterator(gfx::Rect content_rect,
...@@ -85,9 +102,6 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { ...@@ -85,9 +102,6 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
std::set<const void*> processed_pictures_; std::set<const void*> processed_pictures_;
}; };
gfx::Rect AnalysisRectForRaster(gfx::Rect content_rect,
float contents_scale) const;
void DidBeginTracing(); void DidBeginTracing();
protected: protected:
...@@ -122,9 +136,11 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase { ...@@ -122,9 +136,11 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
void RasterCommon( void RasterCommon(
SkCanvas* canvas, SkCanvas* canvas,
SkDrawPictureCallback* callback,
gfx::Rect canvas_rect, gfx::Rect canvas_rect,
float contents_scale, float contents_scale,
RenderingStatsInstrumentation* rendering_stats_instrumentation); RenderingStatsInstrumentation* rendering_stats_instrumentation,
bool is_analysis);
// Once instantiated, |clones_for_drawing_| can't be modified. This // Once instantiated, |clones_for_drawing_| can't be modified. This
// guarantees thread-safe access during the life time of a PicturePileImpl // guarantees thread-safe access during the life time of a PicturePileImpl
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include "skia/ext/lazy_pixel_ref.h" #include "skia/ext/lazy_pixel_ref.h"
#include "skia/ext/paint_simplifier.h" #include "skia/ext/paint_simplifier.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"
#include "ui/gfx/skia_util.h"
namespace cc { namespace cc {
...@@ -33,6 +31,10 @@ class IdentityAllocator : public SkBitmap::Allocator { ...@@ -33,6 +31,10 @@ class IdentityAllocator : public SkBitmap::Allocator {
void* buffer_; void* buffer_;
}; };
// Flag to indicate whether we should try and detect that
// a tile is of solid color.
const bool kUseColorEstimator = true;
class DisableLCDTextFilter : public SkDrawFilter { class DisableLCDTextFilter : public SkDrawFilter {
public: public:
// SkDrawFilter interface. // SkDrawFilter interface.
...@@ -71,11 +73,35 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { ...@@ -71,11 +73,35 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
rendering_stats_(rendering_stats), rendering_stats_(rendering_stats),
reply_(reply) {} reply_(reply) {}
// Overridden from internal::RasterWorkerPoolTask: void RunAnalysisOnThread(unsigned thread_index) {
virtual bool RunOnWorkerThread(unsigned thread_index, TRACE_EVENT1("cc",
void* buffer, "RasterWorkerPoolTaskImpl::RunAnalysisOnThread",
gfx::Size size, "data",
int stride) OVERRIDE { TracedValue::FromValue(DataAsValue().release()));
DCHECK(picture_pile_.get());
DCHECK(rendering_stats_);
PicturePileImpl* picture_clone =
picture_pile_->GetCloneForDrawingOnThread(thread_index);
DCHECK(picture_clone);
picture_clone->AnalyzeInRect(
content_rect_, contents_scale_, &analysis_, rendering_stats_);
// Record the solid color prediction.
UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
analysis_.is_solid_color);
// Clear the flag if we're not using the estimator.
analysis_.is_solid_color &= kUseColorEstimator;
}
bool RunRasterOnThread(unsigned thread_index,
void* buffer,
gfx::Size size,
int stride) {
TRACE_EVENT2( TRACE_EVENT2(
"cc", "RasterWorkerPoolTaskImpl::RunRasterOnThread", "cc", "RasterWorkerPoolTaskImpl::RunRasterOnThread",
"data", "data",
...@@ -89,6 +115,9 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { ...@@ -89,6 +115,9 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
DCHECK(picture_pile_.get()); DCHECK(picture_pile_.get());
DCHECK(buffer); DCHECK(buffer);
if (analysis_.is_solid_color)
return false;
PicturePileImpl* picture_clone = PicturePileImpl* picture_clone =
picture_pile_->GetCloneForDrawingOnThread(thread_index); picture_pile_->GetCloneForDrawingOnThread(thread_index);
...@@ -117,22 +146,8 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { ...@@ -117,22 +146,8 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
break; break;
} }
SkBitmap empty_bitmap; SkBitmapDevice device(bitmap);
empty_bitmap.setConfig( SkCanvas canvas(&device);
SkBitmap::kNo_Config, content_rect_.width(), content_rect_.height());
gfx::Rect analysis_rect(
picture_clone->AnalysisRectForRaster(content_rect_, contents_scale_));
skia::AnalysisDevice analysis_device(empty_bitmap,
gfx::RectToSkRect(analysis_rect));
skia::AnalysisCanvas analysis_canvas(&analysis_device);
SkBitmapDevice raster_device(bitmap);
SkCanvas raster_canvas(&raster_device);
SkNWayCanvas canvas(content_rect_.width(), content_rect_.height());
canvas.addCanvas(&analysis_canvas);
canvas.addCanvas(&raster_canvas);
skia::RefPtr<SkDrawFilter> draw_filter; skia::RefPtr<SkDrawFilter> draw_filter;
switch (raster_mode_) { switch (raster_mode_) {
case LOW_QUALITY_RASTER_MODE: case LOW_QUALITY_RASTER_MODE:
...@@ -178,17 +193,18 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask { ...@@ -178,17 +193,18 @@ class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
ChangeBitmapConfigIfNeeded(bitmap, buffer); ChangeBitmapConfigIfNeeded(bitmap, buffer);
analysis_.is_solid_color = return true;
analysis_canvas.GetColorIfSolid(&analysis_.solid_color);
analysis_.has_text = analysis_canvas.HasText();
// Record the solid color prediction.
UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
analysis_.is_solid_color);
return !analysis_.is_solid_color;
} }
// Overridden from internal::RasterWorkerPoolTask:
virtual bool RunOnWorkerThread(unsigned thread_index,
void* buffer,
gfx::Size size,
int stride)
OVERRIDE {
RunAnalysisOnThread(thread_index);
return RunRasterOnThread(thread_index, buffer, size, stride);
}
virtual void CompleteOnOriginThread() OVERRIDE { virtual void CompleteOnOriginThread() OVERRIDE {
reply_.Run(analysis_, !HasFinishedRunning() || WasCanceled()); reply_.Run(analysis_, !HasFinishedRunning() || WasCanceled());
} }
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "cc/test/impl_side_painting_settings.h" #include "cc/test/impl_side_painting_settings.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/skia_util.h"
namespace cc { namespace cc {
...@@ -108,26 +107,4 @@ void FakePicturePileImpl::RerecordPile() { ...@@ -108,26 +107,4 @@ void FakePicturePileImpl::RerecordPile() {
} }
} }
void FakePicturePileImpl::AnalyzeInRect(gfx::Rect content_rect,
float contents_scale,
Analysis* analysis) {
// Create and raster to a bitmap of content_rect size, even though the
// analysis_rect may be smaller to simulate edge tiles where recorded content
// doesn't cover the entire content_rect.
SkBitmap empty_bitmap;
empty_bitmap.setConfig(SkBitmap::kNo_Config,
content_rect.width(),
content_rect.height());
gfx::Rect analysis_rect(
AnalysisRectForRaster(content_rect, contents_scale));
skia::AnalysisDevice device(empty_bitmap, gfx::RectToSkRect(analysis_rect));
skia::AnalysisCanvas canvas(&device);
RasterDirect(&canvas, content_rect, contents_scale, NULL);
analysis->is_solid_color = canvas.GetColorIfSolid(&analysis->solid_color);
analysis->has_text = canvas.HasText();
}
} // namespace cc } // namespace cc
...@@ -34,10 +34,6 @@ class FakePicturePileImpl : public PicturePileImpl { ...@@ -34,10 +34,6 @@ class FakePicturePileImpl : public PicturePileImpl {
void RemoveRecordingAt(int x, int y); void RemoveRecordingAt(int x, int y);
void RerecordPile(); void RerecordPile();
void AnalyzeInRect(gfx::Rect content_rect,
float contents_scale,
Analysis* analysis);
void add_draw_rect(const gfx::RectF& rect) { void add_draw_rect(const gfx::RectF& rect) {
client_.add_draw_rect(rect, default_paint_); client_.add_draw_rect(rect, default_paint_);
} }
......
...@@ -69,7 +69,7 @@ void DrawPicture(unsigned char* buffer, ...@@ -69,7 +69,7 @@ void DrawPicture(unsigned char* buffer,
SkBitmapDevice device(bitmap); SkBitmapDevice device(bitmap);
SkCanvas canvas(&device); SkCanvas canvas(&device);
canvas.clipRect(gfx::RectToSkRect(layer_rect)); canvas.clipRect(gfx::RectToSkRect(layer_rect));
picture->Raster(&canvas, layer_rect, 1.0f); picture->Raster(&canvas, NULL, layer_rect, 1.0f);
} }
void CreateBitmap(gfx::Size size, const char* uri, SkBitmap* bitmap) { void CreateBitmap(gfx::Size size, const char* uri, SkBitmap* bitmap) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/src/core/SkRasterClip.h" #include "third_party/skia/src/core/SkRasterClip.h"
#include "ui/gfx/rect_conversions.h"
namespace { namespace {
...@@ -69,18 +70,8 @@ bool IsFullQuad(const SkDraw& draw, ...@@ -69,18 +70,8 @@ bool IsFullQuad(const SkDraw& draw,
namespace skia { namespace skia {
AnalysisDevice::AnalysisDevice(const SkBitmap& bitmap, SkRect analysis_rect)
: INHERITED(bitmap),
analysis_rect_(analysis_rect),
is_forced_not_solid_(false),
is_forced_not_transparent_(false),
is_solid_color_(true),
is_transparent_(true),
has_text_(false) {}
AnalysisDevice::AnalysisDevice(const SkBitmap& bitmap) AnalysisDevice::AnalysisDevice(const SkBitmap& bitmap)
: INHERITED(bitmap), : INHERITED(bitmap),
analysis_rect_(SkRect::MakeWH(bitmap.width(), bitmap.height())),
is_forced_not_solid_(false), is_forced_not_solid_(false),
is_forced_not_transparent_(false), is_forced_not_transparent_(false),
is_solid_color_(true), is_solid_color_(true),
...@@ -146,13 +137,8 @@ void AnalysisDevice::drawPoints(const SkDraw& draw, ...@@ -146,13 +137,8 @@ void AnalysisDevice::drawPoints(const SkDraw& draw,
void AnalysisDevice::drawRect(const SkDraw& draw, void AnalysisDevice::drawRect(const SkDraw& draw,
const SkRect& rect, const SkRect& rect,
const SkPaint& paint) { const SkPaint& paint) {
// Early out of work where possible. It could be the case that a picture
// draws text and then clears, but this is unlikely.
if (has_text_ && !is_solid_color_)
return;
bool does_cover_canvas = bool does_cover_canvas =
IsFullQuad(draw, analysis_rect_, rect); IsFullQuad(draw, SkRect::MakeWH(width(), height()), rect);
SkXfermode::Mode xfermode; SkXfermode::Mode xfermode;
SkXfermode::AsMode(paint.getXfermode(), &xfermode); SkXfermode::AsMode(paint.getXfermode(), &xfermode);
...@@ -293,7 +279,7 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, ...@@ -293,7 +279,7 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw,
#endif #endif
void AnalysisDevice::drawVertices(const SkDraw& draw, void AnalysisDevice::drawVertices(const SkDraw& draw,
SkCanvas::VertexMode mode, SkCanvas::VertexMode,
int vertex_count, int vertex_count,
const SkPoint verts[], const SkPoint verts[],
const SkPoint texs[], const SkPoint texs[],
...@@ -331,6 +317,11 @@ bool AnalysisCanvas::HasText() const { ...@@ -331,6 +317,11 @@ bool AnalysisCanvas::HasText() const {
return (static_cast<AnalysisDevice*>(getDevice()))->HasText(); return (static_cast<AnalysisDevice*>(getDevice()))->HasText();
} }
bool AnalysisCanvas::abortDrawing() {
// Early out as soon as we have detected that the tile has text.
return HasText();
}
bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool do_aa) { bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool do_aa) {
return INHERITED::clipRect(rect, op, do_aa); return INHERITED::clipRect(rect, op, do_aa);
} }
...@@ -382,10 +373,9 @@ int AnalysisCanvas::saveLayer(const SkRect* bounds, ...@@ -382,10 +373,9 @@ int AnalysisCanvas::saveLayer(const SkRect* bounds,
// If after we draw to the saved layer, we have to blend with the current // If after we draw to the saved layer, we have to blend with the current
// layer, then we can conservatively say that the canvas will not be of // layer, then we can conservatively say that the canvas will not be of
// solid color. // solid color.
SkRect analysis_rect =
static_cast<AnalysisDevice*>(getDevice())->AnalysisRect();
if ((paint && !IsSolidColorPaint(*paint)) || if ((paint && !IsSolidColorPaint(*paint)) ||
(bounds && !bounds->contains(analysis_rect))) { (bounds && !bounds->contains(SkRect::MakeWH(getDevice()->width(),
getDevice()->height())))) {
if (force_not_solid_stack_level_ == kNoLayer) { if (force_not_solid_stack_level_ == kNoLayer) {
force_not_solid_stack_level_ = saved_stack_size_; force_not_solid_stack_level_ = saved_stack_size_;
(static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true);
......
...@@ -20,15 +20,18 @@ class AnalysisDevice; ...@@ -20,15 +20,18 @@ class AnalysisDevice;
// To use: create a SkBitmap with kNo_Config, create an AnalysisDevice // To use: create a SkBitmap with kNo_Config, create an AnalysisDevice
// using that bitmap, and create an AnalysisCanvas using the device. // using that bitmap, and create an AnalysisCanvas using the device.
// Play a picture into the canvas, and then check result. // Play a picture into the canvas, and then check result.
class SK_API AnalysisCanvas : public SkCanvas { class SK_API AnalysisCanvas : public SkCanvas, public SkDrawPictureCallback {
public: public:
explicit AnalysisCanvas(AnalysisDevice* device); AnalysisCanvas(AnalysisDevice*);
virtual ~AnalysisCanvas(); virtual ~AnalysisCanvas();
// Returns true when a SkColor can be used to represent result. // Returns true when a SkColor can be used to represent result.
bool GetColorIfSolid(SkColor* color) const; bool GetColorIfSolid(SkColor* color) const;
bool HasText() const; bool HasText() const;
// SkDrawPictureCallback override.
virtual bool abortDrawing() OVERRIDE;
// SkCanvas overrides. // SkCanvas overrides.
virtual bool clipRect(const SkRect& rect, virtual bool clipRect(const SkRect& rect,
SkRegion::Op op = SkRegion::kIntersect_Op, SkRegion::Op op = SkRegion::kIntersect_Op,
...@@ -60,9 +63,6 @@ class SK_API AnalysisCanvas : public SkCanvas { ...@@ -60,9 +63,6 @@ class SK_API AnalysisCanvas : public SkCanvas {
// to be derived from SkBaseDevice (rather than SkBitmapDevice) // to be derived from SkBaseDevice (rather than SkBitmapDevice)
class SK_API AnalysisDevice : public SkBitmapDevice { class SK_API AnalysisDevice : public SkBitmapDevice {
public: public:
// |analysis_rect| is in device space.
AnalysisDevice(const SkBitmap& bitmap, SkRect analysis_rect);
// Analyze the entire bitmap.
AnalysisDevice(const SkBitmap& bitmap); AnalysisDevice(const SkBitmap& bitmap);
virtual ~AnalysisDevice(); virtual ~AnalysisDevice();
...@@ -72,8 +72,6 @@ class SK_API AnalysisDevice : public SkBitmapDevice { ...@@ -72,8 +72,6 @@ class SK_API AnalysisDevice : public SkBitmapDevice {
void SetForceNotSolid(bool flag); void SetForceNotSolid(bool flag);
void SetForceNotTransparent(bool flag); void SetForceNotTransparent(bool flag);
SkRect AnalysisRect() const { return analysis_rect_; }
protected: protected:
// SkBaseDevice overrides. // SkBaseDevice overrides.
virtual void clear(SkColor color) OVERRIDE; virtual void clear(SkColor color) OVERRIDE;
...@@ -159,7 +157,6 @@ class SK_API AnalysisDevice : public SkBitmapDevice { ...@@ -159,7 +157,6 @@ class SK_API AnalysisDevice : public SkBitmapDevice {
private: private:
typedef SkBitmapDevice INHERITED; typedef SkBitmapDevice INHERITED;
SkRect analysis_rect_;
bool is_forced_not_solid_; bool is_forced_not_solid_;
bool is_forced_not_transparent_; bool is_forced_not_transparent_;
bool is_solid_color_; bool is_solid_color_;
......
...@@ -18,7 +18,6 @@ void TransparentFill(skia::AnalysisCanvas& canvas) { ...@@ -18,7 +18,6 @@ void TransparentFill(skia::AnalysisCanvas& canvas) {
} }
} // namespace } // namespace
namespace skia { namespace skia {
TEST(AnalysisCanvasTest, EmptyCanvas) { TEST(AnalysisCanvasTest, EmptyCanvas) {
...@@ -342,6 +341,15 @@ TEST(AnalysisCanvasTest, HasText) { ...@@ -342,6 +341,15 @@ TEST(AnalysisCanvasTest, HasText) {
canvas.drawTextOnPath(text, byteLength, path, NULL, paint); canvas.drawTextOnPath(text, byteLength, path, NULL, paint);
EXPECT_TRUE(canvas.HasText()); EXPECT_TRUE(canvas.HasText());
} }
{
// Text under opaque rect.
skia::AnalysisDevice device(bitmap);
skia::AnalysisCanvas canvas(&device);
canvas.drawText(text, byteLength, point.fX, point.fY, paint);
EXPECT_TRUE(canvas.HasText());
canvas.drawRect(SkRect::MakeWH(width, height), paint);
EXPECT_FALSE(canvas.HasText());
}
{ {
// Text under translucent rect. // Text under translucent rect.
skia::AnalysisDevice device(bitmap); skia::AnalysisDevice device(bitmap);
...@@ -353,6 +361,17 @@ TEST(AnalysisCanvasTest, HasText) { ...@@ -353,6 +361,17 @@ TEST(AnalysisCanvasTest, HasText) {
canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint); canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint);
EXPECT_TRUE(canvas.HasText()); EXPECT_TRUE(canvas.HasText());
} }
{
// Text under rect in clear mode.
skia::AnalysisDevice device(bitmap);
skia::AnalysisCanvas canvas(&device);
canvas.drawText(text, byteLength, point.fX, point.fY, paint);
EXPECT_TRUE(canvas.HasText());
SkPaint clearModePaint;
clearModePaint.setXfermodeMode(SkXfermode::kClear_Mode);
canvas.drawRect(SkRect::MakeWH(width, height), clearModePaint);
EXPECT_FALSE(canvas.HasText());
}
{ {
// Clear. // Clear.
skia::AnalysisDevice device(bitmap); skia::AnalysisDevice device(bitmap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment