gfx/tests/gtest/TestLayers.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* vim:set ts=2 sw=2 sts=2 et: */
     2 /* Any copyright is dedicated to the Public Domain.
     3  * http://creativecommons.org/publicdomain/zero/1.0/
     4  */
     6 #include "TestLayers.h"
     7 #include "gtest/gtest.h"
     8 #include "gmock/gmock.h"
    10 using namespace mozilla;
    11 using namespace mozilla::gfx;
    12 using namespace mozilla::layers;
    14 class TestLayerManager: public LayerManager {
    15 public:
    16   TestLayerManager()
    17     : LayerManager()
    18   {}
    20   virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) { return false; }
    21   virtual already_AddRefed<ContainerLayer> CreateContainerLayer() { return nullptr; }
    22   virtual void GetBackendName(nsAString& aName) {}
    23   virtual LayersBackend GetBackendType() { return LayersBackend::LAYERS_BASIC; }
    24   virtual void BeginTransaction() {}
    25   virtual already_AddRefed<ImageLayer> CreateImageLayer() { return nullptr; }
    26   virtual void SetRoot(Layer* aLayer) {}
    27   virtual already_AddRefed<ColorLayer> CreateColorLayer() { return nullptr; }
    28   virtual void BeginTransactionWithTarget(gfxContext* aTarget) {}
    29   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() { return nullptr; }
    30   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
    31                               void* aCallbackData,
    32                               EndTransactionFlags aFlags = END_DEFAULT) {}
    33   virtual int32_t GetMaxTextureSize() const { return 0; }
    34   virtual already_AddRefed<ThebesLayer> CreateThebesLayer() { return nullptr; }
    35 };
    37 class TestContainerLayer: public ContainerLayer {
    38 public:
    39   TestContainerLayer(LayerManager* aManager)
    40     : ContainerLayer(aManager, nullptr)
    41   {}
    43   virtual const char* Name() const {
    44     return "TestContainerLayer";
    45   }
    47   virtual LayerType GetType() const {
    48     return TYPE_CONTAINER;
    49   }
    51   virtual void ComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface) {
    52     DefaultComputeEffectiveTransforms(aTransformToSurface);
    53   }
    54 };
    56 class TestThebesLayer: public ThebesLayer {
    57 public:
    58   TestThebesLayer(LayerManager* aManager)
    59     : ThebesLayer(aManager, nullptr)
    60   {}
    62   virtual const char* Name() const {
    63     return "TestThebesLayer";
    64   }
    66   virtual LayerType GetType() const {
    67     return TYPE_THEBES;
    68   }
    70   virtual void InvalidateRegion(const nsIntRegion& aRegion) {
    71     MOZ_CRASH();
    72   }
    73 };
    75 class TestUserData: public LayerUserData {
    76 public:
    77   MOCK_METHOD0(Die, void());
    78   virtual ~TestUserData() { Die(); }
    79 };
    82 TEST(Layers, LayerConstructor) {
    83   TestContainerLayer layer(nullptr);
    84 }
    86 TEST(Layers, Defaults) {
    87   TestContainerLayer layer(nullptr);
    88   ASSERT_EQ(1.0, layer.GetOpacity());
    89   ASSERT_EQ(1.0f, layer.GetPostXScale());
    90   ASSERT_EQ(1.0f, layer.GetPostYScale());
    92   ASSERT_EQ(nullptr, layer.GetNextSibling());
    93   ASSERT_EQ(nullptr, layer.GetPrevSibling());
    94   ASSERT_EQ(nullptr, layer.GetFirstChild());
    95   ASSERT_EQ(nullptr, layer.GetLastChild());
    96 }
    98 TEST(Layers, Transform) {
    99   TestContainerLayer layer(nullptr);
   101   Matrix4x4 identity;
   102   ASSERT_EQ(true, identity.IsIdentity());
   104   ASSERT_EQ(identity, layer.GetTransform());
   105 }
   107 TEST(Layers, Type) {
   108   TestContainerLayer layer(nullptr);
   109   ASSERT_EQ(nullptr, layer.AsThebesLayer());
   110   ASSERT_EQ(nullptr, layer.AsRefLayer());
   111   ASSERT_EQ(nullptr, layer.AsColorLayer());
   112 }
   114 TEST(Layers, UserData) {
   115   TestContainerLayer* layerPtr = new TestContainerLayer(nullptr);
   116   TestContainerLayer& layer = *layerPtr;
   118   void* key1 = (void*)1;
   119   void* key2 = (void*)2;
   120   void* key3 = (void*)3;
   122   TestUserData* data1 = new TestUserData;
   123   TestUserData* data2 = new TestUserData;
   124   TestUserData* data3 = new TestUserData;
   126   ASSERT_EQ(nullptr, layer.GetUserData(key1));
   127   ASSERT_EQ(nullptr, layer.GetUserData(key2));
   128   ASSERT_EQ(nullptr, layer.GetUserData(key3));
   130   layer.SetUserData(key1, data1);
   131   layer.SetUserData(key2, data2);
   132   layer.SetUserData(key3, data3);
   134   // Also checking that the user data is returned but not free'd
   135   ASSERT_EQ(data1, layer.RemoveUserData(key1).forget());
   136   ASSERT_EQ(data2, layer.RemoveUserData(key2).forget());
   137   ASSERT_EQ(data3, layer.RemoveUserData(key3).forget());
   139   layer.SetUserData(key1, data1);
   140   layer.SetUserData(key2, data2);
   141   layer.SetUserData(key3, data3);
   143   // Layer has ownership of data1-3, check that they are destroyed
   144   EXPECT_CALL(*data1, Die());
   145   EXPECT_CALL(*data2, Die());
   146   EXPECT_CALL(*data3, Die());
   147   delete layerPtr;
   149 }
   151 static
   152 already_AddRefed<Layer> CreateLayer(char aLayerType, LayerManager* aManager) {
   153   nsRefPtr<Layer> layer = nullptr;
   154   if (aLayerType == 'c') {
   155     layer = new TestContainerLayer(aManager);
   156   } else if (aLayerType == 't') {
   157     layer = new TestThebesLayer(aManager);
   158   }
   159   return layer.forget();
   160 }
   162 already_AddRefed<Layer> CreateLayerTree(
   163     const char* aLayerTreeDescription,
   164     nsIntRegion* aVisibleRegions,
   165     const gfx3DMatrix* aTransforms,
   166     nsRefPtr<LayerManager>& manager,
   167     nsTArray<nsRefPtr<Layer> >& aLayersOut) {
   169   aLayersOut.Clear();
   171   manager = new TestLayerManager();
   173   nsRefPtr<Layer> rootLayer = nullptr;
   174   nsRefPtr<ContainerLayer> parentContainerLayer = nullptr;
   175   nsRefPtr<Layer> lastLayer = nullptr;
   176   int layerNumber = 0;
   177   for (size_t i = 0; i < strlen(aLayerTreeDescription); i++) {
   178     if (aLayerTreeDescription[i] == '(') {
   179       if (!lastLayer) {
   180         printf("Syntax error, likely '(' character isn't preceded by a container.\n");
   181         MOZ_CRASH();
   182       }
   183       parentContainerLayer = lastLayer->AsContainerLayer();
   184       if (!parentContainerLayer) {
   185         printf("Layer before '(' must be a container.\n");
   186         MOZ_CRASH();
   187       }
   188     } else if (aLayerTreeDescription[i] == ')') {
   189       parentContainerLayer = parentContainerLayer->GetParent();
   190       lastLayer = nullptr;
   191     } else {
   192       nsRefPtr<Layer> layer = CreateLayer(aLayerTreeDescription[i], manager.get());
   193       if (aVisibleRegions) {
   194         layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
   195       }
   196       if (aTransforms) {
   197         Matrix4x4 transform;
   198         ToMatrix4x4(aTransforms[layerNumber], transform);
   199         layer->SetBaseTransform(transform);
   200       }
   201       aLayersOut.AppendElement(layer);
   202       layerNumber++;
   203       if (rootLayer && !parentContainerLayer) {
   204         MOZ_CRASH();
   205       }
   206       if (!rootLayer) {
   207         rootLayer = layer;
   208       }
   209       if (parentContainerLayer) {
   210         parentContainerLayer->InsertAfter(layer, parentContainerLayer->GetLastChild());
   211         layer->SetParent(parentContainerLayer);
   212       }
   213       lastLayer = layer;
   214     }
   215   }
   216   if (rootLayer) {
   217     rootLayer->ComputeEffectiveTransforms(Matrix4x4());
   218   }
   219   return rootLayer.forget();
   220 }
   222 TEST(Layers, LayerTree) {
   223   const char* layerTreeSyntax = "c(c(tt))";
   224   nsIntRegion layerVisibleRegion[] = {
   225     nsIntRegion(nsIntRect(0,0,100,100)),
   226     nsIntRegion(nsIntRect(0,0,100,100)),
   227     nsIntRegion(nsIntRect(0,0,100,100)),
   228     nsIntRegion(nsIntRect(10,10,20,20)),
   229   };
   230   gfx3DMatrix transforms[] = {
   231     gfx3DMatrix(),
   232     gfx3DMatrix(),
   233     gfx3DMatrix(),
   234     gfx3DMatrix(),
   235   };
   236   nsTArray<nsRefPtr<Layer> > layers;
   238   nsRefPtr<LayerManager> lm;
   239   nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
   241   // B2G g++ doesn't like ASSERT_NE with nullptr directly. It thinks it's
   242   // an int.
   243   Layer* nullLayer = nullptr;
   244   ASSERT_NE(nullLayer, layers[0]->AsContainerLayer());
   245   ASSERT_NE(nullLayer, layers[1]->AsContainerLayer());
   246   ASSERT_NE(nullLayer, layers[2]->AsThebesLayer());
   247   ASSERT_NE(nullLayer, layers[3]->AsThebesLayer());
   248 }
   250 static void ValidateTreePointers(Layer* aLayer) {
   251   if (aLayer->GetNextSibling()) {
   252     ASSERT_EQ(aLayer, aLayer->GetNextSibling()->GetPrevSibling());
   253   } else if (aLayer->GetParent()) {
   254     ASSERT_EQ(aLayer, aLayer->GetParent()->GetLastChild());
   255   }
   256   if (aLayer->GetPrevSibling()) {
   257     ASSERT_EQ(aLayer, aLayer->GetPrevSibling()->GetNextSibling());
   258   } else if (aLayer->GetParent()) {
   259     ASSERT_EQ(aLayer, aLayer->GetParent()->GetFirstChild());
   260   }
   261   if (aLayer->GetFirstChild()) {
   262     ASSERT_EQ(aLayer, aLayer->GetFirstChild()->GetParent());
   263   }
   264   if (aLayer->GetLastChild()) {
   265     ASSERT_EQ(aLayer, aLayer->GetLastChild()->GetParent());
   266   }
   267 }
   269 static void ValidateTreePointers(nsTArray<nsRefPtr<Layer> >& aLayers) {
   270   for (uint32_t i = 0; i < aLayers.Length(); i++) {
   271     ValidateTreePointers(aLayers[i]);
   272   }
   273 }
   275 TEST(Layers, RepositionChild) {
   276   const char* layerTreeSyntax = "c(ttt)";
   278   nsTArray<nsRefPtr<Layer> > layers;
   279   nsRefPtr<LayerManager> lm;
   280   nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers);
   281   ContainerLayer* parent = root->AsContainerLayer();
   282   ValidateTreePointers(layers);
   284   // tree is currently like this (using indexes into layers):
   285   //   0
   286   // 1 2 3
   287   ASSERT_EQ(layers[2], layers[1]->GetNextSibling());
   288   ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
   289   ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
   291   parent->RepositionChild(layers[1], layers[3]);
   292   ValidateTreePointers(layers);
   294   // now the tree is like this:
   295   //   0
   296   // 2 3 1
   297   ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
   298   ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
   299   ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
   301   parent->RepositionChild(layers[3], layers[2]);
   302   ValidateTreePointers(layers);
   304   // no change
   305   ASSERT_EQ(layers[3], layers[2]->GetNextSibling());
   306   ASSERT_EQ(layers[1], layers[3]->GetNextSibling());
   307   ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
   309   parent->RepositionChild(layers[3], layers[1]);
   310   ValidateTreePointers(layers);
   312   //   0
   313   // 2 1 3
   314   ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
   315   ASSERT_EQ(layers[3], layers[1]->GetNextSibling());
   316   ASSERT_EQ(nullptr, layers[3]->GetNextSibling());
   318   parent->RepositionChild(layers[3], nullptr);
   319   ValidateTreePointers(layers);
   321   //   0
   322   // 3 2 1
   323   ASSERT_EQ(layers[2], layers[3]->GetNextSibling());
   324   ASSERT_EQ(layers[1], layers[2]->GetNextSibling());
   325   ASSERT_EQ(nullptr, layers[1]->GetNextSibling());
   326 }

mercurial