summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorajuma <ajuma@chromium.org>2015-02-12 09:46:43 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-12 17:47:27 +0000
commita727ffce6d321dc5c05dcaa096b40394aa4370cc (patch)
tree2169b83f5767868ef3583ab930e085dc23de84ce
parentfaa39fa701d993eff9dae003354259d2aec253b1 (diff)
downloadchromium_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.cc17
-rw-r--r--cc/blink/web_display_item_list_impl.h5
-rw-r--r--cc/resources/display_item_list_unittest.cc49
-rw-r--r--cc/resources/filter_display_item.cc18
-rw-r--r--cc/resources/filter_display_item.h14
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_;
};