Bug 969483 - Fix the RepositionChild function and add a test for it. r=BenWa a=sledru
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 18 Feb 2014 16:38:30 -0500
changeset 182914 43e47b7a6eda91c7902d90392ae5b83571f248bf
parent 182913 547654fa02c15b514623d7bc4b5205a5929d3fe0
child 182915 37bd222fb869a0a8a6cf21c6cd15d90fdfc9120c
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa, sledru
bugs969483
milestone29.0a2
Bug 969483 - Fix the RepositionChild function and add a test for it. r=BenWa a=sledru
gfx/layers/Layers.cpp
gfx/tests/gtest/TestLayers.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -802,19 +802,23 @@ ContainerLayer::RepositionChild(Layer* a
   Layer* prev = aChild->GetPrevSibling();
   Layer* next = aChild->GetNextSibling();
   if (prev == aAfter) {
     // aChild is already in the correct position, nothing to do.
     return;
   }
   if (prev) {
     prev->SetNextSibling(next);
+  } else {
+    mFirstChild = next;
   }
   if (next) {
     next->SetPrevSibling(prev);
+  } else {
+    mLastChild = prev;
   }
   if (!aAfter) {
     aChild->SetPrevSibling(nullptr);
     aChild->SetNextSibling(mFirstChild);
     if (mFirstChild) {
       mFirstChild->SetPrevSibling(aChild);
     }
     mFirstChild = aChild;
--- a/gfx/tests/gtest/TestLayers.cpp
+++ b/gfx/tests/gtest/TestLayers.cpp
@@ -185,20 +185,24 @@ already_AddRefed<Layer> CreateLayerTree(
         printf("Layer before '(' must be a container.\n");
         MOZ_CRASH();
       }
     } else if (aLayerTreeDescription[i] == ')') {
       parentContainerLayer = parentContainerLayer->GetParent();
       lastLayer = nullptr;
     } else {
       nsRefPtr<Layer> layer = CreateLayer(aLayerTreeDescription[i], manager.get());
-      layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
-      Matrix4x4 transform;
-      ToMatrix4x4(aTransforms[layerNumber], transform);
-      layer->SetBaseTransform(transform);
+      if (aVisibleRegions) {
+        layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
+      }
+      if (aTransforms) {
+        Matrix4x4 transform;
+        ToMatrix4x4(aTransforms[layerNumber], transform);
+        layer->SetBaseTransform(transform);
+      }
       aLayersOut.AppendElement(layer);
       layerNumber++;
       if (rootLayer && !parentContainerLayer) {
         MOZ_CRASH();
       }
       if (!rootLayer) {
         rootLayer = layer;
       }
@@ -238,8 +242,85 @@ TEST(Layers, LayerTree) {
   // an int.
   Layer* nullLayer = nullptr;
   ASSERT_NE(nullLayer, layers[0]->AsContainerLayer());
   ASSERT_NE(nullLayer, layers[1]->AsContainerLayer());
   ASSERT_NE(nullLayer, layers[2]->AsThebesLayer());
   ASSERT_NE(nullLayer, layers[3]->AsThebesLayer());
 }
 
+static void ValidateTreePointers(Layer* aLayer) {
+  if (aLayer->GetNextSibling()) {
+    ASSERT_EQ(aLayer, aLayer->GetNextSibling()->GetPrevSibling());
+  } else if (aLayer->GetParent()) {
+    ASSERT_EQ(aLayer, aLayer->GetParent()->GetLastChild());
+  }
+  if (aLayer->GetPrevSibling()) {
+    ASSERT_EQ(aLayer, aLayer->GetPrevSibling()->GetNextSibling());
+  } else if (aLayer->GetParent()) {
+    ASSERT_EQ(aLayer, aLayer->GetParent()->GetFirstChild());
+  }
+  if (aLayer->GetFirstChild()) {
+    ASSERT_EQ(aLayer, aLayer->GetFirstChild()->GetParent());
+  }
+  if (aLayer->GetLastChild()) {
+    ASSERT_EQ(aLayer, aLayer->GetLastChild()->GetParent());
+  }
+}
+
+static void ValidateTreePointers(nsTArray<nsRefPtr<Layer> >& aLayers) {
+  for (uint32_t i = 0; i < aLayers.Length(); i++) {
+    ValidateTreePointers(aLayers[i]);
+  }
+}
+
+TEST(Layers, RepositionChild) {
+  const char* layerTreeSyntax = "c(ttt)";
+
+  nsTArray<nsRefPtr<Layer> > layers;
+  nsRefPtr<LayerManager> lm;
+  nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers);
+  ContainerLayer* parent = root->AsContainerLayer();
+  ValidateTreePointers(layers);
+
+  // tree is currently like this (using indexes into layers):
+  //   0
+  // 1 2 3
+  ASSERT_EQ(layers[2], layers[1]->GetNextSibling());
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
+
+  parent->RepositionChild(layers[1], layers[3]);
+  ValidateTreePointers(layers);
+
+  // now the tree is like this:
+  //   0
+  // 2 3 1
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], layers[2]);
+  ValidateTreePointers(layers);
+
+  // no change
+  ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], layers[1]);
+  ValidateTreePointers(layers);
+
+  //   0
+  // 2 1 3
+  ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
+  ASSERT_EQ(layers[3], layers[1]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
+
+  parent->RepositionChild(layers[3], nullptr);
+  ValidateTreePointers(layers);
+
+  //   0
+  // 3 2 1
+  ASSERT_EQ(layers[2], layers[3]->GetNextSibling());
+  ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
+  ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
+}