1# Copyright 2013 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
5import sys
6import time
7
8from telemetry.core.util import TimeoutException
9from telemetry.page import page_test
10from telemetry.value import scalar
11
12
13class RasterizeAndRecordMicro(page_test.PageTest):
14  def __init__(self):
15    super(RasterizeAndRecordMicro, self).__init__('')
16    self._chrome_branch_number = None
17
18  @classmethod
19  def AddCommandLineArgs(cls, parser):
20    parser.add_option('--start-wait-time', type='float',
21                      default=2,
22                      help='Wait time before the benchmark is started '
23                      '(must be long enought to load all content)')
24    parser.add_option('--rasterize-repeat', type='int',
25                      default=100,
26                      help='Repeat each raster this many times. Increase '
27                      'this value to reduce variance.')
28    parser.add_option('--record-repeat', type='int',
29                      default=100,
30                      help='Repeat each record this many times. Increase '
31                      'this value to reduce variance.')
32    parser.add_option('--timeout', type='int',
33                      default=120,
34                      help='The length of time to wait for the micro '
35                      'benchmark to finish, expressed in seconds.')
36    parser.add_option('--report-detailed-results',
37                      action='store_true',
38                      help='Whether to report additional detailed results.')
39
40  def CustomizeBrowserOptions(self, options):
41    options.AppendExtraBrowserArgs([
42        '--enable-impl-side-painting',
43        '--enable-threaded-compositing',
44        '--enable-gpu-benchmarking'
45    ])
46
47  def DidStartBrowser(self, browser):
48    # TODO(vmpstr): Remove this temporary workaround when reference build has
49    # been updated to branch 1713 or later.
50    backend = browser._browser_backend # pylint: disable=W0212
51    self._chrome_branch_number = getattr(backend, 'chrome_branch_number', None)
52    if (not self._chrome_branch_number or
53        (sys.platform != 'android' and self._chrome_branch_number < 1713)):
54      raise page_test.TestNotSupportedOnPlatformFailure(
55          'rasterize_and_record_micro requires Chrome branch 1713 '
56          'or later. Skipping measurement.')
57
58  def ValidateAndMeasurePage(self, page, tab, results):
59    try:
60      tab.WaitForDocumentReadyStateToBeComplete()
61    except TimeoutException:
62      pass
63    time.sleep(self.options.start_wait_time)
64
65    record_repeat = self.options.record_repeat
66    rasterize_repeat = self.options.rasterize_repeat
67    # Enqueue benchmark
68    tab.ExecuteJavaScript("""
69        window.benchmark_results = {};
70        window.benchmark_results.done = false;
71        window.benchmark_results.id =
72            chrome.gpuBenchmarking.runMicroBenchmark(
73                "rasterize_and_record_benchmark",
74                function(value) {
75                  window.benchmark_results.done = true;
76                  window.benchmark_results.results = value;
77                }, {
78                  "record_repeat_count": """ + str(record_repeat) + """,
79                  "rasterize_repeat_count": """ + str(rasterize_repeat) + """
80                });
81    """)
82
83    benchmark_id = tab.EvaluateJavaScript('window.benchmark_results.id')
84    if (not benchmark_id):
85      raise page_test.MeasurementFailure(
86          'Failed to schedule rasterize_and_record_micro')
87
88    tab.WaitForJavaScriptExpression(
89        'window.benchmark_results.done', self.options.timeout)
90
91    data = tab.EvaluateJavaScript('window.benchmark_results.results')
92
93    pixels_recorded = data['pixels_recorded']
94    record_time = data['record_time_ms']
95    pixels_rasterized = data['pixels_rasterized']
96    rasterize_time = data['rasterize_time_ms']
97
98    results.AddValue(scalar.ScalarValue(
99        results.current_page, 'pixels_recorded', 'pixels', pixels_recorded))
100    results.AddValue(scalar.ScalarValue(
101        results.current_page, 'record_time', 'ms', record_time))
102    results.AddValue(scalar.ScalarValue(
103        results.current_page, 'pixels_rasterized', 'pixels', pixels_rasterized))
104    results.AddValue(scalar.ScalarValue(
105        results.current_page, 'rasterize_time', 'ms', rasterize_time))
106
107    # TODO(skyostil): Remove this temporary workaround when reference build has
108    # been updated to branch 1931 or later.
109    if ((self._chrome_branch_number and self._chrome_branch_number >= 1931) or
110        sys.platform == 'android'):
111      record_time_sk_null_canvas = data['record_time_sk_null_canvas_ms']
112      record_time_painting_disabled = data['record_time_painting_disabled_ms']
113      record_time_skrecord = data['record_time_skrecord_ms']
114      results.AddValue(scalar.ScalarValue(
115          results.current_page, 'record_time_sk_null_canvas', 'ms',
116          record_time_sk_null_canvas))
117      results.AddValue(scalar.ScalarValue(
118          results.current_page, 'record_time_painting_disabled', 'ms',
119          record_time_painting_disabled))
120      results.AddValue(scalar.ScalarValue(
121          results.current_page, 'record_time_skrecord', 'ms',
122          record_time_skrecord))
123
124    if self.options.report_detailed_results:
125      pixels_rasterized_with_non_solid_color = \
126          data['pixels_rasterized_with_non_solid_color']
127      pixels_rasterized_as_opaque = \
128          data['pixels_rasterized_as_opaque']
129      total_layers = data['total_layers']
130      total_picture_layers = data['total_picture_layers']
131      total_picture_layers_with_no_content = \
132          data['total_picture_layers_with_no_content']
133      total_picture_layers_off_screen = \
134          data['total_picture_layers_off_screen']
135
136      results.AddValue(scalar.ScalarValue(
137          results.current_page, 'pixels_rasterized_with_non_solid_color',
138          'pixels', pixels_rasterized_with_non_solid_color))
139      results.AddValue(scalar.ScalarValue(
140          results.current_page, 'pixels_rasterized_as_opaque', 'pixels',
141          pixels_rasterized_as_opaque))
142      results.AddValue(scalar.ScalarValue(
143          results.current_page, 'total_layers', 'count', total_layers))
144      results.AddValue(scalar.ScalarValue(
145          results.current_page, 'total_picture_layers', 'count',
146          total_picture_layers))
147      results.AddValue(scalar.ScalarValue(
148          results.current_page, 'total_picture_layers_with_no_content', 'count',
149          total_picture_layers_with_no_content))
150      results.AddValue(scalar.ScalarValue(
151          results.current_page, 'total_picture_layers_off_screen', 'count',
152          total_picture_layers_off_screen))
153