Skip to content

Commit 9ba4c0d

Browse files
[iOS WK2] Layer content blurry with nested perspective and transforms
https://bugs.webkit.org/show_bug.cgi?id=169457 Source/WebCore: rdar://problem/29879484 Reviewed by Tim Horton. We set rasterizationScale on CALayers to the same values as contentsScale, to avoid blurry layers when CA rasterizes, which often happens with nested perspective transforms. However, in UI-side compositing, if the page is not zoomed, we never applied the rasterizationScale in the UI process. This happened because the PlatformCALayerRemote constructor set m_properties.contentsScale, but did not set the dirty bit that triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier. The fix is to set this dirty bit. The rest of the changes are for testing. Internals now exposes layerIDForElement() for returns an internal (non-stable-across-loads) layerID, which can be passed to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary which the test can dump as JSON, or pull values out of. A few #pragma once cleanups also. Tests: compositing/ios/basic-layer-properties.html compositing/ios/rasterization-scale.html * testing/Internals.cpp: (WebCore::Internals::layerIDForElement): * testing/Internals.h: * testing/Internals.idl: Source/WebKit2: rdar://problem/29879484 Reviewed by Tim Horton. We set rasterizationScale on CALayers to the same values as contentsScale, to avoid blurry layers when CA rasterizes, which often happens with nested perspective transforms. However, in UI-side compositing, if the page is not zoomed, we never applied the rasterizationScale in the UI process. This happened because the PlatformCALayerRemote constructor set m_properties.contentsScale, but did not set the dirty bit that triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier. The fix is to set this dirty bit. The rest of the changes are for testing. Internals now exposes layerIDForElement() for returns an internal (non-stable-across-loads) layerID, which can be passed to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary which the test can dump as JSON, or pull values out of. A few #pragma once cleanups also. * UIProcess/API/Cocoa/WKWebView.mm: (-[WKWebView _propertiesOfLayerWithID:]): * UIProcess/API/Cocoa/WKWebViewPrivate.h: * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h: * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm: (WebKit::RemoteLayerTreeDrawingAreaProxy::layerWithIDForTesting): * UIProcess/mac/RemoteLayerTreeHost.h: * UIProcess/mac/RemoteLayerTreeHost.mm: (WebKit::RemoteLayerTreeHost::layerWithIDForTesting): * WebProcess/WebPage/mac/PlatformCALayerRemote.cpp: (WebKit::PlatformCALayerRemote::PlatformCALayerRemote): Tools: rdar://problem/29879484 Reviewed by Tim Horton. We set rasterizationScale on CALayers to the same values as contentsScale, to avoid blurry layers when CA rasterizes, which often happens with nested perspective transforms. However, in UI-side compositing, if the page is not zoomed, we never applied the rasterizationScale in the UI process. This happened because the PlatformCALayerRemote constructor set m_properties.contentsScale, but did not set the dirty bit that triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier. The fix is to set this dirty bit. The rest of the changes are for testing. Internals now exposes layerIDForElement() for returns an internal (non-stable-across-loads) layerID, which can be passed to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary which the test can dump as JSON, or pull values out of. A few #pragma once cleanups also. * DumpRenderTree/ios/UIScriptControllerIOS.mm: (WTR::UIScriptController::propertiesOfLayerWithID): * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: * TestRunnerShared/UIScriptContext/UIScriptController.cpp: (WTR::UIScriptController::propertiesOfLayerWithID): * TestRunnerShared/UIScriptContext/UIScriptController.h: * WebKitTestRunner/ios/UIScriptControllerIOS.mm: (WTR::UIScriptController::propertiesOfLayerWithID): LayoutTests: Reviewed by Tim Horton. We set rasterizationScale on CALayers to the same values as contentsScale, to avoid blurry layers when CA rasterizes, which often happens with nested perspective transforms. However, in UI-side compositing, if the page is not zoomed, we never applied the rasterizationScale in the UI process. This happened because the PlatformCALayerRemote constructor set m_properties.contentsScale, but did not set the dirty bit that triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier. The fix is to set this dirty bit. The rest of the changes are for testing. Internals now exposes layerIDForElement() for returns an internal (non-stable-across-loads) layerID, which can be passed to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary which the test can dump as JSON, or pull values out of. A few #pragma once cleanups also. * TestExpectations: * compositing/ios/basic-layer-properties-expected.txt: Added. * compositing/ios/basic-layer-properties.html: Added. * compositing/ios/rasterization-scale-expected.txt: Added. * compositing/ios/rasterization-scale.html: Added. * platform/ios-simulator-wk2/TestExpectations: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@213719 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 9f5eaea commit 9ba4c0d

26 files changed

+510
-13
lines changed

LayoutTests/ChangeLog

+32
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
2017-03-09 Simon Fraser <[email protected]>
2+
3+
[iOS WK2] Layer content blurry with nested perspective and transforms
4+
https://bugs.webkit.org/show_bug.cgi?id=169457
5+
6+
Reviewed by Tim Horton.
7+
8+
We set rasterizationScale on CALayers to the same values as contentsScale, to
9+
avoid blurry layers when CA rasterizes, which often happens with nested perspective
10+
transforms.
11+
12+
However, in UI-side compositing, if the page is not zoomed, we never applied the
13+
rasterizationScale in the UI process. This happened because the PlatformCALayerRemote
14+
constructor set m_properties.contentsScale, but did not set the dirty bit that
15+
triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier.
16+
The fix is to set this dirty bit.
17+
18+
The rest of the changes are for testing. Internals now exposes layerIDForElement()
19+
for returns an internal (non-stable-across-loads) layerID, which can be passed
20+
to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects
21+
the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary
22+
which the test can dump as JSON, or pull values out of.
23+
24+
A few #pragma once cleanups also.
25+
26+
* TestExpectations:
27+
* compositing/ios/basic-layer-properties-expected.txt: Added.
28+
* compositing/ios/basic-layer-properties.html: Added.
29+
* compositing/ios/rasterization-scale-expected.txt: Added.
30+
* compositing/ios/rasterization-scale.html: Added.
31+
* platform/ios-simulator-wk2/TestExpectations:
32+
133
2017-03-10 Javier Fernandez <[email protected]>
234

335
[GTK] Unreviewed test gardening

LayoutTests/TestExpectations

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# Platform-specific tests. Skipped here, then re-enabled on the appropriate platform.
77
#//////////////////////////////////////////////////////////////////////////////////////////
88

9+
compositing/ios [ Skip ]
910
css3/touch-action [ Skip ]
1011
accessibility/ios-simulator [ Skip ]
1112
accessibility/gtk [ Skip ]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
Composited box.
2+
{
3+
"anchorPoint": {
4+
"x": 0.5,
5+
"y": 0.5
6+
},
7+
"anchorPointZ": 0,
8+
"bounds": {
9+
"height": 148,
10+
"width": 148,
11+
"x": 0,
12+
"y": 0
13+
},
14+
"contentsScale": 2,
15+
"doubleSided": true,
16+
"hidden": false,
17+
"masksToBounds": false,
18+
"opacity": 1,
19+
"opaque": true,
20+
"position": {
21+
"x": 88,
22+
"y": 80
23+
},
24+
"rasterizationScale": 2,
25+
"sublayerTransform": {
26+
"m11": 1,
27+
"m12": 0,
28+
"m13": 0,
29+
"m14": 0,
30+
"m21": 0,
31+
"m22": 1,
32+
"m23": 0,
33+
"m24": 0,
34+
"m31": 0,
35+
"m32": 0,
36+
"m33": 1,
37+
"m34": 0,
38+
"m41": 0,
39+
"m42": 0,
40+
"m43": 0,
41+
"m44": 1
42+
},
43+
"transform": {
44+
"m11": 1,
45+
"m12": 0,
46+
"m13": 0,
47+
"m14": 0,
48+
"m21": 0,
49+
"m22": 1,
50+
"m23": 0,
51+
"m24": 0,
52+
"m31": 0,
53+
"m32": 0,
54+
"m33": 1,
55+
"m34": 0,
56+
"m41": 0,
57+
"m42": 0,
58+
"m43": 0,
59+
"m44": 1
60+
},
61+
"zPosition": 0
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!DOCTYPE html>
2+
3+
<html>
4+
<head>
5+
<style>
6+
.box {
7+
height: 100px;
8+
width: 100px;
9+
background-color: silver;
10+
box-shadow: 0 0 10px black;
11+
padding: 10px;
12+
margin: 20px;
13+
}
14+
15+
.composited {
16+
will-change: transform;
17+
}
18+
</style>
19+
<script>
20+
if (window.testRunner) {
21+
testRunner.dumpAsText();
22+
testRunner.waitUntilDone();
23+
}
24+
25+
function sortedJSONStringify(object, space)
26+
{
27+
function sorted(o)
28+
{
29+
var result = {};
30+
31+
var keys = [];
32+
for (var key in o) {
33+
if (o.hasOwnProperty(key))
34+
keys.push(key);
35+
}
36+
37+
keys.sort();
38+
for (var key of keys)
39+
result[key] = o[key];
40+
41+
return result;
42+
}
43+
44+
return JSON.stringify(sorted(object), function(key, value) {
45+
if (typeof value === 'object' && !Array.isArray(value) && !(typeof(value) === 'function'))
46+
return sorted(value);
47+
return value;
48+
}, space);
49+
}
50+
51+
function getUIScript(layerID)
52+
{
53+
return `
54+
(function() {
55+
uiController.doAfterPresentationUpdate(function() {
56+
var layerProperties = JSON.stringify(uiController.propertiesOfLayerWithID(${layerID}));
57+
uiController.uiScriptComplete(layerProperties);
58+
})
59+
})();`
60+
}
61+
62+
function doTest()
63+
{
64+
if (!window.testRunner)
65+
return;
66+
67+
var layerID = internals.layerIDForElement(document.getElementById('composited'));
68+
69+
testRunner.runUIScript(getUIScript(layerID), function(layerProperties) {
70+
var propertiesAsJSON = JSON.parse(layerProperties);
71+
document.getElementById('layer-properties').textContent = sortedJSONStringify(propertiesAsJSON, 4);
72+
testRunner.notifyDone();
73+
});
74+
}
75+
76+
window.addEventListener('load', doTest, false);
77+
</script>
78+
</head>
79+
<body>
80+
81+
<div id="composited" class="composited box">
82+
Composited box.
83+
</div>
84+
85+
<pre id="layer-properties"></pre>
86+
</body>
87+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This text should not be blurry
2+
rasterizationScale of layer is 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
2+
3+
<html>
4+
<head>
5+
<meta name="viewport" content="width=device-width">
6+
<style>
7+
.perspective-container {
8+
perspective: 1500px;
9+
width: 100%;
10+
padding: 10px;
11+
border: 1px solid black;
12+
}
13+
14+
.container {
15+
transform: translateZ(20px);
16+
}
17+
18+
.middle {
19+
transform-style: preserve-3d;
20+
perspective: 300px;
21+
}
22+
23+
#blurry-layer {
24+
width: 100%;
25+
height: 50px;
26+
-webkit-backface-visibility: hidden;
27+
transform: rotateX(20deg);
28+
background-color: silver;
29+
font-size: 24pt;
30+
}
31+
</style>
32+
<script>
33+
if (window.testRunner) {
34+
testRunner.dumpAsText();
35+
testRunner.waitUntilDone();
36+
}
37+
38+
function getUIScript(layerID)
39+
{
40+
return `
41+
(function() {
42+
uiController.doAfterPresentationUpdate(function() {
43+
var layerProperties = JSON.stringify(uiController.propertiesOfLayerWithID(${layerID}));
44+
uiController.uiScriptComplete(layerProperties);
45+
})
46+
})();`
47+
}
48+
49+
function doTest()
50+
{
51+
if (!window.testRunner)
52+
return;
53+
54+
var layerID = internals.layerIDForElement(document.getElementById('blurry-layer'));
55+
56+
testRunner.runUIScript(getUIScript(layerID), function(layerProperties) {
57+
var propertiesAsJSON = JSON.parse(layerProperties);
58+
document.getElementById('layer-properties').textContent = 'rasterizationScale of layer is ' + propertiesAsJSON['rasterizationScale'];
59+
testRunner.notifyDone();
60+
});
61+
}
62+
63+
window.addEventListener('load', doTest, false);
64+
</script>
65+
</head>
66+
<body>
67+
68+
<div class="perspective-container">
69+
<div class="container">
70+
<div class="middle">
71+
<div id="blurry-layer">
72+
This text should not be blurry
73+
</div>
74+
</div>
75+
</div>
76+
</div>
77+
78+
<pre id="layer-properties"></pre>
79+
</body>
80+
</html>

LayoutTests/platform/ios-simulator-wk2/TestExpectations

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# Platform-specific directories. Skipped globally, then re-enabled here.
77
#//////////////////////////////////////////////////////////////////////////////////////////
88

9+
compositing/ios [ Pass ]
910
fast/history/ios [ Pass ]
1011
fast/scrolling/ios [ Pass ]
1112
fast/viewport/ios [ Pass ]

Source/WebCore/ChangeLog

+34
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
2017-03-09 Simon Fraser <[email protected]>
2+
3+
[iOS WK2] Layer content blurry with nested perspective and transforms
4+
https://bugs.webkit.org/show_bug.cgi?id=169457
5+
rdar://problem/29879484
6+
7+
Reviewed by Tim Horton.
8+
9+
We set rasterizationScale on CALayers to the same values as contentsScale, to
10+
avoid blurry layers when CA rasterizes, which often happens with nested perspective
11+
transforms.
12+
13+
However, in UI-side compositing, if the page is not zoomed, we never applied the
14+
rasterizationScale in the UI process. This happened because the PlatformCALayerRemote
15+
constructor set m_properties.contentsScale, but did not set the dirty bit that
16+
triggers the application of contentsScale and rasterizationScale in RemoteLayerTreePropertyApplier.
17+
The fix is to set this dirty bit.
18+
19+
The rest of the changes are for testing. Internals now exposes layerIDForElement()
20+
for returns an internal (non-stable-across-loads) layerID, which can be passed
21+
to UIScriptController.propertiesOfLayerWithID() in the UI process, which inspects
22+
the built layer (UIView) hierarchy. propertiesOfLayerWithID() returns a dictionary
23+
which the test can dump as JSON, or pull values out of.
24+
25+
A few #pragma once cleanups also.
26+
27+
Tests: compositing/ios/basic-layer-properties.html
28+
compositing/ios/rasterization-scale.html
29+
30+
* testing/Internals.cpp:
31+
(WebCore::Internals::layerIDForElement):
32+
* testing/Internals.h:
33+
* testing/Internals.idl:
34+
135
2017-03-10 Commit Queue <[email protected]>
236

337
Unreviewed, rolling out r213618.

Source/WebCore/testing/Internals.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -2149,6 +2149,23 @@ ExceptionOr<String> Internals::layerTreeAsText(Document& document, unsigned shor
21492149
return document.frame()->layerTreeAsText(toLayerTreeFlags(flags));
21502150
}
21512151

2152+
ExceptionOr<uint64_t> Internals::layerIDForElement(Element& element)
2153+
{
2154+
Document* document = contextDocument();
2155+
if (!document || !document->frame())
2156+
return Exception { INVALID_ACCESS_ERR };
2157+
2158+
if (!element.renderer() || !element.renderer()->hasLayer())
2159+
return Exception { NOT_FOUND_ERR };
2160+
2161+
auto& layerModelObject = downcast<RenderLayerModelObject>(*element.renderer());
2162+
if (!layerModelObject.layer()->isComposited())
2163+
return Exception { NOT_FOUND_ERR };
2164+
2165+
auto* backing = layerModelObject.layer()->backing();
2166+
return backing->graphicsLayer()->primaryLayerID();
2167+
}
2168+
21522169
ExceptionOr<String> Internals::repaintRectsAsText() const
21532170
{
21542171
Document* document = contextDocument();

Source/WebCore/testing/Internals.h

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class Internals final : public RefCounted<Internals>, private ContextDestruction
274274
LAYER_TREE_INCLUDES_ACCELERATES_DRAWING = 32,
275275
};
276276
ExceptionOr<String> layerTreeAsText(Document&, unsigned short flags) const;
277+
ExceptionOr<uint64_t> layerIDForElement(Element&);
277278
ExceptionOr<String> repaintRectsAsText() const;
278279
ExceptionOr<String> scrollingStateTreeAsText() const;
279280
ExceptionOr<String> mainThreadScrollingReasons() const;

Source/WebCore/testing/Internals.idl

+2
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ enum EventThrottlingBehavior {
260260
const unsigned short LAYER_TREE_INCLUDES_ACCELERATES_DRAWING = 32;
261261
[MayThrowException] DOMString layerTreeAsText(Document document, optional unsigned short flags = 0);
262262

263+
[MayThrowException] unsigned long long layerIDForElement(Element element);
264+
263265
[MayThrowException] DOMString scrollingStateTreeAsText();
264266
[MayThrowException] DOMString mainThreadScrollingReasons(); // FIXME: rename to synchronousScrollingReasons().
265267
[MayThrowException] ClientRectList? nonFastScrollableRects();

0 commit comments

Comments
 (0)