1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/layers/nine_patch_layer.h" 6 7 #include "cc/debug/overdraw_metrics.h" 8 #include "cc/resources/prioritized_resource_manager.h" 9 #include "cc/resources/resource_provider.h" 10 #include "cc/resources/resource_update_queue.h" 11 #include "cc/scheduler/texture_uploader.h" 12 #include "cc/test/fake_layer_tree_host_client.h" 13 #include "cc/test/fake_output_surface.h" 14 #include "cc/test/geometry_test_utils.h" 15 #include "cc/trees/layer_tree_host.h" 16 #include "cc/trees/occlusion_tracker.h" 17 #include "cc/trees/single_thread_proxy.h" 18 #include "testing/gmock/include/gmock/gmock.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "third_party/skia/include/core/SkBitmap.h" 21 22 using ::testing::Mock; 23 using ::testing::_; 24 using ::testing::AtLeast; 25 using ::testing::AnyNumber; 26 27 namespace cc { 28 namespace { 29 30 class MockLayerTreeHost : public LayerTreeHost { 31 public: 32 explicit MockLayerTreeHost(LayerTreeHostClient* client) 33 : LayerTreeHost(client, LayerTreeSettings()) { 34 Initialize(NULL); 35 } 36 }; 37 38 class NinePatchLayerTest : public testing::Test { 39 public: 40 NinePatchLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {} 41 42 cc::Proxy* Proxy() const { return layer_tree_host_->proxy(); } 43 44 protected: 45 virtual void SetUp() { 46 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_)); 47 } 48 49 virtual void TearDown() { 50 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 51 } 52 53 scoped_ptr<MockLayerTreeHost> layer_tree_host_; 54 FakeLayerTreeHostClient fake_client_; 55 }; 56 57 TEST_F(NinePatchLayerTest, TriggerFullUploadOnceWhenChangingBitmap) { 58 scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create(); 59 ASSERT_TRUE(test_layer.get()); 60 test_layer->SetIsDrawable(true); 61 test_layer->SetBounds(gfx::Size(100, 100)); 62 63 layer_tree_host_->SetRootLayer(test_layer); 64 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 65 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get()); 66 67 layer_tree_host_->InitializeOutputSurfaceIfNeeded(); 68 69 PriorityCalculator calculator; 70 ResourceUpdateQueue queue; 71 OcclusionTracker occlusion_tracker(gfx::Rect(), false); 72 73 // No bitmap set should not trigger any uploads. 74 test_layer->SavePaintProperties(); 75 test_layer->SetTexturePriorities(calculator); 76 test_layer->Update(&queue, &occlusion_tracker); 77 EXPECT_EQ(0u, queue.FullUploadSize()); 78 EXPECT_EQ(0u, queue.PartialUploadSize()); 79 80 // Setting a bitmap set should trigger a single full upload. 81 SkBitmap bitmap; 82 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); 83 bitmap.allocPixels(); 84 test_layer->SetBitmap(bitmap, gfx::Rect(5, 5, 1, 1)); 85 test_layer->SavePaintProperties(); 86 test_layer->SetTexturePriorities(calculator); 87 test_layer->Update(&queue, &occlusion_tracker); 88 EXPECT_EQ(1u, queue.FullUploadSize()); 89 EXPECT_EQ(0u, queue.PartialUploadSize()); 90 ResourceUpdate params = queue.TakeFirstFullUpload(); 91 EXPECT_TRUE(params.texture != NULL); 92 93 // Upload the texture. 94 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( 95 1024 * 1024); 96 layer_tree_host_->contents_texture_manager()->PrioritizeTextures(); 97 98 scoped_ptr<OutputSurface> output_surface; 99 scoped_ptr<ResourceProvider> resource_provider; 100 { 101 DebugScopedSetImplThread impl_thread(Proxy()); 102 DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy()); 103 output_surface = CreateFakeOutputSurface(); 104 resource_provider = ResourceProvider::Create(output_surface.get(), 0); 105 params.texture->AcquireBackingTexture(resource_provider.get()); 106 ASSERT_TRUE(params.texture->have_backing_texture()); 107 } 108 109 // Nothing changed, so no repeated upload. 110 test_layer->SavePaintProperties(); 111 test_layer->SetTexturePriorities(calculator); 112 test_layer->Update(&queue, &occlusion_tracker); 113 EXPECT_EQ(0u, queue.FullUploadSize()); 114 EXPECT_EQ(0u, queue.PartialUploadSize()); 115 { 116 DebugScopedSetImplThread impl_thread(Proxy()); 117 DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy()); 118 layer_tree_host_->contents_texture_manager()->ClearAllMemory( 119 resource_provider.get()); 120 } 121 122 // Reupload after eviction 123 test_layer->SavePaintProperties(); 124 test_layer->SetTexturePriorities(calculator); 125 test_layer->Update(&queue, &occlusion_tracker); 126 EXPECT_EQ(1u, queue.FullUploadSize()); 127 EXPECT_EQ(0u, queue.PartialUploadSize()); 128 129 // PrioritizedResourceManager clearing 130 layer_tree_host_->contents_texture_manager()->UnregisterTexture( 131 params.texture); 132 EXPECT_EQ(NULL, params.texture->resource_manager()); 133 test_layer->SavePaintProperties(); 134 test_layer->SetTexturePriorities(calculator); 135 ResourceUpdateQueue queue2; 136 test_layer->Update(&queue2, &occlusion_tracker); 137 EXPECT_EQ(1u, queue2.FullUploadSize()); 138 EXPECT_EQ(0u, queue2.PartialUploadSize()); 139 params = queue2.TakeFirstFullUpload(); 140 EXPECT_TRUE(params.texture != NULL); 141 EXPECT_EQ(params.texture->resource_manager(), 142 layer_tree_host_->contents_texture_manager()); 143 } 144 145 } // namespace 146 } // namespace cc 147