# Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging import os from autotest_lib.client.bin import utils from autotest_lib.client.common_lib import error from autotest_lib.client.cros import chrome_binary_test from autotest_lib.client.cros.graphics import graphics_utils from autotest_lib.client.common_lib.cros import chrome from autotest_lib.client.cros import constants from autotest_lib.client.cros.multimedia import display_facade_native from autotest_lib.client.cros.multimedia import facade_resource EXTRA_BROWSER_ARGS = ['--enable-experimental-web-platform-features', '--force-tablet-mode=clamshell'] class graphics_HwOverlays(graphics_utils.GraphicsTest, chrome_binary_test.ChromeBinaryTest): """Runs a given html and measures stuff.""" version = 1 # The tests are essentially composed of a preamble and an epilog, in between # which we count the amount of overlays. Each of those essentially waits # until either a total number of items is drawn, or there's a timeout. PREAMBLE_TOTAL_NUMBER_OF_DRAW_PASSES = 5 PREAMBLE_TIMEOUT_SECONDS = 10 EPILOG_TOTAL_NUMBER_OF_DRAW_PASSES = 10 EPILOG_TIMEOUT_SECONDS = 10 POLLING_INTERVAL_SECONDS = 1 def initialize(self): super(graphics_HwOverlays, self).initialize() def cleanup(self): super(graphics_HwOverlays, self).cleanup() def set_rotation_to_zero(self, display_facade): # Set rotation to 0 (portrait) otherwise tablet platforms might not get # overlays. internal_display_id = display_facade.get_internal_display_id() logging.info("Internal display ID is %s", internal_display_id) display_facade.set_display_rotation(internal_display_id, rotation=0) def run_once(self, html_file, data_file_url = None, is_video = False, use_skia_renderer = False): """Normalizes the environment, starts a Chrome environment, and executes the test in `html_file`. """ if not graphics_utils.is_drm_atomic_supported(): logging.info('Skipping test: platform does not support DRM atomic') return if graphics_utils.get_max_num_available_drm_planes() <= 2: logging.info('Skipping test: platform supports 2 or less planes') return if is_video and not graphics_utils.is_nv12_supported_by_drm_planes(): logging.info('Skipping test: platform does not support NV12 planes') return extra_browser_args = EXTRA_BROWSER_ARGS if use_skia_renderer: # TODO(andrescj): remove when SkiaRenderer is enabled by default. extra_browser_args.append('--enable-features=UseSkiaRenderer') logging.info('Starting test, navigating to %s', html_file) with chrome.Chrome(extra_browser_args=extra_browser_args, extension_paths=[constants.DISPLAY_TEST_EXTENSION], autotest_ext=True, init_network_controller=True) as cr: facade = facade_resource.FacadeResource(cr) display_facade = display_facade_native.DisplayFacadeNative(facade) # TODO(crbug.com/927103): Run on an external monitor if one is # present. if not display_facade.has_internal_display(): logging.info('Skipping test: platform has no internal display') return self.set_rotation_to_zero(display_facade) cr.browser.platform.SetHTTPServerDirectories(self.bindir) tab = cr.browser.tabs[0] tab.Navigate(cr.browser.platform.http_server.UrlOf( os.path.join(self.bindir, html_file))) tab.WaitForDocumentReadyStateToBeComplete() if data_file_url: tab.EvaluateJavaScript('load_data_url("%s")' % data_file_url) # Draw something; this also triggers JS parsing and execution. tab.EvaluateJavaScript('draw_pass()') # Wait until a few passes have been drawn, then read the amount of # overlays. utils.poll_for_condition( lambda: tab.EvaluateJavaScript('get_draw_passes_count()') > self.PREAMBLE_TOTAL_NUMBER_OF_DRAW_PASSES, exception=error.TestFail('JS is not drawing (preamble)'), timeout=self.PREAMBLE_TIMEOUT_SECONDS, sleep_interval=self.POLLING_INTERVAL_SECONDS) num_overlays = 0; try: num_overlays = graphics_utils.get_num_hardware_overlays() logging.debug('Found %s overlays', num_overlays) except Exception as e: logging.error(e) raise error.TestFail('Error: %s' % str(e)) utils.poll_for_condition( lambda: tab.EvaluateJavaScript('get_draw_passes_count()') > self.EPILOG_TOTAL_NUMBER_OF_DRAW_PASSES, exception=error.TestFail('JS is not drawing (epilog)'), timeout=self.EPILOG_TIMEOUT_SECONDS, sleep_interval=self.POLLING_INTERVAL_SECONDS) if (num_overlays <= 1): raise error.TestFail('%s failed, number of overlays is %d' % (html_file, num_overlays))