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/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/test_launcher_utils.h"
18 #include "chrome/test/base/tracing.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/gpu_data_manager.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/common/gpu_info.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "content/test/gpu/gpu_test_config.h"
25 #include "net/base/net_util.h"
26 #include "ui/gl/gl_switches.h"
27 #include "ui/compositor/compositor_setup.h"
28 #if defined(OS_MACOSX)
29 #include "ui/surface/io_surface_support_mac.h"
33 #include "base/win/windows_version.h"
36 using content::GpuDataManager
;
37 using content::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() : trace_categories_("test_gpu"), gpu_enabled_(false) {}
52 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
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
) {
59 // Do not use mesa if real GPU is required.
60 if (!command_line
->HasSwitch(switches::kUseGpuInTests
)) {
61 #if !defined(OS_MACOSX)
62 CHECK(test_launcher_utils::OverrideGLImplementation(
63 command_line
, gfx::kGLImplementationOSMesaName
)) <<
64 "kUseGL must not be set by test framework code!";
69 command_line
->AppendSwitch(switches::kDisablePopupBlocking
);
70 ui::DisableTestCompositor();
71 command_line
->AppendSwitchASCII(switches::kWindowSize
, "400,300");
74 void SetupBlacklist(const std::string
& json_blacklist
) {
75 content::GPUInfo gpu_info
;
76 GpuDataManager::GetInstance()->InitializeForTesting(
77 json_blacklist
, gpu_info
);
80 // If expected_reply is NULL, we don't check the reply content.
81 void RunTest(const FilePath
& url
,
82 const char* expected_reply
,
84 #if defined(OS_LINUX) && !defined(NDEBUG)
85 // Bypass tests on GPU Linux Debug bots.
91 test_path
= gpu_test_dir_
.Append(url
);
92 ASSERT_TRUE(file_util::PathExists(test_path
))
93 << "Missing test file: " << test_path
.value();
95 content::DOMMessageQueue message_queue
;
97 ui_test_utils::NavigateToURLWithDisposition(
98 browser(), net::FilePathToFileURL(test_path
),
99 NEW_FOREGROUND_TAB
, ui_test_utils::BROWSER_TEST_NONE
);
101 ui_test_utils::NavigateToURL(
102 browser(), net::FilePathToFileURL(test_path
));
106 // Wait for message indicating the test has finished running.
107 ASSERT_TRUE(message_queue
.WaitForMessage(&result
));
109 EXPECT_STREQ(expected_reply
, result
.c_str());
112 // Open the URL and check the trace stream for the given event.
113 void RunEventTest(const FilePath
& url
,
114 const char* event_name
= NULL
,
115 bool event_expected
= false) {
116 #if defined(OS_LINUX) && !defined(NDEBUG)
117 // Bypass tests on GPU Linux Debug bots.
121 #if defined(OS_MACOSX)
122 // Bypass tests on Mac OSX 10.5 bots (IOSurfaceSupport is now required).
123 if (!IOSurfaceSupport::Initialize())
127 ASSERT_TRUE(tracing::BeginTracing(trace_categories_
));
129 // Have to use a new tab for the blacklist to work.
130 RunTest(url
, NULL
, true);
132 ASSERT_TRUE(tracing::EndTracing(&trace_events_json_
));
134 analyzer_
.reset(TraceAnalyzer::Create(trace_events_json_
));
135 analyzer_
->AssociateBeginEndEvents();
136 TraceEventVector events
;
142 analyzer_
->FindEvents(Query::EventNameIs(event_name
), &events
);
145 EXPECT_GT(event_count
, 0U);
147 EXPECT_EQ(event_count
, 0U);
150 // Trigger a resize of the chrome window, and use tracing to wait for the
151 // given |wait_event|.
152 bool ResizeAndWait(const gfx::Rect
& new_bounds
,
153 const char* trace_categories
,
154 const char* wait_category
,
155 const char* wait_event
) {
156 if (!tracing::BeginTracingWithWatch(trace_categories
, wait_category
,
159 browser()->window()->SetBounds(new_bounds
);
160 if (!tracing::WaitForWatchEvent(base::TimeDelta()))
162 if (!tracing::EndTracing(&trace_events_json_
))
164 analyzer_
.reset(TraceAnalyzer::Create(trace_events_json_
));
165 analyzer_
->AssociateBeginEndEvents();
170 FilePath gpu_test_dir_
;
171 scoped_ptr
<TraceAnalyzer
> analyzer_
;
172 std::string trace_categories_
;
173 std::string trace_events_json_
;
177 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, AcceleratedCompositingAllowed
) {
178 GpuFeatureType type
=
179 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
182 const FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
183 RunEventTest(url
, kSwapBuffersEvent
, true);
186 // Flash Stage3D may be blacklisted for other reasons on XP, so ignore it.
187 GpuFeatureType
IgnoreGpuFeatures(GpuFeatureType type
) {
189 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
190 return static_cast<GpuFeatureType
>(type
&
191 ~content::GPU_FEATURE_TYPE_FLASH_STAGE3D
);
196 class AcceleratedCompositingBlockedTest
: public GpuFeatureTest
{
198 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
199 GpuFeatureTest::SetUpInProcessBrowserTestFixture();
200 const std::string json_blacklist
=
202 " \"name\": \"gpu blacklist\",\n"
203 " \"version\": \"1.0\",\n"
207 " \"blacklist\": [\n"
208 " \"accelerated_compositing\"\n"
213 SetupBlacklist(json_blacklist
);
217 #if (defined(OS_WIN) && defined(USE_AURA)) || defined(OS_CHROMEOS)
218 // Compositing is always on for Windows Aura.
219 // Disabled on chrome os due to http://crbug.com/167806
220 #define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked
222 #define MAYBE_AcceleratedCompositingBlocked AcceleratedCompositingBlocked
225 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingBlockedTest
,
226 MAYBE_AcceleratedCompositingBlocked
) {
227 GpuFeatureType type
=
228 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
229 type
= IgnoreGpuFeatures(type
);
231 EXPECT_EQ(type
, content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
);
233 const FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
234 RunEventTest(url
, kSwapBuffersEvent
, false);
237 class AcceleratedCompositingTest
: public GpuFeatureTest
{
239 virtual void SetUpCommandLine(CommandLine
* command_line
) {
240 GpuFeatureTest::SetUpCommandLine(command_line
);
241 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
245 #if defined(OS_WIN) && defined(USE_AURA)
246 // Compositing is always on for Windows Aura.
247 #define MAYBE_AcceleratedCompositingDisabled DISABLED_AcceleratedCompositingDisabled
249 #define MAYBE_AcceleratedCompositingDisabled AcceleratedCompositingDisabled
252 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest
,
253 MAYBE_AcceleratedCompositingDisabled
) {
254 // Compositing is always on for Windows Aura.
255 const FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
256 RunEventTest(url
, kSwapBuffersEvent
, false);
259 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, WebGLAllowed
) {
260 GpuFeatureType type
=
261 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
264 const FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
265 RunEventTest(url
, kWebGLCreationEvent
, true);
268 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, WebGLBlocked
) {
269 const std::string json_blacklist
=
271 " \"name\": \"gpu blacklist\",\n"
272 " \"version\": \"1.0\",\n"
276 " \"blacklist\": [\n"
282 SetupBlacklist(json_blacklist
);
283 GpuFeatureType type
=
284 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
285 type
= IgnoreGpuFeatures(type
);
286 EXPECT_EQ(type
, content::GPU_FEATURE_TYPE_WEBGL
);
288 const FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
289 RunEventTest(url
, kWebGLCreationEvent
, false);
292 class WebGLTest
: public GpuFeatureTest
{
294 virtual void SetUpCommandLine(CommandLine
* command_line
) {
295 GpuFeatureTest::SetUpCommandLine(command_line
);
296 #if !defined(OS_ANDROID)
297 // On Android, WebGL is disabled by default
298 command_line
->AppendSwitch(switches::kDisableExperimentalWebGL
);
303 IN_PROC_BROWSER_TEST_F(WebGLTest
, WebGLDisabled
) {
304 const FilePath
url(FILE_PATH_LITERAL("feature_webgl.html"));
305 RunEventTest(url
, kWebGLCreationEvent
, false);
308 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, MultisamplingAllowed
) {
309 GpuFeatureType type
=
310 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
313 // Multisampling is not supported if running on top of osmesa.
314 std::string use_gl
= CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
316 if (use_gl
== gfx::kGLImplementationOSMesaName
)
319 // Linux Intel uses mesa driver, where multisampling is not supported.
320 // Multisampling is also not supported on virtualized mac os.
321 std::vector
<std::string
> configs
;
322 configs
.push_back("LINUX INTEL");
323 configs
.push_back("MAC VMWARE");
324 if (GPUTestBotConfig::CurrentConfigMatches(configs
))
327 const FilePath
url(FILE_PATH_LITERAL("feature_multisampling.html"));
328 RunTest(url
, "\"TRUE\"", true);
331 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, MultisamplingBlocked
) {
332 // Multisampling fails on virtualized mac os.
333 if (GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
336 const std::string json_blacklist
=
338 " \"name\": \"gpu blacklist\",\n"
339 " \"version\": \"1.0\",\n"
343 " \"blacklist\": [\n"
344 " \"multisampling\"\n"
349 SetupBlacklist(json_blacklist
);
350 GpuFeatureType type
=
351 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
352 type
= IgnoreGpuFeatures(type
);
353 EXPECT_EQ(type
, content::GPU_FEATURE_TYPE_MULTISAMPLING
);
355 const FilePath
url(FILE_PATH_LITERAL("feature_multisampling.html"));
356 RunTest(url
, "\"FALSE\"", true);
359 class WebGLMultisamplingTest
: public GpuFeatureTest
{
361 virtual void SetUpCommandLine(CommandLine
* command_line
) {
362 GpuFeatureTest::SetUpCommandLine(command_line
);
363 command_line
->AppendSwitch(switches::kDisableGLMultisampling
);
367 IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest
, MultisamplingDisabled
) {
368 // Multisampling fails on virtualized mac os.
369 if (GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
372 const FilePath
url(FILE_PATH_LITERAL("feature_multisampling.html"));
373 RunTest(url
, "\"FALSE\"", true);
376 #if defined(OS_LINUX)
377 #define MAYBE_Canvas2DAllowed DISABLED_Canvas2DAllowed
379 #define MAYBE_Canvas2DAllowed Canvas2DAllowed
381 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, MAYBE_Canvas2DAllowed
) {
382 // Accelerated canvas 2D is not supported on XP.
383 if (GPUTestBotConfig::CurrentConfigMatches("XP"))
386 GpuFeatureType type
=
387 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
390 const FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
391 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, true);
394 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, Canvas2DBlocked
) {
395 const std::string json_blacklist
=
397 " \"name\": \"gpu blacklist\",\n"
398 " \"version\": \"1.0\",\n"
402 " \"blacklist\": [\n"
403 " \"accelerated_2d_canvas\"\n"
408 SetupBlacklist(json_blacklist
);
409 GpuFeatureType type
=
410 GpuDataManager::GetInstance()->GetBlacklistedFeatures();
411 type
= IgnoreGpuFeatures(type
);
412 EXPECT_EQ(type
, content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
);
414 const FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
415 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, false);
418 class Canvas2DDisabledTest
: public GpuFeatureTest
{
420 virtual void SetUpCommandLine(CommandLine
* command_line
) {
421 GpuFeatureTest::SetUpCommandLine(command_line
);
422 command_line
->AppendSwitch(switches::kDisableAccelerated2dCanvas
);
426 IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest
, Canvas2DDisabled
) {
427 const FilePath
url(FILE_PATH_LITERAL("feature_canvas2d.html"));
428 RunEventTest(url
, kAcceleratedCanvasCreationEvent
, false);
431 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
,
432 CanOpenPopupAndRenderWithWebGLCanvas
) {
433 const FilePath
url(FILE_PATH_LITERAL("webgl_popup.html"));
434 RunTest(url
, "\"SUCCESS\"", false);
437 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, CanOpenPopupAndRenderWith2DCanvas
) {
438 const FilePath
url(FILE_PATH_LITERAL("canvas_popup.html"));
439 RunTest(url
, "\"SUCCESS\"", false);
442 class ThreadedCompositorTest
: public GpuFeatureTest
{
444 virtual void SetUpCommandLine(CommandLine
* command_line
) {
445 GpuFeatureTest::SetUpCommandLine(command_line
);
446 command_line
->AppendSwitch(switches::kEnableThreadedCompositing
);
450 #if defined(OS_LINUX)
451 // http://crbug.com/157985: test fails on Linux
452 #define MAYBE_ThreadedCompositor DISABLED_ThreadedCompositor
454 #define MAYBE_ThreadedCompositor ThreadedCompositor
456 IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest
, MAYBE_ThreadedCompositor
) {
457 const FilePath
url(FILE_PATH_LITERAL("feature_compositing.html"));
458 RunEventTest(url
, kSwapBuffersEvent
, true);
463 // http://crbug.com/162343: flaky on Windows
464 #define MAYBE_RafNoDamage DISABLED_RafNoDamage
466 #define MAYBE_RafNoDamage RafNoDamage
468 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, MAYBE_RafNoDamage
) {
469 trace_categories_
= "-test_*";
470 const FilePath
url(FILE_PATH_LITERAL("feature_raf_no_damage.html"));
473 if (!analyzer_
.get())
476 // Search for matching name on begin event or async_begin event (any begin).
478 (Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN
) ||
479 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN
)) &&
480 Query::EventNameIs("___RafWithNoDamage___");
481 TraceEventVector events
;
482 size_t num_events
= analyzer_
->FindEvents(query_raf
, &events
);
484 trace_analyzer::RateStats stats
;
485 trace_analyzer::RateStatsOptions stats_options
;
486 stats_options
.trim_min
= stats_options
.trim_max
= num_events
/ 10;
487 EXPECT_TRUE(trace_analyzer::GetRateStats(events
, &stats
, &stats_options
));
489 LOG(INFO
) << "Number of RAFs: " << num_events
<<
490 " Mean: " << stats
.mean_us
<<
491 " Min: " << stats
.min_us
<<
492 " Max: " << stats
.max_us
<<
493 " StdDev: " << stats
.standard_deviation_us
;
495 // Expect that the average time between RAFs is more than 15ms. That will
496 // indicate that the renderer is not simply spinning on RAF.
497 EXPECT_GT(stats
.mean_us
, 15000.0);
499 // Print out the trace events upon error to debug failures.
500 if (stats
.mean_us
<= 15000.0) {
501 fprintf(stderr
, "\n\nTRACE JSON:\n\n%s\n\n", trace_events_json_
.c_str());
505 #if defined(OS_MACOSX)
506 IN_PROC_BROWSER_TEST_F(GpuFeatureTest
, IOSurfaceReuse
) {
507 if (!IOSurfaceSupport::Initialize())
510 const FilePath
url(FILE_PATH_LITERAL("feature_compositing_static.html"));
511 FilePath test_path
= gpu_test_dir_
.Append(url
);
512 ASSERT_TRUE(file_util::PathExists(test_path
))
513 << "Missing test file: " << test_path
.value();
515 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_path
));
517 gfx::Rect bounds
= browser()->window()->GetBounds();
518 gfx::Rect new_bounds
= bounds
;
520 const char* create_event
= "IOSurfaceImageTransportSurface::CreateIOSurface";
521 const char* resize_event
= "IOSurfaceImageTransportSurface::OnResize";
522 const char* draw_event
= "CompositingIOSurfaceMac::DrawIOSurface";
523 Query find_creates
= Query::MatchBeginName(create_event
);
524 Query find_resizes
= Query::MatchBeginName(resize_event
) &&
525 Query::EventHasNumberArg("old_width") &&
526 Query::EventHasNumberArg("new_width");
527 Query find_draws
= Query::MatchBeginName(draw_event
) &&
528 Query::EventHasNumberArg("scale");
530 const int roundup
= 64;
531 // A few resize values assuming a roundup of 64 pixels. The test will resize
532 // by these values one at a time and verify that CreateIOSurface only happens
533 // when the rounded width changes.
534 int offsets
[] = { 1, roundup
- 1, roundup
, roundup
+ 1, 2*roundup
};
535 int num_offsets
= static_cast<int>(arraysize(offsets
));
536 int w_start
= bounds
.width();
538 for (int offset_i
= 0; offset_i
< num_offsets
; ++offset_i
) {
539 new_bounds
.set_width(w_start
+ offsets
[offset_i
]);
540 ASSERT_TRUE(ResizeAndWait(new_bounds
, "gpu", "gpu", resize_event
));
542 TraceEventVector resize_events
;
543 analyzer_
->FindEvents(find_resizes
, &resize_events
);
544 for (size_t resize_i
= 0; resize_i
< resize_events
.size(); ++resize_i
) {
545 const trace_analyzer::TraceEvent
* resize
= resize_events
[resize_i
];
546 // Was a create allowed:
547 int old_width
= resize
->GetKnownArgAsInt("old_width");
548 int new_width
= resize
->GetKnownArgAsInt("new_width");
549 bool expect_create
= (old_width
/roundup
!= new_width
/roundup
||
551 int expected_creates
= expect_create
? 1 : 0;
553 // Find the create event inside this resize event (if any). This will
554 // determine if the resize triggered a reallocation of the IOSurface.
555 double begin_time
= resize
->timestamp
;
556 double end_time
= begin_time
+ resize
->GetAbsTimeToOtherEvent();
557 Query find_this_create
= find_creates
&&
558 Query::EventTime() >= Query::Double(begin_time
) &&
559 Query::EventTime() <= Query::Double(end_time
);
560 TraceEventVector create_events
;
561 int num_creates
= static_cast<int>(analyzer_
->FindEvents(find_this_create
,
563 EXPECT_EQ(expected_creates
, num_creates
);
565 // For debugging failures, print out the width and height of each resize:
568 "%d (resize offset %d): IOSurface width %d -> %d; Creates %d "
569 "Expected %d", offset_i
, offsets
[offset_i
],
570 old_width
, new_width
, num_creates
, expected_creates
);
576 } // namespace anonymous