1# Lint as: python2, python3 2# Copyright 2018 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import logging 7import os 8 9from autotest_lib.client.bin import utils 10from autotest_lib.client.common_lib import error 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 as display_facade_lib 15from autotest_lib.client.cros.multimedia import facade_resource 16 17EXTRA_BROWSER_ARGS = ['--enable-experimental-web-platform-features', 18 '--force-tablet-mode=clamshell'] 19 20 21class graphics_HwOverlays(graphics_utils.GraphicsTest): 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, 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 raise error.TestNAError( 56 'Skipping test: platform does not support DRM atomic') 57 58 if graphics_utils.get_max_num_available_drm_planes() <= 2: 59 raise error.TestNAError( 60 'Skipping test: platform supports 2 or less planes') 61 62 is_video = "video" in html_file 63 if is_video and not graphics_utils.is_nv12_supported_by_drm_planes(): 64 raise error.TestNAError( 65 'Skipping test: platform does not support NV12 planes') 66 67 extra_browser_args = EXTRA_BROWSER_ARGS 68 if use_skia_renderer: 69 # TODO(andrescj): remove when SkiaRenderer is enabled by default. 70 extra_browser_args.append('--enable-features=UseSkiaRenderer') 71 72 logging.info('Starting test, navigating to %s', html_file) 73 74 with chrome.Chrome(extra_browser_args=extra_browser_args, 75 extension_paths=[constants.DISPLAY_TEST_EXTENSION], 76 autotest_ext=True, 77 init_network_controller=True) as cr: 78 facade = facade_resource.FacadeResource(cr) 79 display_facade = display_facade_lib.DisplayFacadeLocal(facade) 80 # TODO(crbug.com/927103): Run on an external monitor if one is 81 # present. 82 if not display_facade.has_internal_display(): 83 raise error.TestNAError( 84 'Skipping test: platform has no internal display') 85 86 self.set_rotation_to_zero(display_facade) 87 88 cr.browser.platform.SetHTTPServerDirectories(self.bindir) 89 90 tab = cr.browser.tabs[0] 91 tab.Navigate(cr.browser.platform.http_server.UrlOf( 92 os.path.join(self.bindir, html_file))) 93 tab.WaitForDocumentReadyStateToBeComplete() 94 95 if data_file_url: 96 tab.EvaluateJavaScript('load_data_url("%s")' % data_file_url) 97 98 # Draw something; this also triggers JS parsing and execution. 99 tab.EvaluateJavaScript('draw_pass()') 100 101 # Wait until a few passes have been drawn, then read the amount of 102 # overlays. 103 utils.poll_for_condition( 104 lambda: tab.EvaluateJavaScript('get_draw_passes_count()') > 105 self.PREAMBLE_TOTAL_NUMBER_OF_DRAW_PASSES, 106 exception=error.TestFail('JS is not drawing (preamble)'), 107 timeout=self.PREAMBLE_TIMEOUT_SECONDS, 108 sleep_interval=self.POLLING_INTERVAL_SECONDS) 109 110 num_overlays = 0; 111 try: 112 num_overlays = graphics_utils.get_num_hardware_overlays() 113 logging.debug('Found %s overlays', num_overlays) 114 except Exception as e: 115 logging.error(e) 116 raise error.TestFail('Error: %s' % str(e)) 117 118 utils.poll_for_condition( 119 lambda: tab.EvaluateJavaScript('get_draw_passes_count()') > 120 self.EPILOG_TOTAL_NUMBER_OF_DRAW_PASSES, 121 exception=error.TestFail('JS is not drawing (epilog)'), 122 timeout=self.EPILOG_TIMEOUT_SECONDS, 123 sleep_interval=self.POLLING_INTERVAL_SECONDS) 124 125 if (num_overlays <= 1): 126 raise error.TestFail('%s failed, number of overlays is %d' % 127 (html_file, num_overlays)) 128