📄 renderlayercompositor.cpp
字号:
/* * 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 <wtf/CurrentTime.h>#endif#ifndef NDEBUG#include "CString.h"#include "RenderTreeAsText.h"#endif#if ENABLE(3D_TRANSFORMS)// This symbol is used to determine from a script whether 3D transforms are enabled (via 'nm').bool WebCoreHas3DTransforms = true;#endifnamespace 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; if (needsLayer) { enableCompositingMode(); if (!layer->backing()) { layer->ensureBacking(); layerChanged = true; } } else { if (layer->backing()) { layer->clearBacking(); layerChanged = true; } } if (layerChanged) { // Invalidate the parent in this region. RenderLayer* compLayer = layer->ancestorCompositingLayer(); if (compLayer) { // We can't reliably compute a dirty rect, because style may have changed already, // so just dirty the whole parent layer compLayer->setBackingNeedsRepaint(); // 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<RenderLayer*>* negZOrderList = layer->negZOrderList(); if (negZOrderList) { for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); } } } Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); if (posZOrderList) { for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { RenderLayer* curLayer = (*it); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); } } } Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); if (normalFlowList) { for (Vector<RenderLayer*>::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); setForcedCompositingLayer(layer, 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<RenderLayer*>* negZOrderList = layer->negZOrderList(); if (negZOrderList && negZOrderList->size() > 0) { for (Vector<RenderLayer*>::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 setForcedCompositingLayer(layer, true); childState.m_compositingAncestor = layer; } } } } ASSERT(!layer->m_normalFlowListDirty); Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); if (normalFlowList && normalFlowList->size() > 0) { for (Vector<RenderLayer*>::const_iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { RenderLayer* curLayer = (*it); computeCompositingRequirements(curLayer, childState); } } if (layer->isStackingContext()) { Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); if (posZOrderList && posZOrderList->size() > 0) { for (Vector<RenderLayer*>::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)) setForcedCompositingLayer(layer, 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::setForcedCompositingLayer(RenderLayer* layer, bool force){ if (force) { layer->ensureBacking(); layer->backing()->forceCompositingLayer();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -