Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 
     28 #include "platform/graphics/GraphicsLayer.h"
     29 
     30 #include "SkImageFilter.h"
     31 #include "SkMatrix44.h"
     32 #include "platform/geometry/FloatRect.h"
     33 #include "platform/geometry/LayoutRect.h"
     34 #include "platform/graphics/GraphicsLayerFactory.h"
     35 #include "platform/graphics/Image.h"
     36 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
     37 #include "platform/graphics/skia/NativeImageSkia.h"
     38 #include "platform/scroll/ScrollableArea.h"
     39 #include "platform/text/TextStream.h"
     40 #include "public/platform/Platform.h"
     41 #include "public/platform/WebAnimation.h"
     42 #include "public/platform/WebCompositorSupport.h"
     43 #include "public/platform/WebFilterOperations.h"
     44 #include "public/platform/WebFloatPoint.h"
     45 #include "public/platform/WebFloatRect.h"
     46 #include "public/platform/WebGraphicsLayerDebugInfo.h"
     47 #include "public/platform/WebLayer.h"
     48 #include "public/platform/WebPoint.h"
     49 #include "public/platform/WebSize.h"
     50 #include "wtf/CurrentTime.h"
     51 #include "wtf/HashMap.h"
     52 #include "wtf/HashSet.h"
     53 #include "wtf/text/WTFString.h"
     54 
     55 #include <algorithm>
     56 
     57 #ifndef NDEBUG
     58 #include <stdio.h>
     59 #endif
     60 
     61 using blink::Platform;
     62 using blink::WebAnimation;
     63 using blink::WebFilterOperations;
     64 using blink::WebLayer;
     65 using blink::WebPoint;
     66 
     67 namespace WebCore {
     68 
     69 typedef HashMap<const GraphicsLayer*, Vector<FloatRect> > RepaintMap;
     70 static RepaintMap& repaintRectMap()
     71 {
     72     DEFINE_STATIC_LOCAL(RepaintMap, map, ());
     73     return map;
     74 }
     75 
     76 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
     77 {
     78     return factory->createGraphicsLayer(client);
     79 }
     80 
     81 GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
     82     : m_client(client)
     83     , m_backgroundColor(Color::transparent)
     84     , m_opacity(1)
     85     , m_blendMode(blink::WebBlendModeNormal)
     86     , m_hasTransformOrigin(false)
     87     , m_contentsOpaque(false)
     88     , m_shouldFlattenTransform(true)
     89     , m_backfaceVisibility(true)
     90     , m_masksToBounds(false)
     91     , m_drawsContent(false)
     92     , m_contentsVisible(true)
     93     , m_isRootForIsolatedGroup(false)
     94     , m_hasScrollParent(false)
     95     , m_hasClipParent(false)
     96     , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
     97     , m_parent(0)
     98     , m_maskLayer(0)
     99     , m_contentsClippingMaskLayer(0)
    100     , m_replicaLayer(0)
    101     , m_replicatedLayer(0)
    102     , m_paintCount(0)
    103     , m_contentsLayer(0)
    104     , m_contentsLayerId(0)
    105     , m_scrollableArea(0)
    106     , m_3dRenderingContext(0)
    107 {
    108 #ifndef NDEBUG
    109     if (m_client)
    110         m_client->verifyNotPainting();
    111 #endif
    112 
    113     m_opaqueRectTrackingContentLayerDelegate = adoptPtr(new OpaqueRectTrackingContentLayerDelegate(this));
    114     m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get()));
    115     m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
    116     m_layer->layer()->setWebLayerClient(this);
    117     m_layer->setAutomaticallyComputeRasterScale(true);
    118 }
    119 
    120 GraphicsLayer::~GraphicsLayer()
    121 {
    122     for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    123         m_linkHighlights[i]->clearCurrentGraphicsLayer();
    124     m_linkHighlights.clear();
    125 
    126 #ifndef NDEBUG
    127     if (m_client)
    128         m_client->verifyNotPainting();
    129 #endif
    130 
    131     if (m_replicaLayer)
    132         m_replicaLayer->setReplicatedLayer(0);
    133 
    134     if (m_replicatedLayer)
    135         m_replicatedLayer->setReplicatedByLayer(0);
    136 
    137     removeAllChildren();
    138     removeFromParent();
    139 
    140     resetTrackedRepaints();
    141     ASSERT(!m_parent);
    142 }
    143 
    144 void GraphicsLayer::setParent(GraphicsLayer* layer)
    145 {
    146     ASSERT(!layer || !layer->hasAncestor(this));
    147     m_parent = layer;
    148 }
    149 
    150 #if ASSERT_ENABLED
    151 
    152 bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
    153 {
    154     for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
    155         if (curr == ancestor)
    156             return true;
    157     }
    158 
    159     return false;
    160 }
    161 
    162 #endif
    163 
    164 bool GraphicsLayer::setChildren(const GraphicsLayerVector& newChildren)
    165 {
    166     // If the contents of the arrays are the same, nothing to do.
    167     if (newChildren == m_children)
    168         return false;
    169 
    170     removeAllChildren();
    171 
    172     size_t listSize = newChildren.size();
    173     for (size_t i = 0; i < listSize; ++i)
    174         addChildInternal(newChildren[i]);
    175 
    176     updateChildList();
    177 
    178     return true;
    179 }
    180 
    181 void GraphicsLayer::addChildInternal(GraphicsLayer* childLayer)
    182 {
    183     ASSERT(childLayer != this);
    184 
    185     if (childLayer->parent())
    186         childLayer->removeFromParent();
    187 
    188     childLayer->setParent(this);
    189     m_children.append(childLayer);
    190 
    191     // Don't call updateChildList here, this function is used in cases where it
    192     // should not be called until all children are processed.
    193 }
    194 
    195 void GraphicsLayer::addChild(GraphicsLayer* childLayer)
    196 {
    197     addChildInternal(childLayer);
    198     updateChildList();
    199 }
    200 
    201 void GraphicsLayer::addChildAtIndex(GraphicsLayer* childLayer, int index)
    202 {
    203     ASSERT(childLayer != this);
    204 
    205     if (childLayer->parent())
    206         childLayer->removeFromParent();
    207 
    208     childLayer->setParent(this);
    209     m_children.insert(index, childLayer);
    210 
    211     updateChildList();
    212 }
    213 
    214 void GraphicsLayer::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    215 {
    216     ASSERT(childLayer != this);
    217     childLayer->removeFromParent();
    218 
    219     bool found = false;
    220     for (unsigned i = 0; i < m_children.size(); i++) {
    221         if (sibling == m_children[i]) {
    222             m_children.insert(i, childLayer);
    223             found = true;
    224             break;
    225         }
    226     }
    227 
    228     childLayer->setParent(this);
    229 
    230     if (!found)
    231         m_children.append(childLayer);
    232 
    233     updateChildList();
    234 }
    235 
    236 void GraphicsLayer::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
    237 {
    238     childLayer->removeFromParent();
    239     ASSERT(childLayer != this);
    240 
    241     bool found = false;
    242     for (unsigned i = 0; i < m_children.size(); i++) {
    243         if (sibling == m_children[i]) {
    244             m_children.insert(i+1, childLayer);
    245             found = true;
    246             break;
    247         }
    248     }
    249 
    250     childLayer->setParent(this);
    251 
    252     if (!found)
    253         m_children.append(childLayer);
    254 
    255     updateChildList();
    256 }
    257 
    258 bool GraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
    259 {
    260     ASSERT(!newChild->parent());
    261     bool found = false;
    262     for (unsigned i = 0; i < m_children.size(); i++) {
    263         if (oldChild == m_children[i]) {
    264             m_children[i] = newChild;
    265             found = true;
    266             break;
    267         }
    268     }
    269 
    270     if (found) {
    271         oldChild->setParent(0);
    272 
    273         newChild->removeFromParent();
    274         newChild->setParent(this);
    275 
    276         updateChildList();
    277         return true;
    278     }
    279 
    280     return false;
    281 }
    282 
    283 void GraphicsLayer::removeAllChildren()
    284 {
    285     while (!m_children.isEmpty()) {
    286         GraphicsLayer* curLayer = m_children.last();
    287         ASSERT(curLayer->parent());
    288         curLayer->removeFromParent();
    289     }
    290 }
    291 
    292 void GraphicsLayer::removeFromParent()
    293 {
    294     if (m_parent) {
    295         // We use reverseFind so that removeAllChildren() isn't n^2.
    296         m_parent->m_children.remove(m_parent->m_children.reverseFind(this));
    297         setParent(0);
    298     }
    299 
    300     platformLayer()->removeFromParent();
    301 }
    302 
    303 void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
    304 {
    305     // FIXME: this could probably be a full early exit.
    306     if (m_replicaLayer != layer) {
    307         if (m_replicaLayer)
    308             m_replicaLayer->setReplicatedLayer(0);
    309 
    310         if (layer)
    311             layer->setReplicatedLayer(this);
    312 
    313         m_replicaLayer = layer;
    314     }
    315 
    316     WebLayer* webReplicaLayer = layer ? layer->platformLayer() : 0;
    317     platformLayer()->setReplicaLayer(webReplicaLayer);
    318 }
    319 
    320 void GraphicsLayer::setOffsetFromRenderer(const IntSize& offset, ShouldSetNeedsDisplay shouldSetNeedsDisplay)
    321 {
    322     if (offset == m_offsetFromRenderer)
    323         return;
    324 
    325     m_offsetFromRenderer = offset;
    326 
    327     // If the compositing layer offset changes, we need to repaint.
    328     if (shouldSetNeedsDisplay == SetNeedsDisplay)
    329         setNeedsDisplay();
    330 }
    331 
    332 void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const IntRect& clip)
    333 {
    334     if (!m_client)
    335         return;
    336     incrementPaintCount();
    337     m_client->paintContents(this, context, m_paintingPhase, clip);
    338 }
    339 
    340 void GraphicsLayer::updateChildList()
    341 {
    342     WebLayer* childHost = m_layer->layer();
    343     childHost->removeAllChildren();
    344 
    345     clearContentsLayerIfUnregistered();
    346 
    347     if (m_contentsLayer) {
    348         // FIXME: add the contents layer in the correct order with negative z-order children.
    349         // This does not cause visible rendering issues because currently contents layers are only used
    350         // for replaced elements that don't have children.
    351         childHost->addChild(m_contentsLayer);
    352     }
    353 
    354     for (size_t i = 0; i < m_children.size(); ++i)
    355         childHost->addChild(m_children[i]->platformLayer());
    356 
    357     for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    358         childHost->addChild(m_linkHighlights[i]->layer());
    359 }
    360 
    361 void GraphicsLayer::updateLayerIsDrawable()
    362 {
    363     // For the rest of the accelerated compositor code, there is no reason to make a
    364     // distinction between drawsContent and contentsVisible. So, for m_layer->layer(), these two
    365     // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
    366     // so it is only given contentsVisible.
    367 
    368     m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
    369     if (WebLayer* contentsLayer = contentsLayerIfRegistered())
    370         contentsLayer->setDrawsContent(m_contentsVisible);
    371 
    372     if (m_drawsContent) {
    373         m_layer->layer()->invalidate();
    374         for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    375             m_linkHighlights[i]->invalidate();
    376     }
    377 }
    378 
    379 void GraphicsLayer::updateContentsRect()
    380 {
    381     WebLayer* contentsLayer = contentsLayerIfRegistered();
    382     if (!contentsLayer)
    383         return;
    384 
    385     contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
    386     contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
    387 
    388     if (m_contentsClippingMaskLayer) {
    389         if (m_contentsClippingMaskLayer->size() != m_contentsRect.size()) {
    390             m_contentsClippingMaskLayer->setSize(m_contentsRect.size());
    391             m_contentsClippingMaskLayer->setNeedsDisplay();
    392         }
    393         m_contentsClippingMaskLayer->setPosition(FloatPoint());
    394         m_contentsClippingMaskLayer->setOffsetFromRenderer(offsetFromRenderer() + IntSize(m_contentsRect.location().x(), m_contentsRect.location().y()));
    395     }
    396 }
    397 
    398 static HashSet<int>* s_registeredLayerSet;
    399 
    400 void GraphicsLayer::registerContentsLayer(WebLayer* layer)
    401 {
    402     if (!s_registeredLayerSet)
    403         s_registeredLayerSet = new HashSet<int>;
    404     if (s_registeredLayerSet->contains(layer->id()))
    405         CRASH();
    406     s_registeredLayerSet->add(layer->id());
    407 }
    408 
    409 void GraphicsLayer::unregisterContentsLayer(WebLayer* layer)
    410 {
    411     ASSERT(s_registeredLayerSet);
    412     if (!s_registeredLayerSet->contains(layer->id()))
    413         CRASH();
    414     s_registeredLayerSet->remove(layer->id());
    415 }
    416 
    417 void GraphicsLayer::setContentsTo(WebLayer* layer)
    418 {
    419     bool childrenChanged = false;
    420     if (layer) {
    421         ASSERT(s_registeredLayerSet);
    422         if (!s_registeredLayerSet->contains(layer->id()))
    423             CRASH();
    424         if (m_contentsLayerId != layer->id()) {
    425             setupContentsLayer(layer);
    426             childrenChanged = true;
    427         }
    428         updateContentsRect();
    429     } else {
    430         if (m_contentsLayer) {
    431             childrenChanged = true;
    432 
    433             // The old contents layer will be removed via updateChildList.
    434             m_contentsLayer = 0;
    435             m_contentsLayerId = 0;
    436         }
    437     }
    438 
    439     if (childrenChanged)
    440         updateChildList();
    441 }
    442 
    443 void GraphicsLayer::setupContentsLayer(WebLayer* contentsLayer)
    444 {
    445     ASSERT(contentsLayer);
    446     m_contentsLayer = contentsLayer;
    447     m_contentsLayerId = m_contentsLayer->id();
    448 
    449     m_contentsLayer->setWebLayerClient(this);
    450     m_contentsLayer->setTransformOrigin(FloatPoint3D());
    451     m_contentsLayer->setUseParentBackfaceVisibility(true);
    452 
    453     // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
    454     // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
    455     m_contentsLayer->setDrawsContent(m_contentsVisible);
    456 
    457     // Insert the content layer first. Video elements require this, because they have
    458     // shadow content that must display in front of the video.
    459     m_layer->layer()->insertChild(m_contentsLayer, 0);
    460     WebLayer* borderWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
    461     m_contentsLayer->setMaskLayer(borderWebLayer);
    462 
    463     m_contentsLayer->setRenderingContext(m_3dRenderingContext);
    464 }
    465 
    466 void GraphicsLayer::clearContentsLayerIfUnregistered()
    467 {
    468     if (!m_contentsLayerId || s_registeredLayerSet->contains(m_contentsLayerId))
    469         return;
    470 
    471     m_contentsLayer = 0;
    472     m_contentsLayerId = 0;
    473 }
    474 
    475 GraphicsLayerDebugInfo& GraphicsLayer::debugInfo()
    476 {
    477     return m_debugInfo;
    478 }
    479 
    480 blink::WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer)
    481 {
    482     GraphicsLayerDebugInfo* clone = m_debugInfo.clone();
    483     clone->setDebugName(debugName(layer));
    484     return clone;
    485 }
    486 
    487 WebLayer* GraphicsLayer::contentsLayerIfRegistered()
    488 {
    489     clearContentsLayerIfUnregistered();
    490     return m_contentsLayer;
    491 }
    492 
    493 void GraphicsLayer::resetTrackedRepaints()
    494 {
    495     repaintRectMap().remove(this);
    496 }
    497 
    498 void GraphicsLayer::addRepaintRect(const FloatRect& repaintRect)
    499 {
    500     if (m_client->isTrackingRepaints()) {
    501         FloatRect largestRepaintRect(FloatPoint(), m_size);
    502         largestRepaintRect.intersect(repaintRect);
    503         RepaintMap::iterator repaintIt = repaintRectMap().find(this);
    504         if (repaintIt == repaintRectMap().end()) {
    505             Vector<FloatRect> repaintRects;
    506             repaintRects.append(largestRepaintRect);
    507             repaintRectMap().set(this, repaintRects);
    508         } else {
    509             Vector<FloatRect>& repaintRects = repaintIt->value;
    510             repaintRects.append(largestRepaintRect);
    511         }
    512     }
    513 }
    514 
    515 void GraphicsLayer::collectTrackedRepaintRects(Vector<FloatRect>& rects) const
    516 {
    517     if (!m_client->isTrackingRepaints())
    518         return;
    519 
    520     RepaintMap::iterator repaintIt = repaintRectMap().find(this);
    521     if (repaintIt != repaintRectMap().end())
    522         rects.appendVector(repaintIt->value);
    523 }
    524 
    525 void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
    526 {
    527     writeIndent(ts, indent);
    528     ts << "(" << "GraphicsLayer";
    529 
    530     if (flags & LayerTreeIncludesDebugInfo) {
    531         ts << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this));
    532         ts << " \"" << m_client->debugName(this) << "\"";
    533     }
    534 
    535     ts << "\n";
    536     dumpProperties(ts, indent, flags, renderingContextMap);
    537     writeIndent(ts, indent);
    538     ts << ")\n";
    539 }
    540 
    541 static bool compareFloatRects(const FloatRect& a, const FloatRect& b)
    542 {
    543     if (a.x() != b.x())
    544         return a.x() > b.x();
    545     if (a.y() != b.y())
    546         return a.y() > b.y();
    547     if (a.width() != b.width())
    548         return a.width() > b.width();
    549     return a.height() > b.height();
    550 }
    551 
    552 void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
    553 {
    554     if (m_position != FloatPoint()) {
    555         writeIndent(ts, indent + 1);
    556         ts << "(position " << m_position.x() << " " << m_position.y() << ")\n";
    557     }
    558 
    559     if (m_boundsOrigin != FloatPoint()) {
    560         writeIndent(ts, indent + 1);
    561         ts << "(bounds origin " << m_boundsOrigin.x() << " " << m_boundsOrigin.y() << ")\n";
    562     }
    563 
    564     if (m_hasTransformOrigin && m_transformOrigin != FloatPoint3D(m_size.width() * 0.5f, m_size.height() * 0.5f, 0)) {
    565         writeIndent(ts, indent + 1);
    566         ts << "(transformOrigin " << m_transformOrigin.x() << " " << m_transformOrigin.y() << ")\n";
    567     }
    568 
    569     if (m_size != IntSize()) {
    570         writeIndent(ts, indent + 1);
    571         ts << "(bounds " << m_size.width() << " " << m_size.height() << ")\n";
    572     }
    573 
    574     if (m_opacity != 1) {
    575         writeIndent(ts, indent + 1);
    576         ts << "(opacity " << m_opacity << ")\n";
    577     }
    578 
    579     if (m_blendMode != blink::WebBlendModeNormal) {
    580         writeIndent(ts, indent + 1);
    581         ts << "(blendMode " << compositeOperatorName(CompositeSourceOver, m_blendMode) << ")\n";
    582     }
    583 
    584     if (m_isRootForIsolatedGroup) {
    585         writeIndent(ts, indent + 1);
    586         ts << "(isolate " << m_isRootForIsolatedGroup << ")\n";
    587     }
    588 
    589     if (m_contentsOpaque) {
    590         writeIndent(ts, indent + 1);
    591         ts << "(contentsOpaque " << m_contentsOpaque << ")\n";
    592     }
    593 
    594     if (!m_shouldFlattenTransform) {
    595         writeIndent(ts, indent + 1);
    596         ts << "(shouldFlattenTransform " << m_shouldFlattenTransform << ")\n";
    597     }
    598 
    599     if (m_3dRenderingContext) {
    600         RenderingContextMap::const_iterator it = renderingContextMap.find(m_3dRenderingContext);
    601         int contextId = renderingContextMap.size() + 1;
    602         if (it == renderingContextMap.end())
    603             renderingContextMap.set(m_3dRenderingContext, contextId);
    604         else
    605             contextId = it->value;
    606 
    607         writeIndent(ts, indent + 1);
    608         ts << "(3dRenderingContext " << contextId << ")\n";
    609     }
    610 
    611     if (m_drawsContent) {
    612         writeIndent(ts, indent + 1);
    613         ts << "(drawsContent " << m_drawsContent << ")\n";
    614     }
    615 
    616     if (!m_contentsVisible) {
    617         writeIndent(ts, indent + 1);
    618         ts << "(contentsVisible " << m_contentsVisible << ")\n";
    619     }
    620 
    621     if (!m_backfaceVisibility) {
    622         writeIndent(ts, indent + 1);
    623         ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n";
    624     }
    625 
    626     if (flags & LayerTreeIncludesDebugInfo) {
    627         writeIndent(ts, indent + 1);
    628         ts << "(";
    629         if (m_client)
    630             ts << "client " << static_cast<void*>(m_client);
    631         else
    632             ts << "no client";
    633         ts << ")\n";
    634     }
    635 
    636     if (m_backgroundColor.alpha()) {
    637         writeIndent(ts, indent + 1);
    638         ts << "(backgroundColor " << m_backgroundColor.nameForRenderTreeAsText() << ")\n";
    639     }
    640 
    641     if (!m_transform.isIdentity()) {
    642         writeIndent(ts, indent + 1);
    643         ts << "(transform ";
    644         ts << "[" << m_transform.m11() << " " << m_transform.m12() << " " << m_transform.m13() << " " << m_transform.m14() << "] ";
    645         ts << "[" << m_transform.m21() << " " << m_transform.m22() << " " << m_transform.m23() << " " << m_transform.m24() << "] ";
    646         ts << "[" << m_transform.m31() << " " << m_transform.m32() << " " << m_transform.m33() << " " << m_transform.m34() << "] ";
    647         ts << "[" << m_transform.m41() << " " << m_transform.m42() << " " << m_transform.m43() << " " << m_transform.m44() << "])\n";
    648     }
    649 
    650     if (m_replicaLayer) {
    651         writeIndent(ts, indent + 1);
    652         ts << "(replica layer";
    653         if (flags & LayerTreeIncludesDebugInfo)
    654             ts << " " << m_replicaLayer;
    655         ts << ")\n";
    656         m_replicaLayer->dumpLayer(ts, indent + 2, flags, renderingContextMap);
    657     }
    658 
    659     if (m_replicatedLayer) {
    660         writeIndent(ts, indent + 1);
    661         ts << "(replicated layer";
    662         if (flags & LayerTreeIncludesDebugInfo)
    663             ts << " " << m_replicatedLayer;
    664         ts << ")\n";
    665     }
    666 
    667     if ((flags & LayerTreeIncludesRepaintRects) && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty()) {
    668         Vector<FloatRect> repaintRectsCopy = repaintRectMap().get(this);
    669         std::sort(repaintRectsCopy.begin(), repaintRectsCopy.end(), &compareFloatRects);
    670         writeIndent(ts, indent + 1);
    671         ts << "(repaint rects\n";
    672         for (size_t i = 0; i < repaintRectsCopy.size(); ++i) {
    673             if (repaintRectsCopy[i].isEmpty())
    674                 continue;
    675             writeIndent(ts, indent + 2);
    676             ts << "(rect ";
    677             ts << repaintRectsCopy[i].x() << " ";
    678             ts << repaintRectsCopy[i].y() << " ";
    679             ts << repaintRectsCopy[i].width() << " ";
    680             ts << repaintRectsCopy[i].height();
    681             ts << ")\n";
    682         }
    683         writeIndent(ts, indent + 1);
    684         ts << ")\n";
    685     }
    686 
    687     if ((flags & LayerTreeIncludesPaintingPhases) && m_paintingPhase) {
    688         writeIndent(ts, indent + 1);
    689         ts << "(paintingPhases\n";
    690         if (m_paintingPhase & GraphicsLayerPaintBackground) {
    691             writeIndent(ts, indent + 2);
    692             ts << "GraphicsLayerPaintBackground\n";
    693         }
    694         if (m_paintingPhase & GraphicsLayerPaintForeground) {
    695             writeIndent(ts, indent + 2);
    696             ts << "GraphicsLayerPaintForeground\n";
    697         }
    698         if (m_paintingPhase & GraphicsLayerPaintMask) {
    699             writeIndent(ts, indent + 2);
    700             ts << "GraphicsLayerPaintMask\n";
    701         }
    702         if (m_paintingPhase & GraphicsLayerPaintChildClippingMask) {
    703             writeIndent(ts, indent + 2);
    704             ts << "GraphicsLayerPaintChildClippingMask\n";
    705         }
    706         if (m_paintingPhase & GraphicsLayerPaintOverflowContents) {
    707             writeIndent(ts, indent + 2);
    708             ts << "GraphicsLayerPaintOverflowContents\n";
    709         }
    710         if (m_paintingPhase & GraphicsLayerPaintCompositedScroll) {
    711             writeIndent(ts, indent + 2);
    712             ts << "GraphicsLayerPaintCompositedScroll\n";
    713         }
    714         writeIndent(ts, indent + 1);
    715         ts << ")\n";
    716     }
    717 
    718     if (flags & LayerTreeIncludesClipAndScrollParents) {
    719         if (m_hasScrollParent) {
    720             writeIndent(ts, indent + 1);
    721             ts << "(hasScrollParent 1)\n";
    722         }
    723         if (m_hasClipParent) {
    724             writeIndent(ts, indent + 1);
    725             ts << "(hasClipParent 1)\n";
    726         }
    727     }
    728 
    729     if (flags & LayerTreeIncludesDebugInfo) {
    730         writeIndent(ts, indent + 1);
    731         ts << "(compositingReasons\n";
    732         for (size_t i = 0; i < WTF_ARRAY_LENGTH(compositingReasonStringMap); ++i) {
    733             if (m_debugInfo.compositingReasons() & compositingReasonStringMap[i].reason) {
    734                 writeIndent(ts, indent + 2);
    735                 ts << compositingReasonStringMap[i].description << "\n";
    736             }
    737         }
    738         writeIndent(ts, indent + 1);
    739         ts << ")\n";
    740     }
    741 
    742     if (m_children.size()) {
    743         writeIndent(ts, indent + 1);
    744         ts << "(children " << m_children.size() << "\n";
    745 
    746         unsigned i;
    747         for (i = 0; i < m_children.size(); i++)
    748             m_children[i]->dumpLayer(ts, indent + 2, flags, renderingContextMap);
    749         writeIndent(ts, indent + 1);
    750         ts << ")\n";
    751     }
    752 }
    753 
    754 String GraphicsLayer::layerTreeAsText(LayerTreeFlags flags) const
    755 {
    756     TextStream ts;
    757 
    758     RenderingContextMap renderingContextMap;
    759     dumpLayer(ts, 0, flags, renderingContextMap);
    760     return ts.release();
    761 }
    762 
    763 String GraphicsLayer::debugName(blink::WebLayer* webLayer) const
    764 {
    765     String name;
    766     if (!m_client)
    767         return name;
    768 
    769     String highlightDebugName;
    770     for (size_t i = 0; i < m_linkHighlights.size(); ++i) {
    771         if (webLayer == m_linkHighlights[i]->layer()) {
    772             highlightDebugName = "LinkHighlight[" + String::number(i) + "] for " + m_client->debugName(this);
    773             break;
    774         }
    775     }
    776 
    777     if (webLayer == m_contentsLayer) {
    778         name = "ContentsLayer for " + m_client->debugName(this);
    779     } else if (!highlightDebugName.isEmpty()) {
    780         name = highlightDebugName;
    781     } else if (webLayer == m_layer->layer()) {
    782         name = m_client->debugName(this);
    783     } else {
    784         ASSERT_NOT_REACHED();
    785     }
    786     return name;
    787 }
    788 
    789 void GraphicsLayer::setCompositingReasons(CompositingReasons reasons)
    790 {
    791     m_debugInfo.setCompositingReasons(reasons);
    792 }
    793 
    794 void GraphicsLayer::setOwnerNodeId(int nodeId)
    795 {
    796     m_debugInfo.setOwnerNodeId(nodeId);
    797 }
    798 
    799 void GraphicsLayer::setPosition(const FloatPoint& point)
    800 {
    801     m_position = point;
    802     platformLayer()->setPosition(m_position);
    803 }
    804 
    805 void GraphicsLayer::setSize(const FloatSize& size)
    806 {
    807     // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
    808     // avoid those assertions.
    809     // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
    810     FloatSize clampedSize = size;
    811     if (clampedSize.width() < 0 || clampedSize.height() < 0)
    812         clampedSize = FloatSize();
    813 
    814     if (clampedSize == m_size)
    815         return;
    816 
    817     m_size = clampedSize;
    818 
    819     m_layer->layer()->setBounds(flooredIntSize(m_size));
    820     // Note that we don't resize m_contentsLayer. It's up the caller to do that.
    821 }
    822 
    823 void GraphicsLayer::setTransform(const TransformationMatrix& transform)
    824 {
    825     m_transform = transform;
    826     platformLayer()->setTransform(TransformationMatrix::toSkMatrix44(m_transform));
    827 }
    828 
    829 void GraphicsLayer::setTransformOrigin(const FloatPoint3D& transformOrigin)
    830 {
    831     m_hasTransformOrigin = true;
    832     m_transformOrigin = transformOrigin;
    833     platformLayer()->setTransformOrigin(transformOrigin);
    834 }
    835 
    836 void GraphicsLayer::setShouldFlattenTransform(bool shouldFlatten)
    837 {
    838     if (shouldFlatten == m_shouldFlattenTransform)
    839         return;
    840 
    841     m_shouldFlattenTransform = shouldFlatten;
    842 
    843     m_layer->layer()->setShouldFlattenTransform(shouldFlatten);
    844 }
    845 
    846 void GraphicsLayer::setRenderingContext(int context)
    847 {
    848     if (m_3dRenderingContext == context)
    849         return;
    850 
    851     m_3dRenderingContext = context;
    852     m_layer->layer()->setRenderingContext(context);
    853 
    854     if (m_contentsLayer)
    855         m_contentsLayer->setRenderingContext(m_3dRenderingContext);
    856 }
    857 
    858 void GraphicsLayer::setMasksToBounds(bool masksToBounds)
    859 {
    860     m_masksToBounds = masksToBounds;
    861     m_layer->layer()->setMasksToBounds(m_masksToBounds);
    862 }
    863 
    864 void GraphicsLayer::setDrawsContent(bool drawsContent)
    865 {
    866     // Note carefully this early-exit is only correct because we also properly call
    867     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
    868     if (drawsContent == m_drawsContent)
    869         return;
    870 
    871     m_drawsContent = drawsContent;
    872     updateLayerIsDrawable();
    873 }
    874 
    875 void GraphicsLayer::setContentsVisible(bool contentsVisible)
    876 {
    877     // Note carefully this early-exit is only correct because we also properly call
    878     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
    879     if (contentsVisible == m_contentsVisible)
    880         return;
    881 
    882     m_contentsVisible = contentsVisible;
    883     updateLayerIsDrawable();
    884 }
    885 
    886 void GraphicsLayer::setClipParent(blink::WebLayer* parent)
    887 {
    888     m_hasClipParent = !!parent;
    889     m_layer->layer()->setClipParent(parent);
    890 }
    891 
    892 void GraphicsLayer::setScrollParent(blink::WebLayer* parent)
    893 {
    894     m_hasScrollParent = !!parent;
    895     m_layer->layer()->setScrollParent(parent);
    896 }
    897 
    898 void GraphicsLayer::setBackgroundColor(const Color& color)
    899 {
    900     if (color == m_backgroundColor)
    901         return;
    902 
    903     m_backgroundColor = color;
    904     m_layer->layer()->setBackgroundColor(m_backgroundColor.rgb());
    905 }
    906 
    907 void GraphicsLayer::setContentsOpaque(bool opaque)
    908 {
    909     m_contentsOpaque = opaque;
    910     m_layer->layer()->setOpaque(m_contentsOpaque);
    911     m_opaqueRectTrackingContentLayerDelegate->setOpaque(m_contentsOpaque);
    912 }
    913 
    914 void GraphicsLayer::setMaskLayer(GraphicsLayer* maskLayer)
    915 {
    916     if (maskLayer == m_maskLayer)
    917         return;
    918 
    919     m_maskLayer = maskLayer;
    920     WebLayer* maskWebLayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
    921     m_layer->layer()->setMaskLayer(maskWebLayer);
    922 }
    923 
    924 void GraphicsLayer::setContentsClippingMaskLayer(GraphicsLayer* contentsClippingMaskLayer)
    925 {
    926     if (contentsClippingMaskLayer == m_contentsClippingMaskLayer)
    927         return;
    928 
    929     m_contentsClippingMaskLayer = contentsClippingMaskLayer;
    930     WebLayer* contentsLayer = contentsLayerIfRegistered();
    931     if (!contentsLayer)
    932         return;
    933     WebLayer* contentsClippingMaskWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
    934     contentsLayer->setMaskLayer(contentsClippingMaskWebLayer);
    935     updateContentsRect();
    936 }
    937 
    938 void GraphicsLayer::setBackfaceVisibility(bool visible)
    939 {
    940     m_backfaceVisibility = visible;
    941     m_layer->setDoubleSided(m_backfaceVisibility);
    942 }
    943 
    944 void GraphicsLayer::setOpacity(float opacity)
    945 {
    946     float clampedOpacity = std::max(std::min(opacity, 1.0f), 0.0f);
    947     m_opacity = clampedOpacity;
    948     platformLayer()->setOpacity(opacity);
    949 }
    950 
    951 void GraphicsLayer::setBlendMode(blink::WebBlendMode blendMode)
    952 {
    953     if (m_blendMode == blendMode)
    954         return;
    955     m_blendMode = blendMode;
    956     platformLayer()->setBlendMode(blink::WebBlendMode(blendMode));
    957 }
    958 
    959 void GraphicsLayer::setIsRootForIsolatedGroup(bool isolated)
    960 {
    961     if (m_isRootForIsolatedGroup == isolated)
    962         return;
    963     m_isRootForIsolatedGroup = isolated;
    964     platformLayer()->setIsRootForIsolatedGroup(isolated);
    965 }
    966 
    967 void GraphicsLayer::setContentsNeedsDisplay()
    968 {
    969     if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
    970         contentsLayer->invalidate();
    971         addRepaintRect(m_contentsRect);
    972     }
    973 }
    974 
    975 void GraphicsLayer::setNeedsDisplay()
    976 {
    977     if (drawsContent()) {
    978         m_layer->layer()->invalidate();
    979         addRepaintRect(FloatRect(FloatPoint(), m_size));
    980         for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    981             m_linkHighlights[i]->invalidate();
    982     }
    983 }
    984 
    985 void GraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect)
    986 {
    987     if (drawsContent()) {
    988         m_layer->layer()->invalidateRect(rect);
    989         addRepaintRect(rect);
    990         for (size_t i = 0; i < m_linkHighlights.size(); ++i)
    991             m_linkHighlights[i]->invalidate();
    992     }
    993 }
    994 
    995 void GraphicsLayer::setContentsRect(const IntRect& rect)
    996 {
    997     if (rect == m_contentsRect)
    998         return;
    999 
   1000     m_contentsRect = rect;
   1001     updateContentsRect();
   1002 }
   1003 
   1004 void GraphicsLayer::setContentsToImage(Image* image)
   1005 {
   1006     RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
   1007     if (nativeImage) {
   1008         if (!m_imageLayer) {
   1009             m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer());
   1010             registerContentsLayer(m_imageLayer->layer());
   1011         }
   1012         m_imageLayer->setBitmap(nativeImage->bitmap());
   1013         m_imageLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
   1014         updateContentsRect();
   1015     } else {
   1016         if (m_imageLayer) {
   1017             unregisterContentsLayer(m_imageLayer->layer());
   1018             m_imageLayer.clear();
   1019         }
   1020     }
   1021 
   1022     setContentsTo(m_imageLayer ? m_imageLayer->layer() : 0);
   1023 }
   1024 
   1025 void GraphicsLayer::setContentsToNinePatch(Image* image, const IntRect& aperture)
   1026 {
   1027     if (m_ninePatchLayer) {
   1028         unregisterContentsLayer(m_ninePatchLayer->layer());
   1029         m_ninePatchLayer.clear();
   1030     }
   1031     RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
   1032     if (nativeImage) {
   1033         m_ninePatchLayer = adoptPtr(Platform::current()->compositorSupport()->createNinePatchLayer());
   1034         m_ninePatchLayer->setBitmap(nativeImage->bitmap(), aperture);
   1035         m_ninePatchLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
   1036         registerContentsLayer(m_ninePatchLayer->layer());
   1037     }
   1038     setContentsTo(m_ninePatchLayer ? m_ninePatchLayer->layer() : 0);
   1039 }
   1040 
   1041 bool GraphicsLayer::addAnimation(PassOwnPtr<WebAnimation> popAnimation)
   1042 {
   1043     OwnPtr<WebAnimation> animation(popAnimation);
   1044     ASSERT(animation);
   1045     platformLayer()->setAnimationDelegate(this);
   1046 
   1047     // Remove any existing animations with the same animation id and target property.
   1048     platformLayer()->removeAnimation(animation->id(), animation->targetProperty());
   1049     return platformLayer()->addAnimation(animation.leakPtr());
   1050 }
   1051 
   1052 void GraphicsLayer::pauseAnimation(int animationId, double timeOffset)
   1053 {
   1054     platformLayer()->pauseAnimation(animationId, timeOffset);
   1055 }
   1056 
   1057 void GraphicsLayer::removeAnimation(int animationId)
   1058 {
   1059     platformLayer()->removeAnimation(animationId);
   1060 }
   1061 
   1062 WebLayer* GraphicsLayer::platformLayer() const
   1063 {
   1064     return m_layer->layer();
   1065 }
   1066 
   1067 static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperations& filters, WebFilterOperations& webFilters)
   1068 {
   1069     for (size_t i = 0; i < filters.size(); ++i) {
   1070         const FilterOperation& op = *filters.at(i);
   1071         switch (op.type()) {
   1072         case FilterOperation::REFERENCE:
   1073             return false; // Not supported.
   1074         case FilterOperation::GRAYSCALE:
   1075         case FilterOperation::SEPIA:
   1076         case FilterOperation::SATURATE:
   1077         case FilterOperation::HUE_ROTATE: {
   1078             float amount = toBasicColorMatrixFilterOperation(op).amount();
   1079             switch (op.type()) {
   1080             case FilterOperation::GRAYSCALE:
   1081                 webFilters.appendGrayscaleFilter(amount);
   1082                 break;
   1083             case FilterOperation::SEPIA:
   1084                 webFilters.appendSepiaFilter(amount);
   1085                 break;
   1086             case FilterOperation::SATURATE:
   1087                 webFilters.appendSaturateFilter(amount);
   1088                 break;
   1089             case FilterOperation::HUE_ROTATE:
   1090                 webFilters.appendHueRotateFilter(amount);
   1091                 break;
   1092             default:
   1093                 ASSERT_NOT_REACHED();
   1094             }
   1095             break;
   1096         }
   1097         case FilterOperation::INVERT:
   1098         case FilterOperation::OPACITY:
   1099         case FilterOperation::BRIGHTNESS:
   1100         case FilterOperation::CONTRAST: {
   1101             float amount = toBasicComponentTransferFilterOperation(op).amount();
   1102             switch (op.type()) {
   1103             case FilterOperation::INVERT:
   1104                 webFilters.appendInvertFilter(amount);
   1105                 break;
   1106             case FilterOperation::OPACITY:
   1107                 webFilters.appendOpacityFilter(amount);
   1108                 break;
   1109             case FilterOperation::BRIGHTNESS:
   1110                 webFilters.appendBrightnessFilter(amount);
   1111                 break;
   1112             case FilterOperation::CONTRAST:
   1113                 webFilters.appendContrastFilter(amount);
   1114                 break;
   1115             default:
   1116                 ASSERT_NOT_REACHED();
   1117             }
   1118             break;
   1119         }
   1120         case FilterOperation::BLUR: {
   1121             float pixelRadius = toBlurFilterOperation(op).stdDeviation().getFloatValue();
   1122             webFilters.appendBlurFilter(pixelRadius);
   1123             break;
   1124         }
   1125         case FilterOperation::DROP_SHADOW: {
   1126             const DropShadowFilterOperation& dropShadowOp = toDropShadowFilterOperation(op);
   1127             webFilters.appendDropShadowFilter(WebPoint(dropShadowOp.x(), dropShadowOp.y()), dropShadowOp.stdDeviation(), dropShadowOp.color().rgb());
   1128             break;
   1129         }
   1130         case FilterOperation::NONE:
   1131             break;
   1132         }
   1133     }
   1134     return true;
   1135 }
   1136 
   1137 bool GraphicsLayer::setFilters(const FilterOperations& filters)
   1138 {
   1139     SkiaImageFilterBuilder builder;
   1140     OwnPtr<WebFilterOperations> webFilters = adoptPtr(Platform::current()->compositorSupport()->createFilterOperations());
   1141     FilterOutsets outsets = filters.outsets();
   1142     builder.setCropOffset(FloatSize(outsets.left(), outsets.top()));
   1143     if (!builder.buildFilterOperations(filters, webFilters.get())) {
   1144         // Make sure the filters are removed from the platform layer, as they are
   1145         // going to fallback to software mode.
   1146         webFilters->clear();
   1147         m_layer->layer()->setFilters(*webFilters);
   1148         m_filters = FilterOperations();
   1149         return false;
   1150     }
   1151 
   1152     m_layer->layer()->setFilters(*webFilters);
   1153     m_filters = filters;
   1154     return true;
   1155 }
   1156 
   1157 void GraphicsLayer::setBackgroundFilters(const FilterOperations& filters)
   1158 {
   1159     OwnPtr<WebFilterOperations> webFilters = adoptPtr(Platform::current()->compositorSupport()->createFilterOperations());
   1160     if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, *webFilters))
   1161         return;
   1162     m_layer->layer()->setBackgroundFilters(*webFilters);
   1163 }
   1164 
   1165 void GraphicsLayer::setPaintingPhase(GraphicsLayerPaintingPhase phase)
   1166 {
   1167     if (m_paintingPhase == phase)
   1168         return;
   1169     m_paintingPhase = phase;
   1170     setNeedsDisplay();
   1171 }
   1172 
   1173 void GraphicsLayer::addLinkHighlight(LinkHighlightClient* linkHighlight)
   1174 {
   1175     ASSERT(linkHighlight && !m_linkHighlights.contains(linkHighlight));
   1176     m_linkHighlights.append(linkHighlight);
   1177     linkHighlight->layer()->setWebLayerClient(this);
   1178     updateChildList();
   1179 }
   1180 
   1181 void GraphicsLayer::removeLinkHighlight(LinkHighlightClient* linkHighlight)
   1182 {
   1183     m_linkHighlights.remove(m_linkHighlights.find(linkHighlight));
   1184     updateChildList();
   1185 }
   1186 
   1187 void GraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea, bool isMainFrame)
   1188 {
   1189     if (m_scrollableArea == scrollableArea)
   1190         return;
   1191 
   1192     m_scrollableArea = scrollableArea;
   1193 
   1194     // Main frame scrolling may involve pinch zoom and gets routed through
   1195     // WebViewImpl explicitly rather than via GraphicsLayer::didScroll.
   1196     // TODO(bokan): With pinch virtual viewport the special case will no
   1197     // longer be needed, remove once old-style pinch is gone.
   1198     if (isMainFrame)
   1199         m_layer->layer()->setScrollClient(0);
   1200     else
   1201         m_layer->layer()->setScrollClient(this);
   1202 }
   1203 
   1204 void GraphicsLayer::paint(GraphicsContext& context, const IntRect& clip)
   1205 {
   1206     paintGraphicsLayerContents(context, clip);
   1207 }
   1208 
   1209 
   1210 void GraphicsLayer::notifyAnimationStarted(double monotonicTime, WebAnimation::TargetProperty)
   1211 {
   1212     if (m_client)
   1213         m_client->notifyAnimationStarted(this, monotonicTime);
   1214 }
   1215 
   1216 void GraphicsLayer::notifyAnimationFinished(double, WebAnimation::TargetProperty)
   1217 {
   1218     // Do nothing.
   1219 }
   1220 
   1221 void GraphicsLayer::didScroll()
   1222 {
   1223     if (m_scrollableArea)
   1224         m_scrollableArea->scrollToOffsetWithoutAnimation(m_scrollableArea->minimumScrollPosition() + toIntSize(m_layer->layer()->scrollPosition()));
   1225 }
   1226 
   1227 } // namespace WebCore
   1228 
   1229 #ifndef NDEBUG
   1230 void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer)
   1231 {
   1232     if (!layer)
   1233         return;
   1234 
   1235     String output = layer->layerTreeAsText(WebCore::LayerTreeIncludesDebugInfo);
   1236     fprintf(stderr, "%s\n", output.utf8().data());
   1237 }
   1238 #endif
   1239