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"
36 #include "FontCache.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "GraphicsLayer.h"
40 #include "HTMLCanvasElement.h"
41 #include "HTMLIFrameElement.h"
42 #include "HTMLMediaElement.h"
43 #include "HTMLNames.h"
44 #include "InspectorInstrumentation.h"
45 #include "KeyframeList.h"
46 #include "PluginViewBase.h"
47 #include "RenderApplet.h"
48 #include "RenderIFrame.h"
49 #include "RenderImage.h"
50 #include "RenderLayerCompositor.h"
51 #include "RenderEmbeddedObject.h"
52 #include "RenderVideo.h"
53 #include "RenderView.h"
54 #include "ScrollingCoordinator.h"
55 #include "StyleResolver.h"
56 #include "TiledBacking.h"
58 #include <wtf/CurrentTime.h>
60 #if ENABLE(CSS_FILTERS)
61 #include "FilterEffectRenderer.h"
64 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
65 #include "GraphicsContext3D.h"
72 using namespace HTMLNames;
74 static bool hasBoxDecorations(const RenderStyle*);
75 static bool hasBoxDecorationsOrBackground(const RenderObject*);
76 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
77 static IntRect clipBox(RenderBox* renderer);
79 static inline bool isAcceleratedCanvas(RenderObject* renderer)
81 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
82 if (renderer->isCanvas()) {
83 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
84 if (CanvasRenderingContext* context = canvas->renderingContext())
85 return context->isAccelerated();
88 UNUSED_PARAM(renderer);
93 bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
95 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
96 : m_owningLayer(layer)
97 , m_artificiallyInflatedBounds(false)
98 , m_isMainFrameRenderViewLayer(false)
99 , m_usingTiledCacheLayer(false)
100 , m_requiresOwnBackingStore(true)
101 #if ENABLE(CSS_FILTERS)
102 , m_canCompositeFilters(false)
105 if (renderer()->isRenderView()) {
106 Frame* frame = toRenderView(renderer())->frameView()->frame();
107 Page* page = frame ? frame->page() : 0;
108 if (page && frame && page->mainFrame() == frame) {
109 m_isMainFrameRenderViewLayer = true;
112 // FIXME: It's a little weird that we base this decision on whether there's a scrolling coordinator or not.
113 if (page->scrollingCoordinator())
114 m_usingTiledCacheLayer = true;
119 createPrimaryGraphicsLayer();
121 if (m_usingTiledCacheLayer) {
122 if (Page* page = renderer()->frame()->page()) {
123 if (TiledBacking* tiledBacking = m_graphicsLayer->tiledBacking()) {
124 tiledBacking->setIsInWindow(page->isOnscreen());
125 tiledBacking->setCanHaveScrollbars(renderer()->frame()->view()->canHaveScrollbars());
131 RenderLayerBacking::~RenderLayerBacking()
133 updateClippingLayers(false, false);
134 updateOverflowControlsLayers(false, false, false);
135 updateForegroundLayer(false);
136 updateMaskLayer(false);
137 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
138 updateScrollingLayers(false);
140 destroyGraphicsLayers();
143 PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
145 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(this);
147 graphicsLayer->setName(name);
151 graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned());
153 #if PLATFORM(MAC) && USE(CA)
154 graphicsLayer->setAcceleratesDrawing(compositor()->acceleratedDrawingEnabled());
157 return graphicsLayer.release();
160 bool RenderLayerBacking::shouldUseTileCache(const GraphicsLayer*) const
162 return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
165 void RenderLayerBacking::createPrimaryGraphicsLayer()
169 layerName = nameForLayer();
172 // The call to createGraphicsLayer ends calling back into here as
173 // a GraphicsLayerClient to ask if it shouldUseTileCache(). We only want
174 // the tile cache on our main layer. This is pretty ugly, but saves us from
175 // exposing the API to all clients.
177 m_creatingPrimaryGraphicsLayer = true;
178 m_graphicsLayer = createGraphicsLayer(layerName);
179 m_creatingPrimaryGraphicsLayer = false;
181 if (m_usingTiledCacheLayer)
182 m_containmentLayer = createGraphicsLayer("TileCache Flattening Layer");
184 if (m_isMainFrameRenderViewLayer) {
185 bool isTransparent = false;
186 if (FrameView* frameView = toRenderView(renderer())->frameView())
187 isTransparent = frameView->isTransparent();
189 m_graphicsLayer->setContentsOpaque(!isTransparent);
190 m_graphicsLayer->setAppliesPageScale();
193 #if PLATFORM(MAC) && USE(CA)
194 if (!compositor()->acceleratedDrawingEnabled() && renderer()->isCanvas()) {
195 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node());
196 if (canvas->shouldAccelerate(canvas->size()))
197 m_graphicsLayer->setAcceleratesDrawing(true);
201 updateLayerOpacity(renderer()->style());
202 updateLayerTransform(renderer()->style());
203 #if ENABLE(CSS_FILTERS)
204 updateLayerFilters(renderer()->style());
208 void RenderLayerBacking::destroyGraphicsLayers()
211 m_graphicsLayer->removeFromParent();
213 m_graphicsLayer = nullptr;
214 m_foregroundLayer = nullptr;
215 m_containmentLayer = nullptr;
216 m_maskLayer = nullptr;
218 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
219 m_scrollingLayer = nullptr;
220 m_scrollingContentsLayer = nullptr;
224 void RenderLayerBacking::updateLayerOpacity(const RenderStyle* style)
226 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
229 void RenderLayerBacking::updateLayerTransform(const RenderStyle* style)
231 // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
232 // baked into it, and we don't want that.
233 TransformationMatrix t;
234 if (m_owningLayer->hasTransform()) {
235 style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
236 makeMatrixRenderable(t, compositor()->canRender3DTransforms());
239 m_graphicsLayer->setTransform(t);
242 #if ENABLE(CSS_FILTERS)
243 void RenderLayerBacking::updateLayerFilters(const RenderStyle* style)
245 m_canCompositeFilters = m_graphicsLayer->setFilters(style->filter());
249 static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
251 RenderStyle* style = renderer->style();
252 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
253 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
256 static bool layerOrAncestorIsTransformed(RenderLayer* layer)
258 for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
259 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
260 if (curr->hasTransform() || curr->hasAcceleratedTouchScrolling())
262 if (curr->hasTransform())
270 bool RenderLayerBacking::shouldClipCompositedBounds() const
272 // Scrollbar layers use this layer for relative positioning, so don't clip.
273 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
276 if (m_usingTiledCacheLayer)
279 if (!compositor()->compositingConsultsOverlap())
282 if (layerOrAncestorIsTransformed(m_owningLayer))
289 void RenderLayerBacking::updateCompositedBounds()
291 IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
293 // Clip to the size of the document or enclosing overflow-scroll layer.
294 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
295 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
296 if (shouldClipCompositedBounds()) {
297 RenderView* view = m_owningLayer->renderer()->view();
298 RenderLayer* rootLayer = view->layer();
300 // Start by clipping to the view's bounds.
301 LayoutRect clippingBounds = view->unscaledDocumentRect();
303 if (m_owningLayer != rootLayer)
304 clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, 0, AbsoluteClipRects).rect()); // FIXME: Incorrect for CSS regions.
307 m_owningLayer->convertToLayerCoords(rootLayer, delta);
308 clippingBounds.move(-delta.x(), -delta.y());
310 layerBounds.intersect(pixelSnappedIntRect(clippingBounds));
313 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
314 // then we need to ensure that the compositing layer has non-zero size so that we can apply
315 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
316 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
317 layerBounds.setWidth(1);
318 layerBounds.setHeight(1);
319 m_artificiallyInflatedBounds = true;
321 m_artificiallyInflatedBounds = false;
323 #if ENABLE(TIZEN_CSS_OVERFLOW_CLIPPING_BACKING_STORE)
324 RenderLayer* parentLayer = m_owningLayer->ancestorCompositingLayer();
326 && !parentLayer->isRootLayer()
327 && compositor()->clipsCompositingDescendants(parentLayer)
329 m_graphicsLayer->setOverflowClipping(true);
331 m_graphicsLayer->setOverflowClipping(false);
334 setCompositedBounds(layerBounds);
337 void RenderLayerBacking::updateAfterWidgetResize()
339 if (renderer()->isRenderPart()) {
340 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
341 innerCompositor->frameViewDidChangeSize();
342 innerCompositor->frameViewDidChangeLocation(contentsBox().location());
347 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdateRoot)
349 RenderLayerCompositor* layerCompositor = compositor();
350 if (!layerCompositor->compositingLayersNeedRebuild()) {
351 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
352 // position of this layer's GraphicsLayer depends on the position of our compositing
353 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
354 // RenderLayers of that ancestor have been processed via updateLayerPositions().
356 // The solution is to update compositing children of this layer here,
357 // via updateCompositingChildrenGeometry().
358 updateCompositedBounds();
359 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth);
362 updateGraphicsLayerGeometry();
363 layerCompositor->updateRootLayerPosition();
368 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
370 RenderLayerCompositor* compositor = this->compositor();
371 RenderObject* renderer = this->renderer();
373 m_owningLayer->updateZOrderLists();
375 bool layerConfigChanged = false;
376 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
377 layerConfigChanged = true;
379 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
380 bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
381 // Our scrolling layer will clip.
382 if (m_owningLayer->hasAcceleratedTouchScrolling())
383 needsDescendentsClippingLayer = false;
385 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
387 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
389 layerConfigChanged = true;
391 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
392 layerConfigChanged = true;
394 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
395 if (updateScrollingLayers(m_owningLayer->hasAcceleratedTouchScrolling()))
396 layerConfigChanged = true;
399 if (layerConfigChanged)
400 updateInternalHierarchy();
402 if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
403 flatteningLayer->removeFromParent();
404 m_graphicsLayer->addChild(flatteningLayer);
407 if (updateMaskLayer(renderer->hasMask()))
408 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
410 if (m_owningLayer->hasReflection()) {
411 if (m_owningLayer->reflectionLayer()->backing()) {
412 GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer();
413 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
416 m_graphicsLayer->setReplicatedByLayer(0);
418 updateBackgroundColor(isSimpleContainerCompositingLayer());
420 if (isDirectlyCompositedImage())
421 updateImageContents();
423 if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) {
424 PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderWidget(renderer)->widget());
425 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
428 else if (renderer->isVideo()) {
429 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer->node());
430 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
433 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
434 else if (isAcceleratedCanvas(renderer)) {
435 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
436 if (CanvasRenderingContext* context = canvas->renderingContext())
437 m_graphicsLayer->setContentsToCanvas(context->platformLayer());
438 layerConfigChanged = true;
441 if (renderer->isRenderPart())
442 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
444 return layerConfigChanged;
447 static IntRect clipBox(RenderBox* renderer)
449 LayoutRect result = PaintInfo::infiniteRect();
450 if (renderer->hasOverflowClip())
451 result = renderer->overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
453 if (renderer->hasClip())
454 result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
456 return pixelSnappedIntRect(result);
460 void RenderLayerBacking::updateGraphicsLayerGeometry()
462 // If we haven't built z-order lists yet, wait until later.
463 if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
466 // Set transform property, if it is not animating. We have to do this here because the transform
467 // is affected by the layer dimensions.
468 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
469 updateLayerTransform(renderer()->style());
471 // Set opacity, if it is not animating.
472 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
473 updateLayerOpacity(renderer()->style());
475 #if ENABLE(CSS_FILTERS)
476 updateLayerFilters(renderer()->style());
479 bool isSimpleContainer = isSimpleContainerCompositingLayer();
481 m_owningLayer->updateDescendantDependentFlags();
483 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
484 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
485 // non-compositing visible layers.
486 m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
488 RenderStyle* style = renderer()->style();
489 m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection());
490 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
492 // Register fixed position layers and their containers with the scrolling coordinator.
493 if (Page* page = renderer()->frame()->page()) {
494 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) {
495 if (style->position() == FixedPosition || compositor()->fixedPositionedByAncestor(m_owningLayer))
496 scrollingCoordinator->setLayerIsFixedToContainerLayer(childForSuperlayers(), true);
498 if (m_ancestorClippingLayer)
499 scrollingCoordinator->setLayerIsFixedToContainerLayer(m_ancestorClippingLayer.get(), false);
500 scrollingCoordinator->setLayerIsFixedToContainerLayer(m_graphicsLayer.get(), false);
502 // Page scale is applied as a transform on the root render view layer. Because the scroll
503 // layer is further up in the hierarchy, we need to avoid marking the root render view
504 // layer as a container.
505 bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
506 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
509 RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
511 // We compute everything relative to the enclosing compositing layer.
512 IntRect ancestorCompositingBounds;
514 ASSERT(compAncestor->backing());
515 ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds());
518 IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds());
520 IntRect relativeCompositingBounds(localCompositingBounds);
522 m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta);
523 relativeCompositingBounds.moveBy(delta);
525 IntPoint graphicsLayerParentLocation;
526 if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
527 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
528 // position relative to it.
529 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
530 graphicsLayerParentLocation = clippingBox.location();
531 } else if (compAncestor)
532 graphicsLayerParentLocation = ancestorCompositingBounds.location();
534 graphicsLayerParentLocation = renderer()->view()->documentRect().location();
536 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
537 if (compAncestor && compAncestor->hasAcceleratedTouchScrolling()) {
538 RenderBox* renderBox = toRenderBox(compAncestor->renderer());
539 IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(),
540 renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(),
541 renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
543 IntSize scrollOffset = compAncestor->scrolledContentOffset();
544 graphicsLayerParentLocation = paddingBox.location() - scrollOffset;
548 if (compAncestor && m_ancestorClippingLayer) {
549 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
550 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
551 // for a compositing layer, rootLayer is the layer itself.
552 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
553 IntRect parentClipRect = compAncestor->hasAcceleratedTouchScrolling() ? relativeCompositingBounds : pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects).rect());
555 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(compAncestor, 0, TemporaryClipRects).rect()); // FIXME: Incorrect for CSS regions.
557 ASSERT(parentClipRect != PaintInfo::infiniteRect());
558 m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
559 m_ancestorClippingLayer->setSize(parentClipRect.size());
561 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
562 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
563 IntSize rendererOffset(parentClipRect.location().x() - delta.x(), parentClipRect.location().y() - delta.y());
564 m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset);
566 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
569 // The primary layer is then parented in, and positioned relative to this clipping layer.
570 graphicsLayerParentLocation = parentClipRect.location();
573 m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
574 m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
576 FloatSize oldSize = m_graphicsLayer->size();
577 FloatSize newSize = relativeCompositingBounds.size();
578 if (oldSize != newSize) {
579 m_graphicsLayer->setSize(newSize);
580 // A bounds change will almost always require redisplay. Usually that redisplay
581 // will happen because of a repaint elsewhere, but not always:
582 // e.g. see RenderView::setMaximalOutlineSize()
583 m_graphicsLayer->setNeedsDisplay();
586 // If we have a layer that clips children, position it.
588 if (GraphicsLayer* clipLayer = clippingLayer()) {
589 clippingBox = clipBox(toRenderBox(renderer()));
590 clipLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
591 clipLayer->setSize(clippingBox.size());
592 clipLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
596 if (m_maskLayer->size() != m_graphicsLayer->size()) {
597 m_maskLayer->setSize(m_graphicsLayer->size());
598 m_maskLayer->setNeedsDisplay();
600 m_maskLayer->setPosition(FloatPoint());
601 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
604 if (m_owningLayer->hasTransform()) {
605 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
607 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
608 IntRect layerBounds = IntRect(delta, borderBox.size());
610 // Update properties that depend on layer dimensions
611 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
612 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
613 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
614 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
615 transformOrigin.z());
616 m_graphicsLayer->setAnchorPoint(anchor);
618 RenderStyle* style = renderer()->style();
619 GraphicsLayer* clipLayer = clippingLayer();
620 if (style->hasPerspective()) {
621 TransformationMatrix t = owningLayer()->perspectiveTransform();
624 clipLayer->setChildrenTransform(t);
625 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
628 m_graphicsLayer->setChildrenTransform(t);
631 clipLayer->setChildrenTransform(TransformationMatrix());
633 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
636 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
639 if (m_foregroundLayer) {
640 FloatPoint foregroundPosition;
641 FloatSize foregroundSize = newSize;
642 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
643 if (hasClippingLayer()) {
644 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
645 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
646 foregroundSize = FloatSize(clippingBox.size());
647 foregroundOffset = clippingBox.location() - IntPoint();
650 m_foregroundLayer->setPosition(foregroundPosition);
651 if (foregroundSize != m_foregroundLayer->size()) {
652 m_foregroundLayer->setSize(foregroundSize);
653 m_foregroundLayer->setNeedsDisplay();
655 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
658 if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
659 RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
660 reflectionBacking->updateGraphicsLayerGeometry();
662 // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
663 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
664 FloatRect layerBounds = compositedBounds();
665 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
666 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location()));
669 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
670 if (m_scrollingLayer) {
671 ASSERT(m_scrollingContentsLayer);
672 RenderBox* renderBox = toRenderBox(renderer());
673 IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
674 IntSize scrollOffset = m_owningLayer->scrolledContentOffset();
676 m_scrollingLayer->setPosition(FloatPoint() + (paddingBox.location() - localCompositingBounds.location()));
677 m_scrollingLayer->setSize(paddingBox.size());
678 m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location(), false);
679 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
680 m_scrollingLayer->setBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height()));
682 m_scrollingContentsLayer->setPosition(FloatPoint());
684 IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight());
685 if (scrollSize != m_scrollingContentsLayer->size())
686 m_scrollingContentsLayer->setNeedsDisplay();
688 m_scrollingContentsLayer->setSize(scrollSize);
689 m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset, false);
691 compositor()->scrollingLayerAddedOrUpdated(m_owningLayer, m_scrollingLayer.get(), m_scrollingContentsLayer.get(), scrollSize);
695 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
696 setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
698 updateContentsRect(isSimpleContainer);
699 updateDrawsContent(isSimpleContainer);
700 updateAfterWidgetResize();
703 void RenderLayerBacking::updateInternalHierarchy()
705 // m_foregroundLayer has to be inserted in the correct order with child layers,
706 // so it's not inserted here.
707 if (m_ancestorClippingLayer) {
708 m_ancestorClippingLayer->removeAllChildren();
709 m_graphicsLayer->removeFromParent();
710 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
713 if (m_containmentLayer) {
714 m_containmentLayer->removeFromParent();
715 m_graphicsLayer->addChild(m_containmentLayer.get());
718 // The clip for child layers does not include space for overflow controls, so they exist as
719 // siblings of the clipping layer if we have one. Normal children of this layer are set as
720 // children of the clipping layer.
721 if (m_layerForHorizontalScrollbar) {
722 m_layerForHorizontalScrollbar->removeFromParent();
723 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
725 if (m_layerForVerticalScrollbar) {
726 m_layerForVerticalScrollbar->removeFromParent();
727 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
729 if (m_layerForScrollCorner) {
730 m_layerForScrollCorner->removeFromParent();
731 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
734 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
735 if (m_scrollingLayer) {
736 GraphicsLayer* superlayer = m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
737 superlayer->addChild(m_scrollingLayer.get());
742 void RenderLayerBacking::updateContentsRect(bool isSimpleContainer)
744 IntRect contentsRect;
745 if (isSimpleContainer && renderer()->hasBackground())
746 contentsRect = backgroundBox();
748 contentsRect = contentsBox();
750 m_graphicsLayer->setContentsRect(contentsRect);
753 void RenderLayerBacking::updateDrawsContent()
755 updateDrawsContent(isSimpleContainerCompositingLayer());
758 void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
760 bool hasPaintedContent = !isSimpleContainer && containsPaintedContent();
762 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
763 m_graphicsLayer->setDrawsContent(hasPaintedContent);
764 if (m_foregroundLayer)
765 m_foregroundLayer->setDrawsContent(hasPaintedContent);
768 // Return true if the layers changed.
769 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
771 bool layersChanged = false;
773 if (needsAncestorClip) {
774 if (!m_ancestorClippingLayer) {
775 m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer");
776 m_ancestorClippingLayer->setMasksToBounds(true);
777 layersChanged = true;
779 } else if (m_ancestorClippingLayer) {
780 m_ancestorClippingLayer->removeFromParent();
781 m_ancestorClippingLayer = nullptr;
782 layersChanged = true;
785 if (needsDescendantClip) {
786 if (!m_containmentLayer && !m_usingTiledCacheLayer) {
787 m_containmentLayer = createGraphicsLayer("Child clipping Layer");
788 m_containmentLayer->setMasksToBounds(true);
789 layersChanged = true;
791 } else if (hasClippingLayer()) {
792 m_containmentLayer->removeFromParent();
793 m_containmentLayer = nullptr;
794 layersChanged = true;
797 return layersChanged;
800 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
802 #if !PLATFORM(CHROMIUM)
803 if (!m_owningLayer->hasOverlayScrollbars())
806 return m_owningLayer->horizontalScrollbar();
809 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
811 #if !PLATFORM(CHROMIUM)
812 if (!m_owningLayer->hasOverlayScrollbars())
815 return m_owningLayer->verticalScrollbar();
818 bool RenderLayerBacking::requiresScrollCornerLayer() const
820 #if !PLATFORM(CHROMIUM)
821 if (!m_owningLayer->hasOverlayScrollbars())
824 return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
827 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
829 bool layersChanged = false;
830 if (needsHorizontalScrollbarLayer) {
831 if (!m_layerForHorizontalScrollbar) {
832 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
833 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_SCROLLBAR)
834 m_layerForHorizontalScrollbar->setOpacity(0);
835 m_layerForHorizontalScrollbar->setIsScrollbar(true);
837 layersChanged = true;
839 } else if (m_layerForHorizontalScrollbar) {
840 m_layerForHorizontalScrollbar.clear();
841 layersChanged = true;
844 if (needsVerticalScrollbarLayer) {
845 if (!m_layerForVerticalScrollbar) {
846 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
847 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_SCROLLBAR)
848 m_layerForVerticalScrollbar->setOpacity(0);
849 m_layerForVerticalScrollbar->setIsScrollbar(true);
851 layersChanged = true;
853 } else if (m_layerForVerticalScrollbar) {
854 m_layerForVerticalScrollbar.clear();
855 layersChanged = true;
858 if (needsScrollCornerLayer) {
859 if (!m_layerForScrollCorner) {
860 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
861 layersChanged = true;
863 } else if (m_layerForScrollCorner) {
864 m_layerForScrollCorner.clear();
865 layersChanged = true;
868 return layersChanged;
871 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
873 bool layerChanged = false;
874 if (needsForegroundLayer) {
875 if (!m_foregroundLayer) {
878 layerName = nameForLayer() + " (foreground)";
880 m_foregroundLayer = createGraphicsLayer(layerName);
881 m_foregroundLayer->setDrawsContent(true);
882 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
885 } else if (m_foregroundLayer) {
886 m_foregroundLayer->removeFromParent();
887 m_foregroundLayer = nullptr;
892 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
897 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
899 bool layerChanged = false;
900 if (needsMaskLayer) {
902 m_maskLayer = createGraphicsLayer("Mask");
903 m_maskLayer->setDrawsContent(true);
904 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
907 } else if (m_maskLayer) {
908 m_maskLayer = nullptr;
913 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
918 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
919 bool RenderLayerBacking::updateScrollingLayers(bool scrollingLayers)
921 bool layerChanged = false;
922 if (scrollingLayers) {
923 if (!m_scrollingLayer) {
924 // Outer layer which corresponds with the scroll view.
925 m_scrollingLayer = GraphicsLayer::create(this);
927 m_scrollingLayer->setName("Scrolling container");
929 m_scrollingLayer->setDrawsContent(false);
930 m_scrollingLayer->setMasksToBounds(true);
932 // Inner layer which renders the content that scrolls.
933 m_scrollingContentsLayer = GraphicsLayer::create(this);
935 m_scrollingContentsLayer->setName("Scrolling Contents");
937 m_scrollingContentsLayer->setDrawsContent(true);
938 m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
939 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
942 // FIXME: scrollingLayerAddedOrUpdated had taken m_owningLayer's width, height
943 // according to original Apple's implementation. But it causes a crash at some sites.
944 // For instance http://goo.gl/pBS5z.
945 // We don't use these width/height of m_owningLayer in current overflow scroll
946 // acceleration. So we just hand over empty size here.
947 compositor()->scrollingLayerAddedOrUpdated(m_owningLayer, m_scrollingLayer.get(), m_scrollingContentsLayer.get(), IntSize());
949 } else if (m_scrollingLayer) {
950 if (!renderer()->documentBeingDestroyed())
951 compositor()->scrollingLayerRemoved(m_owningLayer, m_scrollingLayer.get(), m_scrollingContentsLayer.get());
953 m_scrollingLayer = nullptr;
954 m_scrollingContentsLayer = nullptr;
959 updateInternalHierarchy();
960 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
967 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
969 unsigned phase = GraphicsLayerPaintBackground;
970 if (!m_foregroundLayer)
971 phase |= GraphicsLayerPaintForeground;
973 phase |= GraphicsLayerPaintMask;
975 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
976 if (m_scrollingContentsLayer)
977 phase &= ~GraphicsLayerPaintForeground;
979 return static_cast<GraphicsLayerPaintingPhase>(phase);
982 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
984 float finalOpacity = rendererOpacity;
986 for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
987 // We only care about parents that are stacking contexts.
988 // Recall that opacity creates stacking context.
989 if (!curr->isStackingContext())
992 // If we found a compositing layer, we want to compute opacity
993 // relative to it. So we can break here.
994 if (curr->isComposited())
997 finalOpacity *= curr->renderer()->opacity();
1000 return finalOpacity;
1003 static bool hasBoxDecorations(const RenderStyle* style)
1005 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
1008 static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
1010 return hasBoxDecorations(renderer->style()) || renderer->hasBackground();
1013 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
1015 return hasBoxDecorations(style) || style->hasBackgroundImage();
1018 Color RenderLayerBacking::rendererBackgroundColor() const
1020 RenderObject* backgroundRenderer = renderer();
1021 if (backgroundRenderer->isRoot())
1022 backgroundRenderer = backgroundRenderer->rendererForRootBackground();
1024 return backgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
1027 void RenderLayerBacking::updateBackgroundColor(bool isSimpleContainer)
1029 Color backgroundColor = Color::transparent;
1030 if (isSimpleContainer)
1031 backgroundColor = rendererBackgroundColor();
1032 m_graphicsLayer->setContentsToBackgroundColor(backgroundColor);
1033 if (backgroundColor == Color::transparent)
1034 m_graphicsLayer->clearBackgroundColor();
1037 static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer)
1039 if (!GraphicsLayer::supportsBackgroundColorContent())
1042 if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
1045 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
1046 if (renderer->style()->backgroundComposite() != CompositeSourceOver)
1049 if (renderer->style()->backgroundClip() == TextFillBox)
1055 bool RenderLayerBacking::paintsBoxDecorations() const
1057 if (!m_owningLayer->hasVisibleContent())
1060 if (!hasBoxDecorationsOrBackground(renderer()))
1063 if (!supportsDirectBoxDecorationsComposition(renderer()))
1066 if (m_owningLayer->hasOverflowControls())
1072 bool RenderLayerBacking::paintsChildren() const
1074 if (m_owningLayer->hasVisibleContent() && containsNonEmptyRenderers())
1077 if (hasVisibleNonCompositingDescendantLayers())
1083 // A "simple container layer" is a RenderLayer which has no visible content to render.
1084 // It may have no children, or all its children may be themselves composited.
1085 // This is a useful optimization, because it allows us to avoid allocating backing store.
1086 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
1088 RenderObject* renderObject = renderer();
1089 if (renderObject->isReplaced() || // replaced objects are not containers
1090 renderObject->hasMask()) // masks require special treatment
1093 if (paintsBoxDecorations() || paintsChildren())
1096 if (renderObject->node() && renderObject->node()->isDocumentNode()) {
1097 // Look to see if the root object has a non-simple background
1098 RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0;
1102 RenderStyle* style = rootObject->style();
1104 // Reject anything that has a border, a border-radius or outline,
1105 // or is not a simple background (no background, or solid color).
1106 if (hasBoxDecorationsOrBackgroundImage(style))
1109 // Now look at the body's renderer.
1110 HTMLElement* body = renderObject->document()->body();
1111 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1115 style = bodyObject->style();
1117 if (hasBoxDecorationsOrBackgroundImage(style))
1124 bool RenderLayerBacking::containsNonEmptyRenderers() const
1126 // Some HTML can cause whitespace text nodes to have renderers, like:
1130 // so test for 0x0 RenderTexts here
1131 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
1132 if (!child->hasLayer()) {
1133 if (child->isRenderInline() || !child->isBox())
1136 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
1143 // Conservative test for having no rendered children.
1144 bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
1146 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1147 m_owningLayer->updateLayerListsIfNeeded();
1149 #if !ASSERT_DISABLED
1150 LayerListMutationDetector mutationChecker(m_owningLayer);
1153 if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
1154 size_t listSize = normalFlowList->size();
1155 for (size_t i = 0; i < listSize; ++i) {
1156 RenderLayer* curLayer = normalFlowList->at(i);
1157 if (!curLayer->isComposited() && curLayer->hasVisibleContent())
1162 if (m_owningLayer->isStackingContext()) {
1163 if (!m_owningLayer->hasVisibleDescendant())
1166 // Use the m_hasCompositingDescendant bit to optimize?
1167 if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
1168 size_t listSize = negZOrderList->size();
1169 for (size_t i = 0; i < listSize; ++i) {
1170 RenderLayer* curLayer = negZOrderList->at(i);
1171 if (!curLayer->isComposited() && curLayer->hasVisibleContent())
1176 if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
1177 size_t listSize = posZOrderList->size();
1178 for (size_t i = 0; i < listSize; ++i) {
1179 RenderLayer* curLayer = posZOrderList->at(i);
1180 if (!curLayer->isComposited() && curLayer->hasVisibleContent())
1189 bool RenderLayerBacking::containsPaintedContent() const
1191 if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
1194 if (isDirectlyCompositedImage())
1197 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1198 // and set background color on the layer in that case, instead of allocating backing store and painting.
1200 if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
1201 return hasBoxDecorationsOrBackground(renderer());
1203 #if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
1204 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
1205 if (isAcceleratedCanvas(renderer()))
1206 return hasBoxDecorationsOrBackground(renderer());
1212 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1213 // that require painting. Direct compositing saves backing store.
1214 bool RenderLayerBacking::isDirectlyCompositedImage() const
1216 RenderObject* renderObject = renderer();
1218 if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
1221 RenderImage* imageRenderer = toRenderImage(renderObject);
1222 if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
1223 if (cachedImage->hasImage())
1224 return cachedImage->imageForRenderer(imageRenderer)->isBitmapImage();
1230 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
1232 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1233 updateImageContents();
1237 if ((changeType == MaskImageChanged) && m_maskLayer) {
1238 // The composited layer bounds relies on box->maskClipRect(), which changes
1239 // when the mask image becomes available.
1240 bool isUpdateRoot = true;
1241 updateAfterLayout(CompositingChildren, isUpdateRoot);
1244 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
1245 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
1246 m_graphicsLayer->setContentsNeedsDisplay();
1252 void RenderLayerBacking::updateImageContents()
1254 ASSERT(renderer()->isImage());
1255 RenderImage* imageRenderer = toRenderImage(renderer());
1257 CachedImage* cachedImage = imageRenderer->cachedImage();
1261 Image* image = cachedImage->imageForRenderer(imageRenderer);
1265 // We have to wait until the image is fully loaded before setting it on the layer.
1266 if (!cachedImage->isLoaded())
1269 // This is a no-op if the layer doesn't have an inner layer for the image.
1270 m_graphicsLayer->setContentsToImage(image);
1271 bool isSimpleContainer = false;
1272 updateDrawsContent(isSimpleContainer);
1274 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1275 // the image. So we have to kick the animation each time; this has the downside that the
1276 // image will keep animating, even if its layer is not visible.
1277 image->startAnimation();
1280 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
1282 RenderStyle* style = renderer()->style();
1284 FloatPoint3D origin;
1285 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
1286 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
1287 origin.setZ(style->transformOriginZ());
1292 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
1294 RenderStyle* style = renderer()->style();
1296 float boxWidth = borderBox.width();
1297 float boxHeight = borderBox.height();
1300 origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
1301 origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
1306 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1307 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1309 return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1312 IntRect RenderLayerBacking::contentsBox() const
1314 if (!renderer()->isBox())
1317 IntRect contentsRect;
1319 if (renderer()->isVideo()) {
1320 RenderVideo* videoRenderer = toRenderVideo(renderer());
1321 contentsRect = videoRenderer->videoBox();
1324 contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect());
1326 contentsRect.move(contentOffsetInCompostingLayer());
1327 return contentsRect;
1330 static LayoutRect backgroundRectForBox(const RenderBox* box)
1332 EFillBox clip = box->style()->backgroundClip();
1335 return box->borderBoxRect();
1336 case PaddingFillBox:
1337 return box->paddingBoxRect();
1338 case ContentFillBox:
1339 return box->contentBoxRect();
1344 ASSERT_NOT_REACHED();
1345 return LayoutRect();
1348 IntRect RenderLayerBacking::backgroundBox() const
1350 if (!renderer()->isBox())
1353 IntRect pixelSnappedBackgroundBox = pixelSnappedIntRect(backgroundRectForBox(toRenderBox(renderer())));
1354 pixelSnappedBackgroundBox.move(contentOffsetInCompostingLayer());
1355 return pixelSnappedBackgroundBox;
1358 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1359 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
1361 if (m_scrollingContentsLayer)
1362 return m_scrollingContentsLayer.get();
1364 return m_containmentLayer ? m_containmentLayer.get() : m_graphicsLayer.get();
1368 bool RenderLayerBacking::paintsIntoWindow() const
1370 if (m_usingTiledCacheLayer)
1373 if (m_owningLayer->isRootLayer()) {
1374 #if PLATFORM(BLACKBERRY)
1375 if (compositor()->inForcedCompositingMode())
1379 return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
1385 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
1387 if (requiresOwnBacking == m_requiresOwnBackingStore)
1390 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
1391 // cached clip rects, so when it changes we have to clear clip rects on descendants.
1392 m_owningLayer->clearClipRectsIncludingDescendants(PaintingClipRects);
1393 m_requiresOwnBackingStore = requiresOwnBacking;
1395 compositor()->repaintInCompositedAncestor(m_owningLayer, compositedBounds());
1398 void RenderLayerBacking::setContentsNeedDisplay()
1400 ASSERT(!paintsIntoCompositedAncestor());
1402 if (m_graphicsLayer && m_graphicsLayer->drawsContent())
1403 m_graphicsLayer->setNeedsDisplay();
1405 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
1406 m_foregroundLayer->setNeedsDisplay();
1408 if (m_maskLayer && m_maskLayer->drawsContent())
1409 m_maskLayer->setNeedsDisplay();
1411 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1412 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
1413 m_scrollingContentsLayer->setNeedsDisplay();
1417 // r is in the coordinate space of the layer's render object
1418 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
1420 ASSERT(!paintsIntoCompositedAncestor());
1422 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
1423 IntRect layerDirtyRect = r;
1424 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
1425 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
1428 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
1429 IntRect layerDirtyRect = r;
1430 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
1431 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
1434 if (m_maskLayer && m_maskLayer->drawsContent()) {
1435 IntRect layerDirtyRect = r;
1436 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
1437 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
1440 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1441 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
1442 IntRect layerDirtyRect = r;
1443 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
1444 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
1449 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
1450 const IntRect& paintDirtyRect, // In the coords of rootLayer.
1451 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
1452 RenderObject* paintingRoot)
1454 if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
1455 ASSERT_NOT_REACHED();
1459 FontCachePurgePreventer fontCachePurgePreventer;
1461 RenderLayer::PaintLayerFlags paintFlags = 0;
1462 if (paintingPhase & GraphicsLayerPaintBackground)
1463 paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase;
1464 if (paintingPhase & GraphicsLayerPaintForeground)
1465 paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
1466 if (paintingPhase & GraphicsLayerPaintMask)
1467 paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
1468 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1469 if (paintingPhase & GraphicsLayerPaintOverflowContents)
1470 paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
1473 // FIXME: GraphicsLayers need a way to split for RenderRegions.
1474 m_owningLayer->paintLayerContents(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0, paintFlags);
1476 if (m_owningLayer->containsDirtyOverlayScrollbars())
1477 m_owningLayer->paintOverlayScrollbars(context, paintDirtyRect, paintBehavior, paintingRoot);
1479 ASSERT(!m_owningLayer->m_usedTransparency);
1482 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1488 const IntRect& scrollbarRect = scrollbar->frameRect();
1489 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1490 IntRect transformedClip = clip;
1491 transformedClip.moveBy(scrollbarRect.location());
1492 scrollbar->paint(&context, transformedClip);
1496 // Up-call from compositing layer drawing callback.
1497 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
1500 if (Page* page = renderer()->frame()->page())
1501 page->setIsPainting(true);
1503 if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()
1504 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1505 || graphicsLayer == m_scrollingContentsLayer.get()
1508 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), &context, clip);
1510 // The dirtyRect is in the coords of the painting root.
1511 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1512 IntRect dirtyRect = clip;
1513 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
1514 dirtyRect.intersect(compositedBounds());
1516 IntRect dirtyRect = compositedBounds();
1517 dirtyRect.intersect(clip);
1520 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
1521 paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
1523 if (m_usingTiledCacheLayer)
1524 m_owningLayer->renderer()->frame()->view()->setLastPaintTime(currentTime());
1526 InspectorInstrumentation::didPaint(cookie);
1527 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
1528 paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
1529 } else if (graphicsLayer == layerForVerticalScrollbar()) {
1530 paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
1531 } else if (graphicsLayer == layerForScrollCorner()) {
1532 const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
1534 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
1535 IntRect transformedClip = clip;
1536 transformedClip.moveBy(scrollCornerAndResizer.location());
1537 m_owningLayer->paintScrollCorner(&context, IntPoint(), transformedClip);
1538 m_owningLayer->paintResizer(&context, IntPoint(), transformedClip);
1542 if (Page* page = renderer()->frame()->page())
1543 page->setIsPainting(false);
1547 float RenderLayerBacking::pageScaleFactor() const
1549 return compositor()->pageScaleFactor();
1552 float RenderLayerBacking::deviceScaleFactor() const
1554 return compositor()->deviceScaleFactor();
1557 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer*) const
1559 compositor()->didFlushChangesForLayer(m_owningLayer);
1562 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
1564 if (graphicsLayer != m_graphicsLayer)
1567 if (m_owningLayer->hasTransform()) {
1568 transform = m_owningLayer->currentTransform(RenderStyle::ExcludeTransformOrigin);
1574 bool RenderLayerBacking::showDebugBorders(const GraphicsLayer*) const
1576 return compositor() ? compositor()->compositorShowDebugBorders() : false;
1579 bool RenderLayerBacking::showRepaintCounter(const GraphicsLayer*) const
1581 return compositor() ? compositor()->compositorShowRepaintCounter() : false;
1584 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1585 void RenderLayerBacking::platformLayerChanged(GraphicsLayer*, PlatformLayer* oldLayer, PlatformLayer* newLayer)
1587 compositor()->platformLayerChanged(m_owningLayer, oldLayer, newLayer);
1592 void RenderLayerBacking::verifyNotPainting()
1594 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
1598 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
1600 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
1601 bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
1602 #if ENABLE(CSS_FILTERS)
1603 bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
1605 bool hasFilter = false;
1608 if (!hasOpacity && !hasTransform && !hasFilter)
1611 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1612 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1613 #if ENABLE(CSS_FILTERS)
1614 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
1617 size_t numKeyframes = keyframes.size();
1618 for (size_t i = 0; i < numKeyframes; ++i) {
1619 const KeyframeValue& currentKeyframe = keyframes[i];
1620 const RenderStyle* keyframeStyle = currentKeyframe.style();
1621 float key = currentKeyframe.key();
1626 // Get timing function.
1627 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0;
1629 bool isFirstOrLastKeyframe = key == 0 || key == 1;
1630 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
1631 transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
1633 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
1634 opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
1636 #if ENABLE(CSS_FILTERS)
1637 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
1638 filterVector.insert(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf));
1642 bool didAnimateTransform = false;
1643 bool didAnimateOpacity = false;
1644 #if ENABLE(CSS_FILTERS)
1645 bool didAnimateFilter = false;
1648 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
1649 didAnimateTransform = true;
1651 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
1652 didAnimateOpacity = true;
1654 #if ENABLE(CSS_FILTERS)
1655 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
1656 didAnimateFilter = true;
1659 #if ENABLE(CSS_FILTERS)
1660 return didAnimateTransform || didAnimateOpacity || didAnimateFilter;
1662 return didAnimateTransform || didAnimateOpacity;
1666 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
1668 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
1671 void RenderLayerBacking::animationFinished(const String& animationName)
1673 m_graphicsLayer->removeAnimation(animationName);
1676 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
1678 bool didAnimateOpacity = false;
1679 bool didAnimateTransform = false;
1680 #if ENABLE(CSS_FILTERS)
1681 bool didAnimateFilter = false;
1684 ASSERT(property != CSSPropertyInvalid);
1686 if (property == CSSPropertyOpacity) {
1687 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
1688 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
1689 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1690 opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
1691 opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
1692 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
1693 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
1694 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
1695 updateLayerOpacity(toStyle);
1696 didAnimateOpacity = true;
1701 if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
1702 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
1703 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
1704 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1705 transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
1706 transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
1707 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
1708 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
1709 updateLayerTransform(toStyle);
1710 didAnimateTransform = true;
1715 #if ENABLE(CSS_FILTERS)
1716 if (property == CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) {
1717 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
1718 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
1719 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
1720 filterVector.insert(new FilterAnimationValue(0, &fromStyle->filter()));
1721 filterVector.insert(new FilterAnimationValue(1, &toStyle->filter()));
1722 if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
1723 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
1724 updateLayerFilters(toStyle);
1725 didAnimateFilter = true;
1731 #if ENABLE(CSS_FILTERS)
1732 return didAnimateOpacity || didAnimateTransform || didAnimateFilter;
1734 return didAnimateOpacity || didAnimateTransform;
1738 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
1740 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1741 if (animatedProperty != AnimatedPropertyInvalid)
1742 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
1745 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
1747 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1748 if (animatedProperty != AnimatedPropertyInvalid)
1749 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
1752 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
1754 renderer()->animation()->notifyAnimationStarted(renderer(), time);
1757 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*)
1759 if (!renderer()->documentBeingDestroyed())
1760 compositor()->scheduleLayerFlush();
1763 // This is used for the 'freeze' API, for testing only.
1764 void RenderLayerBacking::suspendAnimations(double time)
1766 m_graphicsLayer->suspendAnimations(time);
1769 void RenderLayerBacking::resumeAnimations()
1771 m_graphicsLayer->resumeAnimations();
1774 IntRect RenderLayerBacking::compositedBounds() const
1776 return m_compositedBounds;
1779 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
1781 m_compositedBounds = bounds;
1784 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
1786 CSSPropertyID cssProperty = CSSPropertyInvalid;
1788 case AnimatedPropertyWebkitTransform:
1789 cssProperty = CSSPropertyWebkitTransform;
1791 case AnimatedPropertyOpacity:
1792 cssProperty = CSSPropertyOpacity;
1794 case AnimatedPropertyBackgroundColor:
1795 cssProperty = CSSPropertyBackgroundColor;
1797 case AnimatedPropertyWebkitFilter:
1798 #if ENABLE(CSS_FILTERS)
1799 cssProperty = CSSPropertyWebkitFilter;
1801 ASSERT_NOT_REACHED();
1804 case AnimatedPropertyInvalid:
1805 ASSERT_NOT_REACHED();
1810 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
1812 switch (cssProperty) {
1813 case CSSPropertyWebkitTransform:
1814 return AnimatedPropertyWebkitTransform;
1815 case CSSPropertyOpacity:
1816 return AnimatedPropertyOpacity;
1817 case CSSPropertyBackgroundColor:
1818 return AnimatedPropertyBackgroundColor;
1819 #if ENABLE(CSS_FILTERS)
1820 case CSSPropertyWebkitFilter:
1821 return AnimatedPropertyWebkitFilter;
1824 // It's fine if we see other css properties here; they are just not accelerated.
1827 return AnimatedPropertyInvalid;
1830 String RenderLayerBacking::nameForLayer() const
1832 String name = renderer()->renderName();
1833 if (Node* node = renderer()->node()) {
1834 if (node->isElementNode())
1835 name += " " + static_cast<Element*>(node)->tagName();
1837 name += " id=\'" + static_cast<Element*>(node)->getIdAttribute() + "\'";
1839 if (node->hasClass()) {
1840 StyledElement* styledElement = static_cast<StyledElement*>(node);
1842 for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
1845 classes += styledElement->classNames()[i];
1847 name += " class=\'" + classes + "\'";
1851 if (m_owningLayer->isReflection())
1852 name += " (reflection)";
1857 CompositingLayerType RenderLayerBacking::compositingLayerType() const
1859 if (m_graphicsLayer->hasContentsLayer())
1860 return MediaCompositingLayer;
1862 if (m_graphicsLayer->drawsContent())
1863 return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
1865 return ContainerCompositingLayer;
1868 double RenderLayerBacking::backingStoreMemoryEstimate() const
1870 double backingMemory;
1872 // m_ancestorClippingLayer and m_containmentLayer are just used for masking or containment, so have no backing.
1873 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
1874 if (m_foregroundLayer)
1875 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
1877 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
1879 if (m_layerForHorizontalScrollbar)
1880 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
1882 if (m_layerForVerticalScrollbar)
1883 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
1885 if (m_layerForScrollCorner)
1886 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
1888 return backingMemory;
1891 } // namespace WebCore
1893 #endif // USE(ACCELERATED_COMPOSITING)