- Revision
- 122152
- Author
- [email protected]
- Date
- 2012-07-09 13:36:21 -0700 (Mon, 09 Jul 2012)
Log Message
Tiled drawing means some elements can disappear behind the page
https://bugs.webkit.org/show_bug.cgi?id=88906
Reviewed by Simon Fraser.
Source/WebCore:
The compositing layers in the tile cache could become siblings
of the compositing layers for page elements. This meant that in
some 3d transforms, the elements could disappear behind the
page background (which is rendered into the tile cache) or intersect
with the tile cache tiles.
Fix this by inserting a flattening layer between the tile cache
and the page, ensuring that the cache will always be rendered
first. I was able to reuse the clipping layer for this, because
the tile cache is attached to the RenderView, so there should never
be a case where we have both a clipping layer and tiles.
The unfortunate part of this code is the temporary state variable
that wraps the call to GraphicsLayer::create. Because that method
calls back into the object, we need to make sure we don't create
another tile cache.
Also added some obvious names to the tile cache layers to
help with debugging.
Test: compositing/tile-cache-must-flatten.html
* platform/graphics/ca/mac/TileCache.mm:
(WebCore::TileCache::TileCache): give the tile host layer a name.
(WebCore::TileCache::createTileLayer):
* platform/graphics/ca/mac/WebTileCacheLayer.mm:
(WebCore): give each tile layer a name.
* rendering/RenderLayerBacking.cpp:
(WebCore):
(WebCore::RenderLayerBacking::shouldUseTileCache): check if we're in the middle
of creating the primary graphics layer before answering.
(WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): wrap our call to
createGraphicsLayer with a message to indicate we are making the layer that should
get a tile cache.
(WebCore::RenderLayerBacking::destroyGraphicsLayers):
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): needs to make
sure the flattening layer is in the tree.
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
(WebCore::RenderLayerBacking::updateInternalHierarchy):
(WebCore::RenderLayerBacking::updateClippingLayers):
(WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
* rendering/RenderLayerBacking.h: rename m_clippingLayer to m_containmentLayer
because it can now either be the clip or the tile cache flattener. Also
a new state property used when creating the main graphics layer.
(WebCore::RenderLayerBacking::hasClippingLayer):
(WebCore::RenderLayerBacking::clippingLayer):
(WebCore::RenderLayerBacking::parentForSublayers):
(WebCore::RenderLayerBacking::hasTileCacheFlatteningLayer):
(WebCore::RenderLayerBacking::tileCacheFlatteningLayer):
(RenderLayerBacking):
LayoutTests:
Reftest to make sure elements can't disappear behind the tile cache.
* compositing/tile-cache-must-flatten-expected.html: Added.
* compositing/tile-cache-must-flatten.html: Added.
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (122151 => 122152)
--- trunk/LayoutTests/ChangeLog 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/LayoutTests/ChangeLog 2012-07-09 20:36:21 UTC (rev 122152)
@@ -1,3 +1,15 @@
+2012-07-09 Dean Jackson <[email protected]>
+
+ Tiled drawing means some elements can disappear behind the page
+ https://bugs.webkit.org/show_bug.cgi?id=88906
+
+ Reviewed by Simon Fraser.
+
+ Reftest to make sure elements can't disappear behind the tile cache.
+
+ * compositing/tile-cache-must-flatten-expected.html: Added.
+ * compositing/tile-cache-must-flatten.html: Added.
+
2012-07-09 Zan Dobersek <[email protected]>
[Gtk] Implement dumpFrameScrollPosition in DumpRenderTree
Modified: trunk/Source/WebCore/ChangeLog (122151 => 122152)
--- trunk/Source/WebCore/ChangeLog 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/Source/WebCore/ChangeLog 2012-07-09 20:36:21 UTC (rev 122152)
@@ -1,3 +1,61 @@
+2012-07-09 Dean Jackson <[email protected]>
+
+ Tiled drawing means some elements can disappear behind the page
+ https://bugs.webkit.org/show_bug.cgi?id=88906
+
+ Reviewed by Simon Fraser.
+
+ The compositing layers in the tile cache could become siblings
+ of the compositing layers for page elements. This meant that in
+ some 3d transforms, the elements could disappear behind the
+ page background (which is rendered into the tile cache) or intersect
+ with the tile cache tiles.
+
+ Fix this by inserting a flattening layer between the tile cache
+ and the page, ensuring that the cache will always be rendered
+ first. I was able to reuse the clipping layer for this, because
+ the tile cache is attached to the RenderView, so there should never
+ be a case where we have both a clipping layer and tiles.
+
+ The unfortunate part of this code is the temporary state variable
+ that wraps the call to GraphicsLayer::create. Because that method
+ calls back into the object, we need to make sure we don't create
+ another tile cache.
+
+ Also added some obvious names to the tile cache layers to
+ help with debugging.
+
+ Test: compositing/tile-cache-must-flatten.html
+
+ * platform/graphics/ca/mac/TileCache.mm:
+ (WebCore::TileCache::TileCache): give the tile host layer a name.
+ (WebCore::TileCache::createTileLayer):
+ * platform/graphics/ca/mac/WebTileCacheLayer.mm:
+ (WebCore): give each tile layer a name.
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore):
+ (WebCore::RenderLayerBacking::shouldUseTileCache): check if we're in the middle
+ of creating the primary graphics layer before answering.
+ (WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): wrap our call to
+ createGraphicsLayer with a message to indicate we are making the layer that should
+ get a tile cache.
+ (WebCore::RenderLayerBacking::destroyGraphicsLayers):
+ (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): needs to make
+ sure the flattening layer is in the tree.
+ (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
+ (WebCore::RenderLayerBacking::updateInternalHierarchy):
+ (WebCore::RenderLayerBacking::updateClippingLayers):
+ (WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
+ * rendering/RenderLayerBacking.h: rename m_clippingLayer to m_containmentLayer
+ because it can now either be the clip or the tile cache flattener. Also
+ a new state property used when creating the main graphics layer.
+ (WebCore::RenderLayerBacking::hasClippingLayer):
+ (WebCore::RenderLayerBacking::clippingLayer):
+ (WebCore::RenderLayerBacking::parentForSublayers):
+ (WebCore::RenderLayerBacking::hasTileCacheFlatteningLayer):
+ (WebCore::RenderLayerBacking::tileCacheFlatteningLayer):
+ (RenderLayerBacking):
+
2012-07-09 Christophe Dumez <[email protected]>
[EFL] Log significant Gamepad API-related events
Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm (122151 => 122152)
--- trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileCache.mm 2012-07-09 20:36:21 UTC (rev 122152)
@@ -64,6 +64,9 @@
[CATransaction begin];
[CATransaction setDisableActions:YES];
[m_tileCacheLayer addSublayer:m_tileContainerLayer.get()];
+#ifndef NDEBUG
+ [m_tileContainerLayer.get() setName:@"TileCache Container Layer"];
+#endif
[CATransaction commit];
}
@@ -394,6 +397,9 @@
[layer.get() setBorderWidth:m_tileDebugBorderWidth];
[layer.get() setEdgeAntialiasingMask:0];
[layer.get() setOpaque:YES];
+#ifndef NDEBUG
+ [layer.get() setName:@"Tile"];
+#endif
#if !defined(BUILDING_ON_SNOW_LEOPARD)
[layer.get() setContentsScale:m_deviceScaleFactor];
Modified: trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm (122151 => 122152)
--- trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm 2012-07-09 20:36:21 UTC (rev 122152)
@@ -42,7 +42,9 @@
// FIXME: The tile size should be configurable.
_tileCache = TileCache::create(self, IntSize(512, 512));
-
+#ifndef NDEBUG
+ [self setName:@"WebTileCacheLayer"];
+#endif
return self;
}
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (122151 => 122152)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2012-07-09 20:36:21 UTC (rev 122152)
@@ -90,6 +90,8 @@
return false;
}
+bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
+
RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
: m_owningLayer(layer)
, m_artificiallyInflatedBounds(false)
@@ -154,7 +156,7 @@
bool RenderLayerBacking::shouldUseTileCache(const GraphicsLayer*) const
{
- return m_usingTiledCacheLayer;
+ return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
}
void RenderLayerBacking::createPrimaryGraphicsLayer()
@@ -163,8 +165,19 @@
#ifndef NDEBUG
layerName = nameForLayer();
#endif
+
+ // The call to createGraphicsLayer ends calling back into here as
+ // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want
+ // the tile cache on our main layer. This is pretty ugly, but saves us from
+ // exposing the API to all clients.
+
+ m_creatingPrimaryGraphicsLayer = true;
m_graphicsLayer = createGraphicsLayer(layerName);
+ m_creatingPrimaryGraphicsLayer = false;
+ if (m_usingTiledCacheLayer)
+ m_containmentLayer = createGraphicsLayer("TileCache Flattening Layer");
+
if (m_isMainFrameRenderViewLayer) {
bool isTransparent = false;
if (FrameView* frameView = toRenderView(renderer())->frameView())
@@ -196,7 +209,7 @@
m_graphicsLayer = nullptr;
m_foregroundLayer = nullptr;
- m_clippingLayer = nullptr;
+ m_containmentLayer = nullptr;
m_maskLayer = nullptr;
}
@@ -349,6 +362,11 @@
if (layerConfigChanged)
updateInternalHierarchy();
+ if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
+ flatteningLayer->removeFromParent();
+ m_graphicsLayer->addChild(flatteningLayer);
+ }
+
if (updateMaskLayer(renderer->hasMask()))
m_graphicsLayer->setMaskLayer(m_maskLayer.get());
@@ -515,11 +533,11 @@
// If we have a layer that clips children, position it.
IntRect clippingBox;
- if (m_clippingLayer) {
+ if (GraphicsLayer* clipLayer = clippingLayer()) {
clippingBox = clipBox(toRenderBox(renderer()));
- m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
- m_clippingLayer->setSize(clippingBox.size());
- m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
+ clipLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
+ clipLayer->setSize(clippingBox.size());
+ clipLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
}
if (m_maskLayer) {
@@ -546,18 +564,19 @@
m_graphicsLayer->setAnchorPoint(anchor);
RenderStyle* style = renderer()->style();
+ GraphicsLayer* clipLayer = clippingLayer();
if (style->hasPerspective()) {
TransformationMatrix t = owningLayer()->perspectiveTransform();
- if (m_clippingLayer) {
- m_clippingLayer->setChildrenTransform(t);
+ if (clipLayer) {
+ clipLayer->setChildrenTransform(t);
m_graphicsLayer->setChildrenTransform(TransformationMatrix());
}
else
m_graphicsLayer->setChildrenTransform(t);
} else {
- if (m_clippingLayer)
- m_clippingLayer->setChildrenTransform(TransformationMatrix());
+ if (clipLayer)
+ clipLayer->setChildrenTransform(TransformationMatrix());
else
m_graphicsLayer->setChildrenTransform(TransformationMatrix());
}
@@ -569,7 +588,7 @@
FloatPoint foregroundPosition;
FloatSize foregroundSize = newSize;
IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
- if (m_clippingLayer) {
+ if (hasClippingLayer()) {
// If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
// so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
foregroundSize = FloatSize(clippingBox.size());
@@ -611,9 +630,9 @@
m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
}
- if (m_clippingLayer) {
- m_clippingLayer->removeFromParent();
- m_graphicsLayer->addChild(m_clippingLayer.get());
+ if (m_containmentLayer) {
+ m_containmentLayer->removeFromParent();
+ m_graphicsLayer->addChild(m_containmentLayer.get());
}
// The clip for child layers does not include space for overflow controls, so they exist as
@@ -661,14 +680,14 @@
}
if (needsDescendantClip) {
- if (!m_clippingLayer) {
- m_clippingLayer = createGraphicsLayer("Child clipping Layer");
- m_clippingLayer->setMasksToBounds(true);
+ if (!m_containmentLayer && !m_usingTiledCacheLayer) {
+ m_containmentLayer = createGraphicsLayer("Child clipping Layer");
+ m_containmentLayer->setMasksToBounds(true);
layersChanged = true;
}
- } else if (m_clippingLayer) {
- m_clippingLayer->removeFromParent();
- m_clippingLayer = nullptr;
+ } else if (hasClippingLayer()) {
+ m_containmentLayer->removeFromParent();
+ m_containmentLayer = nullptr;
layersChanged = true;
}
@@ -1576,7 +1595,7 @@
{
double backingMemory;
- // m_ancestorClippingLayer and m_clippingLayer are just used for masking, so have no backing.
+ // m_ancestorClippingLayer and m_containmentLayer are just used for masking or containment, so have no backing.
backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
if (m_foregroundLayer)
backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (122151 => 122152)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.h 2012-07-09 20:10:31 UTC (rev 122151)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h 2012-07-09 20:36:21 UTC (rev 122152)
@@ -74,8 +74,8 @@
GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); }
// Layer to clip children
- bool hasClippingLayer() const { return m_clippingLayer != 0; }
- GraphicsLayer* clippingLayer() const { return m_clippingLayer.get(); }
+ bool hasClippingLayer() const { return (m_containmentLayer && !m_usingTiledCacheLayer); }
+ GraphicsLayer* clippingLayer() const { return !m_usingTiledCacheLayer ? m_containmentLayer.get() : 0; }
// Layer to get clipped by ancestor
bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; }
@@ -86,7 +86,7 @@
bool hasMaskLayer() const { return m_maskLayer != 0; }
- GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer.get() : m_graphicsLayer.get(); }
+ GraphicsLayer* parentForSublayers() const { return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get(); }
GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); }
// RenderLayers with backing normally short-circuit paintLayer() because
@@ -220,6 +220,9 @@
bool shouldClipCompositedBounds() const;
+ bool hasTileCacheFlatteningLayer() const { return (m_containmentLayer && m_usingTiledCacheLayer); }
+ GraphicsLayer* tileCacheFlatteningLayer() const { return m_usingTiledCacheLayer ? m_containmentLayer.get() : 0; }
+
void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
@@ -230,7 +233,7 @@
OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context
OwnPtr<GraphicsLayer> m_graphicsLayer;
OwnPtr<GraphicsLayer> m_foregroundLayer; // only used in cases where we need to draw the foreground separately
- OwnPtr<GraphicsLayer> m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children
+ OwnPtr<GraphicsLayer> m_containmentLayer; // Only used if we have clipping on a stacking context with compositing children, or if the layer has a tile cache.
OwnPtr<GraphicsLayer> m_maskLayer; // only used if we have a mask
OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
@@ -246,6 +249,8 @@
#if ENABLE(CSS_FILTERS)
bool m_canCompositeFilters;
#endif
+
+ static bool m_creatingPrimaryGraphicsLayer;
};
} // namespace WebCore