/* * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #if USE(ACCELERATED_COMPOSITING) #include "RenderLayerCompositor.h" #include "AnimationController.h" #include "ChromeClient.h" #include "CSSPropertyNames.h" #include "Frame.h" #include "FrameView.h" #include "GraphicsLayer.h" #include "HitTestRequest.h" #include "HitTestResult.h" #include "Page.h" #include "RenderLayerBacking.h" #include "RenderView.h" #if PROFILE_LAYER_REBUILD #include #endif #ifndef NDEBUG #include "CString.h" #include "RenderTreeAsText.h" #endif #if ENABLE(3D_RENDERING) // This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm'). bool WebCoreHas3DRendering = true; #endif namespace WebCore { struct CompositingState { CompositingState(RenderLayer* compAncestor) : m_subtreeIsCompositing(false) , m_compositingAncestor(compAncestor) #ifndef NDEBUG , m_depth(0) #endif { } bool m_subtreeIsCompositing; RenderLayer* m_compositingAncestor; #ifndef NDEBUG int m_depth; #endif }; static TransformationMatrix flipTransform() { TransformationMatrix flipper; flipper.flipY(); return flipper; } RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) : m_renderView(renderView) , m_rootPlatformLayer(0) , m_compositing(false) , m_rootLayerAttached(false) , m_compositingLayersNeedUpdate(false) #if PROFILE_LAYER_REBUILD , m_rootLayerUpdateCount(0) #endif // PROFILE_LAYER_REBUILD { } RenderLayerCompositor::~RenderLayerCompositor() { ASSERT(!m_rootLayerAttached); delete m_rootPlatformLayer; } void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) { if (enable != m_compositing) { m_compositing = enable; // We never go out of compositing mode for a given page, // but if all the layers disappear, we'll just be left with // the empty root layer, which has minimal overhead. if (m_compositing) ensureRootPlatformLayer(); } } void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate) { if (inCompositingMode()) m_compositingLayersNeedUpdate = needUpdate; } void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) { if (!m_compositingLayersNeedUpdate) return; ASSERT(inCompositingMode()); if (!updateRoot) { // Only clear the flag if we're updating the entire hierarchy m_compositingLayersNeedUpdate = false; updateRoot = rootRenderLayer(); } #if PROFILE_LAYER_REBUILD ++m_rootLayerUpdateCount; double startTime = WTF::currentTime(); #endif // Go through the layers in presentation order, so that we can compute which // RLs need compositing layers. // FIXME: we could maybe do this in one pass, but the parenting logic would be more // complex. { CompositingState compState(updateRoot); computeCompositingRequirements(updateRoot, compState); } // Now create and parent the compositing layers. { CompositingState compState(updateRoot); rebuildCompositingLayerTree(updateRoot, compState); } #if PROFILE_LAYER_REBUILD double endTime = WTF::currentTime(); if (!updateRoot) fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n" m_rootLayerUpdateCount, 1000.0 * (endTime - startTime)); #endif ASSERT(updateRoot || !m_compositingLayersNeedUpdate); } bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, StyleDifference diff) { bool needsLayer = needsToBeComposited(layer); bool layerChanged = false; RenderBoxModelObject* repaintContainer = 0; IntRect repaintRect; if (needsLayer) { enableCompositingMode(); if (!layer->backing()) { // Get the repaint container before we make backing for this layer repaintContainer = layer->renderer()->containerForRepaint(); repaintRect = calculateCompositedBounds(layer, repaintContainer ? repaintContainer->layer() : layer->root()); layer->ensureBacking(); layerChanged = true; } } else { if (layer->backing()) { layer->clearBacking(); // Get the repaint container now that we've cleared the backing repaintContainer = layer->renderer()->containerForRepaint(); repaintRect = calculateCompositedBounds(layer, repaintContainer ? repaintContainer->layer() : layer->root()); layerChanged = true; } } if (layerChanged) { // Invalidate the destination into which this layer used to render. layer->renderer()->repaintUsingContainer(repaintContainer, repaintRect); if (!repaintContainer || repaintContainer == m_renderView) { // The contents of this layer may be moving between the window // and a GraphicsLayer, so we need to make sure the window system // synchronizes those changes on the screen. m_renderView->frameView()->setNeedsOneShotDrawingSynchronization(); } } if (!needsLayer) return layerChanged; if (layer->backing()->updateGraphicsLayers(needsContentsCompositingLayer(layer), clippedByAncestor(layer), clipsCompositingDescendants(layer), diff >= StyleDifferenceRepaint)) layerChanged = true; return layerChanged; } // The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant // RenderLayers that are rendered by the composited RenderLayer. IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox) { IntRect boundingBoxRect, unionBounds; boundingBoxRect = unionBounds = layer->localBoundingBox(); ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0)); Vector* negZOrderList = layer->negZOrderList(); if (negZOrderList) { for (Vector::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); } } } Vector* posZOrderList = layer->posZOrderList(); if (posZOrderList) { for (Vector::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); } } } Vector* normalFlowList = layer->normalFlowList(); if (normalFlowList) { for (Vector::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); if (!curLayer->isComposited()) { IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(curAbsBounds); } } } if (!layer->isComposited() && layer->transform()) { TransformationMatrix* affineTrans = layer->transform(); boundingBoxRect = affineTrans->mapRect(boundingBoxRect); unionBounds = affineTrans->mapRect(unionBounds); } int ancestorRelX = 0, ancestorRelY = 0; layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY); unionBounds.move(ancestorRelX, ancestorRelY); if (layerBoundingBox) { boundingBoxRect.move(ancestorRelX, ancestorRelY); *layerBoundingBox = boundingBoxRect; } return unionBounds; } void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/) { setCompositingLayersNeedUpdate(); } void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child) { if (child->isComposited()) setCompositingParent(child, 0); // If the document is being torn down (document's renderer() is null), then there's // no need to do any layer updating. if (parent->renderer()->documentBeingDestroyed()) return; RenderLayer* compLayer = parent->enclosingCompositingLayer(); if (compLayer) { IntRect ancestorRect = calculateCompositedBounds(child, compLayer); compLayer->setBackingNeedsRepaintInRect(ancestorRect); // The contents of this layer may be moving from a GraphicsLayer to the window, // so we need to make sure the window system synchronizes those changes on the screen. m_renderView->frameView()->setNeedsOneShotDrawingSynchronization(); } setCompositingLayersNeedUpdate(); } RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const { for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) { if (curr->isStackingContext()) return 0; if (curr->renderer()->hasOverflowClip()) return curr; } return 0; } // Recurse through the layers in z-index and overflow order (which is equivalent to painting order) // For the z-order children of a compositing layer: // If a child layers has a compositing layer, then all subsequent layers must // be compositing in order to render above that layer. // // If a child in the negative z-order list is compositing, then the layer itself // must be compositing so that its contents render over that child. // This implies that its positive z-index children must also be compositing. // void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, struct CompositingState& ioCompState) { layer->updateLayerPosition(); layer->updateZOrderLists(); layer->updateNormalFlowList(); // Clear the flag layer->setHasCompositingDescendant(false); layer->setMustOverlayCompositedLayers(ioCompState.m_subtreeIsCompositing); const bool isCompositingLayer = needsToBeComposited(layer); ioCompState.m_subtreeIsCompositing = isCompositingLayer; CompositingState childState = ioCompState; if (isCompositingLayer) childState.m_compositingAncestor = layer; // The children of this stacking context don't need to composite, unless there is // a compositing layer among them, so start by assuming false. childState.m_subtreeIsCompositing = false; #ifndef NDEBUG ++childState.m_depth; #endif if (layer->isStackingContext()) { ASSERT(!layer->m_zOrderListsDirty); Vector* negZOrderList = layer->negZOrderList(); if (negZOrderList && negZOrderList->size() > 0) { for (Vector::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); computeCompositingRequirements(curLayer, childState); // if we have to make a layer for this child, make one now so we can have a contents layer // (since we need to ensure that the -ve z-order child renders underneath our contents) if (childState.m_subtreeIsCompositing) { // make |this| compositing layer->setMustOverlayCompositedLayers(true); childState.m_compositingAncestor = layer; } } } } ASSERT(!layer->m_normalFlowListDirty); Vector* normalFlowList = layer->normalFlowList(); if (normalFlowList && normalFlowList->size() > 0) { for (Vector::const_iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); computeCompositingRequirements(curLayer, childState); } } if (layer->isStackingContext()) { Vector* posZOrderList = layer->posZOrderList(); if (posZOrderList && posZOrderList->size() > 0) { for (Vector::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); computeCompositingRequirements(curLayer, childState); } } } // If we have a software transform, and we have layers under us, we need to also // be composited. Also, if we have opacity < 1, then we need to be a layer so that // the child layers are opaque, then rendered with opacity on this layer. if (childState.m_subtreeIsCompositing && (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1)) layer->setMustOverlayCompositedLayers(true); // Subsequent layers in the parent stacking context also need to composite. if (childState.m_subtreeIsCompositing) ioCompState.m_subtreeIsCompositing = true; // Set the flag to say that this SC has compositing children. // this can affect the answer to needsToBeComposited() when clipping, // but that's ok here. layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing); } void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) { ASSERT(childLayer->isComposited()); ASSERT(!parentLayer || parentLayer->isComposited()); if (parentLayer) { GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers(); GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers(); hostingLayer->addChild(hostedLayer); } else childLayer->backing()->childForSuperlayers()->removeFromParent(); // FIXME: setCompositingParent() is only called at present by rebuildCompositingLayerTree(), // which calls updateGraphicsLayerGeometry via updateLayerCompositingState(), so this should // be optimized. if (parentLayer) childLayer->backing()->updateGraphicsLayerGeometry(); } void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer) { ASSERT(layer->isComposited()); GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers(); hostingLayer->removeAllChildren(); } void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer) { ASSERT(layer->isComposited()); GraphicsLayer* layerAnchor = layer->backing()->childForSuperlayers(); if (layerAnchor->parent() != m_rootPlatformLayer) { layerAnchor->removeFromParent(); if (m_rootPlatformLayer) m_rootPlatformLayer->addChild(layerAnchor); } } void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& ioCompState) { updateLayerCompositingState(layer, StyleDifferenceEqual); // host the document layer in the RenderView's root layer if (layer->isRootLayer()) parentInRootLayer(layer); CompositingState childState = ioCompState; if (layer->isComposited()) childState.m_compositingAncestor = layer; #ifndef NDEBUG ++childState.m_depth; #endif RenderLayerBacking* layerBacking = layer->backing(); // FIXME: make this more incremental if (layer->isComposited()) { layerBacking->parentForSublayers()->removeAllChildren(); layerBacking->updateInternalHierarchy(); } // The children of this stacking context don't need to composite, unless there is // a compositing layer among them, so start by assuming false. childState.m_subtreeIsCompositing = false; if (layer->isStackingContext()) { ASSERT(!layer->m_zOrderListsDirty); Vector* negZOrderList = layer->negZOrderList(); if (negZOrderList && negZOrderList->size() > 0) { for (Vector::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); rebuildCompositingLayerTree(curLayer, childState); if (curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } if (layerBacking && layerBacking->contentsLayer()) { // we only have a contents layer if we have an m_layer layerBacking->contentsLayer()->removeFromParent(); GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer(); hostingLayer->addChild(layerBacking->contentsLayer()); } } ASSERT(!layer->m_normalFlowListDirty); Vector* normalFlowList = layer->normalFlowList(); if (normalFlowList && normalFlowList->size() > 0) { for (Vector::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); rebuildCompositingLayerTree(curLayer, childState); if (curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } if (layer->isStackingContext()) { Vector* posZOrderList = layer->posZOrderList(); if (posZOrderList && posZOrderList->size() > 0) { for (Vector::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); rebuildCompositingLayerTree(curLayer, childState); if (curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } } } void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect) { recursiveRepaintLayerRect(rootRenderLayer(), absRect); } void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect) { if (layer->isComposited()) layer->setBackingNeedsRepaintInRect(rect); if (layer->hasCompositingDescendant()) { Vector* negZOrderList = layer->negZOrderList(); if (negZOrderList) { for (Vector::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); int x = 0, y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); recursiveRepaintLayerRect(curLayer, childRect); } } Vector* posZOrderList = layer->posZOrderList(); if (posZOrderList) { for (Vector::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); int x = 0, y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); recursiveRepaintLayerRect(curLayer, childRect); } } Vector* normalFlowList = layer->normalFlowList(); if (normalFlowList) { for (Vector::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); int x = 0, y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); childRect.move(-x, -y); recursiveRepaintLayerRect(curLayer, childRect); } } } } RenderLayer* RenderLayerCompositor::rootRenderLayer() const { return m_renderView->layer(); } GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const { return m_rootPlatformLayer; } void RenderLayerCompositor::didMoveOnscreen() { if (!m_rootPlatformLayer) return; Frame* frame = m_renderView->frameView()->frame(); Page* page = frame ? frame->page() : 0; if (!page) return; page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer); m_rootLayerAttached = true; } void RenderLayerCompositor::willMoveOffscreen() { if (!m_rootPlatformLayer || !m_rootLayerAttached) return; Frame* frame = m_renderView->frameView()->frame(); Page* page = frame ? frame->page() : 0; if (!page) return; page->chrome()->client()->attachRootGraphicsLayer(frame, 0); m_rootLayerAttached = false; } void RenderLayerCompositor::updateRootLayerPosition() { if (m_rootPlatformLayer) m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); } bool RenderLayerCompositor::has3DContent() const { return layerHas3DContent(rootRenderLayer()); } bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const { return requiresCompositingLayer(layer) || layer->mustOverlayCompositedLayers(); } #define VERBOSE_COMPOSITINGLAYER 0 // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. // Use needsToBeComposited() to determine if a RL actually needs a compositing layer. // static bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const { // FIXME: cache the result of these tests? #if VERBOSE_COMPOSITINGLAYER bool gotReason = false; if (!gotReason && inCompositingMode() && layer->isRootLayer()) { fprintf(stderr, "RenderLayer %p requires compositing layer because: it's the document root\n", layer); gotReason = true; } if (!gotReason && requiresCompositingForTransform(layer->renderer())) { fprintf(stderr, "RenderLayer %p requires compositing layer because: it has 3d transform, perspective, backface, or animating transform\n", layer); gotReason = true; } if (!gotReason && layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) { fprintf(stderr, "RenderLayer %p requires compositing layer because: it has backface-visibility: hidden\n", layer); gotReason = true; } if (!gotReason && clipsCompositingDescendants(layer)) { fprintf(stderr, "RenderLayer %p requires compositing layer because: it has overflow clip\n", layer); gotReason = true; } if (!gotReason && requiresCompositingForAnimation(layer->renderer())) { fprintf(stderr, "RenderLayer %p requires compositing layer because: it has a running transition for opacity or transform\n", layer); gotReason = true; } if (!gotReason) fprintf(stderr, "RenderLayer %p does not require compositing layer\n", layer); #endif // The root layer always has a compositing layer, but it may not have backing. return (inCompositingMode() && layer->isRootLayer()) || requiresCompositingForTransform(layer->renderer()) || layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(layer->renderer()); } // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, // up to the enclosing compositing ancestor. This is required because compositing layers are parented // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, // but a sibling in the z-order hierarchy. bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const { if (!layer->isComposited() || !layer->parent()) return false; RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); if (!compositingAncestor) return false; // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(), // so we only care about clipping between its first child that is our ancestor (the computeClipRoot), // and layer. RenderLayer* computeClipRoot = 0; RenderLayer* curr = layer; while (curr) { RenderLayer* next = curr->parent(); if (next == compositingAncestor) { computeClipRoot = curr; break; } curr = next; } if (!computeClipRoot || computeClipRoot == layer) return false; ClipRects parentRects; layer->parentClipRects(computeClipRoot, parentRects, true); return parentRects.overflowClipRect() != ClipRects::infiniteRect(); } // Return true if the given layer is a stacking context and has compositing child // layers that it needs to clip. In this case we insert a clipping GraphicsLayer // into the hierarchy between this layer and its children in the z-order hierarchy. bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const { // FIXME: need to look at hasClip() too eventually return layer->hasCompositingDescendant() && layer->renderer()->hasOverflowClip(); } bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) { RenderStyle* style = renderer->style(); // Note that we ask the renderer if it has a transform, because the style may have transforms, // but the renderer may be an inline that doesn't suppport them. return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective()); } bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) { AnimationController* animController = renderer->animation(); if (animController) return animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) || animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform); return false; } // If an element has negative z-index children, those children render in front of the // layer background, so we need an extra 'contents' layer for the foreground of the layer // object. bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const { return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0); } void RenderLayerCompositor::ensureRootPlatformLayer() { if (m_rootPlatformLayer) return; m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0); m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); m_rootPlatformLayer->setPosition(FloatPoint(0, 0)); if (GraphicsLayer::graphicsContextsFlipped()) m_rootPlatformLayer->setChildrenTransform(flipTransform()); // Need to clip to prevent transformed content showing outside this frame m_rootPlatformLayer->setMasksToBounds(true); didMoveOnscreen(); } bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const { const RenderStyle* style = layer->renderer()->style(); if (style && (style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective() || style->transform().has3DOperation())) return true; if (layer->isStackingContext()) { Vector* negZOrderList = layer->negZOrderList(); if (negZOrderList) { for (Vector::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (layerHas3DContent(curLayer)) return true; } } Vector* posZOrderList = layer->posZOrderList(); if (posZOrderList) { for (Vector::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (layerHas3DContent(curLayer)) return true; } } } Vector* normalFlowList = layer->normalFlowList(); if (normalFlowList) { for (Vector::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); if (layerHas3DContent(curLayer)) return true; } } return false; } } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING)