diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
index 0a3c2ed..56edff8 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
@@ -169,7 +169,13 @@ static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& e
IntRect& occlusionRect = affectedOcclusionRects[j];
// Shrink the rect by expanding the non-opaque pixels outside the rect.
- // To convert the expandedPixel IntRect to outsets:
+
+ // The expandedPixel is the IntRect for a single pixel after being
+ // expanded by filters on the layer. The original pixel would be
+ // IntRect(0, 0, 1, 1), and the expanded pixel is the rect, relative
+ // to this original rect, that the original pixel can influence after
+ // being filtered.
+ // To convert the expandedPixel IntRect back to filter outsets:
// x = -leftOutset
// width = leftOutset + rightOutset
// maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOutset
@@ -189,9 +195,12 @@ static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& e
}
template<typename RenderSurfaceType>
-static void reduceOcclusionBelowSurface(RenderSurfaceType* surface, const TransformationMatrix& surfaceTransform, RenderSurfaceType* surfaceTarget, Region& occlusionInTarget, Region& occlusionInScreen)
+static void reduceOcclusionBelowSurface(RenderSurfaceType* surface, const IntRect& surfaceRect, const TransformationMatrix& surfaceTransform, RenderSurfaceType* surfaceTarget, Region& occlusionInTarget, Region& occlusionInScreen)
{
- IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform, FloatRect(surface->contentRect())));
+ if (surfaceRect.isEmpty())
+ return;
+
+ IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform, FloatRect(surfaceRect)));
if (!surface->clipRect().isEmpty())
boundsInTarget.intersect(surface->clipRect());
@@ -225,6 +234,14 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToTargetRenderSu
if (oldTarget->hasReplica())
oldTargetOcclusionInNewTarget.unite(transformSurfaceOpaqueRegion<RenderSurfaceType>(oldTarget, m_stack[lastIndex].occlusionInTarget, oldTarget->replicaOriginTransform()));
+ IntRect unoccludedSurfaceRect;
+ IntRect unoccludedReplicaRect;
+ if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) {
+ unoccludedSurfaceRect = unoccludedContributingSurfaceContentRect(oldTarget, false, oldTarget->contentRect());
+ if (oldTarget->hasReplica())
+ unoccludedReplicaRect = unoccludedContributingSurfaceContentRect(oldTarget, true, oldTarget->contentRect());
+ }
+
if (surfaceWillBeAtTopAfterPop) {
// Merge the top of the stack down.
m_stack[lastIndex - 1].occlusionInScreen.unite(m_stack[lastIndex].occlusionInScreen);
@@ -237,9 +254,9 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToTargetRenderSu
}
if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) {
- reduceOcclusionBelowSurface(oldTarget, oldTarget->originTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
+ reduceOcclusionBelowSurface(oldTarget, unoccludedSurfaceRect, oldTarget->originTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
if (oldTarget->hasReplica())
- reduceOcclusionBelowSurface(oldTarget, oldTarget->replicaOriginTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
+ reduceOcclusionBelowSurface(oldTarget, unoccludedReplicaRect, oldTarget->replicaOriginTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().occlusionInScreen);
}
}
@@ -427,11 +444,11 @@ IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContentR
}
template<typename LayerType, typename RenderSurfaceType>
-IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContributingSurfaceContentRect(const LayerType* layer, bool forReplica, const IntRect& contentRect) const
+IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContributingSurfaceContentRect(const RenderSurfaceType* surface, bool forReplica, const IntRect& contentRect) const
{
ASSERT(!m_stack.isEmpty());
// This should be called while the contributing render surface is still considered the current target in the occlusion tracker.
- ASSERT(layer->targetRenderSurface() == m_stack.last().surface);
+ ASSERT(surface == m_stack.last().surface);
// A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is
// found just below the top of the stack (if it exists).
@@ -440,7 +457,6 @@ IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContribu
if (contentRect.isEmpty())
return contentRect;
- RenderSurfaceType* surface = layer->renderSurface();
const StackObject& secondLast = m_stack[m_stack.size() - 2];
IntRect surfaceClipRect = surface->clipRect();
@@ -486,7 +502,7 @@ template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leav
template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::markOccludedBehindLayer(const LayerChromium*);
template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::occluded(const LayerChromium*, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect) const;
-template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContributingSurfaceContentRect(const LayerChromium*, bool forReplica, const IntRect& contentRect) const;
+template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContributingSurfaceContentRect(const RenderSurfaceChromium*, bool forReplica, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::layerScissorRectInTargetSurface(const LayerChromium*) const;
template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, bool recordMetricsForFrame);
@@ -498,7 +514,7 @@ template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveToTarge
template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::markOccludedBehindLayer(const CCLayerImpl*);
template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::occluded(const CCLayerImpl*, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect) const;
-template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContributingSurfaceContentRect(const CCLayerImpl*, bool forReplica, const IntRect& contentRect) const;
+template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContributingSurfaceContentRect(const CCRenderSurface*, bool forReplica, const IntRect& contentRect) const;
template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::layerScissorRectInTargetSurface(const CCLayerImpl*) const;
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
index 2705c6b..b802cc6 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h
@@ -59,9 +59,9 @@ public:
// Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Used when considering occlusion for a layer that paints/draws something.
IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect) const;
- // Gives an unoccluded sub-rect of |contentRect| in the content space of the surface owned by |layer|. Used when considering occlusion for a contributing surface
+ // Gives an unoccluded sub-rect of |contentRect| in the content space of the surface. Used when considering occlusion for a contributing surface
// that is rendering into another target surface.
- IntRect unoccludedContributingSurfaceContentRect(const LayerType*, bool forReplica, const IntRect& contentRect) const;
+ IntRect unoccludedContributingSurfaceContentRect(const RenderSurfaceType*, bool forReplica, const IntRect& contentRect) const;
// Report operations for recording overdraw metrics.
CCOverdrawMetrics& overdrawMetrics() const { return *m_overdrawMetrics.get(); }
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
index 94d1d67..e5fd690 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
@@ -71,13 +71,13 @@ bool CCQuadCuller::append(PassOwnPtr<CCDrawQuad> passDrawQuad)
bool CCQuadCuller::appendSurface(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
- IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, false, passDrawQuad->quadRect());
+ IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer->renderSurface(), false, passDrawQuad->quadRect());
return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
}
bool CCQuadCuller::appendReplica(PassOwnPtr<CCDrawQuad> passDrawQuad)
{
- IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer, true, passDrawQuad->quadRect());
+ IntRect culledRect = m_occlusionTracker->unoccludedContributingSurfaceContentRect(m_layer->renderSurface(), true, passDrawQuad->quadRect());
return appendQuadInternal(passDrawQuad, culledRect, m_quadList, *m_occlusionTracker);
}