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.
5 #include "base/command_line.h"
6 #include "base/file_util.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/path_service.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/test/trace_event_analyzer.h"
11 #include "base/version.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/test/base/in_process_browser_test.h"
17 #include "chrome/test/base/tracing.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/gpu_data_manager.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "gpu/config/gpu_feature_type.h"
23 #include "gpu/config/gpu_info.h"
24 #include "gpu/config/gpu_test_config.h"
25 #include "net/base/net_util.h"
26 #include "ui/gl/gl_implementation.h"
28 #if defined(OS_MACOSX)
29 #include "ui/gl/io_surface_support_mac.h"
33 #include "base/win/windows_version.h"
36 using content::GpuDataManager;
37 using gpu::GpuFeatureType;
38 using trace_analyzer::Query;
39 using trace_analyzer::TraceAnalyzer;
40 using trace_analyzer::TraceEventVector;
44 const char kSwapBuffersEvent[] = "SwapBuffers";
45 const char kAcceleratedCanvasCreationEvent[] = "Canvas2DLayerBridgeCreation";
46 const char kWebGLCreationEvent[] = "DrawingBufferCreation";
48 class GpuFeatureTest : public InProcessBrowserTest {
50 GpuFeatureTest() : category_patterns_("test_gpu") {}
52 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
53 base::FilePath test_dir;
54 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
55 gpu_test_dir_ = test_dir.AppendASCII("gpu");
58 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
59 command_line->AppendSwitch(switches::kDisablePopupBlocking);
60 command_line->AppendSwitchASCII(switches::kWindowSize, "400,300");
63 void SetupBlacklist(const std::string& json_blacklist) {
64 gpu::GPUInfo gpu_info;
65 GpuDataManager::GetInstance()->InitializeForTesting(
66 json_blacklist, gpu_info);
69 // If expected_reply is NULL, we don't check the reply content.
70 void RunTest(const base::FilePath& url,
71 const char* expected_reply,
73 #if defined(OS_LINUX) && !defined(NDEBUG)
74 // Bypass tests on GPU Linux Debug bots.
75 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
79 base::FilePath test_path;
80 test_path = gpu_test_dir_.Append(url);
81 ASSERT_TRUE(base::PathExists(test_path))
82 << "Missing test file: " << test_path.value();
84 content::DOMMessageQueue message_queue;
86 ui_test_utils::NavigateToURLWithDisposition(
87 browser(), net::FilePathToFileURL(test_path),
88 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_NONE);
90 ui_test_utils::NavigateToURL(
91 browser(), net::FilePathToFileURL(test_path));
95 // Wait for message indicating the test has finished running.
96 ASSERT_TRUE(message_queue.WaitForMessage(&result));
98 EXPECT_STREQ(expected_reply, result.c_str());
101 // Open the URL and check the trace stream for the given event.
102 void RunEventTest(const base::FilePath& url,
103 const char* event_name = NULL,
104 bool event_expected = false) {
105 #if defined(OS_LINUX) && !defined(NDEBUG)
106 // Bypass tests on GPU Linux Debug bots.
107 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
110 #if defined(OS_MACOSX)
111 // Bypass tests on Mac OSX 10.5 bots (IOSurfaceSupport is now required).
112 if (!IOSurfaceSupport::Initialize())
116 ASSERT_TRUE(tracing::BeginTracing(category_patterns_));
118 // Have to use a new tab for the blacklist to work.
119 RunTest(url, NULL, true);
121 ASSERT_TRUE(tracing::EndTracing(&trace_events_json_));
123 analyzer_.reset(TraceAnalyzer::Create(trace_events_json_));
124 analyzer_->AssociateBeginEndEvents();
125 TraceEventVector events;
131 analyzer_->FindEvents(Query::EventNameIs(event_name), &events);
134 EXPECT_GT(event_count, 0U);
136 EXPECT_EQ(event_count, 0U);
139 // Trigger a resize of the chrome window, and use tracing to wait for the
140 // given |wait_event|.
141 bool ResizeAndWait(const gfx::Rect& new_bounds,
142 const char* category_patterns,
143 const char* wait_category,
144 const char* wait_event) {
145 if (!tracing::BeginTracingWithWatch(category_patterns, wait_category,
148 browser()->window()->SetBounds(new_bounds);
149 if (!tracing::WaitForWatchEvent(base::TimeDelta()))
151 if (!tracing::EndTracing(&trace_events_json_))
153 analyzer_.reset(TraceAnalyzer::Create(trace_events_json_));
154 analyzer_->AssociateBeginEndEvents();
159 base::FilePath gpu_test_dir_;
160 scoped_ptr<TraceAnalyzer> analyzer_;
161 std::string category_patterns_;
162 std::string trace_events_json_;
165 class GpuFeaturePixelTest : public GpuFeatureTest {
167 virtual void SetUp() OVERRIDE {
169 GpuFeatureTest::SetUp();
173 #if defined(OS_WIN) || defined(ADDRESS_SANITIZER) || defined(USE_AURA) || \
175 // This test is flaky on Windows. http://crbug.com/177113
176 // Also fails under AddressSanitizer. http://crbug.com/185178
177 // It fundamentally doesn't test the right thing on Aura.
178 // http://crbug.com/280675
179 // This does not work with software compositing on Mac. http://crbug.com/286038
180 #define MAYBE_AcceleratedCompositingAllowed DISABLED_AcceleratedCompositingAllowed
182 #define MAYBE_AcceleratedCompositingAllowed AcceleratedCompositingAllowed
185 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MAYBE_AcceleratedCompositingAllowed) {
186 EXPECT_FALSE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
187 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING));
189 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
190 RunEventTest(url, kSwapBuffersEvent, true);
193 class AcceleratedCompositingBlockedTest : public GpuFeatureTest {
195 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
196 GpuFeatureTest::SetUpInProcessBrowserTestFixture();
197 const std::string json_blacklist =
199 " \"name\": \"gpu blacklist\",\n"
200 " \"version\": \"1.0\",\n"
205 " \"accelerated_compositing\"\n"
210 SetupBlacklist(json_blacklist);
214 #if defined(USE_AURA) || defined(OS_MACOSX)
215 // Compositing is always on for Aura and Mac.
216 #define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked
218 #define MAYBE_AcceleratedCompositingBlocked AcceleratedCompositingBlocked
221 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingBlockedTest,
222 MAYBE_AcceleratedCompositingBlocked) {
223 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
224 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING));
226 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
227 RunEventTest(url, kSwapBuffersEvent, false);
230 class AcceleratedCompositingTest : public GpuFeatureTest {
232 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
233 GpuFeatureTest::SetUpCommandLine(command_line);
234 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
238 #if defined(USE_AURA) || defined(OS_MACOSX)
239 // Compositing is always on for Aura and Mac.
240 #define MAYBE_AcceleratedCompositingDisabled DISABLED_AcceleratedCompositingDisabled
242 #define MAYBE_AcceleratedCompositingDisabled AcceleratedCompositingDisabled
245 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest,
246 MAYBE_AcceleratedCompositingDisabled) {
247 // Compositing is always on for Windows Aura.
248 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
249 RunEventTest(url, kSwapBuffersEvent, false);
252 // Times out: http://crbug.com/166060
253 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, DISABLED_WebGLAllowed) {
254 EXPECT_FALSE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
255 gpu::GPU_FEATURE_TYPE_WEBGL));
257 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
258 RunEventTest(url, kWebGLCreationEvent, true);
261 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLBlocked) {
262 const std::string json_blacklist =
264 " \"name\": \"gpu blacklist\",\n"
265 " \"version\": \"1.0\",\n"
275 SetupBlacklist(json_blacklist);
276 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
277 gpu::GPU_FEATURE_TYPE_WEBGL));
279 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
280 RunEventTest(url, kWebGLCreationEvent, false);
283 class WebGLTest : public GpuFeatureTest {
285 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
286 GpuFeatureTest::SetUpCommandLine(command_line);
287 #if !defined(OS_ANDROID)
288 // On Android, WebGL is disabled by default
289 command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
294 IN_PROC_BROWSER_TEST_F(WebGLTest, WebGLDisabled) {
295 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
296 RunEventTest(url, kWebGLCreationEvent, false);
299 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingAllowed) {
300 bool expect_blacklisted = false;
301 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
302 expect_blacklisted = true;
304 EXPECT_EQ(expect_blacklisted,
305 GpuDataManager::GetInstance()->IsFeatureBlacklisted(
306 gpu::GPU_FEATURE_TYPE_MULTISAMPLING));
308 // Multisampling is not supported if running on top of osmesa.
309 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
312 // Linux Intel uses mesa driver, where multisampling is not supported.
313 // Multisampling is also not supported on virtualized mac os.
314 std::vector<std::string> configs;
315 configs.push_back("LINUX INTEL");
316 configs.push_back("MAC VMWARE");
317 if (gpu::GPUTestBotConfig::CurrentConfigMatches(configs))
320 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
321 RunTest(url, "\"TRUE\"", true);
324 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingBlocked) {
325 // Multisampling fails on virtualized mac os.
326 if (gpu::GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
329 const std::string json_blacklist =
331 " \"name\": \"gpu blacklist\",\n"
332 " \"version\": \"1.0\",\n"
337 " \"multisampling\"\n"
342 SetupBlacklist(json_blacklist);
343 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
344 gpu::GPU_FEATURE_TYPE_MULTISAMPLING));
346 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
347 RunTest(url, "\"FALSE\"", true);
350 class WebGLMultisamplingTest : public GpuFeatureTest {
352 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
353 GpuFeatureTest::SetUpCommandLine(command_line);
354 command_line->AppendSwitch(switches::kDisableGLMultisampling);
358 IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) {
359 // Multisampling fails on virtualized mac os.
360 if (gpu::GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
363 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
364 RunTest(url, "\"FALSE\"", true);
367 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, Canvas2DAllowed) {
368 // Accelerated canvas 2D is not supported on XP.
369 if (gpu::GPUTestBotConfig::CurrentConfigMatches("XP"))
374 BLACKLISTED, // Disabled via the blacklist.
375 DISABLED, // Not disabled via the blacklist, but expected to be disabled
377 } expected_state = ENABLED;
378 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
379 // Blacklist rule #24 disables accelerated_2d_canvas on Linux.
380 expected_state = BLACKLISTED;
381 #elif defined(OS_WIN)
382 // Blacklist rule #67 disables accelerated_2d_canvas on XP.
383 if (base::win::GetVersion() < base::win::VERSION_VISTA)
384 expected_state = BLACKLISTED;
387 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
388 expected_state = BLACKLISTED;
390 #if defined(USE_AURA)
391 // Canvas 2D is always disabled in software compositing mode, make sure it is
392 // marked as such if it wasn't blacklisted already.
393 if (expected_state == ENABLED &&
394 !content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
395 expected_state = DISABLED;
399 EXPECT_EQ(expected_state == BLACKLISTED,
400 GpuDataManager::GetInstance()->IsFeatureBlacklisted(
401 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
403 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
404 RunEventTest(url, kAcceleratedCanvasCreationEvent, expected_state == ENABLED);
407 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, Canvas2DBlocked) {
408 const std::string json_blacklist =
410 " \"name\": \"gpu blacklist\",\n"
411 " \"version\": \"1.0\",\n"
416 " \"accelerated_2d_canvas\"\n"
421 SetupBlacklist(json_blacklist);
422 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
423 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
425 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
426 RunEventTest(url, kAcceleratedCanvasCreationEvent, false);
429 class Canvas2DDisabledTest : public GpuFeatureTest {
431 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
432 GpuFeatureTest::SetUpCommandLine(command_line);
433 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
437 IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest, Canvas2DDisabled) {
438 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
439 RunEventTest(url, kAcceleratedCanvasCreationEvent, false);
442 IN_PROC_BROWSER_TEST_F(GpuFeaturePixelTest,
443 CanOpenPopupAndRenderWithWebGLCanvas) {
444 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
447 const base::FilePath url(FILE_PATH_LITERAL("webgl_popup.html"));
448 RunTest(url, "\"SUCCESS\"", false);
452 IN_PROC_BROWSER_TEST_F(GpuFeatureTest,
453 DISABLED_CanOpenPopupAndRenderWith2DCanvas) {
454 const base::FilePath url(FILE_PATH_LITERAL("canvas_popup.html"));
455 RunTest(url, "\"SUCCESS\"", false);
458 class ThreadedCompositorTest : public GpuFeatureTest {
460 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
461 GpuFeatureTest::SetUpCommandLine(command_line);
462 command_line->AppendSwitch(switches::kEnableThreadedCompositing);
466 // http://crbug.com/157985
467 IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest, DISABLED_ThreadedCompositor) {
468 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
469 RunEventTest(url, kSwapBuffersEvent, true);
473 #if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
474 // http://crbug.com/162343: flaky on Windows and Mac, failing on ChromiumOS.
475 #define MAYBE_RafNoDamage DISABLED_RafNoDamage
477 #define MAYBE_RafNoDamage RafNoDamage
479 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MAYBE_RafNoDamage) {
480 category_patterns_ = "-test_*";
481 const base::FilePath url(FILE_PATH_LITERAL("feature_raf_no_damage.html"));
484 if (!analyzer_.get())
487 // Search for matching name on begin event or async_begin event (any begin).
489 (Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) ||
490 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN)) &&
491 Query::EventNameIs("___RafWithNoDamage___");
492 TraceEventVector events;
493 size_t num_events = analyzer_->FindEvents(query_raf, &events);
495 trace_analyzer::RateStats stats;
496 trace_analyzer::RateStatsOptions stats_options;
497 stats_options.trim_min = stats_options.trim_max = num_events / 10;
498 EXPECT_TRUE(trace_analyzer::GetRateStats(events, &stats, &stats_options));
500 LOG(INFO) << "Number of RAFs: " << num_events <<
501 " Mean: " << stats.mean_us <<
502 " Min: " << stats.min_us <<
503 " Max: " << stats.max_us <<
504 " StdDev: " << stats.standard_deviation_us;
506 // Expect that the average time between RAFs is more than 15ms. That will
507 // indicate that the renderer is not simply spinning on RAF.
508 EXPECT_GT(stats.mean_us, 15000.0);
510 // Print out the trace events upon error to debug failures.
511 if (stats.mean_us <= 15000.0) {
512 fprintf(stderr, "\n\nTRACE JSON:\n\n%s\n\n", trace_events_json_.c_str());
516 #if defined(OS_MACOSX)
517 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, IOSurfaceReuse) {
518 if (!IOSurfaceSupport::Initialize())
521 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
524 const base::FilePath url(
525 FILE_PATH_LITERAL("feature_compositing_static.html"));
526 base::FilePath test_path = gpu_test_dir_.Append(url);
527 ASSERT_TRUE(base::PathExists(test_path))
528 << "Missing test file: " << test_path.value();
530 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_path));
532 LOG(INFO) << "did navigate";
533 gfx::Rect bounds = browser()->window()->GetBounds();
534 gfx::Rect new_bounds = bounds;
536 const char* create_event = "IOSurfaceImageTransportSurface::CreateIOSurface";
537 const char* resize_event = "IOSurfaceImageTransportSurface::OnResize";
538 const char* draw_event = "CompositingIOSurfaceMac::DrawIOSurface";
539 Query find_creates = Query::MatchBeginName(create_event);
540 Query find_resizes = Query::MatchBeginName(resize_event) &&
541 Query::EventHasNumberArg("old_width") &&
542 Query::EventHasNumberArg("new_width");
543 Query find_draws = Query::MatchBeginName(draw_event) &&
544 Query::EventHasNumberArg("scale");
546 const int roundup = 64;
547 // A few resize values assuming a roundup of 64 pixels. The test will resize
548 // by these values one at a time and verify that CreateIOSurface only happens
549 // when the rounded width changes.
550 int offsets[] = { 1, roundup - 1, roundup, roundup + 1, 2*roundup};
551 int num_offsets = static_cast<int>(arraysize(offsets));
552 int w_start = bounds.width();
554 for (int offset_i = 0; offset_i < num_offsets; ++offset_i) {
555 new_bounds.set_width(w_start + offsets[offset_i]);
556 LOG(INFO) << "before wait";
557 ASSERT_TRUE(ResizeAndWait(new_bounds, "gpu", "gpu", resize_event));
558 LOG(INFO) << "after wait";
560 TraceEventVector resize_events;
561 analyzer_->FindEvents(find_resizes, &resize_events);
562 LOG(INFO) << "num rezize events = " << resize_events.size();
563 for (size_t resize_i = 0; resize_i < resize_events.size(); ++resize_i) {
564 const trace_analyzer::TraceEvent* resize = resize_events[resize_i];
565 // Was a create allowed:
566 int old_width = resize->GetKnownArgAsInt("old_width");
567 int new_width = resize->GetKnownArgAsInt("new_width");
568 bool expect_create = (old_width/roundup != new_width/roundup ||
570 int expected_creates = expect_create ? 1 : 0;
572 // Find the create event inside this resize event (if any). This will
573 // determine if the resize triggered a reallocation of the IOSurface.
574 double begin_time = resize->timestamp;
575 double end_time = begin_time + resize->GetAbsTimeToOtherEvent();
576 Query find_this_create = find_creates &&
577 Query::EventTime() >= Query::Double(begin_time) &&
578 Query::EventTime() <= Query::Double(end_time);
579 TraceEventVector create_events;
580 int num_creates = static_cast<int>(analyzer_->FindEvents(find_this_create,
582 EXPECT_EQ(expected_creates, num_creates);
584 // For debugging failures, print out the width and height of each resize:
587 "%d (resize offset %d): IOSurface width %d -> %d; Creates %d "
588 "Expected %d", offset_i, offsets[offset_i],
589 old_width, new_width, num_creates, expected_creates);
592 LOG(INFO) << "finished test";