Skip to content

Commit

Permalink
Allow paint invalidation containers to cross frame boundaries. (re-land
Browse files Browse the repository at this point in the history
#2)

The previous commit was rolled out because it did not make the required changes
to PaintInvalidationState in order to teach it how to cross frame boundaries.

Previously, the *actual* paint invalidation container, meaning the enclosing
compositing layer / root RenderView, could already have been across a frame boundary.
The logic to do this correctly was done via special code in RenderView.

Instead, generalize the existing mechanisms to find a paint invalidation container
and map rects to repaint container coordinate space to cross frame boundaries.
This simplifies the code, and also causes paint invalidation rects to always be stored
in the coordinate space of their graphics layer backing. The latter is important if we want
to use these rects for determining which parts of a graphics layer need to be painted.

BUG=

Review URL: https://codereview.chromium.org/482063005

git-svn-id: svn://svn.chromium.org/blink/trunk@180736 bbb929c8-8fbe-4397-9dbb-9b2b20218538
  • Loading branch information
[email protected] committed Aug 21, 2014
1 parent 3758056 commit cb7d2bf
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"bounds": [800, 600],
"children": [
{
"bounds": [800, 600],
"contentsOpaque": true,
"drawsContent": true,
"repaintRects": [
[18, 418, 50, 50]
]
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/run-after-display.js"></script>
<script src="resources/text-based-repaint.js"></script>
<script>
window.onload = function() {
runRepaintTest();
};

function repaintTest() {
document.getElementsByTagName('iframe')[0]
.contentDocument
.getElementsByTagName('div')[0]
.style
.backgroundColor = 'green';
}
</script>
</head>
<div style="height: 400px"></div>
<iframe srcdoc="<div style='position: fixed; height: 50px; width: 50px; background-color: red;'></div>"></iframe>
Original file line number Diff line number Diff line change
@@ -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]
]
}
]
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/run-after-display.js"></script>
<script src="resources/text-based-repaint.js"></script>
<script>
window.onload = function() {
runRepaintTest();
};

function repaintTest() {
document.getElementsByTagName('iframe')[0]
.contentDocument
.getElementsByTagName('div')[0]
.style
.backgroundColor = 'green';
}
</script>
</head>
<div style="height: 400px"></div>
<div style="height: 200px; width: 200px; transform: translateZ(0)">
<iframe srcdoc="<div style='height: 50px; width: 50px; background-color: red;'></div>"></iframe>
</div>
2 changes: 1 addition & 1 deletion LayoutTests/fast/repaint/repaint-in-iframe-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"contentsOpaque": true,
"drawsContent": true,
"repaintRects": [
[18, 418, 284, 50]
[18, 418, 50, 50]
]
}
]
Expand Down
2 changes: 1 addition & 1 deletion LayoutTests/fast/repaint/repaint-in-iframe.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
</script>
</head>
<div style="height: 400px"></div>
<iframe srcdoc="<div style='height: 50px; background-color: red;'></div>"></iframe>
<iframe srcdoc="<div style='height: 50px; width: 50px; background-color: red;'></div>"></iframe>
12 changes: 6 additions & 6 deletions Source/core/frame/FrameView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 13 additions & 21 deletions Source/core/rendering/PaintInvalidationState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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;
}

Expand Down
7 changes: 4 additions & 3 deletions Source/core/rendering/PaintInvalidationState.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ class RenderBox;
class RenderInline;
class RenderLayerModelObject;
class RenderObject;
class RenderView;
class RenderSVGModelObject;

class PaintInvalidationState {
WTF_MAKE_NONCOPYABLE(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; }
Expand All @@ -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
{
Expand All @@ -55,7 +56,7 @@ class PaintInvalidationState {

const RenderLayerModelObject& m_paintInvalidationContainer;

RenderObject& m_renderer;
const RenderObject& m_renderer;
};

} // namespace blink
Expand Down
18 changes: 1 addition & 17 deletions Source/core/rendering/RenderLayerRepainter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
32 changes: 20 additions & 12 deletions Source/core/rendering/RenderObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 1 addition & 4 deletions Source/core/rendering/RenderObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -890,10 +890,7 @@ class RenderObject : public NoBaseWillBeGarbageCollectedFinalized<RenderObject>,

// 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;
Expand Down
Loading

0 comments on commit cb7d2bf

Please sign in to comment.