summaryrefslogtreecommitdiffstats
path: root/content/browser/gpu/gpu_memory_test.cc
diff options
context:
space:
mode:
authorccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-11 16:02:46 +0000
committerccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-11 16:02:46 +0000
commit4d66a016257c355b7c084f6e554031660bf131e3 (patch)
tree98d18729e139c4ceecc89d3f542eb1284ea9b126 /content/browser/gpu/gpu_memory_test.cc
parent3f8a01e84bdcac7f8cb1d397681cf3563aa6ea77 (diff)
downloadchromium_src-4d66a016257c355b7c084f6e554031660bf131e3.zip
chromium_src-4d66a016257c355b7c084f6e554031660bf131e3.tar.gz
chromium_src-4d66a016257c355b7c084f6e554031660bf131e3.tar.bz2
Enable a simple GPU memory manager browser test.
Add a mechanism for waiting for RequestAnimationFrames from each visible tab. Outline the structure for flushing out pending GPU work. Add gpu as a explicit dependency of content_browsertests so that we can specify the kForceGpuMemAvailableMb in component builds. BUG=135525 Review URL: https://chromiumcodereview.appspot.com/11826013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176358 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/gpu/gpu_memory_test.cc')
-rw-r--r--content/browser/gpu/gpu_memory_test.cc125
1 files changed, 100 insertions, 25 deletions
diff --git a/content/browser/gpu/gpu_memory_test.cc b/content/browser/gpu/gpu_memory_test.cc
index 75ea141..9312651 100644
--- a/content/browser/gpu/gpu_memory_test.cc
+++ b/content/browser/gpu/gpu_memory_test.cc
@@ -20,6 +20,13 @@
namespace {
+// Run the tests with a memory limit of 256MB, and give
+// and extra 4MB of wiggle-room for over-allocation.
+const char* kMemoryLimitMBSwitch = "256";
+const size_t kMemoryLimitMB = 256;
+const size_t kSingleTabLimitMB = 128;
+const size_t kWiggleRoomMB = 4;
+
// Observer to report GPU memory usage when requested.
class GpuMemoryBytesAllocatedObserver
: public content::GpuDataManagerObserver {
@@ -74,9 +81,8 @@ class GpuMemoryTest : public content::ContentBrowserTest {
virtual void SetUpCommandLine(CommandLine* command_line) {
command_line->AppendSwitch(switches::kEnableLogging);
command_line->AppendSwitch(switches::kForceCompositingMode);
- // TODO: Use switches::kForceGpuMemAvailableMb to fix the memory limit
- // (this is failing some bots (probably because of differing meanings of
- // GPU_EXPORT)
+ command_line->AppendSwitchASCII(switches::kForceGpuMemAvailableMb,
+ kMemoryLimitMBSwitch);
// Only run this on GPU bots for now. These tests should work with
// any GPU process, but may be slow.
if (command_line->HasSwitch(switches::kUseGpuInTests)) {
@@ -95,7 +101,7 @@ class GpuMemoryTest : public content::ContentBrowserTest {
};
// Load a page and consume a specified amount of GPU memory.
- void LoadPage(content::Shell* shell_to_load,
+ void LoadPage(content::Shell* tab_to_load,
PageType page_type,
size_t mb_to_use) {
FilePath url;
@@ -108,17 +114,19 @@ class GpuMemoryTest : public content::ContentBrowserTest {
break;
}
- content::NavigateToURL(shell_to_load, net::FilePathToFileURL(url));
+ content::NavigateToURL(tab_to_load, net::FilePathToFileURL(url));
std::ostringstream js_call;
js_call << "useGpuMemory(";
js_call << mb_to_use;
js_call << ");";
- content::DOMMessageQueue message_queue;
std::string message;
- ASSERT_TRUE(content::ExecuteScript(
- shell_to_load->web_contents(), js_call.str()));
- ASSERT_TRUE(message_queue.WaitForMessage(&message));
- EXPECT_EQ("\"DONE_USE_GPU_MEMORY\"", message);
+ ASSERT_TRUE(
+ content::ExecuteScriptInFrameAndExtractString(
+ tab_to_load->web_contents(),
+ "",
+ js_call.str(),
+ &message));
+ EXPECT_EQ("DONE_USE_GPU_MEMORY", message);
}
// Create a new tab.
@@ -126,22 +134,48 @@ class GpuMemoryTest : public content::ContentBrowserTest {
// The ContentBrowserTest will create one shell by default, use that one
// first so that we don't confuse the memory manager into thinking there
// are more windows than there are.
- content::Shell* new_shell =
+ content::Shell* new_tab =
has_used_first_shell_ ? CreateBrowser() : shell();
has_used_first_shell_ = true;
- visible_shells_.insert(new_shell);
- return new_shell;
+ tabs_.insert(new_tab);
+ visible_tabs_.insert(new_tab);
+ return new_tab;
}
- void SetTabBackgrounded(content::Shell* shell_to_background) {
+ void SetTabBackgrounded(content::Shell* tab_to_background) {
ASSERT_TRUE(
- visible_shells_.find(shell_to_background) != visible_shells_.end());
- visible_shells_.erase(shell_to_background);
- shell_to_background->web_contents()->WasHidden();
+ visible_tabs_.find(tab_to_background) != visible_tabs_.end());
+ visible_tabs_.erase(tab_to_background);
+ tab_to_background->web_contents()->WasHidden();
}
- size_t GetMemoryUsageMbytes() {
- // TODO: This should wait until all effects of memory management complete.
+ bool MemoryUsageInRange(size_t low, size_t high) {
+ FinishGpuMemoryChanges();
+ size_t memory_usage_bytes = GetMemoryUsageMbytes();
+
+ // If it's not immediately the case that low <= usage <= high, then
+ // allow
+ // Because we haven't implemented the full delay in FinishGpuMemoryChanges,
+ // keep re-reading the GPU memory usage for 2 seconds before declaring
+ // failure.
+ base::Time start_time = base::Time::Now();
+ while (low > memory_usage_bytes || memory_usage_bytes > high) {
+ memory_usage_bytes = GetMemoryUsageMbytes();
+ base::TimeDelta delta = base::Time::Now() - start_time;
+ if (delta.InMilliseconds() >= 2000)
+ break;
+ }
+
+ return (low <= memory_usage_bytes && memory_usage_bytes <= high);
+ }
+
+ bool AllowTestsToRun() const {
+ return allow_tests_to_run_;
+ }
+
+ private:
+ void FinishGpuMemoryChanges() {
+ // This should wait until all effects of memory management complete.
// We will need to wait until all
// 1. pending commits from the main thread to the impl thread in the
// compositor complete (for visible compositors).
@@ -152,20 +186,61 @@ class GpuMemoryTest : public content::ContentBrowserTest {
// manager are made.
// Each step in this sequence can cause trigger the next (as a 1-2-3-4-1
// cycle), so we will need to pump this cycle until it stabilizes.
+
+ // Pump the cycle 8 times (in principle it could take an infinite number
+ // of iterations to settle).
+ for (size_t pump_it = 0; pump_it < 8; ++pump_it) {
+ // Wait for a RequestAnimationFrame to complete from all visible tabs
+ // for stage 1 of the cycle.
+ for (std::set<content::Shell*>::iterator it = visible_tabs_.begin();
+ it != visible_tabs_.end();
+ ++it) {
+ std::string js_call(
+ "window.webkitRequestAnimationFrame(function() {"
+ " domAutomationController.setAutomationId(1);"
+ " domAutomationController.send(\"DONE_RAF\");"
+ "})");
+ std::string message;
+ ASSERT_TRUE(
+ content::ExecuteScriptInFrameAndExtractString(
+ (*it)->web_contents(),
+ "",
+ js_call,
+ &message));
+ EXPECT_EQ("DONE_RAF", message);
+ }
+ // TODO(ccameron): send an IPC from Browser -> Renderer (delay it until
+ // painting finishes) -> GPU process (delay it until any pending manages
+ // happen) -> All Renderers -> Browser to flush parts 2, 3, and 4.
+ }
+ }
+
+ size_t GetMemoryUsageMbytes() {
GpuMemoryBytesAllocatedObserver observer;
observer.GetBytesAllocated();
return observer.GetBytesAllocated() / 1048576;
}
- bool AllowTestsToRun() const {
- return allow_tests_to_run_;
- }
-
- private:
bool allow_tests_to_run_;
- std::set<content::Shell*> visible_shells_;
+ std::set<content::Shell*> tabs_;
+ std::set<content::Shell*> visible_tabs_;
bool has_used_first_shell_;
FilePath gpu_test_dir_;
};
+// When trying to load something that doesn't fit into our total GPU memory
+// limit, we shouldn't exceed that limit.
+IN_PROC_BROWSER_TEST_F(GpuMemoryTest, SingleWindowDoesNotExceedLimit) {
+ if (!AllowTestsToRun())
+ return;
+
+ content::Shell* tab = CreateNewTab();
+ LoadPage(tab, PAGE_CSS3D, kMemoryLimitMB);
+ // Make sure that the CSS3D page maxes out a single tab's budget (otherwise
+ // the test doesn't test anything) but still stays under the limit.
+ EXPECT_TRUE(MemoryUsageInRange(
+ kSingleTabLimitMB - kWiggleRoomMB,
+ kMemoryLimitMB + kWiggleRoomMB));
+}
+
} // namespace