Skip to content
Permalink
Browse files
When navigating back to a page, compositing layers may not use accele…
…rated drawing

https://bugs.webkit.org/show_bug.cgi?id=178749
rdar://problem/35158946

Reviewed by Dean Jackson.
Source/WebCore:

There were two issues with setting GraphicsLayerCA's "acceleratesDrawing" state which
occurred on back navigation, related to the ordering of style recalcs and layout.

First, at style recalc time, we created a RenderLayerCompositor but hadn't yet called
its cacheAcceleratedCompositingFlags(), so any layers created during style update
didn't get accelerated drawing. Fix by making cacheAcceleratedCompositingFlags() internal
to RenderLayerCompositor and calling it from willRecalcStyle() and updateCompositingLayers().

Secondly, GraphicsLayerCA::commitLayerChangesBeforeSublayers() needs to updateAcceleratesDrawing()
before updating tiles, so that new tiles fetch the right acceleratesDrawing state from
the TileController.

Test: compositing/accelerated-layers-after-back.html

* page/FrameView.cpp:
(WebCore::FrameView::updateCompositingLayersAfterLayout):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::willRecalcStyle):
(WebCore::RenderLayerCompositor::didRecalcStyleWithNoPendingLayout):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
* rendering/RenderLayerCompositor.h:

Source/WebKit:

Avoid assertions when a test enables accelerated drawing (which we can't support
in the iOS simulator).

* Shared/RemoteLayerTree/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::ensureBackingStore):

Tools:

Fix WTR and DRT to parse "useAcceleratedDrawing" out of "webkit-test-runner" options
and use it to set the state of the web view.

* DumpRenderTree/TestOptions.h:
* DumpRenderTree/TestOptions.mm:
(TestOptions::TestOptions):
* DumpRenderTree/mac/DumpRenderTree.mm:
(setWebPreferencesForTestOptions):
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetPreferencesToConsistentValues):
(WTR::updateTestOptionsFromTestHeader):
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):

LayoutTests:

Moved iframes/resources/page-cache-helper.html up to compositing/resources/go-back.html.

* compositing/accelerated-layers-after-back-expected.txt: Added.
* compositing/accelerated-layers-after-back.html: Added.
* compositing/iframes/page-cache-layer-tree.html:
* compositing/page-cache-back-crash.html:
* compositing/resources/go-back.html: Renamed from LayoutTests/compositing/iframes/resources/page-cache-helper.html.
* platform/ios/compositing/accelerated-layers-after-back-expected.txt: Added.

Canonical link: https://commits.webkit.org/195066@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224078 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
smfr committed Oct 27, 2017
1 parent e661afe commit ad5cab93265e33de45765962099a74f63c73f002
Showing 21 changed files with 286 additions and 30 deletions.
@@ -1,3 +1,20 @@
2017-10-25 Simon Fraser <simon.fraser@apple.com>

When navigating back to a page, compositing layers may not use accelerated drawing
https://bugs.webkit.org/show_bug.cgi?id=178749
rdar://problem/35158946

Reviewed by Dean Jackson.

Moved iframes/resources/page-cache-helper.html up to compositing/resources/go-back.html.

* compositing/accelerated-layers-after-back-expected.txt: Added.
* compositing/accelerated-layers-after-back.html: Added.
* compositing/iframes/page-cache-layer-tree.html:
* compositing/page-cache-back-crash.html:
* compositing/resources/go-back.html: Renamed from LayoutTests/compositing/iframes/resources/page-cache-helper.html.
* platform/ios/compositing/accelerated-layers-after-back-expected.txt: Added.

2017-10-26 Myles C. Maxfield <mmaxfield@apple.com>

[iOS] Update expected results for writing-mode tests
@@ -0,0 +1,45 @@
This layer should use 'acceleratesDrawing' after going back to this page.

Before:

(GraphicsLayer
(anchor 0.00 0.00)
(bounds 800.00 600.00)
(children 1
(GraphicsLayer
(bounds 800.00 600.00)
(contentsOpaque 1)
(acceleratesDrawing 1)
(children 1
(GraphicsLayer
(position 18.00 10.00)
(bounds 222.00 222.00)
(drawsContent 1)
(acceleratesDrawing 1)
)
)
)
)
)
After:

(GraphicsLayer
(anchor 0.00 0.00)
(bounds 785.00 653.00)
(children 1
(GraphicsLayer
(bounds 785.00 653.00)
(contentsOpaque 1)
(acceleratesDrawing 1)
(children 1
(GraphicsLayer
(position 18.00 10.00)
(bounds 222.00 222.00)
(drawsContent 1)
(acceleratesDrawing 1)
)
)
)
)
)

@@ -0,0 +1,67 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useAcceleratedDrawing=true ] -->

<html>
<head>
<style>
.container {
position: relative;
height: 200px;
width: 200px;
margin: 10px;
padding: 10px;
border: 1px solid black;
will-change: transform;
}
</style>
<script>
var jsTestIsAsync = true;

if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
window.testRunner.overridePreference("WebKitUsesPageCachePreferenceKey", 1);
}

function doOnFirstLoad()
{
if (window.internals)
document.getElementById('layers-before-navigate').innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_ACCELERATES_DRAWING);

setTimeout(function() {
window.location.href = 'resources/go-back.html';
}, 0);
}

function doAfterBack()
{
if (window.internals)
document.getElementById('layers-after-back').innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_ACCELERATES_DRAWING);

if (window.testRunner)
testRunner.notifyDone();
}

window.addEventListener("pageshow", function(event) {
if (event.persisted)
setTimeout(doAfterBack, 0);
}, false);

function doTest()
{
doOnFirstLoad();
}

window.addEventListener('load', doTest, false);
</script>
</head>
<body>
<div class="container">
<p>This layer should use 'acceleratesDrawing' after going back to this page.</p>
</div>
<h2>Before:</h2>
<pre id="layers-before-navigate"></pre>
<h2>After:</h2>
<pre id="layers-after-back"></pre>

</body>
</html>
@@ -73,7 +73,7 @@
// Force a back navigation back to this page.
window.addEventListener("load", function(event) {
setTimeout(function() {
window.location.href = "resources/page-cache-helper.html";
window.location.href = "../resources/go-back.html";
}, 0);
}, false);
</script>
@@ -19,7 +19,7 @@
window.addEventListener("load", function() {
setTimeout(function() {
// Navigate to a helper page that will immediately navigate back here after loading.
window.location.href = "iframes/resources/page-cache-helper.html";
window.location.href = "resources/go-back.html";
}, 0);
});
</script>
@@ -9,7 +9,7 @@
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
}

function doTest()
{
@@ -0,0 +1,45 @@
This layer should use 'acceleratesDrawing' after going back to this page.

Before:

(GraphicsLayer
(anchor 0.00 0.00)
(bounds 800.00 600.00)
(children 1
(GraphicsLayer
(bounds 800.00 600.00)
(contentsOpaque 1)
(acceleratesDrawing 1)
(children 1
(GraphicsLayer
(position 18.00 10.00)
(bounds 222.00 222.00)
(drawsContent 1)
(acceleratesDrawing 1)
)
)
)
)
)
After:

(GraphicsLayer
(anchor 0.00 0.00)
(bounds 800.00 638.00)
(children 1
(GraphicsLayer
(bounds 800.00 638.00)
(contentsOpaque 1)
(acceleratesDrawing 1)
(children 1
(GraphicsLayer
(position 18.00 10.00)
(bounds 222.00 222.00)
(drawsContent 1)
(acceleratesDrawing 1)
)
)
)
)
)

@@ -1,3 +1,35 @@
2017-10-25 Simon Fraser <simon.fraser@apple.com>

When navigating back to a page, compositing layers may not use accelerated drawing
https://bugs.webkit.org/show_bug.cgi?id=178749
rdar://problem/35158946

Reviewed by Dean Jackson.

There were two issues with setting GraphicsLayerCA's "acceleratesDrawing" state which
occurred on back navigation, related to the ordering of style recalcs and layout.

First, at style recalc time, we created a RenderLayerCompositor but hadn't yet called
its cacheAcceleratedCompositingFlags(), so any layers created during style update
didn't get accelerated drawing. Fix by making cacheAcceleratedCompositingFlags() internal
to RenderLayerCompositor and calling it from willRecalcStyle() and updateCompositingLayers().

Secondly, GraphicsLayerCA::commitLayerChangesBeforeSublayers() needs to updateAcceleratesDrawing()
before updating tiles, so that new tiles fetch the right acceleratesDrawing state from
the TileController.

Test: compositing/accelerated-layers-after-back.html

* page/FrameView.cpp:
(WebCore::FrameView::updateCompositingLayersAfterLayout):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::willRecalcStyle):
(WebCore::RenderLayerCompositor::didRecalcStyleWithNoPendingLayout):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
* rendering/RenderLayerCompositor.h:

2017-10-26 Alex Christensen <achristensen@webkit.org>

Fix Windows build
@@ -892,8 +892,6 @@ void FrameView::updateCompositingLayersAfterLayout()
if (!renderView)
return;

// This call will make sure the cached hasAcceleratedCompositing is updated from the pref
renderView->compositor().cacheAcceleratedCompositingFlags();
renderView->compositor().updateCompositingLayers(CompositingUpdateType::AfterLayout);
}

@@ -1753,6 +1753,9 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState
if (m_uncommittedChanges & CoverageRectChanged)
updateCoverage(commitState);

if (m_uncommittedChanges & AcceleratesDrawingChanged) // Needs to happen before TilingAreaChanged.
updateAcceleratesDrawing();

if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after CoverageRectChanged, ContentsScaleChanged
updateTiles();

@@ -1775,9 +1778,6 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers(CommitState& commitState
if (m_uncommittedChanges & ContentsNeedsDisplay)
updateContentsNeedsDisplay();

if (m_uncommittedChanges & AcceleratesDrawingChanged)
updateAcceleratesDrawing();

if (m_uncommittedChanges & SupportsSubpixelAntialiasedTextChanged)
updateSupportsSubpixelAntialiasedText();

@@ -299,15 +299,8 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)

void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
{
bool hasAcceleratedCompositing = false;
bool showDebugBorders = false;
bool showRepaintCounter = false;
bool forceCompositingMode = false;
bool acceleratedDrawingEnabled = false;
bool displayListDrawingEnabled = false;

auto& settings = m_renderView.settings();
hasAcceleratedCompositing = settings.acceleratedCompositingEnabled();
bool hasAcceleratedCompositing = settings.acceleratedCompositingEnabled();

// We allow the chrome to override the settings, in case the page is rendered
// on a chrome that doesn't allow accelerated compositing.
@@ -316,15 +309,11 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
hasAcceleratedCompositing = m_compositingTriggers;
}

showDebugBorders = settings.showDebugBorders();
showRepaintCounter = settings.showRepaintCounter();
forceCompositingMode = settings.forceCompositingMode() && hasAcceleratedCompositing;

if (forceCompositingMode && !isMainFrameCompositor())
forceCompositingMode = requiresCompositingForScrollableFrame();

acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled();
displayListDrawingEnabled = settings.displayListDrawingEnabled();
bool showDebugBorders = settings.showDebugBorders();
bool showRepaintCounter = settings.showRepaintCounter();
bool forceCompositingMode = settings.forceCompositingMode() && hasAcceleratedCompositing;
bool acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled();
bool displayListDrawingEnabled = settings.displayListDrawingEnabled();

if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
setCompositingLayersNeedRebuild();
@@ -349,6 +338,18 @@ void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
}
}

void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout()
{
cacheAcceleratedCompositingFlags();
if (isMainFrameCompositor() || !m_forceCompositingMode)
return;

if (!requiresCompositingForScrollableFrame()) {
m_forceCompositingMode = false;
setCompositingLayersNeedRebuild();
}
}

bool RenderLayerCompositor::canRender3DTransforms() const
{
return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
@@ -363,14 +364,14 @@ void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
void RenderLayerCompositor::willRecalcStyle()
{
m_layerNeedsCompositingUpdate = false;
cacheAcceleratedCompositingFlags();
}

bool RenderLayerCompositor::didRecalcStyleWithNoPendingLayout()
{
if (!m_layerNeedsCompositingUpdate)
return false;

cacheAcceleratedCompositingFlags();
return updateCompositingLayers(CompositingUpdateType::AfterStyleChange);
}

@@ -634,6 +635,9 @@ bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
{
LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor " << this << " updateCompositingLayers " << updateType << " root " << updateRoot);

if (updateType == CompositingUpdateType::AfterStyleChange || updateType == CompositingUpdateType::AfterLayout)
cacheAcceleratedCompositingFlagsAfterLayout(); // Some flags (e.g. forceCompositingMode) depend on layout.

m_updateCompositingLayersTimer.stop();

ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
@@ -110,9 +110,6 @@ class RenderLayerCompositor final : public GraphicsLayerClient, public GraphicsL

bool canRender3DTransforms() const;

// Copy the accelerated compositing related flags from Settings
void cacheAcceleratedCompositingFlags();

// Called when the layer hierarchy needs to be updated (compositing layers have been
// created, destroyed or re-parented).
void setCompositingLayersNeedRebuild(bool needRebuild = true);
@@ -346,6 +343,10 @@ class RenderLayerCompositor final : public GraphicsLayerClient, public GraphicsL
// GraphicsLayerUpdaterClient implementation
void flushLayersSoon(GraphicsLayerUpdater&) override;

// Copy the accelerated compositing related flags from Settings
void cacheAcceleratedCompositingFlags();
void cacheAcceleratedCompositingFlagsAfterLayout();

// Whether the given RL needs a compositing layer.
bool needsToBeComposited(const RenderLayer&, RenderLayer::ViewportConstrainedNotCompositedReason* = nullptr) const;
// Whether the layer has an intrinsic need for compositing layer.
@@ -1,3 +1,17 @@
2017-10-25 Simon Fraser <simon.fraser@apple.com>

When navigating back to a page, compositing layers may not use accelerated drawing
https://bugs.webkit.org/show_bug.cgi?id=178749
rdar://problem/35158946

Reviewed by Dean Jackson.

Avoid assertions when a test enables accelerated drawing (which we can't support
in the iOS simulator).

* Shared/RemoteLayerTree/RemoteLayerBackingStore.mm:
(WebKit::RemoteLayerBackingStore::ensureBackingStore):

2017-10-26 Sam Weinig <sam@webkit.org>

[Settings] Generate the bulk of WebPage::updatePreferences(...)

0 comments on commit ad5cab9

Please sign in to comment.