GraphicsLayer* PaintLayerCompositor::fixedRootBackgroundLayer() const { // Get the fixed root background from the LayoutView layer's compositedLayerMapping. PaintLayer* viewLayer = m_layoutView.layer(); if (!viewLayer) return nullptr; if (viewLayer->compositingState() == PaintsIntoOwnBacking && viewLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground()) return viewLayer->compositedLayerMapping()->backgroundLayer(); return nullptr; }
void CompositorAnimations::attachCompositedLayers(const Element& element, const Animation& animation) { ASSERT(element.layoutObject()); PaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer(); ASSERT(layer); WebCompositorAnimationPlayer* compositorPlayer = animation.compositorPlayer(); ASSERT(compositorPlayer); ASSERT(layer->compositedLayerMapping()); compositorPlayer->attachLayer(layer->compositedLayerMapping()->mainGraphicsLayer()->platformLayer()); }
TEST_F(CompositedLayerMappingTest, TallLayerWholeDocumentInterestRect) { setBodyInnerHTML("<div id='target' style='width: 200px; height: 10000px; will-change: transform'></div>"); document().settings()->setMainFrameClipsContent(false); document().view()->updateAllLifecyclePhases(); Element* element = document().getElementById("target"); PaintLayer* paintLayer = toLayoutBoxModelObject(element->layoutObject())->layer(); ASSERT_TRUE(paintLayer->graphicsLayerBacking()); ASSERT_TRUE(paintLayer->compositedLayerMapping()); // recomputeInterestRect computes the interest rect; computeInterestRect applies the extra setting to paint everything. EXPECT_RECT_EQ(IntRect(0, 0, 200, 4592), recomputeInterestRect(paintLayer->graphicsLayerBacking())); EXPECT_RECT_EQ(IntRect(0, 0, 200, 10000), computeInterestRect(paintLayer->compositedLayerMapping(), paintLayer->graphicsLayerBacking(), IntRect())); }
bool CompositorAnimations::startAnimationOnCompositor(const Element& element, int group, double startTime, double timeOffset, const Timing& timing, const Animation& animation, const EffectModel& effect, Vector<int>& startedAnimationIds, double animationPlaybackRate) { ASSERT(startedAnimationIds.isEmpty()); ASSERT(isCandidateForAnimationOnCompositor(timing, element, &animation, effect, animationPlaybackRate)); ASSERT(canStartAnimationOnCompositor(element)); const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(effect); PaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer(); ASSERT(layer); Vector<OwnPtr<WebCompositorAnimation>> animations; CompositorAnimationsImpl::getAnimationOnCompositor(timing, group, startTime, timeOffset, keyframeEffect, animations, animationPlaybackRate); ASSERT(!animations.isEmpty()); for (auto& compositorAnimation : animations) { int id = compositorAnimation->id(); if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) { WebCompositorAnimationPlayer* compositorPlayer = animation.compositorPlayer(); ASSERT(compositorPlayer); compositorPlayer->addAnimation(compositorAnimation.leakPtr()); } else if (!layer->compositedLayerMapping()->mainGraphicsLayer()->addAnimation(compositorAnimation.release())) { // FIXME: We should know ahead of time whether these animations can be started. for (int startedAnimationId : startedAnimationIds) cancelAnimationOnCompositor(element, animation, startedAnimationId); startedAnimationIds.clear(); return false; } startedAnimationIds.append(id); } ASSERT(!startedAnimationIds.isEmpty()); return true; }
void GraphicsLayerTreeBuilder::rebuild(PaintLayer& layer, AncestorInfo info) { // 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 paint invalidation if necessary. layer.stackingNode()->updateLayerListsIfNeeded(); const bool hasCompositedLayerMapping = layer.hasCompositedLayerMapping(); CompositedLayerMapping* currentCompositedLayerMapping = layer.compositedLayerMapping(); // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers. // Otherwise children continue to append to the child list of the enclosing layer. GraphicsLayerVector layerChildren; AncestorInfo infoForChildren(info); if (hasCompositedLayerMapping) { infoForChildren.childLayersOfEnclosingCompositedLayer = &layerChildren; infoForChildren.enclosingCompositedLayer = &layer; } #if ENABLE(ASSERT) LayerListMutationDetector mutationChecker(layer.stackingNode()); #endif if (layer.stackingNode()->isStackingContext()) { PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NegativeZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer()) infoForChildren.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->foregroundLayer()); } PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NormalFlowChildren | PositiveZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); if (hasCompositedLayerMapping) { bool parented = false; if (layer.layoutObject()->isLayoutPart()) parented = PaintLayerCompositor::attachFrameContentLayersToIframeLayer(toLayoutPart(layer.layoutObject())); if (!parented) currentCompositedLayerMapping->setSublayers(layerChildren); if (shouldAppendLayer(layer)) info.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->childForSuperlayers()); } if (layer.scrollParent() && layer.scrollParent()->hasCompositedLayerMapping() && layer.scrollParent()->compositedLayerMapping()->needsToReparentOverflowControls() && layer.scrollParent()->getScrollableArea()->topmostScrollChild() == &layer) info.childLayersOfEnclosingCompositedLayer->append(layer.scrollParent()->compositedLayerMapping()->detachLayerForOverflowControls(*info.enclosingCompositedLayer)); }
static CompositedLayerMapping* mappingFromElement(Element* element) { if (!element) return nullptr; LayoutObject* layoutObject = element->layoutObject(); if (!layoutObject || !layoutObject->isBoxModelObject()) return nullptr; PaintLayer* layer = toLayoutBoxModelObject(layoutObject)->layer(); if (!layer) return nullptr; if (!layer->hasCompositedLayerMapping()) return nullptr; return layer->compositedLayerMapping(); }
bool PaintLayerCompositor::attachFrameContentLayersToIframeLayer(LayoutPart* layoutObject) { PaintLayerCompositor* innerCompositor = frameContentsCompositor(layoutObject); if (!innerCompositor || !innerCompositor->staleInCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame) return false; PaintLayer* layer = layoutObject->layer(); if (!layer->hasCompositedLayerMapping()) return false; layer->compositedLayerMapping()->setSublayers(GraphicsLayerVector(1, innerCompositor->rootGraphicsLayer())); return true; }
static void paintLayers(PaintLayer& layer, SimDisplayItemList& displayList) { if (layer.isAllowedToQueryCompositingState() && layer.compositingState() == PaintsIntoOwnBacking) { CompositedLayerMapping* mapping = layer.compositedLayerMapping(); GraphicsLayer* graphicsLayer = mapping->mainGraphicsLayer(); if (graphicsLayer->hasTrackedPaintInvalidations()) { ContentLayerDelegate* delegate = graphicsLayer->contentLayerDelegateForTesting(); delegate->paintContents(&displayList, WebRect(0, 0, layer.size().width(), layer.size().height())); graphicsLayer->resetTrackedPaintInvalidations(); } } for (PaintLayer* child = layer.firstChild(); child; child = child->nextSibling()) paintLayers(*child, displayList); }
bool CompositorAnimations::canAttachCompositedLayers(const Element& element, const Animation& animation) { if (!RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) return false; if (!animation.compositorPlayer()) return false; if (!element.layoutObject() || !element.layoutObject()->isBoxModelObject()) return false; PaintLayer* layer = toLayoutBoxModelObject(element.layoutObject())->layer(); if (!layer || !layer->isAllowedToQueryCompositingState() || !layer->compositedLayerMapping() || !layer->compositedLayerMapping()->mainGraphicsLayer()) return false; if (!layer->compositedLayerMapping()->mainGraphicsLayer()->platformLayer()) return false; return true; }
static WebLayer* webLayerFromElement(Element* element) { if (!element) return 0; LayoutObject* layoutObject = element->layoutObject(); if (!layoutObject || !layoutObject->isBoxModelObject()) return 0; PaintLayer* layer = toLayoutBoxModelObject(layoutObject)->layer(); if (!layer) return 0; if (!layer->hasCompositedLayerMapping()) return 0; CompositedLayerMapping* compositedLayerMapping = layer->compositedLayerMapping(); GraphicsLayer* graphicsLayer = compositedLayerMapping->mainGraphicsLayer(); if (!graphicsLayer) return 0; return graphicsLayer->platformLayer(); }
TEST_P(CompositedLayerMappingTest, VerticalRightLeftWritingModeDocument) { setBodyInnerHTML( "<style>html,body { margin: 0px } html { -webkit-writing-mode: " "vertical-rl}</style> <div id='target' style='width: 10000px; height: " "200px;'></div>"); document().view()->updateAllLifecyclePhases(); document().view()->layoutViewportScrollableArea()->setScrollOffset( ScrollOffset(-5000, 0), ProgrammaticScroll); document().view()->updateAllLifecyclePhases(); PaintLayer* paintLayer = document().layoutViewItem().layer(); ASSERT_TRUE(paintLayer->graphicsLayerBacking()); ASSERT_TRUE(paintLayer->compositedLayerMapping()); // A scroll by -5000px is equivalent to a scroll by (10000 - 5000 - 800)px = // 4200px in non-RTL mode. Expanding the resulting rect by 4000px in each // direction yields this result. EXPECT_RECT_EQ( IntRect(200, 0, 8800, 600), recomputeInterestRect(paintLayer->graphicsLayerBackingForScrolling())); }
bool PaintLayerCompositor::allocateOrClearCompositedLayerMapping(PaintLayer* layer, const CompositingStateTransitionType compositedLayerUpdate) { bool compositedLayerMappingChanged = false; // FIXME: It would be nice to directly use the layer's compositing reason, // but allocateOrClearCompositedLayerMapping also gets called without having updated compositing // requirements fully. switch (compositedLayerUpdate) { case AllocateOwnCompositedLayerMapping: ASSERT(!layer->hasCompositedLayerMapping()); setCompositingModeEnabled(true); // If we need to issue paint invalidations, do so before allocating the compositedLayerMapping and clearing out the groupedMapping. paintInvalidationOnCompositingChange(layer); // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so // that computing paint invalidation rects will know the layer's correct compositingState. // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping? // Need to create a test where a squashed layer pops into compositing. And also to cover all other // sorts of compositingState transitions. layer->setLostGroupedMapping(false); layer->setGroupedMapping(nullptr, PaintLayer::InvalidateLayerAndRemoveFromMapping); layer->ensureCompositedLayerMapping(); compositedLayerMappingChanged = true; // At this time, the ScrollingCooridnator only supports the top-level frame. if (layer->isRootLayer() && m_layoutView.frame()->isLocalRoot()) { if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewRootLayerDidChange(m_layoutView.frameView()); } break; case RemoveOwnCompositedLayerMapping: // PutInSquashingLayer means you might have to remove the composited layer mapping first. case PutInSquashingLayer: if (layer->hasCompositedLayerMapping()) { // If we're removing the compositedLayerMapping from a reflection, clear the source GraphicsLayer's pointer to // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection // are both either composited, or not composited. if (layer->isReflection()) { PaintLayer* sourceLayer = toLayoutBoxModelObject(layer->layoutObject()->parent())->layer(); if (sourceLayer->hasCompositedLayerMapping()) { ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer()); sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(nullptr); } } layer->clearCompositedLayerMapping(); compositedLayerMappingChanged = true; } break; case RemoveFromSquashingLayer: case NoCompositingStateChange: // Do nothing. break; } if (compositedLayerMappingChanged && layer->layoutObject()->isLayoutPart()) { PaintLayerCompositor* innerCompositor = frameContentsCompositor(toLayoutPart(layer->layoutObject())); if (innerCompositor && innerCompositor->staleInCompositingMode()) innerCompositor->updateRootLayerAttachment(); } if (compositedLayerMappingChanged) layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects); // If a fixed position layer gained/lost a compositedLayerMapping or the reason not compositing it changed, // the scrolling coordinator needs to recalculate whether it can do fast scrolling. if (compositedLayerMappingChanged) { if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewFixedObjectsDidChange(m_layoutView.frameView()); } return compositedLayerMappingChanged; }