diff options
author | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 04:41:48 +0000 |
---|---|---|
committer | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-26 04:41:48 +0000 |
commit | 1dc7943effc15784acb0050a0402fe98e7547a2e (patch) | |
tree | 40ca6ee1c7995e356968bf3608d4e76194d00363 | |
parent | 152f9ae8bdf8e828d016d9d1e58530bc8311bb70 (diff) | |
download | chromium_src-1dc7943effc15784acb0050a0402fe98e7547a2e.zip chromium_src-1dc7943effc15784acb0050a0402fe98e7547a2e.tar.gz chromium_src-1dc7943effc15784acb0050a0402fe98e7547a2e.tar.bz2 |
Add support for converting cc::FilterOperations into an SkImageFilter
This defines a new type of cc::FilterOperation for reference filters, and
defines a method (RenderSurfaceFilters::BuildImageFilter) that builds an
SkImageFilter from a given cc::FilterOperations.
This also removes cc::Layer::SetFilter and cc::LayerImpl::SetFilter.
These were only used when we had a reference filter, but they are no
longer needed now that reference filters can be included in
FilterOperations.
BUG=181613
Review URL: https://codereview.chromium.org/21154002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225329 0039d316-1c4b-4281-b951-d872f2087c98
39 files changed, 420 insertions, 152 deletions
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc index 711ef01..58fa366 100644 --- a/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc @@ -549,7 +549,6 @@ class DelegatedRendererLayerImplTestTransform child_pass_rect, // contents_changed_since_last_frame gfx::RectF(), // mask_uv_rect FilterOperations(), // filters - skia::RefPtr<SkImageFilter>(), // filter FilterOperations()); // background_filters quad_sink.Append(render_pass_quad.PassAs<DrawQuad>(), &data); @@ -951,7 +950,6 @@ class DelegatedRendererLayerImplTestClip child_pass_rect, // contents_changed_since_last_frame gfx::RectF(), // mask_uv_rect FilterOperations(), // filters - skia::RefPtr<SkImageFilter>(), // filter FilterOperations()); // background_filters quad_sink.Append(render_pass_quad.PassAs<DrawQuad>(), &data); diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 86887a6..238d2c3 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -123,8 +123,7 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) { if (host && layer_animation_controller_->has_any_animation()) host->SetNeedsCommit(); - if (host && - (!filters_.IsEmpty() || !background_filters_.IsEmpty() || filter_)) + if (host && (!filters_.IsEmpty() || !background_filters_.IsEmpty())) layer_tree_host_->set_needs_filter_context(); } @@ -472,24 +471,12 @@ void Layer::SetFilters(const FilterOperations& filters) { DCHECK(IsPropertyChangeAllowed()); if (filters_ == filters) return; - DCHECK(!filter_); filters_ = filters; SetNeedsCommit(); if (!filters.IsEmpty() && layer_tree_host_) layer_tree_host_->set_needs_filter_context(); } -void Layer::SetFilter(const skia::RefPtr<SkImageFilter>& filter) { - DCHECK(IsPropertyChangeAllowed()); - if (filter_.get() == filter.get()) - return; - DCHECK(filters_.IsEmpty()); - filter_ = filter; - SetNeedsCommit(); - if (filter && layer_tree_host_) - layer_tree_host_->set_needs_filter_context(); -} - void Layer::SetBackgroundFilters(const FilterOperations& filters) { DCHECK(IsPropertyChangeAllowed()); if (background_filters_ == filters) @@ -821,7 +808,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetDrawsContent(DrawsContent()); layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); layer->SetFilters(filters()); - layer->SetFilter(filter()); layer->SetBackgroundFilters(background_filters()); layer->SetMasksToBounds(masks_to_bounds_); layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 737e83d..9894bc2 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h @@ -124,9 +124,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void SetFilters(const FilterOperations& filters); const FilterOperations& filters() const { return filters_; } - void SetFilter(const skia::RefPtr<SkImageFilter>& filter); - skia::RefPtr<SkImageFilter> filter() const { return filter_; } - // Background filters are filters applied to what is behind this layer, when // they are viewed through non-opaque regions in this layer. They are used // through the WebLayer interface, and are not exposed to HTML. @@ -543,7 +540,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, SkColor background_color_; CompositingReasons compositing_reasons_; float opacity_; - skia::RefPtr<SkImageFilter> filter_; FilterOperations filters_; FilterOperations background_filters_; float anchor_point_z_; diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index b0c5399..ad9b939 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -500,7 +500,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetDrawsContent(DrawsContent()); layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); layer->SetFilters(filters()); - layer->SetFilter(filter()); layer->SetBackgroundFilters(background_filters()); layer->SetMasksToBounds(masks_to_bounds_); layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); @@ -818,7 +817,6 @@ void LayerImpl::SetFilters(const FilterOperations& filters) { if (filters_ == filters) return; - DCHECK(!filter_); filters_ = filters; NoteLayerPropertyChangedForSubtree(); } @@ -832,15 +830,6 @@ void LayerImpl::SetBackgroundFilters( NoteLayerPropertyChanged(); } -void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) { - if (filter_.get() == filter.get()) - return; - - DCHECK(filters_.IsEmpty()); - filter_ = filter; - NoteLayerPropertyChangedForSubtree(); -} - void LayerImpl::SetMasksToBounds(bool masks_to_bounds) { if (masks_to_bounds_ == masks_to_bounds) return; diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index ba0ff7b..14560cc 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -193,9 +193,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { return background_filters_; } - void SetFilter(const skia::RefPtr<SkImageFilter>& filter); - skia::RefPtr<SkImageFilter> filter() const { return filter_; } - void SetMasksToBounds(bool masks_to_bounds); bool masks_to_bounds() const { return masks_to_bounds_; } @@ -597,7 +594,6 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver { FilterOperations filters_; FilterOperations background_filters_; - skia::RefPtr<SkImageFilter> filter_; protected: DrawMode current_draw_mode_; diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 3d8948a..4555bb0 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc @@ -102,8 +102,6 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f); FilterOperations arbitrary_filters; arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); - skia::RefPtr<SkImageFilter> arbitrary_filter = - skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1)); // These properties are internal, and should not be considered "change" when // they are used. @@ -117,7 +115,6 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) { EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetAnchorPointZ(arbitrary_number)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilters(arbitrary_filters)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilters(FilterOperations())); - EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetFilter(arbitrary_filter)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED( root->SetMaskLayer(LayerImpl::Create(host_impl.active_tree(), 4))); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetMasksToBounds(true)); @@ -216,15 +213,12 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f); FilterOperations arbitrary_filters; arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); - skia::RefPtr<SkImageFilter> arbitrary_filter = - skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1)); // Related filter functions. VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(FilterOperations())); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter)); - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter)); + VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters)); // Related scrolling functions. VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetMaxScrollOffset(large_vector2d)); @@ -271,7 +265,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { // Unrelated functions, set to the same values, no needs update. VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( root->SetAnchorPointZ(arbitrary_number)); - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilter(arbitrary_filter)); + VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetMasksToBounds(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetContentsOpaque(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetPosition(arbitrary_point_f)); diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc index 3262e28..91c19a7 100644 --- a/cc/layers/render_surface_impl.cc +++ b/cc/layers/render_surface_impl.cc @@ -228,7 +228,6 @@ void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink, contents_changed_since_last_frame, mask_uv_rect, owning_layer_->filters(), - owning_layer_->filter(), owning_layer_->background_filters()); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); } diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc index f4e3dde..672dba7 100644 --- a/cc/output/filter_operation.cc +++ b/cc/output/filter_operation.cc @@ -21,6 +21,8 @@ bool FilterOperation::operator==(const FilterOperation& other) const { drop_shadow_offset_ == other.drop_shadow_offset_ && drop_shadow_color_ == other.drop_shadow_color_; } + if (type_ == REFERENCE) + return image_filter_.get() == other.image_filter_.get(); return amount_ == other.amount_; } @@ -32,6 +34,7 @@ FilterOperation::FilterOperation(FilterType type, float amount) zoom_inset_(0) { DCHECK_NE(type_, DROP_SHADOW); DCHECK_NE(type_, COLOR_MATRIX); + DCHECK_NE(type_, REFERENCE); memset(matrix_, 0, sizeof(matrix_)); } @@ -68,6 +71,32 @@ FilterOperation::FilterOperation(FilterType type, float amount, int inset) memset(matrix_, 0, sizeof(matrix_)); } +FilterOperation::FilterOperation( + FilterType type, + const skia::RefPtr<SkImageFilter>& image_filter) + : type_(type), + amount_(0), + drop_shadow_offset_(0, 0), + drop_shadow_color_(0), + image_filter_(image_filter), + zoom_inset_(0) { + DCHECK_EQ(type_, REFERENCE); + memset(matrix_, 0, sizeof(matrix_)); +} + +FilterOperation::FilterOperation(const FilterOperation& other) + : type_(other.type_), + amount_(other.amount_), + drop_shadow_offset_(other.drop_shadow_offset_), + drop_shadow_color_(other.drop_shadow_color_), + image_filter_(other.image_filter_), + zoom_inset_(other.zoom_inset_) { + memcpy(matrix_, other.matrix_, sizeof(matrix_)); +} + +FilterOperation::~FilterOperation() { +} + // TODO(ajuma): Define a version of gfx::Tween::ValueBetween for floats, and use // that instead. static float BlendFloats(float from, float to, double progress) { @@ -147,6 +176,9 @@ static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { return FilterOperation::CreateZoomFilter(1.f, 0); case FilterOperation::SATURATING_BRIGHTNESS: return FilterOperation::CreateSaturatingBrightnessFilter(0.f); + case FilterOperation::REFERENCE: + return FilterOperation::CreateReferenceFilter( + skia::RefPtr<SkImageFilter>()); } NOTREACHED(); return FilterOperation::CreateEmptyFilter(); @@ -172,6 +204,7 @@ static float ClampAmountForFilterType(float amount, case FilterOperation::SATURATING_BRIGHTNESS: return amount; case FilterOperation::COLOR_MATRIX: + case FilterOperation::REFERENCE: NOTREACHED(); return amount; } @@ -197,6 +230,14 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from, DCHECK(to_op.type() != FilterOperation::COLOR_MATRIX); blended_filter.set_type(to_op.type()); + if (to_op.type() == FilterOperation::REFERENCE) { + if (progress > 0.5) + blended_filter.set_image_filter(to_op.image_filter()); + else + blended_filter.set_image_filter(from_op.image_filter()); + return blended_filter; + } + blended_filter.set_amount(ClampAmountForFilterType( BlendFloats(from_op.amount(), to_op.amount(), progress), to_op.type())); @@ -250,6 +291,18 @@ scoped_ptr<base::Value> FilterOperation::AsValue() const { value->SetDouble("amount", amount_); value->SetDouble("inset", zoom_inset_); break; + case FilterOperation::REFERENCE: { + int count_inputs = 0; + bool can_filter_image_gpu = false; + if (image_filter_) { + count_inputs = image_filter_->countInputs(); + can_filter_image_gpu = image_filter_->canFilterImageGPU(); + } + value->SetBoolean("is_null", !image_filter_); + value->SetInteger("count_inputs", count_inputs); + value->SetBoolean("can_filter_image_gpu", can_filter_image_gpu); + break; + } } return value.PassAs<base::Value>(); } diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h index f561762..f5c6a82 100644 --- a/cc/output/filter_operation.h +++ b/cc/output/filter_operation.h @@ -8,7 +8,9 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkScalar.h" #include "ui/gfx/point.h" @@ -33,13 +35,19 @@ class CC_EXPORT FilterOperation { DROP_SHADOW, COLOR_MATRIX, ZOOM, + REFERENCE, SATURATING_BRIGHTNESS, // Not used in CSS/SVG. }; + FilterOperation(const FilterOperation& other); + + ~FilterOperation(); + FilterType type() const { return type_; } float amount() const { DCHECK_NE(type_, COLOR_MATRIX); + DCHECK_NE(type_, REFERENCE); return amount_; } @@ -53,6 +61,11 @@ class CC_EXPORT FilterOperation { return drop_shadow_color_; } + skia::RefPtr<SkImageFilter> image_filter() const { + DCHECK_EQ(type_, REFERENCE); + return image_filter_; + } + const SkScalar* matrix() const { DCHECK_EQ(type_, COLOR_MATRIX); return matrix_; @@ -113,6 +126,11 @@ class CC_EXPORT FilterOperation { return FilterOperation(ZOOM, amount, inset); } + static FilterOperation CreateReferenceFilter( + const skia::RefPtr<SkImageFilter>& image_filter) { + return FilterOperation(REFERENCE, image_filter); + } + static FilterOperation CreateSaturatingBrightnessFilter(float amount) { return FilterOperation(SATURATING_BRIGHTNESS, amount); } @@ -132,6 +150,7 @@ class CC_EXPORT FilterOperation { void set_amount(float amount) { DCHECK_NE(type_, COLOR_MATRIX); + DCHECK_NE(type_, REFERENCE); amount_ = amount; } @@ -145,6 +164,11 @@ class CC_EXPORT FilterOperation { drop_shadow_color_ = color; } + void set_image_filter(const skia::RefPtr<SkImageFilter>& image_filter) { + DCHECK_EQ(type_, REFERENCE); + image_filter_ = image_filter; + } + void set_matrix(const SkScalar matrix[20]) { DCHECK_EQ(type_, COLOR_MATRIX); for (unsigned i = 0; i < 20; ++i) @@ -180,10 +204,14 @@ class CC_EXPORT FilterOperation { FilterOperation(FilterType type, float amount, int inset); + FilterOperation(FilterType type, + const skia::RefPtr<SkImageFilter>& image_filter); + FilterType type_; float amount_; gfx::Point drop_shadow_offset_; SkColor drop_shadow_color_; + skia::RefPtr<SkImageFilter> image_filter_; SkScalar matrix_[20]; int zoom_inset_; }; diff --git a/cc/output/filter_operations.cc b/cc/output/filter_operations.cc index e526f5c..92ddd68 100644 --- a/cc/output/filter_operations.cc +++ b/cc/output/filter_operations.cc @@ -59,7 +59,10 @@ void FilterOperations::GetOutsets(int* top, int* left) const { *top = *right = *bottom = *left = 0; for (size_t i = 0; i < operations_.size(); ++i) { - const FilterOperation op = operations_[i]; + const FilterOperation& op = operations_[i]; + // TODO(ajuma): Add support for reference filters once SkImageFilter + // reports its outsets. + DCHECK(op.type() != FilterOperation::REFERENCE); if (op.type() == FilterOperation::BLUR || op.type() == FilterOperation::DROP_SHADOW) { int spread = SpreadForStdDeviation(op.amount()); @@ -80,11 +83,14 @@ void FilterOperations::GetOutsets(int* top, bool FilterOperations::HasFilterThatMovesPixels() const { for (size_t i = 0; i < operations_.size(); ++i) { - const FilterOperation op = operations_[i]; + const FilterOperation& op = operations_[i]; + // TODO(ajuma): Once SkImageFilter reports its outsets, use those here to + // determine whether a reference filter really moves pixels. switch (op.type()) { case FilterOperation::BLUR: case FilterOperation::DROP_SHADOW: case FilterOperation::ZOOM: + case FilterOperation::REFERENCE: return true; case FilterOperation::OPACITY: case FilterOperation::COLOR_MATRIX: @@ -104,12 +110,15 @@ bool FilterOperations::HasFilterThatMovesPixels() const { bool FilterOperations::HasFilterThatAffectsOpacity() const { for (size_t i = 0; i < operations_.size(); ++i) { - const FilterOperation op = operations_[i]; + const FilterOperation& op = operations_[i]; + // TODO(ajuma): Make this smarter for reference filters. Once SkImageFilter + // can report affectsOpacity(), call that. switch (op.type()) { case FilterOperation::OPACITY: case FilterOperation::BLUR: case FilterOperation::DROP_SHADOW: case FilterOperation::ZOOM: + case FilterOperation::REFERENCE: return true; case FilterOperation::COLOR_MATRIX: { const SkScalar* matrix = op.matrix(); @@ -135,6 +144,14 @@ bool FilterOperations::HasFilterThatAffectsOpacity() const { return false; } +bool FilterOperations::HasReferenceFilter() const { + for (size_t i = 0; i < operations_.size(); ++i) { + if (operations_[i].type() == FilterOperation::REFERENCE) + return true; + } + return false; +} + FilterOperations FilterOperations::Blend(const FilterOperations& from, double progress) const { FilterOperations blended_filters; diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h index aa8d58d..410a50d 100644 --- a/cc/output/filter_operations.h +++ b/cc/output/filter_operations.h @@ -44,6 +44,7 @@ class CC_EXPORT FilterOperations { void GetOutsets(int* top, int* right, int* bottom, int* left) const; bool HasFilterThatMovesPixels() const; bool HasFilterThatAffectsOpacity() const; + bool HasReferenceFilter() const; size_t size() const { return operations_.size(); diff --git a/cc/output/filter_operations_unittest.cc b/cc/output/filter_operations_unittest.cc index dbf3736..e975ed5 100644 --- a/cc/output/filter_operations_unittest.cc +++ b/cc/output/filter_operations_unittest.cc @@ -3,7 +3,9 @@ // found in the LICENSE file. #include "cc/output/filter_operations.h" +#include "skia/ext/refptr.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/effects/SkBlurImageFilter.h" #include "ui/gfx/point.h" namespace cc { @@ -497,6 +499,45 @@ TEST(FilterOperationsTest, BlendSaturatingBrightnessWithNull) { EXPECT_EQ(expected, blended); } +TEST(FilterOperationsTest, BlendReferenceFilters) { + skia::RefPtr<SkImageFilter> from_filter = skia::AdoptRef( + new SkBlurImageFilter(1.f, 1.f)); + skia::RefPtr<SkImageFilter> to_filter = skia::AdoptRef( + new SkBlurImageFilter(2.f, 2.f)); + FilterOperation from = FilterOperation::CreateReferenceFilter(from_filter); + FilterOperation to = FilterOperation::CreateReferenceFilter(to_filter); + + FilterOperation blended = FilterOperation::Blend(&from, &to, -0.75); + EXPECT_EQ(from, blended); + + blended = FilterOperation::Blend(&from, &to, 0.5); + EXPECT_EQ(from, blended); + + blended = FilterOperation::Blend(&from, &to, 0.6); + EXPECT_EQ(to, blended); + + blended = FilterOperation::Blend(&from, &to, 1.5); + EXPECT_EQ(to, blended); +} + +TEST(FilterOperationsTest, BlendReferenceWithNull) { + skia::RefPtr<SkImageFilter> image_filter = skia::AdoptRef( + new SkBlurImageFilter(1.f, 1.f)); + FilterOperation filter = FilterOperation::CreateReferenceFilter(image_filter); + FilterOperation null_filter = + FilterOperation::CreateReferenceFilter(skia::RefPtr<SkImageFilter>()); + + FilterOperation blended = FilterOperation::Blend(&filter, NULL, 0.25); + EXPECT_EQ(filter, blended); + blended = FilterOperation::Blend(&filter, NULL, 0.75); + EXPECT_EQ(null_filter, blended); + + blended = FilterOperation::Blend(NULL, &filter, 0.25); + EXPECT_EQ(null_filter, blended); + blended = FilterOperation::Blend(NULL, &filter, 0.75); + EXPECT_EQ(filter, blended); +} + // Tests blending non-empty sequences that have the same length and matching // operations. TEST(FilterOperationsTest, BlendMatchingSequences) { diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index f4b1e57..99c4573 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -772,25 +772,31 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, SkBitmap filter_bitmap; SkScalar color_matrix[20]; bool use_color_matrix = false; - if (quad->filter) { - skia::RefPtr<SkColorFilter> cf; - - { - SkColorFilter* colorfilter_rawptr = NULL; - quad->filter->asColorFilter(&colorfilter_rawptr); - cf = skia::AdoptRef(colorfilter_rawptr); - } + // TODO(ajuma): Always use RenderSurfaceFilters::BuildImageFilter, not just + // when we have a reference filter. + if (quad->filters.HasReferenceFilter()) { + skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( + quad->filters, contents_texture->size()); + if (filter) { + skia::RefPtr<SkColorFilter> cf; + + { + SkColorFilter* colorfilter_rawptr = NULL; + filter->asColorFilter(&colorfilter_rawptr); + cf = skia::AdoptRef(colorfilter_rawptr); + } - if (cf && cf->asColorMatrix(color_matrix) && !quad->filter->getInput(0)) { - // We have a single color matrix as a filter; apply it locally - // in the compositor. - use_color_matrix = true; - } else { - filter_bitmap = ApplyImageFilter(this, - frame->offscreen_context_provider, - quad->rect.origin(), - quad->filter.get(), - contents_texture); + if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) { + // We have a single color matrix as a filter; apply it locally + // in the compositor. + use_color_matrix = true; + } else { + filter_bitmap = ApplyImageFilter(this, + frame->offscreen_context_provider, + quad->rect.origin(), + filter.get(), + contents_texture); + } } } else if (!quad->filters.IsEmpty()) { FilterOperations optimized_filters = diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc index 836287f..e30f0ceb 100644 --- a/cc/output/gl_renderer_unittest.cc +++ b/cc/output/gl_renderer_unittest.cc @@ -1429,6 +1429,8 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { skia::AdoptRef(new SkColorMatrixFilter(matrix))); skia::RefPtr<SkImageFilter> filter = skia::AdoptRef( SkColorFilterImageFilter::Create(color_filter.get(), NULL)); + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(filter)); gfx::Transform transform_causing_aa; transform_causing_aa.Rotate(20.0); @@ -1445,7 +1447,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { AddRenderPassQuad(root_pass, child_pass, 0, - skia::RefPtr<SkImageFilter>(), + FilterOperations(), gfx::Transform()); renderer_->DecideRenderPassAllocationsForFrame( @@ -1463,7 +1465,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { root_pass = AddRenderPass( render_passes, root_pass_id, viewport_rect, gfx::Transform()); - AddRenderPassQuad(root_pass, child_pass, 0, filter, gfx::Transform()); + AddRenderPassQuad(root_pass, child_pass, 0, filters, gfx::Transform()); renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); @@ -1483,7 +1485,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { AddRenderPassQuad(root_pass, child_pass, mask, - skia::RefPtr<SkImageFilter>(), + FilterOperations(), gfx::Transform()); renderer_->DecideRenderPassAllocationsForFrame( @@ -1501,7 +1503,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { root_pass = AddRenderPass( render_passes, root_pass_id, viewport_rect, gfx::Transform()); - AddRenderPassQuad(root_pass, child_pass, mask, filter, gfx::Transform()); + AddRenderPassQuad(root_pass, child_pass, mask, filters, gfx::Transform()); renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); @@ -1521,7 +1523,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { AddRenderPassQuad(root_pass, child_pass, 0, - skia::RefPtr<SkImageFilter>(), + FilterOperations(), transform_causing_aa); renderer_->DecideRenderPassAllocationsForFrame( @@ -1539,7 +1541,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { root_pass = AddRenderPass( render_passes, root_pass_id, viewport_rect, gfx::Transform()); - AddRenderPassQuad(root_pass, child_pass, 0, filter, transform_causing_aa); + AddRenderPassQuad(root_pass, child_pass, 0, filters, transform_causing_aa); renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); @@ -1556,7 +1558,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect, gfx::Transform()); - AddRenderPassQuad(root_pass, child_pass, mask, skia::RefPtr<SkImageFilter>(), + AddRenderPassQuad(root_pass, child_pass, mask, FilterOperations(), transform_causing_aa); renderer_->DecideRenderPassAllocationsForFrame( @@ -1574,7 +1576,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) { root_pass = AddRenderPass(render_passes, root_pass_id, viewport_rect, transform_causing_aa); - AddRenderPassQuad(root_pass, child_pass, mask, filter, transform_causing_aa); + AddRenderPassQuad(root_pass, child_pass, mask, filters, transform_causing_aa); renderer_->DecideRenderPassAllocationsForFrame( *renderer_client_.render_passes_in_draw_order()); @@ -1622,7 +1624,7 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) { AddRenderPassQuad(root_pass, child_pass, 0, - skia::RefPtr<SkImageFilter>(), + FilterOperations(), transform_preventing_aa); renderer_->DecideRenderPassAllocationsForFrame( diff --git a/cc/output/render_surface_filters.cc b/cc/output/render_surface_filters.cc index 04d8c5a..fe9959e 100644 --- a/cc/output/render_surface_filters.cc +++ b/cc/output/render_surface_filters.cc @@ -11,8 +11,13 @@ #include "cc/output/filter_operations.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkFlattenableBuffers.h" +#include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" +#include "third_party/skia/include/effects/SkColorFilterImageFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" +#include "third_party/skia/include/effects/SkComposeImageFilter.h" +#include "third_party/skia/include/effects/SkDropShadowImageFilter.h" #include "third_party/skia/include/effects/SkMagnifierImageFilter.h" #include "third_party/skia/include/gpu/SkGpuDevice.h" #include "third_party/skia/include/gpu/SkGrPixelRef.h" @@ -229,12 +234,22 @@ bool GetColorMatrix(const FilterOperation& op, SkScalar matrix[20]) { case FilterOperation::BLUR: case FilterOperation::DROP_SHADOW: case FilterOperation::ZOOM: + case FilterOperation::REFERENCE: return false; } NOTREACHED(); return false; } +skia::RefPtr<SkImageFilter> CreateMatrixImageFilter( + const SkScalar matrix[20], + const skia::RefPtr<SkImageFilter>& input) { + skia::RefPtr<SkColorFilter> color_filter = + skia::AdoptRef(new SkColorMatrixFilter(matrix)); + return skia::AdoptRef( + SkColorFilterImageFilter::Create(color_filter.get(), input.get())); +} + class FilterBufferState { public: FilterBufferState(GrContext* gr_context, @@ -359,6 +374,9 @@ FilterOperations RenderSurfaceFilters::Optimize( case FilterOperation::ZOOM: new_list.Append(op); break; + case FilterOperation::REFERENCE: + // Not supported on this code path. + NOTREACHED(); case FilterOperation::BRIGHTNESS: case FilterOperation::SATURATING_BRIGHTNESS: case FilterOperation::CONTRAST: @@ -446,6 +464,7 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters, canvas->restore(); break; } + case FilterOperation::REFERENCE: case FilterOperation::BRIGHTNESS: case FilterOperation::SATURATING_BRIGHTNESS: case FilterOperation::CONTRAST: @@ -463,4 +482,111 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters, return state.Source(); } +skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter( + const FilterOperations& filters, + gfx::SizeF size) { + skia::RefPtr<SkImageFilter> image_filter; + SkScalar matrix[20]; + for (size_t i = 0; i < filters.size(); ++i) { + const FilterOperation& op = filters.at(i); + switch (op.type()) { + case FilterOperation::GRAYSCALE: + GetGrayscaleMatrix(1.f - op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::SEPIA: + GetSepiaMatrix(1.f - op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::SATURATE: + GetSaturateMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::HUE_ROTATE: + GetHueRotateMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::INVERT: + GetInvertMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::OPACITY: + GetOpacityMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::BRIGHTNESS: + GetBrightnessMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::CONTRAST: + GetContrastMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::BLUR: + image_filter = skia::AdoptRef(new SkBlurImageFilter( + op.amount(), op.amount(), image_filter.get())); + break; + case FilterOperation::DROP_SHADOW: + image_filter = skia::AdoptRef(new SkDropShadowImageFilter( + SkIntToScalar(op.drop_shadow_offset().x()), + SkIntToScalar(op.drop_shadow_offset().y()), + SkIntToScalar(op.amount()), + op.drop_shadow_color(), + image_filter.get())); + break; + case FilterOperation::COLOR_MATRIX: + image_filter = CreateMatrixImageFilter(op.matrix(), image_filter); + break; + case FilterOperation::ZOOM: { + skia::RefPtr<SkImageFilter> zoom_filter = skia::AdoptRef( + new SkMagnifierImageFilter( + SkRect::MakeXYWH( + (size.width() - (size.width() / op.amount())) / 2.f, + (size.height() - (size.height() / op.amount())) / 2.f, + size.width() / op.amount(), + size.height() / op.amount()), + op.zoom_inset())); + if (image_filter.get()) { + // TODO(ajuma): When there's a 1-input version of + // SkMagnifierImageFilter, use that to handle the input filter + // instead of using an SkComposeImageFilter. + image_filter = skia::AdoptRef(new SkComposeImageFilter( + zoom_filter.get(), image_filter.get())); + } else { + image_filter = zoom_filter; + } + break; + } + case FilterOperation::SATURATING_BRIGHTNESS: + GetSaturatingBrightnessMatrix(op.amount(), matrix); + image_filter = CreateMatrixImageFilter(matrix, image_filter); + break; + case FilterOperation::REFERENCE: { + if (!op.image_filter()) + break; + + skia::RefPtr<SkColorFilter> cf; + + { + SkColorFilter* colorfilter_rawptr = NULL; + op.image_filter()->asColorFilter(&colorfilter_rawptr); + cf = skia::AdoptRef(colorfilter_rawptr); + } + + if (cf && cf->asColorMatrix(matrix) && + !op.image_filter()->getInput(0)) { + image_filter = CreateMatrixImageFilter(matrix, image_filter); + } else if (image_filter) { + image_filter = skia::AdoptRef(new SkComposeImageFilter( + op.image_filter().get(), image_filter.get())); + } else { + image_filter = op.image_filter(); + } + break; + } + } + } + return image_filter; +} + } // namespace cc diff --git a/cc/output/render_surface_filters.h b/cc/output/render_surface_filters.h index 5ab78dc..09d0f73 100644 --- a/cc/output/render_surface_filters.h +++ b/cc/output/render_surface_filters.h @@ -8,9 +8,11 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" +#include "skia/ext/refptr.h" class GrContext; class SkBitmap; +class SkImageFilter; namespace gfx { class SizeF; @@ -28,6 +30,10 @@ class CC_EXPORT RenderSurfaceFilters { GrContext* gr_context); static FilterOperations Optimize(const FilterOperations& filters); + static skia::RefPtr<SkImageFilter> BuildImageFilter( + const FilterOperations& filters, + gfx::SizeF size); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(RenderSurfaceFilters); }; diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 4d9578b..7165a93 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -89,7 +89,6 @@ scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad( rect, // contents_changed_since_last_frame gfx::RectF(), // mask_uv_rect FilterOperations(), // foreground filters - skia::RefPtr<SkImageFilter>(), // foreground filter FilterOperations()); // background filters return quad.PassAs<DrawQuad>(); @@ -623,6 +622,8 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { new SkColorMatrixFilter(matrix))); skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL)); + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(filter)); scoped_ptr<RenderPassDrawQuad> render_pass_quad = RenderPassDrawQuad::Create(); @@ -633,8 +634,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { 0, pass_rect, gfx::RectF(), - FilterOperations(), - filter, + filters, FilterOperations()); root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>()); @@ -726,6 +726,8 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) { new SkColorMatrixFilter(matrix))); skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL)); + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(filter)); scoped_ptr<RenderPassDrawQuad> render_pass_quad = RenderPassDrawQuad::Create(); @@ -736,8 +738,7 @@ TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) { 0, pass_rect, gfx::RectF(), - FilterOperations(), - filter, + filters, FilterOperations()); root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>()); @@ -931,7 +932,6 @@ class RendererPixelTestWithBackgroundFilter filter_pass_content_rect_, // contents_changed_since_last_frame gfx::RectF(), // mask_uv_rect FilterOperations(), // filters - skia::RefPtr<SkImageFilter>(), // filter this->background_filters_); root_pass->quad_list.push_back(filter_pass_quad.PassAs<DrawQuad>()); root_pass->shared_quad_state_list.push_back(shared_state.Pass()); diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index fa8c178..ace1b30 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc @@ -11,6 +11,7 @@ #include "cc/output/compositor_frame_metadata.h" #include "cc/output/copy_output_request.h" #include "cc/output/output_surface.h" +#include "cc/output/render_surface_filters.h" #include "cc/output/software_output_device.h" #include "cc/quads/checkerboard_draw_quad.h" #include "cc/quads/debug_border_draw_quad.h" @@ -440,9 +441,14 @@ void SoftwareRenderer::DrawRenderPassQuad(const DrawingFrame* frame, shader->setLocalMatrix(content_mat); current_paint_.setShader(shader.get()); - SkImageFilter* filter = quad->filter.get(); - if (filter) - current_paint_.setImageFilter(filter); + // TODO(ajuma): Remove this condition once general CSS filters are working + // correctly (http://crbug.com/160302), and add corresponding pixel tests. + if (quad->filters.HasReferenceFilter()) { + skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( + quad->filters, content_texture->size()); + if (filter) + current_paint_.setImageFilter(filter.get()); + } if (quad->mask_resource_id) { ResourceProvider::ScopedReadLockSoftware mask_lock(resource_provider_, diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc index 5705ce7..08a1a7a 100644 --- a/cc/quads/draw_quad_unittest.cc +++ b/cc/quads/draw_quad_unittest.cc @@ -249,6 +249,24 @@ void CompareDrawQuad(DrawQuad* quad, } \ SETUP_AND_COPY_QUAD_ALL(Type, quad_all); +#define CREATE_QUAD_7_NEW_1(Type, a, b, c, d, e, f, g, copy_a) \ + scoped_ptr<Type> quad_new(Type::Create()); \ + { \ + QUAD_DATA \ + quad_new->SetNew(shared_state.get(), quad_rect, a, b, c, d, e, f, g); \ + } \ + SETUP_AND_COPY_QUAD_NEW_1(Type, quad_new, copy_a); + +#define CREATE_QUAD_7_ALL_1(Type, a, b, c, d, e, f, g, copy_a) \ + scoped_ptr<Type> quad_all(Type::Create()); \ + { \ + QUAD_DATA \ + quad_all->SetAll(shared_state.get(), quad_rect, quad_opaque_rect, \ + quad_visible_rect, needs_blending, \ + a, b, c, d, e, f, g); \ + } \ + SETUP_AND_COPY_QUAD_ALL_1(Type, quad_all, copy_a); + #define CREATE_QUAD_8_NEW(Type, a, b, c, d, e, f, g, h) \ scoped_ptr<Type> quad_new(Type::Create()); \ { \ @@ -366,20 +384,17 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) { FilterOperations background_filters; background_filters.Append( FilterOperation::CreateGrayscaleFilter(1.f)); - skia::RefPtr<SkImageFilter> filter = - skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1)); RenderPass::Id copied_render_pass_id(235, 11); CREATE_SHARED_STATE(); - CREATE_QUAD_8_NEW_1(RenderPassDrawQuad, + CREATE_QUAD_7_NEW_1(RenderPassDrawQuad, render_pass_id, is_replica, mask_resource_id, contents_changed_since_last_frame, mask_u_v_rect, filters, - filter, background_filters, copied_render_pass_id); EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material); @@ -390,17 +405,15 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) { copy_quad->contents_changed_since_last_frame); EXPECT_EQ(mask_u_v_rect.ToString(), copy_quad->mask_uv_rect.ToString()); EXPECT_EQ(filters, copy_quad->filters); - EXPECT_EQ(filter, copy_quad->filter); EXPECT_EQ(background_filters, copy_quad->background_filters); - CREATE_QUAD_8_ALL_1(RenderPassDrawQuad, + CREATE_QUAD_7_ALL_1(RenderPassDrawQuad, render_pass_id, is_replica, mask_resource_id, contents_changed_since_last_frame, mask_u_v_rect, filters, - filter, background_filters, copied_render_pass_id); EXPECT_EQ(DrawQuad::RENDER_PASS, copy_quad->material); @@ -411,7 +424,6 @@ TEST(DrawQuadTest, CopyRenderPassDrawQuad) { copy_quad->contents_changed_since_last_frame); EXPECT_EQ(mask_u_v_rect.ToString(), copy_quad->mask_uv_rect.ToString()); EXPECT_EQ(filters, copy_quad->filters); - EXPECT_EQ(filter, copy_quad->filter); EXPECT_EQ(background_filters, copy_quad->background_filters); } @@ -772,20 +784,17 @@ TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) { FilterOperations background_filters; background_filters.Append( FilterOperation::CreateGrayscaleFilter(1.f)); - skia::RefPtr<SkImageFilter> filter = - skia::AdoptRef(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1)); RenderPass::Id copied_render_pass_id(235, 11); CREATE_SHARED_STATE(); - CREATE_QUAD_8_NEW_1(RenderPassDrawQuad, + CREATE_QUAD_7_NEW_1(RenderPassDrawQuad, render_pass_id, is_replica, mask_resource_id, contents_changed_since_last_frame, mask_u_v_rect, filters, - filter, background_filters, copied_render_pass_id); EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id); diff --git a/cc/quads/render_pass_draw_quad.cc b/cc/quads/render_pass_draw_quad.cc index 73b2553..af8cd8c 100644 --- a/cc/quads/render_pass_draw_quad.cc +++ b/cc/quads/render_pass_draw_quad.cc @@ -43,7 +43,6 @@ void RenderPassDrawQuad::SetNew( gfx::Rect contents_changed_since_last_frame, gfx::RectF mask_uv_rect, const FilterOperations& filters, - skia::RefPtr<SkImageFilter> filter, const FilterOperations& background_filters) { DCHECK_GT(render_pass_id.layer_id, 0); DCHECK_GE(render_pass_id.index, 0); @@ -53,7 +52,7 @@ void RenderPassDrawQuad::SetNew( bool needs_blending = false; SetAll(shared_quad_state, rect, opaque_rect, visible_rect, needs_blending, render_pass_id, is_replica, mask_resource_id, - contents_changed_since_last_frame, mask_uv_rect, filters, filter, + contents_changed_since_last_frame, mask_uv_rect, filters, background_filters); } @@ -69,7 +68,6 @@ void RenderPassDrawQuad::SetAll( gfx::Rect contents_changed_since_last_frame, gfx::RectF mask_uv_rect, const FilterOperations& filters, - skia::RefPtr<SkImageFilter> filter, const FilterOperations& background_filters) { DCHECK_GT(render_pass_id.layer_id, 0); DCHECK_GE(render_pass_id.index, 0); @@ -82,7 +80,6 @@ void RenderPassDrawQuad::SetAll( this->contents_changed_since_last_frame = contents_changed_since_last_frame; this->mask_uv_rect = mask_uv_rect; this->filters = filters; - this->filter = filter; this->background_filters = background_filters; } @@ -107,9 +104,6 @@ void RenderPassDrawQuad::ExtendValue(base::DictionaryValue* value) const { MathUtil::AsValue(contents_changed_since_last_frame).release()); value->Set("mask_uv_rect", MathUtil::AsValue(mask_uv_rect).release()); value->Set("filters", filters.AsValue().release()); - // TODO(piman): dump SkImageFilters rather than just indicating if there are - // any or not. - value->SetBoolean("has_filter", !!filter); value->Set("background_filters", background_filters.AsValue().release()); } diff --git a/cc/quads/render_pass_draw_quad.h b/cc/quads/render_pass_draw_quad.h index e253dec..8546c45 100644 --- a/cc/quads/render_pass_draw_quad.h +++ b/cc/quads/render_pass_draw_quad.h @@ -28,7 +28,6 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { gfx::Rect contents_changed_since_last_frame, gfx::RectF mask_uv_rect, const FilterOperations& filters, - skia::RefPtr<SkImageFilter> filter, const FilterOperations& background_filters); void SetAll(const SharedQuadState* shared_quad_state, @@ -42,7 +41,6 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { gfx::Rect contents_changed_since_last_frame, gfx::RectF mask_uv_rect, const FilterOperations& filters, - skia::RefPtr<SkImageFilter> filter, const FilterOperations& background_filters); scoped_ptr<RenderPassDrawQuad> Copy( @@ -55,11 +53,8 @@ class CC_EXPORT RenderPassDrawQuad : public DrawQuad { gfx::Rect contents_changed_since_last_frame; gfx::RectF mask_uv_rect; - // Deprecated post-processing filters, applied to the pixels in the render - // pass' texture. + // Post-processing filters, applied to the pixels in the render pass' texture. FilterOperations filters; - // Post-processing filter applied to the pixels in the render pass' texture. - skia::RefPtr<SkImageFilter> filter; // Post-processing filters, applied to the pixels showing through the // background of the render pass, from behind it. diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc index b50d923..b02e5bb 100644 --- a/cc/test/render_pass_test_common.cc +++ b/cc/test/render_pass_test_common.cc @@ -127,7 +127,6 @@ void TestRenderPass::AppendOneOfEveryQuadType( rect, gfx::RectF(), FilterOperations(), - skia::RefPtr<SkImageFilter>(), FilterOperations()); AppendQuad(render_pass_quad.PassAs<DrawQuad>()); @@ -141,7 +140,6 @@ void TestRenderPass::AppendOneOfEveryQuadType( rect, gfx::RectF(), FilterOperations(), - skia::RefPtr<SkImageFilter>(), FilterOperations()); AppendQuad(render_pass_replica_quad.PassAs<DrawQuad>()); } diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc index 0044f6a..b2045d7 100644 --- a/cc/test/render_pass_test_utils.cc +++ b/cc/test/render_pass_test_utils.cc @@ -88,14 +88,14 @@ void AddRenderPassQuad(TestRenderPass* to_pass, scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); quad->SetNew(shared_state, output_rect, contributing_pass->id, false, 0, output_rect, gfx::RectF(), FilterOperations(), - skia::RefPtr<SkImageFilter>(), FilterOperations()); + FilterOperations()); quad_sink.Append(quad.PassAs<DrawQuad>(), &data); } void AddRenderPassQuad(TestRenderPass* to_pass, TestRenderPass* contributing_pass, ResourceProvider::ResourceId mask_resource_id, - skia::RefPtr<SkImageFilter> filter, + const FilterOperations& filters, gfx::Transform transform) { MockQuadCuller quad_sink(&to_pass->quad_list, &to_pass->shared_quad_state_list); @@ -107,9 +107,8 @@ void AddRenderPassQuad(TestRenderPass* to_pass, transform, output_rect.size(), output_rect, output_rect, false, 1); scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); quad->SetNew(shared_state, output_rect, contributing_pass->id, false, - mask_resource_id, output_rect, gfx::RectF(), - FilterOperations(), - filter, FilterOperations()); + mask_resource_id, output_rect, gfx::RectF(), filters, + FilterOperations()); quad_sink.Append(quad.PassAs<DrawQuad>(), &data); } diff --git a/cc/test/render_pass_test_utils.h b/cc/test/render_pass_test_utils.h index b427e5a..650cbc0 100644 --- a/cc/test/render_pass_test_utils.h +++ b/cc/test/render_pass_test_utils.h @@ -6,6 +6,7 @@ #define CC_TEST_RENDER_PASS_TEST_UTILS_H_ #include "cc/base/scoped_ptr_vector.h" +#include "cc/output/filter_operations.h" #include "cc/quads/render_pass.h" #include "cc/resources/resource_provider.h" #include "third_party/skia/include/core/SkColor.h" @@ -52,7 +53,7 @@ void AddRenderPassQuad(TestRenderPass* to_pass, void AddRenderPassQuad(TestRenderPass* toPass, TestRenderPass* contributing_pass, ResourceProvider::ResourceId mask_resource_id, - skia::RefPtr<SkImageFilter> filter, + const FilterOperations& filters, gfx::Transform transform); } // namespace cc diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc index 64b1586..2be043f 100644 --- a/cc/trees/damage_tracker.cc +++ b/cc/trees/damage_tracker.cc @@ -52,8 +52,7 @@ void DamageTracker::UpdateDamageTrackingState( bool target_surface_property_changed_only_from_descendant, gfx::Rect target_surface_content_rect, LayerImpl* target_surface_mask_layer, - const FilterOperations& filters, - SkImageFilter* filter) { + const FilterOperations& filters) { // // This function computes the "damage rect" of a target surface, and updates // the state that is used to correctly track damage across frames. The damage @@ -143,12 +142,12 @@ void DamageTracker::UpdateDamageTrackingState( damage_rect_for_this_update.Union(damage_from_surface_mask); damage_rect_for_this_update.Union(damage_from_leftover_rects); - if (filters.HasFilterThatMovesPixels()) { - ExpandRectWithFilters(&damage_rect_for_this_update, filters); - } else if (filter) { + if (filters.HasReferenceFilter()) { // TODO(senorblanco): Once SkImageFilter reports its outsets, use // those here to limit damage. damage_rect_for_this_update = target_surface_content_rect; + } else if (filters.HasFilterThatMovesPixels()) { + ExpandRectWithFilters(&damage_rect_for_this_update, filters); } } diff --git a/cc/trees/damage_tracker.h b/cc/trees/damage_tracker.h index ce72fcc..fbcaa69 100644 --- a/cc/trees/damage_tracker.h +++ b/cc/trees/damage_tracker.h @@ -40,8 +40,7 @@ class CC_EXPORT DamageTracker { bool target_surface_property_changed_only_from_descendant, gfx::Rect target_surface_content_rect, LayerImpl* target_surface_mask_layer, - const FilterOperations& filters, - SkImageFilter* filter); + const FilterOperations& filters); gfx::RectF current_damage_rect() { return current_damage_rect_; } diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc index 8a86207..7fb8720 100644 --- a/cc/trees/damage_tracker_unittest.cc +++ b/cc/trees/damage_tracker_unittest.cc @@ -63,8 +63,7 @@ void EmulateDrawingOneFrame(LayerImpl* root) { target_surface->SurfacePropertyChangedOnlyFromDescendant(), target_surface->content_rect(), render_surface_layer_list[i]->mask_layer(), - render_surface_layer_list[i]->filters(), - render_surface_layer_list[i]->filter().get()); + render_surface_layer_list[i]->filters()); } root->ResetAllChangeTrackingForSubtree(); @@ -446,10 +445,12 @@ TEST_F(DamageTrackerTest, VerifyDamageForImageFilter) { skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(new SkBlurImageFilter(SkIntToScalar(2), SkIntToScalar(2))); + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(filter)); // Setting the filter will damage the whole surface. ClearDamageForAllSurfaces(root.get()); - child->SetFilter(filter); + child->SetFilters(filters); EmulateDrawingOneFrame(root.get()); root_damage_rect = root->render_surface()->damage_tracker()->current_damage_rect(); @@ -1297,8 +1298,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) { false, gfx::Rect(), NULL, - FilterOperations(), - NULL); + FilterOperations()); gfx::RectF damage_rect = target_surface->damage_tracker()->current_damage_rect(); diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 378e7c8..27090da 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -555,8 +555,7 @@ static bool SubtreeShouldRenderToSeparateSurface( } // If the layer uses a CSS filter. - if (!layer->filters().IsEmpty() || !layer->background_filters().IsEmpty() || - layer->filter()) { + if (!layer->filters().IsEmpty() || !layer->background_filters().IsEmpty()) { DCHECK(!is_root); return true; } @@ -1546,7 +1545,8 @@ static void CalculateDrawPropertiesInternal( // TODO(senorblanco): make this smarter for the SkImageFilter case (check // for pixel-moving filters) - if (layer->filters().HasFilterThatMovesPixels() || layer->filter()) + if (layer->filters().HasReferenceFilter() || + layer->filters().HasFilterThatMovesPixels()) nearest_ancestor_surface_that_moves_pixels = render_surface; render_surface->SetNearestAncestorThatMovesPixels( diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 59e307b..4a7bad4 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -476,8 +476,7 @@ void LayerTreeHostImpl::TrackDamageForAllSurfaces( render_surface->SurfacePropertyChangedOnlyFromDescendant(), render_surface->content_rect(), render_surface_layer->mask_layer(), - render_surface_layer->filters(), - render_surface_layer->filter().get()); + render_surface_layer->filters()); } } diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index bab6d20..de58b5e 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -5157,7 +5157,6 @@ static void ConfigureRenderPassTestData(const char* test_script, contents_changed_rect, gfx::RectF(0.f, 0.f, 1.f, 1.f), FilterOperations(), - skia::RefPtr<SkImageFilter>(), FilterOperations()); render_pass->AppendQuad(quad.PassAs<DrawQuad>()); } diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 4055376..31b2be4 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -175,11 +175,13 @@ TEST_F(LayerTreeHostFiltersPixelTest, ImageFilterClipped) { colorFilter.get(), NULL, &cropRect)); + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(filter)); // Make the foreground layer's render surface be clipped by the background // layer. background->SetMasksToBounds(true); - foreground->SetFilter(filter); + foreground->SetFilters(filters); // Then we translate the foreground up by 100 pixels in Y, so the cropped // region is moved to to the top. This ensures that the crop rect is being diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc index 5030428..79c615d 100644 --- a/cc/trees/layer_tree_host_unittest_delegated.cc +++ b/cc/trees/layer_tree_host_unittest_delegated.cc @@ -183,7 +183,6 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest { damage_rect, gfx::Rect(0, 0, 1, 1), // mask_uv_rect filters, - skia::RefPtr<SkImageFilter>(), background_filters); frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass()); frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>()); diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index 9fc26da..abaefa7 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc @@ -233,14 +233,11 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget( // If the occlusion within the surface can not be applied to things outside of // the surface's subtree, then clear the occlusion here so it won't be used. - // TODO(senorblanco): Make this smarter for SkImageFilter case: once - // SkImageFilters can report affectsOpacity(), call that. if (finished_target->mask_layer() || !SurfaceOpacityKnown(surface) || surface->draw_opacity() < 1 || target_is_only_for_copy_request || - finished_target->filters().HasFilterThatAffectsOpacity() || - finished_target->filter()) { + finished_target->filters().HasFilterThatAffectsOpacity()) { stack_.back().occlusion_from_outside_target.Clear(); stack_.back().occlusion_from_inside_target.Clear(); } else if (!SurfaceTransformsToTargetKnown(surface)) { diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc index 964fa86..ccf58e7 100644 --- a/content/common/cc_messages.cc +++ b/content/common/cc_messages.cc @@ -44,6 +44,9 @@ void ParamTraits<cc::FilterOperation>::Write( WriteParam(m, p.amount()); WriteParam(m, p.zoom_inset()); break; + case cc::FilterOperation::REFERENCE: + WriteParam(m, p.image_filter()); + break; } } @@ -109,6 +112,16 @@ bool ParamTraits<cc::FilterOperation>::Read( success = true; } break; + case cc::FilterOperation::REFERENCE: { + skia::RefPtr<SkImageFilter> filter; + if (!ReadParam(m, iter, &filter)) { + success = false; + break; + } + r->set_image_filter(filter); + success = true; + break; + } } return success; } @@ -151,6 +164,9 @@ void ParamTraits<cc::FilterOperation>::Log( l->append(", "); LogParam(p.zoom_inset(), l); break; + case cc::FilterOperation::REFERENCE: + LogParam(p.image_filter(), l); + break; } l->append(")"); } diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index 5c8b0b7..745705d 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h @@ -159,7 +159,6 @@ IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassDrawQuad) IPC_STRUCT_TRAITS_MEMBER(contents_changed_since_last_frame) IPC_STRUCT_TRAITS_MEMBER(mask_uv_rect) IPC_STRUCT_TRAITS_MEMBER(filters) - IPC_STRUCT_TRAITS_MEMBER(filter) IPC_STRUCT_TRAITS_MEMBER(background_filters) IPC_STRUCT_TRAITS_END() diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc index 6be248d..1bb93cc 100644 --- a/content/common/cc_messages_unittest.cc +++ b/content/common/cc_messages_unittest.cc @@ -136,11 +136,16 @@ class CCMessagesTest : public testing::Test { EXPECT_EQ(a->contents_changed_since_last_frame, b->contents_changed_since_last_frame); EXPECT_EQ(a->mask_uv_rect.ToString(), b->mask_uv_rect.ToString()); - EXPECT_EQ(a->filters, b->filters); - if (!a->filter || !b->filter) - EXPECT_EQ(a->filter, b->filter); - else - EXPECT_EQ(a->filter->countInputs(), b->filter->countInputs()); + EXPECT_EQ(a->filters.size(), b->filters.size()); + for (size_t i = 0; i < a->filters.size(); ++i) { + if (a->filters.at(i).type() != cc::FilterOperation::REFERENCE) { + EXPECT_EQ(a->filters.at(i), b->filters.at(i)); + } else { + EXPECT_EQ(b->filters.at(i).type(), cc::FilterOperation::REFERENCE); + EXPECT_EQ(a->filters.at(i).image_filter()->countInputs(), + b->filters.at(i).image_filter()->countInputs()); + } + } EXPECT_EQ(a->background_filters, b->background_filters); } @@ -235,14 +240,15 @@ TEST_F(CCMessagesTest, AllQuads) { FilterOperations arbitrary_filters1; arbitrary_filters1.Append(FilterOperation::CreateGrayscaleFilter( arbitrary_float1)); + skia::RefPtr<SkImageFilter> arbitrary_filter = skia::AdoptRef( + new SkBlurImageFilter(arbitrary_sigma, arbitrary_sigma)); + arbitrary_filters1.Append( + cc::FilterOperation::CreateReferenceFilter(arbitrary_filter)); FilterOperations arbitrary_filters2; arbitrary_filters2.Append(FilterOperation::CreateBrightnessFilter( arbitrary_float2)); - skia::RefPtr<SkImageFilter> arbitrary_filter = skia::AdoptRef( - new SkBlurImageFilter(arbitrary_sigma, arbitrary_sigma)); - scoped_ptr<SharedQuadState> shared_state1_in = SharedQuadState::Create(); shared_state1_in->SetAll(arbitrary_matrix, arbitrary_size1, @@ -301,7 +307,6 @@ TEST_F(CCMessagesTest, AllQuads) { arbitrary_rect1, arbitrary_rectf1, arbitrary_filters1, - arbitrary_filter, arbitrary_filters2); scoped_ptr<RenderPassDrawQuad> renderpass_cmp = renderpass_in->Copy( renderpass_in->shared_quad_state, renderpass_in->render_pass_id); diff --git a/webkit/renderer/compositor_bindings/web_filter_operations_impl.cc b/webkit/renderer/compositor_bindings/web_filter_operations_impl.cc index 76f22d7..6fe6e27 100644 --- a/webkit/renderer/compositor_bindings/web_filter_operations_impl.cc +++ b/webkit/renderer/compositor_bindings/web_filter_operations_impl.cc @@ -5,6 +5,7 @@ #include "webkit/renderer/compositor_bindings/web_filter_operations_impl.h" #include "base/basictypes.h" +#include "skia/ext/refptr.h" #include "third_party/WebKit/public/platform/WebColor.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/skia/include/core/SkScalar.h" @@ -79,6 +80,12 @@ void WebFilterOperationsImpl::appendSaturatingBrightnessFilter(float amount) { cc::FilterOperation::CreateSaturatingBrightnessFilter(amount)); } +void WebFilterOperationsImpl::appendReferenceFilter( + SkImageFilter* image_filter) { + filter_operations_.Append( + cc::FilterOperation::CreateReferenceFilter(skia::SharePtr(image_filter))); +} + void WebFilterOperationsImpl::clear() { filter_operations_.Clear(); } diff --git a/webkit/renderer/compositor_bindings/web_filter_operations_impl.h b/webkit/renderer/compositor_bindings/web_filter_operations_impl.h index 35a6479..1a14f99 100644 --- a/webkit/renderer/compositor_bindings/web_filter_operations_impl.h +++ b/webkit/renderer/compositor_bindings/web_filter_operations_impl.h @@ -34,6 +34,7 @@ class WebFilterOperationsImpl : public WebKit::WebFilterOperations { virtual void appendColorMatrixFilter(SkScalar matrix[20]); virtual void appendZoomFilter(float amount, int inset); virtual void appendSaturatingBrightnessFilter(float amount); + virtual void appendReferenceFilter(SkImageFilter* image_filter); virtual void clear(); diff --git a/webkit/renderer/compositor_bindings/web_layer_impl.cc b/webkit/renderer/compositor_bindings/web_layer_impl.cc index f2a3cde..c0b56b8 100644 --- a/webkit/renderer/compositor_bindings/web_layer_impl.cc +++ b/webkit/renderer/compositor_bindings/web_layer_impl.cc @@ -178,8 +178,14 @@ void WebLayerImpl::setBackgroundFilters(const WebFilterOperations& filters) { layer_->SetBackgroundFilters(filters_impl.AsFilterOperations()); } +// TODO(ajuma): Remove this once the Blink CL that stops calling this lands. void WebLayerImpl::setFilter(SkImageFilter* filter) { - layer_->SetFilter(skia::SharePtr(filter)); + cc::FilterOperations filters; + if (filter) { + filters.Append( + cc::FilterOperation::CreateReferenceFilter(skia::SharePtr(filter))); + } + layer_->SetFilters(filters); } void WebLayerImpl::setCompositingReasons( |