Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp (115396 => 115397)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp 2012-04-27 01:40:10 UTC (rev 115396)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp 2012-04-27 02:17:03 UTC (rev 115397)
@@ -58,6 +58,23 @@
{
}
+static inline void expandDamageRectWithFilters(FloatRect& damageRect, const FilterOperations& filters)
+{
+ int top, right, bottom, left;
+ filters.getOutsets(top, right, bottom, left);
+ damageRect.move(-left, -top);
+ damageRect.expand(left + right, top + bottom);
+}
+
+static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect, const FloatRect& filterRect, const FilterOperations& filters)
+{
+ FloatRect expandedDamageRect = damageRect;
+ expandDamageRectWithFilters(expandedDamageRect, filters);
+ expandedDamageRect.intersect(filterRect);
+
+ damageRect.unite(expandedDamageRect);
+}
+
void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, CCLayerImpl* targetSurfaceMaskLayer, const FilterOperations& filters)
{
//
@@ -139,7 +156,8 @@
m_currentDamageRect.uniteIfNonZero(damageFromSurfaceMask);
m_currentDamageRect.uniteIfNonZero(damageFromLeftoverRects);
- expandDamageRectWithForegroundFilters(filters);
+ if (filters.hasFilterThatMovesPixels())
+ expandDamageRectWithFilters(m_currentDamageRect, filters);
}
// The next history map becomes the current map for the next frame.
@@ -166,6 +184,7 @@
FloatRect damageRect = FloatRect();
for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
+ // Visit layers in back-to-front order.
CCLayerImpl* layer = layerList[layerIndex];
if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<CCLayerImpl>(layer, targetSurfaceLayerID))
@@ -269,6 +288,11 @@
FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists.
saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace);
+ // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage
+ // that exists below this layer by that amount.
+ if (layer->backgroundFilters().hasFilterThatMovesPixels())
+ expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters());
+
FloatRect damageRectInLocalSpace;
if (surfaceIsNew || renderSurface->surfacePropertyChanged()) {
// The entire surface contributes damage.
@@ -311,17 +335,6 @@
}
}
-void CCDamageTracker::expandDamageRectWithForegroundFilters(const FilterOperations& filters)
-{
- // Filters can spread damage around in the surface.
- if (filters.hasFilterThatMovesPixels()) {
- int top, right, bottom, left;
- filters.getOutsets(top, right, bottom, left);
- m_currentDamageRect.move(-left, -top);
- m_currentDamageRect.expand(left + right, top + bottom);
- }
-}
-
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
Modified: trunk/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp (115396 => 115397)
--- trunk/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp 2012-04-27 01:40:10 UTC (rev 115396)
+++ trunk/Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp 2012-04-27 02:17:03 UTC (rev 115397)
@@ -365,7 +365,7 @@
CCLayerImpl* child = root->children()[0].get();
FilterOperations filters;
- filters.operations().append(BlurFilterOperation::create(Length(5, WebCore::Percent), FilterOperation::BLUR));
+ filters.operations().append(BlurFilterOperation::create(Length(5, WebCore::Fixed), FilterOperation::BLUR));
int outsetTop, outsetRight, outsetBottom, outsetLeft;
filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
root->setFilters(filters);
@@ -385,6 +385,77 @@
EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
}
+TEST_F(CCDamageTrackerTest, verifyDamageForBackgroundBlurredChild)
+{
+ OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
+ CCLayerImpl* child1 = root->children()[0].get();
+ CCLayerImpl* child2 = root->children()[1].get();
+
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(2, WebCore::Fixed), FilterOperation::BLUR));
+ int outsetTop, outsetRight, outsetBottom, outsetLeft;
+ filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft);
+ child1->setBackgroundFilters(filters);
+
+ // Setting the filter will damage the whole surface.
+ emulateDrawingOneFrame(root.get());
+
+ // CASE 1: Setting the update rect should cause the corresponding damage to
+ // the surface, blurred based on the size of the child's background blur
+ // filter.
+ root->setUpdateRect(FloatRect(297, 297, 2, 2));
+
+ emulateDrawingOneFrame(root.get());
+
+ FloatRect rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage position on the surface should be a composition of the damage on the root and on child2.
+ // Damage on the root should be: position of updateRect (297, 297), but expanded by the blur outsets.
+ FloatRect expectedDamageRect = FloatRect(297, 297, 2, 2);
+ expectedDamageRect.move(-outsetLeft, -outsetTop);
+ expectedDamageRect.expand(outsetLeft + outsetRight, outsetTop + outsetBottom);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 2: Setting the update rect should cause the corresponding damage to
+ // the surface, blurred based on the size of the child's background blur
+ // filter. Since the damage extends to the right/bottom outside of the
+ // blurred layer, only the left/top should end up expanded.
+ root->setUpdateRect(FloatRect(297, 297, 30, 30));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage position on the surface should be a composition of the damage on the root and on child2.
+ // Damage on the root should be: position of updateRect (297, 297), but expanded on the left/top
+ // by the blur outsets.
+ expectedDamageRect = FloatRect(297, 297, 30, 30);
+ expectedDamageRect.move(-outsetLeft, -outsetTop);
+ expectedDamageRect.expand(outsetLeft, outsetTop);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 3: Setting this update rect outside the contentBounds of the blurred
+ // child1 will not cause it to be expanded.
+ root->setUpdateRect(FloatRect(30, 30, 2, 2));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage on the root should be: position of updateRect (30, 30), not
+ // expanded.
+ expectedDamageRect = FloatRect(30, 30, 2, 2);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+
+ // CASE 4: Setting the update rect on child2, which is above child1, will
+ // not get blurred by child1, so it does not need to get expanded.
+ child2->setUpdateRect(FloatRect(0, 0, 1, 1));
+
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ // Damage on child2 should be: position of updateRect offset by the child's position (11, 11), and not expanded by anything.
+ expectedDamageRect = FloatRect(11, 11, 1, 1);
+ EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
+}
+
TEST_F(CCDamageTrackerTest, verifyDamageForAddingAndRemovingLayer)
{
OwnPtr<CCLayerImpl> root = createAndSetUpTestTreeWithOneSurface();