2 * Copyright (C) 2009, 2010, 2011 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.
28 #if USE(ACCELERATED_COMPOSITING)
30 #include "RenderLayerBacking.h"
32 #include "AnimationController.h"
33 #include "CanvasRenderingContext.h"
34 #include "CSSPropertyNames.h"
35 #include "CachedImage.h"
37 #include "FontCache.h"
38 #include "FrameView.h"
39 #include "GraphicsContext.h"
40 #include "GraphicsLayer.h"
41 #include "HTMLCanvasElement.h"
42 #include "HTMLIFrameElement.h"
43 #include "HTMLMediaElement.h"
44 #include "HTMLNames.h"
45 #include "InspectorInstrumentation.h"
46 #include "KeyframeList.h"
47 #include "PluginViewBase.h"
48 #include "RenderApplet.h"
49 #include "RenderIFrame.h"
50 #include "RenderImage.h"
51 #include "RenderLayerCompositor.h"
52 #include "RenderEmbeddedObject.h"
53 #include "RenderVideo.h"
54 #include "RenderView.h"
55 #include "ScrollingCoordinator.h"
57 #include "StyleResolver.h"
58 #include "TiledBacking.h"
59 #include "WebCoreMemoryInstrumentation.h"
60 #include <wtf/CurrentTime.h>
61 #include <wtf/text/StringBuilder.h>
63 #if ENABLE(CSS_FILTERS)
64 #include "FilterEffectRenderer.h"
65 #if ENABLE(CSS_SHADERS)
66 #include "CustomFilterOperation.h"
70 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
71 #include "GraphicsContext3D.h"
78 using namespace HTMLNames;
80 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
81 static IntRect clipBox(RenderBox* renderer);
83 static inline bool isAcceleratedCanvas(RenderObject* renderer)
85 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
86 if (renderer->isCanvas()) {
87 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
88 if (CanvasRenderingContext* context = canvas->renderingContext())
89 return context->isAccelerated();
92 UNUSED_PARAM(renderer);
97 // Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor.
98 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer* layer)
100 Page* page = layer->renderer()->frame()->page();
104 return page->scrollingCoordinator();
107 bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
109 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
110 : m_owningLayer(layer)
112 , m_artificiallyInflatedBounds(false)
113 , m_boundsConstrainedByClipping(false)
114 , m_isMainFrameRenderViewLayer(false)
115 , m_usingTiledCacheLayer(false)
116 , m_requiresOwnBackingStore(true)
117 #if ENABLE(CSS_FILTERS)
118 , m_canCompositeFilters(false)
120 , m_backgroundLayerPaintsFixedRootBackground(false)
122 if (layer->isRootLayer()) {
123 Frame* frame = toRenderView(renderer())->frameView()->frame();
124 Page* page = frame ? frame->page() : 0;
125 if (page && frame && page->mainFrame() == frame) {
126 m_isMainFrameRenderViewLayer = true;
129 // FIXME: It's a little weird that we base this decision on whether there's a scrolling coordinator or not.
130 if (page->scrollingCoordinator())
131 m_usingTiledCacheLayer = true;
136 createPrimaryGraphicsLayer();
138 if (m_usingTiledCacheLayer) {
139 TiledBacking* tiledBacking = this->tiledBacking();
140 if (Page* page = renderer()->frame()->page()) {
141 Frame* frame = renderer()->frame();
142 tiledBacking->setIsInWindow(page->isInWindow());
144 if (m_isMainFrameRenderViewLayer)
145 tiledBacking->setUnparentsOffscreenTiles(true);
147 tiledBacking->setScrollingPerformanceLoggingEnabled(frame->settings() && frame->settings()->scrollingPerformanceLoggingEnabled());
148 adjustTileCacheCoverage();
153 RenderLayerBacking::~RenderLayerBacking()
155 updateClippingLayers(false, false);
156 updateOverflowControlsLayers(false, false, false);
157 updateForegroundLayer(false);
158 updateBackgroundLayer(false);
159 updateMaskLayer(false);
160 updateScrollingLayers(false);
161 detachFromScrollingCoordinator();
162 destroyGraphicsLayers();
165 PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
167 GraphicsLayerFactory* graphicsLayerFactory = 0;
168 if (Page* page = renderer()->frame()->page())
169 graphicsLayerFactory = page->chrome()->client()->graphicsLayerFactory();
171 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
174 graphicsLayer->setName(name);
178 graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned());
180 #if PLATFORM(MAC) && USE(CA)
181 graphicsLayer->setAcceleratesDrawing(compositor()->acceleratedDrawingEnabled());
184 return graphicsLayer.release();
187 bool RenderLayerBacking::shouldUseTileCache(const GraphicsLayer*) const
189 return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
192 TiledBacking* RenderLayerBacking::tiledBacking() const
194 return m_graphicsLayer->tiledBacking();
197 void RenderLayerBacking::adjustTileCacheCoverage()
199 if (!m_usingTiledCacheLayer)
202 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
204 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
205 Frame* frame = renderer()->frame();
207 FrameView* frameView = frame->view();
208 if (frameView->horizontalScrollbarMode() != ScrollbarAlwaysOff)
209 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
211 if (frameView->verticalScrollbarMode() != ScrollbarAlwaysOff)
212 tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
214 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
215 // Ask our TiledBacking for large tiles unless the only reason we're main-thread-scrolling
216 // is a page overlay (find-in-page, the Web Inspector highlight mechanism, etc.).
217 if (scrollingCoordinator->mainThreadScrollingReasons() & ~ScrollingCoordinator::ForcedOnMainThread)
218 tileCoverage |= TiledBacking::CoverageForSlowScrolling;
222 tiledBacking()->setTileCoverage(tileCoverage);
225 void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
227 m_graphicsLayer->setShowDebugBorder(showBorder);
228 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
230 if (m_ancestorClippingLayer)
231 m_ancestorClippingLayer->setShowDebugBorder(showBorder);
233 if (m_foregroundLayer) {
234 m_foregroundLayer->setShowDebugBorder(showBorder);
235 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
238 if (m_contentsContainmentLayer)
239 m_contentsContainmentLayer->setShowDebugBorder(showBorder);
241 if (m_backgroundLayer) {
242 m_backgroundLayer->setShowDebugBorder(showBorder);
243 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
247 m_maskLayer->setShowDebugBorder(showBorder);
248 m_maskLayer->setShowRepaintCounter(showRepaintCounter);
251 if (m_layerForHorizontalScrollbar)
252 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
254 if (m_layerForVerticalScrollbar)
255 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
257 if (m_layerForScrollCorner)
258 m_layerForScrollCorner->setShowDebugBorder(showBorder);
260 if (m_scrollingLayer)
261 m_scrollingLayer->setShowDebugBorder(showBorder);
263 if (m_scrollingContentsLayer) {
264 m_scrollingContentsLayer->setShowDebugBorder(showBorder);
265 m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
269 void RenderLayerBacking::createPrimaryGraphicsLayer()
273 layerName = m_owningLayer->name();
276 // The call to createGraphicsLayer ends calling back into here as
277 // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want
278 // the tile cache on our main layer. This is pretty ugly, but saves us from
279 // exposing the API to all clients.
281 m_creatingPrimaryGraphicsLayer = true;
282 m_graphicsLayer = createGraphicsLayer(layerName);
283 m_creatingPrimaryGraphicsLayer = false;
285 if (m_usingTiledCacheLayer)
286 m_childContainmentLayer = createGraphicsLayer("TileCache Flattening Layer");
288 if (m_isMainFrameRenderViewLayer) {
289 m_graphicsLayer->setContentsOpaque(true);
290 m_graphicsLayer->setAppliesPageScale();
293 #if PLATFORM(MAC) && USE(CA)
294 if (!compositor()->acceleratedDrawingEnabled() && renderer()->isCanvas()) {
295 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node());
296 if (canvas->shouldAccelerate(canvas->size()))
297 m_graphicsLayer->setAcceleratesDrawing(true);
301 updateOpacity(renderer()->style());
302 updateTransform(renderer()->style());
303 #if ENABLE(CSS_FILTERS)
304 updateFilters(renderer()->style());
306 #if ENABLE(CSS_COMPOSITING)
307 updateLayerBlendMode(renderer()->style());
311 void RenderLayerBacking::destroyGraphicsLayers()
314 m_graphicsLayer->removeFromParent();
316 m_ancestorClippingLayer = nullptr;
317 m_contentsContainmentLayer = nullptr;
318 m_graphicsLayer = nullptr;
319 m_foregroundLayer = nullptr;
320 m_backgroundLayer = nullptr;
321 m_childContainmentLayer = nullptr;
322 m_maskLayer = nullptr;
324 m_scrollingLayer = nullptr;
325 m_scrollingContentsLayer = nullptr;
328 void RenderLayerBacking::updateOpacity(const RenderStyle* style)
330 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
333 void RenderLayerBacking::updateTransform(const RenderStyle* style)
335 // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
336 // baked into it, and we don't want that.
337 TransformationMatrix t;
338 if (m_owningLayer->hasTransform()) {
339 style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
340 makeMatrixRenderable(t, compositor()->canRender3DTransforms());
343 if (m_contentsContainmentLayer) {
344 m_contentsContainmentLayer->setTransform(t);
345 m_graphicsLayer->setTransform(TransformationMatrix());
347 m_graphicsLayer->setTransform(t);
350 #if ENABLE(CSS_FILTERS)
351 void RenderLayerBacking::updateFilters(const RenderStyle* style)
353 m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer()->computeFilterOperations(style));
357 #if ENABLE(CSS_COMPOSITING)
358 void RenderLayerBacking::updateLayerBlendMode(const RenderStyle*)
363 static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
365 RenderStyle* style = renderer->style();
366 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
367 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
370 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
372 for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
373 if (curr->hasTransform() || curr->needsCompositedScrolling())
380 bool RenderLayerBacking::shouldClipCompositedBounds() const
382 // Scrollbar layers use this layer for relative positioning, so don't clip.
383 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
386 if (m_usingTiledCacheLayer)
389 if (!compositor()->compositingConsultsOverlap())
392 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
398 void RenderLayerBacking::updateCompositedBounds()
400 IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
402 // Clip to the size of the document or enclosing overflow-scroll layer.
403 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
404 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
405 if (shouldClipCompositedBounds()) {
406 RenderView* view = m_owningLayer->renderer()->view();
407 RenderLayer* rootLayer = view->layer();
409 LayoutRect clippingBounds;
410 if (renderer()->style()->position() == FixedPosition && renderer()->container() == view)
411 clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect();
413 clippingBounds = view->unscaledDocumentRect();
415 if (m_owningLayer != rootLayer)
416 clippingBounds.intersect(m_owningLayer->backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
419 m_owningLayer->convertToLayerCoords(rootLayer, delta);
420 clippingBounds.move(-delta.x(), -delta.y());
422 layerBounds.intersect(pixelSnappedIntRect(clippingBounds));
423 m_boundsConstrainedByClipping = true;
425 m_boundsConstrainedByClipping = false;
427 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
428 // then we need to ensure that the compositing layer has non-zero size so that we can apply
429 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
430 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
431 layerBounds.setWidth(1);
432 layerBounds.setHeight(1);
433 m_artificiallyInflatedBounds = true;
435 m_artificiallyInflatedBounds = false;
437 setCompositedBounds(layerBounds);
440 void RenderLayerBacking::updateAfterWidgetResize()
442 if (renderer()->isRenderPart()) {
443 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
444 innerCompositor->frameViewDidChangeSize();
445 innerCompositor->frameViewDidChangeLocation(contentsBox().location());
450 void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags)
452 RenderLayerCompositor* layerCompositor = compositor();
453 if (!layerCompositor->compositingLayersNeedRebuild()) {
454 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
455 // position of this layer's GraphicsLayer depends on the position of our compositing
456 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
457 // RenderLayers of that ancestor have been processed via updateLayerPositions().
459 // The solution is to update compositing children of this layer here,
460 // via updateCompositingChildrenGeometry().
461 updateCompositedBounds();
462 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly);
464 if (flags & IsUpdateRoot) {
465 updateGraphicsLayerGeometry();
466 layerCompositor->updateRootLayerPosition();
467 RenderLayer* stackingContainer = m_owningLayer->enclosingStackingContainer();
468 if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer))
469 layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer, flags & CompositingChildrenOnly);
473 if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
474 setContentsNeedDisplay();
477 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
479 RenderLayerCompositor* compositor = this->compositor();
480 RenderObject* renderer = this->renderer();
482 m_owningLayer->updateDescendantDependentFlags();
483 m_owningLayer->updateZOrderLists();
485 bool layerConfigChanged = false;
486 setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(m_owningLayer));
488 // The background layer is currently only used for fixed root backgrounds.
489 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
490 layerConfigChanged = true;
492 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
493 layerConfigChanged = true;
495 bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
497 // Our scrolling layer will clip.
498 if (m_owningLayer->needsCompositedScrolling())
499 needsDescendentsClippingLayer = false;
501 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
502 layerConfigChanged = true;
504 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
505 layerConfigChanged = true;
507 if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling()))
508 layerConfigChanged = true;
510 if (layerConfigChanged)
511 updateInternalHierarchy();
513 if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
514 flatteningLayer->removeFromParent();
515 m_graphicsLayer->addChild(flatteningLayer);
518 if (updateMaskLayer(renderer->hasMask()))
519 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
521 if (m_owningLayer->hasReflection()) {
522 if (m_owningLayer->reflectionLayer()->backing()) {
523 GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer();
524 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
527 m_graphicsLayer->setReplicatedByLayer(0);
529 updateBackgroundColor(isSimpleContainerCompositingLayer());
530 updateRootLayerConfiguration();
532 if (isDirectlyCompositedImage())
533 updateImageContents();
535 if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) {
536 PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderWidget(renderer)->widget());
537 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
540 else if (renderer->isVideo()) {
541 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer->node());
542 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
545 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
546 else if (isAcceleratedCanvas(renderer)) {
547 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
548 if (CanvasRenderingContext* context = canvas->renderingContext())
549 m_graphicsLayer->setContentsToCanvas(context->platformLayer());
550 layerConfigChanged = true;
553 if (renderer->isRenderPart())
554 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
556 return layerConfigChanged;
559 static IntRect clipBox(RenderBox* renderer)
561 LayoutRect result = PaintInfo::infiniteRect();
562 if (renderer->hasOverflowClip())
563 result = renderer->overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
565 if (renderer->hasClip())
566 result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
568 return pixelSnappedIntRect(result);
571 void RenderLayerBacking::updateGraphicsLayerGeometry()
573 // If we haven't built z-order lists yet, wait until later.
574 if (m_owningLayer->isStackingContainer() && m_owningLayer->m_zOrderListsDirty)
577 // Set transform property, if it is not animating. We have to do this here because the transform
578 // is affected by the layer dimensions.
579 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
580 updateTransform(renderer()->style());
582 // Set opacity, if it is not animating.
583 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
584 updateOpacity(renderer()->style());
586 #if ENABLE(CSS_FILTERS)
587 updateFilters(renderer()->style());
590 #if ENABLE(CSS_COMPOSITING)
591 updateLayerBlendMode(renderer()->style());
594 bool isSimpleContainer = isSimpleContainerCompositingLayer();
596 m_owningLayer->updateDescendantDependentFlags();
598 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
599 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
600 // non-compositing visible layers.
601 m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
603 RenderStyle* style = renderer()->style();
604 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
605 bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
606 m_graphicsLayer->setPreserves3D(preserves3D);
607 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
609 RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
611 // We compute everything relative to the enclosing compositing layer.
612 IntRect ancestorCompositingBounds;
614 ASSERT(compAncestor->backing());
615 ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds());
618 IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds());
620 IntRect relativeCompositingBounds(localCompositingBounds);
622 m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta);
623 relativeCompositingBounds.moveBy(delta);
625 IntPoint graphicsLayerParentLocation;
626 if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
627 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
628 // position relative to it.
629 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
630 graphicsLayerParentLocation = clippingBox.location();
631 } else if (compAncestor)
632 graphicsLayerParentLocation = ancestorCompositingBounds.location();
634 graphicsLayerParentLocation = renderer()->view()->documentRect().location();
636 if (compAncestor && compAncestor->needsCompositedScrolling()) {
637 RenderBox* renderBox = toRenderBox(compAncestor->renderer());
638 IntSize scrollOffset = compAncestor->scrolledContentOffset();
639 IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
640 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
643 if (compAncestor && m_ancestorClippingLayer) {
644 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
645 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
646 // for a compositing layer, rootLayer is the layer itself.
647 RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
648 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
649 ASSERT(parentClipRect != PaintInfo::infiniteRect());
650 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
651 m_ancestorClippingLayer->setSize(parentClipRect.size());
653 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
654 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
656 // The primary layer is then parented in, and positioned relative to this clipping layer.
657 graphicsLayerParentLocation = parentClipRect.location();
660 FloatSize contentsSize = relativeCompositingBounds.size();
662 if (m_contentsContainmentLayer) {
663 m_contentsContainmentLayer->setPreserves3D(preserves3D);
664 m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
665 // Use the same size as m_graphicsLayer so transforms behave correctly.
666 m_contentsContainmentLayer->setSize(contentsSize);
667 graphicsLayerParentLocation = relativeCompositingBounds.location();
670 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
671 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
673 FloatSize oldSize = m_graphicsLayer->size();
674 if (oldSize != contentsSize) {
675 m_graphicsLayer->setSize(contentsSize);
676 // Usually invalidation will happen via layout etc, but if we've affected the layer
677 // size by constraining relative to a clipping ancestor or the viewport, we
678 // have to invalidate to avoid showing stretched content.
679 if (m_boundsConstrainedByClipping)
680 m_graphicsLayer->setNeedsDisplay();
682 if (!m_isMainFrameRenderViewLayer)
683 m_graphicsLayer->setContentsOpaque(m_owningLayer->contentsOpaqueInRect(localCompositingBounds));
685 // If we have a layer that clips children, position it.
687 if (GraphicsLayer* clipLayer = clippingLayer()) {
688 clippingBox = clipBox(toRenderBox(renderer()));
689 clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
690 clipLayer->setSize(clippingBox.size());
691 clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
695 if (m_maskLayer->size() != m_graphicsLayer->size()) {
696 m_maskLayer->setSize(m_graphicsLayer->size());
697 m_maskLayer->setNeedsDisplay();
699 m_maskLayer->setPosition(FloatPoint());
700 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
703 if (m_owningLayer->hasTransform()) {
704 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
706 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
707 IntRect layerBounds = IntRect(delta, borderBox.size());
709 // Update properties that depend on layer dimensions
710 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
711 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
712 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
713 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
714 transformOrigin.z());
715 if (m_contentsContainmentLayer)
716 m_contentsContainmentLayer->setAnchorPoint(anchor);
718 m_graphicsLayer->setAnchorPoint(anchor);
720 RenderStyle* style = renderer()->style();
721 GraphicsLayer* clipLayer = clippingLayer();
722 if (style->hasPerspective()) {
723 TransformationMatrix t = owningLayer()->perspectiveTransform();
726 clipLayer->setChildrenTransform(t);
727 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
730 m_graphicsLayer->setChildrenTransform(t);
733 clipLayer->setChildrenTransform(TransformationMatrix());
735 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
738 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
739 if (m_contentsContainmentLayer)
740 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
743 if (m_foregroundLayer) {
744 FloatPoint foregroundPosition;
745 FloatSize foregroundSize = contentsSize;
746 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
747 if (hasClippingLayer()) {
748 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
749 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
750 foregroundSize = FloatSize(clippingBox.size());
751 foregroundOffset = toIntSize(clippingBox.location());
754 m_foregroundLayer->setPosition(foregroundPosition);
755 if (foregroundSize != m_foregroundLayer->size()) {
756 m_foregroundLayer->setSize(foregroundSize);
757 m_foregroundLayer->setNeedsDisplay();
759 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
762 if (m_backgroundLayer) {
763 FloatPoint backgroundPosition;
764 FloatSize backgroundSize = contentsSize;
765 if (backgroundLayerPaintsFixedRootBackground()) {
766 FrameView* frameView = toRenderView(renderer())->frameView();
767 backgroundPosition = IntPoint(frameView->scrollOffsetForFixedPosition());
768 backgroundSize = frameView->visibleContentRect().size();
770 m_backgroundLayer->setPosition(backgroundPosition);
771 if (backgroundSize != m_backgroundLayer->size()) {
772 m_backgroundLayer->setSize(backgroundSize);
773 m_backgroundLayer->setNeedsDisplay();
775 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
778 if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
779 RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
780 reflectionBacking->updateGraphicsLayerGeometry();
782 // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
783 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
784 FloatRect layerBounds = compositedBounds();
785 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
786 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
789 if (m_scrollingLayer) {
790 ASSERT(m_scrollingContentsLayer);
791 RenderBox* renderBox = toRenderBox(renderer());
792 IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
793 IntSize scrollOffset = m_owningLayer->scrolledContentOffset();
795 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
797 m_scrollingLayer->setSize(paddingBox.size());
798 m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
800 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
801 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location()));
803 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
805 IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight());
806 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
807 m_scrollingContentsLayer->setNeedsDisplay();
809 IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset);
810 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
811 compositor()->scrollingLayerDidChange(m_owningLayer);
813 m_scrollingContentsLayer->setSize(scrollSize);
814 // FIXME: The paint offset and the scroll offset should really be separate concepts.
815 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
818 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
819 setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
821 updateContentsRect(isSimpleContainer);
822 updateBackgroundColor(isSimpleContainer);
823 updateDrawsContent(isSimpleContainer);
824 updateAfterWidgetResize();
825 registerScrollingLayers();
828 void RenderLayerBacking::registerScrollingLayers()
830 // Register fixed position layers and their containers with the scrolling coordinator.
831 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
832 if (!scrollingCoordinator)
835 compositor()->updateViewportConstraintStatus(m_owningLayer);
837 // FIXME: it would be nice to avoid all this work if the platform doesn't implement setLayerIsFixedToContainerLayer().
838 if (renderer()->style()->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer))
839 scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true);
841 if (m_ancestorClippingLayer)
842 scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false);
843 scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false);
845 // Page scale is applied as a transform on the root render view layer. Because the scroll
846 // layer is further up in the hierarchy, we need to avoid marking the root render view
847 // layer as a container.
848 bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
849 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
852 void RenderLayerBacking::updateInternalHierarchy()
854 // m_foregroundLayer has to be inserted in the correct order with child layers,
855 // so it's not inserted here.
856 if (m_ancestorClippingLayer)
857 m_ancestorClippingLayer->removeAllChildren();
859 if (m_contentsContainmentLayer) {
860 m_contentsContainmentLayer->removeAllChildren();
861 if (m_ancestorClippingLayer)
862 m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
865 if (m_backgroundLayer)
866 m_contentsContainmentLayer->addChild(m_backgroundLayer.get());
868 m_graphicsLayer->removeFromParent();
869 if (m_contentsContainmentLayer)
870 m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
871 else if (m_ancestorClippingLayer)
872 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
874 if (m_childContainmentLayer) {
875 m_childContainmentLayer->removeFromParent();
876 m_graphicsLayer->addChild(m_childContainmentLayer.get());
879 if (m_scrollingLayer) {
880 GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
881 m_scrollingLayer->removeFromParent();
882 superlayer->addChild(m_scrollingLayer.get());
885 // The clip for child layers does not include space for overflow controls, so they exist as
886 // siblings of the clipping layer if we have one. Normal children of this layer are set as
887 // children of the clipping layer.
888 if (m_layerForHorizontalScrollbar) {
889 m_layerForHorizontalScrollbar->removeFromParent();
890 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
892 if (m_layerForVerticalScrollbar) {
893 m_layerForVerticalScrollbar->removeFromParent();
894 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
896 if (m_layerForScrollCorner) {
897 m_layerForScrollCorner->removeFromParent();
898 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
902 void RenderLayerBacking::updateContentsRect(bool isSimpleContainer)
904 IntRect contentsRect;
905 if (isSimpleContainer && renderer()->hasBackground())
906 contentsRect = backgroundBox();
908 contentsRect = contentsBox();
910 m_graphicsLayer->setContentsRect(contentsRect);
913 void RenderLayerBacking::updateDrawsContent()
915 updateDrawsContent(isSimpleContainerCompositingLayer());
918 void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
920 if (m_scrollingLayer) {
921 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
922 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
923 // m_scrollingLayer never has backing store.
924 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
925 bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
926 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
928 bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
929 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
933 bool hasPaintedContent = !isSimpleContainer && containsPaintedContent();
935 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
936 m_graphicsLayer->setDrawsContent(hasPaintedContent);
937 if (m_foregroundLayer)
938 m_foregroundLayer->setDrawsContent(hasPaintedContent);
940 if (m_backgroundLayer)
941 m_backgroundLayer->setDrawsContent(hasPaintedContent);
944 // Return true if the layers changed.
945 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
947 bool layersChanged = false;
949 if (needsAncestorClip) {
950 if (!m_ancestorClippingLayer) {
951 m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer");
952 m_ancestorClippingLayer->setMasksToBounds(true);
953 layersChanged = true;
955 } else if (m_ancestorClippingLayer) {
956 m_ancestorClippingLayer->removeFromParent();
957 m_ancestorClippingLayer = nullptr;
958 layersChanged = true;
961 if (needsDescendantClip) {
962 if (!m_childContainmentLayer && !m_usingTiledCacheLayer) {
963 m_childContainmentLayer = createGraphicsLayer("Child clipping Layer");
964 m_childContainmentLayer->setMasksToBounds(true);
965 layersChanged = true;
967 } else if (hasClippingLayer()) {
968 m_childContainmentLayer->removeFromParent();
969 m_childContainmentLayer = nullptr;
970 layersChanged = true;
973 return layersChanged;
976 void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
978 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
981 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
983 #if !PLATFORM(CHROMIUM)
984 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
987 return m_owningLayer->horizontalScrollbar();
990 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
992 #if !PLATFORM(CHROMIUM)
993 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
996 return m_owningLayer->verticalScrollbar();
999 bool RenderLayerBacking::requiresScrollCornerLayer() const
1001 #if !PLATFORM(CHROMIUM)
1002 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling())
1005 return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
1008 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1010 bool horizontalScrollbarLayerChanged = false;
1011 if (needsHorizontalScrollbarLayer) {
1012 if (!m_layerForHorizontalScrollbar) {
1013 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1014 horizontalScrollbarLayerChanged = true;
1016 } else if (m_layerForHorizontalScrollbar) {
1017 m_layerForHorizontalScrollbar.clear();
1018 horizontalScrollbarLayerChanged = true;
1021 bool verticalScrollbarLayerChanged = false;
1022 if (needsVerticalScrollbarLayer) {
1023 if (!m_layerForVerticalScrollbar) {
1024 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1025 verticalScrollbarLayerChanged = true;
1027 } else if (m_layerForVerticalScrollbar) {
1028 m_layerForVerticalScrollbar.clear();
1029 verticalScrollbarLayerChanged = true;
1032 bool scrollCornerLayerChanged = false;
1033 if (needsScrollCornerLayer) {
1034 if (!m_layerForScrollCorner) {
1035 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1036 scrollCornerLayerChanged = true;
1038 } else if (m_layerForScrollCorner) {
1039 m_layerForScrollCorner.clear();
1040 scrollCornerLayerChanged = true;
1043 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1044 if (horizontalScrollbarLayerChanged)
1045 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
1046 if (verticalScrollbarLayerChanged)
1047 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
1050 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1053 void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
1055 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1056 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1057 Scrollbar* hBar = m_owningLayer->horizontalScrollbar();
1059 layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1060 layer->setSize(hBar->frameRect().size());
1061 if (layer->hasContentsLayer())
1062 layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
1064 layer->setDrawsContent(hBar && !layer->hasContentsLayer());
1067 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1068 Scrollbar* vBar = m_owningLayer->verticalScrollbar();
1070 layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1071 layer->setSize(vBar->frameRect().size());
1072 if (layer->hasContentsLayer())
1073 layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
1075 layer->setDrawsContent(vBar && !layer->hasContentsLayer());
1078 if (GraphicsLayer* layer = layerForScrollCorner()) {
1079 const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
1080 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1081 layer->setSize(scrollCornerAndResizer.size());
1082 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1086 bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
1088 if (GraphicsLayer* layer = layerForHorizontalScrollbar())
1089 if (!layer->drawsContent())
1092 if (GraphicsLayer* layer = layerForVerticalScrollbar())
1093 if (!layer->drawsContent())
1096 if (GraphicsLayer* layer = layerForScrollCorner())
1097 if (!layer->drawsContent())
1103 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1105 bool layerChanged = false;
1106 if (needsForegroundLayer) {
1107 if (!m_foregroundLayer) {
1110 layerName = m_owningLayer->name() + " (foreground)";
1112 m_foregroundLayer = createGraphicsLayer(layerName);
1113 m_foregroundLayer->setDrawsContent(true);
1114 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1115 layerChanged = true;
1117 } else if (m_foregroundLayer) {
1118 m_foregroundLayer->removeFromParent();
1119 m_foregroundLayer = nullptr;
1120 layerChanged = true;
1124 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1126 return layerChanged;
1129 bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1131 bool layerChanged = false;
1132 if (needsBackgroundLayer) {
1133 if (!m_backgroundLayer) {
1136 layerName = m_owningLayer->name() + " (background)";
1138 m_backgroundLayer = createGraphicsLayer(layerName);
1139 m_backgroundLayer->setDrawsContent(true);
1140 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1141 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1142 layerChanged = true;
1145 if (!m_contentsContainmentLayer) {
1148 layerName = m_owningLayer->name() + " (contents containment)";
1150 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1151 m_contentsContainmentLayer->setAppliesPageScale(true);
1152 m_graphicsLayer->setAppliesPageScale(false);
1153 layerChanged = true;
1156 if (m_backgroundLayer) {
1157 m_backgroundLayer->removeFromParent();
1158 m_backgroundLayer = nullptr;
1159 layerChanged = true;
1161 if (m_contentsContainmentLayer) {
1162 m_contentsContainmentLayer->removeFromParent();
1163 m_contentsContainmentLayer = nullptr;
1164 layerChanged = true;
1165 m_graphicsLayer->setAppliesPageScale(true);
1170 // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption.
1171 if (renderer()->view())
1172 compositor()->fixedRootBackgroundLayerChanged();
1175 return layerChanged;
1178 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
1180 bool layerChanged = false;
1181 if (needsMaskLayer) {
1183 m_maskLayer = createGraphicsLayer("Mask");
1184 m_maskLayer->setDrawsContent(true);
1185 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1186 layerChanged = true;
1188 } else if (m_maskLayer) {
1189 m_maskLayer = nullptr;
1190 layerChanged = true;
1194 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1196 return layerChanged;
1199 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1201 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1203 bool layerChanged = false;
1204 if (needsScrollingLayers) {
1205 if (!m_scrollingLayer) {
1206 // Outer layer which corresponds with the scroll view.
1207 m_scrollingLayer = createGraphicsLayer("Scrolling container");
1208 m_scrollingLayer->setDrawsContent(false);
1209 m_scrollingLayer->setMasksToBounds(true);
1211 // Inner layer which renders the content that scrolls.
1212 m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
1213 m_scrollingContentsLayer->setDrawsContent(true);
1214 m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
1215 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1217 layerChanged = true;
1218 if (scrollingCoordinator)
1219 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
1221 } else if (m_scrollingLayer) {
1222 m_scrollingLayer = nullptr;
1223 m_scrollingContentsLayer = nullptr;
1224 layerChanged = true;
1225 if (scrollingCoordinator)
1226 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
1230 updateInternalHierarchy();
1231 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1232 m_graphicsLayer->setNeedsDisplay();
1233 if (renderer()->view())
1234 compositor()->scrollingLayerDidChange(m_owningLayer);
1237 return layerChanged;
1240 void RenderLayerBacking::attachToScrollingCoordinatorWithParent(RenderLayerBacking* parent)
1242 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1243 if (!scrollingCoordinator)
1246 // FIXME: When we support overflow areas, we will have to refine this for overflow areas that are also
1248 ScrollingNodeType nodeType;
1249 if (renderer()->style()->position() == FixedPosition)
1250 nodeType = FixedNode;
1251 else if (renderer()->style()->position() == StickyPosition)
1252 nodeType = StickyNode;
1254 nodeType = ScrollingNode;
1256 ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0;
1257 m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, m_scrollLayerID ? m_scrollLayerID : scrollingCoordinator->uniqueScrollLayerID(), parentID);
1260 void RenderLayerBacking::detachFromScrollingCoordinator()
1262 // If m_scrollLayerID is 0, then this backing is not attached to the ScrollingCoordinator.
1263 if (!m_scrollLayerID)
1266 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1267 if (!scrollingCoordinator)
1270 scrollingCoordinator->detachFromStateTree(m_scrollLayerID);
1271 m_scrollLayerID = 0;
1274 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1277 if (!m_backgroundLayer)
1278 phase |= GraphicsLayerPaintBackground;
1279 if (!m_foregroundLayer)
1280 phase |= GraphicsLayerPaintForeground;
1282 phase |= GraphicsLayerPaintMask;
1284 if (m_scrollingContentsLayer)
1285 phase &= ~GraphicsLayerPaintForeground;
1287 return static_cast<GraphicsLayerPaintingPhase>(phase);
1290 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1292 float finalOpacity = rendererOpacity;
1294 for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
1295 // We only care about parents that are stacking contexts.
1296 // Recall that opacity creates stacking context.
1297 if (!curr->isStackingContainer())
1300 // If we found a compositing layer, we want to compute opacity
1301 // relative to it. So we can break here.
1302 if (curr->isComposited())
1305 finalOpacity *= curr->renderer()->opacity();
1308 return finalOpacity;
1311 static bool hasBoxDecorations(const RenderStyle* style)
1313 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
1316 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
1318 return hasBoxDecorations(style) || style->hasBackgroundImage();
1321 Color RenderLayerBacking::rendererBackgroundColor() const
1323 RenderObject* backgroundRenderer = renderer();
1324 if (backgroundRenderer->isRoot())
1325 backgroundRenderer = backgroundRenderer->rendererForRootBackground();
1327 return backgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
1330 void RenderLayerBacking::updateBackgroundColor(bool isSimpleContainer)
1332 Color backgroundColor;
1333 if (isSimpleContainer)
1334 backgroundColor = rendererBackgroundColor();
1336 // An unset (invalid) color will remove the solid color.
1337 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
1340 void RenderLayerBacking::updateRootLayerConfiguration()
1342 if (!m_usingTiledCacheLayer)
1345 Color backgroundColor;
1346 bool viewIsTransparent = compositor()->viewHasTransparentBackground(&backgroundColor);
1348 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
1349 m_backgroundLayer->setBackgroundColor(backgroundColor);
1350 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
1352 m_graphicsLayer->setBackgroundColor(Color());
1353 m_graphicsLayer->setContentsOpaque(false);
1355 m_graphicsLayer->setBackgroundColor(backgroundColor);
1356 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
1360 static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer)
1362 if (!GraphicsLayer::supportsBackgroundColorContent())
1365 if (renderer->hasClip())
1368 if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
1371 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
1372 if (renderer->style()->backgroundComposite() != CompositeSourceOver)
1375 if (renderer->style()->backgroundClip() == TextFillBox)
1381 bool RenderLayerBacking::paintsBoxDecorations() const
1383 if (!m_owningLayer->hasVisibleBoxDecorations())
1386 if (!supportsDirectBoxDecorationsComposition(renderer()))
1392 bool RenderLayerBacking::paintsChildren() const
1394 if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
1397 if (hasVisibleNonCompositingDescendantLayers())
1403 static bool isCompositedPlugin(RenderObject* renderer)
1405 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
1408 // A "simple container layer" is a RenderLayer which has no visible content to render.
1409 // It may have no children, or all its children may be themselves composited.
1410 // This is a useful optimization, because it allows us to avoid allocating backing store.
1411 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
1413 RenderObject* renderObject = renderer();
1414 if (renderObject->hasMask()) // masks require special treatment
1417 if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
1420 if (paintsBoxDecorations() || paintsChildren())
1423 if (renderObject->isRenderRegion())
1426 if (renderObject->node() && renderObject->node()->isDocumentNode()) {
1427 // Look to see if the root object has a non-simple background
1428 RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0;
1432 RenderStyle* style = rootObject->style();
1434 // Reject anything that has a border, a border-radius or outline,
1435 // or is not a simple background (no background, or solid color).
1436 if (hasBoxDecorationsOrBackgroundImage(style))
1439 // Now look at the body's renderer.
1440 HTMLElement* body = renderObject->document()->body();
1441 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1445 style = bodyObject->style();
1447 if (hasBoxDecorationsOrBackgroundImage(style))
1454 static bool hasVisibleNonCompositingDescendant(RenderLayer* parent)
1456 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1457 parent->updateLayerListsIfNeeded();
1459 #if !ASSERT_DISABLED
1460 LayerListMutationDetector mutationChecker(parent);
1463 if (Vector<RenderLayer*>* normalFlowList = parent->normalFlowList()) {
1464 size_t listSize = normalFlowList->size();
1465 for (size_t i = 0; i < listSize; ++i) {
1466 RenderLayer* curLayer = normalFlowList->at(i);
1467 if (!curLayer->isComposited()
1468 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
1473 if (parent->isStackingContainer()) {
1474 if (!parent->hasVisibleDescendant())
1477 // Use the m_hasCompositingDescendant bit to optimize?
1478 if (Vector<RenderLayer*>* negZOrderList = parent->negZOrderList()) {
1479 size_t listSize = negZOrderList->size();
1480 for (size_t i = 0; i < listSize; ++i) {
1481 RenderLayer* curLayer = negZOrderList->at(i);
1482 if (!curLayer->isComposited()
1483 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
1488 if (Vector<RenderLayer*>* posZOrderList = parent->posZOrderList()) {
1489 size_t listSize = posZOrderList->size();
1490 for (size_t i = 0; i < listSize; ++i) {
1491 RenderLayer* curLayer = posZOrderList->at(i);
1492 if (!curLayer->isComposited()
1493 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
1502 // Conservative test for having no rendered children.
1503 bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
1505 return hasVisibleNonCompositingDescendant(m_owningLayer);
1508 bool RenderLayerBacking::containsPaintedContent() const
1510 if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
1513 if (isDirectlyCompositedImage())
1516 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1517 // and set background color on the layer in that case, instead of allocating backing store and painting.
1519 if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
1520 return m_owningLayer->hasBoxDecorationsOrBackground();
1522 #if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
1523 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1524 if (isAcceleratedCanvas(renderer()))
1525 return m_owningLayer->hasBoxDecorationsOrBackground();
1531 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1532 // that require painting. Direct compositing saves backing store.
1533 bool RenderLayerBacking::isDirectlyCompositedImage() const
1535 RenderObject* renderObject = renderer();
1537 if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
1540 RenderImage* imageRenderer = toRenderImage(renderObject);
1541 if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
1542 if (!cachedImage->hasImage())
1545 Image* image = cachedImage->imageForRenderer(imageRenderer);
1546 if (!image->isBitmapImage())
1549 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
1555 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
1557 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1558 updateImageContents();
1562 if ((changeType == MaskImageChanged) && m_maskLayer) {
1563 // The composited layer bounds relies on box->maskClipRect(), which changes
1564 // when the mask image becomes available.
1565 updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
1568 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1569 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
1570 m_graphicsLayer->setContentsNeedsDisplay();
1576 void RenderLayerBacking::updateImageContents()
1578 ASSERT(renderer()->isImage());
1579 RenderImage* imageRenderer = toRenderImage(renderer());
1581 CachedImage* cachedImage = imageRenderer->cachedImage();
1585 Image* image = cachedImage->imageForRenderer(imageRenderer);
1589 // We have to wait until the image is fully loaded before setting it on the layer.
1590 if (!cachedImage->isLoaded())
1593 // This is a no-op if the layer doesn't have an inner layer for the image.
1594 m_graphicsLayer->setContentsToImage(image);
1595 bool isSimpleContainer = false;
1596 updateDrawsContent(isSimpleContainer);
1598 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1599 // the image. So we have to kick the animation each time; this has the downside that the
1600 // image will keep animating, even if its layer is not visible.
1601 image->startAnimation();
1604 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
1606 RenderStyle* style = renderer()->style();
1608 FloatPoint3D origin;
1609 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
1610 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
1611 origin.setZ(style->transformOriginZ());
1616 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
1618 RenderStyle* style = renderer()->style();
1620 float boxWidth = borderBox.width();
1621 float boxHeight = borderBox.height();
1624 origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
1625 origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
1630 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1631 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1633 return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1636 IntRect RenderLayerBacking::contentsBox() const
1638 if (!renderer()->isBox())
1641 IntRect contentsRect;
1643 if (renderer()->isVideo()) {
1644 RenderVideo* videoRenderer = toRenderVideo(renderer());
1645 contentsRect = videoRenderer->videoBox();
1648 contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect());
1650 contentsRect.move(contentOffsetInCompostingLayer());
1651 return contentsRect;
1654 static LayoutRect backgroundRectForBox(const RenderBox* box)
1656 EFillBox clip = box->style()->backgroundClip();
1659 return box->borderBoxRect();
1660 case PaddingFillBox:
1661 return box->paddingBoxRect();
1662 case ContentFillBox:
1663 return box->contentBoxRect();
1668 ASSERT_NOT_REACHED();
1669 return LayoutRect();
1672 IntRect RenderLayerBacking::backgroundBox() const
1674 if (!renderer()->isBox())
1677 IntRect pixelSnappedBackgroundBox = pixelSnappedIntRect(backgroundRectForBox(toRenderBox(renderer())));
1678 pixelSnappedBackgroundBox.move(contentOffsetInCompostingLayer());
1679 return pixelSnappedBackgroundBox;
1682 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
1684 if (m_scrollingContentsLayer)
1685 return m_scrollingContentsLayer.get();
1687 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1690 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
1692 if (m_ancestorClippingLayer)
1693 return m_ancestorClippingLayer.get();
1695 if (m_contentsContainmentLayer)
1696 return m_contentsContainmentLayer.get();
1698 return m_graphicsLayer.get();
1701 bool RenderLayerBacking::paintsIntoWindow() const
1703 if (m_usingTiledCacheLayer)
1706 if (m_owningLayer->isRootLayer()) {
1707 #if PLATFORM(BLACKBERRY)
1708 if (compositor()->inForcedCompositingMode())
1712 return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
1718 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
1720 if (requiresOwnBacking == m_requiresOwnBackingStore)
1723 m_requiresOwnBackingStore = requiresOwnBacking;
1725 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
1726 // cached clip rects, so when it changes we have to clear clip rects on descendants.
1727 m_owningLayer->clearClipRectsIncludingDescendants(PaintingClipRects);
1728 m_owningLayer->computeRepaintRectsIncludingDescendants();
1730 compositor()->repaintInCompositedAncestor(m_owningLayer, compositedBounds());
1733 #if ENABLE(CSS_COMPOSITING)
1734 void RenderLayerBacking::setBlendMode(BlendMode)
1739 void RenderLayerBacking::setContentsNeedDisplay()
1741 ASSERT(!paintsIntoCompositedAncestor());
1743 if (m_graphicsLayer && m_graphicsLayer->drawsContent())
1744 m_graphicsLayer->setNeedsDisplay();
1746 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
1747 m_foregroundLayer->setNeedsDisplay();
1749 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
1750 m_backgroundLayer->setNeedsDisplay();
1752 if (m_maskLayer && m_maskLayer->drawsContent())
1753 m_maskLayer->setNeedsDisplay();
1755 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
1756 m_scrollingContentsLayer->setNeedsDisplay();
1759 // r is in the coordinate space of the layer's render object
1760 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
1762 ASSERT(!paintsIntoCompositedAncestor());
1764 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
1765 IntRect layerDirtyRect = r;
1766 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
1767 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
1770 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
1771 IntRect layerDirtyRect = r;
1772 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
1773 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
1776 // FIXME: need to split out repaints for the background.
1777 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
1778 IntRect layerDirtyRect = r;
1779 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer());
1780 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect);
1783 if (m_maskLayer && m_maskLayer->drawsContent()) {
1784 IntRect layerDirtyRect = r;
1785 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
1786 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
1789 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
1790 IntRect layerDirtyRect = r;
1791 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
1792 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
1796 void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context,
1797 const IntRect& paintDirtyRect, // In the coords of rootLayer.
1798 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
1800 if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
1801 ASSERT_NOT_REACHED();
1805 FontCachePurgePreventer fontCachePurgePreventer;
1807 RenderLayer::PaintLayerFlags paintFlags = 0;
1808 if (paintingPhase & GraphicsLayerPaintBackground)
1809 paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase;
1810 if (paintingPhase & GraphicsLayerPaintForeground)
1811 paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
1812 if (paintingPhase & GraphicsLayerPaintMask)
1813 paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
1814 if (paintingPhase & GraphicsLayerPaintOverflowContents)
1815 paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
1817 if (graphicsLayer == m_backgroundLayer)
1818 paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
1819 else if (m_backgroundLayer)
1820 paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground;
1822 // FIXME: GraphicsLayers need a way to split for RenderRegions.
1823 RenderLayer::LayerPaintingInfo paintingInfo(m_owningLayer, paintDirtyRect, paintBehavior, LayoutSize());
1824 m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags);
1826 if (m_owningLayer->containsDirtyOverlayScrollbars())
1827 m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
1829 ASSERT(!m_owningLayer->m_usedTransparency);
1832 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1838 const IntRect& scrollbarRect = scrollbar->frameRect();
1839 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1840 IntRect transformedClip = clip;
1841 transformedClip.moveBy(scrollbarRect.location());
1842 scrollbar->paint(&context, transformedClip);
1846 // Up-call from compositing layer drawing callback.
1847 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
1850 if (Page* page = renderer()->frame()->page())
1851 page->setIsPainting(true);
1854 if (graphicsLayer == m_graphicsLayer.get()
1855 || graphicsLayer == m_foregroundLayer.get()
1856 || graphicsLayer == m_backgroundLayer.get()
1857 || graphicsLayer == m_maskLayer.get()
1858 || graphicsLayer == m_scrollingContentsLayer.get()) {
1859 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame());
1861 // The dirtyRect is in the coords of the painting root.
1862 IntRect dirtyRect = clip;
1863 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
1864 dirtyRect.intersect(compositedBounds());
1866 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
1867 paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
1869 if (m_usingTiledCacheLayer)
1870 m_owningLayer->renderer()->frame()->view()->setLastPaintTime(currentTime());
1872 InspectorInstrumentation::didPaint(cookie, &context, clip);
1873 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
1874 paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
1875 } else if (graphicsLayer == layerForVerticalScrollbar()) {
1876 paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
1877 } else if (graphicsLayer == layerForScrollCorner()) {
1878 const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
1880 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
1881 IntRect transformedClip = clip;
1882 transformedClip.moveBy(scrollCornerAndResizer.location());
1883 m_owningLayer->paintScrollCorner(&context, IntPoint(), transformedClip);
1884 m_owningLayer->paintResizer(&context, IntPoint(), transformedClip);
1888 if (Page* page = renderer()->frame()->page())
1889 page->setIsPainting(false);
1893 float RenderLayerBacking::pageScaleFactor() const
1895 return compositor()->pageScaleFactor();
1898 float RenderLayerBacking::deviceScaleFactor() const
1900 return compositor()->deviceScaleFactor();
1903 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
1905 compositor()->didFlushChangesForLayer(m_owningLayer, layer);
1908 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
1910 GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
1911 if (graphicsLayer != transformedLayer)
1914 if (m_owningLayer->hasTransform()) {
1915 transform = m_owningLayer->currentTransform(RenderStyle::ExcludeTransformOrigin);
1921 bool RenderLayerBacking::isTrackingRepaints() const
1923 GraphicsLayerClient* client = compositor();
1924 return client ? client->isTrackingRepaints() : false;
1928 void RenderLayerBacking::verifyNotPainting()
1930 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
1934 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
1936 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
1937 bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
1938 #if ENABLE(CSS_FILTERS)
1939 bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
1941 bool hasFilter = false;
1944 if (!hasOpacity && !hasTransform && !hasFilter)
1947 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1948 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1949 #if ENABLE(CSS_FILTERS)
1950 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
1953 size_t numKeyframes = keyframes.size();
1954 for (size_t i = 0; i < numKeyframes; ++i) {
1955 const KeyframeValue& currentKeyframe = keyframes[i];
1956 const RenderStyle* keyframeStyle = currentKeyframe.style();
1957 float key = currentKeyframe.key();
1962 // Get timing function.
1963 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0;
1965 bool isFirstOrLastKeyframe = key == 0 || key == 1;
1966 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
1967 transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
1969 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
1970 opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
1972 #if ENABLE(CSS_FILTERS)
1973 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
1974 filterVector.insert(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf));
1978 bool didAnimateTransform = false;
1979 bool didAnimateOpacity = false;
1980 #if ENABLE(CSS_FILTERS)
1981 bool didAnimateFilter = false;
1984 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
1985 didAnimateTransform = true;
1987 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
1988 didAnimateOpacity = true;
1990 #if ENABLE(CSS_FILTERS)
1991 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
1992 didAnimateFilter = true;
1995 #if ENABLE(CSS_FILTERS)
1996 return didAnimateTransform || didAnimateOpacity || didAnimateFilter;
1998 return didAnimateTransform || didAnimateOpacity;
2002 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2004 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2007 void RenderLayerBacking::animationFinished(const String& animationName)
2009 m_graphicsLayer->removeAnimation(animationName);
2012 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2014 bool didAnimateOpacity = false;
2015 bool didAnimateTransform = false;
2016 #if ENABLE(CSS_FILTERS)
2017 bool didAnimateFilter = false;
2020 ASSERT(property != CSSPropertyInvalid);
2022 if (property == CSSPropertyOpacity) {
2023 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2024 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2025 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2026 opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
2027 opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
2028 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2029 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2030 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2031 updateOpacity(toStyle);
2032 didAnimateOpacity = true;
2037 if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
2038 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
2039 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2040 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
2041 transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
2042 transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
2043 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
2044 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2045 updateTransform(toStyle);
2046 didAnimateTransform = true;
2051 #if ENABLE(CSS_FILTERS)
2052 if (property == CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) {
2053 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
2054 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2055 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
2056 filterVector.insert(new FilterAnimationValue(0, &fromStyle->filter()));
2057 filterVector.insert(new FilterAnimationValue(1, &toStyle->filter()));
2058 if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
2059 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
2060 updateFilters(toStyle);
2061 didAnimateFilter = true;
2067 #if ENABLE(CSS_FILTERS)
2068 return didAnimateOpacity || didAnimateTransform || didAnimateFilter;
2070 return didAnimateOpacity || didAnimateTransform;
2074 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
2076 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2077 if (animatedProperty != AnimatedPropertyInvalid)
2078 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
2081 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
2083 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2084 if (animatedProperty != AnimatedPropertyInvalid)
2085 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
2088 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
2090 renderer()->animation()->notifyAnimationStarted(renderer(), time);
2093 void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer*)
2095 if (!renderer()->documentBeingDestroyed())
2096 compositor()->scheduleLayerFlush();
2099 void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
2101 compositor()->notifyFlushBeforeDisplayRefresh(layer);
2104 // This is used for the 'freeze' API, for testing only.
2105 void RenderLayerBacking::suspendAnimations(double time)
2107 m_graphicsLayer->suspendAnimations(time);
2110 void RenderLayerBacking::resumeAnimations()
2112 m_graphicsLayer->resumeAnimations();
2115 IntRect RenderLayerBacking::compositedBounds() const
2117 return m_compositedBounds;
2120 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
2122 m_compositedBounds = bounds;
2125 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
2127 CSSPropertyID cssProperty = CSSPropertyInvalid;
2129 case AnimatedPropertyWebkitTransform:
2130 cssProperty = CSSPropertyWebkitTransform;
2132 case AnimatedPropertyOpacity:
2133 cssProperty = CSSPropertyOpacity;
2135 case AnimatedPropertyBackgroundColor:
2136 cssProperty = CSSPropertyBackgroundColor;
2138 case AnimatedPropertyWebkitFilter:
2139 #if ENABLE(CSS_FILTERS)
2140 cssProperty = CSSPropertyWebkitFilter;
2142 ASSERT_NOT_REACHED();
2145 case AnimatedPropertyInvalid:
2146 ASSERT_NOT_REACHED();
2151 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
2153 switch (cssProperty) {
2154 case CSSPropertyWebkitTransform:
2155 return AnimatedPropertyWebkitTransform;
2156 case CSSPropertyOpacity:
2157 return AnimatedPropertyOpacity;
2158 case CSSPropertyBackgroundColor:
2159 return AnimatedPropertyBackgroundColor;
2160 #if ENABLE(CSS_FILTERS)
2161 case CSSPropertyWebkitFilter:
2162 return AnimatedPropertyWebkitFilter;
2165 // It's fine if we see other css properties here; they are just not accelerated.
2168 return AnimatedPropertyInvalid;
2171 CompositingLayerType RenderLayerBacking::compositingLayerType() const
2173 if (m_graphicsLayer->hasContentsLayer())
2174 return MediaCompositingLayer;
2176 if (m_graphicsLayer->drawsContent())
2177 return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
2179 return ContainerCompositingLayer;
2182 double RenderLayerBacking::backingStoreMemoryEstimate() const
2184 double backingMemory;
2186 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
2187 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
2188 if (m_foregroundLayer)
2189 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
2190 if (m_backgroundLayer)
2191 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
2193 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
2195 if (m_scrollingContentsLayer)
2196 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
2198 if (m_layerForHorizontalScrollbar)
2199 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
2201 if (m_layerForVerticalScrollbar)
2202 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
2204 if (m_layerForScrollCorner)
2205 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
2207 return backingMemory;
2210 #if PLATFORM(BLACKBERRY)
2211 bool RenderLayerBacking::contentsVisible(const GraphicsLayer*, const IntRect& localContentRect) const
2213 Frame* frame = renderer()->frame();
2214 FrameView* view = frame ? frame->view() : 0;
2218 IntRect visibleContentRect(view->visibleContentRect());
2219 FloatQuad absoluteContentQuad = renderer()->localToAbsoluteQuad(FloatRect(localContentRect));
2220 return absoluteContentQuad.enclosingBoundingBox().intersects(visibleContentRect);
2224 void RenderLayerBacking::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
2226 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
2227 info.addWeakPointer(m_owningLayer);
2228 info.addMember(m_ancestorClippingLayer, "ancestorClippingLayer");
2229 info.addMember(m_contentsContainmentLayer, "contentsContainmentLayer");
2230 info.addMember(m_graphicsLayer, "graphicsLayer");
2231 info.addMember(m_foregroundLayer, "foregroundLayer");
2232 info.addMember(m_backgroundLayer, "backgroundLayer");
2233 info.addMember(m_childContainmentLayer, "childContainmentLayer");
2234 info.addMember(m_maskLayer, "maskLayer");
2235 info.addMember(m_layerForHorizontalScrollbar, "layerForHorizontalScrollbar");
2236 info.addMember(m_layerForVerticalScrollbar, "layerForVerticalScrollbar");
2237 info.addMember(m_layerForScrollCorner, "layerForScrollCorner");
2238 info.addMember(m_scrollingLayer, "scrollingLayer");
2239 info.addMember(m_scrollingContentsLayer, "scrollingContentsLayer");
2242 } // namespace WebCore
2244 #endif // USE(ACCELERATED_COMPOSITING)