Commit 7317c459 authored by aroben@apple.com's avatar aroben@apple.com
Browse files

Don't access the CACFLayerRef's sublayers directly from PlatformCALayer

There might be a secret extra sublayer (the tile parent layer) that
PlatformCALayer doesn't know about. When PlatformCALayer would
encounter this, it would try to use the tile parent layer's
PlatformCALayer wrapper, which was null, and then would crash. We now
ask PlatformCALayerWinInternal for the sublayer list, since that class
knows about the tile parent layer and can exclude it from the sublayer
list.

Covered by compositing/tiling/huge-layer-resize.html.

Fixes <http://webkit.org/b/52597> Crash beneath
PlatformCALayer::adoptSublayers when switching out of tiling mode
(null-dereference of a PlatformCALayer)

Reviewed by Darin Adler and Chris Marrin.

LayoutTests:

Make compositing/tiling/huge-layer-resize.html faster, more reliable,
and more crashy (when there's a WebKit bug)

This test was trying to cause a layout/paint to happen by returning to
the event loop for a certain amount of time via setTimeout. But this
didn't always result in a layout/paint (at least on Windows). We now
force the layout/paint explicitly, which also lets us speed up the test
by removing the setTimeouts.

* compositing/tiling/huge-layer-resize.html:
(testOnLoad): Changed to use recordLayerTree, which forces a
layout/paint, instead of hoping that setTimeout will do the trick.
(recordLayerTree): Forces a layout/paint, then dumps the layer tree.

Source/WebCore:

* platform/graphics/ca/win/PlatformCALayerWin.cpp:
(PlatformCALayer::adoptSublayers):
(printLayer):
Changed to use PlatformCALayerWinInternal::getSublayers.

* platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:
(PlatformCALayerWinInternal::getSublayers): Added. Retrieves the list
of PlatformCALayers that represent our sublayers. Significantly, this
code knows about the tile parent layer and can thus exclude it.

* platform/graphics/ca/win/PlatformCALayerWinInternal.h: Added
getSublayers.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75985 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent dbac7d92
2011-01-17 Adam Roben <aroben@apple.com>
Make compositing/tiling/huge-layer-resize.html faster, more reliable,
and more crashy (when there's a WebKit bug)
This test was trying to cause a layout/paint to happen by returning to
the event loop for a certain amount of time via setTimeout. But this
didn't always result in a layout/paint (at least on Windows). We now
force the layout/paint explicitly, which also lets us speed up the test
by removing the setTimeouts.
Reviewed by Darin Adler and Chris Marrin.
Test for <http://webkit.org/b/52597> Crash beneath
PlatformCALayer::adoptSublayers when switching out of tiling mode
(null-dereference of a PlatformCALayer)
* compositing/tiling/huge-layer-resize.html:
(testOnLoad): Changed to use recordLayerTree, which forces a
layout/paint, instead of hoping that setTimeout will do the trick.
(recordLayerTree): Forces a layout/paint, then dumps the layer tree.
2011-01-17 Dan Bernstein <mitz@apple.com>
 
Reviewed by Darin Adler.
......
......@@ -26,45 +26,36 @@
}
</style>
<script type="text/javascript" charset="utf-8">
if (window.layoutTestController) {
if (window.layoutTestController)
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
result = "";
function testOnLoad()
{
// Small layer first
window.setTimeout(function() {
if (window.layoutTestController)
result = "First (small layer):<br>" + layoutTestController.layerTreeAsText();
}, 0);
var result = recordLayerTree("First (small layer):<br>");
// Huge layer second
window.setTimeout(function() {
document.getElementById('container').style.height = "5000px";
// Let it render
window.setTimeout(function() {
if (window.layoutTestController)
result += "<br><br>Second (huge layer):<br>" + layoutTestController.layerTreeAsText();
}, 0);
}, 100);
document.getElementById('container').style.height = "5000px";
result += recordLayerTree("<br><br>Second (huge layer):<br>");
// Small layer third
window.setTimeout(function() {
document.getElementById('container').style.height = "500px";
// Let it render
window.setTimeout(function() {
if (window.layoutTestController) {
result += "<br><br>Third (small layer):<br>" + layoutTestController.layerTreeAsText();
document.getElementById('layers').innerHTML = result;
layoutTestController.notifyDone();
}
}, 0);
}, 200);
document.getElementById('container').style.height = "500px";
result += recordLayerTree("<br><br>Third (small layer):<br>");
document.getElementById('layers').innerHTML = result;
}
function recordLayerTree(messagePrefix)
{
if (!window.layoutTestController)
return "";
// Force a layout and a paint to make sure the compositing layers
// have been updated.
document.body.offsetLeft;
layoutTestController.display();
return messagePrefix + layoutTestController.layerTreeAsText();
}
window.addEventListener('load', testOnLoad, false);
......
2011-01-17 Adam Roben <aroben@apple.com>
Don't access the CACFLayerRef's sublayers directly from PlatformCALayer
There might be a secret extra sublayer (the tile parent layer) that
PlatformCALayer doesn't know about. When PlatformCALayer would
encounter this, it would try to use the tile parent layer's
PlatformCALayer wrapper, which was null, and then would crash. We now
ask PlatformCALayerWinInternal for the sublayer list, since that class
knows about the tile parent layer and can exclude it from the sublayer
list.
Covered by compositing/tiling/huge-layer-resize.html.
Fixes <http://webkit.org/b/52597> Crash beneath
PlatformCALayer::adoptSublayers when switching out of tiling mode
(null-dereference of a PlatformCALayer)
Reviewed by Darin Adler and Chris Marrin.
* platform/graphics/ca/win/PlatformCALayerWin.cpp:
(PlatformCALayer::adoptSublayers):
(printLayer):
Changed to use PlatformCALayerWinInternal::getSublayers.
* platform/graphics/ca/win/PlatformCALayerWinInternal.cpp:
(PlatformCALayerWinInternal::getSublayers): Added. Retrieves the list
of PlatformCALayers that represent our sublayers. Significantly, this
code knows about the tile parent layer and can thus exclude it.
* platform/graphics/ca/win/PlatformCALayerWinInternal.h: Added
getSublayers.
2011-01-17 Naoki Takano <takano.naoki@gmail.com>
 
Reviewed by Kent Tamura.
......
......@@ -253,15 +253,8 @@ size_t PlatformCALayer::sublayerCount() const
void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
{
// Make a list of the sublayers from source
PlatformCALayerList sublayers;
size_t n = source->sublayerCount();
CFArrayRef sourceSublayers = CACFLayerGetSublayers(source->platformLayer());
for (size_t i = 0; i < n; ++i) {
CACFLayerRef layer = static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sourceSublayers, i)));
sublayers.append(platformCALayer(layer));
}
intern(source)->getSublayers(sublayers);
// Use setSublayers() because it properly nulls out the superlayer pointers.
setSublayers(sublayers);
......@@ -690,11 +683,11 @@ static void printLayer(const PlatformCALayer* layer, int indent)
printIndent(indent + 1);
fprintf(stderr, "(sublayers\n");
CFArrayRef sublayers = CACFLayerGetSublayers(layer->platformLayer());
for (int i = 0; i < n; ++i) {
PlatformCALayer* sublayer = PlatformCALayer::platformCALayer(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, i)));
printLayer(sublayer, indent + 2);
}
PlatformCALayerList sublayers;
intern(layer)->getSublayers(sublayers);
ASSERT(n == sublayers.size());
for (int i = 0; i < n; ++i)
printLayer(sublayers[i].get(), indent + 2);
printIndent(indent + 1);
fprintf(stderr, ")\n");
......
......@@ -210,6 +210,27 @@ void PlatformCALayerWinInternal::setSublayers(const PlatformCALayerList& list)
}
}
void PlatformCALayerWinInternal::getSublayers(PlatformCALayerList& list) const
{
CFArrayRef sublayers = CACFLayerGetSublayers(owner()->platformLayer());
if (!sublayers) {
list.clear();
return;
}
size_t count = CFArrayGetCount(sublayers);
size_t layersToSkip = 0;
if (owner()->layerType() == PlatformCALayer::LayerTypeWebTiledLayer) {
// Exclude the tile parent layer.
layersToSkip = 1;
}
list.resize(count - layersToSkip);
for (size_t arrayIndex = layersToSkip; arrayIndex < count; ++arrayIndex)
list[arrayIndex - layersToSkip] = PlatformCALayer::platformCALayer(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, arrayIndex)));
}
void PlatformCALayerWinInternal::removeAllSublayers()
{
CACFLayerSetSublayers(owner()->platformLayer(), 0);
......
......@@ -52,6 +52,7 @@ public:
PlatformCALayer* owner() const { return m_owner; }
void setSublayers(const PlatformCALayerList&);
void getSublayers(PlatformCALayerList&) const;
void removeAllSublayers();
void insertSublayer(PlatformCALayer*, size_t);
size_t sublayerCount() const;
......
Supports Markdown
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