зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1727683 - Remove LayerTreeInvalidation. r=jrmuizel
Depends on D123881 Differential Revision: https://phabricator.services.mozilla.com/D123882
This commit is contained in:
Родитель
7960f3b11b
Коммит
5c99a19709
|
@ -1,755 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LayerTreeInvalidation.h"
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include "ImageContainer.h" // for ImageContainer
|
||||
#include "ImageLayers.h" // for ImageLayer, etc
|
||||
#include "Layers.h" // for Layer, ContainerLayer, etc
|
||||
#include "Units.h" // for ParentLayerIntRect
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "mozilla/ArrayUtils.h" // for ArrayEqual
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||
#include "nsTHashMap.h" // for nsTHashMap
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsHashKeys.h" // for nsPtrHashKey
|
||||
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
|
||||
#include "nsRect.h" // for IntRect
|
||||
#include "nsTArray.h" // for AutoTArray, nsTArray_Impl
|
||||
#include "mozilla/Poison.h"
|
||||
#include "TreeTraversal.h" // for ForEachNode
|
||||
|
||||
// LayerTreeInvalidation debugging
|
||||
#define LTI_DEBUG 0
|
||||
|
||||
#if LTI_DEBUG
|
||||
# define LTI_DEEPER(aPrefix) nsPrintfCString("%s ", aPrefix).get()
|
||||
# define LTI_DUMP(rgn, label) \
|
||||
if (!(rgn).IsEmpty()) \
|
||||
printf_stderr("%s%p: " label " portion is %s\n", aPrefix, mLayer.get(), \
|
||||
ToString(rgn).c_str());
|
||||
# define LTI_LOG(...) printf_stderr(__VA_ARGS__)
|
||||
#else
|
||||
# define LTI_DEEPER(aPrefix) nullptr
|
||||
# define LTI_DUMP(rgn, label)
|
||||
# define LTI_LOG(...)
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct LayerPropertiesBase;
|
||||
UniquePtr<LayerPropertiesBase> CloneLayerTreePropertiesInternal(
|
||||
Layer* aRoot, bool aIsMask = false);
|
||||
|
||||
/**
|
||||
* Get accumulated transform of from the context creating layer to the
|
||||
* given layer.
|
||||
*/
|
||||
static Matrix4x4 GetTransformIn3DContext(Layer* aLayer) {
|
||||
Matrix4x4 transform = aLayer->GetLocalTransform();
|
||||
for (Layer* layer = aLayer->GetParent(); layer && layer->Extend3DContext();
|
||||
layer = layer->GetParent()) {
|
||||
transform = transform * layer->GetLocalTransform();
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a transform for the given layer depending on extending 3D
|
||||
* context.
|
||||
*
|
||||
* @return local transform for layers not participating 3D rendering
|
||||
* context, or the accmulated transform in the context for else.
|
||||
*/
|
||||
static Matrix4x4Flagged GetTransformForInvalidation(Layer* aLayer) {
|
||||
return (!aLayer->Is3DContextLeaf() && !aLayer->Extend3DContext()
|
||||
? aLayer->GetLocalTransform()
|
||||
: GetTransformIn3DContext(aLayer));
|
||||
}
|
||||
|
||||
static IntRect TransformRect(const IntRect& aRect,
|
||||
const Matrix4x4Flagged& aTransform) {
|
||||
if (aRect.IsEmpty()) {
|
||||
return IntRect();
|
||||
}
|
||||
|
||||
Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
|
||||
rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
|
||||
rect.RoundOut();
|
||||
|
||||
IntRect intRect;
|
||||
if (!rect.ToIntRect(&intRect)) {
|
||||
intRect = IntRect::MaxIntRect();
|
||||
}
|
||||
|
||||
return intRect;
|
||||
}
|
||||
|
||||
static void AddTransformedRegion(nsIntRegion& aDest, const nsIntRegion& aSource,
|
||||
const Matrix4x4Flagged& aTransform) {
|
||||
for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
|
||||
aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
|
||||
}
|
||||
aDest.SimplifyOutward(20);
|
||||
}
|
||||
|
||||
static void AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource) {
|
||||
aDest.Or(aDest, aSource);
|
||||
aDest.SimplifyOutward(20);
|
||||
}
|
||||
|
||||
Maybe<IntRect> TransformedBounds(Layer* aLayer) {
|
||||
if (aLayer->Extend3DContext()) {
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
MOZ_ASSERT(container);
|
||||
IntRect result;
|
||||
for (Layer* child = container->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
Maybe<IntRect> childBounds = TransformedBounds(child);
|
||||
if (!childBounds) {
|
||||
return Nothing();
|
||||
}
|
||||
Maybe<IntRect> combined = result.SafeUnion(childBounds.value());
|
||||
if (!combined) {
|
||||
LTI_LOG("overflowed bounds of container %p accumulating child %p\n",
|
||||
container, child);
|
||||
return Nothing();
|
||||
}
|
||||
result = combined.value();
|
||||
}
|
||||
return Some(result);
|
||||
}
|
||||
|
||||
return Some(
|
||||
TransformRect(aLayer->GetLocalVisibleRegion().GetBounds().ToUnknownRect(),
|
||||
GetTransformForInvalidation(aLayer)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks over this layer, and all descendant layers.
|
||||
* If any of these are a ContainerLayer that reports invalidations to a
|
||||
* PresShell, then report that the entire bounds have changed.
|
||||
*/
|
||||
static void NotifySubdocumentInvalidation(
|
||||
Layer* aLayer, NotifySubDocInvalidationFunc aCallback) {
|
||||
ForEachNode<ForwardIterator>(
|
||||
aLayer,
|
||||
[aCallback](Layer* layer) {
|
||||
layer->ClearInvalidRegion();
|
||||
if (layer->GetMaskLayer()) {
|
||||
NotifySubdocumentInvalidation(layer->GetMaskLayer(), aCallback);
|
||||
}
|
||||
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
|
||||
Layer* maskLayer = layer->GetAncestorMaskLayerAt(i);
|
||||
NotifySubdocumentInvalidation(maskLayer, aCallback);
|
||||
}
|
||||
},
|
||||
[aCallback](Layer* layer) {
|
||||
ContainerLayer* container = layer->AsContainerLayer();
|
||||
if (container && !container->Extend3DContext()) {
|
||||
nsIntRegion region =
|
||||
container->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
aCallback(container, ®ion);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void SetChildrenChangedRecursive(Layer* aLayer) {
|
||||
ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
|
||||
ContainerLayer* container = layer->AsContainerLayer();
|
||||
if (container) {
|
||||
container->SetChildrenChanged(true);
|
||||
container->SetInvalidCompositeRect(nullptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
struct LayerPropertiesBase : public LayerProperties {
|
||||
explicit LayerPropertiesBase(Layer* aLayer)
|
||||
: mLayer(aLayer),
|
||||
mMaskLayer(nullptr),
|
||||
mVisibleRegion(mLayer->Extend3DContext()
|
||||
? nsIntRegion()
|
||||
: mLayer->GetLocalVisibleRegion().ToUnknownRegion()),
|
||||
mPostXScale(aLayer->GetPostXScale()),
|
||||
mPostYScale(aLayer->GetPostYScale()),
|
||||
mOpacity(aLayer->GetLocalOpacity()),
|
||||
mUseClipRect(!!aLayer->GetLocalClipRect()) {
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
if (aLayer->GetMaskLayer()) {
|
||||
mMaskLayer =
|
||||
CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer(), true);
|
||||
}
|
||||
for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
|
||||
Layer* maskLayer = aLayer->GetAncestorMaskLayerAt(i);
|
||||
mAncestorMaskLayers.AppendElement(
|
||||
CloneLayerTreePropertiesInternal(maskLayer, true));
|
||||
}
|
||||
if (mUseClipRect) {
|
||||
mClipRect = *aLayer->GetLocalClipRect();
|
||||
}
|
||||
mTransform = GetTransformForInvalidation(aLayer);
|
||||
}
|
||||
LayerPropertiesBase()
|
||||
: mLayer(nullptr),
|
||||
mMaskLayer(nullptr),
|
||||
mPostXScale(0.0),
|
||||
mPostYScale(0.0),
|
||||
mOpacity(0.0),
|
||||
mUseClipRect(false) {
|
||||
MOZ_COUNT_CTOR(LayerPropertiesBase);
|
||||
}
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(LayerPropertiesBase)
|
||||
|
||||
protected:
|
||||
LayerPropertiesBase(const LayerPropertiesBase& a) = delete;
|
||||
LayerPropertiesBase& operator=(const LayerPropertiesBase& a) = delete;
|
||||
|
||||
public:
|
||||
bool ComputeDifferences(Layer* aRoot, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) override;
|
||||
|
||||
void MoveBy(const IntPoint& aOffset) override;
|
||||
|
||||
bool ComputeChange(const char* aPrefix, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) {
|
||||
// Bug 1251615: This canary is sometimes hit. We're still not sure why.
|
||||
mCanary.Check();
|
||||
bool transformChanged =
|
||||
!mTransform.FuzzyEqual(GetTransformForInvalidation(mLayer)) ||
|
||||
mLayer->GetPostXScale() != mPostXScale ||
|
||||
mLayer->GetPostYScale() != mPostYScale;
|
||||
const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetLocalClipRect();
|
||||
nsIntRegion result;
|
||||
|
||||
bool ancestorMaskChanged =
|
||||
mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();
|
||||
if (!ancestorMaskChanged) {
|
||||
for (size_t i = 0; i < mAncestorMaskLayers.Length(); i++) {
|
||||
if (mLayer->GetAncestorMaskLayerAt(i) !=
|
||||
mAncestorMaskLayers[i]->mLayer) {
|
||||
ancestorMaskChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't bailout early in general since this function
|
||||
// clears some persistent state at the end. Instead we set an overflow
|
||||
// flag and check it right before returning.
|
||||
bool areaOverflowed = false;
|
||||
|
||||
Layer* otherMask = mLayer->GetMaskLayer();
|
||||
if ((mMaskLayer ? mMaskLayer->mLayer : nullptr) != otherMask ||
|
||||
ancestorMaskChanged || (mUseClipRect != !!otherClip) ||
|
||||
mLayer->GetLocalOpacity() != mOpacity || transformChanged) {
|
||||
Maybe<IntRect> oldBounds = OldTransformedBounds();
|
||||
Maybe<IntRect> newBounds = NewTransformedBounds();
|
||||
if (oldBounds && newBounds) {
|
||||
LTI_DUMP(oldBounds.value(), "oldtransform");
|
||||
LTI_DUMP(newBounds.value(), "newtransform");
|
||||
result = oldBounds.value();
|
||||
AddRegion(result, newBounds.value());
|
||||
} else {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
|
||||
// We can't bail out early because we might need to update some internal
|
||||
// layer state.
|
||||
}
|
||||
|
||||
nsIntRegion internal;
|
||||
if (!ComputeChangeInternal(aPrefix, internal, aCallback)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
|
||||
LTI_DUMP(internal, "internal");
|
||||
AddRegion(result, internal);
|
||||
LTI_DUMP(mLayer->GetInvalidRegion().GetRegion(), "invalid");
|
||||
AddTransformedRegion(result, mLayer->GetInvalidRegion().GetRegion(),
|
||||
mTransform);
|
||||
|
||||
if (mMaskLayer && otherMask) {
|
||||
nsIntRegion mask;
|
||||
if (!mMaskLayer->ComputeChange(aPrefix, mask, aCallback)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
LTI_DUMP(mask, "mask");
|
||||
AddRegion(result, mask);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < std::min(mAncestorMaskLayers.Length(),
|
||||
mLayer->GetAncestorMaskLayerCount());
|
||||
i++) {
|
||||
nsIntRegion mask;
|
||||
if (!mAncestorMaskLayers[i]->ComputeChange(aPrefix, mask, aCallback)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
LTI_DUMP(mask, "ancestormask");
|
||||
AddRegion(result, mask);
|
||||
}
|
||||
|
||||
if (mUseClipRect && otherClip) {
|
||||
if (!mClipRect.IsEqualInterior(*otherClip)) {
|
||||
nsIntRegion tmp;
|
||||
tmp.Xor(mClipRect.ToUnknownRect(), otherClip->ToUnknownRect());
|
||||
LTI_DUMP(tmp, "clip");
|
||||
AddRegion(result, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
mLayer->ClearInvalidRegion();
|
||||
|
||||
if (areaOverflowed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutRegion = std::move(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CheckCanary() {
|
||||
mCanary.Check();
|
||||
mLayer->CheckCanary();
|
||||
}
|
||||
|
||||
IntRect NewTransformedBoundsForLeaf() {
|
||||
return TransformRect(
|
||||
mLayer->GetLocalVisibleRegion().GetBounds().ToUnknownRect(),
|
||||
GetTransformForInvalidation(mLayer));
|
||||
}
|
||||
|
||||
IntRect OldTransformedBoundsForLeaf() {
|
||||
return TransformRect(mVisibleRegion.GetBounds().ToUnknownRect(),
|
||||
mTransform);
|
||||
}
|
||||
|
||||
Maybe<IntRect> NewTransformedBounds() { return TransformedBounds(mLayer); }
|
||||
|
||||
virtual Maybe<IntRect> OldTransformedBounds() {
|
||||
return Some(
|
||||
TransformRect(mVisibleRegion.GetBounds().ToUnknownRect(), mTransform));
|
||||
}
|
||||
|
||||
virtual bool ComputeChangeInternal(const char* aPrefix,
|
||||
nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<Layer> mLayer;
|
||||
UniquePtr<LayerPropertiesBase> mMaskLayer;
|
||||
nsTArray<UniquePtr<LayerPropertiesBase>> mAncestorMaskLayers;
|
||||
nsIntRegion mVisibleRegion;
|
||||
Matrix4x4Flagged mTransform;
|
||||
float mPostXScale;
|
||||
float mPostYScale;
|
||||
float mOpacity;
|
||||
ParentLayerIntRect mClipRect;
|
||||
bool mUseClipRect;
|
||||
mozilla::CorruptionCanary mCanary;
|
||||
};
|
||||
|
||||
struct ContainerLayerProperties : public LayerPropertiesBase {
|
||||
explicit ContainerLayerProperties(ContainerLayer* aLayer)
|
||||
: LayerPropertiesBase(aLayer),
|
||||
mPreXScale(aLayer->GetPreXScale()),
|
||||
mPreYScale(aLayer->GetPreYScale()) {
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
child->CheckCanary();
|
||||
mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ContainerLayerProperties(const ContainerLayerProperties& a) = delete;
|
||||
ContainerLayerProperties& operator=(const ContainerLayerProperties& a) =
|
||||
delete;
|
||||
|
||||
public:
|
||||
bool ComputeChangeInternal(const char* aPrefix, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) override {
|
||||
// Make sure we got our virtual call right
|
||||
mSubtypeCanary.Check();
|
||||
ContainerLayer* container = mLayer->AsContainerLayer();
|
||||
nsIntRegion invalidOfLayer; // Invalid regions of this layer.
|
||||
nsIntRegion result; // Invliad regions for children only.
|
||||
|
||||
container->CheckCanary();
|
||||
|
||||
bool childrenChanged = false;
|
||||
bool invalidateWholeLayer = false;
|
||||
bool areaOverflowed = false;
|
||||
if (mPreXScale != container->GetPreXScale() ||
|
||||
mPreYScale != container->GetPreYScale()) {
|
||||
Maybe<IntRect> oldBounds = OldTransformedBounds();
|
||||
Maybe<IntRect> newBounds = NewTransformedBounds();
|
||||
if (oldBounds && newBounds) {
|
||||
invalidOfLayer = oldBounds.value();
|
||||
AddRegion(invalidOfLayer, newBounds.value());
|
||||
} else {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
childrenChanged = true;
|
||||
invalidateWholeLayer = true;
|
||||
|
||||
// Can't bail out early, we need to update the child container layers
|
||||
}
|
||||
|
||||
// A low frame rate is especially visible to users when scrolling, so we
|
||||
// particularly want to avoid unnecessary invalidation at that time. For us
|
||||
// here, that means avoiding unnecessary invalidation of child items when
|
||||
// other children are added to or removed from our container layer, since
|
||||
// that may be caused by children being scrolled in or out of view. We are
|
||||
// less concerned with children changing order.
|
||||
// TODO: Consider how we could avoid unnecessary invalidation when children
|
||||
// change order, and whether the overhead would be worth it.
|
||||
|
||||
nsTHashMap<nsPtrHashKey<Layer>, uint32_t> oldIndexMap(mChildren.Length());
|
||||
for (uint32_t i = 0; i < mChildren.Length(); ++i) {
|
||||
mChildren[i]->CheckCanary();
|
||||
oldIndexMap.InsertOrUpdate(mChildren[i]->mLayer, i);
|
||||
}
|
||||
|
||||
uint32_t i = 0; // cursor into the old child list mChildren
|
||||
for (Layer* child = container->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
bool invalidateChildsCurrentArea = false;
|
||||
if (i < mChildren.Length()) {
|
||||
uint32_t childsOldIndex;
|
||||
if (oldIndexMap.Get(child, &childsOldIndex)) {
|
||||
if (childsOldIndex >= i) {
|
||||
// Invalidate the old areas of layers that used to be between the
|
||||
// current |child| and the previous |child| that was also in the
|
||||
// old list mChildren (if any of those children have been reordered
|
||||
// rather than removed, we will invalidate their new area when we
|
||||
// encounter them in the new list):
|
||||
for (uint32_t j = i; j < childsOldIndex; ++j) {
|
||||
if (Maybe<IntRect> bounds =
|
||||
mChildren[j]->OldTransformedBounds()) {
|
||||
LTI_DUMP(bounds.value(), "reordered child");
|
||||
AddRegion(result, bounds.value());
|
||||
} else {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
childrenChanged |= true;
|
||||
}
|
||||
if (childsOldIndex >= mChildren.Length()) {
|
||||
MOZ_CRASH("Out of bounds");
|
||||
}
|
||||
// Invalidate any regions of the child that have changed:
|
||||
nsIntRegion region;
|
||||
if (!mChildren[childsOldIndex]->ComputeChange(LTI_DEEPER(aPrefix),
|
||||
region, aCallback)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
i = childsOldIndex + 1;
|
||||
if (!region.IsEmpty()) {
|
||||
LTI_LOG("%s%p: child %p produced %s\n", aPrefix, mLayer.get(),
|
||||
mChildren[childsOldIndex]->mLayer.get(),
|
||||
ToString(region).c_str());
|
||||
AddRegion(result, region);
|
||||
childrenChanged |= true;
|
||||
}
|
||||
} else {
|
||||
// We've already seen this child in mChildren (which means it must
|
||||
// have been reordered) and invalidated its old area. We need to
|
||||
// invalidate its new area too:
|
||||
invalidateChildsCurrentArea = true;
|
||||
}
|
||||
} else {
|
||||
// |child| is new
|
||||
invalidateChildsCurrentArea = true;
|
||||
SetChildrenChangedRecursive(child);
|
||||
}
|
||||
} else {
|
||||
// |child| is new, or was reordered to a higher index
|
||||
invalidateChildsCurrentArea = true;
|
||||
if (!oldIndexMap.Contains(child)) {
|
||||
SetChildrenChangedRecursive(child);
|
||||
}
|
||||
}
|
||||
if (invalidateChildsCurrentArea) {
|
||||
LTI_DUMP(child->GetLocalVisibleRegion().ToUnknownRegion(),
|
||||
"invalidateChildsCurrentArea");
|
||||
if (Maybe<IntRect> bounds = TransformedBounds(child)) {
|
||||
AddRegion(result, bounds.value());
|
||||
} else {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidation(child, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(child);
|
||||
}
|
||||
}
|
||||
childrenChanged |= invalidateChildsCurrentArea;
|
||||
}
|
||||
|
||||
// Process remaining removed children.
|
||||
while (i < mChildren.Length()) {
|
||||
childrenChanged |= true;
|
||||
if (Maybe<IntRect> bounds = mChildren[i]->OldTransformedBounds()) {
|
||||
LTI_DUMP(bounds.value(), "removed child");
|
||||
AddRegion(result, bounds.value());
|
||||
} else {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (aCallback) {
|
||||
aCallback(container, areaOverflowed ? nullptr : &result);
|
||||
}
|
||||
|
||||
if (childrenChanged || areaOverflowed) {
|
||||
container->SetChildrenChanged(true);
|
||||
}
|
||||
|
||||
if (container->UseIntermediateSurface()) {
|
||||
Maybe<IntRect> bounds;
|
||||
if (!invalidateWholeLayer && !areaOverflowed) {
|
||||
bounds = Some(result.GetBounds());
|
||||
|
||||
// Process changes in the visible region.
|
||||
IntRegion newVisible =
|
||||
mLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
if (!newVisible.IsEqual(mVisibleRegion)) {
|
||||
newVisible.XorWith(mVisibleRegion);
|
||||
bounds = bounds->SafeUnion(newVisible.GetBounds());
|
||||
}
|
||||
}
|
||||
container->SetInvalidCompositeRect(bounds ? bounds.ptr() : nullptr);
|
||||
}
|
||||
|
||||
// Safe to bail out early now, persistent state has been set.
|
||||
if (areaOverflowed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mLayer->Extend3DContext()) {
|
||||
// |result| contains invalid regions only of children.
|
||||
result.Transform(GetTransformForInvalidation(mLayer).GetMatrix());
|
||||
}
|
||||
// else, effective transforms have applied on children.
|
||||
|
||||
LTI_DUMP(invalidOfLayer, "invalidOfLayer");
|
||||
result.OrWith(invalidOfLayer);
|
||||
|
||||
aOutRegion = std::move(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
Maybe<IntRect> OldTransformedBounds() override {
|
||||
if (mLayer->Extend3DContext()) {
|
||||
IntRect result;
|
||||
for (UniquePtr<LayerPropertiesBase>& child : mChildren) {
|
||||
Maybe<IntRect> childBounds = child->OldTransformedBounds();
|
||||
if (!childBounds) {
|
||||
return Nothing();
|
||||
}
|
||||
Maybe<IntRect> combined = result.SafeUnion(childBounds.value());
|
||||
if (!combined) {
|
||||
LTI_LOG("overflowed bounds of container %p accumulating child %p\n",
|
||||
this, child->mLayer.get());
|
||||
return Nothing();
|
||||
}
|
||||
result = combined.value();
|
||||
}
|
||||
return Some(result);
|
||||
}
|
||||
return LayerPropertiesBase::OldTransformedBounds();
|
||||
}
|
||||
|
||||
// The old list of children:
|
||||
mozilla::CorruptionCanary mSubtypeCanary;
|
||||
nsTArray<UniquePtr<LayerPropertiesBase>> mChildren;
|
||||
float mPreXScale;
|
||||
float mPreYScale;
|
||||
};
|
||||
|
||||
struct ColorLayerProperties : public LayerPropertiesBase {
|
||||
explicit ColorLayerProperties(ColorLayer* aLayer)
|
||||
: LayerPropertiesBase(aLayer),
|
||||
mColor(aLayer->GetColor()),
|
||||
mBounds(aLayer->GetBounds()) {}
|
||||
|
||||
protected:
|
||||
ColorLayerProperties(const ColorLayerProperties& a) = delete;
|
||||
ColorLayerProperties& operator=(const ColorLayerProperties& a) = delete;
|
||||
|
||||
public:
|
||||
bool ComputeChangeInternal(const char* aPrefix, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) override {
|
||||
ColorLayer* color = static_cast<ColorLayer*>(mLayer.get());
|
||||
|
||||
if (mColor != color->GetColor()) {
|
||||
LTI_DUMP(NewTransformedBoundsForLeaf(), "color");
|
||||
aOutRegion = NewTransformedBoundsForLeaf();
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIntRegion boundsDiff;
|
||||
boundsDiff.Xor(mBounds, color->GetBounds());
|
||||
LTI_DUMP(boundsDiff, "colorbounds");
|
||||
|
||||
AddTransformedRegion(aOutRegion, boundsDiff, mTransform);
|
||||
return true;
|
||||
}
|
||||
|
||||
DeviceColor mColor;
|
||||
IntRect mBounds;
|
||||
};
|
||||
|
||||
struct ImageLayerProperties : public LayerPropertiesBase {
|
||||
explicit ImageLayerProperties(ImageLayer* aImage, bool aIsMask)
|
||||
: LayerPropertiesBase(aImage),
|
||||
mContainer(aImage->GetContainer()),
|
||||
mSamplingFilter(aImage->GetSamplingFilter()),
|
||||
mScaleToSize(aImage->GetScaleToSize()),
|
||||
mScaleMode(aImage->GetScaleMode()),
|
||||
mLastProducerID(-1),
|
||||
mLastFrameID(-1),
|
||||
mIsMask(aIsMask) {}
|
||||
|
||||
bool ComputeChangeInternal(const char* aPrefix, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) override {
|
||||
ImageLayer* imageLayer = static_cast<ImageLayer*>(mLayer.get());
|
||||
|
||||
if (!imageLayer->GetLocalVisibleRegion().ToUnknownRegion().IsEqual(
|
||||
mVisibleRegion)) {
|
||||
IntRect result = NewTransformedBoundsForLeaf();
|
||||
result = result.Union(OldTransformedBoundsForLeaf());
|
||||
aOutRegion = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
ImageContainer* container = imageLayer->GetContainer();
|
||||
if (mContainer != container ||
|
||||
mSamplingFilter != imageLayer->GetSamplingFilter() ||
|
||||
mScaleToSize != imageLayer->GetScaleToSize() ||
|
||||
mScaleMode != imageLayer->GetScaleMode()) {
|
||||
if (mIsMask) {
|
||||
// Mask layers have an empty visible region, so we have to
|
||||
// use the image size instead.
|
||||
IntSize size;
|
||||
if (container) {
|
||||
size = container->GetCurrentSize();
|
||||
}
|
||||
IntRect rect(0, 0, size.width, size.height);
|
||||
LTI_DUMP(rect, "mask");
|
||||
aOutRegion = TransformRect(rect, GetTransformForInvalidation(mLayer));
|
||||
return true;
|
||||
}
|
||||
LTI_DUMP(NewTransformedBoundsForLeaf(), "bounds");
|
||||
aOutRegion = NewTransformedBoundsForLeaf();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ImageContainer> mContainer;
|
||||
SamplingFilter mSamplingFilter;
|
||||
gfx::IntSize mScaleToSize;
|
||||
ScaleMode mScaleMode;
|
||||
int32_t mLastProducerID;
|
||||
int32_t mLastFrameID;
|
||||
bool mIsMask;
|
||||
};
|
||||
|
||||
UniquePtr<LayerPropertiesBase> CloneLayerTreePropertiesInternal(
|
||||
Layer* aRoot, bool aIsMask /* = false */) {
|
||||
if (!aRoot) {
|
||||
return MakeUnique<LayerPropertiesBase>();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!aIsMask || aRoot->GetType() == Layer::TYPE_IMAGE);
|
||||
|
||||
aRoot->CheckCanary();
|
||||
|
||||
switch (aRoot->GetType()) {
|
||||
case Layer::TYPE_CONTAINER:
|
||||
case Layer::TYPE_REF:
|
||||
return MakeUnique<ContainerLayerProperties>(aRoot->AsContainerLayer());
|
||||
case Layer::TYPE_COLOR:
|
||||
return MakeUnique<ColorLayerProperties>(static_cast<ColorLayer*>(aRoot));
|
||||
case Layer::TYPE_IMAGE:
|
||||
return MakeUnique<ImageLayerProperties>(static_cast<ImageLayer*>(aRoot),
|
||||
aIsMask);
|
||||
case Layer::TYPE_CANVAS:
|
||||
case Layer::TYPE_DISPLAYITEM:
|
||||
case Layer::TYPE_READBACK:
|
||||
case Layer::TYPE_SHADOW:
|
||||
case Layer::TYPE_PAINTED:
|
||||
return MakeUnique<LayerPropertiesBase>(aRoot);
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected root layer type");
|
||||
return MakeUnique<LayerPropertiesBase>(aRoot);
|
||||
}
|
||||
|
||||
/* static */
|
||||
UniquePtr<LayerProperties> LayerProperties::CloneFrom(Layer* aRoot) {
|
||||
return CloneLayerTreePropertiesInternal(aRoot);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void LayerProperties::ClearInvalidations(Layer* aLayer) {
|
||||
ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
|
||||
layer->ClearInvalidRegion();
|
||||
if (layer->GetMaskLayer()) {
|
||||
ClearInvalidations(layer->GetMaskLayer());
|
||||
}
|
||||
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
|
||||
ClearInvalidations(layer->GetAncestorMaskLayerAt(i));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool LayerPropertiesBase::ComputeDifferences(
|
||||
Layer* aRoot, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) {
|
||||
NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
|
||||
if (mLayer != aRoot) {
|
||||
if (aCallback) {
|
||||
NotifySubdocumentInvalidation(aRoot, aCallback);
|
||||
} else {
|
||||
ClearInvalidations(aRoot);
|
||||
}
|
||||
IntRect bounds = TransformRect(
|
||||
aRoot->GetLocalVisibleRegion().GetBounds().ToUnknownRect(),
|
||||
aRoot->GetLocalTransform());
|
||||
Maybe<IntRect> oldBounds = OldTransformedBounds();
|
||||
if (!oldBounds) {
|
||||
return false;
|
||||
}
|
||||
Maybe<IntRect> result = bounds.SafeUnion(oldBounds.value());
|
||||
if (!result) {
|
||||
LTI_LOG("overflowed bounds computing the union of layers %p and %p\n",
|
||||
mLayer.get(), aRoot);
|
||||
return false;
|
||||
}
|
||||
aOutRegion = result.value();
|
||||
return true;
|
||||
}
|
||||
return ComputeChange(" ", aOutRegion, aCallback);
|
||||
}
|
||||
|
||||
void LayerPropertiesBase::MoveBy(const IntPoint& aOffset) {
|
||||
mTransform.PostTranslate(aOffset.x, aOffset.y, 0);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -1,79 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_LAYER_TREE_INVALIDATION_H
|
||||
#define GFX_LAYER_TREE_INVALIDATION_H
|
||||
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "mozilla/UniquePtr.h" // for UniquePtr
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
class ContainerLayer;
|
||||
|
||||
/**
|
||||
* Callback for ContainerLayer invalidations.
|
||||
*
|
||||
* @param aContainer ContainerLayer being invalidated.
|
||||
* @param aRegion Invalidated region in the ContainerLayer's coordinate
|
||||
* space. If null, then the entire region must be invalidated.
|
||||
*/
|
||||
typedef void (*NotifySubDocInvalidationFunc)(ContainerLayer* aLayer,
|
||||
const nsIntRegion* aRegion);
|
||||
|
||||
/**
|
||||
* A set of cached layer properties (including those of child layers),
|
||||
* used for comparing differences in layer trees.
|
||||
*/
|
||||
struct LayerProperties {
|
||||
protected:
|
||||
LayerProperties() = default;
|
||||
|
||||
LayerProperties(const LayerProperties& a) = delete;
|
||||
LayerProperties& operator=(const LayerProperties& a) = delete;
|
||||
|
||||
public:
|
||||
virtual ~LayerProperties() = default;
|
||||
|
||||
/**
|
||||
* Copies the current layer tree properties into
|
||||
* a new LayerProperties object.
|
||||
*
|
||||
* @param Layer tree to copy, or nullptr if we have no
|
||||
* initial layer tree.
|
||||
*/
|
||||
static UniquePtr<LayerProperties> CloneFrom(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Clear all invalidation status from this layer tree.
|
||||
*/
|
||||
static void ClearInvalidations(Layer* aRoot);
|
||||
|
||||
/**
|
||||
* Compares a set of existing layer tree properties to the current layer
|
||||
* tree and generates the changed rectangle.
|
||||
*
|
||||
* @param aRoot Root layer of the layer tree to compare against.
|
||||
* @param aOutRegion Outparam that will contain the painted area changed by
|
||||
* the layer tree changes.
|
||||
* @param aCallback If specified, callback to call when ContainerLayers
|
||||
* are invalidated.
|
||||
* @return True on success, false if a calculation overflowed and the entire
|
||||
* layer tree area should be considered invalidated.
|
||||
*/
|
||||
virtual bool ComputeDifferences(Layer* aRoot, nsIntRegion& aOutRegion,
|
||||
NotifySubDocInvalidationFunc aCallback) = 0;
|
||||
|
||||
virtual void MoveBy(const gfx::IntPoint& aOffset) = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_LAYER_TREE_INVALIDATON_H */
|
|
@ -24,7 +24,6 @@ EXPORTS += [
|
|||
"Layers.h",
|
||||
"LayerScope.h",
|
||||
"LayersTypes.h",
|
||||
"LayerTreeInvalidation.h",
|
||||
"LayerUserData.h",
|
||||
"opengl/OGLShaderConfig.h",
|
||||
"opengl/OGLShaderProgram.h",
|
||||
|
@ -433,7 +432,6 @@ UNIFIED_SOURCES += [
|
|||
"LayerScope.cpp",
|
||||
"LayersHelpers.cpp",
|
||||
"LayersTypes.cpp",
|
||||
"LayerTreeInvalidation.cpp",
|
||||
"MemoryPressureObserver.cpp",
|
||||
"opengl/CompositingRenderTargetOGL.cpp",
|
||||
"opengl/CompositorOGL.cpp",
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "nsLayoutUtils.h"
|
||||
#include "nsTHashSet.h"
|
||||
#include "WebRenderCanvasRenderer.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
|
|
@ -163,7 +163,6 @@
|
|||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "Layers.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "mozilla/dom/DocumentTimeline.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -6358,22 +6357,6 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|||
if (!(aFlags & PaintFlags::PaintSyncDecodeImages) &&
|
||||
!frame->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE) &&
|
||||
!mNextPaintCompressed) {
|
||||
NotifySubDocInvalidationFunc computeInvalidFunc =
|
||||
presContext->MayHavePaintEventListenerInSubDocument()
|
||||
? nsPresContext::NotifySubDocInvalidation
|
||||
: 0;
|
||||
bool computeInvalidRect =
|
||||
computeInvalidFunc ||
|
||||
(renderer->GetBackendType() == LayersBackend::LAYERS_BASIC);
|
||||
|
||||
UniquePtr<LayerProperties> props;
|
||||
// For WR, the layermanager has no root layer. We want to avoid
|
||||
// calling ComputeDifferences in that case because it assumes non-null
|
||||
// and crashes.
|
||||
if (computeInvalidRect && layerManager && layerManager->GetRoot()) {
|
||||
props = LayerProperties::CloneFrom(layerManager->GetRoot());
|
||||
}
|
||||
|
||||
if (layerManager) {
|
||||
MaybeSetupTransactionIdAllocator(layerManager, presContext);
|
||||
}
|
||||
|
@ -6381,31 +6364,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|||
if (renderer->EndEmptyTransaction((aFlags & PaintFlags::PaintComposite)
|
||||
? LayerManager::END_DEFAULT
|
||||
: LayerManager::END_NO_COMPOSITE)) {
|
||||
nsIntRegion invalid;
|
||||
bool areaOverflowed = false;
|
||||
if (props) {
|
||||
if (!props->ComputeDifferences(layerManager->GetRoot(), invalid,
|
||||
computeInvalidFunc)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
} else if (layerManager) {
|
||||
LayerProperties::ClearInvalidations(layerManager->GetRoot());
|
||||
}
|
||||
if (props && !areaOverflowed) {
|
||||
if (!invalid.IsEmpty()) {
|
||||
nsIntRect bounds = invalid.GetBounds();
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(bounds.x),
|
||||
presContext->DevPixelsToAppUnits(bounds.y),
|
||||
presContext->DevPixelsToAppUnits(bounds.width),
|
||||
presContext->DevPixelsToAppUnits(bounds.height));
|
||||
if (shouldInvalidate) {
|
||||
aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(
|
||||
aViewToPaint, rect);
|
||||
}
|
||||
presContext->NotifyInvalidation(
|
||||
layerManager->GetLastTransactionId(), bounds);
|
||||
}
|
||||
} else if (shouldInvalidate) {
|
||||
if (shouldInvalidate) {
|
||||
aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint);
|
||||
}
|
||||
|
||||
|
@ -6448,19 +6407,7 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|||
|
||||
bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
|
||||
|
||||
if (!layerManager) {
|
||||
FallbackRenderer* fallback = renderer->AsFallback();
|
||||
MOZ_ASSERT(fallback);
|
||||
|
||||
if (aFlags & PaintFlags::PaintComposite) {
|
||||
nsIntRect bounds = presContext->GetVisibleArea().ToOutsidePixels(
|
||||
presContext->AppUnitsPerDevPixel());
|
||||
fallback->EndTransactionWithColor(bounds, ToDeviceColor(bgcolor));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
||||
if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
||||
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
|
||||
presContext->GetVisibleArea(), presContext->AppUnitsPerDevPixel());
|
||||
WebRenderBackgroundData data(wr::ToLayoutRect(bounds),
|
||||
|
@ -6473,19 +6420,14 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<ColorLayer> root = layerManager->CreateColorLayer();
|
||||
if (root) {
|
||||
FallbackRenderer* fallback = renderer->AsFallback();
|
||||
MOZ_ASSERT(fallback);
|
||||
|
||||
if (aFlags & PaintFlags::PaintComposite) {
|
||||
nsIntRect bounds = presContext->GetVisibleArea().ToOutsidePixels(
|
||||
presContext->AppUnitsPerDevPixel());
|
||||
root->SetColor(ToDeviceColor(bgcolor));
|
||||
root->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(bounds));
|
||||
layerManager->SetRoot(root);
|
||||
fallback->EndTransactionWithColor(bounds, ToDeviceColor(bgcolor));
|
||||
}
|
||||
MaybeSetupTransactionIdAllocator(layerManager, presContext);
|
||||
layerManager->EndTransaction(nullptr, nullptr,
|
||||
(aFlags & PaintFlags::PaintComposite)
|
||||
? LayerManager::END_DEFAULT
|
||||
: LayerManager::END_NO_COMPOSITE);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -109,8 +109,6 @@ using namespace mozilla::dom;
|
|||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
uint8_t gNotifySubDocInvalidationData;
|
||||
|
||||
/**
|
||||
* Layer UserData for ContainerLayers that want to be notified
|
||||
* of local invalidations of them and their descendant layers.
|
||||
|
@ -1999,26 +1997,6 @@ bool nsPresContext::MayHavePaintEventListener() {
|
|||
return ::MayHavePaintEventListener(mDocument->GetInnerWindow());
|
||||
}
|
||||
|
||||
bool nsPresContext::MayHavePaintEventListenerInSubDocument() {
|
||||
if (MayHavePaintEventListener()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
auto recurse = [&result](dom::Document& aSubDoc) {
|
||||
if (nsPresContext* pc = aSubDoc.GetPresContext()) {
|
||||
if (pc->MayHavePaintEventListenerInSubDocument()) {
|
||||
result = true;
|
||||
return CallState::Stop;
|
||||
}
|
||||
}
|
||||
return CallState::Continue;
|
||||
};
|
||||
|
||||
mDocument->EnumerateSubDocuments(recurse);
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsPresContext::NotifyInvalidation(TransactionId aTransactionId,
|
||||
const nsIntRect& aRect) {
|
||||
// Prevent values from overflow after DevPixelsToAppUnits().
|
||||
|
@ -2076,49 +2054,6 @@ void nsPresContext::NotifyInvalidation(TransactionId aTransactionId,
|
|||
transaction->mInvalidations.AppendElement(aRect);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsPresContext::NotifySubDocInvalidation(ContainerLayer* aContainer,
|
||||
const nsIntRegion* aRegion) {
|
||||
ContainerLayerPresContext* data = static_cast<ContainerLayerPresContext*>(
|
||||
aContainer->GetUserData(&gNotifySubDocInvalidationData));
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
TransactionId transactionId = aContainer->Manager()->GetLastTransactionId();
|
||||
IntRect visibleBounds =
|
||||
aContainer->GetVisibleRegion().GetBounds().ToUnknownRect();
|
||||
|
||||
if (!aRegion) {
|
||||
IntRect rect(IntPoint(0, 0), visibleBounds.Size());
|
||||
data->mPresContext->NotifyInvalidation(transactionId, rect);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntPoint topLeft = visibleBounds.TopLeft();
|
||||
for (auto iter = aRegion->RectIter(); !iter.Done(); iter.Next()) {
|
||||
nsIntRect rect(iter.Get());
|
||||
// PresContext coordinate space is relative to the start of our visible
|
||||
// region. Is this really true? This feels like the wrong way to get the
|
||||
// right answer.
|
||||
rect.MoveBy(-topLeft);
|
||||
data->mPresContext->NotifyInvalidation(transactionId, rect);
|
||||
}
|
||||
}
|
||||
|
||||
void nsPresContext::SetNotifySubDocInvalidationData(
|
||||
ContainerLayer* aContainer) {
|
||||
ContainerLayerPresContext* pres = new ContainerLayerPresContext;
|
||||
pres->mPresContext = this;
|
||||
aContainer->SetUserData(&gNotifySubDocInvalidationData, pres);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsPresContext::ClearNotifySubDocInvalidationData(
|
||||
ContainerLayer* aContainer) {
|
||||
aContainer->SetUserData(&gNotifySubDocInvalidationData, nullptr);
|
||||
}
|
||||
|
||||
class DelayedFireDOMPaintEvent : public Runnable {
|
||||
public:
|
||||
DelayedFireDOMPaintEvent(
|
||||
|
|
|
@ -938,14 +938,6 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
void FireDOMPaintEvent(nsTArray<nsRect>* aList, TransactionId aTransactionId,
|
||||
mozilla::TimeStamp aTimeStamp = mozilla::TimeStamp());
|
||||
|
||||
// Callback for catching invalidations in ContainerLayers
|
||||
// Passed to LayerProperties::ComputeDifference
|
||||
static void NotifySubDocInvalidation(
|
||||
mozilla::layers::ContainerLayer* aContainer, const nsIntRegion* aRegion);
|
||||
void SetNotifySubDocInvalidationData(
|
||||
mozilla::layers::ContainerLayer* aContainer);
|
||||
static void ClearNotifySubDocInvalidationData(
|
||||
mozilla::layers::ContainerLayer* aContainer);
|
||||
bool IsDOMPaintEventPending();
|
||||
|
||||
/**
|
||||
|
@ -1121,13 +1113,6 @@ class nsPresContext : public nsISupports, public mozilla::SupportsWeakPtr {
|
|||
*/
|
||||
bool MayHavePaintEventListener();
|
||||
|
||||
/**
|
||||
* Checks for MozAfterPaint listeners on the document and
|
||||
* any subdocuments, except for subdocuments that are non-top-level
|
||||
* content documents.
|
||||
*/
|
||||
bool MayHavePaintEventListenerInSubDocument();
|
||||
|
||||
void InvalidatePaintedLayers();
|
||||
|
||||
uint32_t GetNextFrameRateMultiplier() const {
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "nsIFrameInlines.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "BorderConsts.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
|
@ -2523,22 +2522,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(
|
|||
return layerManager.forget();
|
||||
}
|
||||
|
||||
NotifySubDocInvalidationFunc computeInvalidFunc =
|
||||
presContext->MayHavePaintEventListenerInSubDocument()
|
||||
? nsPresContext::NotifySubDocInvalidation
|
||||
: nullptr;
|
||||
|
||||
UniquePtr<LayerProperties> props;
|
||||
|
||||
bool computeInvalidRect =
|
||||
(computeInvalidFunc || (!renderer->IsCompositingCheap() &&
|
||||
renderer->NeedsWidgetInvalidation())) &&
|
||||
widgetTransaction;
|
||||
|
||||
if (computeInvalidRect && layerManager) {
|
||||
props = LayerProperties::CloneFrom(layerManager->GetRoot());
|
||||
}
|
||||
|
||||
if (doBeginTransaction) {
|
||||
if (aCtx) {
|
||||
MOZ_ASSERT(layerManager);
|
||||
|
@ -2587,41 +2570,9 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(
|
|||
TriggerPendingAnimations(*document, renderer->GetAnimationReadyTime());
|
||||
}
|
||||
|
||||
nsIntRegion invalid;
|
||||
if (props) {
|
||||
if (!props->ComputeDifferences(layerManager->GetRoot(), invalid,
|
||||
computeInvalidFunc)) {
|
||||
invalid = nsIntRect::MaxIntRect();
|
||||
}
|
||||
} else if (widgetTransaction && layerManager) {
|
||||
LayerProperties::ClearInvalidations(layerManager->GetRoot());
|
||||
}
|
||||
|
||||
bool shouldInvalidate = renderer->NeedsWidgetInvalidation();
|
||||
|
||||
if (view) {
|
||||
if (props) {
|
||||
if (!invalid.IsEmpty()) {
|
||||
nsIntRect bounds = invalid.GetBounds();
|
||||
nsRect rect(presContext->DevPixelsToAppUnits(bounds.x),
|
||||
presContext->DevPixelsToAppUnits(bounds.y),
|
||||
presContext->DevPixelsToAppUnits(bounds.width),
|
||||
presContext->DevPixelsToAppUnits(bounds.height));
|
||||
// Treat the invalid region from the layer manager as being relative to
|
||||
// the widget, rather than relative to the view. (It's unclear whether
|
||||
// this is the right thing to do, but it matches some aspects of
|
||||
// painting more than the alternative would. Moreover, non-zero view to
|
||||
// widget offsets only occur for fractionally-positioned popups, for bad
|
||||
// reasons. See bug 1688899 for details.)
|
||||
// Make the rectangle relative to the view.
|
||||
rect -= view->ViewToWidgetOffset();
|
||||
if (shouldInvalidate) {
|
||||
view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
|
||||
}
|
||||
presContext->NotifyInvalidation(layerManager->GetLastTransactionId(),
|
||||
bounds);
|
||||
}
|
||||
} else if (shouldInvalidate) {
|
||||
if (shouldInvalidate) {
|
||||
if (!renderer->AsFallback()) {
|
||||
view->GetViewManager()->InvalidateView(view);
|
||||
} else {
|
||||
|
@ -4984,8 +4935,8 @@ bool nsDisplayBoxShadowOuter::CreateWebRenderCommands(
|
|||
|
||||
aBuilder.PushBoxShadow(deviceBoxRect, deviceClipRect, !BackfaceIsHidden(),
|
||||
deviceBoxRect, wr::ToLayoutVector2D(shadowOffset),
|
||||
wr::ToColorF(ToDeviceColor(shadowColor)),
|
||||
blurRadius, spreadRadius, borderRadius,
|
||||
wr::ToColorF(ToDeviceColor(shadowColor)), blurRadius,
|
||||
spreadRadius, borderRadius,
|
||||
wr::BoxShadowClipMode::Outset);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче