diff --git a/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe-expected.txt b/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe-expected.txt
new file mode 100644
index 00000000000..9e173047fea
--- /dev/null
+++ b/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe-expected.txt
@@ -0,0 +1,14 @@
+{
+ "bounds": [800, 600],
+ "children": [
+ {
+ "bounds": [800, 600],
+ "contentsOpaque": true,
+ "drawsContent": true,
+ "repaintRects": [
+ [18, 418, 50, 50]
+ ]
+ }
+ ]
+}
+
diff --git a/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe.html b/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe.html
new file mode 100644
index 00000000000..9b53f96ec1a
--- /dev/null
+++ b/LayoutTests/fast/repaint/invalidate-paint-for-fixed-pos-inside-iframe.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
diff --git a/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer-expected.txt b/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer-expected.txt
new file mode 100644
index 00000000000..e0b97835b53
--- /dev/null
+++ b/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer-expected.txt
@@ -0,0 +1,22 @@
+{
+ "bounds": [785, 616],
+ "children": [
+ {
+ "bounds": [785, 616],
+ "contentsOpaque": true,
+ "drawsContent": true,
+ "children": [
+ {
+ "position": [8, 408],
+ "transformOrigin": [100, 100],
+ "bounds": [304, 200],
+ "drawsContent": true,
+ "repaintRects": [
+ [10, 10, 50, 50]
+ ]
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer.html b/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer.html
new file mode 100644
index 00000000000..3f07dff91d6
--- /dev/null
+++ b/LayoutTests/fast/repaint/invalidate-paint-in-iframe-in-composited-layer.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LayoutTests/fast/repaint/repaint-in-iframe-expected.txt b/LayoutTests/fast/repaint/repaint-in-iframe-expected.txt
index e40490720ef..9e173047fea 100644
--- a/LayoutTests/fast/repaint/repaint-in-iframe-expected.txt
+++ b/LayoutTests/fast/repaint/repaint-in-iframe-expected.txt
@@ -6,7 +6,7 @@
"contentsOpaque": true,
"drawsContent": true,
"repaintRects": [
- [18, 418, 284, 50]
+ [18, 418, 50, 50]
]
}
]
diff --git a/LayoutTests/fast/repaint/repaint-in-iframe.html b/LayoutTests/fast/repaint/repaint-in-iframe.html
index 9141495ff16..0cc28dceac9 100644
--- a/LayoutTests/fast/repaint/repaint-in-iframe.html
+++ b/LayoutTests/fast/repaint/repaint-in-iframe.html
@@ -18,4 +18,4 @@
-
+
diff --git a/Source/core/frame/FrameView.cpp b/Source/core/frame/FrameView.cpp
index 05659b0f631..6d6e8ef1c20 100644
--- a/Source/core/frame/FrameView.cpp
+++ b/Source/core/frame/FrameView.cpp
@@ -965,14 +965,14 @@ void FrameView::layout(bool allowSubtree)
// See http://crbug.com/306706
void FrameView::invalidateTreeIfNeeded()
{
- RenderObject* rootForPaintInvalidation = renderView();
- ASSERT(!rootForPaintInvalidation->needsLayout());
+ RenderView& rootForPaintInvalidation = *renderView();
+ ASSERT(!rootForPaintInvalidation.needsLayout());
- TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation->debugName().ascii());
+ TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation.debugName().ascii());
- PaintInvalidationState rootPaintInvalidationState(*rootForPaintInvalidation);
+ PaintInvalidationState rootPaintInvalidationState(rootForPaintInvalidation);
- rootForPaintInvalidation->invalidateTreeIfNeeded(rootPaintInvalidationState);
+ rootForPaintInvalidation.invalidateTreeIfNeeded(rootPaintInvalidationState);
// Invalidate the paint of the frameviews scrollbars if needed
if (hasVerticalBarDamage())
@@ -1604,7 +1604,7 @@ HostWindow* FrameView::hostWindow() const
void FrameView::contentRectangleForPaintInvalidation(const IntRect& r)
{
ASSERT(paintInvalidationIsAllowed());
- ASSERT(!m_frame->owner());
+ ASSERT(!m_frame->ownerRenderer());
if (m_isTrackingPaintInvalidations) {
IntRect paintInvalidationRect = r;
diff --git a/Source/core/rendering/PaintInvalidationState.cpp b/Source/core/rendering/PaintInvalidationState.cpp
index 12753da0aa2..c5287961dc8 100644
--- a/Source/core/rendering/PaintInvalidationState.cpp
+++ b/Source/core/rendering/PaintInvalidationState.cpp
@@ -13,32 +13,25 @@
namespace blink {
-PaintInvalidationState::PaintInvalidationState(RenderObject& renderer)
+PaintInvalidationState::PaintInvalidationState(const RenderView& renderView)
: m_clipped(false)
, m_cachedOffsetsEnabled(true)
, m_forceCheckForPaintInvalidation(false)
- , m_paintInvalidationContainer(*renderer.containerForPaintInvalidation())
- , m_renderer(renderer)
+ , m_paintInvalidationContainer(*renderView.containerForPaintInvalidation())
+ , m_renderer(renderView)
{
bool establishesPaintInvalidationContainer = &m_renderer == &m_paintInvalidationContainer;
if (!establishesPaintInvalidationContainer) {
- if (!renderer.supportsPaintInvalidationStateCachedOffsets()) {
+ if (!renderView.supportsPaintInvalidationStateCachedOffsets()) {
m_cachedOffsetsEnabled = false;
return;
}
- bool invalidationContainerSkipped;
- RenderObject* container = renderer.container(&m_paintInvalidationContainer, &invalidationContainerSkipped);
- if (container && !invalidationContainerSkipped) {
- FloatPoint point = container->localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer);
- if (container->isTableRow())
- point = FloatPoint(point.x() - toRenderBox(container)->x().toFloat(), point.y() - toRenderBox(container)->y().toFloat());
- m_paintOffset = LayoutSize(point.x(), point.y());
-
- applyClipIfNeeded(*container);
- }
- } else {
- applyClipIfNeeded(m_renderer);
+ FloatPoint point = renderView.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
+ m_paintOffset = LayoutSize(point.x(), point.y());
}
+ m_clipRect = renderView.viewRect();
+ m_clipRect.move(m_paintOffset);
+ m_clipped = true;
}
PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& next, RenderLayerModelObject& renderer, const RenderLayerModelObject& paintInvalidationContainer)
@@ -50,7 +43,7 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& nex
{
// FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
bool establishesPaintInvalidationContainer = &m_renderer == &m_paintInvalidationContainer;
- bool fixed = m_renderer.isOutOfFlowPositioned() && m_renderer.style()->position() == FixedPosition;
+ bool fixed = m_renderer.style()->position() == FixedPosition;
if (establishesPaintInvalidationContainer) {
// When we hit a new paint invalidation container, we don't need to
@@ -61,12 +54,11 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& nex
if (!renderer.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled) {
m_cachedOffsetsEnabled = false;
} else {
- LayoutSize offset = m_renderer.isBox() && !m_renderer.isTableRow() ? toRenderBox(renderer).locationOffset() : LayoutSize();
if (fixed) {
- // FIXME: This doesn't work correctly with transforms.
- FloatPoint fixedOffset = m_renderer.view()->localToAbsolute(FloatPoint(), IsFixed);
- m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
+ FloatPoint fixedOffset = m_renderer.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
+ m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y());
} else {
+ LayoutSize offset = m_renderer.isBox() && !m_renderer.isTableRow() ? toRenderBox(renderer).locationOffset() : LayoutSize();
m_paintOffset = next.m_paintOffset + offset;
}
diff --git a/Source/core/rendering/PaintInvalidationState.h b/Source/core/rendering/PaintInvalidationState.h
index 8f0765857de..d7dcd2ec013 100644
--- a/Source/core/rendering/PaintInvalidationState.h
+++ b/Source/core/rendering/PaintInvalidationState.h
@@ -14,6 +14,7 @@ class RenderBox;
class RenderInline;
class RenderLayerModelObject;
class RenderObject;
+class RenderView;
class RenderSVGModelObject;
class PaintInvalidationState {
@@ -21,7 +22,7 @@ class PaintInvalidationState {
public:
PaintInvalidationState(const PaintInvalidationState& next, RenderLayerModelObject& renderer, const RenderLayerModelObject& paintInvalidationContainer);
- explicit PaintInvalidationState(RenderObject&);
+ explicit PaintInvalidationState(const RenderView&);
const LayoutRect& clipRect() const { return m_clipRect; }
const LayoutSize& paintOffset() const { return m_paintOffset; }
@@ -33,7 +34,7 @@ class PaintInvalidationState {
void setForceCheckForPaintInvalidation() { m_forceCheckForPaintInvalidation = true; }
const RenderLayerModelObject& paintInvalidationContainer() const { return m_paintInvalidationContainer; }
- RenderObject& renderer() const { return m_renderer; }
+ const RenderObject& renderer() const { return m_renderer; }
bool canMapToContainer(const RenderLayerModelObject* container) const
{
@@ -55,7 +56,7 @@ class PaintInvalidationState {
const RenderLayerModelObject& m_paintInvalidationContainer;
- RenderObject& m_renderer;
+ const RenderObject& m_renderer;
};
} // namespace blink
diff --git a/Source/core/rendering/RenderLayerRepainter.cpp b/Source/core/rendering/RenderLayerRepainter.cpp
index 29e712e8e91..62336f56365 100644
--- a/Source/core/rendering/RenderLayerRepainter.cpp
+++ b/Source/core/rendering/RenderLayerRepainter.cpp
@@ -110,23 +110,7 @@ void RenderLayerRepainter::setBackingNeedsPaintInvalidationInRect(const LayoutRe
// https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
// so assert but check that the layer is composited.
ASSERT(m_renderer.compositingState() != NotComposited);
- if (m_renderer.compositingState() == NotComposited) {
- // If we're trying to issue paint invalidations of the placeholder document layer, propagate the
- // paint invalidation to the native view system.
- LayoutRect absRect(r);
- LayoutPoint delta;
- m_renderer.layer()->convertToLayerCoords(m_renderer.layer()->root(), delta);
- absRect.moveBy(delta);
-
- if (absRect.isEmpty())
- return;
-
- RenderView* view = m_renderer.view();
- if (view)
- view->invalidatePaintForRectangle(absRect);
- return;
- }
- // FIXME: generalize accessors to backing GraphicsLayers so that this code is squasphing-agnostic.
+ // FIXME: generalize accessors to backing GraphicsLayers so that this code is squashing-agnostic.
if (m_renderer.layer()->groupedMapping()) {
LayoutRect paintInvalidationRect = r;
paintInvalidationRect.move(m_renderer.layer()->subpixelAccumulation());
diff --git a/Source/core/rendering/RenderObject.cpp b/Source/core/rendering/RenderObject.cpp
index c976c3aee3d..0186feb8cbc 100644
--- a/Source/core/rendering/RenderObject.cpp
+++ b/Source/core/rendering/RenderObject.cpp
@@ -66,6 +66,7 @@
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderMarquee.h"
#include "core/rendering/RenderObjectInlines.h"
+#include "core/rendering/RenderPart.h"
#include "core/rendering/RenderScrollbarPart.h"
#include "core/rendering/RenderTableCaption.h"
#include "core/rendering/RenderTableCell.h"
@@ -1445,13 +1446,11 @@ const RenderLayerModelObject* RenderObject::containerForPaintInvalidation() cons
const RenderLayerModelObject* RenderObject::enclosingCompositedContainer() const
{
RenderLayerModelObject* container = 0;
- if (view()->usesCompositing()) {
- // FIXME: CompositingState is not necessarily up to date for many callers of this function.
- DisableCompositingQueryAsserts disabler;
+ // FIXME: CompositingState is not necessarily up to date for many callers of this function.
+ DisableCompositingQueryAsserts disabler;
- if (RenderLayer* compositingLayer = enclosingLayer()->enclosingLayerForPaintInvalidation())
- container = compositingLayer->renderer();
- }
+ if (RenderLayer* compositingLayer = enclosingLayer()->enclosingLayerForPaintInvalidationCrossingFrameBoundaries())
+ container = compositingLayer->renderer();
return container;
}
@@ -1466,7 +1465,14 @@ const RenderLayerModelObject* RenderObject::adjustCompositedContainerForSpecialA
if (!paintInvalidationContainer || paintInvalidationContainer->flowThreadContainingBlock() != parentRenderFlowThread)
paintInvalidationContainer = parentRenderFlowThread;
}
- return paintInvalidationContainer ? paintInvalidationContainer : view();
+
+ if (paintInvalidationContainer)
+ return paintInvalidationContainer;
+
+ RenderView* renderView = view();
+ while (renderView->frame()->ownerRenderer())
+ renderView = renderView->frame()->ownerRenderer()->view();
+ return renderView;
}
bool RenderObject::isPaintInvalidationContainer() const
@@ -1525,14 +1531,11 @@ void RenderObject::invalidatePaintUsingContainer(const RenderLayerModelObject* p
return;
}
- RenderView* v = view();
if (paintInvalidationContainer->isRenderView()) {
- ASSERT(paintInvalidationContainer == v);
- v->invalidatePaintForRectangle(r);
+ toRenderView(paintInvalidationContainer)->invalidatePaintForRectangle(r);
return;
}
-
- if (v->usesCompositing()) {
+ if (paintInvalidationContainer->view()->usesCompositing()) {
ASSERT(paintInvalidationContainer->hasLayer() && (paintInvalidationContainer->layer()->compositingState() == PaintsIntoOwnBacking || paintInvalidationContainer->layer()->compositingState() == PaintsIntoGroupedBacking));
paintInvalidationContainer->layer()->paintInvalidator().setBackingNeedsPaintInvalidationInRect(r);
}
@@ -1763,6 +1766,11 @@ LayoutRect RenderObject::rectWithOutlineForPaintInvalidation(const RenderLayerMo
return r;
}
+LayoutRect RenderObject::absoluteClippedOverflowRect() const
+{
+ return clippedOverflowRectForPaintInvalidation(view());
+}
+
LayoutRect RenderObject::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*, const PaintInvalidationState*) const
{
ASSERT_NOT_REACHED();
diff --git a/Source/core/rendering/RenderObject.h b/Source/core/rendering/RenderObject.h
index 6759aed9f69..61543211182 100644
--- a/Source/core/rendering/RenderObject.h
+++ b/Source/core/rendering/RenderObject.h
@@ -890,10 +890,7 @@ class RenderObject : public NoBaseWillBeGarbageCollectedFinalized,
// Returns the rect that should have paint invalidated whenever this object changes. The rect is in the view's
// coordinate space. This method deals with outlines and overflow.
- LayoutRect absoluteClippedOverflowRect() const
- {
- return clippedOverflowRectForPaintInvalidation(0);
- }
+ LayoutRect absoluteClippedOverflowRect() const;
IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0) const;
virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* = 0) const;
diff --git a/Source/core/rendering/RenderView.cpp b/Source/core/rendering/RenderView.cpp
index 36d94d166d7..8e8549ff5f0 100644
--- a/Source/core/rendering/RenderView.cpp
+++ b/Source/core/rendering/RenderView.cpp
@@ -294,10 +294,6 @@ void RenderView::mapLocalToContainer(const RenderLayerModelObject* paintInvalida
return;
}
}
-
- // If a container was specified, and was not 0 or the RenderView,
- // then we should have found it by now.
- ASSERT_ARG(paintInvalidationContainer, !paintInvalidationContainer);
}
const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
@@ -438,9 +434,12 @@ void RenderView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInval
// We specifically need to issue paint invalidations for the viewRect since other renderers
// short-circuit on full-paint invalidation.
- if (doingFullPaintInvalidation() && !viewRect().isEmpty())
- invalidatePaintForRectangle(viewRect());
-
+ LayoutRect dirtyRect = viewRect();
+ if (doingFullPaintInvalidation() && !dirtyRect.isEmpty()) {
+ const RenderLayerModelObject* paintInvalidationContainer = &paintInvalidationState.paintInvalidationContainer();
+ mapRectToPaintInvalidationBacking(paintInvalidationContainer, dirtyRect, IsNotFixedPosition, &paintInvalidationState);
+ invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRect, InvalidationFull);
+ }
RenderBlock::invalidateTreeIfNeeded(paintInvalidationState);
}
@@ -451,24 +450,12 @@ void RenderView::invalidatePaintForRectangle(const LayoutRect& paintInvalidation
if (document().printing() || !m_frameView)
return;
- // We always just invalidate the root view, since we could be an iframe that is clipped out
- // or even invisible.
- HTMLFrameOwnerElement* owner = document().ownerElement();
+ ASSERT(layer()->compositingState() == PaintsIntoOwnBacking || !frame()->ownerRenderer());
+
if (layer()->compositingState() == PaintsIntoOwnBacking) {
layer()->paintInvalidator().setBackingNeedsPaintInvalidationInRect(paintInvalidationRect);
- } else if (!owner) {
+ } else {
m_frameView->contentRectangleForPaintInvalidation(pixelSnappedIntRect(paintInvalidationRect));
- } else if (RenderBox* obj = owner->renderBox()) {
- // Intersect the viewport with the paint invalidation rect.
- LayoutRect viewRectangle = viewRect();
- LayoutRect rectToInvalidate = intersection(paintInvalidationRect, viewRectangle);
-
- // Adjust for scroll offset of the view.
- rectToInvalidate.moveBy(-viewRectangle.location());
-
- // Adjust for frame border.
- rectToInvalidate.moveBy(obj->contentBoxRect().location());
- obj->invalidatePaintRectangle(rectToInvalidate);
}
}
@@ -483,12 +470,8 @@ void RenderView::invalidatePaintForViewAndCompositedLayers()
compositor()->fullyInvalidatePaint();
}
-void RenderView::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, ViewportConstrainedPosition viewportConstraint, const PaintInvalidationState*) const
+void RenderView::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, ViewportConstrainedPosition viewportConstraint, const PaintInvalidationState* state) const
{
- // If a container was specified, and was not 0 or the RenderView,
- // then we should have found it by now.
- ASSERT_ARG(paintInvalidationContainer, !paintInvalidationContainer || paintInvalidationContainer == this);
-
if (document().printing())
return;
@@ -513,8 +496,30 @@ void RenderView::mapRectToPaintInvalidationBacking(const RenderLayerModelObject*
// Apply our transform if we have one (because of full page zooming).
if (!paintInvalidationContainer && layer() && layer()->transform())
rect = layer()->transform()->mapRect(rect);
+
+ ASSERT(paintInvalidationContainer);
+ if (paintInvalidationContainer == this)
+ return;
+
+ Element* owner = document().ownerElement();
+ if (!owner)
+ return;
+
+ if (RenderBox* obj = owner->renderBox()) {
+ // Intersect the viewport with the paint invalidation rect.
+ LayoutRect viewRectangle = viewRect();
+ rect.intersect(viewRectangle);
+
+ // Adjust for scroll offset of the view.
+ rect.moveBy(-viewRectangle.location());
+
+ // Adjust for frame border.
+ rect.moveBy(obj->contentBoxRect().location());
+ obj->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, IsNotFixedPosition, 0);
+ }
}
+
void RenderView::absoluteRects(Vector& rects, const LayoutPoint& accumulatedOffset) const
{
rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
diff --git a/Source/core/rendering/RenderView.h b/Source/core/rendering/RenderView.h
index 352a73d43b0..00ddd9ca4c1 100644
--- a/Source/core/rendering/RenderView.h
+++ b/Source/core/rendering/RenderView.h
@@ -156,6 +156,7 @@ class RenderView FINAL : public RenderBlockFlow {
void pushLayoutState(LayoutState&);
void popLayoutState();
+ virtual void invalidateTreeIfNeeded(const PaintInvalidationState&) OVERRIDE FINAL;
private:
virtual void mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0, const PaintInvalidationState* = 0) const OVERRIDE;
@@ -163,7 +164,6 @@ class RenderView FINAL : public RenderBlockFlow {
virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
virtual void computeSelfHitTestRects(Vector&, const LayoutPoint& layerOffset) const OVERRIDE;
- virtual void invalidateTreeIfNeeded(const PaintInvalidationState&) OVERRIDE FINAL;
bool shouldInvalidatePaint(const LayoutRect&) const;