2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "platform/graphics/GraphicsLayer.h"
29 #include "SkImageFilter.h"
30 #include "SkMatrix44.h"
31 #include "platform/TraceEvent.h"
32 #include "platform/geometry/FloatRect.h"
33 #include "platform/geometry/LayoutRect.h"
34 #include "platform/graphics/FirstPaintInvalidationTracking.h"
35 #include "platform/graphics/GraphicsLayerFactory.h"
36 #include "platform/graphics/Image.h"
37 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
38 #include "platform/graphics/skia/NativeImageSkia.h"
39 #include "platform/scroll/ScrollableArea.h"
40 #include "platform/text/TextStream.h"
41 #include "public/platform/Platform.h"
42 #include "public/platform/WebCompositorAnimation.h"
43 #include "public/platform/WebCompositorSupport.h"
44 #include "public/platform/WebFilterOperations.h"
45 #include "public/platform/WebFloatPoint.h"
46 #include "public/platform/WebFloatRect.h"
47 #include "public/platform/WebGraphicsLayerDebugInfo.h"
48 #include "public/platform/WebLayer.h"
49 #include "public/platform/WebPoint.h"
50 #include "public/platform/WebSize.h"
51 #include "wtf/CurrentTime.h"
52 #include "wtf/HashMap.h"
53 #include "wtf/HashSet.h"
54 #include "wtf/text/WTFString.h"
63 typedef HashMap<const GraphicsLayer*, Vector<FloatRect> > RepaintMap;
64 static RepaintMap& repaintRectMap()
66 DEFINE_STATIC_LOCAL(RepaintMap, map, ());
70 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
72 return factory->createGraphicsLayer(client);
75 GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
77 , m_backgroundColor(Color::transparent)
79 , m_blendMode(WebBlendModeNormal)
80 , m_hasTransformOrigin(false)
81 , m_contentsOpaque(false)
82 , m_shouldFlattenTransform(true)
83 , m_backfaceVisibility(true)
84 , m_masksToBounds(false)
85 , m_drawsContent(false)
86 , m_contentsVisible(true)
87 , m_isRootForIsolatedGroup(false)
88 , m_hasScrollParent(false)
89 , m_hasClipParent(false)
90 , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
93 , m_contentsClippingMaskLayer(0)
95 , m_replicatedLayer(0)
98 , m_contentsLayerId(0)
100 , m_3dRenderingContext(0)
104 m_client->verifyNotPainting();
107 m_contentLayerDelegate = adoptPtr(new ContentLayerDelegate(this));
108 m_layer = adoptPtr(Platform::current()->compositorSupport()->createContentLayer(m_contentLayerDelegate.get()));
109 m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
110 m_layer->layer()->setWebLayerClient(this);
111 m_layer->setAutomaticallyComputeRasterScale(true);
114 GraphicsLayer::~GraphicsLayer()
116 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
117 m_linkHighlights[i]->clearCurrentGraphicsLayer();
118 m_linkHighlights.clear();
122 m_client->verifyNotPainting();
126 m_replicaLayer->setReplicatedLayer(0);
128 if (m_replicatedLayer)
129 m_replicatedLayer->setReplicatedByLayer(0);
134 resetTrackedPaintInvalidations();
138 void GraphicsLayer::setParent(GraphicsLayer* layer)
140 ASSERT(!layer || !layer->hasAncestor(this));
146 bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
148 for (GraphicsLayer* curr = parent(); curr; curr = curr->parent()) {
149 if (curr == ancestor)
158 bool GraphicsLayer::setChildren(const GraphicsLayerVector& newChildren)
160 // If the contents of the arrays are the same, nothing to do.
161 if (newChildren == m_children)
166 size_t listSize = newChildren.size();
167 for (size_t i = 0; i < listSize; ++i)
168 addChildInternal(newChildren[i]);
175 void GraphicsLayer::addChildInternal(GraphicsLayer* childLayer)
177 ASSERT(childLayer != this);
179 if (childLayer->parent())
180 childLayer->removeFromParent();
182 childLayer->setParent(this);
183 m_children.append(childLayer);
185 // Don't call updateChildList here, this function is used in cases where it
186 // should not be called until all children are processed.
189 void GraphicsLayer::addChild(GraphicsLayer* childLayer)
191 addChildInternal(childLayer);
195 void GraphicsLayer::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
197 ASSERT(childLayer != this);
198 childLayer->removeFromParent();
201 for (unsigned i = 0; i < m_children.size(); i++) {
202 if (sibling == m_children[i]) {
203 m_children.insert(i, childLayer);
209 childLayer->setParent(this);
212 m_children.append(childLayer);
217 void GraphicsLayer::removeAllChildren()
219 while (!m_children.isEmpty()) {
220 GraphicsLayer* curLayer = m_children.last();
221 ASSERT(curLayer->parent());
222 curLayer->removeFromParent();
226 void GraphicsLayer::removeFromParent()
229 // We use reverseFind so that removeAllChildren() isn't n^2.
230 m_parent->m_children.remove(m_parent->m_children.reverseFind(this));
234 platformLayer()->removeFromParent();
237 void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
239 // FIXME: this could probably be a full early exit.
240 if (m_replicaLayer != layer) {
242 m_replicaLayer->setReplicatedLayer(0);
245 layer->setReplicatedLayer(this);
247 m_replicaLayer = layer;
250 WebLayer* webReplicaLayer = layer ? layer->platformLayer() : 0;
251 platformLayer()->setReplicaLayer(webReplicaLayer);
254 void GraphicsLayer::setOffsetFromRenderer(const IntSize& offset, ShouldSetNeedsDisplay shouldSetNeedsDisplay)
256 if (offset == m_offsetFromRenderer)
259 m_offsetFromRenderer = offset;
261 // If the compositing layer offset changes, we need to repaint.
262 if (shouldSetNeedsDisplay == SetNeedsDisplay)
266 void GraphicsLayer::paintGraphicsLayerContents(GraphicsContext& context, const IntRect& clip)
270 if (firstPaintInvalidationTrackingEnabled())
271 m_debugInfo.clearAnnotatedInvalidateRects();
272 incrementPaintCount();
273 m_client->paintContents(this, context, m_paintingPhase, clip);
276 void GraphicsLayer::updateChildList()
278 WebLayer* childHost = m_layer->layer();
279 childHost->removeAllChildren();
281 clearContentsLayerIfUnregistered();
283 if (m_contentsLayer) {
284 // FIXME: add the contents layer in the correct order with negative z-order children.
285 // This does not cause visible rendering issues because currently contents layers are only used
286 // for replaced elements that don't have children.
287 childHost->addChild(m_contentsLayer);
290 for (size_t i = 0; i < m_children.size(); ++i)
291 childHost->addChild(m_children[i]->platformLayer());
293 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
294 childHost->addChild(m_linkHighlights[i]->layer());
297 void GraphicsLayer::updateLayerIsDrawable()
299 // For the rest of the accelerated compositor code, there is no reason to make a
300 // distinction between drawsContent and contentsVisible. So, for m_layer->layer(), these two
301 // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
302 // so it is only given contentsVisible.
304 m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
305 if (WebLayer* contentsLayer = contentsLayerIfRegistered())
306 contentsLayer->setDrawsContent(m_contentsVisible);
308 if (m_drawsContent) {
309 m_layer->layer()->invalidate();
310 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
311 m_linkHighlights[i]->invalidate();
315 void GraphicsLayer::updateContentsRect()
317 WebLayer* contentsLayer = contentsLayerIfRegistered();
321 contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
322 contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
324 if (m_contentsClippingMaskLayer) {
325 if (m_contentsClippingMaskLayer->size() != m_contentsRect.size()) {
326 m_contentsClippingMaskLayer->setSize(m_contentsRect.size());
327 m_contentsClippingMaskLayer->setNeedsDisplay();
329 m_contentsClippingMaskLayer->setPosition(FloatPoint());
330 m_contentsClippingMaskLayer->setOffsetFromRenderer(offsetFromRenderer() + IntSize(m_contentsRect.location().x(), m_contentsRect.location().y()));
334 static HashSet<int>* s_registeredLayerSet;
336 void GraphicsLayer::registerContentsLayer(WebLayer* layer)
338 if (!s_registeredLayerSet)
339 s_registeredLayerSet = new HashSet<int>;
340 if (s_registeredLayerSet->contains(layer->id()))
342 s_registeredLayerSet->add(layer->id());
345 void GraphicsLayer::unregisterContentsLayer(WebLayer* layer)
347 ASSERT(s_registeredLayerSet);
348 if (!s_registeredLayerSet->contains(layer->id()))
350 s_registeredLayerSet->remove(layer->id());
353 void GraphicsLayer::setContentsTo(WebLayer* layer)
355 bool childrenChanged = false;
357 ASSERT(s_registeredLayerSet);
358 if (!s_registeredLayerSet->contains(layer->id()))
360 if (m_contentsLayerId != layer->id()) {
361 setupContentsLayer(layer);
362 childrenChanged = true;
364 updateContentsRect();
366 if (m_contentsLayer) {
367 childrenChanged = true;
369 // The old contents layer will be removed via updateChildList.
371 m_contentsLayerId = 0;
379 void GraphicsLayer::setupContentsLayer(WebLayer* contentsLayer)
381 ASSERT(contentsLayer);
382 m_contentsLayer = contentsLayer;
383 m_contentsLayerId = m_contentsLayer->id();
385 m_contentsLayer->setWebLayerClient(this);
386 m_contentsLayer->setTransformOrigin(FloatPoint3D());
387 m_contentsLayer->setUseParentBackfaceVisibility(true);
389 // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
390 // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
391 m_contentsLayer->setDrawsContent(m_contentsVisible);
393 // Insert the content layer first. Video elements require this, because they have
394 // shadow content that must display in front of the video.
395 m_layer->layer()->insertChild(m_contentsLayer, 0);
396 WebLayer* borderWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
397 m_contentsLayer->setMaskLayer(borderWebLayer);
399 m_contentsLayer->setRenderingContext(m_3dRenderingContext);
402 void GraphicsLayer::clearContentsLayerIfUnregistered()
404 if (!m_contentsLayerId || s_registeredLayerSet->contains(m_contentsLayerId))
408 m_contentsLayerId = 0;
411 GraphicsLayerDebugInfo& GraphicsLayer::debugInfo()
416 WebGraphicsLayerDebugInfo* GraphicsLayer::takeDebugInfoFor(WebLayer* layer)
418 GraphicsLayerDebugInfo* clone = m_debugInfo.clone();
419 clone->setDebugName(debugName(layer));
423 WebLayer* GraphicsLayer::contentsLayerIfRegistered()
425 clearContentsLayerIfUnregistered();
426 return m_contentsLayer;
429 void GraphicsLayer::resetTrackedPaintInvalidations()
431 repaintRectMap().remove(this);
434 void GraphicsLayer::addRepaintRect(const FloatRect& repaintRect)
436 if (m_client->isTrackingPaintInvalidations()) {
437 RepaintMap::iterator repaintIt = repaintRectMap().find(this);
438 if (repaintIt == repaintRectMap().end()) {
439 Vector<FloatRect> repaintRects;
440 repaintRects.append(repaintRect);
441 repaintRectMap().set(this, repaintRects);
443 Vector<FloatRect>& repaintRects = repaintIt->value;
444 repaintRects.append(repaintRect);
449 static bool compareFloatRects(const FloatRect& a, const FloatRect& b)
452 return a.x() > b.x();
454 return a.y() > b.y();
455 if (a.width() != b.width())
456 return a.width() > b.width();
457 return a.height() > b.height();
460 template <typename T>
461 static PassRefPtr<JSONArray> pointAsJSONArray(const T& point)
463 RefPtr<JSONArray> array = adoptRef(new JSONArray);
464 array->pushNumber(point.x());
465 array->pushNumber(point.y());
469 template <typename T>
470 static PassRefPtr<JSONArray> sizeAsJSONArray(const T& size)
472 RefPtr<JSONArray> array = adoptRef(new JSONArray);
473 array->pushNumber(size.width());
474 array->pushNumber(size.height());
478 template <typename T>
479 static PassRefPtr<JSONArray> rectAsJSONArray(const T& rect)
481 RefPtr<JSONArray> array = adoptRef(new JSONArray);
482 array->pushNumber(rect.x());
483 array->pushNumber(rect.y());
484 array->pushNumber(rect.width());
485 array->pushNumber(rect.height());
489 static double roundCloseToZero(double number)
491 return std::abs(number) < 1e-7 ? 0 : number;
494 static PassRefPtr<JSONArray> transformAsJSONArray(const TransformationMatrix& t)
496 RefPtr<JSONArray> array = adoptRef(new JSONArray);
498 RefPtr<JSONArray> row = adoptRef(new JSONArray);
499 row->pushNumber(roundCloseToZero(t.m11()));
500 row->pushNumber(roundCloseToZero(t.m12()));
501 row->pushNumber(roundCloseToZero(t.m13()));
502 row->pushNumber(roundCloseToZero(t.m14()));
503 array->pushArray(row);
506 RefPtr<JSONArray> row = adoptRef(new JSONArray);
507 row->pushNumber(roundCloseToZero(t.m21()));
508 row->pushNumber(roundCloseToZero(t.m22()));
509 row->pushNumber(roundCloseToZero(t.m23()));
510 row->pushNumber(roundCloseToZero(t.m24()));
511 array->pushArray(row);
514 RefPtr<JSONArray> row = adoptRef(new JSONArray);
515 row->pushNumber(roundCloseToZero(t.m31()));
516 row->pushNumber(roundCloseToZero(t.m32()));
517 row->pushNumber(roundCloseToZero(t.m33()));
518 row->pushNumber(roundCloseToZero(t.m34()));
519 array->pushArray(row);
522 RefPtr<JSONArray> row = adoptRef(new JSONArray);
523 row->pushNumber(roundCloseToZero(t.m41()));
524 row->pushNumber(roundCloseToZero(t.m42()));
525 row->pushNumber(roundCloseToZero(t.m43()));
526 row->pushNumber(roundCloseToZero(t.m44()));
527 array->pushArray(row);
532 static String pointerAsString(const void* ptr)
539 PassRefPtr<JSONObject> GraphicsLayer::layerTreeAsJSON(LayerTreeFlags flags, RenderingContextMap& renderingContextMap) const
541 RefPtr<JSONObject> json = adoptRef(new JSONObject);
543 if (flags & LayerTreeIncludesDebugInfo) {
544 json->setString("this", pointerAsString(this));
545 json->setString("debugName", m_client->debugName(this));
548 if (m_position != FloatPoint())
549 json->setArray("position", pointAsJSONArray(m_position));
551 if (m_hasTransformOrigin && m_transformOrigin != FloatPoint3D(m_size.width() * 0.5f, m_size.height() * 0.5f, 0))
552 json->setArray("transformOrigin", pointAsJSONArray(m_transformOrigin));
554 if (m_size != IntSize())
555 json->setArray("bounds", sizeAsJSONArray(m_size));
558 json->setNumber("opacity", m_opacity);
560 if (m_blendMode != WebBlendModeNormal)
561 json->setString("blendMode", compositeOperatorName(CompositeSourceOver, m_blendMode));
563 if (m_isRootForIsolatedGroup)
564 json->setBoolean("isolate", m_isRootForIsolatedGroup);
566 if (m_contentsOpaque)
567 json->setBoolean("contentsOpaque", m_contentsOpaque);
569 if (!m_shouldFlattenTransform)
570 json->setBoolean("shouldFlattenTransform", m_shouldFlattenTransform);
572 if (m_3dRenderingContext) {
573 RenderingContextMap::const_iterator it = renderingContextMap.find(m_3dRenderingContext);
574 int contextId = renderingContextMap.size() + 1;
575 if (it == renderingContextMap.end())
576 renderingContextMap.set(m_3dRenderingContext, contextId);
578 contextId = it->value;
580 json->setNumber("3dRenderingContext", contextId);
584 json->setBoolean("drawsContent", m_drawsContent);
586 if (!m_contentsVisible)
587 json->setBoolean("contentsVisible", m_contentsVisible);
589 if (!m_backfaceVisibility)
590 json->setString("backfaceVisibility", m_backfaceVisibility ? "visible" : "hidden");
592 if (flags & LayerTreeIncludesDebugInfo)
593 json->setString("client", pointerAsString(m_client));
595 if (m_backgroundColor.alpha())
596 json->setString("backgroundColor", m_backgroundColor.nameForRenderTreeAsText());
598 if (!m_transform.isIdentity())
599 json->setArray("transform", transformAsJSONArray(m_transform));
602 json->setObject("replicaLayer", m_replicaLayer->layerTreeAsJSON(flags, renderingContextMap));
604 if (m_replicatedLayer)
605 json->setString("replicatedLayer", flags & LayerTreeIncludesDebugInfo ? pointerAsString(m_replicatedLayer) : "");
607 if ((flags & LayerTreeIncludesPaintInvalidationRects) && repaintRectMap().contains(this) && !repaintRectMap().get(this).isEmpty()) {
608 Vector<FloatRect> repaintRectsCopy = repaintRectMap().get(this);
609 std::sort(repaintRectsCopy.begin(), repaintRectsCopy.end(), &compareFloatRects);
610 RefPtr<JSONArray> repaintRectsJSON = adoptRef(new JSONArray);
611 for (size_t i = 0; i < repaintRectsCopy.size(); ++i) {
612 if (repaintRectsCopy[i].isEmpty())
614 repaintRectsJSON->pushArray(rectAsJSONArray(repaintRectsCopy[i]));
616 json->setArray("repaintRects", repaintRectsJSON);
619 if ((flags & LayerTreeIncludesPaintingPhases) && m_paintingPhase) {
620 RefPtr<JSONArray> paintingPhasesJSON = adoptRef(new JSONArray);
621 if (m_paintingPhase & GraphicsLayerPaintBackground)
622 paintingPhasesJSON->pushString("GraphicsLayerPaintBackground");
623 if (m_paintingPhase & GraphicsLayerPaintForeground)
624 paintingPhasesJSON->pushString("GraphicsLayerPaintForeground");
625 if (m_paintingPhase & GraphicsLayerPaintMask)
626 paintingPhasesJSON->pushString("GraphicsLayerPaintMask");
627 if (m_paintingPhase & GraphicsLayerPaintChildClippingMask)
628 paintingPhasesJSON->pushString("GraphicsLayerPaintChildClippingMask");
629 if (m_paintingPhase & GraphicsLayerPaintOverflowContents)
630 paintingPhasesJSON->pushString("GraphicsLayerPaintOverflowContents");
631 if (m_paintingPhase & GraphicsLayerPaintCompositedScroll)
632 paintingPhasesJSON->pushString("GraphicsLayerPaintCompositedScroll");
633 json->setArray("paintingPhases", paintingPhasesJSON);
636 if (flags & LayerTreeIncludesClipAndScrollParents) {
637 if (m_hasScrollParent)
638 json->setBoolean("hasScrollParent", true);
640 json->setBoolean("hasClipParent", true);
643 if (flags & LayerTreeIncludesDebugInfo) {
644 RefPtr<JSONArray> compositingReasonsJSON = adoptRef(new JSONArray);
645 for (size_t i = 0; i < kNumberOfCompositingReasons; ++i) {
646 if (m_debugInfo.compositingReasons() & kCompositingReasonStringMap[i].reason)
647 compositingReasonsJSON->pushString(kCompositingReasonStringMap[i].description);
649 json->setArray("compositingReasons", compositingReasonsJSON);
652 if (m_children.size()) {
653 RefPtr<JSONArray> childrenJSON = adoptRef(new JSONArray);
654 for (size_t i = 0; i < m_children.size(); i++)
655 childrenJSON->pushObject(m_children[i]->layerTreeAsJSON(flags, renderingContextMap));
656 json->setArray("children", childrenJSON);
662 String GraphicsLayer::layerTreeAsText(LayerTreeFlags flags) const
664 RenderingContextMap renderingContextMap;
665 RefPtr<JSONObject> json = layerTreeAsJSON(flags, renderingContextMap);
666 return json->toPrettyJSONString();
669 String GraphicsLayer::debugName(WebLayer* webLayer) const
675 String highlightDebugName;
676 for (size_t i = 0; i < m_linkHighlights.size(); ++i) {
677 if (webLayer == m_linkHighlights[i]->layer()) {
678 highlightDebugName = "LinkHighlight[" + String::number(i) + "] for " + m_client->debugName(this);
683 if (webLayer == m_contentsLayer) {
684 name = "ContentsLayer for " + m_client->debugName(this);
685 } else if (!highlightDebugName.isEmpty()) {
686 name = highlightDebugName;
687 } else if (webLayer == m_layer->layer()) {
688 name = m_client->debugName(this);
690 ASSERT_NOT_REACHED();
695 void GraphicsLayer::setCompositingReasons(CompositingReasons reasons)
697 m_debugInfo.setCompositingReasons(reasons);
700 void GraphicsLayer::setOwnerNodeId(int nodeId)
702 m_debugInfo.setOwnerNodeId(nodeId);
705 void GraphicsLayer::setPosition(const FloatPoint& point)
708 platformLayer()->setPosition(m_position);
711 void GraphicsLayer::setSize(const FloatSize& size)
713 // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
714 // avoid those assertions.
715 // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
716 FloatSize clampedSize = size;
717 if (clampedSize.width() < 0 || clampedSize.height() < 0)
718 clampedSize = FloatSize();
720 if (clampedSize == m_size)
723 m_size = clampedSize;
725 m_layer->layer()->setBounds(flooredIntSize(m_size));
726 // Note that we don't resize m_contentsLayer. It's up the caller to do that.
729 void GraphicsLayer::setTransform(const TransformationMatrix& transform)
731 m_transform = transform;
732 platformLayer()->setTransform(TransformationMatrix::toSkMatrix44(m_transform));
735 void GraphicsLayer::setTransformOrigin(const FloatPoint3D& transformOrigin)
737 m_hasTransformOrigin = true;
738 m_transformOrigin = transformOrigin;
739 platformLayer()->setTransformOrigin(transformOrigin);
742 void GraphicsLayer::setShouldFlattenTransform(bool shouldFlatten)
744 if (shouldFlatten == m_shouldFlattenTransform)
747 m_shouldFlattenTransform = shouldFlatten;
749 m_layer->layer()->setShouldFlattenTransform(shouldFlatten);
752 void GraphicsLayer::setRenderingContext(int context)
754 if (m_3dRenderingContext == context)
757 m_3dRenderingContext = context;
758 m_layer->layer()->setRenderingContext(context);
761 m_contentsLayer->setRenderingContext(m_3dRenderingContext);
764 void GraphicsLayer::setMasksToBounds(bool masksToBounds)
766 m_masksToBounds = masksToBounds;
767 m_layer->layer()->setMasksToBounds(m_masksToBounds);
770 void GraphicsLayer::setDrawsContent(bool drawsContent)
772 // Note carefully this early-exit is only correct because we also properly call
773 // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
774 if (drawsContent == m_drawsContent)
777 m_drawsContent = drawsContent;
778 updateLayerIsDrawable();
781 void GraphicsLayer::setContentsVisible(bool contentsVisible)
783 // Note carefully this early-exit is only correct because we also properly call
784 // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
785 if (contentsVisible == m_contentsVisible)
788 m_contentsVisible = contentsVisible;
789 updateLayerIsDrawable();
792 void GraphicsLayer::setClipParent(WebLayer* parent)
794 m_hasClipParent = !!parent;
795 m_layer->layer()->setClipParent(parent);
798 void GraphicsLayer::setScrollParent(WebLayer* parent)
800 m_hasScrollParent = !!parent;
801 m_layer->layer()->setScrollParent(parent);
804 void GraphicsLayer::setBackgroundColor(const Color& color)
806 if (color == m_backgroundColor)
809 m_backgroundColor = color;
810 m_layer->layer()->setBackgroundColor(m_backgroundColor.rgb());
813 void GraphicsLayer::setContentsOpaque(bool opaque)
815 m_contentsOpaque = opaque;
816 m_layer->layer()->setOpaque(m_contentsOpaque);
817 m_contentLayerDelegate->setOpaque(m_contentsOpaque);
818 clearContentsLayerIfUnregistered();
820 m_contentsLayer->setOpaque(opaque);
823 void GraphicsLayer::setMaskLayer(GraphicsLayer* maskLayer)
825 if (maskLayer == m_maskLayer)
828 m_maskLayer = maskLayer;
829 WebLayer* maskWebLayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
830 m_layer->layer()->setMaskLayer(maskWebLayer);
833 void GraphicsLayer::setContentsClippingMaskLayer(GraphicsLayer* contentsClippingMaskLayer)
835 if (contentsClippingMaskLayer == m_contentsClippingMaskLayer)
838 m_contentsClippingMaskLayer = contentsClippingMaskLayer;
839 WebLayer* contentsLayer = contentsLayerIfRegistered();
842 WebLayer* contentsClippingMaskWebLayer = m_contentsClippingMaskLayer ? m_contentsClippingMaskLayer->platformLayer() : 0;
843 contentsLayer->setMaskLayer(contentsClippingMaskWebLayer);
844 updateContentsRect();
847 void GraphicsLayer::setBackfaceVisibility(bool visible)
849 m_backfaceVisibility = visible;
850 m_layer->setDoubleSided(m_backfaceVisibility);
853 void GraphicsLayer::setOpacity(float opacity)
855 float clampedOpacity = std::max(std::min(opacity, 1.0f), 0.0f);
856 m_opacity = clampedOpacity;
857 platformLayer()->setOpacity(opacity);
860 void GraphicsLayer::setBlendMode(WebBlendMode blendMode)
862 if (m_blendMode == blendMode)
864 m_blendMode = blendMode;
865 platformLayer()->setBlendMode(WebBlendMode(blendMode));
868 void GraphicsLayer::setIsRootForIsolatedGroup(bool isolated)
870 if (m_isRootForIsolatedGroup == isolated)
872 m_isRootForIsolatedGroup = isolated;
873 platformLayer()->setIsRootForIsolatedGroup(isolated);
876 void GraphicsLayer::setContentsNeedsDisplay()
878 if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
879 contentsLayer->invalidate();
880 addRepaintRect(m_contentsRect);
884 void GraphicsLayer::setNeedsDisplay()
886 if (drawsContent()) {
887 m_layer->layer()->invalidate();
888 addRepaintRect(FloatRect(FloatPoint(), m_size));
889 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
890 m_linkHighlights[i]->invalidate();
894 void GraphicsLayer::setNeedsDisplayInRect(const IntRect& rect, PaintInvalidationReason invalidationReason)
896 if (drawsContent()) {
897 m_layer->layer()->invalidateRect(rect);
898 if (firstPaintInvalidationTrackingEnabled())
899 m_debugInfo.appendAnnotatedInvalidateRect(rect, invalidationReason);
900 addRepaintRect(rect);
901 for (size_t i = 0; i < m_linkHighlights.size(); ++i)
902 m_linkHighlights[i]->invalidate();
906 void GraphicsLayer::setContentsRect(const IntRect& rect)
908 if (rect == m_contentsRect)
911 m_contentsRect = rect;
912 updateContentsRect();
915 void GraphicsLayer::setContentsToImage(Image* image)
917 RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
920 m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer());
921 registerContentsLayer(m_imageLayer->layer());
923 m_imageLayer->setImageBitmap(nativeImage->bitmap());
924 m_imageLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
925 updateContentsRect();
928 unregisterContentsLayer(m_imageLayer->layer());
929 m_imageLayer.clear();
933 setContentsTo(m_imageLayer ? m_imageLayer->layer() : 0);
936 void GraphicsLayer::setContentsToNinePatch(Image* image, const IntRect& aperture)
938 if (m_ninePatchLayer) {
939 unregisterContentsLayer(m_ninePatchLayer->layer());
940 m_ninePatchLayer.clear();
942 RefPtr<NativeImageSkia> nativeImage = image ? image->nativeImageForCurrentFrame() : nullptr;
944 m_ninePatchLayer = adoptPtr(Platform::current()->compositorSupport()->createNinePatchLayer());
945 const SkBitmap& bitmap = nativeImage->bitmap();
946 int borderWidth = bitmap.width() - aperture.width();
947 int borderHeight = bitmap.height() - aperture.height();
948 WebRect border(aperture.x(), aperture.y(), borderWidth, borderHeight);
950 m_ninePatchLayer->setBitmap(bitmap);
951 m_ninePatchLayer->setAperture(aperture);
952 m_ninePatchLayer->setBorder(border);
954 m_ninePatchLayer->layer()->setOpaque(image->currentFrameKnownToBeOpaque());
955 registerContentsLayer(m_ninePatchLayer->layer());
957 setContentsTo(m_ninePatchLayer ? m_ninePatchLayer->layer() : 0);
960 bool GraphicsLayer::addAnimation(PassOwnPtr<WebCompositorAnimation> popAnimation)
962 OwnPtr<WebCompositorAnimation> animation(popAnimation);
964 platformLayer()->setAnimationDelegate(this);
966 // Remove any existing animations with the same animation id and target property.
967 platformLayer()->removeAnimation(animation->id(), animation->targetProperty());
968 return platformLayer()->addAnimation(animation.leakPtr());
971 void GraphicsLayer::pauseAnimation(int animationId, double timeOffset)
973 platformLayer()->pauseAnimation(animationId, timeOffset);
976 void GraphicsLayer::removeAnimation(int animationId)
978 platformLayer()->removeAnimation(animationId);
981 WebLayer* GraphicsLayer::platformLayer() const
983 return m_layer->layer();
986 void GraphicsLayer::setFilters(const FilterOperations& filters)
988 SkiaImageFilterBuilder builder;
989 OwnPtr<WebFilterOperations> webFilters = adoptPtr(Platform::current()->compositorSupport()->createFilterOperations());
990 FilterOutsets outsets = filters.outsets();
991 builder.setCropOffset(FloatSize(outsets.left(), outsets.top()));
992 builder.buildFilterOperations(filters, webFilters.get());
993 m_layer->layer()->setFilters(*webFilters);
996 void GraphicsLayer::setPaintingPhase(GraphicsLayerPaintingPhase phase)
998 if (m_paintingPhase == phase)
1000 m_paintingPhase = phase;
1004 void GraphicsLayer::addLinkHighlight(LinkHighlightClient* linkHighlight)
1006 ASSERT(linkHighlight && !m_linkHighlights.contains(linkHighlight));
1007 m_linkHighlights.append(linkHighlight);
1008 linkHighlight->layer()->setWebLayerClient(this);
1012 void GraphicsLayer::removeLinkHighlight(LinkHighlightClient* linkHighlight)
1014 m_linkHighlights.remove(m_linkHighlights.find(linkHighlight));
1018 void GraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea, bool isViewport)
1020 if (m_scrollableArea == scrollableArea)
1023 m_scrollableArea = scrollableArea;
1025 // Viewport scrolling may involve pinch zoom and gets routed through
1026 // WebViewImpl explicitly rather than via GraphicsLayer::didScroll.
1028 m_layer->layer()->setScrollClient(0);
1030 m_layer->layer()->setScrollClient(this);
1033 void GraphicsLayer::paint(GraphicsContext& context, const IntRect& clip)
1035 paintGraphicsLayerContents(context, clip);
1039 void GraphicsLayer::notifyAnimationStarted(double monotonicTime, int group)
1042 m_client->notifyAnimationStarted(this, monotonicTime, group);
1045 void GraphicsLayer::notifyAnimationFinished(double, int)
1049 void GraphicsLayer::didScroll()
1051 if (m_scrollableArea) {
1052 DoublePoint newPosition = m_scrollableArea->minimumScrollPosition() + toDoubleSize(m_layer->layer()->scrollPositionDouble());
1053 // FIXME: Remove the toFloatPoint(). crbug.com/414283.
1054 m_scrollableArea->scrollToOffsetWithoutAnimation(toFloatPoint(newPosition));
1058 } // namespace blink
1061 void showGraphicsLayerTree(const blink::GraphicsLayer* layer)
1066 String output = layer->layerTreeAsText(blink::LayerTreeIncludesDebugInfo);
1067 fprintf(stderr, "%s\n", output.utf8().data());