Commit 346b1c32 authored by chrishtr's avatar chrishtr Committed by Commit bot

Remove paintOffsetTranslation for fixed-position elements.

Thus only transformed elements now paint with transform. The concept
of painting fixed-position elements with transform was introduced in
https://codereview.chromium.org/1110653003, to help with paint invalidation
of SPv1. However we ended up invalidating whole subtrees on scroll in v1,
so this is not necessary.

Also added invalidation of paint properties when changing compositing mode,
since this can affect whether paintsWithTransform changes its behavior.

BUG=674623
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2

Review-Url: https://codereview.chromium.org/2570423003
Cr-Commit-Position: refs/heads/master@{#440906}
parent 5ca9da50
......@@ -217,6 +217,7 @@ Bug(none) compositing/iframes/composited-iframe-alignment.html [ Failure ]
Bug(none) compositing/iframes/composited-parent-iframe.html [ Failure ]
Bug(none) compositing/iframes/connect-compositing-iframe2.html [ Failure ]
Bug(none) compositing/iframes/connect-compositing-iframe3.html [ Failure ]
Bug(none) compositing/iframes/fixed-position-iframe.html [ Failure ]
Bug(none) compositing/iframes/iframe-resize.html [ Failure ]
Bug(none) compositing/iframes/iframe-size-from-zero.html [ Failure ]
Bug(none) compositing/iframes/invisible-nested-iframe-hide.html [ Crash Failure ]
......@@ -480,6 +481,7 @@ Bug(none) fast/block/positioning/offsetLeft-offsetTop-multicolumn.html [ Failure
Bug(none) fast/block/positioning/relative-overflow-block.html [ Failure ]
Bug(none) fast/block/positioning/relative-overflow-replaced-float.html [ Failure ]
Bug(none) fast/block/positioning/relative-overflow-replaced.html [ Failure ]
Bug(none) fast/block/positioning/rtl-fixed-positioning.html [ Failure ]
Bug(none) fast/block/positioning/vertical-lr/002.html [ Failure ]
Bug(none) fast/block/positioning/vertical-rl/002.html [ Failure ]
Bug(none) fast/body-propagation/overflow/001-xhtml.xhtml [ Failure ]
......
......@@ -452,9 +452,10 @@ void PaintLayerCompositor::updateIfNeeded() {
m_needsUpdateFixedBackground = false;
}
for (unsigned i = 0; i < layersNeedingPaintInvalidation.size(); i++)
for (unsigned i = 0; i < layersNeedingPaintInvalidation.size(); i++) {
forceRecomputeVisualRectsIncludingNonCompositingDescendants(
layersNeedingPaintInvalidation[i]->layoutObject());
}
// Inform the inspector that the layer tree has changed.
if (m_layoutView.frame()->isMainFrame())
......
......@@ -2715,6 +2715,12 @@ bool PaintLayer::hasCompositedClippingMask() const {
}
bool PaintLayer::paintsWithTransform(GlobalPaintFlags globalPaintFlags) const {
if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) {
return transform() &&
((globalPaintFlags & GlobalPaintFlattenCompositingLayers) ||
compositingState() != PaintsIntoOwnBacking);
}
return (transform() ||
layoutObject()->style()->position() == FixedPosition) &&
((globalPaintFlags & GlobalPaintFlattenCompositingLayers) ||
......
......@@ -421,18 +421,20 @@ PaintResult PaintLayerPainter::paintLayerContents(
// SPv2. Related thread
// https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuWFf-mxM
if (fragmentPolicy == ForceSingleFragment ||
RuntimeEnabledFeatures::slimmingPaintV2Enabled())
RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
m_paintLayer.appendSingleFragmentIgnoringPagination(
layerFragments, localPaintingInfo.rootLayer,
localPaintingInfo.paintDirtyRect, cacheSlot,
IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot,
localPaintingInfo.subPixelAccumulation);
else
} else if (!collectPaintFragmentsForPaginatedFixedPosition(
paintingInfo, layerFragments)) {
m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer,
localPaintingInfo.paintDirtyRect, cacheSlot,
IgnoreOverlayScrollbarSize,
respectOverflowClip, &offsetFromRoot,
localPaintingInfo.subPixelAccumulation);
}
if (shouldPaintContent) {
// TODO(wangxianzhu): This is for old slow scrolling. Implement similar
......@@ -589,6 +591,42 @@ bool PaintLayerPainter::atLeastOneFragmentIntersectsDamageRect(
return false;
}
bool PaintLayerPainter::collectPaintFragmentsForPaginatedFixedPosition(
const PaintLayerPaintingInfo& paintingInfo,
PaintLayerFragments& layerFragments) {
LayoutObject* object = m_paintLayer.layoutObject();
LayoutView* view = object->view();
bool isFixedPosObjectInPagedMedia =
object->style()->position() == FixedPosition &&
object->container() == view && view->pageLogicalHeight();
// TODO(crbug.com/619094): Figure out the correct behaviour for fixed position
// objects in paged media with vertical writing modes.
if (!isFixedPosObjectInPagedMedia || !view->isHorizontalWritingMode())
return false;
// "For paged media, boxes with fixed positions are repeated on every page."
// https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning
unsigned pages =
ceilf(view->documentRect().height() / view->pageLogicalHeight());
LayoutPoint paginationOffset;
// The fixed position object is offset from the top of the page, so remove
// any scroll offset.
LayoutPoint offsetFromRoot;
m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
paginationOffset -= offsetFromRoot - m_paintLayer.location();
for (unsigned i = 0; i < pages; i++) {
PaintLayerFragment fragment;
fragment.backgroundRect = paintingInfo.paintDirtyRect;
fragment.paginationOffset = paginationOffset;
layerFragments.append(fragment);
paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight());
}
return true;
}
PaintResult PaintLayerPainter::paintLayerWithTransform(
GraphicsContext& context,
const PaintLayerPaintingInfo& paintingInfo,
......@@ -610,62 +648,46 @@ PaintResult PaintLayerPainter::paintLayerWithTransform(
object->style()->position() == FixedPosition &&
object->container() == view && view->pageLogicalHeight();
PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer();
PaintLayerFragments fragments;
// TODO(crbug.com/619094): Figure out the correct behaviour for fixed position
// objects in paged media with vertical writing modes.
if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) {
// "For paged media, boxes with fixed positions are repeated on every page."
// https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning
unsigned pages =
ceilf(view->documentRect().height() / view->pageLogicalHeight());
LayoutPoint paginationOffset;
// The fixed position object is offset from the top of the page, so remove
// any scroll offset.
LayoutPoint offsetFromRoot;
m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
paginationOffset -= offsetFromRoot - m_paintLayer.location();
for (unsigned i = 0; i < pages; i++) {
PaintLayerFragments layerFragments;
if (!collectPaintFragmentsForPaginatedFixedPosition(paintingInfo,
layerFragments)) {
if (paginationLayer) {
// FIXME: This is a mess. Look closely at this code and the code in Layer
// and fix any issues in it & refactor to make it obvious from code
// structure what it does and that it's correct.
ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
? UncachedClipRects
: PaintingClipRects;
ShouldRespectOverflowClipType respectOverflowClip =
shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject());
// Calculate the transformed bounding box in the current coordinate space,
// to figure out which fragmentainers (e.g. columns) we need to visit.
LayoutRect transformedExtent = PaintLayer::transparencyClipBox(
&m_paintLayer, paginationLayer,
PaintLayer::PaintingTransparencyClipBox,
PaintLayer::RootOfTransparencyClipBox,
paintingInfo.subPixelAccumulation,
paintingInfo.getGlobalPaintFlags());
// FIXME: we don't check if paginationLayer is within
// paintingInfo.rootLayer
// here.
paginationLayer->collectFragments(
layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect,
cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0,
paintingInfo.subPixelAccumulation, &transformedExtent);
} else {
// We don't need to collect any fragments in the regular way here. We have
// already calculated a clip rectangle for the ancestry if it was needed,
// and clipping this layer is something that can be done further down the
// path, when the transform has been applied.
PaintLayerFragment fragment;
fragment.backgroundRect = paintingInfo.paintDirtyRect;
fragment.paginationOffset = paginationOffset;
fragments.append(fragment);
paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight());
layerFragments.append(fragment);
}
} else if (paginationLayer) {
// FIXME: This is a mess. Look closely at this code and the code in Layer
// and fix any issues in it & refactor to make it obvious from code
// structure what it does and that it's correct.
ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects)
? UncachedClipRects
: PaintingClipRects;
ShouldRespectOverflowClipType respectOverflowClip =
shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject());
// Calculate the transformed bounding box in the current coordinate space,
// to figure out which fragmentainers (e.g. columns) we need to visit.
LayoutRect transformedExtent = PaintLayer::transparencyClipBox(
&m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox,
PaintLayer::RootOfTransparencyClipBox,
paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags());
// FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer
// here.
paginationLayer->collectFragments(
fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect,
cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0,
paintingInfo.subPixelAccumulation, &transformedExtent);
} else {
// We don't need to collect any fragments in the regular way here. We have
// already calculated a clip rectangle for the ancestry if it was needed,
// and clipping this layer is something that can be done further down the
// path, when the transform has been applied.
PaintLayerFragment fragment;
fragment.backgroundRect = paintingInfo.paintDirtyRect;
fragments.append(fragment);
}
Optional<DisplayItemCacheSkipper> cacheSkipper;
if (fragments.size() > 1)
if (layerFragments.size() > 1)
cacheSkipper.emplace(context);
ClipRect ancestorBackgroundClipRect;
......@@ -686,7 +708,7 @@ PaintResult PaintLayerPainter::paintLayerWithTransform(
}
PaintResult result = FullyPainted;
for (const auto& fragment : fragments) {
for (const auto& fragment : layerFragments) {
Optional<LayerClipRecorder> clipRecorder;
if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
ClipRect clipRectForFragment(ancestorBackgroundClipRect);
......
......@@ -56,6 +56,10 @@ class CORE_EXPORT PaintLayerPainter {
private:
enum ClipState { HasNotClipped, HasClipped };
bool collectPaintFragmentsForPaginatedFixedPosition(
const PaintLayerPaintingInfo&,
PaintLayerFragments&);
PaintResult paintLayerContentsCompositingAllPhases(
GraphicsContext&,
const PaintLayerPaintingInfo&,
......
......@@ -219,10 +219,6 @@ void PaintPropertyTreeBuilder::updatePaintOffsetTranslation(
usesPaintOffsetTranslation = true;
} else if (object.isBoxModelObject() &&
context.current.paintOffset != LayoutPoint()) {
// TODO(trchen): Eliminate PaintLayer dependency.
// TODO(chrishtr): When changing the condition here, make sure to update
// the condition in LayoutBoxModelObject::styleDidChange() above
// setNeedsPaintPropertyUpdate().
PaintLayer* layer = toLayoutBoxModelObject(object).layer();
if (layer &&
layer->paintsWithTransform(GlobalPaintFlattenCompositingLayers))
......
......@@ -140,18 +140,12 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
Element* target1 = document().getElementById("target1");
const ObjectPaintProperties* target1Properties =
target1->layoutObject()->paintProperties();
EXPECT_EQ(TransformationMatrix().translate(200, 150),
target1Properties->paintOffsetTranslation()->matrix());
EXPECT_EQ(framePreTranslation(),
target1Properties->paintOffsetTranslation()->parent());
EXPECT_EQ(target1Properties->paintOffsetTranslation(),
target1Properties->overflowClip()->localTransformSpace());
EXPECT_EQ(FloatRoundedRect(0, 0, 100, 100),
EXPECT_EQ(FloatRoundedRect(200, 150, 100, 100),
target1Properties->overflowClip()->clipRect());
// Likewise, it inherits clip from the viewport, skipping overflow clip of the
// scroller.
EXPECT_EQ(frameContentClip(), target1Properties->overflowClip()->parent());
// target1 should not have it's own scroll node and instead should inherit
// target1 should not have its own scroll node and instead should inherit
// positionedScroll's.
const ObjectPaintProperties* positionedScrollProperties =
positionedScroll->layoutObject()->paintProperties();
......@@ -161,7 +155,6 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
->scrollOffsetTranslation()
->matrix());
EXPECT_EQ(nullptr, target1Properties->scroll());
CHECK_EXACT_VISUAL_RECT(LayoutRect(200, 150, 100, 100),
target1->layoutObject(), frameView->layoutView());
......@@ -173,13 +166,7 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
Element* scroller = document().getElementById("transformedScroll");
const ObjectPaintProperties* scrollerProperties =
scroller->layoutObject()->paintProperties();
EXPECT_EQ(TransformationMatrix().translate(200, 150),
target2Properties->paintOffsetTranslation()->matrix());
EXPECT_EQ(scrollerProperties->scrollTranslation(),
target2Properties->paintOffsetTranslation()->parent());
EXPECT_EQ(target2Properties->paintOffsetTranslation(),
target2Properties->overflowClip()->localTransformSpace());
EXPECT_EQ(FloatRoundedRect(0, 0, 100, 100),
EXPECT_EQ(FloatRoundedRect(200, 150, 100, 100),
target2Properties->overflowClip()->clipRect());
EXPECT_EQ(scrollerProperties->overflowClip(),
target2Properties->overflowClip()->parent());
......@@ -1049,12 +1036,11 @@ TEST_P(PaintPropertyTreeBuilderTest,
Element* fixed = document().getElementById("fixed");
const ObjectPaintProperties* fixedProperties =
fixed->layoutObject()->paintProperties();
EXPECT_EQ(TransformationMatrix().translate(200, 150),
fixedProperties->paintOffsetTranslation()->matrix());
// Ensure the fixed position element is rooted at the nearest transform
// container.
EXPECT_EQ(containerProperties->transform(),
fixedProperties->paintOffsetTranslation()->parent());
fixedProperties->localBorderBoxProperties()
->propertyTreeState.transform());
}
TEST_P(PaintPropertyTreeBuilderTest, ControlClip) {
......@@ -1447,13 +1433,8 @@ TEST_P(PaintPropertyTreeBuilderTest, CSSClipFixedPositionDescendant) {
clipProperties->cssClip(),
fixedProperties->localBorderBoxProperties()->propertyTreeState.clip());
EXPECT_EQ(framePreTranslation(), fixedProperties->localBorderBoxProperties()
->propertyTreeState.transform()
->parent());
EXPECT_EQ(TransformationMatrix().translate(654, 321),
fixedProperties->localBorderBoxProperties()
->propertyTreeState.transform()
->matrix());
EXPECT_EQ(LayoutPoint(),
->propertyTreeState.transform());
EXPECT_EQ(LayoutPoint(654, 321),
fixedProperties->localBorderBoxProperties()->paintOffset);
CHECK_VISUAL_RECT(LayoutRect(), fixed, document().view()->layoutView(),
// TODO(crbug.com/599939): CSS clip of fixed-position
......@@ -1589,13 +1570,8 @@ TEST_P(PaintPropertyTreeBuilderTest, CSSClipFixedPositionDescendantNonShared) {
clipProperties->cssClipFixedPosition(),
fixedProperties->localBorderBoxProperties()->propertyTreeState.clip());
EXPECT_EQ(framePreTranslation(), fixedProperties->localBorderBoxProperties()
->propertyTreeState.transform()
->parent());
EXPECT_EQ(TransformationMatrix().translate(654, 321),
fixedProperties->localBorderBoxProperties()
->propertyTreeState.transform()
->matrix());
EXPECT_EQ(LayoutPoint(),
->propertyTreeState.transform());
EXPECT_EQ(LayoutPoint(654, 321),
fixedProperties->localBorderBoxProperties()->paintOffset);
CHECK_VISUAL_RECT(LayoutRect(), fixed, document().view()->layoutView(),
// TODO(crbug.com/599939): CSS clip of fixed-position
......@@ -3078,10 +3054,7 @@ TEST_P(PaintPropertyTreeBuilderTest, FilterReparentClips) {
getLayoutObjectByElementId("child")->paintProperties();
const PropertyTreeState& childPaintState =
childProperties->localBorderBoxProperties()->propertyTreeState;
EXPECT_EQ(framePreTranslation(),
childProperties->paintOffsetTranslation()->parent());
EXPECT_EQ(childProperties->paintOffsetTranslation(),
childPaintState.transform());
// This will change once we added clip expansion node.
EXPECT_EQ(filterProperties->effect()->outputClip(), childPaintState.clip());
EXPECT_EQ(filterProperties->effect(), childPaintState.effect());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment