diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/RenderLayerBacking.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/rendering/RenderLayerBacking.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderLayerBacking.cpp | 1868 |
1 files changed, 1055 insertions, 813 deletions
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp index 1c1c6e9a8..a8961494a 100644 --- a/Source/WebCore/rendering/RenderLayerBacking.cpp +++ b/Source/WebCore/rendering/RenderLayerBacking.cpp @@ -13,7 +13,7 @@ * 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 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 @@ -25,19 +25,18 @@ #include "config.h" -#if USE(ACCELERATED_COMPOSITING) - #include "RenderLayerBacking.h" -#include "AnimationController.h" +#include "CSSAnimationController.h" #include "CanvasRenderingContext.h" #include "CSSPropertyNames.h" #include "CachedImage.h" #include "Chrome.h" -#include "FontCache.h" +#include "FilterEffectRenderer.h" #include "FrameView.h" #include "GraphicsContext.h" #include "GraphicsLayer.h" +#include "HTMLBodyElement.h" #include "HTMLCanvasElement.h" #include "HTMLIFrameElement.h" #include "HTMLMediaElement.h" @@ -46,13 +45,16 @@ #include "InspectorInstrumentation.h" #include "KeyframeList.h" #include "MainFrame.h" +#include "Page.h" #include "PluginViewBase.h" #include "ProgressTracker.h" #include "RenderFlowThread.h" +#include "RenderHTMLCanvas.h" #include "RenderIFrame.h" #include "RenderImage.h" #include "RenderLayerCompositor.h" #include "RenderEmbeddedObject.h" +#include "RenderMedia.h" #include "RenderNamedFlowFragment.h" #include "RenderRegion.h" #include "RenderVideo.h" @@ -61,28 +63,20 @@ #include "Settings.h" #include "StyleResolver.h" #include "TiledBacking.h" -#include <wtf/text/StringBuilder.h> - -#if ENABLE(CSS_FILTERS) -#include "FilterEffectRenderer.h" -#endif -#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) -#include "GraphicsContext3D.h" +#if PLATFORM(IOS) +#include "RuntimeApplicationChecks.h" #endif namespace WebCore { using namespace HTMLNames; -static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); -static IntRect clipBox(RenderBox& renderer); - CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer) { ASSERT(renderer.isCanvas()); - const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer.node()); + const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer.node()); CanvasRenderingContext* context = canvas->renderingContext(); if (!context || !context->isAccelerated()) return UnacceleratedCanvas; @@ -97,106 +91,86 @@ CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer #endif } -// Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor. -static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer) -{ - Page* page = layer.renderer().frame().page(); - if (!page) - return 0; - - return page->scrollingCoordinator(); -} - -bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false; - RenderLayerBacking::RenderLayerBacking(RenderLayer& layer) : m_owningLayer(layer) - , m_scrollLayerID(0) - , m_artificiallyInflatedBounds(false) - , m_isMainFrameRenderViewLayer(false) - , m_usingTiledCacheLayer(false) - , m_requiresOwnBackingStore(true) -#if ENABLE(CSS_FILTERS) - , m_canCompositeFilters(false) -#endif - , m_backgroundLayerPaintsFixedRootBackground(false) { - Page* page = renderer().frame().page(); - - if (layer.isRootLayer() && page) { - if (renderer().frame().isMainFrame()) - m_isMainFrameRenderViewLayer = true; - - m_usingTiledCacheLayer = page->chrome().client().shouldUseTiledBackingForFrameView(renderer().frame().view()); + if (layer.isRootLayer()) { + m_isMainFrameRenderViewLayer = renderer().frame().isMainFrame(); + m_isMainFrameLayerWithTiledBacking = renderer().page().chrome().client().shouldUseTiledBackingForFrameView(renderer().view().frameView()); } createPrimaryGraphicsLayer(); - if (m_usingTiledCacheLayer && page) { - TiledBacking* tiledBacking = this->tiledBacking(); - - tiledBacking->setIsInWindow(page->isInWindow()); + if (TiledBacking* tiledBacking = this->tiledBacking()) { + tiledBacking->setIsInWindow(renderer().page().isInWindow()); - if (m_isMainFrameRenderViewLayer) { - tiledBacking->setExposedRect(renderer().frame().view()->exposedRect()); - tiledBacking->setUnparentsOffscreenTiles(true); - setTiledBackingHasMargins(page->settings().backgroundShouldExtendBeyondPage()); + if (m_isMainFrameLayerWithTiledBacking) { + tiledBacking->setScrollingPerformanceLoggingEnabled(renderer().settings().scrollingPerformanceLoggingEnabled()); + adjustTiledBackingCoverage(); } - - tiledBacking->setScrollingPerformanceLoggingEnabled(page->settings().scrollingPerformanceLoggingEnabled()); - adjustTiledBackingCoverage(); } } RenderLayerBacking::~RenderLayerBacking() { updateAncestorClippingLayer(false); + updateChildClippingStrategy(false); updateDescendantClippingLayer(false); updateOverflowControlsLayers(false, false, false); updateForegroundLayer(false); updateBackgroundLayer(false); - updateMaskLayer(false); + updateMaskingLayer(false, false); updateScrollingLayers(false); - detachFromScrollingCoordinator(); + detachFromScrollingCoordinator(Scrolling | ViewportConstrained); destroyGraphicsLayers(); } void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer) { - if (layer && layer->usingTiledBacking()) + if (layer && layer->type() == GraphicsLayer::Type::Normal && layer->tiledBacking()) compositor().layerTiledBackingUsageChanged(layer, false); } -std::unique_ptr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name) +std::unique_ptr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name, GraphicsLayer::Type layerType) { - GraphicsLayerFactory* graphicsLayerFactory = 0; - if (Page* page = renderer().frame().page()) - graphicsLayerFactory = page->chrome().client().graphicsLayerFactory(); + auto* graphicsLayerFactory = renderer().page().chrome().client().graphicsLayerFactory(); - std::unique_ptr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this); + std::unique_ptr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, *this, layerType); -#ifndef NDEBUG graphicsLayer->setName(name); -#else - UNUSED_PARAM(name); -#endif - graphicsLayer->setMaintainsPixelAlignment(compositor().keepLayersPixelAligned()); -#if PLATFORM(MAC) && USE(CA) +#if PLATFORM(COCOA) && USE(CA) graphicsLayer->setAcceleratesDrawing(compositor().acceleratedDrawingEnabled()); -#endif + graphicsLayer->setUsesDisplayListDrawing(compositor().displayListDrawingEnabled()); +#endif return graphicsLayer; } -bool RenderLayerBacking::shouldUseTiledBacking(const GraphicsLayer*) const +void RenderLayerBacking::setUsesDisplayListDrawing(bool usesDisplayListDrawing) { - return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer; + // Note that this only affects the primary layer. + if (usesDisplayListDrawing == m_graphicsLayer->usesDisplayListDrawing()) + return; + + m_graphicsLayer->setUsesDisplayListDrawing(usesDisplayListDrawing); + if (m_graphicsLayer->drawsContent()) + m_graphicsLayer->setNeedsDisplay(); } -bool RenderLayerBacking::tiledBackingHasMargin() const +String RenderLayerBacking::displayListAsText(DisplayList::AsTextFlags flags) const { - return m_usingTiledCacheLayer && tiledBacking()->hasMargins(); + return m_graphicsLayer->displayListAsText(flags); +} + +void RenderLayerBacking::setIsTrackingDisplayListReplay(bool isTrackingReplay) +{ + m_graphicsLayer->setIsTrackingDisplayListReplay(isTrackingReplay); +} + +String RenderLayerBacking::replayDisplayListAsText(DisplayList::AsTextFlags flags) const +{ + return m_graphicsLayer->replayDisplayListAsText(flags); } void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking) @@ -209,7 +183,7 @@ TiledBacking* RenderLayerBacking::tiledBacking() const return m_graphicsLayer->tiledBacking(); } -static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backing) +static TiledBacking::TileCoverage computePageTiledBackingCoverage(RenderLayerBacking* backing) { // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability. FrameView& frameView = backing->owningLayer().renderer().view().frameView(); @@ -217,38 +191,31 @@ static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backin TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea; bool useMinimalTilesDuringLiveResize = frameView.inLiveResize(); if (frameView.speculativeTilingEnabled() && !useMinimalTilesDuringLiveResize) { - bool clipsToExposedRect = !frameView.exposedRect().isInfinite(); + bool clipsToExposedRect = static_cast<bool>(frameView.viewExposedRect()); if (frameView.horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect) tileCoverage |= TiledBacking::CoverageForHorizontalScrolling; if (frameView.verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect) tileCoverage |= TiledBacking::CoverageForVerticalScrolling; } - if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(backing->owningLayer())) { - // Ask our TiledBacking for large tiles unless the only reason we're main-thread-scrolling - // is a page overlay (find-in-page, the Web Inspector highlight mechanism, etc.). - if (scrollingCoordinator->synchronousScrollingReasons() & ~ScrollingCoordinator::ForcedOnMainThread) - tileCoverage |= TiledBacking::CoverageForSlowScrolling; - } return tileCoverage; } void RenderLayerBacking::adjustTiledBackingCoverage() { - if (!m_usingTiledCacheLayer) + if (!m_isMainFrameLayerWithTiledBacking) return; - TiledBacking::TileCoverage tileCoverage = computeTileCoverage(this); + TiledBacking::TileCoverage tileCoverage = computePageTiledBackingCoverage(this); tiledBacking()->setTileCoverage(tileCoverage); } -void RenderLayerBacking::setTiledBackingHasMargins(bool extendBackground) +void RenderLayerBacking::setTiledBackingHasMargins(bool hasExtendedBackgroundOnLeftAndRight, bool hasExtendedBackgroundOnTopAndBottom) { - if (!m_usingTiledCacheLayer) + if (!m_isMainFrameLayerWithTiledBacking) return; - int marginSize = extendBackground ? 512 : 0; - tiledBacking()->setTileMargins(marginSize, marginSize, marginSize, marginSize); + tiledBacking()->setHasMargins(hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnLeftAndRight, hasExtendedBackgroundOnLeftAndRight); } void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter) @@ -297,59 +264,68 @@ void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaint void RenderLayerBacking::createPrimaryGraphicsLayer() { - String layerName; -#ifndef NDEBUG - layerName = m_owningLayer.name(); -#endif - - // The call to createGraphicsLayer ends calling back into here as - // a GraphicsLayerClient to ask if it shouldUseTiledBacking(). We only want - // the tile cache on our main layer. This is pretty ugly, but saves us from - // exposing the API to all clients. - - m_creatingPrimaryGraphicsLayer = true; - m_graphicsLayer = createGraphicsLayer(layerName); - m_creatingPrimaryGraphicsLayer = false; + String layerName = m_owningLayer.name(); + const unsigned maxLayerNameLength = 100; + if (layerName.length() > maxLayerNameLength) { + layerName.truncate(maxLayerNameLength); + layerName.append("..."); + } + m_graphicsLayer = createGraphicsLayer(layerName, m_isMainFrameLayerWithTiledBacking ? GraphicsLayer::Type::PageTiledBacking : GraphicsLayer::Type::Normal); - if (m_usingTiledCacheLayer) - m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer"); + if (m_isMainFrameLayerWithTiledBacking) { + m_childContainmentLayer = createGraphicsLayer("Page TiledBacking containment"); + m_graphicsLayer->addChild(m_childContainmentLayer.get()); + } - if (m_isMainFrameRenderViewLayer) { #if !PLATFORM(IOS) + if (m_isMainFrameRenderViewLayer) { // Page scale is applied above the RenderView on iOS. - m_graphicsLayer->setContentsOpaque(true); + m_graphicsLayer->setContentsOpaque(!compositor().viewHasTransparentBackground()); m_graphicsLayer->setAppliesPageScale(); -#endif } +#endif -#if PLATFORM(MAC) && USE(CA) +#if PLATFORM(COCOA) && USE(CA) if (!compositor().acceleratedDrawingEnabled() && renderer().isCanvas()) { - const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element()); + const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element()); if (canvas->shouldAccelerate(canvas->size())) m_graphicsLayer->setAcceleratesDrawing(true); } #endif - updateOpacity(&renderer().style()); - updateTransform(&renderer().style()); -#if ENABLE(CSS_FILTERS) - updateFilters(&renderer().style()); + updateOpacity(renderer().style()); + updateTransform(renderer().style()); + updateFilters(renderer().style()); +#if ENABLE(FILTERS_LEVEL_2) + updateBackdropFilters(renderer().style()); #endif #if ENABLE(CSS_COMPOSITING) - updateBlendMode(&renderer().style()); + updateBlendMode(renderer().style()); #endif + updateCustomAppearance(renderer().style()); } #if PLATFORM(IOS) void RenderLayerBacking::layerWillBeDestroyed() { RenderObject& renderer = this->renderer(); - if (renderer.isEmbeddedObject() && toRenderEmbeddedObject(renderer).allowsAcceleratedCompositing()) { - PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer).widget()); + if (is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing()) { + PluginViewBase* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer).widget()); if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia()) pluginViewBase->detachPluginLayer(); } } + +bool RenderLayerBacking::needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack(const GraphicsLayer& layer) const +{ + if (m_isMainFrameRenderViewLayer && IOSApplication::isDumpRenderTree()) { + // In iOS WebKit1 the main frame's RenderView layer is always transparent. We lie that it is opaque so that + // internals.layerTreeAsText() tests succeed. + ASSERT_UNUSED(layer, !layer.contentsOpaque()); + return true; + } + return false; +} #endif void RenderLayerBacking::destroyGraphicsLayers() @@ -366,23 +342,25 @@ void RenderLayerBacking::destroyGraphicsLayers() m_backgroundLayer = nullptr; m_childContainmentLayer = nullptr; m_maskLayer = nullptr; + m_childClippingMaskLayer = nullptr; m_scrollingLayer = nullptr; m_scrollingContentsLayer = nullptr; } -void RenderLayerBacking::updateOpacity(const RenderStyle* style) +void RenderLayerBacking::updateOpacity(const RenderStyle& style) { - m_graphicsLayer->setOpacity(compositingOpacity(style->opacity())); + m_graphicsLayer->setOpacity(compositingOpacity(style.opacity())); } -void RenderLayerBacking::updateTransform(const RenderStyle* style) +void RenderLayerBacking::updateTransform(const RenderStyle& style) { // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin // baked into it, and we don't want that. TransformationMatrix t; if (m_owningLayer.hasTransform()) { - style->applyTransform(t, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); + auto& renderBox = downcast<RenderBox>(renderer()); + style.applyTransform(t, snapRectToDevicePixels(renderBox.borderBoxRect(), deviceScaleFactor()), RenderStyle::ExcludeTransformOrigin); makeMatrixRenderable(t, compositor().canRender3DTransforms()); } @@ -393,54 +371,81 @@ void RenderLayerBacking::updateTransform(const RenderStyle* style) m_graphicsLayer->setTransform(t); } -#if ENABLE(CSS_FILTERS) -void RenderLayerBacking::updateFilters(const RenderStyle* style) +void RenderLayerBacking::updateFilters(const RenderStyle& style) { - m_canCompositeFilters = m_graphicsLayer->setFilters(style->filter()); + m_canCompositeFilters = m_graphicsLayer->setFilters(style.filter()); } -#endif -#if ENABLE(CSS_COMPOSITING) -void RenderLayerBacking::updateBlendMode(const RenderStyle* style) +#if ENABLE(FILTERS_LEVEL_2) +void RenderLayerBacking::updateBackdropFilters(const RenderStyle& style) { - if (m_ancestorClippingLayer) - m_ancestorClippingLayer->setBlendMode(style->blendMode()); + m_canCompositeBackdropFilters = m_graphicsLayer->setBackdropFilters(style.backdropFilter()); +} + +void RenderLayerBacking::updateBackdropFiltersGeometry() +{ + if (!m_canCompositeBackdropFilters) + return; + + if (!is<RenderBox>(renderer())) + return; + + RenderBox& renderer = downcast<RenderBox>(this->renderer()); + LayoutRect boxRect = renderer.borderBoxRect(); + if (renderer.hasClip()) + boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr)); + boxRect.move(contentOffsetInCompostingLayer()); + + FloatRoundedRect backdropFiltersRect; + if (renderer.style().hasBorderRadius() && !renderer.hasClip()) + backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor()); else - m_graphicsLayer->setBlendMode(style->blendMode()); + backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor())); + + m_graphicsLayer->setBackdropFiltersRect(backdropFiltersRect); } #endif -static bool hasNonZeroTransformOrigin(const RenderObject& renderer) +#if ENABLE(CSS_COMPOSITING) +void RenderLayerBacking::updateBlendMode(const RenderStyle& style) { - const RenderStyle& style = renderer.style(); - return (style.transformOriginX().type() == Fixed && style.transformOriginX().value()) - || (style.transformOriginY().type() == Fixed && style.transformOriginY().value()); + // FIXME: where is the blend mode updated when m_ancestorClippingLayers come and go? + if (m_ancestorClippingLayer) { + m_ancestorClippingLayer->setBlendMode(style.blendMode()); + m_graphicsLayer->setBlendMode(BlendModeNormal); + } else + m_graphicsLayer->setBlendMode(style.blendMode()); } +#endif -#if PLATFORM(IOS) -// FIXME: We should merge the concept of RenderLayer::{hasAcceleratedTouchScrolling, needsCompositedScrolling}() -// so that we can remove this iOS-specific variant. -static bool layerOrAncestorIsTransformedOrScrolling(RenderLayer& layer) +void RenderLayerBacking::updateCustomAppearance(const RenderStyle& style) { - for (RenderLayer* curr = &layer; curr; curr = curr->parent()) { - if (curr->hasTransform() || curr->hasAcceleratedTouchScrolling()) - return true; - } - - return false; + ControlPart appearance = style.appearance(); + if (appearance == MediaControlsLightBarBackgroundPart) + m_graphicsLayer->setCustomAppearance(GraphicsLayer::LightBackdropAppearance); + else if (appearance == MediaControlsDarkBarBackgroundPart) + m_graphicsLayer->setCustomAppearance(GraphicsLayer::DarkBackdropAppearance); + else + m_graphicsLayer->setCustomAppearance(GraphicsLayer::NoCustomAppearance); } -#else + +// FIXME: the hasAcceleratedTouchScrolling()/needsCompositedScrolling() concepts need to be merged. static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer) { for (RenderLayer* curr = &layer; curr; curr = curr->parent()) { - if (curr->hasTransform() || curr->needsCompositedScrolling()) + if (curr->hasTransform() +#if PLATFORM(IOS) + || curr->hasTouchScrollableOverflow() +#else + || curr->needsCompositedScrolling() +#endif + ) return true; } return false; } -#endif - + bool RenderLayerBacking::shouldClipCompositedBounds() const { #if !PLATFORM(IOS) @@ -449,16 +454,11 @@ bool RenderLayerBacking::shouldClipCompositedBounds() const return false; #endif - if (m_usingTiledCacheLayer) + if (m_isMainFrameLayerWithTiledBacking) return false; -#if !PLATFORM(IOS) if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer)) return false; -#else - if (layerOrAncestorIsTransformedOrScrolling(m_owningLayer)) - return false; -#endif if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions()) return false; @@ -466,32 +466,33 @@ bool RenderLayerBacking::shouldClipCompositedBounds() const return true; } -void RenderLayerBacking::updateCompositedBounds() +static bool hasNonZeroTransformOrigin(const RenderObject& renderer) { - LayoutRect layerBounds = compositor().calculateCompositedBounds(m_owningLayer, m_owningLayer); + const RenderStyle& style = renderer.style(); + return (style.transformOriginX().type() == Fixed && style.transformOriginX().value()) + || (style.transformOriginY().type() == Fixed && style.transformOriginY().value()); +} +void RenderLayerBacking::updateCompositedBounds() +{ + LayoutRect layerBounds = m_owningLayer.calculateLayerBounds(&m_owningLayer, LayoutSize(), RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask); // Clip to the size of the document or enclosing overflow-scroll layer. // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with. // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist. if (shouldClipCompositedBounds()) { - RenderView& view = m_owningLayer.renderer().view(); + RenderView& view = renderer().view(); RenderLayer* rootLayer = view.layer(); LayoutRect clippingBounds; - if (renderer().style().position() == FixedPosition && renderer().container() == &view) { -#if PLATFORM(IOS) - clippingBounds = view.frameView().visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect); -#else - clippingBounds = view.frameView().viewportConstrainedVisibleContentRect(); -#endif - } else + if (renderer().style().position() == FixedPosition && renderer().container() == &view) + clippingBounds = view.frameView().rectForFixedPositionLayout(); + else clippingBounds = view.unscaledDocumentRect(); if (&m_owningLayer != rootLayer) - clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions. + clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions. - LayoutPoint delta; - m_owningLayer.convertToLayerCoords(rootLayer, delta, RenderLayer::AdjustForColumns); + LayoutPoint delta = m_owningLayer.convertToLayerCoords(rootLayer, LayoutPoint(), RenderLayer::AdjustForColumns); clippingBounds.move(-delta.x(), -delta.y()); layerBounds.intersect(clippingBounds); @@ -500,7 +501,7 @@ void RenderLayerBacking::updateCompositedBounds() // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, // then we need to ensure that the compositing layer has non-zero size so that we can apply // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value). - if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) { + if (layerBounds.isEmpty() && (hasNonZeroTransformOrigin(renderer()) || renderer().style().hasPerspective())) { layerBounds.setWidth(1); layerBounds.setHeight(1); m_artificiallyInflatedBounds = true; @@ -512,9 +513,9 @@ void RenderLayerBacking::updateCompositedBounds() void RenderLayerBacking::updateAfterWidgetResize() { - if (!renderer().isWidget()) + if (!is<RenderWidget>(renderer())) return; - if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderWidget(&renderer()))) { + if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(&downcast<RenderWidget>(renderer()))) { innerCompositor->frameViewDidChangeSize(); innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location())); } @@ -523,7 +524,7 @@ void RenderLayerBacking::updateAfterWidgetResize() void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags) { if (!compositor().compositingLayersNeedRebuild()) { - // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the + // Calling updateGeometry() here gives incorrect results, because the // position of this layer's GraphicsLayer depends on the position of our compositing // ancestor's GraphicsLayer. That cannot be determined until all the descendant // RenderLayers of that ancestor have been processed via updateLayerPositions(). @@ -534,7 +535,7 @@ void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags) compositor().updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly); if (flags & IsUpdateRoot) { - updateGraphicsLayerGeometry(); + updateGeometry(); compositor().updateRootLayerPosition(); RenderLayer* stackingContainer = m_owningLayer.enclosingStackingContainer(); if (!compositor().compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != &m_owningLayer)) @@ -542,11 +543,11 @@ void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags) } } - if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor()) + if (flags & NeedsFullRepaint && canIssueSetNeedsDisplay()) setContentsNeedDisplay(); } -bool RenderLayerBacking::updateGraphicsLayerConfiguration() +bool RenderLayerBacking::updateConfiguration() { m_owningLayer.updateDescendantDependentFlags(); m_owningLayer.updateZOrderLists(); @@ -561,34 +562,31 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() if (updateForegroundLayer(compositor().needsContentsCompositingLayer(m_owningLayer))) layerConfigChanged = true; - bool needsDescendentsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer); + bool needsDescendantsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer); + if (!renderer().view().needsLayout()) { + bool usesCompositedScrolling; #if PLATFORM(IOS) - // Our scrolling layer will clip. - if (m_owningLayer.hasAcceleratedTouchScrolling()) - needsDescendentsClippingLayer = false; + usesCompositedScrolling = m_owningLayer.hasTouchScrollableOverflow(); #else - // Our scrolling layer will clip. - if (m_owningLayer.needsCompositedScrolling()) - needsDescendentsClippingLayer = false; -#endif // PLATFORM(IOS) + usesCompositedScrolling = m_owningLayer.needsCompositedScrolling(); +#endif + // Our scrolling layer will clip. + if (usesCompositedScrolling) + needsDescendantsClippingLayer = false; - if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer))) - layerConfigChanged = true; + if (updateScrollingLayers(usesCompositedScrolling)) + layerConfigChanged = true; - if (updateDescendantClippingLayer(needsDescendentsClippingLayer)) - layerConfigChanged = true; + if (updateDescendantClippingLayer(needsDescendantsClippingLayer)) + layerConfigChanged = true; + } - if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer())) + if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer))) layerConfigChanged = true; -#if PLATFORM(IOS) - if (updateScrollingLayers(m_owningLayer.hasAcceleratedTouchScrolling())) - layerConfigChanged = true; -#else - if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling())) + if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer())) layerConfigChanged = true; -#endif // PLATFORM(IOS) if (layerConfigChanged) updateInternalHierarchy(); @@ -598,8 +596,9 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() m_graphicsLayer->addChild(flatteningLayer); } - if (updateMaskLayer(renderer().hasMask())) - m_graphicsLayer->setMaskLayer(m_maskLayer.get()); + updateMaskingLayer(renderer().hasMask(), renderer().hasClipPath()); + + updateChildClippingStrategy(needsDescendantsClippingLayer); if (m_owningLayer.hasReflection()) { if (m_owningLayer.reflectionLayer()->backing()) { @@ -607,19 +606,20 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() m_graphicsLayer->setReplicatedByLayer(reflectionLayer); } } else - m_graphicsLayer->setReplicatedByLayer(0); - - bool isSimpleContainer = isSimpleContainerCompositingLayer(); - bool didUpdateContentsRect = false; - updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect); + m_graphicsLayer->setReplicatedByLayer(nullptr); - updateRootLayerConfiguration(); + if (!m_owningLayer.isRootLayer()) { + bool isSimpleContainer = isSimpleContainerCompositingLayer(); + bool didUpdateContentsRect = false; + updateDirectlyCompositedBoxDecorations(isSimpleContainer, didUpdateContentsRect); + } else + updateRootLayerConfiguration(); if (isDirectlyCompositedImage()) updateImageContents(); - if (renderer().isEmbeddedObject() && toRenderEmbeddedObject(&renderer())->allowsAcceleratedCompositing()) { - PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(&renderer())->widget()); + if (is<RenderEmbeddedObject>(renderer()) && downcast<RenderEmbeddedObject>(renderer()).allowsAcceleratedCompositing()) { + PluginViewBase* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer()).widget()); #if PLATFORM(IOS) if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) { pluginViewBase->detachPluginLayer(); @@ -627,30 +627,30 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() } #else if (!pluginViewBase->shouldNotAddLayer()) - m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer()); + m_graphicsLayer->setContentsToPlatformLayer(pluginViewBase->platformLayer(), GraphicsLayer::ContentsLayerForPlugin); #endif } #if ENABLE(VIDEO) - else if (renderer().isVideo()) { - HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer().element()); - m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer()); + else if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo()) { + HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(renderer().element()); + m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer(), GraphicsLayer::ContentsLayerForMedia); } #endif #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) { - const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element()); + const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element()); if (CanvasRenderingContext* context = canvas->renderingContext()) - m_graphicsLayer->setContentsToCanvas(context->platformLayer()); + m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer(), GraphicsLayer::ContentsLayerForCanvas); layerConfigChanged = true; } #endif - if (renderer().isWidget()) - layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderWidget(&renderer())); + if (is<RenderWidget>(renderer())) + layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(&downcast<RenderWidget>(renderer())); return layerConfigChanged; } -static IntRect clipBox(RenderBox& renderer) +static LayoutRect clipBox(RenderBox& renderer) { LayoutRect result = LayoutRect::infiniteRect(); if (renderer.hasOverflowClip()) @@ -659,175 +659,289 @@ static IntRect clipBox(RenderBox& renderer) if (renderer.hasClip()) result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions. - return pixelSnappedIntRect(result); + return result; } -void RenderLayerBacking::updateGraphicsLayerGeometry() +static bool subpixelOffsetFromRendererChanged(const LayoutSize& oldSubpixelOffsetFromRenderer, const LayoutSize& newSubpixelOffsetFromRenderer, float deviceScaleFactor) +{ + FloatSize previous = snapSizeToDevicePixel(oldSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor); + FloatSize current = snapSizeToDevicePixel(newSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor); + return previous != current; +} + +static FloatSize subpixelForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor) +{ + LayoutUnit x = point.x(); + LayoutUnit y = point.y(); + x = x >= 0 ? floorToDevicePixel(x, pixelSnappingFactor) : ceilToDevicePixel(x, pixelSnappingFactor); + y = y >= 0 ? floorToDevicePixel(y, pixelSnappingFactor) : ceilToDevicePixel(y, pixelSnappingFactor); + return point - LayoutPoint(x, y); +} + +struct OffsetFromRenderer { + // 1.2px - > { m_devicePixelOffset = 1px m_subpixelOffset = 0.2px } + LayoutSize m_devicePixelOffset; + LayoutSize m_subpixelOffset; +}; + +static OffsetFromRenderer computeOffsetFromRenderer(const LayoutSize& offset, float deviceScaleFactor) +{ + OffsetFromRenderer offsetFromRenderer; + offsetFromRenderer.m_subpixelOffset = LayoutSize(subpixelForLayerPainting(toLayoutPoint(offset), deviceScaleFactor)); + offsetFromRenderer.m_devicePixelOffset = offset - offsetFromRenderer.m_subpixelOffset; + return offsetFromRenderer; +} + +struct SnappedRectInfo { + LayoutRect m_snappedRect; + LayoutSize m_snapDelta; +}; + +static SnappedRectInfo snappedGraphicsLayer(const LayoutSize& offset, const LayoutSize& size, float deviceScaleFactor) +{ + SnappedRectInfo snappedGraphicsLayer; + LayoutRect graphicsLayerRect = LayoutRect(toLayoutPoint(offset), size); + snappedGraphicsLayer.m_snappedRect = LayoutRect(snapRectToDevicePixels(graphicsLayerRect, deviceScaleFactor)); + snappedGraphicsLayer.m_snapDelta = snappedGraphicsLayer.m_snappedRect.location() - toLayoutPoint(offset); + return snappedGraphicsLayer; +} + +static LayoutSize computeOffsetFromAncestorGraphicsLayer(RenderLayer* compositedAncestor, const LayoutPoint& location, float deviceScaleFactor) +{ + if (!compositedAncestor) + return toLayoutSize(location); + + // FIXME: This is a workaround until after webkit.org/162634 gets fixed. ancestorSubpixelOffsetFromRenderer + // could be stale when a dynamic composited state change triggers a pre-order updateGeometry() traversal. + LayoutSize ancestorSubpixelOffsetFromRenderer = compositedAncestor->backing()->subpixelOffsetFromRenderer(); + LayoutRect ancestorCompositedBounds = compositedAncestor->backing()->compositedBounds(); + LayoutSize floored = toLayoutSize(LayoutPoint(floorPointToDevicePixels(ancestorCompositedBounds.location() - ancestorSubpixelOffsetFromRenderer, deviceScaleFactor))); + LayoutSize ancestorRendererOffsetFromAncestorGraphicsLayer = -(floored + ancestorSubpixelOffsetFromRenderer); + return ancestorRendererOffsetFromAncestorGraphicsLayer + toLayoutSize(location); +} + +class ComputedOffsets { +public: + ComputedOffsets(const RenderLayer& renderLayer, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect) + : m_renderLayer(renderLayer) + , m_location(localRect.location()) + , m_parentGraphicsLayerOffset(toLayoutSize(parentGraphicsLayerRect.location())) + , m_primaryGraphicsLayerOffset(toLayoutSize(primaryGraphicsLayerRect.location())) + , m_deviceScaleFactor(renderLayer.renderer().document().deviceScaleFactor()) + { + } + + LayoutSize fromParentGraphicsLayer() + { + if (!m_fromParentGraphicsLayer) + m_fromParentGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset; + return m_fromParentGraphicsLayer.value(); + } + + LayoutSize fromPrimaryGraphicsLayer() + { + if (!m_fromPrimaryGraphicsLayer) + m_fromPrimaryGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset - m_primaryGraphicsLayerOffset; + return m_fromPrimaryGraphicsLayer.value(); + } + +private: + LayoutSize fromAncestorGraphicsLayer() + { + if (!m_fromAncestorGraphicsLayer) { + RenderLayer* compositedAncestor = m_renderLayer.ancestorCompositingLayer(); + LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(compositedAncestor, m_location, RenderLayer::AdjustForColumns); + m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor); + } + return m_fromAncestorGraphicsLayer.value(); + } + + std::optional<LayoutSize> m_fromAncestorGraphicsLayer; + std::optional<LayoutSize> m_fromParentGraphicsLayer; + std::optional<LayoutSize> m_fromPrimaryGraphicsLayer; + + const RenderLayer& m_renderLayer; + // Location is relative to the renderer. + const LayoutPoint m_location; + const LayoutSize m_parentGraphicsLayerOffset; + const LayoutSize m_primaryGraphicsLayerOffset; + float m_deviceScaleFactor; +}; + +LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const +{ + ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, LayoutRect()); + return LayoutRect(encloseRectToDevicePixels(LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), + deviceScaleFactor())); +} + +LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compositedAncestor, LayoutSize& ancestorClippingLayerOffset) const +{ + if (!compositedAncestor || !compositedAncestor->backing()) + return renderer().view().documentRect(); + + auto* ancestorBackingLayer = compositedAncestor->backing(); + LayoutRect parentGraphicsLayerRect; + if (m_owningLayer.isInsideFlowThread()) { + /// FIXME: flows/columns need work. + LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds(); + ancestorCompositedBounds.setLocation(LayoutPoint()); + adjustAncestorCompositingBoundsForFlowThread(ancestorCompositedBounds, compositedAncestor); + parentGraphicsLayerRect = ancestorCompositedBounds; + } + + if (ancestorBackingLayer->hasClippingLayer()) { + // If the compositing ancestor has a layer to clip children, we parent in that, and therefore position relative to it. + LayoutRect clippingBox = clipBox(downcast<RenderBox>(compositedAncestor->renderer())); + LayoutSize clippingBoxOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, clippingBox.location(), deviceScaleFactor()); + parentGraphicsLayerRect = snappedGraphicsLayer(clippingBoxOffset, clippingBox.size(), deviceScaleFactor()).m_snappedRect; + } + +#if PLATFORM(IOS) + if (compositedAncestor->hasTouchScrollableOverflow()) { + LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds(); + auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer()); + LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom()); + ScrollOffset scrollOffset = compositedAncestor->scrollOffset(); + parentGraphicsLayerRect = LayoutRect((paddingBox.location() - toLayoutSize(ancestorCompositedBounds.location()) - toLayoutSize(scrollOffset)), paddingBox.size()); + } +#else + if (compositedAncestor->needsCompositedScrolling()) { + auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer()); + LayoutPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop()); + parentGraphicsLayerRect = LayoutRect(scrollOrigin - toLayoutSize(compositedAncestor->scrollOffset()), renderBox.borderBoxRect().size()); + } +#endif + + if (m_ancestorClippingLayer) { + // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this + // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects + // for a compositing layer, rootLayer is the layer itself. + ShouldRespectOverflowClip shouldRespectOverflowClip = compositedAncestor->isolatesCompositedBlending() ? RespectOverflowClip : IgnoreOverflowClip; + RenderLayer::ClipRectsContext clipRectsContext(compositedAncestor, TemporaryClipRects, IgnoreOverlayScrollbarSize, shouldRespectOverflowClip); + LayoutRect parentClipRect = m_owningLayer.backgroundClipRect(clipRectsContext).rect(); // FIXME: Incorrect for CSS regions. + ASSERT(!parentClipRect.isInfinite()); + LayoutSize clippingOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, parentClipRect.location(), deviceScaleFactor()); + LayoutRect snappedClippingLayerRect = snappedGraphicsLayer(clippingOffset, parentClipRect.size(), deviceScaleFactor()).m_snappedRect; + // The primary layer is then parented in, and positioned relative to this clipping layer. + ancestorClippingLayerOffset = snappedClippingLayerRect.location() - parentGraphicsLayerRect.location(); + parentGraphicsLayerRect = snappedClippingLayerRect; + } + return parentGraphicsLayerRect; +} + +void RenderLayerBacking::updateGeometry() { // If we haven't built z-order lists yet, wait until later. if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty) return; + const RenderStyle& style = renderer().style(); // Set transform property, if it is not animating. We have to do this here because the transform // is affected by the layer dimensions. - if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyWebkitTransform)) - updateTransform(&renderer().style()); + if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused)) + updateTransform(style); // Set opacity, if it is not animating. - if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyOpacity)) - updateOpacity(&renderer().style()); - -#if ENABLE(CSS_FILTERS) - updateFilters(&renderer().style()); -#endif + if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused)) + updateOpacity(style); + updateFilters(style); +#if ENABLE(FILTERS_LEVEL_2) + updateBackdropFilters(style); +#endif #if ENABLE(CSS_COMPOSITING) - updateBlendMode(&renderer().style()); + updateBlendMode(style); #endif - - bool isSimpleContainer = isSimpleContainerCompositingLayer(); - m_owningLayer.updateDescendantDependentFlags(); - // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing - // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any - // non-compositing visible layers. - m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendantLayers()); - - const RenderStyle& style = renderer().style(); // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959 bool preserves3D = style.transformStyle3D() == TransformStyle3DPreserve3D && !renderer().hasReflection(); m_graphicsLayer->setPreserves3D(preserves3D); m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibilityVisible); - RenderLayer* compAncestor = m_owningLayer.ancestorCompositingLayer(); - - // We compute everything relative to the enclosing compositing layer. - IntRect ancestorCompositingBounds; - if (compAncestor) { - ASSERT(compAncestor->backing()); - ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds()); - } - - LayoutRect localRawCompositingBounds = compositedBounds(); - LayoutPoint rawDelta; - m_owningLayer.convertToLayerCoords(compAncestor, rawDelta, RenderLayer::AdjustForColumns); - IntPoint delta = flooredIntPoint(rawDelta); - m_subpixelAccumulation = toLayoutSize(rawDelta.fraction()); - // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates. - localRawCompositingBounds.move(m_subpixelAccumulation); - - IntRect localCompositingBounds = pixelSnappedIntRect(localRawCompositingBounds); - IntRect relativeCompositingBounds(localCompositingBounds); - relativeCompositingBounds.moveBy(delta); - - adjustAncestorCompositingBoundsForFlowThread(ancestorCompositingBounds, compAncestor); - - IntPoint graphicsLayerParentLocation; - if (compAncestor && compAncestor->backing()->hasClippingLayer()) { - // If the compositing ancestor has a layer to clip children, we parent in that, and therefore - // position relative to it. - IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer())); - graphicsLayerParentLocation = clippingBox.location(); - } else if (compAncestor) - graphicsLayerParentLocation = ancestorCompositingBounds.location(); - else - graphicsLayerParentLocation = renderer().view().documentRect().location(); + RenderLayer* compositedAncestor = m_owningLayer.ancestorCompositingLayer(); + LayoutSize ancestorClippingLayerOffset; + LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor, ancestorClippingLayerOffset); + LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect(parentGraphicsLayerRect); -#if PLATFORM(IOS) - if (compAncestor && compAncestor->hasAcceleratedTouchScrolling()) { - RenderBox* renderBox = toRenderBox(&compAncestor->renderer()); - IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), - renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), - renderBox->height() - renderBox->borderTop() - renderBox->borderBottom()); + ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect); + m_compositedBoundsOffsetFromGraphicsLayer = compositedBoundsOffset.fromPrimaryGraphicsLayer(); + m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location()); + m_graphicsLayer->setSize(primaryGraphicsLayerRect.size()); - IntSize scrollOffset = compAncestor->scrolledContentOffset(); - graphicsLayerParentLocation = paddingBox.location() - scrollOffset; + ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect); + if (m_ancestorClippingLayer) { + // Clipping layer is parented in the ancestor layer. + m_ancestorClippingLayer->setPosition(toLayoutPoint(ancestorClippingLayerOffset)); + m_ancestorClippingLayer->setSize(parentGraphicsLayerRect.size()); + m_ancestorClippingLayer->setOffsetFromRenderer(-rendererOffset.fromParentGraphicsLayer()); } -#endif - - if (compAncestor && compAncestor->needsCompositedScrolling()) { - RenderBox& renderBox = toRenderBox(compAncestor->renderer()); - IntSize scrollOffset = compAncestor->scrolledContentOffset(); - IntPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop()); - graphicsLayerParentLocation = scrollOrigin - scrollOffset; - } - - if (compAncestor && m_ancestorClippingLayer) { - // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this - // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects - // for a compositing layer, rootLayer is the layer itself. - RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip); - IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions. - ASSERT(parentClipRect != IntRect::infiniteRect()); - m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation)); - m_ancestorClippingLayer->setSize(parentClipRect.size()); - // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. - m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta); - - // The primary layer is then parented in, and positioned relative to this clipping layer. - graphicsLayerParentLocation = parentClipRect.location(); - } - - FloatSize contentsSize = relativeCompositingBounds.size(); - if (m_contentsContainmentLayer) { m_contentsContainmentLayer->setPreserves3D(preserves3D); - m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation)); + m_contentsContainmentLayer->setPosition(primaryGraphicsLayerRect.location()); + m_graphicsLayer->setPosition(FloatPoint()); // Use the same size as m_graphicsLayer so transforms behave correctly. - m_contentsContainmentLayer->setSize(contentsSize); - graphicsLayerParentLocation = relativeCompositingBounds.location(); + m_contentsContainmentLayer->setSize(primaryGraphicsLayerRect.size()); } - m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation)); - m_graphicsLayer->setSize(contentsSize); - IntSize offsetFromRenderer = toIntSize(localCompositingBounds.location()); - if (offsetFromRenderer != m_graphicsLayer->offsetFromRenderer()) { - m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location())); + // Compute renderer offset from primary graphics layer. Note that primaryGraphicsLayerRect is in parentGraphicsLayer's coordidate system which is not necessarily + // the same as the ancestor graphics layer. + OffsetFromRenderer primaryGraphicsLayerOffsetFromRenderer; + LayoutSize oldSubpixelOffsetFromRenderer = m_subpixelOffsetFromRenderer; + primaryGraphicsLayerOffsetFromRenderer = computeOffsetFromRenderer(-rendererOffset.fromPrimaryGraphicsLayer(), deviceScaleFactor()); + m_subpixelOffsetFromRenderer = primaryGraphicsLayerOffsetFromRenderer.m_subpixelOffset; + + if (primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset != m_graphicsLayer->offsetFromRenderer()) { + m_graphicsLayer->setOffsetFromRenderer(primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset); positionOverflowControlsLayers(); } if (!m_isMainFrameRenderViewLayer) { // For non-root layers, background is always painted by the primary graphics layer. ASSERT(!m_backgroundLayer); - bool hadSubpixelRounding = LayoutSize(relativeCompositingBounds.size()) != localRawCompositingBounds.size(); - m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(localCompositingBounds)); + // Subpixel offset from graphics layer or size changed. + bool hadSubpixelRounding = !m_subpixelOffsetFromRenderer.isZero() || compositedBounds().size() != primaryGraphicsLayerRect.size(); + m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds())); } // If we have a layer that clips children, position it. - IntRect clippingBox; + LayoutRect clippingBox; if (GraphicsLayer* clipLayer = clippingLayer()) { - clippingBox = clipBox(toRenderBox(renderer())); - clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location())); - clipLayer->setSize(clippingBox.size()); - clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location())); + clippingBox = clipBox(downcast<RenderBox>(renderer())); + // Clipping layer is parented in the primary graphics layer. + LayoutSize clipBoxOffsetFromGraphicsLayer = toLayoutSize(clippingBox.location()) + rendererOffset.fromPrimaryGraphicsLayer(); + SnappedRectInfo snappedClippingGraphicsLayer = snappedGraphicsLayer(clipBoxOffsetFromGraphicsLayer, clippingBox.size(), deviceScaleFactor()); + clipLayer->setPosition(snappedClippingGraphicsLayer.m_snappedRect.location()); + clipLayer->setSize(snappedClippingGraphicsLayer.m_snappedRect.size()); + clipLayer->setOffsetFromRenderer(toLayoutSize(clippingBox.location() - snappedClippingGraphicsLayer.m_snapDelta)); + + if (m_childClippingMaskLayer && !m_scrollingLayer) { + m_childClippingMaskLayer->setSize(clipLayer->size()); + m_childClippingMaskLayer->setPosition(FloatPoint()); + m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer()); + } } - if (m_maskLayer) { - m_maskLayer->setSize(m_graphicsLayer->size()); - m_maskLayer->setPosition(FloatPoint()); - m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); - } + if (m_maskLayer) + updateMaskingLayerGeometry(); - if (m_owningLayer.hasTransform()) { - const IntRect borderBox = toRenderBox(renderer()).pixelSnappedBorderBoxRect(); - - // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds. - IntRect layerBounds(delta, borderBox.size()); - - // Update properties that depend on layer dimensions - FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); + if (m_owningLayer.renderer().hasTransformRelatedProperty()) { + // Update properties that depend on layer dimensions. + FloatPoint3D transformOrigin = computeTransformOriginForPainting(downcast<RenderBox>(renderer()).borderBoxRect()); + FloatPoint layerOffset = roundPointToDevicePixels(toLayoutPoint(rendererOffset.fromParentGraphicsLayer()), deviceScaleFactor()); // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. - FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, - relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f, - transformOrigin.z()); + FloatPoint3D anchor( + primaryGraphicsLayerRect.width() ? ((layerOffset.x() - primaryGraphicsLayerRect.x()) + transformOrigin.x()) / primaryGraphicsLayerRect.width() : 0.5, + primaryGraphicsLayerRect.height() ? ((layerOffset.y() - primaryGraphicsLayerRect.y())+ transformOrigin.y()) / primaryGraphicsLayerRect.height() : 0.5, + transformOrigin.z()); + if (m_contentsContainmentLayer) m_contentsContainmentLayer->setAnchorPoint(anchor); else m_graphicsLayer->setAnchorPoint(anchor); - const RenderStyle& style = renderer().style(); GraphicsLayer* clipLayer = clippingLayer(); if (style.hasPerspective()) { TransformationMatrix t = owningLayer().perspectiveTransform(); @@ -845,20 +959,20 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() m_graphicsLayer->setChildrenTransform(TransformationMatrix()); } } else { - m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); + m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0)); if (m_contentsContainmentLayer) - m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); + m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0)); } if (m_foregroundLayer) { FloatPoint foregroundPosition; - FloatSize foregroundSize = contentsSize; - IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); + FloatSize foregroundSize = primaryGraphicsLayerRect.size(); + FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); if (hasClippingLayer()) { // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. foregroundSize = FloatSize(clippingBox.size()); - foregroundOffset = toIntSize(clippingBox.location()); + foregroundOffset = toFloatSize(clippingBox.location()); } m_foregroundLayer->setPosition(foregroundPosition); @@ -868,11 +982,11 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() if (m_backgroundLayer) { FloatPoint backgroundPosition; - FloatSize backgroundSize = contentsSize; + FloatSize backgroundSize = primaryGraphicsLayerRect.size(); if (backgroundLayerPaintsFixedRootBackground()) { const FrameView& frameView = renderer().view().frameView(); - backgroundPosition = IntPoint(frameView.scrollOffsetForFixedPosition()); - backgroundSize = frameView.visibleContentRect().size(); + backgroundPosition = frameView.scrollPositionForFixedPosition(); + backgroundSize = frameView.layoutSize(); } m_backgroundLayer->setPosition(backgroundPosition); m_backgroundLayer->setSize(backgroundSize); @@ -881,36 +995,37 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) { RenderLayerBacking* reflectionBacking = m_owningLayer.reflectionLayer()->backing(); - reflectionBacking->updateGraphicsLayerGeometry(); + reflectionBacking->updateGeometry(); // The reflection layer has the bounds of m_owningLayer.reflectionLayer(), // but the reflected layer is the bounds of this layer, so we need to position it appropriately. - FloatRect layerBounds = compositedBounds(); + FloatRect layerBounds = this->compositedBounds(); FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds(); reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location())); } if (m_scrollingLayer) { ASSERT(m_scrollingContentsLayer); - RenderBox& renderBox = toRenderBox(renderer()); - IntRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom()); - IntSize scrollOffset = m_owningLayer.scrollOffset(); + auto& renderBox = downcast<RenderBox>(renderer()); + LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom()); + ScrollOffset scrollOffset = m_owningLayer.scrollOffset(); - m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location())); + // FIXME: need to do some pixel snapping here. + m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - compositedBounds().location())); - m_scrollingLayer->setSize(paddingBox.size()); + m_scrollingLayer->setSize(roundedIntSize(LayoutSize(renderBox.clientWidth(), renderBox.clientHeight()))); #if PLATFORM(IOS) - IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer(); - m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location()); + FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer(); + m_scrollingLayer->setOffsetFromRenderer(FloatPoint() - paddingBox.location()); bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer(); if (m_owningLayer.isInUserScroll()) { - // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause - // jitter. Set a flag to ensure that we sync up later. + // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause jitter. + m_scrollingLayer->syncBoundsOrigin(scrollOffset); m_owningLayer.setRequiresScrollBoundsOriginUpdate(true); } else { // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer. - m_scrollingLayer->setBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height())); + m_scrollingLayer->setBoundsOrigin(scrollOffset); m_owningLayer.setRequiresScrollBoundsOriginUpdate(false); } @@ -924,14 +1039,19 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() m_scrollingContentsLayer->setSize(scrollSize); // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting. // FIXME: The paint offset and the scroll offset should really be separate concepts. - m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset, GraphicsLayer::DontSetNeedsDisplay); - - compositor().scrollingLayerAddedOrUpdated(&m_owningLayer); + LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset)); + m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay); #else - m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height())); + m_scrollingContentsLayer->setPosition(-scrollOffset); - IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer(); - m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location())); + FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer(); + m_scrollingLayer->setOffsetFromRenderer(-toFloatSize(paddingBox.location())); + + if (m_childClippingMaskLayer) { + m_childClippingMaskLayer->setPosition(m_scrollingLayer->position()); + m_childClippingMaskLayer->setSize(m_scrollingLayer->size()); + m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBox.location())); + } bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer(); @@ -939,7 +1059,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged) m_scrollingContentsLayer->setNeedsDisplay(); - IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset); + LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset)); if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) compositor().scrollingLayerDidChange(m_owningLayer); @@ -955,24 +1075,72 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store. - setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compAncestor, relativeCompositingBounds, ancestorCompositingBounds)); + LayoutRect ancestorCompositedBounds = compositedAncestor ? compositedAncestor->backing()->compositedBounds() : LayoutRect(); + setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compositedAncestor, + LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), ancestorCompositedBounds)); +#if ENABLE(FILTERS_LEVEL_2) + updateBackdropFiltersGeometry(); +#endif + updateAfterWidgetResize(); + + if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay()) + setContentsNeedDisplay(); - bool didUpdateContentsRect = false; - updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect); - if (!didUpdateContentsRect && m_graphicsLayer->hasContentsLayer()) - resetContentsRect(); + compositor().updateScrollCoordinatedStatus(m_owningLayer); +} + +void RenderLayerBacking::updateAfterDescendants() +{ + bool isSimpleContainer = false; + if (!m_owningLayer.isRootLayer()) { + bool didUpdateContentsRect = false; + // FIXME: this duplicates work we did in updateConfiguration(). + isSimpleContainer = isSimpleContainerCompositingLayer(); + updateDirectlyCompositedBoxDecorations(isSimpleContainer, didUpdateContentsRect); + if (!didUpdateContentsRect && m_graphicsLayer->usesContentsLayer()) + resetContentsRect(); + } updateDrawsContent(isSimpleContainer); - updateAfterWidgetResize(); - registerScrollingLayers(); + + m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositedDescendants()); + if (m_scrollingLayer) { + m_scrollingLayer->setContentsVisible(renderer().style().visibility() == VISIBLE); + m_scrollingLayer->setUserInteractionEnabled(renderer().style().pointerEvents() != PE_NONE); + } } -void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(IntRect& ancestorCompositingBounds, const RenderLayer* compositingAncestor) const +// FIXME: Avoid repaints when clip path changes. +void RenderLayerBacking::updateMaskingLayerGeometry() { - if (!m_owningLayer.isInsideFlowThread()) - return; + m_maskLayer->setSize(m_graphicsLayer->size()); + m_maskLayer->setPosition(FloatPoint()); + m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); + + if (!m_maskLayer->drawsContent()) { + if (renderer().hasClipPath()) { + ASSERT(renderer().style().clipPath()->type() != ClipPathOperation::Reference); + + WindRule windRule; + // FIXME: Use correct reference box for inlines: https://bugs.webkit.org/show_bug.cgi?id=129047 + LayoutRect boundingBox = m_owningLayer.boundingBox(&m_owningLayer); + LayoutRect referenceBoxForClippedInline = LayoutRect(snapRectToDevicePixels(boundingBox, deviceScaleFactor())); + LayoutSize offset = LayoutSize(snapSizeToDevicePixel(-m_subpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor())); + Path clipPath = m_owningLayer.computeClipPath(offset, referenceBoxForClippedInline, windRule); + + FloatSize pathOffset = m_maskLayer->offsetFromRenderer(); + if (!pathOffset.isZero()) + clipPath.translate(-pathOffset); + + m_maskLayer->setShapeLayerPath(clipPath); + m_maskLayer->setShapeLayerWindRule(windRule); + } + } +} - RenderLayer* flowThreadLayer = m_owningLayer.isInsideOutOfFlowThread() ? m_owningLayer.stackingContainer() : m_owningLayer.enclosingFlowThreadAncestor(); +void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(LayoutRect& ancestorCompositingBounds, const RenderLayer* compositingAncestor) const +{ + RenderLayer* flowThreadLayer = m_owningLayer.isInsideOutOfFlowThread() ? m_owningLayer.stackingContainer() : nullptr; if (flowThreadLayer && flowThreadLayer->isRenderFlowThread()) { if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions()) { // The RenderNamedFlowThread is not composited, as we need it to paint the @@ -984,15 +1152,15 @@ void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(IntRect& a } // Move the ancestor position at the top of the region where the composited layer is going to display. - RenderFlowThread& flowThread = toRenderFlowThread(flowThreadLayer->renderer()); + RenderFlowThread& flowThread = downcast<RenderFlowThread>(flowThreadLayer->renderer()); RenderNamedFlowFragment* parentRegion = flowThread.cachedRegionForCompositedLayer(m_owningLayer); if (!parentRegion) return; IntPoint flowDelta; m_owningLayer.convertToPixelSnappedLayerCoords(flowThreadLayer, flowDelta); - parentRegion->adjustRegionBoundsFromFlowThreadPortionRect(flowDelta, ancestorCompositingBounds); - RenderBoxModelObject& layerOwner = toRenderBoxModelObject(parentRegion->layerOwner()); + parentRegion->adjustRegionBoundsFromFlowThreadPortionRect(ancestorCompositingBounds); + RenderBoxModelObject& layerOwner = downcast<RenderBoxModelObject>(parentRegion->layerOwner()); RenderLayerBacking* layerOwnerBacking = layerOwner.layer()->backing(); if (!layerOwnerBacking) return; @@ -1012,7 +1180,7 @@ void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(IntRect& a } } -void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer, bool& didUpdateContentsRect) +void RenderLayerBacking::updateDirectlyCompositedBoxDecorations(bool isSimpleContainer, bool& didUpdateContentsRect) { if (!m_owningLayer.hasVisibleContent()) return; @@ -1023,29 +1191,6 @@ void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer updateDirectlyCompositedBackgroundImage(isSimpleContainer, didUpdateContentsRect); } -void RenderLayerBacking::registerScrollingLayers() -{ -#if PLATFORM(IOS) - compositor().updateViewportConstraintStatus(m_owningLayer); -#else - // Register fixed position layers and their containers with the scrolling coordinator. - ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); - if (!scrollingCoordinator) - return; - - compositor().updateViewportConstraintStatus(m_owningLayer); - - if (!scrollingCoordinator->supportsFixedPositionLayers()) - return; - - // Page scale is applied as a transform on the root render view layer. Because the scroll - // layer is further up in the hierarchy, we need to avoid marking the root render view - // layer as a container. - bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer(); - scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer); -#endif -} - void RenderLayerBacking::updateInternalHierarchy() { // m_foregroundLayer has to be inserted in the correct order with child layers, @@ -1097,17 +1242,17 @@ void RenderLayerBacking::updateInternalHierarchy() void RenderLayerBacking::resetContentsRect() { - m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox())); + m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor())); - LayoutRect contentsClippingRect; - if (renderer().isBox()) - contentsClippingRect = toRenderBox(renderer()).contentBoxRect(); - - contentsClippingRect.move(contentOffsetInCompostingLayer()); - m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect)); + if (is<RenderBox>(renderer())) { + LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size()); + boxRect.move(contentOffsetInCompostingLayer()); + FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor()); + m_graphicsLayer->setContentsClippingRect(contentsClippingRect); + } m_graphicsLayer->setContentsTileSize(IntSize()); - m_graphicsLayer->setContentsTilePhase(IntPoint()); + m_graphicsLayer->setContentsTilePhase(IntSize()); } void RenderLayerBacking::updateDrawsContent() @@ -1122,10 +1267,10 @@ void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer) // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint. // m_scrollingLayer never has backing store. // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint. - bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground(); + bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasVisibleBoxDecorationsOrBackground(); m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent); - bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || paintsChildren()); + bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || paintsChildRenderers()); m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent); return; } @@ -1148,7 +1293,7 @@ bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip) if (needsAncestorClip) { if (!m_ancestorClippingLayer) { - m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer"); + m_ancestorClippingLayer = createGraphicsLayer("ancestor clipping"); m_ancestorClippingLayer->setMasksToBounds(true); layersChanged = true; } @@ -1168,8 +1313,8 @@ bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip) bool layersChanged = false; if (needsDescendantClip) { - if (!m_childContainmentLayer && !m_usingTiledCacheLayer) { - m_childContainmentLayer = createGraphicsLayer("Child clipping Layer"); + if (!m_childContainmentLayer && !m_isMainFrameLayerWithTiledBacking) { + m_childContainmentLayer = createGraphicsLayer("child clipping"); m_childContainmentLayer->setMasksToBounds(true); layersChanged = true; } @@ -1247,11 +1392,11 @@ bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScroll scrollCornerLayerChanged = true; } - if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) { + if (auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator()) { if (horizontalScrollbarLayerChanged) - scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, HorizontalScrollbar); + scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar); if (verticalScrollbarLayerChanged) - scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, VerticalScrollbar); + scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar); } return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged; @@ -1262,31 +1407,31 @@ void RenderLayerBacking::positionOverflowControlsLayers() if (!m_owningLayer.hasScrollbars()) return; - const IntRect borderBox = toRenderBox(renderer()).pixelSnappedBorderBoxRect(); + const IntRect borderBox = snappedIntRect(renderBox()->borderBoxRect()); - IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer(); + FloatSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer(); if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox); layer->setPosition(hBarRect.location() - offsetFromRenderer); layer->setSize(hBarRect.size()); - if (layer->hasContentsLayer()) { + if (layer->usesContentsLayer()) { IntRect barRect = IntRect(IntPoint(), hBarRect.size()); layer->setContentsRect(barRect); - layer->setContentsClippingRect(barRect); + layer->setContentsClippingRect(FloatRoundedRect(barRect)); } - layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->hasContentsLayer()); + layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->usesContentsLayer()); } if (GraphicsLayer* layer = layerForVerticalScrollbar()) { IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox); layer->setPosition(vBarRect.location() - offsetFromRenderer); layer->setSize(vBarRect.size()); - if (layer->hasContentsLayer()) { + if (layer->usesContentsLayer()) { IntRect barRect = IntRect(IntPoint(), vBarRect.size()); layer->setContentsRect(barRect); - layer->setContentsClippingRect(barRect); + layer->setContentsClippingRect(FloatRoundedRect(barRect)); } - layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->hasContentsLayer()); + layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->usesContentsLayer()); } if (GraphicsLayer* layer = layerForScrollCorner()) { @@ -1319,10 +1464,7 @@ bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) bool layerChanged = false; if (needsForegroundLayer) { if (!m_foregroundLayer) { - String layerName; -#ifndef NDEBUG - layerName = m_owningLayer.name() + " (foreground)"; -#endif + String layerName = m_owningLayer.name() + " (foreground)"; m_foregroundLayer = createGraphicsLayer(layerName); m_foregroundLayer->setDrawsContent(true); m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); @@ -1348,10 +1490,7 @@ bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer) bool layerChanged = false; if (needsBackgroundLayer) { if (!m_backgroundLayer) { - String layerName; -#ifndef NDEBUG - layerName = m_owningLayer.name() + " (background)"; -#endif + String layerName = m_owningLayer.name() + " (background)"; m_backgroundLayer = createGraphicsLayer(layerName); m_backgroundLayer->setDrawsContent(true); m_backgroundLayer->setAnchorPoint(FloatPoint3D()); @@ -1360,10 +1499,7 @@ bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer) } if (!m_contentsContainmentLayer) { - String layerName; -#ifndef NDEBUG - layerName = m_owningLayer.name() + " (contents containment)"; -#endif + String layerName = m_owningLayer.name() + " (contents containment)"; m_contentsContainmentLayer = createGraphicsLayer(layerName); m_contentsContainmentLayer->setAppliesPageScale(true); m_graphicsLayer->setAppliesPageScale(false); @@ -1394,17 +1530,38 @@ bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer) return layerChanged; } -bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) +// Masking layer is used for masks or clip-path. +void RenderLayerBacking::updateMaskingLayer(bool hasMask, bool hasClipPath) { bool layerChanged = false; - if (needsMaskLayer) { + if (hasMask || hasClipPath) { + GraphicsLayerPaintingPhase maskPhases = 0; + if (hasMask) + maskPhases = GraphicsLayerPaintMask; + + if (hasClipPath) { + // If we have a mask, we need to paint the combined clip-path and mask into the mask layer. + if (hasMask || renderer().style().clipPath()->type() == ClipPathOperation::Reference || !GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape)) + maskPhases |= GraphicsLayerPaintClipPath; + } + + bool paintsContent = maskPhases; + GraphicsLayer::Type requiredLayerType = paintsContent ? GraphicsLayer::Type::Normal : GraphicsLayer::Type::Shape; + if (m_maskLayer && m_maskLayer->type() != requiredLayerType) { + m_graphicsLayer->setMaskLayer(nullptr); + willDestroyLayer(m_maskLayer.get()); + m_maskLayer = nullptr; + } + if (!m_maskLayer) { - m_maskLayer = createGraphicsLayer("Mask"); - m_maskLayer->setDrawsContent(true); - m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask); + m_maskLayer = createGraphicsLayer("mask", requiredLayerType); + m_maskLayer->setDrawsContent(paintsContent); + m_maskLayer->setPaintingPhase(maskPhases); layerChanged = true; + m_graphicsLayer->setMaskLayer(m_maskLayer.get()); } } else if (m_maskLayer) { + m_graphicsLayer->setMaskLayer(nullptr); willDestroyLayer(m_maskLayer.get()); m_maskLayer = nullptr; layerChanged = true; @@ -1412,97 +1569,101 @@ bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) if (layerChanged) m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); +} - return layerChanged; +void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendantsClippingLayer) +{ + if (hasClippingLayer() && needsDescendantsClippingLayer) { + if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) { + // FIXME: we shouldn't get geometry here as layout may not have been udpated. + LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size()); + boxRect.move(contentOffsetInCompostingLayer()); + FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor()); + if (clippingLayer()->setMasksToBoundsRect(contentsClippingRect)) { + if (m_childClippingMaskLayer) + m_childClippingMaskLayer = nullptr; + return; + } + + if (!m_childClippingMaskLayer) { + m_childClippingMaskLayer = createGraphicsLayer("child clipping mask"); + m_childClippingMaskLayer->setDrawsContent(true); + m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask); + clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get()); + } + } + } else { + if (m_childClippingMaskLayer) { + if (hasClippingLayer()) + clippingLayer()->setMaskLayer(nullptr); + m_childClippingMaskLayer = nullptr; + } else + if (hasClippingLayer()) + clippingLayer()->setMasksToBoundsRect(FloatRoundedRect(FloatRect(FloatPoint(), clippingLayer()->size()))); + } } bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers) { - ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); + if (needsScrollingLayers == !!m_scrollingLayer) + return false; - bool layerChanged = false; - if (needsScrollingLayers) { - if (!m_scrollingLayer) { - // Outer layer which corresponds with the scroll view. - m_scrollingLayer = createGraphicsLayer("Scrolling container"); - m_scrollingLayer->setDrawsContent(false); - m_scrollingLayer->setMasksToBounds(true); - - // Inner layer which renders the content that scrolls. - m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents"); - m_scrollingContentsLayer->setDrawsContent(true); - GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll; - if (!m_foregroundLayer) - paintPhase |= GraphicsLayerPaintForeground; - m_scrollingContentsLayer->setPaintingPhase(paintPhase); - m_scrollingLayer->addChild(m_scrollingContentsLayer.get()); + if (!m_scrollingLayer) { + // Outer layer which corresponds with the scroll view. + m_scrollingLayer = createGraphicsLayer("scrolling container", GraphicsLayer::Type::Scrolling); + m_scrollingLayer->setDrawsContent(false); + m_scrollingLayer->setMasksToBounds(true); + + // Inner layer which renders the content that scrolls. + m_scrollingContentsLayer = createGraphicsLayer("scrolled Contents"); + m_scrollingContentsLayer->setDrawsContent(true); + + GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll; + if (!m_foregroundLayer) + paintPhase |= GraphicsLayerPaintForeground; + m_scrollingContentsLayer->setPaintingPhase(paintPhase); + m_scrollingLayer->addChild(m_scrollingContentsLayer.get()); + } else { + compositor().willRemoveScrollingLayerWithBacking(m_owningLayer, *this); - layerChanged = true; - if (scrollingCoordinator) - scrollingCoordinator->scrollableAreaScrollLayerDidChange(&m_owningLayer); -#if PLATFORM(IOS) - if (m_owningLayer.parent()) - compositor().scrollingLayerAddedOrUpdated(&m_owningLayer); -#endif - } - } else if (m_scrollingLayer) { -#if PLATFORM(IOS) - if (!renderer().documentBeingDestroyed()) - compositor().scrollingLayerRemoved(&m_owningLayer, m_scrollingLayer->platformLayer(), m_scrollingContentsLayer->platformLayer()); -#endif willDestroyLayer(m_scrollingLayer.get()); willDestroyLayer(m_scrollingContentsLayer.get()); m_scrollingLayer = nullptr; m_scrollingContentsLayer = nullptr; - layerChanged = true; - if (scrollingCoordinator) - scrollingCoordinator->scrollableAreaScrollLayerDidChange(&m_owningLayer); } - if (layerChanged) { - updateInternalHierarchy(); - m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); -#if !PLATFORM(IOS) - m_graphicsLayer->setNeedsDisplay(); - compositor().scrollingLayerDidChange(m_owningLayer); -#endif - } + m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); + m_graphicsLayer->setNeedsDisplay(); // Because painting phases changed. - return layerChanged; + if (m_scrollingLayer) + compositor().didAddScrollingLayer(m_owningLayer); + + return true; } -void RenderLayerBacking::attachToScrollingCoordinatorWithParent(RenderLayerBacking* parent) +void RenderLayerBacking::detachFromScrollingCoordinator(LayerScrollCoordinationRoles roles) { - ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); - if (!scrollingCoordinator) + if (!m_scrollingNodeID && !m_viewportConstrainedNodeID) return; - // FIXME: When we support overflow areas, we will have to refine this for overflow areas that are also - // positon:fixed. - ScrollingNodeType nodeType; - if (renderer().style().position() == FixedPosition) - nodeType = FixedNode; - else if (renderer().style().position() == StickyPosition) - nodeType = StickyNode; - else - nodeType = ScrollingNode; + auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator(); + if (!scrollingCoordinator) + return; - ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0; - m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, m_scrollLayerID ? m_scrollLayerID : scrollingCoordinator->uniqueScrollLayerID(), parentID); + if ((roles & Scrolling) && m_scrollingNodeID) { + scrollingCoordinator->detachFromStateTree(m_scrollingNodeID); + m_scrollingNodeID = 0; + } + + if ((roles & ViewportConstrained) && m_viewportConstrainedNodeID) { + scrollingCoordinator->detachFromStateTree(m_viewportConstrainedNodeID); + m_viewportConstrainedNodeID = 0; + } } -void RenderLayerBacking::detachFromScrollingCoordinator() +void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated) { - // If m_scrollLayerID is 0, then this backing is not attached to the ScrollingCoordinator. - if (!m_scrollLayerID) - return; - - ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); - if (!scrollingCoordinator) - return; - - scrollingCoordinator->detachFromStateTree(m_scrollLayerID); - m_scrollLayerID = 0; + m_graphicsLayer->setIsViewportConstrained(viewportCoordinated); } GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const @@ -1512,8 +1673,6 @@ GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() co phase |= GraphicsLayerPaintBackground; if (!m_foregroundLayer) phase |= GraphicsLayerPaintForeground; - if (!m_maskLayer) - phase |= GraphicsLayerPaintMask; if (m_scrollingContentsLayer) { phase &= ~GraphicsLayerPaintForeground; @@ -1544,38 +1703,75 @@ float RenderLayerBacking::compositingOpacity(float rendererOpacity) const return finalOpacity; } -static bool hasBoxDecorations(const RenderStyle* style) +// FIXME: Code is duplicated in RenderLayer. Also, we should probably not consider filters a box decoration here. +static inline bool hasVisibleBoxDecorations(const RenderStyle& style) { - return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter(); + return style.hasVisibleBorder() || style.hasBorderRadius() || style.hasOutline() || style.hasAppearance() || style.boxShadow() || style.hasFilter(); } -static bool canCreateTiledImage(const RenderStyle*); +static bool canDirectlyCompositeBackgroundBackgroundImage(const RenderStyle& style) +{ + if (!GraphicsLayer::supportsContentsTiling()) + return false; + + auto& fillLayer = style.backgroundLayers(); + if (fillLayer.next()) + return false; + + if (!fillLayer.imagesAreLoaded()) + return false; + + if (fillLayer.attachment() != ScrollBackgroundAttachment) + return false; + + // FIXME: Allow color+image compositing when it makes sense. + // For now bailing out. + if (style.visitedDependentColor(CSSPropertyBackgroundColor).isVisible()) + return false; + + // FIXME: support gradients with isGeneratedImage. + auto* styleImage = fillLayer.image(); + if (!styleImage->isCachedImage()) + return false; + + auto* image = styleImage->cachedImage()->image(); + if (!image->isBitmapImage()) + return false; + + return true; +} -static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) +static bool hasPaintedBoxDecorationsOrBackgroundImage(const RenderStyle& style) { - if (hasBoxDecorations(style)) + if (hasVisibleBoxDecorations(style)) return true; - if (!style->hasBackgroundImage()) + if (!style.hasBackgroundImage()) return false; - return !GraphicsLayer::supportsContentsTiling() || !canCreateTiledImage(style); + return !canDirectlyCompositeBackgroundBackgroundImage(style); } -static bool hasPerspectiveOrPreserves3D(const RenderStyle* style) +static inline bool hasPerspectiveOrPreserves3D(const RenderStyle& style) { - return style->hasPerspective() || style->preserves3D(); + return style.hasPerspective() || style.preserves3D(); } Color RenderLayerBacking::rendererBackgroundColor() const { - const auto& backgroundRenderer = renderer().isRoot() ? renderer().rendererForRootBackground() : renderer(); - return backgroundRenderer.style().visitedDependentColor(CSSPropertyBackgroundColor); + RenderElement* backgroundRenderer = nullptr; + if (renderer().isDocumentElementRenderer()) + backgroundRenderer = renderer().view().rendererForRootBackground(); + + if (!backgroundRenderer) + backgroundRenderer = &renderer(); + + return backgroundRenderer->style().visitedDependentColor(CSSPropertyBackgroundColor); } void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleContainer, bool& didUpdateContentsRect) { - if (!isSimpleContainer) { + if (!isSimpleContainer || (is<RenderBox>(renderer()) && !downcast<RenderBox>(renderer()).paintsOwnBackground())) { m_graphicsLayer->setContentsToSolidColor(Color()); return; } @@ -1584,44 +1780,12 @@ void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleCo // An unset (invalid) color will remove the solid color. m_graphicsLayer->setContentsToSolidColor(backgroundColor); - IntRect contentsRect = backgroundBox(); + FloatRect contentsRect = backgroundBoxForSimpleContainerPainting(); m_graphicsLayer->setContentsRect(contentsRect); - m_graphicsLayer->setContentsClippingRect(contentsRect); + m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(contentsRect)); didUpdateContentsRect = true; } -bool canCreateTiledImage(const RenderStyle* style) -{ - const FillLayer* fillLayer = style->backgroundLayers(); - if (fillLayer->next()) - return false; - - if (!fillLayer->imagesAreLoaded()) - return false; - - if (fillLayer->attachment() != ScrollBackgroundAttachment) - return false; - - Color color = style->visitedDependentColor(CSSPropertyBackgroundColor); - - // FIXME: Allow color+image compositing when it makes sense. - // For now bailing out. - if (color.isValid() && color.alpha()) - return false; - - StyleImage* styleImage = fillLayer->image(); - - // FIXME: support gradients with isGeneratedImage. - if (!styleImage->isCachedImage()) - return false; - - Image* image = styleImage->cachedImage()->image(); - if (!image->isBitmapImage()) - return false; - - return true; -} - void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleContainer, bool& didUpdateContentsRect) { if (!GraphicsLayer::supportsContentsTiling()) @@ -1630,30 +1794,30 @@ void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleCo if (isDirectlyCompositedImage()) return; - const RenderStyle& style = renderer().style(); - + auto& style = renderer().style(); if (!isSimpleContainer || !style.hasBackgroundImage()) { m_graphicsLayer->setContentsToImage(0); return; } - IntRect destRect = backgroundBox(); - IntPoint phase; - IntSize tileSize; + auto destRect = backgroundBoxForSimpleContainerPainting(); + FloatSize phase; + FloatSize tileSize; + // FIXME: Absolute paint location is required here. + downcast<RenderBox>(renderer()).getGeometryForBackgroundImage(&renderer(), LayoutPoint(), destRect, phase, tileSize); - RefPtr<Image> image = style.backgroundLayers()->image()->cachedImage()->image(); - toRenderBox(renderer()).getGeometryForBackgroundImage(&m_owningLayer.renderer(), destRect, phase, tileSize); m_graphicsLayer->setContentsTileSize(tileSize); m_graphicsLayer->setContentsTilePhase(phase); m_graphicsLayer->setContentsRect(destRect); - m_graphicsLayer->setContentsClippingRect(destRect); - m_graphicsLayer->setContentsToImage(image.get()); + m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(destRect)); + m_graphicsLayer->setContentsToImage(style.backgroundLayers().image()->cachedImage()->image()); + didUpdateContentsRect = true; } void RenderLayerBacking::updateRootLayerConfiguration() { - if (!m_usingTiledCacheLayer) + if (!m_isMainFrameLayerWithTiledBacking) return; Color backgroundColor; @@ -1671,15 +1835,16 @@ void RenderLayerBacking::updateRootLayerConfiguration() } } -static bool supportsDirectBoxDecorationsComposition(const RenderLayerModelObject& renderer) +static bool supportsDirectlyCompositedBoxDecorations(const RenderLayerModelObject& renderer) { if (!GraphicsLayer::supportsBackgroundColorContent()) return false; + const RenderStyle& style = renderer.style(); if (renderer.hasClip()) return false; - if (hasBoxDecorationsOrBackgroundImage(&renderer.style())) + if (hasPaintedBoxDecorationsOrBackgroundImage(style)) return false; // FIXME: We can't create a directly composited background if this @@ -1687,14 +1852,11 @@ static bool supportsDirectBoxDecorationsComposition(const RenderLayerModelObject // A better solution might be to introduce a flattening layer if // we do direct box decoration composition. // https://bugs.webkit.org/show_bug.cgi?id=119461 - if (hasPerspectiveOrPreserves3D(&renderer.style())) + if (hasPerspectiveOrPreserves3D(style)) return false; // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now. - if (renderer.style().backgroundComposite() != CompositeSourceOver) - return false; - - if (renderer.style().backgroundClip() == TextFillBox) + if (style.backgroundComposite() != CompositeSourceOver) return false; return true; @@ -1705,38 +1867,35 @@ bool RenderLayerBacking::paintsBoxDecorations() const if (!m_owningLayer.hasVisibleBoxDecorations()) return false; - if (!supportsDirectBoxDecorationsComposition(renderer())) - return true; - - return false; + return !supportsDirectlyCompositedBoxDecorations(renderer()); } -bool RenderLayerBacking::paintsChildren() const +bool RenderLayerBacking::paintsChildRenderers() const { if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers()) return true; - if (hasVisibleNonCompositingDescendantLayers()) + if (isPaintDestinationForDescendantLayers()) return true; return false; } -static bool isRestartedPlugin(RenderObject* renderer) +static bool isRestartedPlugin(RenderObject& renderer) { - if (!renderer->isEmbeddedObject()) + if (!is<RenderEmbeddedObject>(renderer)) return false; - Element* element = toElement(renderer->node()); - if (!element || !element->isPluginElement()) + HTMLFrameOwnerElement& element = downcast<RenderEmbeddedObject>(renderer).frameOwnerElement(); + if (!is<HTMLPlugInElement>(element)) return false; - return toHTMLPlugInElement(element)->isRestartedPlugin(); + return downcast<HTMLPlugInElement>(element).isRestartedPlugin(); } -static bool isCompositedPlugin(RenderObject* renderer) +static bool isCompositedPlugin(RenderObject& renderer) { - return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing(); + return is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing(); } // A "simple container layer" is a RenderLayer which has no visible content to render. @@ -1744,47 +1903,53 @@ static bool isCompositedPlugin(RenderObject* renderer) // This is a useful optimization, because it allows us to avoid allocating backing store. bool RenderLayerBacking::isSimpleContainerCompositingLayer() const { - if (renderer().hasMask()) // masks require special treatment + if (renderer().isRenderReplaced() && (!isCompositedPlugin(renderer()) || isRestartedPlugin(renderer()))) return false; - if (renderer().isReplaced() && (!isCompositedPlugin(&renderer()) || isRestartedPlugin(&renderer()))) + if (renderer().isTextControl()) return false; - if (paintsBoxDecorations() || paintsChildren()) + if (paintsBoxDecorations() || paintsChildRenderers()) return false; + if (renderer().style().backgroundClip() == TextFillBox) + return false; + if (renderer().isRenderNamedFlowFragmentContainer()) return false; + if (renderer().isDocumentElementRenderer() && m_owningLayer.isolatesCompositedBlending()) + return false; + if (renderer().isRenderView()) { // Look to see if the root object has a non-simple background - RenderObject* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : 0; + auto* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : nullptr; if (!rootObject) return false; - RenderStyle* style = &rootObject->style(); - // Reject anything that has a border, a border-radius or outline, // or is not a simple background (no background, or solid color). - if (hasBoxDecorationsOrBackgroundImage(style)) + if (hasPaintedBoxDecorationsOrBackgroundImage(rootObject->style())) return false; // Now look at the body's renderer. - HTMLElement* body = renderer().document().body(); - RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; - if (!bodyObject) + auto* body = renderer().document().body(); + if (!body) + return false; + auto* bodyRenderer = body->renderer(); + if (!bodyRenderer) return false; - style = &bodyObject->style(); - - if (hasBoxDecorationsOrBackgroundImage(style)) + if (hasPaintedBoxDecorationsOrBackgroundImage(bodyRenderer->style())) return false; } return true; } -static bool hasVisibleNonCompositingDescendant(RenderLayer& parent) +enum class LayerTraversal { Continue, Stop }; + +static LayerTraversal traverseVisibleNonCompositedDescendantLayers(RenderLayer& parent, std::function<LayerTraversal (const RenderLayer&)> layerFunc) { // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512. parent.updateLayerListsIfNeeded(); @@ -1793,49 +1958,75 @@ static bool hasVisibleNonCompositingDescendant(RenderLayer& parent) LayerListMutationDetector mutationChecker(&parent); #endif - if (Vector<RenderLayer*>* normalFlowList = parent.normalFlowList()) { - size_t listSize = normalFlowList->size(); - for (size_t i = 0; i < listSize; ++i) { - RenderLayer* curLayer = normalFlowList->at(i); - if (!curLayer->isComposited() - && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer))) - return true; + if (auto* normalFlowList = parent.normalFlowList()) { + for (auto* childLayer : *normalFlowList) { + if (compositedWithOwnBackingStore(*childLayer)) + continue; + + if (layerFunc(*childLayer) == LayerTraversal::Stop) + return LayerTraversal::Stop; + + if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop) + return LayerTraversal::Stop; } } if (parent.isStackingContainer()) { if (!parent.hasVisibleDescendant()) - return false; + return LayerTraversal::Continue; // Use the m_hasCompositingDescendant bit to optimize? - if (Vector<RenderLayer*>* negZOrderList = parent.negZOrderList()) { - size_t listSize = negZOrderList->size(); - for (size_t i = 0; i < listSize; ++i) { - RenderLayer* curLayer = negZOrderList->at(i); - if (!curLayer->isComposited() - && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer))) - return true; + if (auto* negZOrderList = parent.negZOrderList()) { + for (auto* childLayer : *negZOrderList) { + if (compositedWithOwnBackingStore(*childLayer)) + continue; + + if (layerFunc(*childLayer) == LayerTraversal::Stop) + return LayerTraversal::Stop; + + if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop) + return LayerTraversal::Stop; } } - if (Vector<RenderLayer*>* posZOrderList = parent.posZOrderList()) { - size_t listSize = posZOrderList->size(); - for (size_t i = 0; i < listSize; ++i) { - RenderLayer* curLayer = posZOrderList->at(i); - if (!curLayer->isComposited() - && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer))) - return true; + if (auto* posZOrderList = parent.posZOrderList()) { + for (auto* childLayer : *posZOrderList) { + if (compositedWithOwnBackingStore(*childLayer)) + continue; + + if (layerFunc(*childLayer) == LayerTraversal::Stop) + return LayerTraversal::Stop; + + if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop) + return LayerTraversal::Stop; } } } - return false; + return LayerTraversal::Continue; } // Conservative test for having no rendered children. -bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const +bool RenderLayerBacking::isPaintDestinationForDescendantLayers() const { - return hasVisibleNonCompositingDescendant(m_owningLayer); + bool hasPaintingDescendant = false; + traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasPaintingDescendant](const RenderLayer& layer) { + hasPaintingDescendant = layer.isVisuallyNonEmpty(); + return hasPaintingDescendant ? LayerTraversal::Stop : LayerTraversal::Continue; + }); + + return hasPaintingDescendant; +} + +bool RenderLayerBacking::hasVisibleNonCompositedDescendants() const +{ + bool hasVisibleDescendant = false; + traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasVisibleDescendant](const RenderLayer& layer) { + hasVisibleDescendant = layer.hasVisibleContent(); + return hasVisibleDescendant ? LayerTraversal::Stop : LayerTraversal::Continue; + }); + + return hasVisibleDescendant; } bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const @@ -1849,13 +2040,13 @@ bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, // and set background color on the layer in that case, instead of allocating backing store and painting. #if ENABLE(VIDEO) - if (renderer().isVideo() && toRenderVideo(renderer()).shouldDisplayVideo()) - return m_owningLayer.hasBoxDecorationsOrBackground(); + if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo()) + return m_owningLayer.hasVisibleBoxDecorationsOrBackground() || (!(downcast<RenderVideo>(renderer()).supportsAcceleratedRendering()) && m_requiresOwnBackingStore); #endif #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) - if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) - return m_owningLayer.hasBoxDecorationsOrBackground(); + if (is<RenderHTMLCanvas>(renderer()) && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) + return m_owningLayer.hasVisibleBoxDecorationsOrBackground(); #endif return true; @@ -1865,10 +2056,15 @@ bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const // that require painting. Direct compositing saves backing store. bool RenderLayerBacking::isDirectlyCompositedImage() const { - if (!renderer().isRenderImage() || renderer().isMedia() || m_owningLayer.hasBoxDecorationsOrBackground() || renderer().hasClip()) + if (!is<RenderImage>(renderer()) || m_owningLayer.hasVisibleBoxDecorationsOrBackground() || m_owningLayer.paintsWithFilters() || renderer().hasClip()) return false; - RenderImage& imageRenderer = toRenderImage(renderer()); +#if ENABLE(VIDEO) + if (is<RenderMedia>(renderer())) + return false; +#endif + + auto& imageRenderer = downcast<RenderImage>(renderer()); if (CachedImage* cachedImage = imageRenderer.cachedImage()) { if (!cachedImage->hasImage()) return false; @@ -1893,8 +2089,8 @@ void RenderLayerBacking::contentChanged(ContentChangeType changeType) return; } - if ((changeType == BackgroundImageChanged) && canCreateTiledImage(&renderer().style())) - updateGraphicsLayerGeometry(); + if ((changeType == BackgroundImageChanged) && canDirectlyCompositeBackgroundBackgroundImage(renderer().style())) + updateGeometry(); if ((changeType == MaskImageChanged) && m_maskLayer) { // The composited layer bounds relies on box->maskClipRect(), which changes @@ -1912,8 +2108,7 @@ void RenderLayerBacking::contentChanged(ContentChangeType changeType) void RenderLayerBacking::updateImageContents() { - ASSERT(renderer().isRenderImage()); - RenderImage& imageRenderer = toRenderImage(renderer()); + auto& imageRenderer = downcast<RenderImage>(renderer()); CachedImage* cachedImage = imageRenderer.cachedImage(); if (!cachedImage) @@ -1928,11 +2123,12 @@ void RenderLayerBacking::updateImageContents() return; // This is a no-op if the layer doesn't have an inner layer for the image. - m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox())); + m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor())); - LayoutRect contentsClippingRect = imageRenderer.contentBoxRect(); - contentsClippingRect.move(contentOffsetInCompostingLayer()); - m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect)); + LayoutRect boxRect(LayoutPoint(), imageRenderer.size()); + boxRect.move(contentOffsetInCompostingLayer()); + FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor()); + m_graphicsLayer->setContentsClippingRect(contentsClippingRect); m_graphicsLayer->setContentsToImage(image); bool isSimpleContainer = false; @@ -1944,52 +2140,39 @@ void RenderLayerBacking::updateImageContents() image->startAnimation(); } -FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const +FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const { const RenderStyle& style = renderer().style(); + float deviceScaleFactor = this->deviceScaleFactor(); FloatPoint3D origin; - origin.setX(floatValueForLength(style.transformOriginX(), borderBox.width())); - origin.setY(floatValueForLength(style.transformOriginY(), borderBox.height())); + origin.setX(roundToDevicePixel(floatValueForLength(style.transformOriginX(), borderBox.width()), deviceScaleFactor)); + origin.setY(roundToDevicePixel(floatValueForLength(style.transformOriginY(), borderBox.height()), deviceScaleFactor)); origin.setZ(style.transformOriginZ()); return origin; } -FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const -{ - const RenderStyle& style = renderer().style(); - - float boxWidth = borderBox.width(); - float boxHeight = borderBox.height(); - - FloatPoint origin; - origin.setX(floatValueForLength(style.perspectiveOriginX(), boxWidth)); - origin.setY(floatValueForLength(style.perspectiveOriginY(), boxHeight)); - - return origin; -} - // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const { - return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y()); + return LayoutSize(-m_compositedBounds.x() + m_compositedBoundsOffsetFromGraphicsLayer.width(), -m_compositedBounds.y() + m_compositedBoundsOffsetFromGraphicsLayer.height()); } LayoutRect RenderLayerBacking::contentsBox() const { - if (!renderer().isBox()) + if (!is<RenderBox>(renderer())) return LayoutRect(); - RenderBox& renderBox = toRenderBox(renderer()); + auto& renderBox = downcast<RenderBox>(renderer()); LayoutRect contentsRect; #if ENABLE(VIDEO) - if (renderBox.isVideo()) - contentsRect = toRenderVideo(renderBox).videoBox(); + if (is<RenderVideo>(renderBox)) + contentsRect = downcast<RenderVideo>(renderBox).videoBox(); else #endif - if (renderBox.isRenderReplaced()) { - RenderReplaced& renderReplaced = *toRenderReplaced(&renderBox); + if (is<RenderReplaced>(renderBox)) { + RenderReplaced& renderReplaced = downcast<RenderReplaced>(renderBox); contentsRect = renderReplaced.replacedContentRect(renderBox.intrinsicSize()); } else contentsRect = renderBox.contentBoxRect(); @@ -2007,7 +2190,7 @@ static LayoutRect backgroundRectForBox(const RenderBox& box) return box.paddingBoxRect(); case ContentFillBox: return box.contentBoxRect(); - case TextFillBox: + default: break; } @@ -2015,14 +2198,14 @@ static LayoutRect backgroundRectForBox(const RenderBox& box) return LayoutRect(); } -IntRect RenderLayerBacking::backgroundBox() const +FloatRect RenderLayerBacking::backgroundBoxForSimpleContainerPainting() const { - if (!renderer().isBox()) - return IntRect(); + if (!is<RenderBox>(renderer())) + return FloatRect(); - LayoutRect backgroundBox = backgroundRectForBox(toRenderBox(renderer())); + LayoutRect backgroundBox = backgroundRectForBox(downcast<RenderBox>(renderer())); backgroundBox.move(contentOffsetInCompostingLayer()); - return pixelSnappedIntRect(backgroundBox); + return snapRectToDevicePixels(backgroundBox, deviceScaleFactor()); } GraphicsLayer* RenderLayerBacking::parentForSublayers() const @@ -2030,14 +2213,7 @@ GraphicsLayer* RenderLayerBacking::parentForSublayers() const if (m_scrollingContentsLayer) return m_scrollingContentsLayer.get(); -#if PLATFORM(IOS) - // FIXME: Can we remove this iOS-specific code path? - if (GraphicsLayer* clippingLayer = this->clippingLayer()) - return clippingLayer; - return m_graphicsLayer.get(); -#else return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get(); -#endif } GraphicsLayer* RenderLayerBacking::childForSuperlayers() const @@ -2053,7 +2229,11 @@ GraphicsLayer* RenderLayerBacking::childForSuperlayers() const bool RenderLayerBacking::paintsIntoWindow() const { - if (m_usingTiledCacheLayer) +#if USE(COORDINATED_GRAPHICS_THREADED) + return false; +#endif + + if (m_isMainFrameLayerWithTiledBacking) return false; if (m_owningLayer.isRootLayer()) { @@ -2083,20 +2263,13 @@ void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking) compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds()); } -#if ENABLE(CSS_COMPOSITING) -void RenderLayerBacking::setBlendMode(BlendMode blendMode) -{ - m_graphicsLayer->setBlendMode(blendMode); -} -#endif - void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip) { ASSERT(!paintsIntoCompositedAncestor()); FrameView& frameView = owningLayer().renderer().view().frameView(); if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints()) - frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBox()); + frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting()); if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles. @@ -2116,61 +2289,72 @@ void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer if (m_maskLayer && m_maskLayer->drawsContent()) m_maskLayer->setNeedsDisplay(); + if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) + m_childClippingMaskLayer->setNeedsDisplay(); + if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) m_scrollingContentsLayer->setNeedsDisplay(); } // r is in the coordinate space of the layer's render object -void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r, GraphicsLayer::ShouldClipToLayer shouldClip) +void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, GraphicsLayer::ShouldClipToLayer shouldClip) { ASSERT(!paintsIntoCompositedAncestor()); + FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor()); FrameView& frameView = owningLayer().renderer().view().frameView(); if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints()) - frameView.addTrackedRepaintRect(pixelSnappedIntRect(r)); + frameView.addTrackedRepaintRect(pixelSnappedRectForPainting); if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { - IntRect layerDirtyRect = r; - layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer()); + FloatRect layerDirtyRect = pixelSnappedRectForPainting; + layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer); m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip); } if (m_foregroundLayer && m_foregroundLayer->drawsContent()) { - IntRect layerDirtyRect = r; - layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer()); + FloatRect layerDirtyRect = pixelSnappedRectForPainting; + layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer); m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip); } // FIXME: need to split out repaints for the background. if (m_backgroundLayer && m_backgroundLayer->drawsContent()) { - IntRect layerDirtyRect = r; - layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer()); + FloatRect layerDirtyRect = pixelSnappedRectForPainting; + layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer); m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip); } if (m_maskLayer && m_maskLayer->drawsContent()) { - IntRect layerDirtyRect = r; - layerDirtyRect.move(-m_maskLayer->offsetFromRenderer()); + FloatRect layerDirtyRect = pixelSnappedRectForPainting; + layerDirtyRect.move(-m_maskLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer); m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip); } + if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) { + FloatRect layerDirtyRect = r; + layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer()); + m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect); + } + if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) { - IntRect layerDirtyRect = r; - layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer()); + FloatRect layerDirtyRect = pixelSnappedRectForPainting; + layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer); #if PLATFORM(IOS) - // Account for the fact that RenderLayerBacking::updateGraphicsLayerGeometry() bakes scrollOffset into offsetFromRenderer on iOS. - layerDirtyRect.move(-m_owningLayer.scrollOffset()); + // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS, + // but the repaint rect is computed without taking the scroll position into account (see shouldApplyClipAndScrollPositionForRepaint()). + layerDirtyRect.moveBy(-m_owningLayer.scrollPosition()); #endif m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip); } } -void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context, - const IntRect& paintDirtyRect, // In the coords of rootLayer. - PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase) +void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext& context, + const IntRect& paintDirtyRect, // In the coords of rootLayer. + PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase) { - if (paintsIntoWindow() || paintsIntoCompositedAncestor()) { -#if !PLATFORM(IOS) + if ((paintsIntoWindow() || paintsIntoCompositedAncestor()) && paintingPhase != GraphicsLayerPaintChildClippingMask) { +#if !PLATFORM(IOS) && !OS(WINDOWS) // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy // when pages are restored from the PageCache. // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache @@ -2179,8 +2363,6 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap return; } - FontCachePurgePreventer fontCachePurgePreventer; - RenderLayer::PaintLayerFlags paintFlags = 0; if (paintingPhase & GraphicsLayerPaintBackground) paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase; @@ -2188,6 +2370,10 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase; if (paintingPhase & GraphicsLayerPaintMask) paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase; + if (paintingPhase & GraphicsLayerPaintClipPath) + paintFlags |= RenderLayer::PaintLayerPaintingCompositingClipPathPhase; + if (paintingPhase & GraphicsLayerPaintChildClippingMask) + paintFlags |= RenderLayer::PaintLayerPaintingChildClippingMaskPhase; if (paintingPhase & GraphicsLayerPaintOverflowContents) paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents; if (paintingPhase & GraphicsLayerPaintCompositedScroll) @@ -2197,74 +2383,73 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers. else if (compositor().fixedRootBackgroundLayer()) paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground; - + +#ifndef NDEBUG + RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&renderer()); +#endif + + FrameView::PaintingState paintingState; + if (m_owningLayer.isRootLayer()) + renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState); + // FIXME: GraphicsLayers need a way to split for RenderRegions. - RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, m_subpixelAccumulation); + RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer); m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags); if (m_owningLayer.containsDirtyOverlayScrollbars()) m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars); + if (m_owningLayer.isRootLayer()) + renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState); + compositor().didPaintBacking(this); ASSERT(!m_owningLayer.m_usedTransparency); } -static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) -{ - if (!scrollbar) - return; - - context.save(); - const IntRect& scrollbarRect = scrollbar->frameRect(); - context.translate(-scrollbarRect.x(), -scrollbarRect.y()); - IntRect transformedClip = clip; - transformedClip.moveBy(scrollbarRect.location()); - scrollbar->paint(&context, transformedClip); - context.restore(); -} - // Up-call from compositing layer drawing callback. -void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) +void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const FloatRect& clip) { #ifndef NDEBUG - if (Page* page = renderer().frame().page()) - page->setIsPainting(true); + renderer().page().setIsPainting(true); #endif + // The dirtyRect is in the coords of the painting root. + FloatRect adjustedClipRect = clip; + adjustedClipRect.move(m_subpixelOffsetFromRenderer); + IntRect dirtyRect = enclosingIntRect(adjustedClipRect); + if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_backgroundLayer.get() || graphicsLayer == m_maskLayer.get() + || graphicsLayer == m_childClippingMaskLayer.get() || graphicsLayer == m_scrollingContentsLayer.get()) { - InspectorInstrumentation::willPaint(&renderer()); + InspectorInstrumentation::willPaint(renderer()); - // The dirtyRect is in the coords of the painting root. - IntRect dirtyRect = clip; if (!(paintingPhase & GraphicsLayerPaintOverflowContents)) dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin())); // We have to use the same root as for hit testing, because both methods can compute and cache clipRects. - paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase); + paintIntoLayer(graphicsLayer, context, dirtyRect, PaintBehaviorNormal, paintingPhase); - InspectorInstrumentation::didPaint(&renderer(), &context, clip); + InspectorInstrumentation::didPaint(renderer(), dirtyRect); } else if (graphicsLayer == layerForHorizontalScrollbar()) { - paintScrollbar(m_owningLayer.horizontalScrollbar(), context, clip); + paintScrollbar(m_owningLayer.horizontalScrollbar(), context, dirtyRect); } else if (graphicsLayer == layerForVerticalScrollbar()) { - paintScrollbar(m_owningLayer.verticalScrollbar(), context, clip); + paintScrollbar(m_owningLayer.verticalScrollbar(), context, dirtyRect); } else if (graphicsLayer == layerForScrollCorner()) { const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect(); context.save(); context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y()); - LayoutRect transformedClip = clip; + LayoutRect transformedClip = LayoutRect(clip); transformedClip.moveBy(scrollCornerAndResizer.location()); - m_owningLayer.paintScrollCorner(&context, IntPoint(), pixelSnappedIntRect(transformedClip)); - m_owningLayer.paintResizer(&context, IntPoint(), transformedClip); + m_owningLayer.paintScrollCorner(context, IntPoint(), snappedIntRect(transformedClip)); + m_owningLayer.paintResizer(context, IntPoint(), transformedClip); context.restore(); } #ifndef NDEBUG - if (Page* page = renderer().frame().page()) - page->setIsPainting(false); + renderer().page().setIsPainting(false); #endif } @@ -2273,6 +2458,11 @@ float RenderLayerBacking::pageScaleFactor() const return compositor().pageScaleFactor(); } +float RenderLayerBacking::zoomedOutPageScaleFactor() const +{ + return compositor().zoomedOutPageScaleFactor(); +} + float RenderLayerBacking::deviceScaleFactor() const { return compositor().deviceScaleFactor(); @@ -2283,6 +2473,11 @@ float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer return compositor().contentsScaleMultiplierForNewTiles(layer); } +bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const +{ + return m_isMainFrameRenderViewLayer; +} + void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const { compositor().didFlushChangesForLayer(m_owningLayer, layer); @@ -2306,8 +2501,11 @@ bool RenderLayerBacking::isTrackingRepaints() const return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints(); } -bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer) const +bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer, LayerTreeAsTextBehavior behavior) const { + if (behavior & LayerTreeAsTextDebug) + return false; + // Skip the root tile cache's flattening layer. return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get(); } @@ -2333,30 +2531,52 @@ bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, return true; } +bool RenderLayerBacking::shouldAggressivelyRetainTiles(const GraphicsLayer*) const +{ + // Only the main frame TileController has enough information about in-window state to + // correctly implement aggressive tile retention. + if (!m_isMainFrameRenderViewLayer) + return false; + + return renderer().settings().aggressiveTileRetentionEnabled(); +} + +bool RenderLayerBacking::shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const +{ + return renderer().settings().temporaryTileCohortRetentionEnabled(); +} + +bool RenderLayerBacking::useGiantTiles() const +{ + return renderer().settings().useGiantTiles(); +} + #ifndef NDEBUG void RenderLayerBacking::verifyNotPainting() { - ASSERT(!renderer().frame().page() || !renderer().frame().page()->isPainting()); + ASSERT(!renderer().page().isPainting()); } #endif bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) { bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); - bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); -#if ENABLE(CSS_FILTERS) - bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter); -#else - bool hasFilter = false; + bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyTransform); + bool hasFilter = keyframes.containsProperty(CSSPropertyFilter); + + bool hasBackdropFilter = false; +#if ENABLE(FILTERS_LEVEL_2) + hasBackdropFilter = keyframes.containsProperty(CSSPropertyWebkitBackdropFilter); #endif - if (!hasOpacity && !hasTransform && !hasFilter) + if (!hasOpacity && !hasTransform && !hasFilter && !hasBackdropFilter) return false; - - KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); + + KeyframeValueList transformVector(AnimatedPropertyTransform); KeyframeValueList opacityVector(AnimatedPropertyOpacity); -#if ENABLE(CSS_FILTERS) - KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); + KeyframeValueList filterVector(AnimatedPropertyFilter); +#if ENABLE(FILTERS_LEVEL_2) + KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter); #endif size_t numKeyframes = keyframes.size(); @@ -2368,36 +2588,41 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim if (!keyframeStyle) continue; - // Get timing function. - RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0).timingFunction() : 0; + TimingFunction* tf = currentKeyframe.timingFunction(keyframes.animationName()); bool isFirstOrLastKeyframe = key == 0 || key == 1; - if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform)) - transformVector.insert(TransformAnimationValue::create(key, keyframeStyle->transform(), tf)); + if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyTransform)) + transformVector.insert(std::make_unique<TransformAnimationValue>(key, keyframeStyle->transform(), tf)); if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity)) - opacityVector.insert(FloatAnimationValue::create(key, keyframeStyle->opacity(), tf)); + opacityVector.insert(std::make_unique<FloatAnimationValue>(key, keyframeStyle->opacity(), tf)); + + if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyFilter)) + filterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->filter(), tf)); -#if ENABLE(CSS_FILTERS) - if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter)) - filterVector.insert(FilterAnimationValue::create(key, keyframeStyle->filter(), tf)); +#if ENABLE(FILTERS_LEVEL_2) + if ((hasBackdropFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitBackdropFilter)) + backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->backdropFilter(), tf)); #endif } - if (renderer().frame().page() && !renderer().frame().page()->settings().acceleratedCompositedAnimationsEnabled()) + if (!renderer().settings().acceleratedCompositedAnimationsEnabled()) return false; bool didAnimate = false; - if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) + if (hasTransform && m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), anim, keyframes.animationName(), timeOffset)) didAnimate = true; if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) didAnimate = true; -#if ENABLE(CSS_FILTERS) if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset)) didAnimate = true; + +#if ENABLE(FILTERS_LEVEL_2) + if (hasBackdropFilter && m_graphicsLayer->addAnimation(backdropFilterVector, IntSize(), anim, keyframes.animationName(), timeOffset)) + didAnimate = true; #endif return didAnimate; @@ -2423,41 +2648,55 @@ bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID proper const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { KeyframeValueList opacityVector(AnimatedPropertyOpacity); - opacityVector.insert(FloatAnimationValue::create(0, compositingOpacity(fromStyle->opacity()))); - opacityVector.insert(FloatAnimationValue::create(1, compositingOpacity(toStyle->opacity()))); + opacityVector.insert(std::make_unique<FloatAnimationValue>(0, compositingOpacity(fromStyle->opacity()))); + opacityVector.insert(std::make_unique<FloatAnimationValue>(1, compositingOpacity(toStyle->opacity()))); // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. - if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { + if (m_graphicsLayer->addAnimation(opacityVector, FloatSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. - updateOpacity(toStyle); + updateOpacity(*toStyle); didAnimate = true; } } } - if (property == CSSPropertyWebkitTransform && m_owningLayer.hasTransform()) { - const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); + if (property == CSSPropertyTransform && m_owningLayer.hasTransform()) { + const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyTransform); if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { - KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); - transformVector.insert(TransformAnimationValue::create(0, fromStyle->transform())); - transformVector.insert(TransformAnimationValue::create(1, toStyle->transform())); - if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { + KeyframeValueList transformVector(AnimatedPropertyTransform); + transformVector.insert(std::make_unique<TransformAnimationValue>(0, fromStyle->transform())); + transformVector.insert(std::make_unique<TransformAnimationValue>(1, toStyle->transform())); + if (m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyTransform), timeOffset)) { // To ensure that the correct transform is visible when the animation ends, also set the final transform. - updateTransform(toStyle); + updateTransform(*toStyle); didAnimate = true; } } } -#if ENABLE(CSS_FILTERS) - if (property == CSSPropertyWebkitFilter && m_owningLayer.hasFilter()) { - const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter); + if (property == CSSPropertyFilter && m_owningLayer.hasFilter()) { + const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyFilter); if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) { - KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); - filterVector.insert(FilterAnimationValue::create(0, fromStyle->filter())); - filterVector.insert(FilterAnimationValue::create(1, toStyle->filter())); - if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) { + KeyframeValueList filterVector(AnimatedPropertyFilter); + filterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->filter())); + filterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->filter())); + if (m_graphicsLayer->addAnimation(filterVector, FloatSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyFilter), timeOffset)) { // To ensure that the correct filter is visible when the animation ends, also set the final filter. - updateFilters(toStyle); + updateFilters(*toStyle); + didAnimate = true; + } + } + } + +#if ENABLE(FILTERS_LEVEL_2) + if (property == CSSPropertyWebkitBackdropFilter && m_owningLayer.hasBackdropFilter()) { + const Animation* backdropFilterAnim = toStyle->transitionForProperty(CSSPropertyWebkitBackdropFilter); + if (backdropFilterAnim && !backdropFilterAnim->isEmptyOrZeroDuration()) { + KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter); + backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->backdropFilter())); + backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->backdropFilter())); + if (m_graphicsLayer->addAnimation(backdropFilterVector, FloatSize(), backdropFilterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitBackdropFilter), timeOffset)) { + // To ensure that the correct backdrop filter is visible when the animation ends, also set the final backdrop filter. + updateBackdropFilters(*toStyle); didAnimate = true; } } @@ -2481,14 +2720,14 @@ void RenderLayerBacking::transitionFinished(CSSPropertyID property) m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty)); } -void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) +void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, const String&, double time) { - renderer().animation().notifyAnimationStarted(&renderer(), time); + renderer().animation().notifyAnimationStarted(renderer(), time); } void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer) { - if (renderer().documentBeingDestroyed()) + if (renderer().renderTreeBeingDestroyed()) return; compositor().scheduleLayerFlush(layer->canThrottleLayerFlush()); } @@ -2529,8 +2768,8 @@ LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth(); LayoutUnit topMarginHeight = tiledBacking->topMarginHeight(); - boundsIncludingMargin.moveBy(IntPoint(-leftMarginWidth, -topMarginHeight)); - boundsIncludingMargin.expand(leftMarginWidth + (LayoutUnit)tiledBacking->rightMarginWidth(), topMarginHeight + (LayoutUnit)tiledBacking->bottomMarginHeight()); + boundsIncludingMargin.moveBy(LayoutPoint(-leftMarginWidth, -topMarginHeight)); + boundsIncludingMargin.expand(leftMarginWidth + tiledBacking->rightMarginWidth(), topMarginHeight + tiledBacking->bottomMarginHeight()); return boundsIncludingMargin; } @@ -2539,24 +2778,25 @@ CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID { CSSPropertyID cssProperty = CSSPropertyInvalid; switch (property) { - case AnimatedPropertyWebkitTransform: - cssProperty = CSSPropertyWebkitTransform; - break; - case AnimatedPropertyOpacity: - cssProperty = CSSPropertyOpacity; - break; - case AnimatedPropertyBackgroundColor: - cssProperty = CSSPropertyBackgroundColor; - break; - case AnimatedPropertyWebkitFilter: -#if ENABLE(CSS_FILTERS) - cssProperty = CSSPropertyWebkitFilter; -#else - ASSERT_NOT_REACHED(); + case AnimatedPropertyTransform: + cssProperty = CSSPropertyTransform; + break; + case AnimatedPropertyOpacity: + cssProperty = CSSPropertyOpacity; + break; + case AnimatedPropertyBackgroundColor: + cssProperty = CSSPropertyBackgroundColor; + break; + case AnimatedPropertyFilter: + cssProperty = CSSPropertyFilter; + break; +#if ENABLE(FILTERS_LEVEL_2) + case AnimatedPropertyWebkitBackdropFilter: + cssProperty = CSSPropertyWebkitBackdropFilter; + break; #endif - break; - case AnimatedPropertyInvalid: - ASSERT_NOT_REACHED(); + case AnimatedPropertyInvalid: + ASSERT_NOT_REACHED(); } return cssProperty; } @@ -2564,30 +2804,32 @@ CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty) { switch (cssProperty) { - case CSSPropertyWebkitTransform: - return AnimatedPropertyWebkitTransform; - case CSSPropertyOpacity: - return AnimatedPropertyOpacity; - case CSSPropertyBackgroundColor: - return AnimatedPropertyBackgroundColor; -#if ENABLE(CSS_FILTERS) - case CSSPropertyWebkitFilter: - return AnimatedPropertyWebkitFilter; + case CSSPropertyTransform: + return AnimatedPropertyTransform; + case CSSPropertyOpacity: + return AnimatedPropertyOpacity; + case CSSPropertyBackgroundColor: + return AnimatedPropertyBackgroundColor; + case CSSPropertyFilter: + return AnimatedPropertyFilter; +#if ENABLE(FILTERS_LEVEL_2) + case CSSPropertyWebkitBackdropFilter: + return AnimatedPropertyWebkitBackdropFilter; #endif - default: - // It's fine if we see other css properties here; they are just not accelerated. - break; + default: + // It's fine if we see other css properties here; they are just not accelerated. + break; } return AnimatedPropertyInvalid; } CompositingLayerType RenderLayerBacking::compositingLayerType() const { - if (m_graphicsLayer->hasContentsLayer()) + if (m_graphicsLayer->usesContentsLayer()) return MediaCompositingLayer; if (m_graphicsLayer->drawsContent()) - return m_graphicsLayer->usingTiledBacking() ? TiledCompositingLayer : NormalCompositingLayer; + return m_graphicsLayer->tiledBacking() ? TiledCompositingLayer : NormalCompositingLayer; return ContainerCompositingLayer; } @@ -2604,6 +2846,8 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const backingMemory += m_backgroundLayer->backingStoreMemoryEstimate(); if (m_maskLayer) backingMemory += m_maskLayer->backingStoreMemoryEstimate(); + if (m_childClippingMaskLayer) + backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate(); if (m_scrollingContentsLayer) backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate(); @@ -2621,5 +2865,3 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const } } // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) |