Add a logging channel and some ouput for compositing
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Apr 2012 04:30:13 +0000 (04:30 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Apr 2012 04:30:13 +0000 (04:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=84817

Reviewed by Darin Adler.

Add a logging channel called "Compositing".

Output useful information to this channel, including
a line for each composited layer, its composited bounds,
the reason it was composited, the backing store megapixels,
and a count of total composited layers and total backing
store megapixels.

* platform/Logging.cpp:
(WebCore):
(WebCore::getChannelFromName):
* platform/Logging.h:
(WebCore):
* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::backingStoreArea):
* platform/graphics/GraphicsLayer.h:
(GraphicsLayer):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::backingStoreArea):
(WebCore):
* platform/graphics/ca/GraphicsLayerCA.h:
(GraphicsLayerCA):
* platform/mac/LoggingMac.mm:
(WebCore::initializeLoggingChannelsIfNecessary):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::nameForLayer):
(WebCore::RenderLayerBacking::backingStoreArea):
(WebCore):
* rendering/RenderLayerBacking.h:
(RenderLayerBacking):
* rendering/RenderLayerCompositor.cpp:
(WebCore):
(WebCore::compositingLogEnabled):
(WebCore::RenderLayerCompositor::RenderLayerCompositor):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
(WebCore::RenderLayerCompositor::logCompositingInfo):
(WebCore::RenderLayerCompositor::rebuildCompositingLayerTree):
(WebCore::RenderLayerCompositor::updateLayerTreeGeometry):
(WebCore::RenderLayerCompositor::reasonForCompositing):
* rendering/RenderLayerCompositor.h:
(RenderLayerCompositor):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@115165 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/Logging.cpp
Source/WebCore/platform/Logging.h
Source/WebCore/platform/graphics/GraphicsLayer.cpp
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/platform/mac/LoggingMac.mm
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h

index ad4c293..4b85421 100644 (file)
@@ -1,3 +1,52 @@
+2012-04-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Add a logging channel and some ouput for compositing
+        https://bugs.webkit.org/show_bug.cgi?id=84817
+
+        Reviewed by Darin Adler.
+
+        Add a logging channel called "Compositing".
+        
+        Output useful information to this channel, including
+        a line for each composited layer, its composited bounds,
+        the reason it was composited, the backing store megapixels,
+        and a count of total composited layers and total backing
+        store megapixels.
+
+        * platform/Logging.cpp:
+        (WebCore):
+        (WebCore::getChannelFromName):
+        * platform/Logging.h:
+        (WebCore):
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::backingStoreArea):
+        * platform/graphics/GraphicsLayer.h:
+        (GraphicsLayer):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::backingStoreArea):
+        (WebCore):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        (GraphicsLayerCA):
+        * platform/mac/LoggingMac.mm:
+        (WebCore::initializeLoggingChannelsIfNecessary):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::nameForLayer):
+        (WebCore::RenderLayerBacking::backingStoreArea):
+        (WebCore):
+        * rendering/RenderLayerBacking.h:
+        (RenderLayerBacking):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore):
+        (WebCore::compositingLogEnabled):
+        (WebCore::RenderLayerCompositor::RenderLayerCompositor):
+        (WebCore::RenderLayerCompositor::updateCompositingLayers):
+        (WebCore::RenderLayerCompositor::logCompositingInfo):
+        (WebCore::RenderLayerCompositor::rebuildCompositingLayerTree):
+        (WebCore::RenderLayerCompositor::updateLayerTreeGeometry):
+        (WebCore::RenderLayerCompositor::reasonForCompositing):
+        * rendering/RenderLayerCompositor.h:
+        (RenderLayerCompositor):
+
 2012-04-24  Kulanthaivel Palanichamy  <kulanthaivel@codeaurora.org>
 
         getMatchedCSSRules() should return null when the second argument is an unrecognized pseudo-element name
index bd01964..34637a7 100644 (file)
@@ -62,6 +62,8 @@ WTFLogChannel LogProgress =          { 0x08000000, "WebCoreLogLevel", WTFLogChan
 WTFLogChannel LogFileAPI =           { 0x10000000, "WebCoreLogLevel", WTFLogChannelOff };
 
 WTFLogChannel LogWebAudio =          { 0x20000000, "WebCoreLogLevel", WTFLogChannelOff };
+WTFLogChannel LogCompositing =       { 0x40000000, "WebCoreLogLevel", WTFLogChannelOff };
+
 
 WTFLogChannel* getChannelFromName(const String& channelName)
 {
@@ -140,6 +142,9 @@ WTFLogChannel* getChannelFromName(const String& channelName)
     if (equalIgnoringCase(channelName, String("WebAudio")))
         return &LogWebAudio;
 
+    if (equalIgnoringCase(channelName, String("Compositing")))
+        return &LogCompositing;
+
     return 0;
 }
 
index 8201f16..1af1c04 100644 (file)
@@ -60,6 +60,7 @@ namespace WebCore {
     extern WTFLogChannel LogProgress;
     extern WTFLogChannel LogFileAPI;
     extern WTFLogChannel LogWebAudio;
+    extern WTFLogChannel LogCompositing;
 
     void initializeLoggingChannelsIfNecessary();
     WTFLogChannel* getChannelFromName(const String& channelName);
index b29de76..10d7b7f 100644 (file)
@@ -509,6 +509,14 @@ int GraphicsLayer::validateTransformOperations(const KeyframeValueList& valueLis
     return firstIndex;
 }
 
+double GraphicsLayer::backingStoreArea() const
+{
+    if (!drawsContent())
+        return 0;
+    
+    // Effects of page and device scale are ignored; subclasses should override to take these into account.
+    return static_cast<double>(size().width()) * size().height();
+}
 
 static void writeIndent(TextStream& ts, int indent)
 {
index 1a06a64..16c73a4 100644 (file)
@@ -426,6 +426,9 @@ public:
     // pointers for the layers and timing data will be included in the returned string.
     String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
 
+    // Return an estimate of the backing store area (in pixels). May be incorrect for tiled layers.
+    virtual double backingStoreArea() const;
+
     bool usingTiledLayer() const { return m_usingTiledLayer; }
 
     virtual TiledBacking* tiledBacking() { return 0; }
index 99adf2b..1d9b4c1 100644 (file)
@@ -2810,6 +2810,15 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
     m_uncommittedChanges |= flags;
 }
 
+double GraphicsLayerCA::backingStoreArea() const
+{
+    if (!drawsContent())
+        return 0;
+    
+    // contentsLayer is given to us, so we don't really know anything about its contents.
+    return static_cast<double>(size().width()) * size().height() * m_layer->contentsScale();
+}
+
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
index e385dba..4d5f01b 100644 (file)
@@ -162,6 +162,8 @@ private:
     virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) OVERRIDE;
     virtual float platformCALayerDeviceScaleFactor() OVERRIDE;
 
+    virtual double backingStoreArea() const;
+
     void updateOpacityOnLayer();
     
 #if ENABLE(CSS_FILTERS)
index 45cf6e5..4c9b303 100644 (file)
@@ -73,6 +73,7 @@ void initializeLoggingChannelsIfNecessary()
     initializeWithUserDefault(LogPlugins);
     initializeWithUserDefault(LogArchives);
     initializeWithUserDefault(LogWebAudio);
+    initializeWithUserDefault(LogCompositing);
 }
 
 }
index a8d7834..da127ff 100644 (file)
@@ -1500,7 +1500,6 @@ AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID
     return AnimatedPropertyInvalid;
 }
 
-#ifndef NDEBUG
 String RenderLayerBacking::nameForLayer() const
 {
     String name = renderer()->renderName();
@@ -1516,7 +1515,6 @@ String RenderLayerBacking::nameForLayer() const
 
     return name;
 }
-#endif
 
 CompositingLayerType RenderLayerBacking::compositingLayerType() const
 {
@@ -1529,6 +1527,30 @@ CompositingLayerType RenderLayerBacking::compositingLayerType() const
     return ContainerCompositingLayer;
 }
 
+double RenderLayerBacking::backingStoreArea() const
+{
+    double backingArea;
+    
+    // m_ancestorClippingLayer and m_clippingLayer are just used for masking, so have no backing.
+    backingArea = m_graphicsLayer->backingStoreArea();
+    if (m_foregroundLayer)
+        backingArea += m_foregroundLayer->backingStoreArea();
+    if (m_maskLayer)
+        backingArea += m_maskLayer->backingStoreArea();
+
+    if (m_layerForHorizontalScrollbar)
+        backingArea += m_layerForHorizontalScrollbar->backingStoreArea();
+
+    if (m_layerForVerticalScrollbar)
+        backingArea += m_layerForVerticalScrollbar->backingStoreArea();
+
+    if (m_layerForScrollCorner)
+        backingArea += m_layerForScrollCorner->backingStoreArea();
+    
+    return backingArea;
+}
+
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
+
index ccff773..a6a03ac 100644 (file)
@@ -158,6 +158,11 @@ public:
 #if ENABLE(CSS_FILTERS)
     bool canCompositeFilters() const { return m_canCompositeFilters; }
 #endif
+
+    // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers.
+    double backingStoreArea() const;
+
+    String nameForLayer() const;
     
 private:
     void createPrimaryGraphicsLayer();
@@ -220,10 +225,6 @@ private:
     static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
     static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID);
 
-#ifndef NDEBUG
-    String nameForLayer() const;
-#endif
-
     RenderLayer* m_owningLayer;
 
     OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context
index 37b5ff7..2dbf6bc 100644 (file)
@@ -59,7 +59,7 @@
 #include "HTMLMediaElement.h"
 #endif
 
-#if PROFILE_LAYER_REBUILD
+#if !LOG_DISABLED
 #include <wtf/CurrentTime.h>
 #endif
 
@@ -145,6 +145,18 @@ struct CompositingState {
 #endif
 };
 
+
+static inline bool compositingLogEnabled()
+{
+#if !LOG_DISABLED
+    return LogCompositing.state == WTFLogChannelOn;
+#else
+    return false;
+#endif
+}
+
+#define PIXELS_PER_MEGAPIXEL 1000000.0
+
 RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
     : m_renderView(renderView)
     , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
@@ -161,9 +173,12 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
     , m_flushingLayers(false)
     , m_forceCompositingMode(false)
     , m_rootLayerAttachment(RootLayerUnattached)
-#if PROFILE_LAYER_REBUILD
+#if !LOG_DISABLED
     , m_rootLayerUpdateCount(0)
-#endif // PROFILE_LAYER_REBUILD
+    , m_obligateCompositedLayerCount(0)
+    , m_secondaryCompositedLayerCount(0)
+    , m_backingAreaMegaPixels(0)
+#endif
 {
 }
 
@@ -353,10 +368,12 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
     if (isFullUpdate && updateType == CompositingUpdateAfterLayout)
         m_reevaluateCompositingAfterLayout = false;
 
-#if PROFILE_LAYER_REBUILD
-    ++m_rootLayerUpdateCount;
-    
-    double startTime = WTF::currentTime();
+#if !LOG_DISABLED
+    double startTime;
+    if (compositingLogEnabled()) {
+        ++m_rootLayerUpdateCount;
+        startTime = currentTime();
+    }
 #endif        
 
     if (checkForHierarchyUpdate) {
@@ -373,6 +390,19 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
         needHierarchyUpdate |= layersChanged;
     }
 
+#if !LOG_DISABLED
+    if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+        m_obligateCompositedLayerCount = 0;
+        m_secondaryCompositedLayerCount = 0;
+        m_backingAreaMegaPixels = 0;
+
+        Frame* frame = m_renderView->frameView()->frame();
+        bool isMainFrame = !m_renderView->document()->ownerElement();
+        LOG(Compositing, "\nUpdate %d of %s. Overlap testing is %s\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame->tree()->uniqueName().string().utf8().data(),
+            m_compositingConsultsOverlap ? "on" : "off");
+    }
+#endif        
+
     if (needHierarchyUpdate) {
         // Update the hierarchy of the compositing layers.
         Vector<GraphicsLayer*> childList;
@@ -393,11 +423,13 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
         updateLayerTreeGeometry(updateRoot);
     }
     
-#if PROFILE_LAYER_REBUILD
-    double endTime = WTF::currentTime();
-    if (isFullUpdate)
-        fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n",
-                    m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
+#if !LOG_DISABLED
+    if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+        double endTime = currentTime();
+        LOG(Compositing, "%d layers (%d primary, %d secondary), total backing area %.2fMP, update took %.2fms, \n",
+            m_obligateCompositedLayerCount + m_secondaryCompositedLayerCount, m_obligateCompositedLayerCount,
+            m_secondaryCompositedLayerCount, m_backingAreaMegaPixels, 1000.0 * (endTime - startTime));
+    }
 #endif
     ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
 
@@ -405,6 +437,27 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
         enableCompositingMode(false);
 }
 
+#if !LOG_DISABLED
+void RenderLayerCompositor::logLayerInfo(const RenderLayer* layer)
+{
+    if (!compositingLogEnabled())
+        return;
+        
+    if (requiresCompositingLayer(layer) || layer->isRootLayer())
+        ++m_obligateCompositedLayerCount;
+    else
+        ++m_secondaryCompositedLayerCount;
+
+    RenderLayerBacking* backing = layer->backing();
+    
+    m_backingAreaMegaPixels += backing->backingStoreArea() / PIXELS_PER_MEGAPIXEL;
+
+    LOG(Compositing, "  Layer %p %dx%d %.3fMP (%s) %s\n", layer, backing->compositedBounds().width(), backing->compositedBounds().height(),
+        backing->backingStoreArea() / PIXELS_PER_MEGAPIXEL,
+        reasonForCompositing(layer), layer->backing()->nameForLayer().utf8().data());
+}
+#endif
+
 bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
 {
     bool layerChanged = false;
@@ -859,6 +912,10 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vect
 
         if (!layer->parent())
             updateRootLayerPosition();
+
+#if !LOG_DISABLED
+        logLayerInfo(layer);
+#endif
     }
 
     // If this layer has backing, then we are collecting its children, otherwise appending
@@ -1042,6 +1099,10 @@ void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
 
         if (!layer->parent())
             updateRootLayerPosition();
+
+#if !LOG_DISABLED
+        logLayerInfo(layer);
+#endif
     }
 
 #if !ASSERT_DISABLED
@@ -1371,6 +1432,56 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, co
         || layer->mustOverlapCompositedLayers();
 }
 
+#if !LOG_DISABLED
+const char* RenderLayerCompositor::reasonForCompositing(const RenderLayer* layer)
+{
+    RenderObject* renderer = layer->renderer();
+    if (layer->isReflection()) {
+        renderer = renderer->parent();
+        layer = toRenderBoxModelObject(renderer)->layer();
+    }
+
+    if (requiresCompositingForTransform(renderer))
+        return "transform";
+
+    if (requiresCompositingForVideo(renderer))
+        return "video";
+
+    if (requiresCompositingForCanvas(renderer))
+        return "canvas";
+
+    if (requiresCompositingForPlugin(renderer))
+        return "plugin";
+
+    if (requiresCompositingForFrame(renderer))
+        return "iframe";
+    
+    if ((canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden))
+        return "backface-visibility: hidden";
+
+    if (clipsCompositingDescendants(layer))
+        return "clips compositing descendants";
+
+    if (requiresCompositingForAnimation(renderer))
+        return "animation";
+
+    if (requiresCompositingForFilters(renderer))
+        return "filters";
+
+    if (requiresCompositingForPosition(renderer, layer))
+        return "position: fixed";
+
+    // This includes layers made composited by requiresCompositingWhenDescendantsAreCompositing().
+    if (layer->mustOverlapCompositedLayers())
+        return "overlap/stacking";
+
+    if (inCompositingMode() && layer->isRootLayer())
+        return "root";
+
+    return "";
+}
+#endif
+
 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
 // up to the enclosing compositing ancestor. This is required because compositing layers are parented
 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
index 7334c96..0b3ed72 100644 (file)
@@ -32,8 +32,6 @@
 
 namespace WebCore {
 
-#define PROFILE_LAYER_REBUILD 0
-
 class GraphicsLayer;
 class RenderEmbeddedObject;
 class RenderPart;
@@ -302,6 +300,11 @@ private:
     bool requiresContentShadowLayer() const;
 #endif
 
+#if !LOG_DISABLED
+    const char* reasonForCompositing(const RenderLayer*);
+    void logLayerInfo(const RenderLayer*);
+#endif
+
 private:
     RenderView* m_renderView;
     OwnPtr<GraphicsLayer> m_rootContentLayer;
@@ -342,8 +345,12 @@ private:
     OwnPtr<GraphicsLayer> m_layerForOverhangAreas;
     OwnPtr<GraphicsLayer> m_contentShadowLayer;
 #endif
-#if PROFILE_LAYER_REBUILD
+
+#if !LOG_DISABLED
     int m_rootLayerUpdateCount;
+    int m_obligateCompositedLayerCount; // count of layer that have to be composited.
+    int m_secondaryCompositedLayerCount; // count of layers that have to be composited because of stacking or overlap.
+    double m_backingAreaMegaPixels;
 #endif
 };