diff options
Diffstat (limited to 'WebCore/rendering/RenderLayerCompositor.cpp')
-rw-r--r-- | WebCore/rendering/RenderLayerCompositor.cpp | 591 |
1 files changed, 376 insertions, 215 deletions
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index fec3b1d..fb15800 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -38,7 +38,9 @@ #include "HitTestResult.h" #include "Page.h" #include "RenderLayerBacking.h" +#include "RenderVideo.h" #include "RenderView.h" +#include "Settings.h" #if PROFILE_LAYER_REBUILD #include <wtf/CurrentTime.h> @@ -58,34 +60,29 @@ namespace WebCore { struct CompositingState { CompositingState(RenderLayer* compAncestor) - : m_subtreeIsCompositing(false) - , m_compositingAncestor(compAncestor) + : m_compositingAncestor(compAncestor) + , m_subtreeIsCompositing(false) #ifndef NDEBUG , m_depth(0) #endif { } - bool m_subtreeIsCompositing; RenderLayer* m_compositingAncestor; + bool m_subtreeIsCompositing; #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_hasAcceleratedCompositing(true) + , m_compositingConsultsOverlap(true) , m_compositing(false) , m_rootLayerAttached(false) - , m_compositingLayersNeedUpdate(false) + , m_compositingLayersNeedRebuild(false) #if PROFILE_LAYER_REBUILD , m_rootLayerUpdateCount(0) #endif // PROFILE_LAYER_REBUILD @@ -108,39 +105,52 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) // the empty root layer, which has minimal overhead. if (m_compositing) ensureRootPlatformLayer(); + else + destroyRootPlatformLayer(); } } -void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate) +void RenderLayerCompositor::cacheAcceleratedCompositingEnabledFlag() { - if (inCompositingMode()) { - if (!m_compositingLayersNeedUpdate && needUpdate) - scheduleViewUpdate(); + bool hasAcceleratedCompositing = false; + if (Settings* settings = m_renderView->document()->settings()) + hasAcceleratedCompositing = settings->acceleratedCompositingEnabled(); - m_compositingLayersNeedUpdate = needUpdate; - } + if (hasAcceleratedCompositing != m_hasAcceleratedCompositing) + setCompositingLayersNeedRebuild(); + + m_hasAcceleratedCompositing = hasAcceleratedCompositing; +} + +void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild) +{ + if (inCompositingMode()) + m_compositingLayersNeedRebuild = needRebuild; } -void RenderLayerCompositor::scheduleViewUpdate() +void RenderLayerCompositor::scheduleSync() { Frame* frame = m_renderView->frameView()->frame(); Page* page = frame ? frame->page() : 0; if (!page) return; - page->chrome()->client()->scheduleViewUpdate(); + page->chrome()->client()->scheduleCompositingLayerSync(); } void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) { - if (!m_compositingLayersNeedUpdate) + // When m_compositingConsultsOverlap is true, then layer positions affect compositing, + // so we can only bail here when we're not looking at overlap. + if (!m_compositingLayersNeedRebuild && !m_compositingConsultsOverlap) return; ASSERT(inCompositingMode()); + bool needLayerRebuild = m_compositingLayersNeedRebuild; if (!updateRoot) { - // Only clear the flag if we're updating the entire hierarchy - m_compositingLayersNeedUpdate = false; + // Only clear the flag if we're updating the entire hierarchy. + m_compositingLayersNeedRebuild = false; updateRoot = rootRenderLayer(); } @@ -156,13 +166,20 @@ void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) // complex. { CompositingState compState(updateRoot); - computeCompositingRequirements(updateRoot, compState); + bool layersChanged; + if (m_compositingConsultsOverlap) { + OverlapMap overlapTestRequestMap; + computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged); + } else + computeCompositingRequirements(updateRoot, 0, compState, layersChanged); + + needLayerRebuild |= layersChanged; } // Now create and parent the compositing layers. { CompositingState compState(updateRoot); - rebuildCompositingLayerTree(updateRoot, compState); + rebuildCompositingLayerTree(updateRoot, compState, needLayerRebuild); } #if PROFILE_LAYER_REBUILD @@ -171,16 +188,23 @@ void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot) fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n", m_rootLayerUpdateCount, 1000.0 * (endTime - startTime)); #endif - ASSERT(updateRoot || !m_compositingLayersNeedUpdate); + ASSERT(updateRoot || !m_compositingLayersNeedRebuild); + + if (!hasAcceleratedCompositing()) + enableCompositingMode(false); } -bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) +bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) { - bool needsLayer = needsToBeComposited(layer); bool layerChanged = false; - if (needsLayer) { + if (needsToBeComposited(layer)) { enableCompositingMode(); + + // 3D transforms turn off the testing of overlap. + if (requiresCompositingForTransform(layer->renderer())) + setCompositingConsultsOverlap(false); + if (!layer->backing()) { // If we need to repaint, do so before making backing @@ -195,12 +219,30 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, Comp layer->clearBacking(); layerChanged = true; + // The layer's cached repaints rects are relative to the repaint container, so change when + // compositing changes; we need to update them here. + layer->computeRepaintRects(); + // If we need to repaint, do so now that we've removed the backing if (shouldRepaint == CompositingChangeRepaintNow) repaintOnCompositingChange(layer); } } +#if ENABLE(VIDEO) + if (layerChanged && layer->renderer()->isVideo()) { + // If it's a video, give the media player a chance to hook up to the layer. + RenderVideo* video = toRenderVideo(layer->renderer()); + video->acceleratedRenderingStateChanged(); + } +#endif + return layerChanged; +} + +bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) +{ + bool layerChanged = updateBacking(layer, shouldRepaint); + // See if we need content or clipping layers. Methods called here should assume // that the compositing state of descendant layers has not been updated yet. if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration()) @@ -211,6 +253,10 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, Comp void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) { + // If the renderer is not attached yet, no need to repaint. + if (!layer->renderer()->parent()) + return; + RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint(); if (!repaintContainer) repaintContainer = m_renderView; @@ -226,17 +272,27 @@ void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) // 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 RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) { + if (!layer->isSelfPaintingLayer()) + return IntRect(); + IntRect boundingBoxRect, unionBounds; boundingBoxRect = unionBounds = layer->localBoundingBox(); + if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) { + int ancestorRelX = 0, ancestorRelY = 0; + layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY); + boundingBoxRect.move(ancestorRelX, ancestorRelY); + return boundingBoxRect; + } + 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 (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = negZOrderList->at(i); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); @@ -244,10 +300,10 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye } } - Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); - if (posZOrderList) { - for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = posZOrderList->at(i); if (!curLayer->isComposited()) { IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(childUnionBounds); @@ -255,10 +311,10 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye } } - Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); - if (normalFlowList) { - for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = normalFlowList->at(i); if (!curLayer->isComposited()) { IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer); unionBounds.unite(curAbsBounds); @@ -276,39 +332,38 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye 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(); + setCompositingLayersNeedRebuild(); } 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()) + if (!child->isComposited() || parent->renderer()->documentBeingDestroyed()) return; + setCompositingParent(child, 0); + RenderLayer* compLayer = parent->enclosingCompositingLayer(); if (compLayer) { - IntRect ancestorRect = calculateCompositedBounds(child, compLayer); - compLayer->setBackingNeedsRepaintInRect(ancestorRect); + ASSERT(compLayer->backing()); + IntRect compBounds = child->backing()->compositedBounds(); + + int offsetX = 0, offsetY = 0; + child->convertToLayerCoords(compLayer, offsetX, offsetY); + compBounds.move(offsetX, offsetY); + + compLayer->setBackingNeedsRepaintInRect(compBounds); + // 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(); + setCompositingLayersNeedRebuild(); } RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const @@ -323,6 +378,31 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend return 0; } +void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed) +{ + if (layer->isRootLayer()) + return; + + if (!boundsComputed) { + layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); + boundsComputed = true; + } + + overlapMap.add(layer, layerBounds); +} + +bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const IntRect& layerBounds) +{ + RenderLayerCompositor::OverlapMap::const_iterator end = overlapMap.end(); + for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) { + const IntRect& bounds = it->second; + if (layerBounds.intersects(bounds)) + return true; + } + + return false; +} + // 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 @@ -332,7 +412,7 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend // 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) +void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, struct CompositingState& compositingState, bool& layersChanged) { layer->updateLayerPosition(); layer->updateZOrderLists(); @@ -340,61 +420,82 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, s // Clear the flag layer->setHasCompositingDescendant(false); - layer->setMustOverlayCompositedLayers(ioCompState.m_subtreeIsCompositing); - const bool willBeComposited = needsToBeComposited(layer); - // If we are going to become composited, repaint the old rendering destination - if (!layer->isComposited() && willBeComposited) - repaintOnCompositingChange(layer); + bool mustOverlapCompositedLayers = compositingState.m_subtreeIsCompositing; - ioCompState.m_subtreeIsCompositing = willBeComposited; + bool haveComputedBounds = false; + IntRect absBounds; + if (overlapMap && mustOverlapCompositedLayers) { + // If we're testing for overlap, we only need to composite if we overlap something that is already composited. + absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); + haveComputedBounds = true; + mustOverlapCompositedLayers &= overlapsCompositedLayers(*overlapMap, absBounds); + } + + layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); + + // The children of this layer don't need to composite, unless there is + // a compositing layer among them, so start by inheriting the compositing + // ancestor with m_subtreeIsCompositing set to false. + CompositingState childState(compositingState.m_compositingAncestor); +#ifndef NDEBUG + ++childState.m_depth; +#endif - CompositingState childState = ioCompState; - if (willBeComposited) + const bool willBeComposited = needsToBeComposited(layer); + if (willBeComposited) { + // Tell the parent it has compositing descendants. + compositingState.m_subtreeIsCompositing = true; + // This layer now acts as the ancestor for kids. childState.m_compositingAncestor = layer; + if (overlapMap) + addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); + } - // 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; +#if ENABLE(VIDEO) + // Video is special. It's a replaced element with a content layer, but has shadow content + // for the controller that must render in front. Without this, the controls fail to show + // when the video element is a stacking context (e.g. due to opacity or transform). + if (willBeComposited && layer->renderer()->isVideo()) + childState.m_subtreeIsCompositing = true; #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 (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = negZOrderList->at(i); + computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); + + // 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); + // make layer compositing + layer->setMustOverlapCompositedLayers(true); childState.m_compositingAncestor = layer; + if (overlapMap) + addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); } } } } 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 (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = normalFlowList->at(i); + computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); } } 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 (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = posZOrderList->at(i); + computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); } } } @@ -403,24 +504,40 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, s // 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); + (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1)) { + layer->setMustOverlapCompositedLayers(true); + if (overlapMap) + addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); + } // Subsequent layers in the parent stacking context also need to composite. if (childState.m_subtreeIsCompositing) - ioCompState.m_subtreeIsCompositing = true; + compositingState.m_subtreeIsCompositing = true; + + // If the layer is going into compositing mode, repaint its old location. + if (!layer->isComposited() && needsToBeComposited(layer)) + repaintOnCompositingChange(layer); // 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); + + // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree(). + if (updateBacking(layer, CompositingChangeRepaintNow)) + layersChanged = true; } void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) { ASSERT(childLayer->isComposited()); - ASSERT(!parentLayer || parentLayer->isComposited()); - + + // It's possible to be called with a parent that isn't yet composited when we're doing + // partial updates as required by painting or hit testing. Just bail in that case; + // we'll do a full layer update soon. + if (!parentLayer || !parentLayer->isComposited()) + return; + if (parentLayer) { GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers(); GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers(); @@ -451,20 +568,45 @@ void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer) } } -void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& ioCompState) +#if ENABLE(VIDEO) +bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const { - bool wasComposited = layer->isComposited(); + // FIXME: ideally we need to look at all ancestors for mask or video. But for now, + // just bail on the obvious cases. + if (o->hasMask() || o->hasReflection() || !m_hasAcceleratedCompositing) + return false; + + return o->supportsAcceleratedRendering(); +} +#endif +void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& compositingState, bool updateHierarchy) +{ // Make the layer compositing if necessary, and set up clipping and content layers. // Note that we can only do work here that is independent of whether the descendant layers // have been processed. computeCompositingRequirements() will already have done the repaint if necessary. - updateLayerCompositingState(layer, CompositingChangeWillRepaintLater); + RenderLayerBacking* layerBacking = layer->backing(); + if (layerBacking) { + // The compositing state of all our children has been updated already, so now + // we can compute and cache the composited bounds for this layer. + layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer)); + + layerBacking->updateGraphicsLayerConfiguration(); + layerBacking->updateGraphicsLayerGeometry(); + + if (!layer->parent()) + updateRootLayerPosition(); + + // FIXME: make this more incremental + if (updateHierarchy) + layerBacking->parentForSublayers()->removeAllChildren(); + } // host the document layer in the RenderView's root layer - if (layer->isRootLayer()) + if (updateHierarchy && layer->isRootLayer() && layer->isComposited()) parentInRootLayer(layer); - CompositingState childState = ioCompState; + CompositingState childState = compositingState; if (layer->isComposited()) childState.m_compositingAncestor = layer; @@ -472,14 +614,6 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru ++childState.m_depth; #endif - RenderLayerBacking* layerBacking = layer->backing(); - - // FIXME: make this more incremental - if (layerBacking) { - 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; @@ -487,58 +621,89 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru 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); - rebuildCompositingLayerTree(curLayer, childState); - if (curLayer->isComposited()) + if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = negZOrderList->at(i); + rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); + if (updateHierarchy && curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } - if (layerBacking && layerBacking->contentsLayer()) { + if (updateHierarchy && layerBacking && layerBacking->foregroundLayer()) { // we only have a contents layer if we have an m_layer - layerBacking->contentsLayer()->removeFromParent(); + layerBacking->foregroundLayer()->removeFromParent(); GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer(); - hostingLayer->addChild(layerBacking->contentsLayer()); + hostingLayer->addChild(layerBacking->foregroundLayer()); } } ASSERT(!layer->m_normalFlowListDirty); - Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); - if (normalFlowList && normalFlowList->size() > 0) { - for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { - RenderLayer* curLayer = (*it); - rebuildCompositingLayerTree(curLayer, childState); - if (curLayer->isComposited()) + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = normalFlowList->at(i); + rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); + if (updateHierarchy && curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } 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); - rebuildCompositingLayerTree(curLayer, childState); - if (curLayer->isComposited()) + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = posZOrderList->at(i); + rebuildCompositingLayerTree(curLayer, childState, updateHierarchy); + if (updateHierarchy && curLayer->isComposited()) setCompositingParent(curLayer, childState.m_compositingAncestor); } } } +} + + +// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry. +void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth updateDepth) +{ + if (layer != compositingAncestor) { + if (RenderLayerBacking* layerBacking = layer->backing()) { + layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer)); + layerBacking->updateGraphicsLayerGeometry(); + if (updateDepth == RenderLayerBacking::CompositingChildren) + return; + } + } + + if (!layer->hasCompositingDescendant()) + return; - if (layerBacking) { - // Do work here that requires that we've processed all of the descendant layers - layerBacking->updateGraphicsLayerGeometry(); - } else if (wasComposited) { - // We stopped being a compositing layer. Now that our descendants have been udated, we can - // repaint our new rendering destination. - repaintOnCompositingChange(layer); + if (layer->isStackingContext()) { + if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) + updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), updateDepth); + } + } + + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) + updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), updateDepth); + } + + if (layer->isStackingContext()) { + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) + updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), updateDepth); + } } } + void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect) { recursiveRepaintLayerRect(rootRenderLayer(), absRect); @@ -550,10 +715,10 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const layer->setBackingNeedsRepaintInRect(rect); if (layer->hasCompositingDescendant()) { - Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); - if (negZOrderList) { - for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = negZOrderList->at(i); int x = 0, y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); @@ -562,10 +727,10 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const } } - Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); - if (posZOrderList) { - for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = posZOrderList->at(i); int x = 0, y = 0; curLayer->convertToLayerCoords(layer, x, y); IntRect childRect(rect); @@ -573,17 +738,16 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const recursiveRepaintLayerRect(curLayer, childRect); } } - - Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); - if (normalFlowList) { - for (Vector<RenderLayer*>::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); - } + } + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = normalFlowList->at(i); + int x = 0, y = 0; + curLayer->convertToLayerCoords(layer, x, y); + IntRect childRect(rect); + childRect.move(-x, -y); + recursiveRepaintLayerRect(curLayer, childRect); } } } @@ -629,7 +793,15 @@ void RenderLayerCompositor::willMoveOffscreen() void RenderLayerCompositor::updateRootLayerPosition() { if (m_rootPlatformLayer) - m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); + m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight())); +} + +void RenderLayerCompositor::didStartAcceleratedAnimation() +{ + // If an accelerated animation or transition runs, we have to turn off overlap checking because + // we don't do layout for every frame, but we have to ensure that the layering is + // correct between the animating object and other objects on the page. + setCompositingConsultsOverlap(false); } bool RenderLayerCompositor::has3DContent() const @@ -639,52 +811,21 @@ bool RenderLayerCompositor::has3DContent() const bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const { - return requiresCompositingLayer(layer) || layer->mustOverlayCompositedLayers(); -} + if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer()) + return false; -#define VERBOSE_COMPOSITINGLAYER 0 + return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers(); +} // 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()) || + requiresCompositingForVideo(layer->renderer()) || layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden || clipsCompositingDescendants(layer) || requiresCompositingForAnimation(layer->renderer()); @@ -737,7 +878,7 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer layer->renderer()->hasOverflowClip(); } -bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) +bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const { RenderStyle* style = renderer->style(); // Note that we ask the renderer if it has a transform, because the style may have transforms, @@ -745,12 +886,23 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* render return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective()); } -bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) +bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const { - AnimationController* animController = renderer->animation(); - if (animController) - return animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) || - animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform); +#if ENABLE(VIDEO) + if (renderer->isVideo()) { + RenderVideo* video = toRenderVideo(renderer); + return canAccelerateVideoRendering(video); + } +#endif + return false; +} + +bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const +{ + if (AnimationController* animController = renderer->animation()) { + return (animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode()) + || animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform); + } return false; } @@ -768,11 +920,10 @@ void RenderLayerCompositor::ensureRootPlatformLayer() return; m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0); - m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); + m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight())); m_rootPlatformLayer->setPosition(FloatPoint(0, 0)); - - if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp) - m_rootPlatformLayer->setChildrenTransform(flipTransform()); + // The root layer does flipping if we need it on this platform. + m_rootPlatformLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation()); // Need to clip to prevent transformed content showing outside this frame m_rootPlatformLayer->setMasksToBounds(true); @@ -780,6 +931,16 @@ void RenderLayerCompositor::ensureRootPlatformLayer() didMoveOnscreen(); } +void RenderLayerCompositor::destroyRootPlatformLayer() +{ + if (!m_rootPlatformLayer) + return; + + willMoveOffscreen(); + delete m_rootPlatformLayer; + m_rootPlatformLayer = 0; +} + bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const { const RenderStyle* style = layer->renderer()->style(); @@ -791,29 +952,29 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const return true; if (layer->isStackingContext()) { - Vector<RenderLayer*>* negZOrderList = layer->negZOrderList(); - if (negZOrderList) { - for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { + size_t listSize = negZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = negZOrderList->at(i); if (layerHas3DContent(curLayer)) return true; } } - Vector<RenderLayer*>* posZOrderList = layer->posZOrderList(); - if (posZOrderList) { - for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { + size_t listSize = posZOrderList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = posZOrderList->at(i); if (layerHas3DContent(curLayer)) return true; } } } - Vector<RenderLayer*>* normalFlowList = layer->normalFlowList(); - if (normalFlowList) { - for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) { - RenderLayer* curLayer = (*it); + if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { + size_t listSize = normalFlowList->size(); + for (size_t i = 0; i < listSize; ++i) { + RenderLayer* curLayer = normalFlowList->at(i); if (layerHas3DContent(curLayer)) return true; } |