diff options
author | ajuma <ajuma@chromium.org> | 2015-02-12 09:46:43 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-12 17:47:27 +0000 |
commit | a727ffce6d321dc5c05dcaa096b40394aa4370cc (patch) | |
tree | 2169b83f5767868ef3583ab930e085dc23de84ce | |
parent | faa39fa701d993eff9dae003354259d2aec253b1 (diff) | |
download | chromium_src-a727ffce6d321dc5c05dcaa096b40394aa4370cc.zip chromium_src-a727ffce6d321dc5c05dcaa096b40394aa4370cc.tar.gz chromium_src-a727ffce6d321dc5c05dcaa096b40394aa4370cc.tar.bz2 |
cc: Use FilterOperations instead of SkImageFilter in FilterDisplayItem
This replaces FilterDisplayItem's SkImageFilter with FilterOperations.
Currently, filters on Layers are set using FilterOperations; this allows
filters to be animated on the compositor thread. Using FilterOperations
rather than an SkImageFilter in FilterDisplayItems will allow cc to continue
to be able to animate filters once cc becomes responsible for layerization
decisions.
The Blink side of this is http://crrev.com/875423003
BUG=453924
Review URL: https://codereview.chromium.org/904513004
Cr-Commit-Position: refs/heads/master@{#315996}
-rw-r--r-- | cc/blink/web_display_item_list_impl.cc | 17 | ||||
-rw-r--r-- | cc/blink/web_display_item_list_impl.h | 5 | ||||
-rw-r--r-- | cc/resources/display_item_list_unittest.cc | 49 | ||||
-rw-r--r-- | cc/resources/filter_display_item.cc | 18 | ||||
-rw-r--r-- | cc/resources/filter_display_item.h | 14 |
5 files changed, 88 insertions, 15 deletions
diff --git a/cc/blink/web_display_item_list_impl.cc b/cc/blink/web_display_item_list_impl.cc index fdd05df..879857c 100644 --- a/cc/blink/web_display_item_list_impl.cc +++ b/cc/blink/web_display_item_list_impl.cc @@ -7,6 +7,7 @@ #include <vector> #include "cc/blink/web_blend_mode.h" +#include "cc/blink/web_filter_operations_impl.h" #include "cc/resources/clip_display_item.h" #include "cc/resources/clip_path_display_item.h" #include "cc/resources/drawing_display_item.h" @@ -95,12 +96,26 @@ void WebDisplayItemListImpl::appendEndTransparencyItem() { display_item_list_->AppendItem(cc::EndTransparencyDisplayItem::Create()); } +#if FILTER_DISPLAY_ITEM_USES_FILTER_OPERATIONS +void WebDisplayItemListImpl::appendFilterItem( + const blink::WebFilterOperations& filters, + const blink::WebFloatRect& bounds) { + const WebFilterOperationsImpl& filters_impl = + static_cast<const WebFilterOperationsImpl&>(filters); + display_item_list_->AppendItem( + cc::FilterDisplayItem::Create(filters_impl.AsFilterOperations(), bounds)); +} +#else void WebDisplayItemListImpl::appendFilterItem( SkImageFilter* filter, const blink::WebFloatRect& bounds) { + cc::FilterOperations filter_operations; + filter_operations.Append( + cc::FilterOperation::CreateReferenceFilter(skia::SharePtr(filter))); display_item_list_->AppendItem( - cc::FilterDisplayItem::Create(skia::SharePtr(filter), bounds)); + cc::FilterDisplayItem::Create(filter_operations, bounds)); } +#endif void WebDisplayItemListImpl::appendEndFilterItem() { display_item_list_->AppendItem(cc::EndFilterDisplayItem::Create()); diff --git a/cc/blink/web_display_item_list_impl.h b/cc/blink/web_display_item_list_impl.h index cd35975..136aed6 100644 --- a/cc/blink/web_display_item_list_impl.h +++ b/cc/blink/web_display_item_list_impl.h @@ -48,8 +48,13 @@ class WebDisplayItemListImpl : public blink::WebDisplayItemList { virtual void appendTransparencyItem(float opacity, blink::WebBlendMode blend_mode); virtual void appendEndTransparencyItem(); +#if FILTER_DISPLAY_ITEM_USES_FILTER_OPERATIONS + virtual void appendFilterItem(const blink::WebFilterOperations& filters, + const blink::WebFloatRect& bounds); +#else virtual void appendFilterItem(SkImageFilter* filter, const blink::WebFloatRect& bounds); +#endif virtual void appendEndFilterItem(); private: diff --git a/cc/resources/display_item_list_unittest.cc b/cc/resources/display_item_list_unittest.cc index d6455a2..ddf2cb7 100644 --- a/cc/resources/display_item_list_unittest.cc +++ b/cc/resources/display_item_list_unittest.cc @@ -6,8 +6,11 @@ #include <vector> +#include "cc/output/filter_operation.h" +#include "cc/output/filter_operations.h" #include "cc/resources/clip_display_item.h" #include "cc/resources/drawing_display_item.h" +#include "cc/resources/filter_display_item.h" #include "cc/resources/transform_display_item.h" #include "cc/test/skia_common.h" #include "skia/ext/refptr.h" @@ -16,6 +19,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPictureRecorder.h" +#include "third_party/skia/include/effects/SkBitmapSource.h" #include "ui/gfx/skia_util.h" namespace cc { @@ -162,5 +166,50 @@ TEST(DisplayItemListTest, TransformItem) { EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); } +TEST(DisplayItemList, FilterItem) { + gfx::Rect layer_rect(100, 100); + FilterOperations filters; + unsigned char pixels[4 * 100 * 100] = {0}; + scoped_refptr<DisplayItemList> list = DisplayItemList::Create(); + + SkBitmap source_bitmap; + source_bitmap.allocN32Pixels(50, 50); + SkCanvas source_canvas(source_bitmap); + source_canvas.clear(SkColorSetRGB(128, 128, 128)); + + // For most SkImageFilters, the |dst| bounds computed by computeFastBounds are + // dependent on the provided |src| bounds. This means, for example, that + // translating |src| results in a corresponding translation of |dst|. But this + // is not the case for all SkImageFilters; for some of them (e.g. + // SkBitmapSource), the computation of |dst| in computeFastBounds doesn't + // involve |src| at all. Incorrectly assuming such a relationship (e.g. by + // translating |dst| after it is computed by computeFastBounds, rather than + // translating |src| before it provided to computedFastBounds) can cause + // incorrect clipping of filter output. To test for this, we include an + // SkBitmapSource filter in |filters|. Here, |src| is |filter_bounds|, defined + // below. + skia::RefPtr<SkImageFilter> image_filter = + skia::AdoptRef(SkBitmapSource::Create(source_bitmap)); + filters.Append(FilterOperation::CreateReferenceFilter(image_filter)); + filters.Append(FilterOperation::CreateBrightnessFilter(0.5f)); + gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f); + list->AppendItem(FilterDisplayItem::Create(filters, filter_bounds)); + list->AppendItem(EndFilterDisplayItem::Create()); + + DrawDisplayList(pixels, layer_rect, list); + + SkBitmap expected_bitmap; + unsigned char expected_pixels[4 * 100 * 100] = {0}; + SkPaint paint; + paint.setColor(SkColorSetRGB(64, 64, 64)); + SkImageInfo info = + SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height()); + expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes()); + SkCanvas expected_canvas(expected_bitmap); + expected_canvas.drawRect(RectFToSkRect(filter_bounds), paint); + + EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100)); +} + } // namespace } // namespace cc diff --git a/cc/resources/filter_display_item.cc b/cc/resources/filter_display_item.cc index daa0f8f..31abf28 100644 --- a/cc/resources/filter_display_item.cc +++ b/cc/resources/filter_display_item.cc @@ -6,6 +6,8 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event_argument.h" +#include "cc/output/render_surface_filters.h" +#include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkPaint.h" @@ -14,9 +16,9 @@ namespace cc { -FilterDisplayItem::FilterDisplayItem(skia::RefPtr<SkImageFilter> filter, +FilterDisplayItem::FilterDisplayItem(const FilterOperations& filters, gfx::RectF bounds) - : filter_(filter), bounds_(bounds) { + : filters_(filters), bounds_(bounds) { } FilterDisplayItem::~FilterDisplayItem() { @@ -25,14 +27,18 @@ FilterDisplayItem::~FilterDisplayItem() { void FilterDisplayItem::Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const { canvas->save(); - SkRect boundaries; - filter_->computeFastBounds(gfx::RectFToSkRect(bounds_), &boundaries); canvas->translate(bounds_.x(), bounds_.y()); - boundaries.offset(-bounds_.x(), -bounds_.y()); + + skia::RefPtr<SkImageFilter> image_filter = + RenderSurfaceFilters::BuildImageFilter( + filters_, gfx::SizeF(bounds_.width(), bounds_.height())); + SkRect boundaries; + image_filter->computeFastBounds( + SkRect::MakeWH(bounds_.width(), bounds_.height()), &boundaries); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - paint.setImageFilter(filter_.get()); + paint.setImageFilter(image_filter.get()); canvas->saveLayer(&boundaries, &paint); canvas->translate(-bounds_.x(), -bounds_.y()); diff --git a/cc/resources/filter_display_item.h b/cc/resources/filter_display_item.h index f93d3b3..28eeb95 100644 --- a/cc/resources/filter_display_item.h +++ b/cc/resources/filter_display_item.h @@ -7,13 +7,12 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "cc/output/filter_operations.h" #include "cc/resources/display_item.h" -#include "skia/ext/refptr.h" #include "ui/gfx/geometry/rect_f.h" class SkCanvas; class SkDrawPictureCallback; -class SkImageFilter; namespace cc { @@ -21,10 +20,9 @@ class CC_EXPORT FilterDisplayItem : public DisplayItem { public: ~FilterDisplayItem() override; - static scoped_ptr<FilterDisplayItem> Create( - skia::RefPtr<SkImageFilter> filter, - gfx::RectF bounds) { - return make_scoped_ptr(new FilterDisplayItem(filter, bounds)); + static scoped_ptr<FilterDisplayItem> Create(const FilterOperations& filters, + gfx::RectF bounds) { + return make_scoped_ptr(new FilterDisplayItem(filters, bounds)); } void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override; @@ -35,10 +33,10 @@ class CC_EXPORT FilterDisplayItem : public DisplayItem { void AsValueInto(base::trace_event::TracedValue* array) const override; protected: - FilterDisplayItem(skia::RefPtr<SkImageFilter> filter, gfx::RectF bounds); + FilterDisplayItem(const FilterOperations& filters, gfx::RectF bounds); private: - skia::RefPtr<SkImageFilter> filter_; + FilterOperations filters_; gfx::RectF bounds_; }; |