OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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 "base/callback.h" |
| 6 #include "base/command_line.h" |
| 7 #include "base/path_service.h" |
| 8 #include "content/public/browser/gpu_data_manager.h" |
| 9 #include "content/public/browser/gpu_data_manager_observer.h" |
| 10 #include "content/public/browser/web_contents.h" |
| 11 #include "content/public/common/content_paths.h" |
| 12 #include "content/public/common/content_switches.h" |
| 13 #include "content/public/test/browser_test_utils.h" |
| 14 #include "content/public/test/test_utils.h" |
| 15 #include "content/shell/shell.h" |
| 16 #include "content/test/content_browser_test.h" |
| 17 #include "content/test/content_browser_test_utils.h" |
| 18 #include "gpu/command_buffer/service/gpu_switches.h" |
| 19 #include "net/base/net_util.h" |
| 20 |
| 21 namespace { |
| 22 |
| 23 // Run the tests with a memory limit of 256MB, and give |
| 24 // and extra 24MB of wiggle-room for over-allocation. |
| 25 const char* kMemoryLimitSwitch = "256"; |
| 26 const size_t kMemoryLimit = 256; |
| 27 const size_t kSingleTabLimit = 128; |
| 28 const size_t kSingleTabMinimum = 64; |
| 29 const size_t kWiggleRoom = 24; |
| 30 |
| 31 // Observer to report GPU memory usage when requested. |
| 32 class GpuMemoryBytesAllocatedObserver |
| 33 : public content::GpuDataManagerObserver { |
| 34 public: |
| 35 GpuMemoryBytesAllocatedObserver() |
| 36 : bytes_allocated_(0) { |
| 37 } |
| 38 |
| 39 virtual ~GpuMemoryBytesAllocatedObserver() { |
| 40 } |
| 41 |
| 42 virtual void OnGpuInfoUpdate() OVERRIDE {} |
| 43 |
| 44 virtual void OnVideoMemoryUsageStatsUpdate( |
| 45 const content::GPUVideoMemoryUsageStats& video_memory_usage_stats) |
| 46 OVERRIDE { |
| 47 bytes_allocated_ = video_memory_usage_stats.bytes_allocated; |
| 48 message_loop_runner_->Quit(); |
| 49 } |
| 50 |
| 51 size_t GetBytesAllocated() { |
| 52 message_loop_runner_ = new content::MessageLoopRunner; |
| 53 content::GpuDataManager::GetInstance()->AddObserver(this); |
| 54 content::GpuDataManager::GetInstance()-> |
| 55 RequestVideoMemoryUsageStatsUpdate(); |
| 56 message_loop_runner_->Run(); |
| 57 content::GpuDataManager::GetInstance()->RemoveObserver(this); |
| 58 message_loop_runner_ = NULL; |
| 59 return bytes_allocated_; |
| 60 } |
| 61 |
| 62 private: |
| 63 size_t bytes_allocated_; |
| 64 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| 65 }; |
| 66 |
| 67 class GpuMemoryTest : public content::ContentBrowserTest { |
| 68 public: |
| 69 GpuMemoryTest() |
| 70 : allow_tests_to_run_(false), |
| 71 has_used_first_shell_(false) { |
| 72 } |
| 73 virtual ~GpuMemoryTest() { |
| 74 } |
| 75 |
| 76 virtual void SetUpInProcessBrowserTestFixture() { |
| 77 FilePath test_dir; |
| 78 ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &test_dir)); |
| 79 gpu_test_dir_ = test_dir.AppendASCII("gpu"); |
| 80 } |
| 81 |
| 82 virtual void SetUpCommandLine(CommandLine* command_line) { |
| 83 command_line->AppendSwitch(switches::kEnableLogging); |
| 84 command_line->AppendSwitch(switches::kForceCompositingMode); |
| 85 command_line->AppendSwitchASCII(switches::kForceGpuMemAvailableMb, |
| 86 kMemoryLimitSwitch); |
| 87 // Only run this on GPU bots for now. These tests should work with |
| 88 // any GPU process, but may be slow. |
| 89 if (command_line->HasSwitch(switches::kUseGpuInTests)) { |
| 90 allow_tests_to_run_ = true; |
| 91 } |
| 92 // Don't enable these tests on Android just yet (they use lots of memory and |
| 93 // may not be stable). |
| 94 #if defined(OS_ANDROID) |
| 95 allow_tests_to_run_ = false; |
| 96 #endif |
| 97 } |
| 98 |
| 99 enum PageType { |
| 100 PAGE_CSS3D, |
| 101 PAGE_WEBGL, |
| 102 }; |
| 103 |
| 104 // Load a page and consume a specified amount of GPU memory. |
| 105 void LoadPage(content::Shell* shell_to_load, |
| 106 PageType page_type, |
| 107 size_t mb_to_use) { |
| 108 FilePath url; |
| 109 switch (page_type) { |
| 110 case PAGE_CSS3D: |
| 111 url = gpu_test_dir_.AppendASCII("mem_css3d.html"); |
| 112 break; |
| 113 case PAGE_WEBGL: |
| 114 url = gpu_test_dir_.AppendASCII("mem_webgl.html"); |
| 115 break; |
| 116 } |
| 117 |
| 118 content::NavigateToURL(shell_to_load, net::FilePathToFileURL(url)); |
| 119 std::ostringstream js_call; |
| 120 js_call << "useGpuMemory("; |
| 121 js_call << mb_to_use; |
| 122 js_call << ");"; |
| 123 content::DOMMessageQueue message_queue; |
| 124 std::string message; |
| 125 ASSERT_TRUE(content::ExecuteScript( |
| 126 shell_to_load->web_contents(), js_call.str())); |
| 127 ASSERT_TRUE(message_queue.WaitForMessage(&message)); |
| 128 EXPECT_EQ("\"DONE_USE_GPU_MEMORY\"", message); |
| 129 } |
| 130 |
| 131 // Create a new tab. |
| 132 content::Shell* CreateNewTab() { |
| 133 // The ContentBrowserTest will create one shell by default, use that one |
| 134 // first so that we don't confuse the memory manager into thinking there |
| 135 // are more windows than there are. |
| 136 content::Shell* new_shell = |
| 137 has_used_first_shell_ ? CreateBrowser() : shell(); |
| 138 has_used_first_shell_ = true; |
| 139 visible_shells_.insert(new_shell); |
| 140 return new_shell; |
| 141 } |
| 142 |
| 143 void SetTabBackgrounded(content::Shell* shell_to_background) { |
| 144 ASSERT_TRUE( |
| 145 visible_shells_.find(shell_to_background) != visible_shells_.end()); |
| 146 visible_shells_.erase(shell_to_background); |
| 147 shell_to_background->web_contents()->WasHidden(); |
| 148 } |
| 149 |
| 150 size_t GetMemoryUsageMbytes() { |
| 151 // TODO: This should wait until all effects of memory management complete. |
| 152 // We will need to wait until all |
| 153 // 1. pending commits from the main thread to the impl thread in the |
| 154 // compositor complete (for visible compositors). |
| 155 // 2. allocations that the renderer's impl thread will make due to the |
| 156 // compositor and WebGL are completed. |
| 157 // 3. pending GpuMemoryManager::Manage() calls to manage are made. |
| 158 // 4. renderers' OnMemoryAllocationChanged callbacks in response to |
| 159 // manager are made. |
| 160 // Each step in this sequence can cause trigger the next (as a 1-2-3-4-1 |
| 161 // cycle), so we will need to pump this cycle until it stabilizes. |
| 162 GpuMemoryBytesAllocatedObserver observer; |
| 163 observer.GetBytesAllocated(); |
| 164 return observer.GetBytesAllocated() / 1048576; |
| 165 } |
| 166 |
| 167 bool AllowTestsToRun() const { |
| 168 return allow_tests_to_run_; |
| 169 } |
| 170 |
| 171 private: |
| 172 bool allow_tests_to_run_; |
| 173 std::set<content::Shell*> visible_shells_; |
| 174 bool has_used_first_shell_; |
| 175 FilePath gpu_test_dir_; |
| 176 }; |
| 177 |
| 178 } // namespace |
OLD | NEW |