From 09cdf3e990745cfbcada2d0a49ef371029fc6a97 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Tue, 16 Mar 2010 15:35:12 +0000 Subject: Refactor how we set up the layers hierarchy when using fixed composited layers, and fix the z-index position. Bug:2497910 Bug:2450006 We add a new COMPOSITED_FIXED_ELEMENTS define to isolate the changes in the webkit common code. We previously had a problem where the hierarchy of GraphicsLayer (i.e. the backed surfaces associated to the composited RenderLayer) was not reflecting that layers were children of a fixed layer. The workaround we currently have is not fully satisfactory, due to the way we draw layers on screen (in some cases layers were wrongly translated, see Bug:2497910). Instead, modifying the webkit common code simplify things a lot, and makes the patch more likely to be upstreamed to webkit, as it's now a reasonably well-delimited feature (use composited layers for fixed elements). What we do now is to consider fixed elements as a stacking context, which makes all layers children of such elements children too in the GraphicsLayer hierarchy, and modifying the offset of those children accordingly (in RenderLayer.cpp). In addition, we fixes the z-index bugs we had by signaling that there is a fixed element to its siblings, and turning the siblings as composited layers as well (so that the ordering works fully UI-side). Change-Id: I735c6c14d955ef54653f0053187d3495bef1f332 --- WebCore/rendering/RenderLayerCompositor.cpp | 61 ++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 10 deletions(-) (limited to 'WebCore/rendering/RenderLayerCompositor.cpp') diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index a831a8b..2768461 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -67,6 +67,9 @@ struct CompositingState { CompositingState(RenderLayer* compAncestor) : m_compositingAncestor(compAncestor) , m_subtreeIsCompositing(false) +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + , m_fixedSibling(false) +#endif #ifndef NDEBUG , m_depth(0) #endif @@ -75,6 +78,9 @@ struct CompositingState { RenderLayer* m_compositingAncestor; bool m_subtreeIsCompositing; +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + bool m_fixedSibling; +#endif #ifndef NDEBUG int m_depth; #endif @@ -496,7 +502,19 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O #endif const bool willBeComposited = needsToBeComposited(layer); + +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + // If we are a fixed layer, signal it to our siblings + if (layer->isFixed()) + compositingState.m_fixedSibling = true; + + if (!willBeComposited && compositingState.m_fixedSibling) + layer->setMustOverlapCompositedLayers(true); + + if (willBeComposited || compositingState.m_fixedSibling) { +#else if (willBeComposited) { +#endif // Tell the parent it has compositing descendants. compositingState.m_subtreeIsCompositing = true; // This layer now acts as the ancestor for kids. @@ -517,6 +535,25 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O ASSERT(!layer->m_zOrderListsDirty); if (Vector* negZOrderList = layer->negZOrderList()) { size_t listSize = negZOrderList->size(); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + childState.m_fixedSibling = false; + + // For the negative z-order, if we have a fixed layer + // we need to make all the siblings composited layers. + // Otherwise a negative layer (below the fixed layer) could + // still be drawn onto a higher z-order layer (e.g. the body) + // if not immediately intersecting with our fixed layer. + // So it's not enough here to only set m_fixedSibling for + // subsequent siblings as we do for the normal flow + // and positive z-order. + for (size_t j = 0; j < listSize; ++j) { + if ((negZOrderList->at(j))->isFixed()) { + childState.m_fixedSibling = true; + break; + } + } +#endif + for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = negZOrderList->at(i); computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); @@ -537,6 +574,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O ASSERT(!layer->m_normalFlowListDirty); if (Vector* normalFlowList = layer->normalFlowList()) { size_t listSize = normalFlowList->size(); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + childState.m_fixedSibling = false; +#endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = normalFlowList->at(i); computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); @@ -546,6 +586,9 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O if (layer->isStackingContext()) { if (Vector* posZOrderList = layer->posZOrderList()) { size_t listSize = posZOrderList->size(); +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + childState.m_fixedSibling = false; +#endif for (size_t i = 0; i < listSize; ++i) { RenderLayer* curLayer = posZOrderList->at(i); computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); @@ -927,14 +970,12 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer()) return false; -#if PLATFORM(ANDROID) - // if an ancestor is fixed positionned, we need to be composited... - RenderObject* renderer = layer->renderer(); - RenderObject* parent = renderer->parent(); - while (parent && (parent = renderer->parent())) { - if (parent->isPositioned() && parent->style()->position() == FixedPosition) - return true; - renderer = parent; +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + // if an ancestor is fixed positioned, we need to be composited... + const RenderLayer* currLayer = layer; + while ((currLayer = currLayer->parent())) { + if (currLayer->isComposited() && currLayer->isFixed()) + return true; } #endif @@ -955,8 +996,8 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c // The root layer always has a compositing layer, but it may not have backing. return (inCompositingMode() && layer->isRootLayer()) || requiresCompositingForTransform(renderer) || -#if PLATFORM(ANDROID) - (renderer->isPositioned() && renderer->style()->position() == FixedPosition) || +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + layer->isFixed() || #else requiresCompositingForVideo(renderer) || requiresCompositingForCanvas(renderer) || -- cgit v1.1