Skip to content

Commit cb7d2bf

Browse files
author
chrishtr@chromium.org
committed
Allow paint invalidation containers to cross frame boundaries. (re-land #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
1 parent 3758056 commit cb7d2bf

14 files changed

+160
-93
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"bounds": [800, 600],
3+
"children": [
4+
{
5+
"bounds": [800, 600],
6+
"contentsOpaque": true,
7+
"drawsContent": true,
8+
"repaintRects": [
9+
[18, 418, 50, 50]
10+
]
11+
}
12+
]
13+
}
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="../../resources/run-after-display.js"></script>
5+
<script src="resources/text-based-repaint.js"></script>
6+
<script>
7+
window.onload = function() {
8+
runRepaintTest();
9+
};
10+
11+
function repaintTest() {
12+
document.getElementsByTagName('iframe')[0]
13+
.contentDocument
14+
.getElementsByTagName('div')[0]
15+
.style
16+
.backgroundColor = 'green';
17+
}
18+
</script>
19+
</head>
20+
<div style="height: 400px"></div>
21+
<iframe srcdoc="<div style='position: fixed; height: 50px; width: 50px; background-color: red;'></div>"></iframe>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"bounds": [785, 616],
3+
"children": [
4+
{
5+
"bounds": [785, 616],
6+
"contentsOpaque": true,
7+
"drawsContent": true,
8+
"children": [
9+
{
10+
"position": [8, 408],
11+
"transformOrigin": [100, 100],
12+
"bounds": [304, 200],
13+
"drawsContent": true,
14+
"repaintRects": [
15+
[10, 10, 50, 50]
16+
]
17+
}
18+
]
19+
}
20+
]
21+
}
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<script src="../../resources/run-after-display.js"></script>
5+
<script src="resources/text-based-repaint.js"></script>
6+
<script>
7+
window.onload = function() {
8+
runRepaintTest();
9+
};
10+
11+
function repaintTest() {
12+
document.getElementsByTagName('iframe')[0]
13+
.contentDocument
14+
.getElementsByTagName('div')[0]
15+
.style
16+
.backgroundColor = 'green';
17+
}
18+
</script>
19+
</head>
20+
<div style="height: 400px"></div>
21+
<div style="height: 200px; width: 200px; transform: translateZ(0)">
22+
<iframe srcdoc="<div style='height: 50px; width: 50px; background-color: red;'></div>"></iframe>
23+
</div>

LayoutTests/fast/repaint/repaint-in-iframe-expected.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"contentsOpaque": true,
77
"drawsContent": true,
88
"repaintRects": [
9-
[18, 418, 284, 50]
9+
[18, 418, 50, 50]
1010
]
1111
}
1212
]

LayoutTests/fast/repaint/repaint-in-iframe.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
</script>
1919
</head>
2020
<div style="height: 400px"></div>
21-
<iframe srcdoc="<div style='height: 50px; background-color: red;'></div>"></iframe>
21+
<iframe srcdoc="<div style='height: 50px; width: 50px; background-color: red;'></div>"></iframe>

Source/core/frame/FrameView.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -965,14 +965,14 @@ void FrameView::layout(bool allowSubtree)
965965
// See http://crbug.com/306706
966966
void FrameView::invalidateTreeIfNeeded()
967967
{
968-
RenderObject* rootForPaintInvalidation = renderView();
969-
ASSERT(!rootForPaintInvalidation->needsLayout());
968+
RenderView& rootForPaintInvalidation = *renderView();
969+
ASSERT(!rootForPaintInvalidation.needsLayout());
970970

971-
TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation->debugName().ascii());
971+
TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation.debugName().ascii());
972972

973-
PaintInvalidationState rootPaintInvalidationState(*rootForPaintInvalidation);
973+
PaintInvalidationState rootPaintInvalidationState(rootForPaintInvalidation);
974974

975-
rootForPaintInvalidation->invalidateTreeIfNeeded(rootPaintInvalidationState);
975+
rootForPaintInvalidation.invalidateTreeIfNeeded(rootPaintInvalidationState);
976976

977977
// Invalidate the paint of the frameviews scrollbars if needed
978978
if (hasVerticalBarDamage())
@@ -1604,7 +1604,7 @@ HostWindow* FrameView::hostWindow() const
16041604
void FrameView::contentRectangleForPaintInvalidation(const IntRect& r)
16051605
{
16061606
ASSERT(paintInvalidationIsAllowed());
1607-
ASSERT(!m_frame->owner());
1607+
ASSERT(!m_frame->ownerRenderer());
16081608

16091609
if (m_isTrackingPaintInvalidations) {
16101610
IntRect paintInvalidationRect = r;

Source/core/rendering/PaintInvalidationState.cpp

+13-21
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,25 @@
1313

1414
namespace blink {
1515

16-
PaintInvalidationState::PaintInvalidationState(RenderObject& renderer)
16+
PaintInvalidationState::PaintInvalidationState(const RenderView& renderView)
1717
: m_clipped(false)
1818
, m_cachedOffsetsEnabled(true)
1919
, m_forceCheckForPaintInvalidation(false)
20-
, m_paintInvalidationContainer(*renderer.containerForPaintInvalidation())
21-
, m_renderer(renderer)
20+
, m_paintInvalidationContainer(*renderView.containerForPaintInvalidation())
21+
, m_renderer(renderView)
2222
{
2323
bool establishesPaintInvalidationContainer = &m_renderer == &m_paintInvalidationContainer;
2424
if (!establishesPaintInvalidationContainer) {
25-
if (!renderer.supportsPaintInvalidationStateCachedOffsets()) {
25+
if (!renderView.supportsPaintInvalidationStateCachedOffsets()) {
2626
m_cachedOffsetsEnabled = false;
2727
return;
2828
}
29-
bool invalidationContainerSkipped;
30-
RenderObject* container = renderer.container(&m_paintInvalidationContainer, &invalidationContainerSkipped);
31-
if (container && !invalidationContainerSkipped) {
32-
FloatPoint point = container->localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer);
33-
if (container->isTableRow())
34-
point = FloatPoint(point.x() - toRenderBox(container)->x().toFloat(), point.y() - toRenderBox(container)->y().toFloat());
35-
m_paintOffset = LayoutSize(point.x(), point.y());
36-
37-
applyClipIfNeeded(*container);
38-
}
39-
} else {
40-
applyClipIfNeeded(m_renderer);
29+
FloatPoint point = renderView.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
30+
m_paintOffset = LayoutSize(point.x(), point.y());
4131
}
32+
m_clipRect = renderView.viewRect();
33+
m_clipRect.move(m_paintOffset);
34+
m_clipped = true;
4235
}
4336

4437
PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& next, RenderLayerModelObject& renderer, const RenderLayerModelObject& paintInvalidationContainer)
@@ -50,7 +43,7 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& nex
5043
{
5144
// FIXME: SVG could probably benefit from a stack-based optimization like html does. crbug.com/391054
5245
bool establishesPaintInvalidationContainer = &m_renderer == &m_paintInvalidationContainer;
53-
bool fixed = m_renderer.isOutOfFlowPositioned() && m_renderer.style()->position() == FixedPosition;
46+
bool fixed = m_renderer.style()->position() == FixedPosition;
5447

5548
if (establishesPaintInvalidationContainer) {
5649
// When we hit a new paint invalidation container, we don't need to
@@ -61,12 +54,11 @@ PaintInvalidationState::PaintInvalidationState(const PaintInvalidationState& nex
6154
if (!renderer.supportsPaintInvalidationStateCachedOffsets() || !next.m_cachedOffsetsEnabled) {
6255
m_cachedOffsetsEnabled = false;
6356
} else {
64-
LayoutSize offset = m_renderer.isBox() && !m_renderer.isTableRow() ? toRenderBox(renderer).locationOffset() : LayoutSize();
6557
if (fixed) {
66-
// FIXME: This doesn't work correctly with transforms.
67-
FloatPoint fixedOffset = m_renderer.view()->localToAbsolute(FloatPoint(), IsFixed);
68-
m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
58+
FloatPoint fixedOffset = m_renderer.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries);
59+
m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y());
6960
} else {
61+
LayoutSize offset = m_renderer.isBox() && !m_renderer.isTableRow() ? toRenderBox(renderer).locationOffset() : LayoutSize();
7062
m_paintOffset = next.m_paintOffset + offset;
7163
}
7264

Source/core/rendering/PaintInvalidationState.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ class RenderBox;
1414
class RenderInline;
1515
class RenderLayerModelObject;
1616
class RenderObject;
17+
class RenderView;
1718
class RenderSVGModelObject;
1819

1920
class PaintInvalidationState {
2021
WTF_MAKE_NONCOPYABLE(PaintInvalidationState);
2122
public:
2223
PaintInvalidationState(const PaintInvalidationState& next, RenderLayerModelObject& renderer, const RenderLayerModelObject& paintInvalidationContainer);
2324

24-
explicit PaintInvalidationState(RenderObject&);
25+
explicit PaintInvalidationState(const RenderView&);
2526

2627
const LayoutRect& clipRect() const { return m_clipRect; }
2728
const LayoutSize& paintOffset() const { return m_paintOffset; }
@@ -33,7 +34,7 @@ class PaintInvalidationState {
3334
void setForceCheckForPaintInvalidation() { m_forceCheckForPaintInvalidation = true; }
3435

3536
const RenderLayerModelObject& paintInvalidationContainer() const { return m_paintInvalidationContainer; }
36-
RenderObject& renderer() const { return m_renderer; }
37+
const RenderObject& renderer() const { return m_renderer; }
3738

3839
bool canMapToContainer(const RenderLayerModelObject* container) const
3940
{
@@ -55,7 +56,7 @@ class PaintInvalidationState {
5556

5657
const RenderLayerModelObject& m_paintInvalidationContainer;
5758

58-
RenderObject& m_renderer;
59+
const RenderObject& m_renderer;
5960
};
6061

6162
} // namespace blink

Source/core/rendering/RenderLayerRepainter.cpp

+1-17
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,7 @@ void RenderLayerRepainter::setBackingNeedsPaintInvalidationInRect(const LayoutRe
110110
// https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
111111
// so assert but check that the layer is composited.
112112
ASSERT(m_renderer.compositingState() != NotComposited);
113-
if (m_renderer.compositingState() == NotComposited) {
114-
// If we're trying to issue paint invalidations of the placeholder document layer, propagate the
115-
// paint invalidation to the native view system.
116-
LayoutRect absRect(r);
117-
LayoutPoint delta;
118-
m_renderer.layer()->convertToLayerCoords(m_renderer.layer()->root(), delta);
119-
absRect.moveBy(delta);
120-
121-
if (absRect.isEmpty())
122-
return;
123-
124-
RenderView* view = m_renderer.view();
125-
if (view)
126-
view->invalidatePaintForRectangle(absRect);
127-
return;
128-
}
129-
// FIXME: generalize accessors to backing GraphicsLayers so that this code is squasphing-agnostic.
113+
// FIXME: generalize accessors to backing GraphicsLayers so that this code is squashing-agnostic.
130114
if (m_renderer.layer()->groupedMapping()) {
131115
LayoutRect paintInvalidationRect = r;
132116
paintInvalidationRect.move(m_renderer.layer()->subpixelAccumulation());

Source/core/rendering/RenderObject.cpp

+20-12
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "core/rendering/RenderListItem.h"
6767
#include "core/rendering/RenderMarquee.h"
6868
#include "core/rendering/RenderObjectInlines.h"
69+
#include "core/rendering/RenderPart.h"
6970
#include "core/rendering/RenderScrollbarPart.h"
7071
#include "core/rendering/RenderTableCaption.h"
7172
#include "core/rendering/RenderTableCell.h"
@@ -1445,13 +1446,11 @@ const RenderLayerModelObject* RenderObject::containerForPaintInvalidation() cons
14451446
const RenderLayerModelObject* RenderObject::enclosingCompositedContainer() const
14461447
{
14471448
RenderLayerModelObject* container = 0;
1448-
if (view()->usesCompositing()) {
1449-
// FIXME: CompositingState is not necessarily up to date for many callers of this function.
1450-
DisableCompositingQueryAsserts disabler;
1449+
// FIXME: CompositingState is not necessarily up to date for many callers of this function.
1450+
DisableCompositingQueryAsserts disabler;
14511451

1452-
if (RenderLayer* compositingLayer = enclosingLayer()->enclosingLayerForPaintInvalidation())
1453-
container = compositingLayer->renderer();
1454-
}
1452+
if (RenderLayer* compositingLayer = enclosingLayer()->enclosingLayerForPaintInvalidationCrossingFrameBoundaries())
1453+
container = compositingLayer->renderer();
14551454
return container;
14561455
}
14571456

@@ -1466,7 +1465,14 @@ const RenderLayerModelObject* RenderObject::adjustCompositedContainerForSpecialA
14661465
if (!paintInvalidationContainer || paintInvalidationContainer->flowThreadContainingBlock() != parentRenderFlowThread)
14671466
paintInvalidationContainer = parentRenderFlowThread;
14681467
}
1469-
return paintInvalidationContainer ? paintInvalidationContainer : view();
1468+
1469+
if (paintInvalidationContainer)
1470+
return paintInvalidationContainer;
1471+
1472+
RenderView* renderView = view();
1473+
while (renderView->frame()->ownerRenderer())
1474+
renderView = renderView->frame()->ownerRenderer()->view();
1475+
return renderView;
14701476
}
14711477

14721478
bool RenderObject::isPaintInvalidationContainer() const
@@ -1525,14 +1531,11 @@ void RenderObject::invalidatePaintUsingContainer(const RenderLayerModelObject* p
15251531
return;
15261532
}
15271533

1528-
RenderView* v = view();
15291534
if (paintInvalidationContainer->isRenderView()) {
1530-
ASSERT(paintInvalidationContainer == v);
1531-
v->invalidatePaintForRectangle(r);
1535+
toRenderView(paintInvalidationContainer)->invalidatePaintForRectangle(r);
15321536
return;
15331537
}
1534-
1535-
if (v->usesCompositing()) {
1538+
if (paintInvalidationContainer->view()->usesCompositing()) {
15361539
ASSERT(paintInvalidationContainer->hasLayer() && (paintInvalidationContainer->layer()->compositingState() == PaintsIntoOwnBacking || paintInvalidationContainer->layer()->compositingState() == PaintsIntoGroupedBacking));
15371540
paintInvalidationContainer->layer()->paintInvalidator().setBackingNeedsPaintInvalidationInRect(r);
15381541
}
@@ -1763,6 +1766,11 @@ LayoutRect RenderObject::rectWithOutlineForPaintInvalidation(const RenderLayerMo
17631766
return r;
17641767
}
17651768

1769+
LayoutRect RenderObject::absoluteClippedOverflowRect() const
1770+
{
1771+
return clippedOverflowRectForPaintInvalidation(view());
1772+
}
1773+
17661774
LayoutRect RenderObject::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject*, const PaintInvalidationState*) const
17671775
{
17681776
ASSERT_NOT_REACHED();

Source/core/rendering/RenderObject.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -890,10 +890,7 @@ class RenderObject : public NoBaseWillBeGarbageCollectedFinalized<RenderObject>,
890890

891891
// Returns the rect that should have paint invalidated whenever this object changes. The rect is in the view's
892892
// coordinate space. This method deals with outlines and overflow.
893-
LayoutRect absoluteClippedOverflowRect() const
894-
{
895-
return clippedOverflowRectForPaintInvalidation(0);
896-
}
893+
LayoutRect absoluteClippedOverflowRect() const;
897894
IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
898895
virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0) const;
899896
virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* = 0) const;

0 commit comments

Comments
 (0)