void GraphicsLayerUpdater::updateRecursive(RenderLayer& layer, UpdateType updateType, const UpdateContext& context, Vector<RenderLayer*>& layersNeedingPaintInvalidation) { if (layer.hasCompositedLayerMapping()) { CompositedLayerMapping* mapping = layer.compositedLayerMapping(); if (updateType == ForceUpdate || mapping->needsGraphicsLayerUpdate()) { const RenderLayer* compositingContainer = context.compositingContainer(layer); ASSERT(compositingContainer == layer.enclosingLayerWithCompositedLayerMapping(ExcludeSelf)); if (mapping->updateGraphicsLayerConfiguration()) m_needsRebuildTree = true; mapping->updateGraphicsLayerGeometry(compositingContainer, context.compositingStackingContext(), layersNeedingPaintInvalidation); if (mapping->hasUnpositionedOverflowControlsLayers()) layer.scrollableArea()->positionOverflowControls(IntSize()); updateType = mapping->updateTypeForChildren(updateType); mapping->clearNeedsGraphicsLayerUpdate(); } } UpdateContext childContext(context, layer); for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) updateRecursive(*child, updateType, childContext, layersNeedingPaintInvalidation); }
void GraphicsLayerUpdater::update(RenderLayer& layer, UpdateType updateType) { if (layer.hasCompositedLayerMapping()) { CompositedLayerMappingPtr mapping = layer.compositedLayerMapping(); // Note carefully: here we assume that the compositing state of all descendants have been updated already, // so it is legitimate to compute and cache the composited bounds for this layer. mapping->updateCompositedBounds(updateType); if (RenderLayerReflectionInfo* reflection = layer.reflectionInfo()) { if (reflection->reflectionLayer()->hasCompositedLayerMapping()) reflection->reflectionLayer()->compositedLayerMapping()->updateCompositedBounds(ForceUpdate); } mapping->updateGraphicsLayerConfiguration(); updateType = mapping->updateGraphicsLayerGeometry(updateType); mapping->clearNeedsGeometryUpdate(); if (!layer.parent()) layer.compositor()->updateRootLayerPosition(); if (mapping->hasUnpositionedOverflowControlsLayers()) layer.scrollableArea()->positionOverflowControls(); } for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) update(*child, updateType); }
RenderLayer* LinkHighlight::computeEnclosingCompositingLayer() { if (!m_node || !m_node->renderer()) return 0; // Find the nearest enclosing composited layer and attach to it. We may need to cross frame boundaries // to find a suitable layer. RenderObject* renderer = m_node->renderer(); RenderLayerModelObject* repaintContainer; do { repaintContainer = renderer->containerForRepaint(); if (!repaintContainer) { renderer = renderer->frame()->ownerRenderer(); if (!renderer) return 0; } } while (!repaintContainer); RenderLayer* renderLayer = repaintContainer->layer(); if (!renderLayer || renderLayer->compositingState() == NotComposited) return 0; GraphicsLayer* newGraphicsLayer = renderLayer->compositedLayerMapping()->mainGraphicsLayer(); m_clipLayer->setTransform(SkMatrix44()); if (!newGraphicsLayer->drawsContent()) { if (renderLayer->scrollableArea() && renderLayer->scrollableArea()->usesCompositedScrolling()) { ASSERT(renderLayer->hasCompositedLayerMapping() && renderLayer->compositedLayerMapping()->scrollingContentsLayer()); newGraphicsLayer = renderLayer->compositedLayerMapping()->scrollingContentsLayer(); } } if (m_currentGraphicsLayer != newGraphicsLayer) { if (m_currentGraphicsLayer) clearGraphicsLayerLinkHighlightPointer(); m_currentGraphicsLayer = newGraphicsLayer; m_currentGraphicsLayer->addLinkHighlight(this); } return renderLayer; }
RenderLayer* LinkHighlight::computeEnclosingCompositingLayer() { if (!m_node || !m_node->renderer()) return 0; // Find the nearest enclosing composited layer and attach to it. We may need to cross frame boundaries // to find a suitable layer. RenderObject* renderer = m_node->renderer(); RenderLayer* renderLayer; do { renderLayer = renderer->enclosingLayer()->enclosingCompositingLayerForRepaint(); if (!renderLayer) { renderer = renderer->frame()->ownerRenderer(); if (!renderer) return 0; } } while (!renderLayer); CompositedLayerMappingPtr compositedLayerMapping = renderLayer->compositingState() == PaintsIntoGroupedBacking ? renderLayer->groupedMapping() : renderLayer->compositedLayerMapping(); GraphicsLayer* newGraphicsLayer = renderLayer->compositingState() == PaintsIntoGroupedBacking ? compositedLayerMapping->squashingLayer() : compositedLayerMapping->mainGraphicsLayer(); m_clipLayer->setTransform(SkMatrix44(SkMatrix44::kIdentity_Constructor)); if (!newGraphicsLayer->drawsContent()) { if (renderLayer->scrollableArea() && renderLayer->scrollableArea()->usesCompositedScrolling()) { ASSERT(renderLayer->hasCompositedLayerMapping() && renderLayer->compositedLayerMapping()->scrollingContentsLayer()); newGraphicsLayer = compositedLayerMapping->scrollingContentsLayer(); } } if (m_currentGraphicsLayer != newGraphicsLayer) { if (m_currentGraphicsLayer) clearGraphicsLayerLinkHighlightPointer(); m_currentGraphicsLayer = newGraphicsLayer; m_currentGraphicsLayer->addLinkHighlight(this); } return renderLayer; }
void GraphicsLayerUpdater::update(RenderLayer& layer, UpdateType updateType, const UpdateContext& context) { if (layer.hasCompositedLayerMapping()) { CompositedLayerMappingPtr mapping = layer.compositedLayerMapping(); const RenderLayer* compositingContainer = context.compositingContainer(layer); ASSERT(compositingContainer == layer.ancestorCompositingLayer()); if (mapping->updateRequiresOwnBackingStoreForAncestorReasons(compositingContainer)) updateType = ForceUpdate; // Note carefully: here we assume that the compositing state of all descendants have been updated already, // so it is legitimate to compute and cache the composited bounds for this layer. mapping->updateCompositedBounds(updateType); if (RenderLayerReflectionInfo* reflection = layer.reflectionInfo()) { if (reflection->reflectionLayer()->hasCompositedLayerMapping()) reflection->reflectionLayer()->compositedLayerMapping()->updateCompositedBounds(ForceUpdate); } if (mapping->updateGraphicsLayerConfiguration(updateType)) m_needsRebuildTree = true; mapping->updateGraphicsLayerGeometry(updateType, compositingContainer); updateType = mapping->updateTypeForChildren(updateType); mapping->clearNeedsGraphicsLayerUpdate(); if (!layer.parent()) layer.compositor()->updateRootLayerPosition(); if (mapping->hasUnpositionedOverflowControlsLayers()) layer.scrollableArea()->positionOverflowControls(); } UpdateContext childContext(context, layer); for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) update(*child, updateType, childContext); }
bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const { // position:fixed elements that create their own stacking context (e.g. have an explicit z-index, // opacity, transform) can get their own composited layer. A stacking context is required otherwise // z-index and clipping will be broken. if (!renderer->isPositioned()) return false; EPosition position = renderer->style()->position(); bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition; // FIXME: The isStackingContainer check here is redundant. Fixed position elements are always stacking contexts. if (isFixed && !layer->stackingNode()->isStackingContainer()) return false; bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition; if (!isFixed && !isSticky) return false; // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled(). if (Settings* settings = m_renderView.document().settings()) { if (!settings->acceleratedCompositingForFixedPositionEnabled()) return false; } if (isSticky) return isViewportConstrainedFixedOrStickyLayer(layer); RenderObject* container = renderer->container(); // If the renderer is not hooked up yet then we have to wait until it is. if (!container) { *needToRecomputeCompositingRequirements = true; return false; } // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. // They will stay fixed wrt the container rather than the enclosing frame. if (container != &m_renderView) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; return false; } // If the fixed-position element does not have any scrollable ancestor between it and // its container, then we do not need to spend compositor resources for it. Start by // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below. bool hasScrollableAncestor = false; // The FrameView has the scrollbars associated with the top level viewport, so we have to // check the FrameView in addition to the hierarchy of ancestors. FrameView* frameView = m_renderView.frameView(); if (frameView && frameView->isScrollable()) hasScrollableAncestor = true; RenderLayer* ancestor = layer->parent(); while (ancestor && !hasScrollableAncestor) { if (frameView->containsScrollableArea(ancestor->scrollableArea())) hasScrollableAncestor = true; if (ancestor->renderer() == &m_renderView) break; ancestor = ancestor->parent(); } if (!hasScrollableAncestor) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors; return false; } // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) { *needToRecomputeCompositingRequirements = true; return layer->hasCompositedLayerMapping(); } bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant(); if (!paintsContent) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; return false; } // Fixed position elements that are invisible in the current view don't get their own layer. if (FrameView* frameView = m_renderView.frameView()) { LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect(); LayoutRect layerBounds = layer->calculateLayerBounds(layer->compositor()->rootRenderLayer(), 0, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants | RenderLayer::PretendLayerHasOwnBacking); if (!viewBounds.intersects(enclosingIntRect(layerBounds))) { if (viewportConstrainedNotCompositedReason) { *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; *needToRecomputeCompositingRequirements = true; } return false; } } return true; }