Title: [139815] trunk/Source/WebCore
Revision
139815
Author
[email protected]
Date
2013-01-15 18:01:39 -0800 (Tue, 15 Jan 2013)

Log Message

Add the ability for a RenderLayerBacking to have a layer that renders backgrounds.
https://bugs.webkit.org/show_bug.cgi?id=106961

Reviewed by Dean Jackson.

In some cases we need a compositing layer to render its background into
a separate GraphicsLayer (e.g. for background-attachment: fixed in some scenarios).

To support this, have RenderLayer optionally create a GraphicsLayer for the background.
Currently nothing causes background layers to get created.

Having a background layer requires that we add an additional containment layer
which encloses the background, primary and foreground layers, since the
background layer has to be composited behind the primary content. This containment
layer gets any transform, including page scale on the RenderView's layer.

No new tests; there's no way to create a background layer yet. This was tested during
development by forcing a background layer.

* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateDebugIndicators): Show borders on both new layers
and repaint counters on the background layer.
(WebCore::RenderLayerBacking::destroyGraphicsLayers): Clear the two new layers.
(WebCore::RenderLayerBacking::updateTransform): If we have a containment layer, it
takes the transform (and clear the transform on the primary layer).
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Make the background
layer if we need one (currently never).
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Position and size
the containment layer if we have one. If we do, then the m_graphicsLayer will
be at 0,0 in that containment layer. The background layer is also sized similarly
to the foreground layer.
(WebCore::RenderLayerBacking::updateInternalHierarchy): Adapt to the new hierarchy
with containment and background layers if we have them.
(WebCore::RenderLayerBacking::updateBackgroundLayer): Here's where we create the background
and containment layers.
(WebCore::RenderLayerBacking::childForSuperlayers): If we have a containment layer, that's
what gets attached to our parent.
(WebCore::RenderLayerBacking::getCurrentTransform): The containment layer gets the transform
if we have one, so check that here.
(WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
(WebCore::RenderLayerBacking::reportMemoryUsage):
* rendering/RenderLayerBacking.h:
(RenderLayerBacking):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::deviceOrPageScaleFactorChanged): We need to start notifying
about page/device scale on the containment layer if there is one (since it takes page scale), so
use childForSuperlayers() rather than just getting the primary layer.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (139814 => 139815)


--- trunk/Source/WebCore/ChangeLog	2013-01-16 01:48:37 UTC (rev 139814)
+++ trunk/Source/WebCore/ChangeLog	2013-01-16 02:01:39 UTC (rev 139815)
@@ -1,3 +1,53 @@
+2013-01-15  Simon Fraser  <[email protected]>
+
+        Add the ability for a RenderLayerBacking to have a layer that renders backgrounds.
+        https://bugs.webkit.org/show_bug.cgi?id=106961
+
+        Reviewed by Dean Jackson.
+
+        In some cases we need a compositing layer to render its background into
+        a separate GraphicsLayer (e.g. for background-attachment: fixed in some scenarios).
+        
+        To support this, have RenderLayer optionally create a GraphicsLayer for the background.
+        Currently nothing causes background layers to get created.
+        
+        Having a background layer requires that we add an additional containment layer
+        which encloses the background, primary and foreground layers, since the 
+        background layer has to be composited behind the primary content. This containment
+        layer gets any transform, including page scale on the RenderView's layer.
+        
+        No new tests; there's no way to create a background layer yet. This was tested during
+        development by forcing a background layer.
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateDebugIndicators): Show borders on both new layers
+        and repaint counters on the background layer.
+        (WebCore::RenderLayerBacking::destroyGraphicsLayers): Clear the two new layers.
+        (WebCore::RenderLayerBacking::updateTransform): If we have a containment layer, it
+        takes the transform (and clear the transform on the primary layer).
+        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Make the background
+        layer if we need one (currently never).
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Position and size
+        the containment layer if we have one. If we do, then the m_graphicsLayer will
+        be at 0,0 in that containment layer. The background layer is also sized similarly
+        to the foreground layer.
+        (WebCore::RenderLayerBacking::updateInternalHierarchy): Adapt to the new hierarchy
+        with containment and background layers if we have them.
+        (WebCore::RenderLayerBacking::updateBackgroundLayer): Here's where we create the background
+        and containment layers.
+        (WebCore::RenderLayerBacking::childForSuperlayers): If we have a containment layer, that's
+        what gets attached to our parent.
+        (WebCore::RenderLayerBacking::getCurrentTransform): The containment layer gets the transform
+        if we have one, so check that here.
+        (WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
+        (WebCore::RenderLayerBacking::reportMemoryUsage):
+        * rendering/RenderLayerBacking.h:
+        (RenderLayerBacking):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::deviceOrPageScaleFactorChanged): We need to start notifying
+        about page/device scale on the containment layer if there is one (since it takes page scale), so
+        use childForSuperlayers() rather than just getting the primary layer.
+
 2013-01-15  Pan Deng  <[email protected]>
 
         Remove Key3 and Challenge Response fields from Websocket implementation and Web Inspector.

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (139814 => 139815)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2013-01-16 01:48:37 UTC (rev 139814)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2013-01-16 02:01:39 UTC (rev 139815)
@@ -233,6 +233,14 @@
         m_foregroundLayer->setShowDebugBorder(showBorder);
         m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
     }
+    
+    if (m_contentsContainmentLayer)
+        m_contentsContainmentLayer->setShowDebugBorder(showBorder);
+    
+    if (m_backgroundLayer) {
+        m_backgroundLayer->setShowDebugBorder(showBorder);
+        m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
+    }
 
     if (m_maskLayer) {
         m_maskLayer->setShowDebugBorder(showBorder);
@@ -309,8 +317,10 @@
         m_graphicsLayer->removeFromParent();
 
     m_ancestorClippingLayer = nullptr;
+    m_contentsContainmentLayer = nullptr;
     m_graphicsLayer = nullptr;
     m_foregroundLayer = nullptr;
+    m_backgroundLayer = nullptr;
     m_childContainmentLayer = nullptr;
     m_maskLayer = nullptr;
 
@@ -333,7 +343,11 @@
         makeMatrixRenderable(t, compositor()->canRender3DTransforms());
     }
     
-    m_graphicsLayer->setTransform(t);
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->setTransform(t);
+        m_graphicsLayer->setTransform(TransformationMatrix());
+    } else
+        m_graphicsLayer->setTransform(t);
 }
 
 #if ENABLE(CSS_FILTERS)
@@ -465,6 +479,11 @@
     m_owningLayer->updateZOrderLists();
 
     bool layerConfigChanged = false;
+    
+    // FIXME: The background layer is currently unused.
+    if (updateBackgroundLayer(false))
+        layerConfigChanged = true;
+
     if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
         layerConfigChanged = true;
     
@@ -576,7 +595,9 @@
     m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
 
     RenderStyle* style = renderer()->style();
-    m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection());
+    // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
+    bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
+    m_graphicsLayer->setPreserves3D(preserves3D);
     m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
 
     RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
@@ -630,13 +651,22 @@
         graphicsLayerParentLocation = parentClipRect.location();
     }
 
+    FloatSize contentsSize = relativeCompositingBounds.size();
+    
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->setPreserves3D(preserves3D);
+        m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+        // Use the same size as m_graphicsLayer so transforms behave correctly.
+        m_contentsContainmentLayer->setSize(contentsSize);
+        graphicsLayerParentLocation = relativeCompositingBounds.location();
+    }
+
     m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
     m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
     
     FloatSize oldSize = m_graphicsLayer->size();
-    FloatSize newSize = relativeCompositingBounds.size();
-    if (oldSize != newSize) {
-        m_graphicsLayer->setSize(newSize);
+    if (oldSize != contentsSize) {
+        m_graphicsLayer->setSize(contentsSize);
         // Usually invalidation will happen via layout etc, but if we've affected the layer
         // size by constraining relative to a clipping ancestor or the viewport, we
         // have to invalidate to avoid showing stretched content.
@@ -674,7 +704,10 @@
         FloatPoint3D anchor(relativeCompositingBounds.width()  != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width()  : 0.5f,
                             relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
                             transformOrigin.z());
-        m_graphicsLayer->setAnchorPoint(anchor);
+        if (m_contentsContainmentLayer)
+            m_contentsContainmentLayer->setAnchorPoint(anchor);
+        else
+            m_graphicsLayer->setAnchorPoint(anchor);
 
         RenderStyle* style = renderer()->style();
         GraphicsLayer* clipLayer = clippingLayer();
@@ -695,11 +728,13 @@
         }
     } else {
         m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
+        if (m_contentsContainmentLayer)
+            m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
     }
 
     if (m_foregroundLayer) {
         FloatPoint foregroundPosition;
-        FloatSize foregroundSize = newSize;
+        FloatSize foregroundSize = contentsSize;
         IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
         if (hasClippingLayer()) {
             // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
@@ -716,6 +751,17 @@
         m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
     }
 
+    if (m_backgroundLayer) {
+        FloatSize backgroundSize = contentsSize;
+        IntSize backgroundOffset = m_graphicsLayer->offsetFromRenderer();
+        m_backgroundLayer->setPosition(FloatPoint());
+        if (backgroundSize != m_backgroundLayer->size()) {
+            m_backgroundLayer->setSize(backgroundSize);
+            m_backgroundLayer->setNeedsDisplay();
+        }
+        m_backgroundLayer->setOffsetFromRenderer(backgroundOffset);
+    }
+
     if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
         RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
         reflectionBacking->updateGraphicsLayerGeometry();
@@ -792,12 +838,24 @@
 {
     // m_foregroundLayer has to be inserted in the correct order with child layers,
     // so it's not inserted here.
-    if (m_ancestorClippingLayer) {
+    if (m_ancestorClippingLayer)
         m_ancestorClippingLayer->removeAllChildren();
-        m_graphicsLayer->removeFromParent();
-        m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+    
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->removeAllChildren();
+        if (m_ancestorClippingLayer)
+            m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
     }
+    
+    if (m_backgroundLayer)
+        m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
 
+    m_graphicsLayer->removeFromParent();
+    if (m_contentsContainmentLayer)
+        m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
+    else if (m_ancestorClippingLayer)
+        m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+
     if (m_childContainmentLayer) {
         m_childContainmentLayer->removeFromParent();
         m_graphicsLayer->addChild(m_childContainmentLayer.get());
@@ -1032,6 +1090,49 @@
     return layerChanged;
 }
 
+bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
+{
+    bool layerChanged = false;
+    if (needsBackgroundLayer) {
+        if (!m_backgroundLayer) {
+            String layerName;
+#ifndef NDEBUG
+            layerName = m_owningLayer->name() + " (background)";
+#endif
+            m_backgroundLayer = createGraphicsLayer(layerName);
+            m_backgroundLayer->setDrawsContent(true);
+            m_backgroundLayer->setAnchorPoint(FloatPoint3D());
+            m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
+            layerChanged = true;
+        }
+        
+        if (!m_contentsContainmentLayer) {
+            String layerName;
+#ifndef NDEBUG
+            layerName = m_owningLayer->name() + " (contents containment)";
+#endif
+            m_contentsContainmentLayer = createGraphicsLayer(layerName);
+            m_contentsContainmentLayer->setAppliesPageScale(true);
+            m_graphicsLayer->setAppliesPageScale(false);
+            layerChanged = true;
+        }
+    } else {
+        if (m_backgroundLayer) {
+            m_backgroundLayer->removeFromParent();
+            m_backgroundLayer = nullptr;
+            layerChanged = true;
+        }
+        if (m_contentsContainmentLayer) {
+            m_contentsContainmentLayer->removeFromParent();
+            m_contentsContainmentLayer = nullptr;
+            layerChanged = true;
+            m_graphicsLayer->setAppliesPageScale(true);
+        }
+    }
+
+    return layerChanged;
+}
+
 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
 {
     bool layerChanged = false;
@@ -1548,6 +1649,17 @@
     return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
 }
 
+GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
+{
+    if (m_ancestorClippingLayer)
+        return m_ancestorClippingLayer.get();
+
+    if (m_contentsContainmentLayer)
+        return m_contentsContainmentLayer.get();
+    
+    return m_graphicsLayer.get();
+}
+
 bool RenderLayerBacking::paintsIntoWindow() const
 {
     if (m_usingTiledCacheLayer)
@@ -1738,7 +1850,8 @@
 
 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
 {
-    if (graphicsLayer != m_graphicsLayer)
+    GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
+    if (graphicsLayer != transformedLayer)
         return false;
 
     if (m_owningLayer->hasTransform()) {
@@ -2013,7 +2126,7 @@
 {
     double backingMemory;
     
-    // m_ancestorClippingLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
+    // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
     backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
     if (m_foregroundLayer)
         backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
@@ -2054,6 +2167,7 @@
     MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
     info.addWeakPointer(m_owningLayer);
     info.addMember(m_ancestorClippingLayer);
+    info.addMember(m_contentsContainmentLayer);
     info.addMember(m_graphicsLayer);
     info.addMember(m_foregroundLayer);
     info.addMember(m_childContainmentLayer);

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (139814 => 139815)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2013-01-16 01:48:37 UTC (rev 139814)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2013-01-16 02:01:39 UTC (rev 139815)
@@ -101,7 +101,7 @@
     bool hasMaskLayer() const { return m_maskLayer != 0; }
 
     GraphicsLayer* parentForSublayers() const;
-    GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer.get() : m_graphicsLayer.get(); }
+    GraphicsLayer* childForSuperlayers() const;
 
     // RenderLayers with backing normally short-circuit paintLayer() because
     // their content is rendered via callbacks from GraphicsLayer. However, the document
@@ -204,6 +204,7 @@
     bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
     bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer);
     bool updateForegroundLayer(bool needsForegroundLayer);
+    bool updateBackgroundLayer(bool needsBackgroundLayer);
     bool updateMaskLayer(bool needsMaskLayer);
     bool requiresHorizontalScrollbarLayer() const;
     bool requiresVerticalScrollbarLayer() const;
@@ -264,8 +265,10 @@
     RenderLayer* m_owningLayer;
 
     OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // Only used if we are clipped by an ancestor which is not a stacking context.
+    OwnPtr<GraphicsLayer> m_contentsContainmentLayer; // Only used if we have a background layer; takes the transform.
     OwnPtr<GraphicsLayer> m_graphicsLayer;
     OwnPtr<GraphicsLayer> m_foregroundLayer; // Only used in cases where we need to draw the foreground separately.
+    OwnPtr<GraphicsLayer> m_backgroundLayer; // Only used in cases where we need to draw the background separately.
     OwnPtr<GraphicsLayer> m_childContainmentLayer; // 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.
 

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (139814 => 139815)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-01-16 01:48:37 UTC (rev 139814)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-01-16 02:01:39 UTC (rev 139815)
@@ -2626,7 +2626,7 @@
     if (!viewLayer->isComposited())
         return;
 
-    if (GraphicsLayer* rootLayer = viewLayer->backing()->graphicsLayer())
+    if (GraphicsLayer* rootLayer = viewLayer->backing()->childForSuperlayers())
         rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to