summaryrefslogtreecommitdiffstats
path: root/cc/layers
diff options
context:
space:
mode:
Diffstat (limited to 'cc/layers')
-rw-r--r--cc/layers/compositing_reasons.h2
-rw-r--r--cc/layers/delegated_renderer_layer.cc11
-rw-r--r--cc/layers/delegated_renderer_layer_impl_unittest.cc45
-rw-r--r--cc/layers/layer.cc80
-rw-r--r--cc/layers/layer.h22
-rw-r--r--cc/layers/layer_impl.cc25
-rw-r--r--cc/layers/layer_impl.h13
-rw-r--r--cc/layers/layer_impl_unittest.cc33
-rw-r--r--cc/layers/layer_unittest.cc2
-rw-r--r--cc/layers/render_surface_impl.cc3
10 files changed, 195 insertions, 41 deletions
diff --git a/cc/layers/compositing_reasons.h b/cc/layers/compositing_reasons.h
index 02354a0..6331a90 100644
--- a/cc/layers/compositing_reasons.h
+++ b/cc/layers/compositing_reasons.h
@@ -53,6 +53,8 @@ const uint64 kCompositingReasonLayerForBackground = GG_UINT64_C(1) << 30;
const uint64 kCompositingReasonLayerForMask = GG_UINT64_C(1) << 31;
const uint64 kCompositingReasonOverflowScrollingParent = GG_UINT64_C(1) << 32;
const uint64 kCompositingReasonOutOfFlowClipping = GG_UINT64_C(1) << 33;
+const uint64 kCompositingReasonIsolateCompositedDescendants =
+ GG_UINT64_C(1) << 35;
typedef uint64 CompositingReasons;
diff --git a/cc/layers/delegated_renderer_layer.cc b/cc/layers/delegated_renderer_layer.cc
index a92b701..a940903 100644
--- a/cc/layers/delegated_renderer_layer.cc
+++ b/cc/layers/delegated_renderer_layer.cc
@@ -107,10 +107,13 @@ void DelegatedRendererLayer::SetDisplaySize(gfx::Size size) {
SetNeedsCommit();
}
-static bool FrameDataHasFilter(DelegatedFrameData* frame) {
+static bool FrameDataRequiresFilterContext(const DelegatedFrameData* frame) {
for (size_t i = 0; i < frame->render_pass_list.size(); ++i) {
const QuadList& quad_list = frame->render_pass_list[i]->quad_list;
for (size_t j = 0; j < quad_list.size(); ++j) {
+ if (quad_list[j]->shared_quad_state->blend_mode !=
+ SkXfermode::kSrcOver_Mode)
+ return true;
if (quad_list[j]->material != DrawQuad::RENDER_PASS)
continue;
const RenderPassDrawQuad* render_pass_quad =
@@ -133,9 +136,9 @@ bool DelegatedRendererLayer::Update(ResourceUpdateQueue* queue,
frame_provider_->GetFrameDataAndRefResources(this, &frame_damage_);
should_collect_new_frame_ = false;
- // If any quad has a filter operation, then we need a filter context to draw
- // this layer's content.
- if (FrameDataHasFilter(frame_data_) && layer_tree_host())
+ // If any quad has a filter operation or a blend mode other than normal,
+ // then we need an offscreen context to draw this layer's content.
+ if (FrameDataRequiresFilterContext(frame_data_))
layer_tree_host()->set_needs_filter_context();
return true;
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index c8811a2..8cb0f3e 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -529,13 +529,13 @@ class DelegatedRendererLayerImplTestTransform
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state = quad_sink.UseSharedQuadState(
SharedQuadState::Create());
- shared_quad_state->SetAll(
- child_pass_transform,
- child_pass_content_bounds,
- child_pass_rect,
- child_pass_clip_rect,
- child_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(child_pass_transform,
+ child_pass_content_bounds,
+ child_pass_rect,
+ child_pass_clip_rect,
+ child_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<SolidColorDrawQuad> color_quad;
color_quad = SolidColorDrawQuad::Create();
@@ -564,13 +564,13 @@ class DelegatedRendererLayerImplTestTransform
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state =
quad_sink.UseSharedQuadState(SharedQuadState::Create());
- shared_quad_state->SetAll(
- root_pass_transform,
- root_pass_content_bounds,
- root_pass_rect,
- root_pass_clip_rect,
- root_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(root_pass_transform,
+ root_pass_content_bounds,
+ root_pass_rect,
+ root_pass_clip_rect,
+ root_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
@@ -933,13 +933,13 @@ class DelegatedRendererLayerImplTestClip
AppendQuadsData data(pass->id);
SharedQuadState* shared_quad_state =
quad_sink.UseSharedQuadState(SharedQuadState::Create());
- shared_quad_state->SetAll(
- child_pass_transform,
- child_pass_content_bounds,
- child_pass_rect,
- child_pass_clip_rect,
- child_pass_clipped,
- 1.f);
+ shared_quad_state->SetAll(child_pass_transform,
+ child_pass_content_bounds,
+ child_pass_rect,
+ child_pass_clip_rect,
+ child_pass_clipped,
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<SolidColorDrawQuad> color_quad;
color_quad = SolidColorDrawQuad::Create();
@@ -971,7 +971,8 @@ class DelegatedRendererLayerImplTestClip
root_pass_rect,
root_pass_clip_rect,
root_pass_clipped,
- 1.f);
+ 1.f,
+ SkXfermode::kSrcOver_Mode);
scoped_ptr<RenderPassDrawQuad> render_pass_quad =
RenderPassDrawQuad::Create();
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index e0ffb5c..7790719 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -47,6 +47,8 @@ Layer::Layer()
background_color_(0),
compositing_reasons_(kCompositingReasonUnknown),
opacity_(1.f),
+ blend_mode_(SkXfermode::kSrcOver_Mode),
+ is_root_for_isolated_group_(false),
anchor_point_z_(0.f),
is_container_for_fixed_position_layers_(false),
is_drawable_(false),
@@ -125,8 +127,7 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) {
if (host && layer_animation_controller_->has_any_animation())
host->SetNeedsCommit();
- if (host && (!filters_.IsEmpty() || !background_filters_.IsEmpty()))
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
void Layer::SetNeedsUpdate() {
@@ -160,6 +161,15 @@ void Layer::SetNextCommitWaitsForActivation() {
layer_tree_host_->SetNextCommitWaitsForActivation();
}
+void Layer::SetNeedsFilterContextIfNeeded() {
+ if (!layer_tree_host_)
+ return;
+
+ if (!filters_.IsEmpty() || !background_filters_.IsEmpty() ||
+ !uses_default_blend_mode())
+ layer_tree_host_->set_needs_filter_context();
+}
+
void Layer::SetNeedsPushProperties() {
if (needs_push_properties_)
return;
@@ -471,8 +481,7 @@ void Layer::SetFilters(const FilterOperations& filters) {
return;
filters_ = filters;
SetNeedsCommit();
- if (!filters.IsEmpty() && layer_tree_host_)
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
bool Layer::FilterIsAnimating() const {
@@ -485,8 +494,7 @@ void Layer::SetBackgroundFilters(const FilterOperations& filters) {
return;
background_filters_ = filters;
SetNeedsCommit();
- if (!filters.IsEmpty() && layer_tree_host_)
- layer_tree_host_->set_needs_filter_context();
+ SetNeedsFilterContextIfNeeded();
}
void Layer::SetOpacity(float opacity) {
@@ -505,6 +513,64 @@ bool Layer::OpacityCanAnimateOnImplThread() const {
return false;
}
+void Layer::SetBlendMode(SkXfermode::Mode blend_mode) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (blend_mode_ == blend_mode)
+ return;
+
+ // Allowing only blend modes that are defined in the CSS Compositing standard:
+ // http://dev.w3.org/fxtf/compositing-1/#blending
+ switch (blend_mode) {
+ case SkXfermode::kSrcOver_Mode:
+ case SkXfermode::kScreen_Mode:
+ case SkXfermode::kOverlay_Mode:
+ case SkXfermode::kDarken_Mode:
+ case SkXfermode::kLighten_Mode:
+ case SkXfermode::kColorDodge_Mode:
+ case SkXfermode::kColorBurn_Mode:
+ case SkXfermode::kHardLight_Mode:
+ case SkXfermode::kSoftLight_Mode:
+ case SkXfermode::kDifference_Mode:
+ case SkXfermode::kExclusion_Mode:
+ case SkXfermode::kMultiply_Mode:
+ case SkXfermode::kHue_Mode:
+ case SkXfermode::kSaturation_Mode:
+ case SkXfermode::kColor_Mode:
+ case SkXfermode::kLuminosity_Mode:
+ // supported blend modes
+ break;
+ case SkXfermode::kClear_Mode:
+ case SkXfermode::kSrc_Mode:
+ case SkXfermode::kDst_Mode:
+ case SkXfermode::kDstOver_Mode:
+ case SkXfermode::kSrcIn_Mode:
+ case SkXfermode::kDstIn_Mode:
+ case SkXfermode::kSrcOut_Mode:
+ case SkXfermode::kDstOut_Mode:
+ case SkXfermode::kSrcATop_Mode:
+ case SkXfermode::kDstATop_Mode:
+ case SkXfermode::kXor_Mode:
+ case SkXfermode::kPlus_Mode:
+ case SkXfermode::kModulate_Mode:
+ // Porter Duff Compositing Operators are not yet supported
+ // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators
+ NOTREACHED();
+ return;
+ }
+
+ blend_mode_ = blend_mode;
+ SetNeedsCommit();
+ SetNeedsFilterContextIfNeeded();
+}
+
+void Layer::SetIsRootForIsolatedGroup(bool root) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (is_root_for_isolated_group_ == root)
+ return;
+ is_root_for_isolated_group_ = root;
+ SetNeedsCommit();
+}
+
void Layer::SetContentsOpaque(bool opaque) {
DCHECK(IsPropertyChangeAllowed());
if (contents_opaque_ == opaque)
@@ -832,6 +898,8 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating())
layer->SetOpacity(opacity_);
DCHECK(!(OpacityIsAnimating() && layer->OpacityIsAnimatingOnImplOnly()));
+ layer->SetBlendMode(blend_mode_);
+ layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
layer->SetPosition(position_);
layer->SetIsContainerForFixedPositionLayers(
IsContainerForFixedPositionLayers());
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index b552a35..9af3dea 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -29,6 +29,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/transform.h"
@@ -126,6 +127,22 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
bool OpacityIsAnimating() const;
virtual bool OpacityCanAnimateOnImplThread() const;
+ void SetBlendMode(SkXfermode::Mode blend_mode);
+ SkXfermode::Mode blend_mode() const { return blend_mode_; }
+
+ bool uses_default_blend_mode() const {
+ return blend_mode_ == SkXfermode::kSrcOver_Mode;
+ }
+
+ // A layer is root for an isolated group when it and all its descendants are
+ // drawn over a black and fully transparent background, creating an isolated
+ // group. It should be used along with SetBlendMode(), in order to restrict
+ // layers within the group to blend with layers outside this group.
+ void SetIsRootForIsolatedGroup(bool root);
+ bool is_root_for_isolated_group() const {
+ return is_root_for_isolated_group_;
+ }
+
void SetFilters(const FilterOperations& filters);
const FilterOperations& filters() const { return filters_; }
bool FilterIsAnimating() const;
@@ -459,6 +476,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
// unused resources on the impl thread are returned before commit completes.
void SetNextCommitWaitsForActivation();
+ // Called when the blend mode or filters have been changed.
+ void SetNeedsFilterContextIfNeeded();
+
void SetNeedsPushProperties();
void AddDependentNeedsPushProperties();
void RemoveDependentNeedsPushProperties();
@@ -552,6 +572,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
SkColor background_color_;
CompositingReasons compositing_reasons_;
float opacity_;
+ SkXfermode::Mode blend_mode_;
+ bool is_root_for_isolated_group_;
FilterOperations filters_;
FilterOperations background_filters_;
float anchor_point_z_;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 99f9502..f8882291 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -53,6 +53,8 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
masks_to_bounds_(false),
contents_opaque_(false),
opacity_(1.0),
+ blend_mode_(SkXfermode::kSrcOver_Mode),
+ is_root_for_isolated_group_(false),
preserves_3d_(false),
use_parent_backface_visibility_(false),
draw_checkerboard_for_missing_tiles_(false),
@@ -246,7 +248,8 @@ scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
draw_properties_.visible_content_rect,
draw_properties_.clip_rect,
draw_properties_.is_clipped,
- draw_properties_.opacity);
+ draw_properties_.opacity,
+ blend_mode_);
return state.Pass();
}
@@ -524,6 +527,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
layer->SetContentsOpaque(contents_opaque_);
layer->SetOpacity(opacity_);
+ layer->SetBlendMode(blend_mode_);
+ layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
layer->SetPosition(position_);
layer->SetIsContainerForFixedPositionLayers(
is_container_for_fixed_position_layers_);
@@ -880,6 +885,21 @@ bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
return opacity_animation && opacity_animation->is_impl_only();
}
+void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) {
+ if (blend_mode_ == blend_mode)
+ return;
+
+ blend_mode_ = blend_mode;
+ NoteLayerPropertyChangedForSubtree();
+}
+
+void LayerImpl::SetIsRootForIsolatedGroup(bool root) {
+ if (is_root_for_isolated_group_ == root)
+ return;
+
+ is_root_for_isolated_group_ = root;
+}
+
void LayerImpl::SetPosition(gfx::PointF position) {
if (position_ == position)
return;
@@ -1281,6 +1301,9 @@ CompositingReasonsAsValue(CompositingReasons reasons) {
if (reasons & kCompositingReasonOutOfFlowClipping)
reason_list->AppendString("Has clipping ancestor");
+ if (reasons & kCompositingReasonIsolateCompositedDescendants)
+ reason_list->AppendString("Should isolate composited descendants");
+
return reason_list.PassAs<base::Value>();
}
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 6d06b6d2..1969b74 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -213,6 +213,17 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
bool OpacityIsAnimating() const;
bool OpacityIsAnimatingOnImplOnly() const;
+ void SetBlendMode(SkXfermode::Mode);
+ SkXfermode::Mode blend_mode() const { return blend_mode_; }
+ bool uses_default_blend_mode() const {
+ return blend_mode_ == SkXfermode::kSrcOver_Mode;
+ }
+
+ void SetIsRootForIsolatedGroup(bool root);
+ bool is_root_for_isolated_group() const {
+ return is_root_for_isolated_group_;
+ }
+
void SetPosition(gfx::PointF position);
gfx::PointF position() const { return position_; }
@@ -571,6 +582,8 @@ class CC_EXPORT LayerImpl : LayerAnimationValueObserver {
bool masks_to_bounds_;
bool contents_opaque_;
float opacity_;
+ SkXfermode::Mode blend_mode_;
+ bool is_root_for_isolated_group_;
gfx::PointF position_;
bool preserves_3d_;
bool use_parent_backface_visibility_;
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc
index 2d3305c..c43adff 100644
--- a/cc/layers/layer_impl_unittest.cc
+++ b/cc/layers/layer_impl_unittest.cc
@@ -40,6 +40,13 @@ namespace {
EXPECT_FALSE(child->LayerPropertyChanged()); \
EXPECT_FALSE(grand_child->LayerPropertyChanged());
+#define EXECUTE_AND_VERIFY_ONLY_DESCENDANTS_CHANGED(code_to_test) \
+ root->ResetAllChangeTrackingForSubtree(); \
+ code_to_test; \
+ EXPECT_FALSE(root->LayerPropertyChanged()); \
+ EXPECT_TRUE(child->LayerPropertyChanged()); \
+ EXPECT_TRUE(grand_child->LayerPropertyChanged());
+
#define VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(code_to_test) \
root->ResetAllChangeTrackingForSubtree(); \
host_impl.ForcePrepareToDraw(); \
@@ -91,6 +98,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
FilterOperations arbitrary_filters;
arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
+ SkXfermode::Mode arbitrary_blend_mode = SkXfermode::kMultiply_Mode;
// These properties are internal, and should not be considered "change" when
// they are used.
@@ -119,6 +127,7 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetScrollOffset(arbitrary_vector2d));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetHideLayerAndSubtree(true));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetOpacity(arbitrary_number));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBlendMode(arbitrary_blend_mode));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetTransform(arbitrary_transform));
// Changing these properties only affects the layer itself.
@@ -131,13 +140,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(
root->SetBackgroundFilters(arbitrary_filters));
- // Special case: check that sublayer transform changes all layer's
- // descendants, but not the layer itself.
- root->ResetAllChangeTrackingForSubtree();
- root->SetSublayerTransform(arbitrary_transform);
- EXPECT_FALSE(root->LayerPropertyChanged());
- EXPECT_TRUE(child->LayerPropertyChanged());
- EXPECT_TRUE(grand_child->LayerPropertyChanged());
+ // Changing these properties affects all layer's descendants,
+ // but not the layer itself.
+ EXECUTE_AND_VERIFY_ONLY_DESCENDANTS_CHANGED(
+ root->SetSublayerTransform(arbitrary_transform));
// Special case: check that SetBounds changes behavior depending on
// masksToBounds.
@@ -148,6 +154,9 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
// changed.
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBounds(arbitrary_size));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetIsRootForIsolatedGroup(true));
+
// After setting all these properties already, setting to the exact same
// values again should not cause any change.
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
@@ -172,6 +181,10 @@ TEST(LayerImplTest, VerifyLayerChangesAreTrackedProperly) {
root->SetContentsScale(arbitrary_number, arbitrary_number));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetContentsOpaque(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetOpacity(arbitrary_number));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetBlendMode(arbitrary_blend_mode));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
+ root->SetIsRootForIsolatedGroup(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetDrawsContent(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(
root->SetSublayerTransform(arbitrary_transform));
@@ -199,6 +212,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
FilterOperations arbitrary_filters;
arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
+ SkXfermode::Mode arbitrary_blend_mode = SkXfermode::kMultiply_Mode;
// Related filter functions.
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetFilters(arbitrary_filters));
@@ -243,6 +257,7 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetBackgroundFilters(arbitrary_filters));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetOpacity(arbitrary_number));
+ VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetBlendMode(arbitrary_blend_mode));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetTransform(arbitrary_transform));
VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetSublayerTransform(arbitrary_transform));
@@ -251,6 +266,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->SetIsRootForIsolatedGroup(true));
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));
@@ -269,6 +285,9 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) {
root->SetBackgroundFilters(arbitrary_filters));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetOpacity(arbitrary_number));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
+ root->SetBlendMode(arbitrary_blend_mode));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(root->SetIsRootForIsolatedGroup(true));
+ VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetTransform(arbitrary_transform));
VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(
root->SetSublayerTransform(arbitrary_transform));
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 0414acb..a77a5fb 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -545,6 +545,8 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) {
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBackgroundColor(SK_ColorLTGRAY));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetMasksToBounds(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendMode(SkXfermode::kHue_Mode));
+ EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsRootForIsolatedGroup(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetContentsOpaque(true));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPosition(gfx::PointF(4.f, 9.f)));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetSublayerTransform(
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 660f5e4..53e60c7 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -156,7 +156,8 @@ void RenderSurfaceImpl::AppendQuads(QuadSink* quad_sink,
content_rect_,
clip_rect_,
is_clipped_,
- draw_opacity_);
+ draw_opacity_,
+ owning_layer_->blend_mode());
if (owning_layer_->ShowDebugBorders()) {
SkColor color = for_replica ?