Skip to content

Commit

Permalink
Update RenderLayerBacking to store backingSharingLayers in a WeakList…
Browse files Browse the repository at this point in the history
…HashSet

https://bugs.webkit.org/show_bug.cgi?id=261449

Reviewed by Simon Fraser.

Update RenderLayerBacking to store backingSharingLayers in a `WeakListHashSet<RenderLayer>`
instead of a Vector<WeakPtr<RenderLayer>>. This is beneficial to performance as we keep
doing linear searches in the vector otherwise.

* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::~RenderLayer):
* Source/WebCore/rendering/RenderLayerBacking.cpp:
(WebCore::clearBackingSharingLayerProviders):
(WebCore::RenderLayerBacking::setBackingSharingLayers):
(WebCore::RenderLayerBacking::removeBackingSharingLayer):
(WebCore::RenderLayerBacking::updateCompositedBounds):
(WebCore::RenderLayerBacking::paintIntoLayer):
* Source/WebCore/rendering/RenderLayerBacking.h:
* Source/WebCore/rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::BackingSharingState::endBackingSharingSequence):

Canonical link: https://commits.webkit.org/267912@main
  • Loading branch information
cdumez committed Sep 12, 2023
1 parent dd81c72 commit 3a63df5
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 39 deletions.
6 changes: 0 additions & 6 deletions Source/WebCore/rendering/RenderLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,12 +395,6 @@ RenderLayer::~RenderLayer()
clearLayerScrollableArea();
clearLayerFilters();

if (paintsIntoProvidedBacking()) {
auto* backingProviderLayer = this->backingProviderLayer();
if (backingProviderLayer->backing())
backingProviderLayer->backing()->removeBackingSharingLayer(*this);
}

// Child layers will be deleted by their corresponding render objects, so
// we don't need to delete them ourselves.

Expand Down
52 changes: 24 additions & 28 deletions Source/WebCore/rendering/RenderLayerBacking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,57 +289,53 @@ void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
compositor().layerTiledBackingUsageChanged(layer, false);
}

static void clearBackingSharingLayerProviders(const Vector<WeakPtr<RenderLayer>>& sharingLayers, const RenderLayer& providerLayer)
static void clearBackingSharingLayerProviders(WeakListHashSet<RenderLayer>& sharingLayers, const RenderLayer& providerLayer)
{
for (auto& layerWeakPtr : sharingLayers) {
if (!layerWeakPtr)
continue;
if (layerWeakPtr->backingProviderLayer() == &providerLayer)
layerWeakPtr->setBackingProviderLayer(nullptr);
for (auto& layer : sharingLayers) {
if (layer.backingProviderLayer() == &providerLayer)
layer.setBackingProviderLayer(nullptr);
}
}

void RenderLayerBacking::setBackingSharingLayers(Vector<WeakPtr<RenderLayer>>&& sharingLayers)
void RenderLayerBacking::setBackingSharingLayers(WeakListHashSet<RenderLayer>&& sharingLayers)
{
bool sharingLayersChanged = m_backingSharingLayers != sharingLayers;
if (sharingLayersChanged) {
// For layers that used to share and no longer do, and are not composited, recompute repaint rects.
for (auto& oldSharingLayer : m_backingSharingLayers) {
// Layers that go from shared to composited have their repaint rects recomputed in RenderLayerCompositor::updateBacking().
// FIXME: Two O(n^2) traversals in this funtion. Probably OK because sharing lists are usually small, but still.
if (!sharingLayers.contains(oldSharingLayer) && !oldSharingLayer->isComposited())
oldSharingLayer->computeRepaintRectsIncludingDescendants();
bool sharingLayersChanged = m_backingSharingLayers.computeSize() != sharingLayers.computeSize();
// For layers that used to share and no longer do, and are not composited, recompute repaint rects.
for (auto& oldSharingLayer : m_backingSharingLayers) {
// Layers that go from shared to composited have their repaint rects recomputed in RenderLayerCompositor::updateBacking().
if (!sharingLayers.contains(oldSharingLayer)) {
sharingLayersChanged = true;
if (!oldSharingLayer.isComposited())
oldSharingLayer.computeRepaintRectsIncludingDescendants();
}
}

clearBackingSharingLayerProviders(m_backingSharingLayers, m_owningLayer);

ASSERT(sharingLayersChanged == (m_backingSharingLayers != sharingLayers));
if (sharingLayersChanged) {
if (sharingLayers.size())
if (!sharingLayers.isEmptyIgnoringNullReferences())
setRequiresOwnBackingStore(true);
setContentsNeedDisplay(); // This could be optimized to only repaint rects for changed layers.
}

auto oldSharingLayers = std::exchange(m_backingSharingLayers, WTFMove(sharingLayers));

for (auto& layerWeakPtr : m_backingSharingLayers)
layerWeakPtr->setBackingProviderLayer(&m_owningLayer);
for (auto& layer : m_backingSharingLayers)
layer.setBackingProviderLayer(&m_owningLayer);

if (sharingLayersChanged) {
// For layers that are newly sharing, recompute repaint rects.
for (auto& currentSharingLayer : m_backingSharingLayers) {
if (!oldSharingLayers.contains(currentSharingLayer))
currentSharingLayer->computeRepaintRectsIncludingDescendants();
currentSharingLayer.computeRepaintRectsIncludingDescendants();
}
}
}

void RenderLayerBacking::removeBackingSharingLayer(RenderLayer& layer)
{
layer.setBackingProviderLayer(nullptr);
m_backingSharingLayers.removeFirst(&layer);
ASSERT(!m_backingSharingLayers.contains(&layer));
m_backingSharingLayers.remove(layer);
}

void RenderLayerBacking::clearBackingSharingLayers()
Expand Down Expand Up @@ -928,11 +924,11 @@ bool RenderLayerBacking::updateCompositedBounds()

// If the backing provider has overflow:clip, we know all sharing layers are affected by the clip because they are containing-block descendants.
if (!renderer().hasNonVisibleOverflow()) {
for (auto& layerWeakPtr : m_backingSharingLayers) {
for (auto& layer : m_backingSharingLayers) {
auto* boundsRootLayer = &m_owningLayer;
ASSERT(layerWeakPtr->isDescendantOf(m_owningLayer));
auto offset = layerWeakPtr->offsetFromAncestor(&m_owningLayer);
auto bounds = layerWeakPtr->calculateLayerBounds(boundsRootLayer, offset, RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
ASSERT(layer.isDescendantOf(m_owningLayer));
auto offset = layer.offsetFromAncestor(&m_owningLayer);
auto bounds = layer.calculateLayerBounds(boundsRootLayer, offset, RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
layerBounds.unite(bounds);
}
}
Expand Down Expand Up @@ -3502,8 +3498,8 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap
if (is<EventRegionContext>(regionContext))
sharingLayerPaintFlags.add(RenderLayer::PaintLayerFlag::CollectingEventRegion);

for (auto& layerWeakPtr : m_backingSharingLayers)
paintOneLayer(*layerWeakPtr, sharingLayerPaintFlags);
for (auto& layer : m_backingSharingLayers)
paintOneLayer(layer, sharingLayerPaintFlags);
}

if (!regionContext)
Expand Down
9 changes: 5 additions & 4 deletions Source/WebCore/rendering/RenderLayerBacking.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "RenderLayer.h"
#include "RenderLayerCompositor.h"
#include "ScrollingCoordinator.h"
#include <wtf/WeakListHashSet.h>

namespace WebCore {

Expand Down Expand Up @@ -71,10 +72,10 @@ class RenderLayerBacking final : public GraphicsLayerClient {
RenderLayer& owningLayer() const { return m_owningLayer; }

// Included layers are non-z-order descendant layers that are painted into this backing.
const Vector<WeakPtr<RenderLayer>>& backingSharingLayers() const { return m_backingSharingLayers; }
void setBackingSharingLayers(Vector<WeakPtr<RenderLayer>>&&);
const WeakListHashSet<RenderLayer>& backingSharingLayers() const { return m_backingSharingLayers; }
void setBackingSharingLayers(WeakListHashSet<RenderLayer>&&);

bool hasBackingSharingLayers() const { return !m_backingSharingLayers.isEmpty(); }
bool hasBackingSharingLayers() const { return !m_backingSharingLayers.isEmptyIgnoringNullReferences(); }

void removeBackingSharingLayer(RenderLayer&);
void clearBackingSharingLayers();
Expand Down Expand Up @@ -412,7 +413,7 @@ class RenderLayerBacking final : public GraphicsLayerClient {
RenderLayer& m_owningLayer;

// A list other layers that paint into this backing store, later than m_owningLayer in paint order.
Vector<WeakPtr<RenderLayer>> m_backingSharingLayers;
WeakListHashSet<RenderLayer> m_backingSharingLayers;

std::unique_ptr<LayerAncestorClippingStack> m_ancestorClippingStack; // Only used if we are clipped by an ancestor which is not a stacking context.
std::unique_ptr<LayerAncestorClippingStack> m_overflowControlsHostLayerAncestorClippingStack; // Used when we have an overflow controls host layer which was reparented, and needs clipping by ancestors.
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/RenderLayerCompositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ void RenderLayerCompositor::BackingSharingState::endBackingSharingSequence(Rende

for (auto& candidate : m_backingProviderCandidates) {
candidate.sharingLayers.remove(endLayer);
candidate.providerLayer->backing()->setBackingSharingLayers(copyToVector(candidate.sharingLayers));
candidate.providerLayer->backing()->setBackingSharingLayers(WTFMove(candidate.sharingLayers));
}
m_backingProviderCandidates.clear();
m_backingProviderStackingContext = nullptr;
Expand Down

0 comments on commit 3a63df5

Please sign in to comment.