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/TraceEvent.h"
33#include "platform/geometry/FloatRect.h"
34#include "platform/geometry/LayoutRect.h"
35#include "platform/graphics/FirstPaintInvalidationTracking.h"
36#include "platform/graphics/GraphicsLayerFactory.h"
37#include "platform/graphics/Image.h"
38#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
39#include "platform/graphics/skia/NativeImageSkia.h"
40#include "platform/scroll/ScrollableArea.h"
41#include "platform/text/TextStream.h"
42#include "public/platform/Platform.h"
43#include "public/platform/WebCompositorAnimation.h"
44#include "public/platform/WebCompositorSupport.h"
45#include "public/platform/WebFilterOperations.h"
46#include "public/platform/WebFloatPoint.h"
47#include "public/platform/WebFloatRect.h"
48#include "public/platform/WebGraphicsLayerDebugInfo.h"
49#include "public/platform/WebLayer.h"
50#include "public/platform/WebPoint.h"
51#include "public/platform/WebSize.h"
52#include "wtf/CurrentTime.h"
53#include "wtf/HashMap.h"
54#include "wtf/HashSet.h"
55#include "wtf/text/WTFString.h"
56
57#include <algorithm>
58
59#ifndef NDEBUG
60#include <stdio.h>
61#endif
62
63using blink::Platform;
64using blink::WebCompositorAnimation;
65using blink::WebFilterOperations;
66using blink::WebLayer;
67using blink::WebPoint;
68
69namespace blink {
70
71typedef HashMap<const GraphicsLayer*, Vector<FloatRect> > RepaintMap;
72static RepaintMap& repaintRectMap()
73{
74    DEFINE_STATIC_LOCAL(RepaintMap, map, ());
75    return map;
76}
77
78PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
79{
80    return factory->createGraphicsLayer(client);
81}
82
83GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
84    : m_client(client)
85    , m_backgroundColor(Color::transparent)
86    , m_opacity(1)
87    , m_blendMode(WebBlendModeNormal)
88    , m_hasTransformOrigin(false)
89    , m_contentsOpaque(false)
90    , m_shouldFlattenTransform(true)
91    , m_backfaceVisibility(true)
92    , m_masksToBounds(false)
93    , m_drawsContent(false)
94    , m_contentsVisible(true)
95    , m_isRootForIsolatedGroup(false)
96    , m_hasScrollParent(false)
97    , m_hasClipParent(false)
98    , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
99    , m_parent(0)
100    , m_maskLayer(0)
101    , m_contentsClippingMaskLayer(0)
102    , m_replicaLayer(0)
103    , m_replicatedLayer(0)
104    , m_paintCount(0)
105    , m_contentsLayer(0)
106    , m_contentsLayerId(0)
107    , m_scrollableArea(0)
108    , m_3dRenderingContext(0)
109{
110#if ENABLE(ASSERT)
111    if (m_client)
112        m_client->verifyNotPainting();
113#endif
114
115    m_contentLayerDelegate = adoptPtr(new ContentLayerDelegate(this));
116    m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_contentLayerDelegate.get()));
117    m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
118    m_layer->layer()->setWebLayerClient(this);
119    m_layer->setAutomaticallyComputeRasterScale(true);
120}
121
122GraphicsLayer::~GraphicsLayer()
123{
124    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
125        m_linkHighlights[i]->clearCurrentGraphicsLayer();
126    m_linkHighlights.clear();
127
128#if ENABLE(ASSERT)
129    if (m_client)
130        m_client->verifyNotPainting();
131#endif
132
133    if (m_replicaLayer)
134        m_replicaLayer->setReplicatedLayer(0);
135
136    if (m_replicatedLayer)
137        m_replicatedLayer->setReplicatedByLayer(0);
138
139    removeAllChildren();
140    removeFromParent();
141
142    resetTrackedPaintInvalidations();
143    ASSERT(!m_parent);
144}
145
146void GraphicsLayer::setParent(GraphicsLayer* layer)
147{
148    ASSERT(!layer || !layer->hasAncestor(this));
149    m_parent = layer;
150}
151
152#if ENABLE(ASSERT)
153
154bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
155{
156    for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
157        if (curr == ancestor)
158            return true;
159    }
160
161    return false;
162}
163
164#endif
165
166bool GraphicsLayer::setChildren(const GraphicsLayerVector& newChildren)
167{
168    // If the contents of the arrays are the same, nothing to do.
169    if (newChildren == m_children)
170        return false;
171
172    removeAllChildren();
173
174    size_t listSize = newChildren.size();
175    for (size_t i = 0; i < listSize; ++i)
176        addChildInternal(newChildren[i]);
177
178    updateChildList();
179
180    return true;
181}
182
183void GraphicsLayer::addChildInternal(GraphicsLayer* childLayer)
184{
185    ASSERT(childLayer != this);
186
187    if (childLayer->parent())
188        childLayer->removeFromParent();
189
190    childLayer->setParent(this);
191    m_children.append(childLayer);
192
193    // Don't call updateChildList here, this function is used in cases where it
194    // should not be called until all children are processed.
195}
196
197void GraphicsLayer::addChild(GraphicsLayer* childLayer)
198{
199    addChildInternal(childLayer);
200    updateChildList();
201}
202
203void GraphicsLayer::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
204{
205    ASSERT(childLayer != this);
206    childLayer->removeFromParent();
207
208    bool found = false;
209    for (unsigned i = 0; i < m_children.size(); i++) {
210        if (sibling == m_children[i]) {
211            m_children.insert(i, childLayer);
212            found = true;
213            break;
214        }
215    }
216
217    childLayer->setParent(this);
218
219    if (!found)
220        m_children.append(childLayer);
221
222    updateChildList();
223}
224
225void GraphicsLayer::removeAllChildren()
226{
227    while (!m_children.isEmpty()) {
228        GraphicsLayer* curLayer = m_children.last();
229        ASSERT(curLayer->parent());
230        curLayer->removeFromParent();
231    }
232}
233
234void GraphicsLayer::removeFromParent()
235{
236    if (m_parent) {
237        // We use reverseFind so that removeAllChildren() isn't n^2.
238        m_parent->m_children.remove(m_parent->m_children.reverseFind(this));
239        setParent(0);
240    }
241
242    platformLayer()->removeFromParent();
243}
244
245void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
246{
247    // FIXME: this could probably be a full early exit.
248    if (m_replicaLayer != layer) {
249        if (m_replicaLayer)
250            m_replicaLayer->setReplicatedLayer(0);
251
252        if (layer)
253            layer->setReplicatedLayer(this);
254
255        m_replicaLayer = layer;
256    }
257
258    WebLayer* webReplicaLayer = layer ? layer->platformLayer() : 0;
259    platformLayer()->setReplicaLayer(webReplicaLayer);
260}
261
262void GraphicsLayer::setOffsetFromRenderer(const IntSize& offset, ShouldSetNeedsDisplay shouldSetNeedsDisplay)
263{
264    if (offset == m_offsetFromRenderer)
265        return;
266
267    m_offsetFromRenderer = offset;
268
269    // If the compositing layer offset changes, we need to repaint.
270    if (shouldSetNeedsDisplay == SetNeedsDisplay)
271        setNeedsDisplay();
272}
273
274void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const IntRect& clip)
275{
276    if (!m_client)
277        return;
278    if (firstPaintInvalidationTrackingEnabled())
279        m_debugInfo.clearAnnotatedInvalidateRects();
280    incrementPaintCount();
281    m_client->paintContents(this, context, m_paintingPhase, clip);
282}
283
284void GraphicsLayer::updateChildList()
285{
286    WebLayer* childHost = m_layer->layer();
287    childHost->removeAllChildren();
288
289    clearContentsLayerIfUnregistered();
290
291    if (m_contentsLayer) {
292        // FIXME: add the contents layer in the correct order with negative z-order children.
293        // This does not cause visible rendering issues because currently contents layers are only used
294        // for replaced elements that don't have children.
295        childHost->addChild(m_contentsLayer);
296    }
297
298    for (size_t i = 0; i < m_children.size(); ++i)
299        childHost->addChild(m_children[i]->platformLayer());
300
301    for (size_t i = 0; i < m_linkHighlights.size(); ++i)
302        childHost->addChild(m_linkHighlights[i]->layer());
303}
304
305void GraphicsLayer::updateLayerIsDrawable()
306{
307    // For the rest of the accelerated compositor code, there is no reason to make a
308    // distinction between drawsContent and contentsVisible. So, for m_layer->layer(), these two
309    // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
310    // so it is only given contentsVisible.
311
312    m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
313    if (WebLayer* contentsLayer = contentsLayerIfRegistered())
314        contentsLayer->setDrawsContent(m_contentsVisible);
315
316    if (m_drawsContent) {
317        m_layer->layer()->invalidate();
318        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
319            m_linkHighlights[i]->invalidate();
320    }
321}
322
323void GraphicsLayer::updateContentsRect()
324{
325    WebLayer* contentsLayer = contentsLayerIfRegistered();
326    if (!contentsLayer)
327        return;
328
329    contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
330    contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
331
332    if (m_contentsClippingMaskLayer) {
333        if (m_contentsClippingMaskLayer->size() != m_contentsRect.size()) {
334            m_contentsClippingMaskLayer->setSize(m_contentsRect.size());
335            m_contentsClippingMaskLayer->setNeedsDisplay();
336        }
337        m_contentsClippingMaskLayer->setPosition(FloatPoint());
338        m_contentsClippingMaskLayer->setOffsetFromRenderer(offsetFromRenderer() + IntSize(m_contentsRect.location().x(), m_contentsRect.location().y()));
339    }
340}
341
342static HashSet<int>* s_registeredLayerSet;
343
344void GraphicsLayer::registerContentsLayer(WebLayer* layer)
345{
346    if (!s_registeredLayerSet)
347        s_registeredLayerSet = new HashSet<int>;
348    if (s_registeredLayerSet->contains(layer->id()))
349        CRASH();
350    s_registeredLayerSet->add(layer->id());
351}
352
353void GraphicsLayer::unregisterContentsLayer(WebLayer* layer)
354{
355    ASSERT(s_registeredLayerSet);
356    if (!s_registeredLayerSet->contains(layer->id()))
357        CRASH();
358    s_registeredLayerSet->remove(layer->id());
359}
360
361void GraphicsLayer::setContentsTo(WebLayer* layer)
362{
363    bool childrenChanged = false;
364    if (layer) {
365        ASSERT(s_registeredLayerSet);
366        if (!s_registeredLayerSet->contains(layer->id()))
367            CRASH();
368        if (m_contentsLayerId != layer->id()) {
369            setupContentsLayer(layer);
370            childrenChanged = true;
371        }
372        updateContentsRect();
373    } else {
374        if (m_contentsLayer) {
375            childrenChanged = true;
376
377            // The old contents layer will be removed via updateChildList.
378            m_contentsLayer = 0;
379            m_contentsLayerId = 0;
380        }
381    }
382
383    if (childrenChanged)
384        updateChildList();
385}
386
387void GraphicsLayer::setupContentsLayer(WebLayer* contentsLayer)
388{
389    ASSERT(contentsLayer);
390    m_contentsLayer = contentsLayer;
391    m_contentsLayerId = m_contentsLayer->id();
392
393    m_contentsLayer->setWebLayerClient(this);
394    m_contentsLayer->setTransformOrigin(FloatPoint3D());
395    m_contentsLayer->setUseParentBackfaceVisibility(true);
396
397    // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
398    // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
399    m_contentsLayer->setDrawsContent(m_contentsVisible);
400
401    // Insert the content layer first. Video elements require this, because they have
402    // shadow content that must display in front of the video.
403    m_layer->layer()->insertChild(m_contentsLayer, 0);
404    WebLayer* borderWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
405    m_contentsLayer->setMaskLayer(borderWebLayer);
406
407    m_contentsLayer->setRenderingContext(m_3dRenderingContext);
408}
409
410void GraphicsLayer::clearContentsLayerIfUnregistered()
411{
412    if (!m_contentsLayerId || s_registeredLayerSet->contains(m_contentsLayerId))
413        return;
414
415    m_contentsLayer = 0;
416    m_contentsLayerId = 0;
417}
418
419GraphicsLayerDebugInfo& GraphicsLayer::debugInfo()
420{
421    return m_debugInfo;
422}
423
424WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer)
425{
426    GraphicsLayerDebugInfo* clone = m_debugInfo.clone();
427    clone->setDebugName(debugName(layer));
428    return clone;
429}
430
431WebLayer* GraphicsLayer::contentsLayerIfRegistered()
432{
433    clearContentsLayerIfUnregistered();
434    return m_contentsLayer;
435}
436
437void GraphicsLayer::resetTrackedPaintInvalidations()
438{
439    repaintRectMap().remove(this);
440}
441
442void GraphicsLayer::addRepaintRect(const FloatRect& repaintRect)
443{
444    if (m_client->isTrackingPaintInvalidations()) {
445        FloatRect largestRepaintRect(FloatPoint(), m_size);
446        largestRepaintRect.intersect(repaintRect);
447        RepaintMap::iterator repaintIt = repaintRectMap().find(this);
448        if (repaintIt == repaintRectMap().end()) {
449            Vector<FloatRect> repaintRects;
450            repaintRects.append(largestRepaintRect);
451            repaintRectMap().set(this, repaintRects);
452        } else {
453            Vector<FloatRect>& repaintRects = repaintIt->value;
454            repaintRects.append(largestRepaintRect);
455        }
456    }
457}
458
459static bool compareFloatRects(const FloatRect& a, const FloatRect& b)
460{
461    if (a.x() != b.x())
462        return a.x() > b.x();
463    if (a.y() != b.y())
464        return a.y() > b.y();
465    if (a.width() != b.width())
466        return a.width() > b.width();
467    return a.height() > b.height();
468}
469
470template <typename T>
471static PassRefPtr<JSONArray> pointAsJSONArray(const T& point)
472{
473    RefPtr<JSONArray> array = adoptRef(new JSONArray);
474    array->pushNumber(point.x());
475    array->pushNumber(point.y());
476    return array;
477}
478
479template <typename T>
480static PassRefPtr<JSONArray> sizeAsJSONArray(const T& size)
481{
482    RefPtr<JSONArray> array = adoptRef(new JSONArray);
483    array->pushNumber(size.width());
484    array->pushNumber(size.height());
485    return array;
486}
487
488template <typename T>
489static PassRefPtr<JSONArray> rectAsJSONArray(const T& rect)
490{
491    RefPtr<JSONArray> array = adoptRef(new JSONArray);
492    array->pushNumber(rect.x());
493    array->pushNumber(rect.y());
494    array->pushNumber(rect.width());
495    array->pushNumber(rect.height());
496    return array;
497}
498
499static double roundCloseToZero(double number)
500{
501    return std::abs(number) < 1e-7 ? 0 : number;
502}
503
504static PassRefPtr<JSONArray> transformAsJSONArray(const TransformationMatrix& t)
505{
506    RefPtr<JSONArray> array = adoptRef(new JSONArray);
507    {
508        RefPtr<JSONArray> row = adoptRef(new JSONArray);
509        row->pushNumber(roundCloseToZero(t.m11()));
510        row->pushNumber(roundCloseToZero(t.m12()));
511        row->pushNumber(roundCloseToZero(t.m13()));
512        row->pushNumber(roundCloseToZero(t.m14()));
513        array->pushArray(row);
514    }
515    {
516        RefPtr<JSONArray> row = adoptRef(new JSONArray);
517        row->pushNumber(roundCloseToZero(t.m21()));
518        row->pushNumber(roundCloseToZero(t.m22()));
519        row->pushNumber(roundCloseToZero(t.m23()));
520        row->pushNumber(roundCloseToZero(t.m24()));
521        array->pushArray(row);
522    }
523    {
524        RefPtr<JSONArray> row = adoptRef(new JSONArray);
525        row->pushNumber(roundCloseToZero(t.m31()));
526        row->pushNumber(roundCloseToZero(t.m32()));
527        row->pushNumber(roundCloseToZero(t.m33()));
528        row->pushNumber(roundCloseToZero(t.m34()));
529        array->pushArray(row);
530    }
531    {
532        RefPtr<JSONArray> row = adoptRef(new JSONArray);
533        row->pushNumber(roundCloseToZero(t.m41()));
534        row->pushNumber(roundCloseToZero(t.m42()));
535        row->pushNumber(roundCloseToZero(t.m43()));
536        row->pushNumber(roundCloseToZero(t.m44()));
537        array->pushArray(row);
538    }
539    return array;
540}
541
542static String pointerAsString(const void* ptr)
543{
544    TextStream ts;
545    ts << ptr;
546    return ts.release();
547}
548
549PassRefPtr<JSONObject> GraphicsLayer::layerTreeAsJSON(LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
550{
551    RefPtr<JSONObject> json = adoptRef(new JSONObject);
552
553    if (flags & LayerTreeIncludesDebugInfo) {
554        json->setString("this", pointerAsString(this));
555        json->setString("debugName", m_client->debugName(this));
556    }
557
558    if (m_position != FloatPoint())
559        json->setArray("position", pointAsJSONArray(m_position));
560
561    if (m_hasTransformOrigin && m_transformOrigin != FloatPoint3D(m_size.width() * 0.5f, m_size.height() * 0.5f, 0))
562        json->setArray("transformOrigin", pointAsJSONArray(m_transformOrigin));
563
564    if (m_size != IntSize())
565        json->setArray("bounds", sizeAsJSONArray(m_size));
566
567    if (m_opacity != 1)
568        json->setNumber("opacity", m_opacity);
569
570    if (m_blendMode != WebBlendModeNormal)
571        json->setString("blendMode", compositeOperatorName(CompositeSourceOver, m_blendMode));
572
573    if (m_isRootForIsolatedGroup)
574        json->setBoolean("isolate", m_isRootForIsolatedGroup);
575
576    if (m_contentsOpaque)
577        json->setBoolean("contentsOpaque", m_contentsOpaque);
578
579    if (!m_shouldFlattenTransform)
580        json->setBoolean("shouldFlattenTransform", m_shouldFlattenTransform);
581
582    if (m_3dRenderingContext) {
583        RenderingContextMap::const_iterator it = renderingContextMap.find(m_3dRenderingContext);
584        int contextId = renderingContextMap.size() + 1;
585        if (it == renderingContextMap.end())
586            renderingContextMap.set(m_3dRenderingContext, contextId);
587        else
588            contextId = it->value;
589
590        json->setNumber("3dRenderingContext", contextId);
591    }
592
593    if (m_drawsContent)
594        json->setBoolean("drawsContent", m_drawsContent);
595
596    if (!m_contentsVisible)
597        json->setBoolean("contentsVisible", m_contentsVisible);
598
599    if (!m_backfaceVisibility)
600        json->setString("backfaceVisibility", m_backfaceVisibility ? "visible" : "hidden");
601
602    if (flags & LayerTreeIncludesDebugInfo)
603        json->setString("client", pointerAsString(m_client));
604
605    if (m_backgroundColor.alpha())
606        json->setString("backgroundColor", m_backgroundColor.nameForRenderTreeAsText());
607
608    if (!m_transform.isIdentity())
609        json->setArray("transform", transformAsJSONArray(m_transform));
610
611    if (m_replicaLayer)
612        json->setObject("replicaLayer", m_replicaLayer->layerTreeAsJSON(flags, renderingContextMap));
613
614    if (m_replicatedLayer)
615        json->setString("replicatedLayer", flags & LayerTreeIncludesDebugInfo ? pointerAsString(m_replicatedLayer) : "");
616
617    if ((flags & LayerTreeIncludesPaintInvalidationRects) && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty()) {
618        Vector<FloatRect> repaintRectsCopy = repaintRectMap().get(this);
619        std::sort(repaintRectsCopy.begin(), repaintRectsCopy.end(), &compareFloatRects);
620        RefPtr<JSONArray> repaintRectsJSON = adoptRef(new JSONArray);
621        for (size_t i = 0; i < repaintRectsCopy.size(); ++i) {
622            if (repaintRectsCopy[i].isEmpty())
623                continue;
624            repaintRectsJSON->pushArray(rectAsJSONArray(repaintRectsCopy[i]));
625        }
626        json->setArray("repaintRects", repaintRectsJSON);
627    }
628
629    if ((flags & LayerTreeIncludesPaintingPhases) && m_paintingPhase) {
630        RefPtr<JSONArray> paintingPhasesJSON = adoptRef(new JSONArray);
631        if (m_paintingPhase & GraphicsLayerPaintBackground)
632            paintingPhasesJSON->pushString("GraphicsLayerPaintBackground");
633        if (m_paintingPhase & GraphicsLayerPaintForeground)
634            paintingPhasesJSON->pushString("GraphicsLayerPaintForeground");
635        if (m_paintingPhase & GraphicsLayerPaintMask)
636            paintingPhasesJSON->pushString("GraphicsLayerPaintMask");
637        if (m_paintingPhase & GraphicsLayerPaintChildClippingMask)
638            paintingPhasesJSON->pushString("GraphicsLayerPaintChildClippingMask");
639        if (m_paintingPhase & GraphicsLayerPaintOverflowContents)
640            paintingPhasesJSON->pushString("GraphicsLayerPaintOverflowContents");
641        if (m_paintingPhase & GraphicsLayerPaintCompositedScroll)
642            paintingPhasesJSON->pushString("GraphicsLayerPaintCompositedScroll");
643        json->setArray("paintingPhases", paintingPhasesJSON);
644    }
645
646    if (flags & LayerTreeIncludesClipAndScrollParents) {
647        if (m_hasScrollParent)
648            json->setBoolean("hasScrollParent", true);
649        if (m_hasClipParent)
650            json->setBoolean("hasClipParent", true);
651    }
652
653    if (flags & LayerTreeIncludesDebugInfo) {
654        RefPtr<JSONArray> compositingReasonsJSON = adoptRef(new JSONArray);
655        for (size_t i = 0; i < kNumberOfCompositingReasons; ++i) {
656            if (m_debugInfo.compositingReasons() & kCompositingReasonStringMap[i].reason)
657                compositingReasonsJSON->pushString(kCompositingReasonStringMap[i].description);
658        }
659        json->setArray("compositingReasons", compositingReasonsJSON);
660    }
661
662    if (m_children.size()) {
663        RefPtr<JSONArray> childrenJSON = adoptRef(new JSONArray);
664        for (size_t i = 0; i < m_children.size(); i++)
665            childrenJSON->pushObject(m_children[i]->layerTreeAsJSON(flags, renderingContextMap));
666        json->setArray("children", childrenJSON);
667    }
668
669    return json;
670}
671
672String GraphicsLayer::layerTreeAsText(LayerTreeFlags flags) const
673{
674    RenderingContextMap renderingContextMap;
675    RefPtr<JSONObject> json = layerTreeAsJSON(flags, renderingContextMap);
676    return json->toPrettyJSONString();
677}
678
679String GraphicsLayer::debugName(WebLayer* webLayer) const
680{
681    String name;
682    if (!m_client)
683        return name;
684
685    String highlightDebugName;
686    for (size_t i = 0; i < m_linkHighlights.size(); ++i) {
687        if (webLayer == m_linkHighlights[i]->layer()) {
688            highlightDebugName = "LinkHighlight[" + String::number(i) + "] for " + m_client->debugName(this);
689            break;
690        }
691    }
692
693    if (webLayer == m_contentsLayer) {
694        name = "ContentsLayer for " + m_client->debugName(this);
695    } else if (!highlightDebugName.isEmpty()) {
696        name = highlightDebugName;
697    } else if (webLayer == m_layer->layer()) {
698        name = m_client->debugName(this);
699    } else {
700        ASSERT_NOT_REACHED();
701    }
702    return name;
703}
704
705void GraphicsLayer::setCompositingReasons(CompositingReasons reasons)
706{
707    m_debugInfo.setCompositingReasons(reasons);
708}
709
710void GraphicsLayer::setOwnerNodeId(int nodeId)
711{
712    m_debugInfo.setOwnerNodeId(nodeId);
713}
714
715void GraphicsLayer::setPosition(const FloatPoint& point)
716{
717    m_position = point;
718    platformLayer()->setPosition(m_position);
719}
720
721void GraphicsLayer::setSize(const FloatSize& size)
722{
723    // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
724    // avoid those assertions.
725    // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
726    FloatSize clampedSize = size;
727    if (clampedSize.width() < 0 || clampedSize.height() < 0)
728        clampedSize = FloatSize();
729
730    if (clampedSize == m_size)
731        return;
732
733    m_size = clampedSize;
734
735    m_layer->layer()->setBounds(flooredIntSize(m_size));
736    // Note that we don't resize m_contentsLayer. It's up the caller to do that.
737}
738
739void GraphicsLayer::setTransform(const TransformationMatrix& transform)
740{
741    m_transform = transform;
742    platformLayer()->setTransform(TransformationMatrix::toSkMatrix44(m_transform));
743}
744
745void GraphicsLayer::setTransformOrigin(const FloatPoint3D& transformOrigin)
746{
747    m_hasTransformOrigin = true;
748    m_transformOrigin = transformOrigin;
749    platformLayer()->setTransformOrigin(transformOrigin);
750}
751
752void GraphicsLayer::setShouldFlattenTransform(bool shouldFlatten)
753{
754    if (shouldFlatten == m_shouldFlattenTransform)
755        return;
756
757    m_shouldFlattenTransform = shouldFlatten;
758
759    m_layer->layer()->setShouldFlattenTransform(shouldFlatten);
760}
761
762void GraphicsLayer::setRenderingContext(int context)
763{
764    if (m_3dRenderingContext == context)
765        return;
766
767    m_3dRenderingContext = context;
768    m_layer->layer()->setRenderingContext(context);
769
770    if (m_contentsLayer)
771        m_contentsLayer->setRenderingContext(m_3dRenderingContext);
772}
773
774void GraphicsLayer::setMasksToBounds(bool masksToBounds)
775{
776    m_masksToBounds = masksToBounds;
777    m_layer->layer()->setMasksToBounds(m_masksToBounds);
778}
779
780void GraphicsLayer::setDrawsContent(bool drawsContent)
781{
782    // Note carefully this early-exit is only correct because we also properly call
783    // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
784    if (drawsContent == m_drawsContent)
785        return;
786
787    m_drawsContent = drawsContent;
788    updateLayerIsDrawable();
789}
790
791void GraphicsLayer::setContentsVisible(bool contentsVisible)
792{
793    // Note carefully this early-exit is only correct because we also properly call
794    // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
795    if (contentsVisible == m_contentsVisible)
796        return;
797
798    m_contentsVisible = contentsVisible;
799    updateLayerIsDrawable();
800}
801
802void GraphicsLayer::setClipParent(WebLayer* parent)
803{
804    m_hasClipParent = !!parent;
805    m_layer->layer()->setClipParent(parent);
806}
807
808void GraphicsLayer::setScrollParent(WebLayer* parent)
809{
810    m_hasScrollParent = !!parent;
811    m_layer->layer()->setScrollParent(parent);
812}
813
814void GraphicsLayer::setBackgroundColor(const Color& color)
815{
816    if (color == m_backgroundColor)
817        return;
818
819    m_backgroundColor = color;
820    m_layer->layer()->setBackgroundColor(m_backgroundColor.rgb());
821}
822
823void GraphicsLayer::setContentsOpaque(bool opaque)
824{
825    m_contentsOpaque = opaque;
826    m_layer->layer()->setOpaque(m_contentsOpaque);
827    m_contentLayerDelegate->setOpaque(m_contentsOpaque);
828    clearContentsLayerIfUnregistered();
829    if (m_contentsLayer)
830        m_contentsLayer->setOpaque(opaque);
831}
832
833void GraphicsLayer::setMaskLayer(GraphicsLayer* maskLayer)
834{
835    if (maskLayer == m_maskLayer)
836        return;
837
838    m_maskLayer = maskLayer;
839    WebLayer* maskWebLayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
840    m_layer->layer()->setMaskLayer(maskWebLayer);
841}
842
843void GraphicsLayer::setContentsClippingMaskLayer(GraphicsLayer* contentsClippingMaskLayer)
844{
845    if (contentsClippingMaskLayer == m_contentsClippingMaskLayer)
846        return;
847
848    m_contentsClippingMaskLayer = contentsClippingMaskLayer;
849    WebLayer* contentsLayer = contentsLayerIfRegistered();
850    if (!contentsLayer)
851        return;
852    WebLayer* contentsClippingMaskWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
853    contentsLayer->setMaskLayer(contentsClippingMaskWebLayer);
854    updateContentsRect();
855}
856
857void GraphicsLayer::setBackfaceVisibility(bool visible)
858{
859    m_backfaceVisibility = visible;
860    m_layer->setDoubleSided(m_backfaceVisibility);
861}
862
863void GraphicsLayer::setOpacity(float opacity)
864{
865    float clampedOpacity = std::max(std::min(opacity, 1.0f), 0.0f);
866    m_opacity = clampedOpacity;
867    platformLayer()->setOpacity(opacity);
868}
869
870void GraphicsLayer::setBlendMode(WebBlendMode blendMode)
871{
872    if (m_blendMode == blendMode)
873        return;
874    m_blendMode = blendMode;
875    platformLayer()->setBlendMode(WebBlendMode(blendMode));
876}
877
878void GraphicsLayer::setIsRootForIsolatedGroup(bool isolated)
879{
880    if (m_isRootForIsolatedGroup == isolated)
881        return;
882    m_isRootForIsolatedGroup = isolated;
883    platformLayer()->setIsRootForIsolatedGroup(isolated);
884}
885
886void GraphicsLayer::setContentsNeedsDisplay()
887{
888    if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
889        contentsLayer->invalidate();
890        addRepaintRect(m_contentsRect);
891    }
892}
893
894void GraphicsLayer::setNeedsDisplay()
895{
896    if (drawsContent()) {
897        m_layer->layer()->invalidate();
898        addRepaintRect(FloatRect(FloatPoint(), m_size));
899        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
900            m_linkHighlights[i]->invalidate();
901    }
902}
903
904void GraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect, WebInvalidationDebugAnnotations annotations)
905{
906    if (drawsContent()) {
907        m_layer->layer()->invalidateRect(rect);
908        if (firstPaintInvalidationTrackingEnabled())
909            m_debugInfo.appendAnnotatedInvalidateRect(rect, annotations);
910        addRepaintRect(rect);
911        for (size_t i = 0; i < m_linkHighlights.size(); ++i)
912            m_linkHighlights[i]->invalidate();
913    }
914}
915
916void GraphicsLayer::setContentsRect(const IntRect& rect)
917{
918    if (rect == m_contentsRect)
919        return;
920
921    m_contentsRect = rect;
922    updateContentsRect();
923}
924
925void GraphicsLayer::setContentsToImage(Image* image)
926{
927    RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
928    if (nativeImage) {
929        if (!m_imageLayer) {
930            m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer());
931            registerContentsLayer(m_imageLayer->layer());
932        }
933        m_imageLayer->setImageBitmap(nativeImage->bitmap());
934        m_imageLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
935        updateContentsRect();
936    } else {
937        if (m_imageLayer) {
938            unregisterContentsLayer(m_imageLayer->layer());
939            m_imageLayer.clear();
940        }
941    }
942
943    setContentsTo(m_imageLayer ? m_imageLayer->layer() : 0);
944}
945
946void GraphicsLayer::setContentsToNinePatch(Image* image, const IntRect& aperture)
947{
948    if (m_ninePatchLayer) {
949        unregisterContentsLayer(m_ninePatchLayer->layer());
950        m_ninePatchLayer.clear();
951    }
952    RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
953    if (nativeImage) {
954        m_ninePatchLayer = adoptPtr(Platform::current()->compositorSupport()->createNinePatchLayer());
955        const SkBitmap& bitmap = nativeImage->bitmap();
956        int borderWidth = bitmap.width() - aperture.width();
957        int borderHeight = bitmap.height() - aperture.height();
958        WebRect border(aperture.x(), aperture.y(), borderWidth, borderHeight);
959
960        m_ninePatchLayer->setBitmap(bitmap);
961        m_ninePatchLayer->setAperture(aperture);
962        m_ninePatchLayer->setBorder(border);
963
964        m_ninePatchLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
965        registerContentsLayer(m_ninePatchLayer->layer());
966    }
967    setContentsTo(m_ninePatchLayer ? m_ninePatchLayer->layer() : 0);
968}
969
970bool GraphicsLayer::addAnimation(PassOwnPtr<WebCompositorAnimation> popAnimation)
971{
972    OwnPtr<WebCompositorAnimation> animation(popAnimation);
973    ASSERT(animation);
974    platformLayer()->setAnimationDelegate(this);
975
976    // Remove any existing animations with the same animation id and target property.
977    platformLayer()->removeAnimation(animation->id(), animation->targetProperty());
978    return platformLayer()->addAnimation(animation.leakPtr());
979}
980
981void GraphicsLayer::pauseAnimation(int animationId, double timeOffset)
982{
983    platformLayer()->pauseAnimation(animationId, timeOffset);
984}
985
986void GraphicsLayer::removeAnimation(int animationId)
987{
988    platformLayer()->removeAnimation(animationId);
989}
990
991WebLayer* GraphicsLayer::platformLayer() const
992{
993    return m_layer->layer();
994}
995
996void GraphicsLayer::setFilters(const FilterOperations& filters)
997{
998    SkiaImageFilterBuilder builder;
999    OwnPtr<WebFilterOperations> webFilters = adoptPtr(Platform::current()->compositorSupport()->createFilterOperations());
1000    FilterOutsets outsets = filters.outsets();
1001    builder.setCropOffset(FloatSize(outsets.left(), outsets.top()));
1002    builder.buildFilterOperations(filters, webFilters.get());
1003    m_layer->layer()->setFilters(*webFilters);
1004}
1005
1006void GraphicsLayer::setPaintingPhase(GraphicsLayerPaintingPhase phase)
1007{
1008    if (m_paintingPhase == phase)
1009        return;
1010    m_paintingPhase = phase;
1011    setNeedsDisplay();
1012}
1013
1014void GraphicsLayer::addLinkHighlight(LinkHighlightClient* linkHighlight)
1015{
1016    ASSERT(linkHighlight && !m_linkHighlights.contains(linkHighlight));
1017    m_linkHighlights.append(linkHighlight);
1018    linkHighlight->layer()->setWebLayerClient(this);
1019    updateChildList();
1020}
1021
1022void GraphicsLayer::removeLinkHighlight(LinkHighlightClient* linkHighlight)
1023{
1024    m_linkHighlights.remove(m_linkHighlights.find(linkHighlight));
1025    updateChildList();
1026}
1027
1028void GraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea, bool isMainFrame)
1029{
1030    if (m_scrollableArea == scrollableArea)
1031        return;
1032
1033    m_scrollableArea = scrollableArea;
1034
1035    // Main frame scrolling may involve pinch zoom and gets routed through
1036    // WebViewImpl explicitly rather than via GraphicsLayer::didScroll.
1037    // TODO(bokan): With pinch virtual viewport the special case will no
1038    // longer be needed, remove once old-style pinch is gone.
1039    if (isMainFrame)
1040        m_layer->layer()->setScrollClient(0);
1041    else
1042        m_layer->layer()->setScrollClient(this);
1043}
1044
1045void GraphicsLayer::paint(GraphicsContext& context, const IntRect& clip)
1046{
1047    paintGraphicsLayerContents(context, clip);
1048}
1049
1050
1051void GraphicsLayer::notifyAnimationStarted(double monotonicTime, WebCompositorAnimation::TargetProperty)
1052{
1053    if (m_client)
1054        m_client->notifyAnimationStarted(this, monotonicTime);
1055}
1056
1057void GraphicsLayer::notifyAnimationFinished(double, WebCompositorAnimation::TargetProperty)
1058{
1059    // Do nothing.
1060}
1061
1062void GraphicsLayer::didScroll()
1063{
1064    if (m_scrollableArea)
1065        m_scrollableArea->scrollToOffsetWithoutAnimation(m_scrollableArea->minimumScrollPosition() + toIntSize(m_layer->layer()->scrollPosition()));
1066}
1067
1068} // namespace blink
1069
1070#ifndef NDEBUG
1071void showGraphicsLayerTree(const blink::GraphicsLayer* layer)
1072{
1073    if (!layer)
1074        return;
1075
1076    String output = layer->layerTreeAsText(blink::LayerTreeIncludesDebugInfo);
1077    fprintf(stderr, "%s\n", output.utf8().data());
1078}
1079#endif
1080