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/filename_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 // TODO(jam): http://crbug.com/350550
219 #define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked
222 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingBlockedTest
,
223 MAYBE_AcceleratedCompositingBlocked
) {
224 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
225 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
));
227 const base::FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
228 RunEventTest(url
, kSwapBuffersEvent
, false);
231 class AcceleratedCompositingTest
: public GpuFeatureTest
{
233 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
234 GpuFeatureTest::SetUpCommandLine(command_line
);
235 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
239 #if defined(USE_AURA) || defined(OS_MACOSX)
240 // Compositing is always on for Aura and Mac.
241 #define MAYBE_AcceleratedCompositingDisabled DISABLED_AcceleratedCompositingDisabled
243 #define MAYBE_AcceleratedCompositingDisabled AcceleratedCompositingDisabled
246 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest
,
247 MAYBE_AcceleratedCompositingDisabled
) {
248 // Compositing is always on for Windows Aura.
249 const base::FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
250 RunEventTest(url
, kSwapBuffersEvent
, false);
253 // Times out: http://crbug.com/166060
254 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, DISABLED_WebGLAllowed
) {
255 EXPECT_FALSE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
256 gpu::GPU_FEATURE_TYPE_WEBGL
));
258 const base::FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
259 RunEventTest(url
, kWebGLCreationEvent
, true);
262 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, WebGLBlocked
) {
263 const std::string json_blacklist
=
265 " \"name\": \"gpu blacklist\",\n"
266 " \"version\": \"1.0\",\n"
276 SetupBlacklist(json_blacklist
);
277 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
278 gpu::GPU_FEATURE_TYPE_WEBGL
));
280 const base::FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
281 RunEventTest(url
, kWebGLCreationEvent
, false);
284 class WebGLTest
: public GpuFeatureTest
{
286 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
287 GpuFeatureTest::SetUpCommandLine(command_line
);
288 #if !defined(OS_ANDROID)
289 // On Android, WebGL is disabled by default
290 command_line
->AppendSwitch(switches::kDisableExperimentalWebGL
);
295 IN_PROC_BROWSER_TEST_F(WebGLTest
, WebGLDisabled
) {
296 const base::FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
297 RunEventTest(url
, kWebGLCreationEvent
, false);
300 // This test is oblivious to the fact that multisample could be blacklisted on
301 // some configurations. Previously disabled on GOOGLE_CHROME_BUILD and
302 // on OS_MACOSX: http://crbug.com/314745
303 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, DISABLED_MultisamplingAllowed
) {
304 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
306 // Multisampling is not supported if running on top of osmesa.
307 if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL
)
309 // Linux Intel uses mesa driver, where multisampling is not supported.
310 // Multisampling is also not supported on virtualized mac os.
311 std::vector
<std::string
> configs
;
312 configs
.push_back("LINUX INTEL");
313 configs
.push_back("MAC VMWARE");
314 if (gpu::GPUTestBotConfig::CurrentConfigMatches(configs
))
317 const base::FilePath
url(FILE_PATH_LITERAL("feature_multisampling.html"));
318 RunTest(url
, "\"TRUE\"", true);
321 class WebGLMultisamplingTest
: public GpuFeatureTest
{
323 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
324 GpuFeatureTest::SetUpCommandLine(command_line
);
325 command_line
->AppendSwitch(switches::kDisableGLMultisampling
);
329 IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest
, MultisamplingDisabled
) {
330 // Multisampling fails on virtualized mac os.
331 if (gpu::GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
334 const base::FilePath
url(FILE_PATH_LITERAL("feature_multisampling.html"));
335 RunTest(url
, "\"FALSE\"", true);
338 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, Canvas2DAllowed
) {
339 // Accelerated canvas 2D is not supported on XP.
340 if (gpu::GPUTestBotConfig::CurrentConfigMatches("XP"))
345 BLACKLISTED
, // Disabled via the blacklist.
346 DISABLED
, // Not disabled via the blacklist, but expected to be disabled
348 } expected_state
= ENABLED
;
349 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
350 // Blacklist rule #24 disables accelerated_2d_canvas on Linux.
351 expected_state
= BLACKLISTED
;
352 #elif defined(OS_WIN)
353 // Blacklist rule #67 disables accelerated_2d_canvas on XP.
354 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
355 expected_state
= BLACKLISTED
;
358 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
359 expected_state
= BLACKLISTED
;
361 #if defined(USE_AURA)
362 // Canvas 2D is always disabled in software compositing mode, make sure it is
363 // marked as such if it wasn't blacklisted already.
364 if (expected_state
== ENABLED
&&
365 !content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
366 expected_state
= DISABLED
;
370 EXPECT_EQ(expected_state
== BLACKLISTED
,
371 GpuDataManager::GetInstance()->IsFeatureBlacklisted(
372 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
));
374 const base::FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
375 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, expected_state
== ENABLED
);
378 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, Canvas2DBlocked
) {
379 const std::string json_blacklist
=
381 " \"name\": \"gpu blacklist\",\n"
382 " \"version\": \"1.0\",\n"
387 " \"accelerated_2d_canvas\"\n"
392 SetupBlacklist(json_blacklist
);
393 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
394 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
));
396 const base::FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
397 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, false);
400 class Canvas2DDisabledTest
: public GpuFeatureTest
{
402 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
403 GpuFeatureTest::SetUpCommandLine(command_line
);
404 command_line
->AppendSwitch(switches::kDisableAccelerated2dCanvas
);
408 IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest
, Canvas2DDisabled
) {
409 const base::FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
410 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, false);
413 IN_PROC_BROWSER_TEST_F(GpuFeaturePixelTest
,
414 CanOpenPopupAndRenderWithWebGLCanvas
) {
415 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
418 const base::FilePath
url(FILE_PATH_LITERAL("webgl_popup.html"));
419 RunTest(url
, "\"SUCCESS\"", false);
423 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
,
424 DISABLED_CanOpenPopupAndRenderWith2DCanvas
) {
425 const base::FilePath
url(FILE_PATH_LITERAL("canvas_popup.html"));
426 RunTest(url
, "\"SUCCESS\"", false);
429 class ThreadedCompositorTest
: public GpuFeatureTest
{
431 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
432 GpuFeatureTest::SetUpCommandLine(command_line
);
433 command_line
->AppendSwitch(switches::kEnableThreadedCompositing
);
437 // http://crbug.com/157985
438 IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest
, DISABLED_ThreadedCompositor
) {
439 const base::FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
440 RunEventTest(url
, kSwapBuffersEvent
, true);
444 #if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
445 // http://crbug.com/162343: flaky on Windows and Mac, failing on ChromiumOS.
446 #define MAYBE_RafNoDamage DISABLED_RafNoDamage
448 #define MAYBE_RafNoDamage RafNoDamage
450 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, MAYBE_RafNoDamage
) {
451 category_patterns_
= "-test_*";
452 const base::FilePath
url(FILE_PATH_LITERAL("feature_raf_no_damage.html"));
455 if (!analyzer_
.get())
458 // Search for matching name on begin event or async_begin event (any begin).
460 (Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN
) ||
461 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN
)) &&
462 Query::EventNameIs("___RafWithNoDamage___");
463 TraceEventVector events
;
464 size_t num_events
= analyzer_
->FindEvents(query_raf
, &events
);
466 trace_analyzer::RateStats stats
;
467 trace_analyzer::RateStatsOptions stats_options
;
468 stats_options
.trim_min
= stats_options
.trim_max
= num_events
/ 10;
469 EXPECT_TRUE(trace_analyzer::GetRateStats(events
, &stats
, &stats_options
));
471 LOG(INFO
) << "Number of RAFs: " << num_events
<<
472 " Mean: " << stats
.mean_us
<<
473 " Min: " << stats
.min_us
<<
474 " Max: " << stats
.max_us
<<
475 " StdDev: " << stats
.standard_deviation_us
;
477 // Expect that the average time between RAFs is more than 15ms. That will
478 // indicate that the renderer is not simply spinning on RAF.
479 EXPECT_GT(stats
.mean_us
, 15000.0);
481 // Print out the trace events upon error to debug failures.
482 if (stats
.mean_us
<= 15000.0) {
483 fprintf(stderr
, "\n\nTRACE JSON:\n\n%s\n\n", trace_events_json_
.c_str());
487 #if defined(OS_MACOSX)
488 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, IOSurfaceReuse
) {
489 if (!IOSurfaceSupport::Initialize())
492 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
495 const base::FilePath
url(
496 FILE_PATH_LITERAL("feature_compositing_static.html"));
497 base::FilePath test_path
= gpu_test_dir_
.Append(url
);
498 ASSERT_TRUE(base::PathExists(test_path
))
499 << "Missing test file: " << test_path
.value();
501 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_path
));
503 LOG(INFO
) << "did navigate";
504 gfx::Rect bounds
= browser()->window()->GetBounds();
505 gfx::Rect new_bounds
= bounds
;
507 const char* create_event
= "IOSurfaceImageTransportSurface::CreateIOSurface";
508 const char* resize_event
= "IOSurfaceImageTransportSurface::OnResize";
509 const char* draw_event
= "CompositingIOSurfaceMac::DrawIOSurface";
510 Query find_creates
= Query::MatchBeginName(create_event
);
511 Query find_resizes
= Query::MatchBeginName(resize_event
) &&
512 Query::EventHasNumberArg("old_width") &&
513 Query::EventHasNumberArg("new_width");
514 Query find_draws
= Query::MatchBeginName(draw_event
) &&
515 Query::EventHasNumberArg("scale");
517 const int roundup
= 64;
518 // A few resize values assuming a roundup of 64 pixels. The test will resize
519 // by these values one at a time and verify that CreateIOSurface only happens
520 // when the rounded width changes.
521 int offsets
[] = { 1, roundup
- 1, roundup
, roundup
+ 1, 2*roundup
};
522 int num_offsets
= static_cast<int>(arraysize(offsets
));
523 int w_start
= bounds
.width();
525 for (int offset_i
= 0; offset_i
< num_offsets
; ++offset_i
) {
526 new_bounds
.set_width(w_start
+ offsets
[offset_i
]);
527 LOG(INFO
) << "before wait";
528 ASSERT_TRUE(ResizeAndWait(new_bounds
, "gpu", "gpu", resize_event
));
529 LOG(INFO
) << "after wait";
531 TraceEventVector resize_events
;
532 analyzer_
->FindEvents(find_resizes
, &resize_events
);
533 LOG(INFO
) << "num rezize events = " << resize_events
.size();
534 for (size_t resize_i
= 0; resize_i
< resize_events
.size(); ++resize_i
) {
535 const trace_analyzer::TraceEvent
* resize
= resize_events
[resize_i
];
536 // Was a create allowed:
537 int old_width
= resize
->GetKnownArgAsInt("old_width");
538 int new_width
= resize
->GetKnownArgAsInt("new_width");
539 bool expect_create
= (old_width
/roundup
!= new_width
/roundup
||
541 int expected_creates
= expect_create
? 1 : 0;
543 // Find the create event inside this resize event (if any). This will
544 // determine if the resize triggered a reallocation of the IOSurface.
545 double begin_time
= resize
->timestamp
;
546 double end_time
= begin_time
+ resize
->GetAbsTimeToOtherEvent();
547 Query find_this_create
= find_creates
&&
548 Query::EventTime() >= Query::Double(begin_time
) &&
549 Query::EventTime() <= Query::Double(end_time
);
550 TraceEventVector create_events
;
551 int num_creates
= static_cast<int>(analyzer_
->FindEvents(find_this_create
,
553 EXPECT_EQ(expected_creates
, num_creates
);
555 // For debugging failures, print out the width and height of each resize:
558 "%d (resize offset %d): IOSurface width %d -> %d; Creates %d "
559 "Expected %d", offset_i
, offsets
[offset_i
],
560 old_width
, new_width
, num_creates
, expected_creates
);
563 LOG(INFO
) << "finished test";