• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 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 logging
6import os
7
8from autotest_lib.client.bin import utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros import chrome_binary_test
11from autotest_lib.client.cros.graphics import graphics_utils
12from autotest_lib.client.common_lib.cros import chrome
13from autotest_lib.client.cros import constants
14from autotest_lib.client.cros.multimedia import display_facade_native
15from autotest_lib.client.cros.multimedia import facade_resource
16
17EXTRA_BROWSER_ARGS = ['--enable-experimental-web-platform-features',
18                      '--force-tablet-mode=clamshell']
19
20class graphics_HwOverlays(graphics_utils.GraphicsTest,
21                          chrome_binary_test.ChromeBinaryTest):
22    """Runs a given html and measures stuff."""
23    version = 1
24
25    # The tests are essentially composed of a preamble and an epilog, in between
26    # which we count the amount of overlays. Each of those essentially waits
27    # until either a total number of items is drawn, or there's a timeout.
28    PREAMBLE_TOTAL_NUMBER_OF_DRAW_PASSES = 5
29    PREAMBLE_TIMEOUT_SECONDS = 10
30    EPILOG_TOTAL_NUMBER_OF_DRAW_PASSES = 10
31    EPILOG_TIMEOUT_SECONDS = 10
32
33    POLLING_INTERVAL_SECONDS = 1
34
35    def initialize(self):
36        super(graphics_HwOverlays, self).initialize()
37
38    def cleanup(self):
39        super(graphics_HwOverlays, self).cleanup()
40
41    def set_rotation_to_zero(self, display_facade):
42        # Set rotation to 0 (portrait) otherwise tablet platforms might not get
43        # overlays.
44        internal_display_id = display_facade.get_internal_display_id()
45
46        logging.info("Internal display ID is %s", internal_display_id)
47        display_facade.set_display_rotation(internal_display_id, rotation=0)
48
49    def run_once(self, html_file, data_file_url = None, is_video = False,
50                 use_skia_renderer = False):
51        """Normalizes the environment, starts a Chrome environment, and
52        executes the test in `html_file`.
53        """
54        if not graphics_utils.is_drm_atomic_supported():
55            logging.info('Skipping test: platform does not support DRM atomic')
56            return
57
58        if graphics_utils.get_max_num_available_drm_planes() <= 2:
59            logging.info('Skipping test: platform supports 2 or less planes')
60            return
61
62        if is_video and not graphics_utils.is_nv12_supported_by_drm_planes():
63            logging.info('Skipping test: platform does not support NV12 planes')
64            return
65
66        extra_browser_args = EXTRA_BROWSER_ARGS
67        if use_skia_renderer:
68            # TODO(andrescj): remove when SkiaRenderer is enabled by default.
69            extra_browser_args.append('--enable-features=UseSkiaRenderer')
70
71        logging.info('Starting test, navigating to %s', html_file)
72
73        with chrome.Chrome(extra_browser_args=extra_browser_args,
74                           extension_paths=[constants.DISPLAY_TEST_EXTENSION],
75                           autotest_ext=True,
76                           init_network_controller=True) as cr:
77            facade = facade_resource.FacadeResource(cr)
78            display_facade = display_facade_native.DisplayFacadeNative(facade)
79            # TODO(crbug.com/927103): Run on an external monitor if one is
80            # present.
81            if not display_facade.has_internal_display():
82                logging.info('Skipping test: platform has no internal display')
83                return
84
85            self.set_rotation_to_zero(display_facade)
86
87            cr.browser.platform.SetHTTPServerDirectories(self.bindir)
88
89            tab = cr.browser.tabs[0]
90            tab.Navigate(cr.browser.platform.http_server.UrlOf(
91                    os.path.join(self.bindir, html_file)))
92            tab.WaitForDocumentReadyStateToBeComplete()
93
94            if data_file_url:
95                tab.EvaluateJavaScript('load_data_url("%s")' % data_file_url)
96
97            # Draw something; this also triggers JS parsing and execution.
98            tab.EvaluateJavaScript('draw_pass()')
99
100            # Wait until a few passes have been drawn, then read the amount of
101            # overlays.
102            utils.poll_for_condition(
103                    lambda: tab.EvaluateJavaScript('get_draw_passes_count()') >
104                            self.PREAMBLE_TOTAL_NUMBER_OF_DRAW_PASSES,
105                    exception=error.TestFail('JS is not drawing (preamble)'),
106                    timeout=self.PREAMBLE_TIMEOUT_SECONDS,
107                    sleep_interval=self.POLLING_INTERVAL_SECONDS)
108
109            num_overlays = 0;
110            try:
111                num_overlays = graphics_utils.get_num_hardware_overlays()
112                logging.debug('Found %s overlays', num_overlays)
113            except Exception as e:
114                logging.error(e)
115                raise error.TestFail('Error: %s' % str(e))
116
117            utils.poll_for_condition(
118                    lambda: tab.EvaluateJavaScript('get_draw_passes_count()') >
119                            self.EPILOG_TOTAL_NUMBER_OF_DRAW_PASSES,
120                    exception=error.TestFail('JS is not drawing (epilog)'),
121                    timeout=self.EPILOG_TIMEOUT_SECONDS,
122                    sleep_interval=self.POLLING_INTERVAL_SECONDS)
123
124            if (num_overlays <= 1):
125                raise error.TestFail('%s failed, number of overlays is %d' %
126                        (html_file, num_overlays))
127