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/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"
27
28 #if defined(OS_MACOSX)
29 #include "ui/gl/io_surface_support_mac.h"
30 #endif
31
32 #if defined(OS_WIN)
33 #include "base/win/windows_version.h"
34 #endif
35
36 using content::GpuDataManager;
37 using gpu::GpuFeatureType;
38 using trace_analyzer::Query;
39 using trace_analyzer::TraceAnalyzer;
40 using trace_analyzer::TraceEventVector;
41
42 namespace {
43
44 const char kSwapBuffersEvent[] = "SwapBuffers";
45 const char kAcceleratedCanvasCreationEvent[] = "Canvas2DLayerBridgeCreation";
46 const char kWebGLCreationEvent[] = "DrawingBufferCreation";
47
48 class GpuFeatureTest : public InProcessBrowserTest {
49 public:
GpuFeatureTest()50 GpuFeatureTest() : category_patterns_("test_gpu") {}
51
SetUp()52 virtual void SetUp() OVERRIDE {
53 // We expect to use real GL contexts for these tests.
54 UseRealGLContexts();
55
56 InProcessBrowserTest::SetUp();
57 }
58
SetUpInProcessBrowserTestFixture()59 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
60 base::FilePath test_dir;
61 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
62 gpu_test_dir_ = test_dir.AppendASCII("gpu");
63 }
64
SetUpCommandLine(CommandLine * command_line)65 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
66 command_line->AppendSwitch(switches::kDisablePopupBlocking);
67 command_line->AppendSwitchASCII(switches::kWindowSize, "400,300");
68 }
69
SetupBlacklist(const std::string & json_blacklist)70 void SetupBlacklist(const std::string& json_blacklist) {
71 gpu::GPUInfo gpu_info;
72 GpuDataManager::GetInstance()->InitializeForTesting(
73 json_blacklist, gpu_info);
74 }
75
76 // If expected_reply is NULL, we don't check the reply content.
RunTest(const base::FilePath & url,const char * expected_reply,bool new_tab)77 void RunTest(const base::FilePath& url,
78 const char* expected_reply,
79 bool new_tab) {
80 #if defined(OS_LINUX) && !defined(NDEBUG)
81 // Bypass tests on GPU Linux Debug bots.
82 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
83 return;
84 #endif
85
86 base::FilePath test_path;
87 test_path = gpu_test_dir_.Append(url);
88 ASSERT_TRUE(base::PathExists(test_path))
89 << "Missing test file: " << test_path.value();
90
91 content::DOMMessageQueue message_queue;
92 if (new_tab) {
93 ui_test_utils::NavigateToURLWithDisposition(
94 browser(), net::FilePathToFileURL(test_path),
95 NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_NONE);
96 } else {
97 ui_test_utils::NavigateToURL(
98 browser(), net::FilePathToFileURL(test_path));
99 }
100
101 std::string result;
102 // Wait for message indicating the test has finished running.
103 ASSERT_TRUE(message_queue.WaitForMessage(&result));
104 if (expected_reply)
105 EXPECT_STREQ(expected_reply, result.c_str());
106 }
107
108 // Open the URL and check the trace stream for the given event.
RunEventTest(const base::FilePath & url,const char * event_name=NULL,bool event_expected=false)109 void RunEventTest(const base::FilePath& url,
110 const char* event_name = NULL,
111 bool event_expected = false) {
112 #if defined(OS_LINUX) && !defined(NDEBUG)
113 // Bypass tests on GPU Linux Debug bots.
114 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
115 return;
116 #endif
117 #if defined(OS_MACOSX)
118 // Bypass tests on Mac OSX 10.5 bots (IOSurfaceSupport is now required).
119 if (!IOSurfaceSupport::Initialize())
120 return;
121 #endif
122
123 ASSERT_TRUE(tracing::BeginTracing(category_patterns_));
124
125 // Have to use a new tab for the blacklist to work.
126 RunTest(url, NULL, true);
127
128 ASSERT_TRUE(tracing::EndTracing(&trace_events_json_));
129
130 analyzer_.reset(TraceAnalyzer::Create(trace_events_json_));
131 analyzer_->AssociateBeginEndEvents();
132 TraceEventVector events;
133
134 if (!event_name)
135 return;
136
137 size_t event_count =
138 analyzer_->FindEvents(Query::EventNameIs(event_name), &events);
139
140 if (event_expected)
141 EXPECT_GT(event_count, 0U);
142 else
143 EXPECT_EQ(event_count, 0U);
144 }
145
146 // Trigger a resize of the chrome window, and use tracing to wait for the
147 // given |wait_event|.
ResizeAndWait(const gfx::Rect & new_bounds,const char * category_patterns,const char * wait_category,const char * wait_event)148 bool ResizeAndWait(const gfx::Rect& new_bounds,
149 const char* category_patterns,
150 const char* wait_category,
151 const char* wait_event) {
152 if (!tracing::BeginTracingWithWatch(category_patterns, wait_category,
153 wait_event, 1))
154 return false;
155 browser()->window()->SetBounds(new_bounds);
156 if (!tracing::WaitForWatchEvent(base::TimeDelta()))
157 return false;
158 if (!tracing::EndTracing(&trace_events_json_))
159 return false;
160 analyzer_.reset(TraceAnalyzer::Create(trace_events_json_));
161 analyzer_->AssociateBeginEndEvents();
162 return true;
163 }
164
165 protected:
166 base::FilePath gpu_test_dir_;
167 scoped_ptr<TraceAnalyzer> analyzer_;
168 std::string category_patterns_;
169 std::string trace_events_json_;
170 };
171
172 #if defined(OS_WIN) || defined(ADDRESS_SANITIZER) || defined(USE_AURA) || \
173 defined(OS_MACOSX)
174 // This test is flaky on Windows. http://crbug.com/177113
175 // Also fails under AddressSanitizer. http://crbug.com/185178
176 // It fundamentally doesn't test the right thing on Aura.
177 // http://crbug.com/280675
178 // This does not work with software compositing on Mac. http://crbug.com/286038
179 #define MAYBE_AcceleratedCompositingAllowed DISABLED_AcceleratedCompositingAllowed
180 #else
181 #define MAYBE_AcceleratedCompositingAllowed AcceleratedCompositingAllowed
182 #endif
183
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,MAYBE_AcceleratedCompositingAllowed)184 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MAYBE_AcceleratedCompositingAllowed) {
185 EXPECT_FALSE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
186 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING));
187
188 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
189 RunEventTest(url, kSwapBuffersEvent, true);
190 }
191
192 class AcceleratedCompositingBlockedTest : public GpuFeatureTest {
193 public:
SetUpInProcessBrowserTestFixture()194 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
195 GpuFeatureTest::SetUpInProcessBrowserTestFixture();
196 const std::string json_blacklist =
197 "{\n"
198 " \"name\": \"gpu blacklist\",\n"
199 " \"version\": \"1.0\",\n"
200 " \"entries\": [\n"
201 " {\n"
202 " \"id\": 1,\n"
203 " \"features\": [\n"
204 " \"accelerated_compositing\"\n"
205 " ]\n"
206 " }\n"
207 " ]\n"
208 "}";
209 SetupBlacklist(json_blacklist);
210 }
211 };
212
213 #if defined(USE_AURA)
214 // Compositing is always on for Aura.
215 #define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked
216 #else
217 #define MAYBE_AcceleratedCompositingBlocked AcceleratedCompositingBlocked
218 #endif
219
IN_PROC_BROWSER_TEST_F(AcceleratedCompositingBlockedTest,MAYBE_AcceleratedCompositingBlocked)220 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingBlockedTest,
221 MAYBE_AcceleratedCompositingBlocked) {
222 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
223 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING));
224
225 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
226 RunEventTest(url, kSwapBuffersEvent, false);
227 }
228
229 class AcceleratedCompositingTest : public GpuFeatureTest {
230 public:
SetUpCommandLine(CommandLine * command_line)231 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
232 GpuFeatureTest::SetUpCommandLine(command_line);
233 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
234 }
235 };
236
237 #if defined(USE_AURA)
238 // Compositing is always on for Aura.
239 #define MAYBE_AcceleratedCompositingDisabled DISABLED_AcceleratedCompositingDisabled
240 #else
241 #define MAYBE_AcceleratedCompositingDisabled AcceleratedCompositingDisabled
242 #endif
243
IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest,MAYBE_AcceleratedCompositingDisabled)244 IN_PROC_BROWSER_TEST_F(AcceleratedCompositingTest,
245 MAYBE_AcceleratedCompositingDisabled) {
246 // Compositing is always on for Windows Aura.
247 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
248 RunEventTest(url, kSwapBuffersEvent, false);
249 }
250
251 // Times out: http://crbug.com/166060
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,DISABLED_WebGLAllowed)252 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, DISABLED_WebGLAllowed) {
253 EXPECT_FALSE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
254 gpu::GPU_FEATURE_TYPE_WEBGL));
255
256 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
257 RunEventTest(url, kWebGLCreationEvent, true);
258 }
259
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,WebGLBlocked)260 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, WebGLBlocked) {
261 const std::string json_blacklist =
262 "{\n"
263 " \"name\": \"gpu blacklist\",\n"
264 " \"version\": \"1.0\",\n"
265 " \"entries\": [\n"
266 " {\n"
267 " \"id\": 1,\n"
268 " \"features\": [\n"
269 " \"webgl\"\n"
270 " ]\n"
271 " }\n"
272 " ]\n"
273 "}";
274 SetupBlacklist(json_blacklist);
275 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
276 gpu::GPU_FEATURE_TYPE_WEBGL));
277
278 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
279 RunEventTest(url, kWebGLCreationEvent, false);
280 }
281
282 class WebGLTest : public GpuFeatureTest {
283 public:
SetUpCommandLine(CommandLine * command_line)284 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
285 GpuFeatureTest::SetUpCommandLine(command_line);
286 #if !defined(OS_ANDROID)
287 // On Android, WebGL is disabled by default
288 command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
289 #endif
290 }
291 };
292
IN_PROC_BROWSER_TEST_F(WebGLTest,WebGLDisabled)293 IN_PROC_BROWSER_TEST_F(WebGLTest, WebGLDisabled) {
294 const base::FilePath url(FILE_PATH_LITERAL("feature_webgl.html"));
295 RunEventTest(url, kWebGLCreationEvent, false);
296 }
297
298 #if defined(GOOGLE_CHROME_BUILD) && defined(OS_MACOSX)
299 // http://crbug.com/314745
300 #define MultisamplingAllowed DISABLED_MultisamplingAllowed
301 #endif
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,MultisamplingAllowed)302 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingAllowed) {
303 bool expect_blacklisted = false;
304 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
305 expect_blacklisted = true;
306
307 EXPECT_EQ(expect_blacklisted,
308 GpuDataManager::GetInstance()->IsFeatureBlacklisted(
309 gpu::GPU_FEATURE_TYPE_MULTISAMPLING));
310
311 // Multisampling is not supported if running on top of osmesa.
312 if (gfx::GetGLImplementation() != gfx::kGLImplementationOSMesaGL)
313 return;
314
315 // Linux Intel uses mesa driver, where multisampling is not supported.
316 // Multisampling is also not supported on virtualized mac os.
317 std::vector<std::string> configs;
318 configs.push_back("LINUX INTEL");
319 configs.push_back("MAC VMWARE");
320 if (gpu::GPUTestBotConfig::CurrentConfigMatches(configs))
321 return;
322
323 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
324 RunTest(url, "\"TRUE\"", true);
325 }
326
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,MultisamplingBlocked)327 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MultisamplingBlocked) {
328 // Multisampling fails on virtualized mac os.
329 if (gpu::GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
330 return;
331
332 const std::string json_blacklist =
333 "{\n"
334 " \"name\": \"gpu blacklist\",\n"
335 " \"version\": \"1.0\",\n"
336 " \"entries\": [\n"
337 " {\n"
338 " \"id\": 1,\n"
339 " \"features\": [\n"
340 " \"multisampling\"\n"
341 " ]\n"
342 " }\n"
343 " ]\n"
344 "}";
345 SetupBlacklist(json_blacklist);
346 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
347 gpu::GPU_FEATURE_TYPE_MULTISAMPLING));
348
349 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
350 RunTest(url, "\"FALSE\"", true);
351 }
352
353 class WebGLMultisamplingTest : public GpuFeatureTest {
354 public:
SetUpCommandLine(CommandLine * command_line)355 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
356 GpuFeatureTest::SetUpCommandLine(command_line);
357 command_line->AppendSwitch(switches::kDisableGLMultisampling);
358 }
359 };
360
IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest,MultisamplingDisabled)361 IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) {
362 // Multisampling fails on virtualized mac os.
363 if (gpu::GPUTestBotConfig::CurrentConfigMatches("MAC VMWARE"))
364 return;
365
366 const base::FilePath url(FILE_PATH_LITERAL("feature_multisampling.html"));
367 RunTest(url, "\"FALSE\"", true);
368 }
369
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,Canvas2DAllowed)370 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, Canvas2DAllowed) {
371 // Accelerated canvas 2D is not supported on XP.
372 if (gpu::GPUTestBotConfig::CurrentConfigMatches("XP"))
373 return;
374
375 enum Canvas2DState {
376 ENABLED,
377 BLACKLISTED, // Disabled via the blacklist.
378 DISABLED, // Not disabled via the blacklist, but expected to be disabled
379 // by configuration.
380 } expected_state = ENABLED;
381 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
382 // Blacklist rule #24 disables accelerated_2d_canvas on Linux.
383 expected_state = BLACKLISTED;
384 #elif defined(OS_WIN)
385 // Blacklist rule #67 disables accelerated_2d_canvas on XP.
386 if (base::win::GetVersion() < base::win::VERSION_VISTA)
387 expected_state = BLACKLISTED;
388 #endif
389
390 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
391 expected_state = BLACKLISTED;
392
393 #if defined(USE_AURA)
394 // Canvas 2D is always disabled in software compositing mode, make sure it is
395 // marked as such if it wasn't blacklisted already.
396 if (expected_state == ENABLED &&
397 !content::GpuDataManager::GetInstance()->CanUseGpuBrowserCompositor()) {
398 expected_state = DISABLED;
399 }
400 #endif
401
402 EXPECT_EQ(expected_state == BLACKLISTED,
403 GpuDataManager::GetInstance()->IsFeatureBlacklisted(
404 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
405
406 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
407 RunEventTest(url, kAcceleratedCanvasCreationEvent, expected_state == ENABLED);
408 }
409
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,Canvas2DBlocked)410 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, Canvas2DBlocked) {
411 const std::string json_blacklist =
412 "{\n"
413 " \"name\": \"gpu blacklist\",\n"
414 " \"version\": \"1.0\",\n"
415 " \"entries\": [\n"
416 " {\n"
417 " \"id\": 1,\n"
418 " \"features\": [\n"
419 " \"accelerated_2d_canvas\"\n"
420 " ]\n"
421 " }\n"
422 " ]\n"
423 "}";
424 SetupBlacklist(json_blacklist);
425 EXPECT_TRUE(GpuDataManager::GetInstance()->IsFeatureBlacklisted(
426 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
427
428 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
429 RunEventTest(url, kAcceleratedCanvasCreationEvent, false);
430 }
431
432 class Canvas2DDisabledTest : public GpuFeatureTest {
433 public:
SetUpCommandLine(CommandLine * command_line)434 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
435 GpuFeatureTest::SetUpCommandLine(command_line);
436 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
437 }
438 };
439
IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest,Canvas2DDisabled)440 IN_PROC_BROWSER_TEST_F(Canvas2DDisabledTest, Canvas2DDisabled) {
441 const base::FilePath url(FILE_PATH_LITERAL("feature_canvas2d.html"));
442 RunEventTest(url, kAcceleratedCanvasCreationEvent, false);
443 }
444
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,CanOpenPopupAndRenderWithWebGLCanvas)445 IN_PROC_BROWSER_TEST_F(GpuFeatureTest,
446 CanOpenPopupAndRenderWithWebGLCanvas) {
447 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
448 return;
449
450 const base::FilePath url(FILE_PATH_LITERAL("webgl_popup.html"));
451 RunTest(url, "\"SUCCESS\"", false);
452 }
453
454 // crbug.com/176466
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,DISABLED_CanOpenPopupAndRenderWith2DCanvas)455 IN_PROC_BROWSER_TEST_F(GpuFeatureTest,
456 DISABLED_CanOpenPopupAndRenderWith2DCanvas) {
457 const base::FilePath url(FILE_PATH_LITERAL("canvas_popup.html"));
458 RunTest(url, "\"SUCCESS\"", false);
459 }
460
461 class ThreadedCompositorTest : public GpuFeatureTest {
462 public:
SetUpCommandLine(CommandLine * command_line)463 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
464 GpuFeatureTest::SetUpCommandLine(command_line);
465 command_line->AppendSwitch(switches::kEnableThreadedCompositing);
466 }
467 };
468
469 // http://crbug.com/157985
IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest,DISABLED_ThreadedCompositor)470 IN_PROC_BROWSER_TEST_F(ThreadedCompositorTest, DISABLED_ThreadedCompositor) {
471 const base::FilePath url(FILE_PATH_LITERAL("feature_compositing.html"));
472 RunEventTest(url, kSwapBuffersEvent, true);
473 }
474
475
476 #if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_MACOSX)
477 // http://crbug.com/162343: flaky on Windows and Mac, failing on ChromiumOS.
478 #define MAYBE_RafNoDamage DISABLED_RafNoDamage
479 #else
480 #define MAYBE_RafNoDamage RafNoDamage
481 #endif
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,MAYBE_RafNoDamage)482 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MAYBE_RafNoDamage) {
483 category_patterns_ = "-test_*";
484 const base::FilePath url(FILE_PATH_LITERAL("feature_raf_no_damage.html"));
485 RunEventTest(url);
486
487 if (!analyzer_.get())
488 return;
489
490 // Search for matching name on begin event or async_begin event (any begin).
491 Query query_raf =
492 (Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) ||
493 Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN)) &&
494 Query::EventNameIs("___RafWithNoDamage___");
495 TraceEventVector events;
496 size_t num_events = analyzer_->FindEvents(query_raf, &events);
497
498 trace_analyzer::RateStats stats;
499 trace_analyzer::RateStatsOptions stats_options;
500 stats_options.trim_min = stats_options.trim_max = num_events / 10;
501 EXPECT_TRUE(trace_analyzer::GetRateStats(events, &stats, &stats_options));
502
503 LOG(INFO) << "Number of RAFs: " << num_events <<
504 " Mean: " << stats.mean_us <<
505 " Min: " << stats.min_us <<
506 " Max: " << stats.max_us <<
507 " StdDev: " << stats.standard_deviation_us;
508
509 // Expect that the average time between RAFs is more than 15ms. That will
510 // indicate that the renderer is not simply spinning on RAF.
511 EXPECT_GT(stats.mean_us, 15000.0);
512
513 // Print out the trace events upon error to debug failures.
514 if (stats.mean_us <= 15000.0) {
515 fprintf(stderr, "\n\nTRACE JSON:\n\n%s\n\n", trace_events_json_.c_str());
516 }
517 }
518
519 #if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(GpuFeatureTest,IOSurfaceReuse)520 IN_PROC_BROWSER_TEST_F(GpuFeatureTest, IOSurfaceReuse) {
521 if (!IOSurfaceSupport::Initialize())
522 return;
523
524 if (gpu::GPUTestBotConfig::GpuBlacklistedOnBot())
525 return;
526
527 const base::FilePath url(
528 FILE_PATH_LITERAL("feature_compositing_static.html"));
529 base::FilePath test_path = gpu_test_dir_.Append(url);
530 ASSERT_TRUE(base::PathExists(test_path))
531 << "Missing test file: " << test_path.value();
532
533 ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_path));
534
535 gfx::Rect bounds = browser()->window()->GetBounds();
536 gfx::Rect new_bounds = bounds;
537
538 const char* create_event = "IOSurfaceImageTransportSurface::CreateIOSurface";
539 const char* resize_event = "IOSurfaceImageTransportSurface::OnResize";
540 const char* draw_event = "CompositingIOSurfaceMac::DrawIOSurface";
541 Query find_creates = Query::MatchBeginName(create_event);
542 Query find_resizes = Query::MatchBeginName(resize_event) &&
543 Query::EventHasNumberArg("old_width") &&
544 Query::EventHasNumberArg("new_width");
545 Query find_draws = Query::MatchBeginName(draw_event) &&
546 Query::EventHasNumberArg("scale");
547
548 const int roundup = 64;
549 // A few resize values assuming a roundup of 64 pixels. The test will resize
550 // by these values one at a time and verify that CreateIOSurface only happens
551 // when the rounded width changes.
552 int offsets[] = { 1, roundup - 1, roundup, roundup + 1, 2*roundup};
553 int num_offsets = static_cast<int>(arraysize(offsets));
554 int w_start = bounds.width();
555
556 for (int offset_i = 0; offset_i < num_offsets; ++offset_i) {
557 new_bounds.set_width(w_start + offsets[offset_i]);
558 ASSERT_TRUE(ResizeAndWait(new_bounds, "gpu", "gpu", resize_event));
559
560 TraceEventVector resize_events;
561 analyzer_->FindEvents(find_resizes, &resize_events);
562 for (size_t resize_i = 0; resize_i < resize_events.size(); ++resize_i) {
563 const trace_analyzer::TraceEvent* resize = resize_events[resize_i];
564 // Was a create allowed:
565 int old_width = resize->GetKnownArgAsInt("old_width");
566 int new_width = resize->GetKnownArgAsInt("new_width");
567 bool expect_create = (old_width/roundup != new_width/roundup ||
568 old_width == 0);
569 int expected_creates = expect_create ? 1 : 0;
570
571 // Find the create event inside this resize event (if any). This will
572 // determine if the resize triggered a reallocation of the IOSurface.
573 double begin_time = resize->timestamp;
574 double end_time = begin_time + resize->GetAbsTimeToOtherEvent();
575 Query find_this_create = find_creates &&
576 Query::EventTime() >= Query::Double(begin_time) &&
577 Query::EventTime() <= Query::Double(end_time);
578 TraceEventVector create_events;
579 int num_creates = static_cast<int>(analyzer_->FindEvents(find_this_create,
580 &create_events));
581 EXPECT_EQ(expected_creates, num_creates);
582
583 // For debugging failures, print out the width and height of each resize:
584 LOG(INFO) <<
585 base::StringPrintf(
586 "%d (resize offset %d): IOSurface width %d -> %d; Creates %d "
587 "Expected %d", offset_i, offsets[offset_i],
588 old_width, new_width, num_creates, expected_creates);
589 }
590 }
591 }
592 #endif
593
594 } // namespace
595