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