Bug 1227231: Use generic tree traversal algorithms for loops over Layer trees. r=botond

Create an Iterator type with classes ForwardIterator and ReverseIterator,
having GetFirstChild/GetNextSibling and GetLastChild/GetPrevSibling
methods, respectively. Specify the iterator type for each call to
ForEachNode. With this, we can support trees with forward and reverse
sibling structures.

Additionally, apply these algorithms to all Layer recursive traversals,
where applicable. Update tests to ensure both directions yield expected
results.

MozReview-Commit-ID: iYpX22XHTa
This commit is contained in:
Kevin Wern
2016-03-10 01:20:40 -08:00
parent e71269370e
commit 4d07bc92ea
12 changed files with 1442 additions and 890 deletions

View File

@@ -24,6 +24,7 @@
#include "nsTArray.h" // for AutoTArray, nsTArray_Impl
#include "mozilla/layers/ImageHost.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "TreeTraversal.h" // for ForEachNode
using namespace mozilla::gfx;
@@ -102,28 +103,28 @@ AddRegion(nsIntRegion& aDest, const nsIntRegion& aSource)
* then report that the entire bounds have changed.
*/
static void
NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
NotifySubdocumentInvalidation(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
{
aLayer->ClearInvalidRect();
ContainerLayer* container = aLayer->AsContainerLayer();
if (aLayer->GetMaskLayer()) {
NotifySubdocumentInvalidationRecursive(aLayer->GetMaskLayer(), aCallback);
}
for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
Layer* maskLayer = aLayer->GetAncestorMaskLayerAt(i);
NotifySubdocumentInvalidationRecursive(maskLayer, aCallback);
}
if (!container) {
return;
}
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
NotifySubdocumentInvalidationRecursive(child, aCallback);
}
aCallback(container, container->GetLocalVisibleRegion().ToUnknownRegion());
ForEachNode<ForwardIterator>(
aLayer,
[aCallback] (Layer* layer)
{
layer->ClearInvalidRect();
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) {
aCallback(container, container->GetLocalVisibleRegion().ToUnknownRegion());
}
});
}
struct LayerPropertiesBase : public LayerProperties
@@ -346,7 +347,7 @@ struct ContainerLayerProperties : public LayerPropertiesBase
AddTransformedRegion(result, child->GetLocalVisibleRegion().ToUnknownRegion(),
GetTransformForInvalidation(child));
if (aCallback) {
NotifySubdocumentInvalidationRecursive(child, aCallback);
NotifySubdocumentInvalidation(child, aCallback);
} else {
ClearInvalidations(child);
}
@@ -588,22 +589,20 @@ LayerProperties::CloneFrom(Layer* aRoot)
/* static */ void
LayerProperties::ClearInvalidations(Layer *aLayer)
{
aLayer->ClearInvalidRect();
if (aLayer->GetMaskLayer()) {
ClearInvalidations(aLayer->GetMaskLayer());
}
for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
ClearInvalidations(aLayer->GetAncestorMaskLayerAt(i));
}
ForEachNode<ForwardIterator>(
aLayer,
[] (Layer* layer)
{
layer->ClearInvalidRect();
if (layer->GetMaskLayer()) {
ClearInvalidations(layer->GetMaskLayer());
}
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
ClearInvalidations(layer->GetAncestorMaskLayerAt(i));
}
ContainerLayer* container = aLayer->AsContainerLayer();
if (!container) {
return;
}
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
ClearInvalidations(child);
}
}
);
}
nsIntRegion
@@ -613,7 +612,7 @@ LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFu
NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
if (mLayer != aRoot) {
if (aCallback) {
NotifySubdocumentInvalidationRecursive(aRoot, aCallback);
NotifySubdocumentInvalidation(aRoot, aCallback);
} else {
ClearInvalidations(aRoot);
}