• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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