• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
63 using blink::Platform;
64 using blink::WebCompositorAnimation;
65 using blink::WebFilterOperations;
66 using blink::WebLayer;
67 using blink::WebPoint;
68 
69 namespace blink {
70 
71 typedef HashMap<const GraphicsLayer*, Vector<FloatRect> > RepaintMap;
repaintRectMap()72 static RepaintMap& repaintRectMap()
73 {
74     DEFINE_STATIC_LOCAL(RepaintMap, map, ());
75     return map;
76 }
77 
create(GraphicsLayerFactory * factory,GraphicsLayerClient * client)78 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
79 {
80     return factory->createGraphicsLayer(client);
81 }
82 
GraphicsLayer(GraphicsLayerClient * client)83 GraphicsLayer::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 
~GraphicsLayer()122 GraphicsLayer::~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 
setParent(GraphicsLayer * layer)146 void GraphicsLayer::setParent(GraphicsLayer* layer)
147 {
148     ASSERT(!layer || !layer->hasAncestor(this));
149     m_parent = layer;
150 }
151 
152 #if ENABLE(ASSERT)
153 
hasAncestor(GraphicsLayer * ancestor) const154 bool 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 
setChildren(const GraphicsLayerVector & newChildren)166 bool 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 
addChildInternal(GraphicsLayer * childLayer)183 void 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 
addChild(GraphicsLayer * childLayer)197 void GraphicsLayer::addChild(GraphicsLayer* childLayer)
198 {
199     addChildInternal(childLayer);
200     updateChildList();
201 }
202 
addChildBelow(GraphicsLayer * childLayer,GraphicsLayer * sibling)203 void 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 
removeAllChildren()225 void GraphicsLayer::removeAllChildren()
226 {
227     while (!m_children.isEmpty()) {
228         GraphicsLayer* curLayer = m_children.last();
229         ASSERT(curLayer->parent());
230         curLayer->removeFromParent();
231     }
232 }
233 
removeFromParent()234 void 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 
setReplicatedByLayer(GraphicsLayer * layer)245 void 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 
setOffsetFromRenderer(const IntSize & offset,ShouldSetNeedsDisplay shouldSetNeedsDisplay)262 void 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 
paintGraphicsLayerContents(GraphicsContext & context,const IntRect & clip)274 void 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 
updateChildList()284 void 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 
updateLayerIsDrawable()305 void 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 
updateContentsRect()323 void 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 
342 static HashSet<int>* s_registeredLayerSet;
343 
registerContentsLayer(WebLayer * layer)344 void 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 
unregisterContentsLayer(WebLayer * layer)353 void 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 
setContentsTo(WebLayer * layer)361 void 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 
setupContentsLayer(WebLayer * contentsLayer)387 void 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 
clearContentsLayerIfUnregistered()410 void 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 
debugInfo()419 GraphicsLayerDebugInfo& GraphicsLayer::debugInfo()
420 {
421     return m_debugInfo;
422 }
423 
takeDebugInfoFor(WebLayer * layer)424 WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer)
425 {
426     GraphicsLayerDebugInfo* clone = m_debugInfo.clone();
427     clone->setDebugName(debugName(layer));
428     return clone;
429 }
430 
contentsLayerIfRegistered()431 WebLayer* GraphicsLayer::contentsLayerIfRegistered()
432 {
433     clearContentsLayerIfUnregistered();
434     return m_contentsLayer;
435 }
436 
resetTrackedPaintInvalidations()437 void GraphicsLayer::resetTrackedPaintInvalidations()
438 {
439     repaintRectMap().remove(this);
440 }
441 
addRepaintRect(const FloatRect & repaintRect)442 void 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 
compareFloatRects(const FloatRect & a,const FloatRect & b)459 static 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 
470 template <typename T>
pointAsJSONArray(const T & point)471 static 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 
479 template <typename T>
sizeAsJSONArray(const T & size)480 static 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 
488 template <typename T>
rectAsJSONArray(const T & rect)489 static 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 
roundCloseToZero(double number)499 static double roundCloseToZero(double number)
500 {
501     return std::abs(number) < 1e-7 ? 0 : number;
502 }
503 
transformAsJSONArray(const TransformationMatrix & t)504 static 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 
pointerAsString(const void * ptr)542 static String pointerAsString(const void* ptr)
543 {
544     TextStream ts;
545     ts << ptr;
546     return ts.release();
547 }
548 
layerTreeAsJSON(LayerTreeFlags flags,RenderingContextMap & renderingContextMap) const549 PassRefPtr<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 
layerTreeAsText(LayerTreeFlags flags) const672 String GraphicsLayer::layerTreeAsText(LayerTreeFlags flags) const
673 {
674     RenderingContextMap renderingContextMap;
675     RefPtr<JSONObject> json = layerTreeAsJSON(flags, renderingContextMap);
676     return json->toPrettyJSONString();
677 }
678 
debugName(WebLayer * webLayer) const679 String 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 
setCompositingReasons(CompositingReasons reasons)705 void GraphicsLayer::setCompositingReasons(CompositingReasons reasons)
706 {
707     m_debugInfo.setCompositingReasons(reasons);
708 }
709 
setOwnerNodeId(int nodeId)710 void GraphicsLayer::setOwnerNodeId(int nodeId)
711 {
712     m_debugInfo.setOwnerNodeId(nodeId);
713 }
714 
setPosition(const FloatPoint & point)715 void GraphicsLayer::setPosition(const FloatPoint& point)
716 {
717     m_position = point;
718     platformLayer()->setPosition(m_position);
719 }
720 
setSize(const FloatSize & size)721 void 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 
setTransform(const TransformationMatrix & transform)739 void GraphicsLayer::setTransform(const TransformationMatrix& transform)
740 {
741     m_transform = transform;
742     platformLayer()->setTransform(TransformationMatrix::toSkMatrix44(m_transform));
743 }
744 
setTransformOrigin(const FloatPoint3D & transformOrigin)745 void GraphicsLayer::setTransformOrigin(const FloatPoint3D& transformOrigin)
746 {
747     m_hasTransformOrigin = true;
748     m_transformOrigin = transformOrigin;
749     platformLayer()->setTransformOrigin(transformOrigin);
750 }
751 
setShouldFlattenTransform(bool shouldFlatten)752 void 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 
setRenderingContext(int context)762 void 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 
setMasksToBounds(bool masksToBounds)774 void GraphicsLayer::setMasksToBounds(bool masksToBounds)
775 {
776     m_masksToBounds = masksToBounds;
777     m_layer->layer()->setMasksToBounds(m_masksToBounds);
778 }
779 
setDrawsContent(bool drawsContent)780 void 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 
setContentsVisible(bool contentsVisible)791 void 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 
setClipParent(WebLayer * parent)802 void GraphicsLayer::setClipParent(WebLayer* parent)
803 {
804     m_hasClipParent = !!parent;
805     m_layer->layer()->setClipParent(parent);
806 }
807 
setScrollParent(WebLayer * parent)808 void GraphicsLayer::setScrollParent(WebLayer* parent)
809 {
810     m_hasScrollParent = !!parent;
811     m_layer->layer()->setScrollParent(parent);
812 }
813 
setBackgroundColor(const Color & color)814 void 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 
setContentsOpaque(bool opaque)823 void 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 
setMaskLayer(GraphicsLayer * maskLayer)833 void 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 
setContentsClippingMaskLayer(GraphicsLayer * contentsClippingMaskLayer)843 void 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 
setBackfaceVisibility(bool visible)857 void GraphicsLayer::setBackfaceVisibility(bool visible)
858 {
859     m_backfaceVisibility = visible;
860     m_layer->setDoubleSided(m_backfaceVisibility);
861 }
862 
setOpacity(float opacity)863 void 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 
setBlendMode(WebBlendMode blendMode)870 void GraphicsLayer::setBlendMode(WebBlendMode blendMode)
871 {
872     if (m_blendMode == blendMode)
873         return;
874     m_blendMode = blendMode;
875     platformLayer()->setBlendMode(WebBlendMode(blendMode));
876 }
877 
setIsRootForIsolatedGroup(bool isolated)878 void GraphicsLayer::setIsRootForIsolatedGroup(bool isolated)
879 {
880     if (m_isRootForIsolatedGroup == isolated)
881         return;
882     m_isRootForIsolatedGroup = isolated;
883     platformLayer()->setIsRootForIsolatedGroup(isolated);
884 }
885 
setContentsNeedsDisplay()886 void GraphicsLayer::setContentsNeedsDisplay()
887 {
888     if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
889         contentsLayer->invalidate();
890         addRepaintRect(m_contentsRect);
891     }
892 }
893 
setNeedsDisplay()894 void 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 
setNeedsDisplayInRect(const FloatRect & rect,WebInvalidationDebugAnnotations annotations)904 void 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 
setContentsRect(const IntRect & rect)916 void GraphicsLayer::setContentsRect(const IntRect& rect)
917 {
918     if (rect == m_contentsRect)
919         return;
920 
921     m_contentsRect = rect;
922     updateContentsRect();
923 }
924 
setContentsToImage(Image * image)925 void 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 
setContentsToNinePatch(Image * image,const IntRect & aperture)946 void 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 
addAnimation(PassOwnPtr<WebCompositorAnimation> popAnimation)970 bool 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 
pauseAnimation(int animationId,double timeOffset)981 void GraphicsLayer::pauseAnimation(int animationId, double timeOffset)
982 {
983     platformLayer()->pauseAnimation(animationId, timeOffset);
984 }
985 
removeAnimation(int animationId)986 void GraphicsLayer::removeAnimation(int animationId)
987 {
988     platformLayer()->removeAnimation(animationId);
989 }
990 
platformLayer() const991 WebLayer* GraphicsLayer::platformLayer() const
992 {
993     return m_layer->layer();
994 }
995 
setFilters(const FilterOperations & filters)996 void 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 
setPaintingPhase(GraphicsLayerPaintingPhase phase)1006 void GraphicsLayer::setPaintingPhase(GraphicsLayerPaintingPhase phase)
1007 {
1008     if (m_paintingPhase == phase)
1009         return;
1010     m_paintingPhase = phase;
1011     setNeedsDisplay();
1012 }
1013 
addLinkHighlight(LinkHighlightClient * linkHighlight)1014 void 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 
removeLinkHighlight(LinkHighlightClient * linkHighlight)1022 void GraphicsLayer::removeLinkHighlight(LinkHighlightClient* linkHighlight)
1023 {
1024     m_linkHighlights.remove(m_linkHighlights.find(linkHighlight));
1025     updateChildList();
1026 }
1027 
setScrollableArea(ScrollableArea * scrollableArea,bool isMainFrame)1028 void 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 
paint(GraphicsContext & context,const IntRect & clip)1045 void GraphicsLayer::paint(GraphicsContext& context, const IntRect& clip)
1046 {
1047     paintGraphicsLayerContents(context, clip);
1048 }
1049 
1050 
notifyAnimationStarted(double monotonicTime,WebCompositorAnimation::TargetProperty)1051 void GraphicsLayer::notifyAnimationStarted(double monotonicTime, WebCompositorAnimation::TargetProperty)
1052 {
1053     if (m_client)
1054         m_client->notifyAnimationStarted(this, monotonicTime);
1055 }
1056 
notifyAnimationFinished(double,WebCompositorAnimation::TargetProperty)1057 void GraphicsLayer::notifyAnimationFinished(double, WebCompositorAnimation::TargetProperty)
1058 {
1059     // Do nothing.
1060 }
1061 
didScroll()1062 void 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
showGraphicsLayerTree(const blink::GraphicsLayer * layer)1071 void 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