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.

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

mercurial