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 |