| # Copyright 2016 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # This is more akin to a .pyl/JSON file, so it's expected to be long. |
| # pylint: disable=too-many-lines |
| |
| from collections.abc import Callable |
| from enum import Enum |
| import json |
| import logging |
| import os |
| import posixpath |
| import time |
| import urllib.parse |
| |
| from telemetry.internal.browser import browser as browser_module |
| |
| import gpu_path_util |
| from gpu_tests import common_browser_args as cba |
| from gpu_tests import crop_actions as ca |
| from gpu_tests import overlay_support |
| from gpu_tests import skia_gold_heartbeat_integration_test_base as sghitb |
| from gpu_tests import skia_gold_matching_algorithms as algo |
| from gpu_tests.util import websocket_server as wss |
| |
| CRASH_TYPE_BROWSER = 'browser' |
| CRASH_TYPE_GPU = 'gpu-process' |
| CRASH_TYPE_RENDERER = 'renderer' |
| |
| EXPECTED_CRASHES_PLATFORM_DEFAULT = '' |
| EXPECTED_CRASHES_PLATFORM_FUCHSIA = 'fuchsia' |
| |
| SHORT_GLOBAL_TIMEOUT = 30 |
| |
| # Meant to be used when we know a test is going to be noisy, and we want any |
| # images it generates to be auto-triaged until we have enough data to calculate |
| # more suitable/less permissive parameters. |
| VERY_PERMISSIVE_SOBEL_ALGO = algo.SobelMatchingAlgorithm( |
| max_different_pixels=100000000, |
| pixel_delta_threshold=255, |
| edge_threshold=0, |
| ignored_border_thickness=1) |
| |
| # The optimizer script spat out pretty similar values for most MP4 tests, so |
| # combine into a single set of parameters. |
| GENERAL_MP4_ALGO = algo.SobelMatchingAlgorithm( |
| max_different_pixels=56300, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=80, |
| ignored_border_thickness=1) |
| |
| ROUNDING_ERROR_ALGO = algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=100000000, pixel_per_channel_delta_threshold=1) |
| |
| BrowserArgType = list[str] |
| |
| |
| def DoNotCaptureFullScreenshot(_) -> bool: |
| return False |
| |
| |
| def DoNotRequireFullscreenOsScreenshot() -> bool: |
| return False |
| |
| |
| class PixelTestPage(sghitb.SkiaGoldHeartbeatTestCase): |
| """A wrapper class mimicking the functionality of the PixelTestsStorySet |
| from the old-style GPU tests. |
| """ |
| |
| def __init__( # pylint: disable=too-many-arguments |
| self, |
| url: str, |
| name: str, |
| *args, |
| crop_action: ca.BaseCropAction | None = None, |
| browser_args: BrowserArgType | None = None, |
| restart_browser_after_test: bool = False, |
| other_args: dict | None = None, |
| expected_per_process_crashes: dict[str, dict[str, int]] | None = None, |
| timeout: int = 300, |
| should_capture_full_screenshot_func: Callable[[browser_module.Browser], |
| bool] | None = None, |
| requires_fullscreen_os_screenshot_func: Callable[[], bool] | None = None, |
| known_flaky_output_test: bool = False, |
| **kwargs): |
| # Video tests can result in non-hermetic test behavior due to overlays, so |
| # do a full refresh after each one. See crbug.com/1484212. |
| is_video_test = 'video' in name.lower() |
| super().__init__(name, refresh_after_finish=is_video_test, *args, **kwargs) |
| self.url = url |
| self.crop_action = crop_action |
| self.browser_args = browser_args |
| # Whether the browser should be forcibly restarted after the test |
| # runs. The browser is always restarted after running tests with |
| # optional_actions. |
| self.restart_browser_after_test = restart_browser_after_test |
| # These are used to pass additional arguments to the test harness. |
| # VideoPathTraceTest and OverlayModeTest support the following boolean |
| # arguments: pixel_format, zero_copy, no_overlay, video_is_rotated and |
| # full_size. |
| self.other_args = other_args |
| # This lets the test runner know that one or more crashes are expected as |
| # part of the test. Should be a map of platform name (str) to a map of |
| # process type (str) to crashes (int) |
| self.expected_per_process_crashes = expected_per_process_crashes or {} |
| # Test timeout |
| self.timeout = timeout |
| # Most tests will use the standard capture code path which captures an image |
| # that is more representative of what is shown to a user, but some tests |
| # require capturing the entire web contents for some reason. |
| if should_capture_full_screenshot_func is None: |
| should_capture_full_screenshot_func = DoNotCaptureFullScreenshot |
| self.ShouldCaptureFullScreenshot = should_capture_full_screenshot_func |
| # Some tests may require to capture a full OS screenshot to exercise |
| # end-to-end integration. That is, such browsers as LaCros do delegated |
| # compositing and they are interested in comparing the result produced |
| # by the OS compositor rather than Chromium's one. |
| if requires_fullscreen_os_screenshot_func is None: |
| requires_fullscreen_os_screenshot_func = ( |
| DoNotRequireFullscreenOsScreenshot) |
| self.RequiresFullScreenOSScreenshot = requires_fullscreen_os_screenshot_func |
| # Some tests are known to produce flaky output that cannot be handled with |
| # inexact matching without relaxing comparison parameters so much that |
| # regressions could make it in. Such tests are allowed to potentially run |
| # multiple times so that inexact matching with stricter parameters can |
| # match. |
| self.known_flaky_output_test = known_flaky_output_test |
| |
| # pytype: disable=signature-mismatch |
| |
| class TestActionCrashGpuProcess(sghitb.TestAction): |
| """Runs JavaScript to crash the GPU process once.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| sghitb.EvalInTestIframe(tab_data.tab, |
| 'chrome.gpuBenchmarking.crashGpuProcess()') |
| |
| |
| class TestActionSwitchTabs(sghitb.TestAction): |
| """Opens and briefly switches to a new tab before switching back.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| if not tab.browser.supports_tab_control: |
| test_instance.fail('Browser must support tab control') |
| dummy_tab = tab.browser.tabs.New() |
| dummy_tab.Activate() |
| # Wait for 2 seconds so that the new tab becomes visible. |
| dummy_tab.action_runner.Wait(2) |
| tab.Activate() |
| |
| |
| class TestActionSwitchTabsAndCopyImage(sghitb.TestAction): |
| """Opens and closes a new tab before running test-specific JavaScript.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| if not tab.browser.supports_tab_control: |
| test_instance.fail('Browser must support tab control') |
| dummy_tab = tab.browser.tabs.New() |
| dummy_tab.Activate() |
| # Wait for 2 seconds so that the new tab becomes visible. |
| dummy_tab.action_runner.Wait(2) |
| dummy_tab.Close() |
| sghitb.EvalInTestIframe(tab, 'copyImage()') |
| |
| |
| class TestActionSleepBeforeRender(sghitb.TestAction): |
| """Wait for 2 seconds before webgpu rendering.""" |
| |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| time.sleep(2) |
| sghitb.EvalInTestIframe(tab, 'render()') |
| |
| |
| class TestActionRunOffscreenCanvasIBRCWebGLLowPerfTest(sghitb.TestAction): |
| """Runs steps for an offscreen canvas IBRC WebGL test on the low power GPU.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| test_instance.AssertLowPowerGPU() |
| sghitb.EvalInTestIframe(tab, 'setup()') |
| # Wait a few seconds for any (incorrect) GPU switched notifications to |
| # propagate throughout the system. |
| time.sleep(5) |
| test_instance.AssertLowPowerGPU() |
| sghitb.EvalInTestIframe(tab, 'render()') |
| |
| |
| class TestActionRunOffscreenCanvasIBRCWebGLHighPerfTest(sghitb.TestAction): |
| """Runs steps for an offscreen canvas IBRC WebGL test on the high perf GPU.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| test_instance.AssertLowPowerGPU() |
| sghitb.EvalInTestIframe(tab, 'setup(true)') |
| # Wait a few seconds for any (incorrect) GPU switched notifications to |
| # propagate throughout the system. |
| time.sleep(5) |
| test_instance.AssertHighPerformanceGPU() |
| sghitb.EvalInTestIframe(tab, 'render()') |
| |
| |
| class TestActionRunTestWithHighPerformanceTab(sghitb.TestAction): |
| """Runs steps for a specific test with a high perf second tab present.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| tab = tab_data.tab |
| if not test_instance.IsDualGPUMacLaptop(): |
| # Short-circuit this test. |
| logging.info('Short-circuiting test because not running on dual-GPU Mac ' |
| 'laptop') |
| sghitb.EvalInTestIframe(tab, 'initialize(false)') |
| return |
| |
| high_performance_tab = tab.browser.tabs.New() |
| high_performance_file = posixpath.join( |
| gpu_path_util.GPU_DATA_RELATIVE_PATH, |
| 'functional_webgl_high_performance.html') |
| high_performance_websocket_server = wss.WebsocketServer() |
| high_performance_websocket_server.StartServer() |
| high_performance_tab_data = sghitb.TabData( |
| high_performance_tab, high_performance_websocket_server) |
| high_performance_loop_state = sghitb.LoopState() |
| try: |
| test_instance.NavigateTo(high_performance_file, |
| tab_data=high_performance_tab_data) |
| test_instance.HandleMessageLoop(SHORT_GLOBAL_TIMEOUT, |
| loop_state=high_performance_loop_state, |
| tab_data=high_performance_tab_data) |
| assert high_performance_loop_state.test_finished |
| |
| # Wait a few seconds for the GPU switched notification to propagate |
| # throughout the system. |
| time.sleep(5) |
| # Switch back to the main tab and quickly start its rendering, while the |
| # high-power GPU is still active. |
| tab.Activate() |
| sghitb.EvalInTestIframe(tab, 'initialize(true)') |
| test_instance.HandleMessageLoop(SHORT_GLOBAL_TIMEOUT, |
| loop_state=loop_state, |
| tab_data=tab_data) |
| high_performance_tab.Close() |
| finally: |
| high_performance_websocket_server.StopServer() |
| # Wait for ~15 seconds for the system to switch back to the |
| # integrated GPU. |
| time.sleep(15) |
| # Run the page to completion. |
| sghitb.EvalInTestIframe(tab, 'setTimeout(runToCompletion, 0)') |
| |
| |
| class TestActionRunLowToHighPowerTest(sghitb.TestAction): |
| """Runs steps for the low to high power GPU transition test.""" |
| def Run(self, test_case: PixelTestPage, tab_data: sghitb.TabData, |
| loop_state: sghitb.LoopState, |
| test_instance: sghitb.SkiaGoldHeartbeatIntegrationTestBase) -> None: |
| is_dual_gpu = test_instance.IsDualGPUMacLaptop() |
| sghitb.EvalInTestIframe(tab_data.tab, |
| f'initialize({json.dumps(is_dual_gpu)})') |
| # pytype: enable=signature-mismatch |
| |
| |
| def GetMediaStreamTestBrowserArgs( |
| media_stream_source_relpath: str) -> list[str]: |
| return [ |
| '--use-fake-device-for-media-stream', '--use-fake-ui-for-media-stream', |
| '--use-file-for-fake-video-capture=' + |
| os.path.join(gpu_path_util.CHROMIUM_SRC_DIR, media_stream_source_relpath) |
| ] |
| |
| |
| def RequiresFullScreenOSScreenshot() -> bool: |
| return True |
| |
| |
| def CaptureFullScreenshotOnFuchsia(browser: browser_module.Browser) -> bool: |
| return browser.platform.GetOSName() == 'fuchsia' |
| |
| |
| class PixelTestPages(): |
| @staticmethod |
| def DefaultPages(base_name: str) -> list[PixelTestPage]: |
| sw_compositing_args = [cba.DISABLE_GPU_COMPOSITING] |
| experimental_hdr_args = [cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES] |
| |
| switch_tab_test_actions = [ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionSwitchTabs(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ] |
| |
| low_power_test_actions = [ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionRunOffscreenCanvasIBRCWebGLLowPerfTest(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ] |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| |
| return [ |
| PixelTestPage( |
| 'pixel_background_image.html', |
| base_name + '_BackgroundImage', |
| crop_action=ca.FixedRectCropAction(20, 20, 370, 370), |
| # Small Fuchsia screens result in an incomplete capture |
| # without this. |
| should_capture_full_screenshot_func=CaptureFullScreenshotOnFuchsia, |
| matching_algorithm=ROUNDING_ERROR_ALGO), |
| PixelTestPage('pixel_reflected_div.html', |
| base_name + '_ReflectedDiv', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBox', |
| crop_action=standard_crop, |
| matching_algorithm=algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=130, |
| pixel_per_channel_delta_threshold=2)), |
| PixelTestPage('pixel_canvas2d_blit.html', |
| base_name + '_Canvas2DBlitText', |
| crop_action=ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 1000, 300)), |
| matching_algorithm=algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=5, |
| pixel_per_channel_delta_threshold=2)), |
| PixelTestPage('pixel_canvas2d_untagged.html', |
| base_name + '_Canvas2DUntagged', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_css3d.html', |
| base_name + '_CSS3DBlueBox', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=0, |
| pixel_delta_threshold=0, |
| edge_threshold=90)), |
| PixelTestPage('pixel_webgl_aa_alpha.html', |
| base_name + '_WebGLGreenTriangle_AA_Alpha', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_noaa_alpha.html', |
| base_name + '_WebGLGreenTriangle_NoAA_Alpha', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_aa_noalpha.html', |
| base_name + '_WebGLGreenTriangle_AA_NoAlpha', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_noaa_noalpha.html', |
| base_name + '_WebGLGreenTriangle_NoAA_NoAlpha', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_noalpha_implicit_clear.html', |
| base_name + |
| '_WebGLTransparentGreenTriangle_NoAlpha_ImplicitClear', |
| crop_action=standard_crop), |
| PixelTestPage( |
| 'pixel_webgl_context_restored.html', |
| base_name + '_WebGLContextRestored', |
| crop_action=standard_crop, |
| test_actions=[ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionCrashGpuProcess(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ], |
| expected_per_process_crashes={ |
| # Fuchsia is special cased due to the way it checks for crashes |
| # (asking the browser) vs. how other platforms handle it |
| # (looking for minidumps). The method for crashing the GPU |
| # process in this test is recorded as a crash but does not |
| # generate a minidump. |
| EXPECTED_CRASHES_PLATFORM_FUCHSIA: { |
| CRASH_TYPE_GPU: 1, |
| }, |
| }), |
| PixelTestPage( |
| 'pixel_webgl_sad_canvas.html', |
| base_name + '_WebGLSadCanvas', |
| crop_action=standard_crop, |
| test_actions=[ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionCrashGpuProcess(), |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionCrashGpuProcess(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ], |
| expected_per_process_crashes={ |
| # Fuchsia is special cased due to the way it checks for crashes |
| # (asking the browser) vs. how other platforms handle it |
| # (looking for minidumps). The method for crashing the GPU |
| # process in this test is recorded as a crash but does not |
| # generate a minidump. |
| EXPECTED_CRASHES_PLATFORM_FUCHSIA: { |
| CRASH_TYPE_GPU: 2, |
| }, |
| }), |
| PixelTestPage('pixel_scissor.html', |
| base_name + '_ScissorTestWithPreserveDrawingBuffer', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas2d_webgl.html', |
| base_name + '_2DCanvasWebGL', |
| crop_action=standard_crop), |
| PixelTestPage( |
| 'pixel_background.html', |
| base_name + '_SolidColorBackground', |
| crop_action=ca.FixedRectCropAction(500, 500, 600, 600), |
| # Small Fuchsia screens result in an incomplete capture |
| # without this. |
| should_capture_full_screenshot_func=CaptureFullScreenshotOnFuchsia), |
| PixelTestPage( |
| 'pixel_video_mp4.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_MP4', |
| crop_action=standard_crop, |
| # Most images are actually very similar, but Pixel 2 |
| # tends to produce images with all colors shifted by a |
| # small amount. |
| matching_algorithm=GENERAL_MP4_ALGO), |
| PixelTestPage( |
| 'pixel_video_mp4_four_colors_aspect_4x3.html' |
| '?width=240&height=135&use_timer=1', |
| base_name + '_Video_MP4_FourColors_Aspect_4x3', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=41700, |
| pixel_per_channel_delta_threshold=5, |
| edge_threshold=40, |
| ignored_border_thickness=1)), |
| PixelTestPage( |
| 'pixel_video_mp4_four_colors_rot_90.html' |
| '?width=270&height=240&use_timer=1', |
| base_name + '_Video_MP4_FourColors_Rot_90', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO), |
| PixelTestPage( |
| 'pixel_video_mp4_four_colors_rot_180.html' |
| '?width=240&height=135&use_timer=1', |
| base_name + '_Video_MP4_FourColors_Rot_180', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO), |
| PixelTestPage( |
| 'pixel_video_mp4_four_colors_rot_270.htm' |
| 'l?width=270&height=240&use_timer=1', |
| base_name + '_Video_MP4_FourColors_Rot_270', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO), |
| PixelTestPage( |
| 'pixel_video_mp4_rounded_corner.html' |
| '?width=240&height=135&use_timer=1', |
| base_name + '_Video_MP4_Rounded_Corner', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=30500, |
| pixel_per_channel_delta_threshold=5, |
| edge_threshold=70, |
| ignored_border_thickness=1)), |
| PixelTestPage('pixel_video_vp9.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_VP9', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=114000, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=20, |
| ignored_border_thickness=1)), |
| PixelTestPage('pixel_video_av1.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_AV1', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=114000, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=20, |
| ignored_border_thickness=1)), |
| PixelTestPage('pixel_video_hevc.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_HEVC', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=114000, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=20, |
| ignored_border_thickness=1)), |
| PixelTestPage( |
| 'pixel_video_media_stream_incompatible_stride.html', |
| base_name + '_Video_Media_Stream_Incompatible_Stride', |
| browser_args=GetMediaStreamTestBrowserArgs( |
| 'media/test/data/four-colors-incompatible-stride.y4m'), |
| crop_action=standard_crop, |
| matching_algorithm=VERY_PERMISSIVE_SOBEL_ALGO), |
| |
| # The MP4 contains H.264 which is primarily hardware decoded on bots. |
| PixelTestPage( |
| 'pixel_video_context_loss.html?src=' |
| '/media/test/data/four-colors.mp4', |
| base_name + '_Video_Context_Loss_MP4', |
| crop_action=standard_crop, |
| # Optimizer script spat out a value of 255 for the Sobel edge |
| # threshold, so use fuzzy for now since it's slightly more |
| # efficient. |
| matching_algorithm=algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=31700, |
| pixel_per_channel_delta_threshold=10), |
| expected_per_process_crashes={ |
| EXPECTED_CRASHES_PLATFORM_DEFAULT: { |
| CRASH_TYPE_GPU: 1, |
| }, |
| }, |
| restart_browser_after_test=True), |
| |
| # The VP9 test clip is primarily software decoded on bots. |
| PixelTestPage(('pixel_video_context_loss.html' |
| '?src=/media/test/data/four-colors-vp9.webm'), |
| base_name + '_Video_Context_Loss_VP9', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=54400, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=250, |
| ignored_border_thickness=1), |
| expected_per_process_crashes={ |
| EXPECTED_CRASHES_PLATFORM_DEFAULT: { |
| CRASH_TYPE_GPU: 1, |
| }, |
| }, |
| restart_browser_after_test=True), |
| PixelTestPage( |
| 'pixel_video_backdrop_filter.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_BackdropFilter', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=1000, |
| pixel_per_channel_delta_threshold=10, |
| edge_threshold=40, |
| ignored_border_thickness=1)), |
| PixelTestPage('pixel_webgl_premultiplied_alpha_false.html', |
| base_name + '_WebGL_PremultipliedAlpha_False', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl2_blitframebuffer_result_displayed.html', |
| base_name + '_WebGL2_BlitFramebuffer_Result_Displayed', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl2_clearbufferfv_result_displayed.html', |
| base_name + '_WebGL2_ClearBufferfv_Result_Displayed', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_repeated_webgl_to_2d.html', |
| base_name + '_RepeatedWebGLTo2D', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_repeated_webgl_to_2d.html', |
| base_name + '_RepeatedWebGLTo2D_SoftwareCompositing', |
| crop_action=standard_crop, |
| browser_args=sw_compositing_args), |
| PixelTestPage('pixel_canvas2d_tab_switch.html', |
| base_name + '_Canvas2DTabSwitch', |
| crop_action=standard_crop, |
| test_actions=switch_tab_test_actions), |
| PixelTestPage('pixel_canvas2d_tab_switch.html', |
| base_name + '_Canvas2DTabSwitch_SoftwareCompositing', |
| crop_action=standard_crop, |
| browser_args=sw_compositing_args, |
| test_actions=switch_tab_test_actions), |
| PixelTestPage('pixel_webgl_copy_image.html', |
| base_name + '_WebGLCopyImage', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_texture_from_webgl_readback.html', |
| base_name + '_WebGLTextureFromWebGLReadback', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_read_pixels_tab_switch.html', |
| base_name + '_WebGLReadPixelsTabSwitch', |
| crop_action=standard_crop, |
| test_actions=switch_tab_test_actions), |
| PixelTestPage('pixel_webgl_read_pixels_tab_switch.html', |
| base_name + |
| '_WebGLReadPixelsTabSwitch_SoftwareCompositing', |
| crop_action=standard_crop, |
| browser_args=sw_compositing_args, |
| test_actions=switch_tab_test_actions), |
| PixelTestPage('pixel_offscreen_canvas_ibrc_webgl_main.html', |
| base_name + '_OffscreenCanvasIBRCWebGLMain', |
| crop_action=standard_crop, |
| test_actions=low_power_test_actions), |
| PixelTestPage('pixel_offscreen_canvas_ibrc_webgl_worker.html', |
| base_name + '_OffscreenCanvasIBRCWebGLWorker', |
| crop_action=standard_crop, |
| test_actions=low_power_test_actions), |
| PixelTestPage( |
| 'pixel_webgl_preserved_after_tab_switch.html', |
| base_name + '_WebGLPreservedAfterTabSwitch', |
| crop_action=standard_crop, |
| test_actions=[ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionSwitchTabsAndCopyImage(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ]), |
| PixelTestPage('pixel_svg_huge.html', |
| base_name + '_SVGHuge', |
| crop_action=ca.FixedRectCropAction(0, 0, 400, 400), |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=0, |
| pixel_delta_threshold=0, |
| edge_threshold=90)), |
| PixelTestPage('pixel_webgl_display_p3.html', |
| base_name + '_WebGLDisplayP3', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_float.html', |
| base_name + '_WebGLFloat', |
| crop_action=standard_crop, |
| browser_args=experimental_hdr_args), |
| PixelTestPage('pixel_offscreenCanvas_ibrc_worker.html', |
| base_name + '_OffscreenCanvasIBRCWorker', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_webgl_resized_canvas.html', |
| base_name + '_WebglResizedCanvas', |
| crop_action=standard_crop), |
| PixelTestPage( |
| 'pixel_render_passes.html', |
| base_name + '_RenderPasses', |
| crop_action=ca.FixedRectCropAction(3, 90, 485, 245), |
| requires_fullscreen_os_screenshot_func=\ |
| RequiresFullScreenOSScreenshot |
| ), |
| PixelTestPage('pixel_view_transitions_capture.html', |
| base_name + '_ViewTransitionsCapture', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=0, |
| pixel_delta_threshold=0, |
| edge_threshold=90)), |
| PixelTestPage( |
| 'pixel_perspective_paint.html', |
| base_name + '_PerspectiveTest', |
| crop_action=ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 500, 300)), |
| ), |
| |
| # The following tests are a subset of the above, only that they |
| # run in TreesInViz mode, to make sure basic graphics features render |
| # correctly in this mode. They should be deleted once TreesInViz is |
| # turned on by default on GPU bots. |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBox' + '_TreesInViz', |
| crop_action=standard_crop, |
| matching_algorithm=algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=130, |
| pixel_per_channel_delta_threshold=2), |
| browser_args=['--enable-features=TreesInViz']), |
| PixelTestPage('pixel_css3d.html', |
| base_name + '_CSS3DBlueBox' + '_TreesInViz', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=0, |
| pixel_delta_threshold=0, |
| edge_threshold=90), |
| browser_args=['--enable-features=TreesInViz']), |
| PixelTestPage('pixel_webgl_aa_alpha.html', |
| base_name + '_WebGLGreenTriangle_AA_Alpha' + '_TreesInViz', |
| crop_action=standard_crop, |
| browser_args=['--enable-features=TreesInViz']), |
| PixelTestPage( |
| 'pixel_video_mp4.html?width=240&height=135&use_timer=1', |
| base_name + '_Video_MP4' + '_TreesInViz', |
| crop_action=standard_crop, |
| # Most images are actually very similar, but Pixel 2 |
| # tends to produce images with all colors shifted by a |
| # small amount. |
| matching_algorithm=GENERAL_MP4_ALGO, |
| browser_args=['--enable-features=TreesInViz']), |
| PixelTestPage('pixel_view_transitions_capture.html', |
| base_name + '_ViewTransitionsCapture' + '_TreesInViz', |
| crop_action=standard_crop, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=0, |
| pixel_delta_threshold=0, |
| edge_threshold=90), |
| browser_args=['--enable-features=TreesInViz']), |
| PixelTestPage('pixel_background.html', |
| base_name + '_SolidColorBackground' + '_TreesInViz', |
| crop_action=ca.FixedRectCropAction(500, 500, 600, 600), |
| # Small Fuchsia screens result in an incomplete capture |
| # without this. |
| should_capture_full_screenshot_func=( |
| CaptureFullScreenshotOnFuchsia), |
| browser_args=['--enable-features=TreesInViz']), |
| # TODO(crbug.com/431824747): Re-enable once the issue with TreesInViz |
| # capturing non-browser content is fixed. |
| # PixelTestPage('pixel_render_passes.html', |
| # base_name + '_RenderPasses' + '_TreesInViz', |
| # crop_action=ca.FixedRectCropAction(3, 90, 485, 245), |
| # requires_fullscreen_os_screenshot_func=\ |
| # RequiresFullScreenOSScreenshot, |
| # browser_args=['--enable-features=TreesInViz']), |
| ] |
| |
| @staticmethod |
| def WebGPUPages(base_name) -> list[PixelTestPage]: |
| |
| class Mode(Enum): |
| WEBGPU_DEFAULT = 0 |
| WEBGPU_SWIFTSHADER = 1 |
| VULKAN_SWIFTSHADER = 2 |
| |
| def webgpu_pages_helper(base_name, mode): |
| webgpu_args = [cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES] |
| video_frame_query_params = '?sourceType=hw_decoder' |
| if mode == Mode.WEBGPU_SWIFTSHADER: |
| base_name += '_WebGPUSwiftShader' |
| webgpu_args += [ |
| '--enable-features=Vulkan', '--use-webgpu-adapter=swiftshader' |
| ] |
| video_frame_query_params = '?sourceType=sw_decoder' |
| elif mode == Mode.VULKAN_SWIFTSHADER: |
| base_name += '_VulkanSwiftShader' |
| webgpu_args += [ |
| '--enable-features=Vulkan', '--use-angle=swiftshader', |
| '--use-vulkan=swiftshader', '--use-webgpu-adapter=swiftshader', |
| '--disable-vulkan-surface', '--enable-unsafe-webgpu' |
| ] |
| video_frame_query_params = '?sourceType=sw_decoder' |
| |
| # For most tests which have a few elements of interest. |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 500, 500)) |
| # For tests which don't have a white background to remove. In this case, |
| # we're effectively just making sure the color is correct. |
| fixed_crop = ca.FixedRectCropAction(0, 0, 300, 300) |
| |
| # For testing VideoFrame with HDR color space. |
| hdr_params = '?sourceType=hdr_canvas' |
| hdr_args = ['--enable-blink-features=CanvasHDR,WebCodecsHBDFormats'] |
| |
| return [ |
| PixelTestPage('pixel_webgpu_import_video_frame.html' + |
| video_frame_query_params, |
| base_name + '_WebGPUImportVideoFrame', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage( |
| 'pixel_webgpu_import_video_frame.html' + video_frame_query_params, |
| base_name + '_WebGPUImportVideoFrameUnaccelerated', |
| crop_action=standard_crop, |
| browser_args=webgpu_args + [cba.DISABLE_ACCELERATED_2D_CANVAS]), |
| PixelTestPage( |
| 'pixel_webgpu_import_video_frame_offscreen_canvas.html' + |
| video_frame_query_params, |
| base_name + '_WebGPUImportVideoFrameOffscreenCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage( |
| 'pixel_webgpu_import_video_frame_offscreen_canvas.html' + |
| video_frame_query_params, |
| base_name + '_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args + [cba.DISABLE_ACCELERATED_2D_CANVAS]), |
| PixelTestPage('pixel_webgpu_import_video_frame_hdr.html' + hdr_params, |
| base_name + '_WebGPUImportVideoFrameHDR', |
| crop_action=standard_crop, |
| browser_args=webgpu_args + hdr_args), |
| PixelTestPage('pixel_webgpu_webgl_teximage2d.html', |
| base_name + '_WebGPUWebGLTexImage2D', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_canvas2d_drawimage.html', |
| base_name + '_WebGPUCanvas2DDrawImage', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_texture_storage.html', |
| base_name + '_WebGPUCanvasTextureStorage', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_image.html', |
| base_name + '_WebGPUToDataURL', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_cached_swap_buffer_invalidated.html', |
| base_name + |
| '_WebGPUCachedSwapBufferInvalidatedShouldBeBlank', |
| crop_action=fixed_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_2d_canvas.html', |
| base_name + '_WebGPUCopyExternalImage2DCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_imageData.html', |
| base_name + '_WebGPUCopyExternalImageImageData', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_imageBitmap.html', |
| base_name + '_WebGPUCopyExternalImageImageBitmap', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_offscreenCanvas.html', |
| base_name + '_WebGPUCopyExternalImageOffscreenCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_webgl_canvas.html', |
| base_name + '_WebGPUCopyExternalImageWebGLCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_copy_externalImage_webgpu_canvas.html', |
| base_name + '_WebGPUCopyExternalImageWebGPUCanvas', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_display_p3.html', |
| base_name + '_WebGPUDisplayP3', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| PixelTestPage('pixel_webgpu_canvas_format_reinterpretation.html', |
| base_name + '_WebGPUCanvasFormatReinterpretation', |
| crop_action=standard_crop, |
| browser_args=webgpu_args), |
| ] |
| |
| return (webgpu_pages_helper(base_name, mode=Mode.WEBGPU_DEFAULT) + |
| webgpu_pages_helper(base_name, mode=Mode.WEBGPU_SWIFTSHADER) + |
| webgpu_pages_helper(base_name, mode=Mode.VULKAN_SWIFTSHADER)) |
| |
| @staticmethod |
| def WebGPUCanvasCapturePages(base_name) -> list[PixelTestPage]: |
| webgpu_args = [cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES] |
| |
| browser_args_canvas_one_copy_capture = webgpu_args + [ |
| '--enable-features=OneCopyCanvasCapture' |
| ] |
| other_args_canvas_one_copy_capture = {'one_copy': True} |
| |
| browser_args_canvas_disable_one_copy_capture = webgpu_args + [ |
| '--disable-features=OneCopyCanvasCapture' |
| ] |
| other_args_canvas_accelerated_two_copy = { |
| 'one_copy': False, |
| 'accelerated_two_copy': True |
| } |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 500, 500)) |
| |
| return [ |
| # Enabled OneCopyCapture |
| PixelTestPage('pixel_webgpu_canvas_capture_to_video.html', |
| base_name + '_WebGPUCanvasOneCopyCapture', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO, |
| browser_args=browser_args_canvas_one_copy_capture, |
| other_args=other_args_canvas_one_copy_capture), |
| PixelTestPage('pixel_webgpu_canvas_capture_to_video.html?hidden=true', |
| base_name + '_WebGPUCanvasOneCopyCapture_Hidden', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO, |
| browser_args=browser_args_canvas_one_copy_capture, |
| other_args=other_args_canvas_one_copy_capture), |
| # Disabled OneCopyCapture + canvas is opaque |
| PixelTestPage( |
| 'pixel_webgpu_canvas_capture_to_video.html?has_alpha=false', |
| base_name + '_WebGPUCanvasDisableOneCopyCapture_Accelerated', |
| crop_action=standard_crop, |
| matching_algorithm=GENERAL_MP4_ALGO, |
| browser_args=browser_args_canvas_disable_one_copy_capture, |
| other_args=other_args_canvas_accelerated_two_copy), |
| ] |
| |
| @staticmethod |
| def WebGPUDeviceDestroyPages(base_name) -> list[PixelTestPage]: |
| webgpu_args = [cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES] |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 320, 210)) |
| |
| offscreen_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 210, 210)) |
| |
| methods = [ |
| 'drawImage', 'toDataURL', 'toBlob', 'captureStream', |
| 'transferToImageBitmap', 'copyExternalImageToTexture', 'glTexImage2D' |
| ] |
| canvas_tyes = ['onscreen', 'offscreen', 'transferToOffscreen'] |
| |
| test_actions = [ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionSleepBeforeRender(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ] |
| |
| testPages = [] |
| for method in methods: |
| for canvas_type in canvas_tyes: |
| if method == 'toDataURL' and canvas_type != 'onscreen': |
| continue # toDataURL is only supported for onscreen canvas |
| if method == 'captureStream' and canvas_type != 'onscreen': |
| continue # only test captureStream for onscreen canvas |
| if method == 'transferToImageBitmap' and canvas_type == 'onscreen': |
| continue # transferToImageBitmap only works on OffScreenCanvas |
| |
| arguments = '?method=' + method + '&canvas=' + canvas_type |
| |
| canvas_type_name = canvas_type[0].upper() + canvas_type[1:] |
| method_name = method[0].upper() + method[1:] |
| test_name = canvas_type_name + 'Canvas' + '_' + method_name |
| |
| crop = standard_crop |
| if canvas_type == 'offscreen': |
| crop = offscreen_crop |
| |
| testPages.append( |
| PixelTestPage('pixel_destroyed_webgpu_canvas.html' + arguments, |
| base_name + '_WebGPUDestroyed_' + test_name, |
| crop_action=crop, |
| browser_args=webgpu_args, |
| test_actions=test_actions)) |
| |
| return testPages |
| |
| # Pages that should be run with GPU rasterization enabled. |
| @staticmethod |
| def GpuRasterizationPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [ |
| cba.ENABLE_GPU_RASTERIZATION, |
| cba.DISABLE_SOFTWARE_COMPOSITING_FALLBACK, |
| ] |
| |
| return [ |
| PixelTestPage('pixel_background.html', |
| base_name + '_GpuRasterization_BlueBox', |
| crop_action=ca.FixedRectCropAction(0, 0, 220, 220), |
| browser_args=browser_args), |
| PixelTestPage('concave_paths.html', |
| base_name + '_GpuRasterization_ConcavePaths', |
| crop_action=ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, None, 200)), |
| browser_args=browser_args), |
| PixelTestPage( |
| 'pixel_precision_rounded_corner.html', |
| base_name + '_PrecisionRoundedCorner', |
| # Entire image is typically too big to be captured fully via the |
| # default screenshot path, so continue to use the historical crop |
| # bounds which results in a small section of the rendered circle |
| # being captured. |
| crop_action=ca.FixedRectCropAction(0, 0, 400, 400), |
| browser_args=browser_args, |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=10, |
| pixel_per_channel_delta_threshold=15, |
| edge_threshold=100), |
| # Small Fuchsia screens result in an incomplete capture |
| # without this. |
| should_capture_full_screenshot_func=CaptureFullScreenshotOnFuchsia), |
| ] |
| |
| # Pages that should be run with off-thread paint worklet flags. |
| @staticmethod |
| def PaintWorkletPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [ |
| '--enable-blink-features=OffMainThreadCSSPaint', |
| '--enable-gpu-rasterization' |
| ] |
| |
| return [ |
| PixelTestPage('pixel_paintWorklet_transform.html', |
| base_name + '_PaintWorkletTransform', |
| crop_action=ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 200, 200)), |
| browser_args=browser_args), |
| ] |
| |
| # Pages that should be run with experimental canvas features. |
| @staticmethod |
| def ExperimentalCanvasFeaturesPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [ |
| cba.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES, |
| ] |
| accelerated_args = [ |
| cba.DISABLE_SOFTWARE_COMPOSITING_FALLBACK, |
| ] |
| unaccelerated_args = [ |
| cba.DISABLE_ACCELERATED_2D_CANVAS, |
| cba.DISABLE_GPU_COMPOSITING, |
| ] |
| unaccelerated_canvas_accelerated_compositing_args = [ |
| cba.DISABLE_ACCELERATED_2D_CANVAS, |
| cba.DISABLE_SOFTWARE_COMPOSITING_FALLBACK, |
| ] |
| |
| # The sRGB tests have been observed to create a large number |
| # (~15,000) of pixels with difference ~3. |
| srgb_fuzzy_algo = algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=20000, pixel_per_channel_delta_threshold=2) |
| |
| # Small number of differing pixels. May need to be upgraded to sobel in the |
| # future since there are a number of hard edges in the image. |
| offscreen_canvas_algo = algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=100, pixel_per_channel_delta_threshold=3) |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 400, 400)) |
| |
| return [ |
| PixelTestPage('pixel_offscreenCanvas_transfer_after_style_resize.html', |
| base_name + '_OffscreenCanvasTransferAfterStyleResize', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_transfer_before_style_resize.html', |
| base_name + '_OffscreenCanvasTransferBeforeStyleResize', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_webgl_paint_after_resize.html', |
| base_name + '_OffscreenCanvasWebGLPaintAfterResize', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_transferToImageBitmap_main.html', |
| base_name + '_OffscreenCanvasTransferToImageBitmap', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage( |
| 'pixel_offscreenCanvas_transferToImageBitmap_main.html', |
| base_name + |
| '_OffscreenCanvasTransferToImageBitmapSoftwareCompositing', |
| crop_action=standard_crop, |
| browser_args=browser_args + unaccelerated_args), |
| PixelTestPage('pixel_offscreenCanvas_transferToImageBitmap_worker.html', |
| base_name + '_OffscreenCanvasTransferToImageBitmapWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_webgl_commit_main.html', |
| base_name + '_OffscreenCanvasWebGLDefault', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_webgl_commit_worker.html', |
| base_name + '_OffscreenCanvasWebGLDefaultWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_webgl_commit_main.html', |
| base_name + '_OffscreenCanvasWebGLSoftwareCompositing', |
| crop_action=standard_crop, |
| browser_args=browser_args + |
| [cba.DISABLE_GPU_COMPOSITING]), |
| PixelTestPage( |
| 'pixel_offscreenCanvas_webgl_commit_worker.html', |
| base_name + '_OffscreenCanvasWebGLSoftwareCompositingWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args + [cba.DISABLE_GPU_COMPOSITING]), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_main.html', |
| base_name + '_OffscreenCanvasAccelerated2D', |
| crop_action=standard_crop, |
| browser_args=browser_args + accelerated_args, |
| matching_algorithm=offscreen_canvas_algo), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_worker.html', |
| base_name + '_OffscreenCanvasAccelerated2DWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args + accelerated_args, |
| matching_algorithm=offscreen_canvas_algo), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_main.html', |
| base_name + '_OffscreenCanvasUnaccelerated2D', |
| crop_action=standard_crop, |
| browser_args=browser_args + unaccelerated_args), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_worker.html', |
| base_name + '_OffscreenCanvasUnaccelerated2DWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args + unaccelerated_args), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_main.html', |
| base_name + |
| '_OffscreenCanvasUnaccelerated2DGPUCompositing', |
| crop_action=standard_crop, |
| browser_args=browser_args + |
| unaccelerated_canvas_accelerated_compositing_args), |
| PixelTestPage('pixel_offscreenCanvas_2d_commit_worker.html', |
| base_name + |
| '_OffscreenCanvasUnaccelerated2DGPUCompositingWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args + |
| unaccelerated_canvas_accelerated_compositing_args), |
| PixelTestPage('pixel_offscreenCanvas_2d_resize_on_worker.html', |
| base_name + '_OffscreenCanvas2DResizeOnWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_offscreenCanvas_webgl_resize_on_worker.html', |
| base_name + '_OffscreenCanvasWebglResizeOnWorker', |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_canvas_display_srgb.html', |
| base_name + '_CanvasDisplaySRGBAccelerated2D', |
| crop_action=standard_crop, |
| browser_args=browser_args + accelerated_args, |
| matching_algorithm=srgb_fuzzy_algo), |
| PixelTestPage('pixel_canvas_display_srgb.html', |
| base_name + '_CanvasDisplaySRGBUnaccelerated2D', |
| crop_action=standard_crop, |
| browser_args=browser_args + unaccelerated_args, |
| matching_algorithm=srgb_fuzzy_algo), |
| PixelTestPage( |
| 'pixel_canvas_display_srgb.html', |
| base_name + '_CanvasDisplaySRGBUnaccelerated2DGPUCompositing', |
| crop_action=standard_crop, |
| browser_args=browser_args + [cba.DISABLE_ACCELERATED_2D_CANVAS], |
| matching_algorithm=srgb_fuzzy_algo), |
| PixelTestPage('pixel_webgl_webcodecs_breakoutbox_displays_frame.html', |
| base_name + '_WebGLWebCodecsBreakoutBoxDisplaysFrame', |
| crop_action=standard_crop, |
| browser_args=browser_args) |
| ] |
| |
| @staticmethod |
| def LowLatencyPages(base_name: str) -> list[PixelTestPage]: |
| unaccelerated_args = [ |
| cba.DISABLE_ACCELERATED_2D_CANVAS, |
| cba.DISABLE_GPU_COMPOSITING, |
| ] |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 250, 250)) |
| |
| return [ |
| PixelTestPage('pixel_canvas_low_latency_2d.html', |
| base_name + '_CanvasLowLatency2D', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_2d.html', |
| base_name + '_CanvasUnacceleratedLowLatency2D', |
| crop_action=standard_crop, |
| browser_args=unaccelerated_args), |
| PixelTestPage('pixel_canvas_low_latency_webgl.html', |
| base_name + '_CanvasLowLatencyWebGL', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_webgl_alpha_false.html', |
| base_name + '_CanvasLowLatencyWebGLAlphaFalse', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_2d_draw_image.html', |
| base_name + '_CanvasLowLatency2DDrawImage', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_webgl_draw_image.html', |
| base_name + '_CanvasLowLatencyWebGLDrawImage', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_2d_image_data.html', |
| base_name + '_CanvasLowLatency2DImageData', |
| crop_action=standard_crop), |
| PixelTestPage('pixel_canvas_low_latency_webgl_rounded_corners.html', |
| base_name + '_CanvasLowLatencyWebGLRoundedCorners', |
| crop_action=standard_crop, |
| matching_algorithm=ROUNDING_ERROR_ALGO), |
| PixelTestPage('pixel_canvas_low_latency_webgl_occluded.html', |
| base_name + '_CanvasLowLatencyWebGLOccluded', |
| crop_action=standard_crop, |
| other_args={'no_overlay': True}), |
| ] |
| |
| # Only add these tests on platforms where SwiftShader is enabled. |
| # Currently this is Windows and Linux. |
| @staticmethod |
| def SwiftShaderPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [ |
| cba.DISABLE_GPU, '--enable-features=AllowSwiftShaderFallback', |
| '--disable-features=AllowD3D11WarpFallback' |
| ] |
| suffix = '_SwiftShader' |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| return [ |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_css3d.html', |
| base_name + '_CSS3DBlueBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_webgl_aa_alpha.html', |
| base_name + '_WebGLGreenTriangle_AA_Alpha' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_repeated_webgl_to_2d.html', |
| base_name + '_RepeatedWebGLTo2D' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| ] |
| |
| # Only add these tests on platforms where D3D11 WARP is enabled. |
| # Currently this is Windows. |
| @staticmethod |
| def WARPPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [ |
| cba.DISABLE_GPU, '--disable-features=AllowSwiftShaderFallback', |
| '--enable-features=AllowD3D11WarpFallback' |
| ] |
| suffix = '_WARP' |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| return [ |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_css3d.html', |
| base_name + '_CSS3DBlueBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_webgl_aa_alpha.html', |
| base_name + '_WebGLGreenTriangle_AA_Alpha' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| PixelTestPage('pixel_repeated_webgl_to_2d.html', |
| base_name + '_RepeatedWebGLTo2D' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args), |
| ] |
| |
| # Test rendering where GPU process is blocked. |
| @staticmethod |
| def NoGpuProcessPages(base_name: str) -> list[PixelTestPage]: |
| browser_args = [cba.DISABLE_GPU, cba.DISABLE_SOFTWARE_RASTERIZER] |
| suffix = '_NoGpuProcess' |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| return [ |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| gpu_process_disabled=True), |
| PixelTestPage('pixel_css3d.html', |
| base_name + '_CSS3DBlueBox' + suffix, |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| gpu_process_disabled=True), |
| ] |
| |
| # Pages that should be run with various macOS specific command line |
| # arguments. |
| @staticmethod |
| def MacSpecificPages(base_name: str) -> list[PixelTestPage]: |
| unaccelerated_2d_canvas_args = [cba.DISABLE_ACCELERATED_2D_CANVAS] |
| |
| non_chromium_image_args = ['--disable-webgl-image-chromium'] |
| |
| # This disables the Core Animation compositor, falling back to the |
| # old GLRenderer path, but continuing to allocate IOSurfaces for |
| # WebGL's back buffer. |
| no_overlays_args = ['--disable-features=CoreAnimationRenderer'] |
| |
| angle_gl = ['--use-angle=gl'] |
| |
| # The filter effect tests produce images with lots of gradients and blurs |
| # which don't play nicely with Sobel filters, so a fuzzy algorithm instead |
| # of Sobel. The images are also relatively large (360k pixels), and large |
| # portions of the image are prone to noise, hence the large max different |
| # pixels value. |
| filter_effect_fuzzy_algo = algo.FuzzyMatchingAlgorithm( |
| max_different_pixels=57500, pixel_per_channel_delta_threshold=10) |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| |
| # Use a fixed crop since the fuzziness of the image is liable to make the |
| # image size change randomly. |
| filter_effects_crop = ca.FixedRectCropAction(0, 0, 300, 300) |
| |
| return [ |
| PixelTestPage('pixel_canvas2d_webgl.html', |
| base_name + '_IOSurface2DCanvasWebGL', |
| crop_action=standard_crop), |
| |
| # On macOS, test WebGL non-Chromium Image compositing path. |
| PixelTestPage('pixel_webgl_aa_alpha.html', |
| base_name + |
| '_WebGLGreenTriangle_NonChromiumImage_AA_Alpha', |
| crop_action=standard_crop, |
| browser_args=non_chromium_image_args), |
| PixelTestPage('pixel_webgl_noaa_alpha.html', |
| base_name + |
| '_WebGLGreenTriangle_NonChromiumImage_NoAA_Alpha', |
| crop_action=standard_crop, |
| browser_args=non_chromium_image_args), |
| PixelTestPage('pixel_webgl_aa_noalpha.html', |
| base_name + |
| '_WebGLGreenTriangle_NonChromiumImage_AA_NoAlpha', |
| crop_action=standard_crop, |
| browser_args=non_chromium_image_args), |
| PixelTestPage('pixel_webgl_noaa_noalpha.html', |
| base_name + |
| '_WebGLGreenTriangle_NonChromiumImage_NoAA_NoAlpha', |
| crop_action=standard_crop, |
| browser_args=non_chromium_image_args), |
| |
| # On macOS, test CSS filter effects with and without the CA compositor. |
| PixelTestPage('filter_effects.html', |
| base_name + '_CSSFilterEffects', |
| crop_action=filter_effects_crop, |
| matching_algorithm=filter_effect_fuzzy_algo), |
| PixelTestPage('filter_effects.html', |
| base_name + '_CSSFilterEffects_NoOverlays', |
| crop_action=filter_effects_crop, |
| browser_args=no_overlays_args, |
| matching_algorithm=filter_effect_fuzzy_algo), |
| |
| # Test WebGL's premultipliedAlpha:false without the CA compositor. |
| PixelTestPage('pixel_webgl_premultiplied_alpha_false.html', |
| base_name + '_WebGL_PremultipliedAlpha_False_NoOverlays', |
| crop_action=standard_crop, |
| browser_args=no_overlays_args), |
| |
| # Test GpuBenchmarking::AddCoreAnimationStatusEventListener. |
| # Error code is 0 (gfx::kCALayerSuccess) when it succeeds. |
| # --enable-gpu-benchmarking is added by default and it's required to run |
| # this test. |
| PixelTestPage('core_animation_status_api.html?error=0', |
| base_name + '_CoreAnimationStatusApiNoError', |
| crop_action=standard_crop), |
| # Test GpuBenchmarking::AddCoreAnimationStatusEventListener. |
| # Error code is 32 (gfx::kCALayerFailedOverlayDisabled) when |
| # CoreAnimationRenderer is disabled. |
| # --enable-gpu-benchmarking is added by default and it's required to run |
| # this test. |
| PixelTestPage('core_animation_status_api.html?error=32', |
| base_name + '_CoreAnimationStatusApiWithError', |
| crop_action=standard_crop, |
| browser_args=no_overlays_args), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage('canvas_uses_overlay.html', |
| base_name + '_CanvasUsesOverlay', |
| crop_action=standard_crop), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage('canvas_uses_overlay.html', |
| base_name + '_UnacceleratedCanvasUsesOverlay', |
| crop_action=standard_crop, |
| browser_args=unaccelerated_2d_canvas_args), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage( |
| 'offscreencanvas_imagebitmap_from_worker_uses_overlay.html', |
| base_name + '_OffscreenCanvasImageBitmapWorkerUsesOverlay', |
| crop_action=standard_crop), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage( |
| 'offscreencanvas_imagebitmap_from_worker_uses_overlay.html', |
| base_name + |
| '_UnacceleratedOffscreenCanvasImageBitmapWorkerUsesOverlay', |
| crop_action=standard_crop, |
| browser_args=unaccelerated_2d_canvas_args), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage('offscreencanvas_imagebitmap_uses_overlay.html', |
| base_name + '_OffscreenCanvasImageBitmapUsesOverlay', |
| crop_action=standard_crop), |
| |
| # --enable-gpu-benchmarking is required to run this test. it's added to |
| # the pixel tests by default. |
| PixelTestPage('offscreencanvas_imagebitmap_uses_overlay.html', |
| base_name + |
| '_UnacceleratedOffscreenCanvasImageBitmapUsesOverlay', |
| crop_action=standard_crop, |
| browser_args=unaccelerated_2d_canvas_args), |
| |
| # Regression test for crbug.com/1410696 |
| PixelTestPage('pixel_offscreenCanvas_ibrc_worker.html', |
| base_name + '_OffscreenCanvasIBRCWorkerAngleGL', |
| crop_action=standard_crop, |
| browser_args=angle_gl), |
| ] |
| |
| # Pages that should be run only on dual-GPU MacBook Pros (at the |
| # present time, anyway). |
| @staticmethod |
| def DualGPUMacSpecificPages(base_name: str) -> list[PixelTestPage]: |
| |
| low_to_high_power_test_actions = [ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionRunLowToHighPowerTest(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ] |
| |
| high_perf_test_actions = [ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionRunOffscreenCanvasIBRCWebGLHighPerfTest(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ] |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 350, 350)) |
| |
| return [ |
| PixelTestPage( |
| 'pixel_webgl_high_to_low_power.html', |
| base_name + '_WebGLHighToLowPower', |
| crop_action=standard_crop, |
| test_actions=[ |
| sghitb.TestActionWaitForContinue(SHORT_GLOBAL_TIMEOUT), |
| TestActionRunTestWithHighPerformanceTab(), |
| sghitb.TestActionWaitForFinish(SHORT_GLOBAL_TIMEOUT), |
| ]), |
| PixelTestPage('pixel_webgl_low_to_high_power.html', |
| base_name + '_WebGLLowToHighPower', |
| crop_action=standard_crop, |
| test_actions=low_to_high_power_test_actions), |
| PixelTestPage('pixel_webgl_low_to_high_power_alpha_false.html', |
| base_name + '_WebGLLowToHighPowerAlphaFalse', |
| crop_action=standard_crop, |
| test_actions=low_to_high_power_test_actions), |
| PixelTestPage('pixel_offscreen_canvas_ibrc_webgl_main.html', |
| base_name + '_OffscreenCanvasIBRCWebGLHighPerfMain', |
| crop_action=standard_crop, |
| test_actions=high_perf_test_actions), |
| PixelTestPage('pixel_offscreen_canvas_ibrc_webgl_worker.html', |
| base_name + '_OffscreenCanvasIBRCWebGLHighPerfWorker', |
| crop_action=standard_crop, |
| test_actions=high_perf_test_actions), |
| ] |
| |
| # pylint: disable=too-many-locals |
| @staticmethod |
| def DirectCompositionPages(base_name: str, |
| swap_count: int | None = None |
| ) -> list[PixelTestPage]: |
| browser_args = [ |
| cba.ENABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS, |
| # All bots are connected with a power source, however, we want to to |
| # test with the code path that's enabled with battery power. |
| cba.DISABLE_DIRECT_COMPOSITION_VP_SCALING, |
| ] |
| browser_args_NV12 = browser_args + [ |
| '--direct-composition-video-swap-chain-format=nv12' |
| ] |
| browser_args_YUY2 = browser_args + [ |
| '--direct-composition-video-swap-chain-format=yuy2' |
| ] |
| browser_args_BGRA = browser_args + [ |
| '--direct-composition-video-swap-chain-format=bgra' |
| ] |
| browser_args_vp_scaling = [ |
| cba.ENABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS, |
| cba.ENABLE_DIRECT_COMPOSITION_VP_SCALING, |
| ] |
| browser_args_sw_decode = browser_args + [ |
| cba.DISABLE_ACCELERATED_VIDEO_DECODE |
| ] |
| |
| # 16 was the highest value set for any test before switching to allow |
| # configurable swap count. |
| swap_count = swap_count or 16 |
| swap_param = f'swaps={swap_count}' |
| |
| # Most tests fall roughly into 3 tiers of noisiness. |
| # Parameter values were determined using the automated optimization script, |
| # and similar values combined into a single set using the most permissive |
| # value for each parameter in that tier. |
| strict_dc_sobel_algorithm = algo.SobelMatchingAlgorithm( |
| max_different_pixels=2000, |
| pixel_per_channel_delta_threshold=3, |
| edge_threshold=250, |
| ignored_border_thickness=1) |
| permissive_dc_sobel_algorithm = algo.SobelMatchingAlgorithm( |
| max_different_pixels=16800, |
| pixel_per_channel_delta_threshold=10, |
| edge_threshold=30, |
| ignored_border_thickness=1) |
| very_permissive_dc_sobel_algorithm = algo.SobelMatchingAlgorithm( |
| max_different_pixels=30400, |
| pixel_per_channel_delta_threshold=20, |
| edge_threshold=10, |
| ignored_border_thickness=1, |
| ) |
| |
| h264 = overlay_support.ZeroCopyCodec.H264 |
| vp9 = overlay_support.ZeroCopyCodec.VP9 |
| |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 300, 300)) |
| mp4_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 600, 600)) |
| large_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 1000, 600)) |
| |
| MP4_FULLSIZE_WIDTH = 960 |
| MP4_FULLSIZE_HEIGHT = 540 |
| MP4_HALF_WIDTH = MP4_FULLSIZE_WIDTH / 2 |
| MP4_HALF_HEIGHT = MP4_FULLSIZE_HEIGHT / 2 |
| |
| return [ |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_HALF_WIDTH}&' |
| f'height={MP4_HALF_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4', |
| crop_action=mp4_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_FULLSIZE_WIDTH}&' |
| f'height={MP4_FULLSIZE_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4_Fullsize', |
| browser_args=browser_args, |
| other_args={ |
| 'full_size': True, |
| 'codec': h264, |
| }, |
| crop_action=large_crop, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_HALF_WIDTH}&' |
| f'height={MP4_HALF_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4_NV12', |
| crop_action=mp4_crop, |
| browser_args=browser_args_NV12, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.NV12, |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_HALF_WIDTH}&' |
| f'height={MP4_HALF_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4_YUY2', |
| crop_action=mp4_crop, |
| browser_args=browser_args_YUY2, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.YUY2, |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_FULLSIZE_WIDTH}&' |
| f'height={MP4_FULLSIZE_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4_BGRA', |
| crop_action=large_crop, |
| browser_args=browser_args_BGRA, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.BGRA8, |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width={MP4_HALF_WIDTH}&' |
| f'height={MP4_HALF_HEIGHT}&{swap_param}', |
| base_name + '_DirectComposition_Video_MP4_VP_SCALING', |
| crop_action=mp4_crop, |
| browser_args=browser_args_vp_scaling, |
| other_args={ |
| 'zero_copy': False, |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_mp4_four_colors_aspect_4x3.html?' |
| f'width={MP4_HALF_WIDTH}&height={MP4_HALF_HEIGHT}&{swap_param}'), |
| base_name + '_DirectComposition_Video_MP4_FourColors_Aspect_4x3', |
| crop_action=mp4_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_mp4_four_colors_rot_90.html?' |
| f'width={MP4_HALF_HEIGHT}&height={MP4_HALF_WIDTH}&{swap_param}'), |
| base_name + '_DirectComposition_Video_MP4_FourColors_Rot_90', |
| crop_action=mp4_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'video_rotation': overlay_support.VideoRotation.ROT90, |
| 'codec': h264, |
| }, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_mp4_four_colors_rot_180.html?' |
| f'width={MP4_HALF_WIDTH}&height={MP4_HALF_HEIGHT}&{swap_param}'), |
| base_name + '_DirectComposition_Video_MP4_FourColors_Rot_180', |
| crop_action=mp4_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'video_rotation': overlay_support.VideoRotation.ROT180, |
| 'codec': h264, |
| }, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_mp4_four_colors_rot_270.html?' |
| f'width={MP4_HALF_HEIGHT}&height={MP4_HALF_WIDTH}&{swap_param}'), |
| base_name + '_DirectComposition_Video_MP4_FourColors_Rot_270', |
| crop_action=mp4_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'video_rotation': overlay_support.VideoRotation.ROT270, |
| 'codec': h264, |
| }, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage(f'pixel_video_vp9.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9', |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'codec': vp9, |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| f'pixel_video_vp9.html?width=960&height=540&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9_Fullsize', |
| crop_action=large_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'full_size': True, |
| 'codec': vp9, |
| }, |
| # Much larger image than other VP9 tests. |
| matching_algorithm=algo.SobelMatchingAlgorithm( |
| max_different_pixels=504000, |
| pixel_per_channel_delta_threshold=5, |
| edge_threshold=10, |
| ignored_border_thickness=1, |
| )), |
| PixelTestPage(f'pixel_video_vp9.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9_NV12', |
| crop_action=standard_crop, |
| browser_args=browser_args_NV12, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.NV12, |
| 'codec': vp9, |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage(f'pixel_video_vp9.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9_YUY2', |
| crop_action=standard_crop, |
| browser_args=browser_args_YUY2, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.YUY2, |
| 'codec': vp9, |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage(f'pixel_video_vp9.html?width=960&height=540&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9_BGRA', |
| crop_action=large_crop, |
| browser_args=browser_args_BGRA, |
| other_args={ |
| 'pixel_format': overlay_support.PixelFormat.BGRA8, |
| 'codec': vp9 |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage((f'pixel_video_vp9_i420a.html?' |
| f'width=240&height=135&{swap_param}'), |
| base_name + '_DirectComposition_Video_VP9_I420A', |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'no_overlay': True, |
| 'codec': vp9 |
| }, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage(f'pixel_video_vp9.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_VP9_VP_SCALING', |
| crop_action=standard_crop, |
| browser_args=browser_args_vp_scaling, |
| other_args={ |
| 'zero_copy': False, |
| 'codec': vp9, |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_underlay.html?' |
| f'width=240&height=136&{swap_param}'), |
| base_name + '_DirectComposition_Underlay', |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| # Underlay zero copy usage seems to track H.264 zero copy |
| # support. |
| other_args={ |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| (f'pixel_video_underlay.html?' |
| f'width=960&height=540&{swap_param}'), |
| base_name + '_DirectComposition_Underlay_Fullsize', |
| crop_action=large_crop, |
| browser_args=browser_args, |
| # Underlay zero copy usage seems to track H.264 zero copy |
| # support. |
| other_args={ |
| 'full_size': True, |
| 'codec': h264, |
| }, |
| matching_algorithm=strict_dc_sobel_algorithm), |
| PixelTestPage((f'pixel_video_mp4_rounded_corner.html?' |
| f'width=240&height=135&{swap_param}'), |
| base_name + '_DirectComposition_Video_MP4_Rounded_Corner', |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'codec': h264, |
| }, |
| matching_algorithm=permissive_dc_sobel_algorithm), |
| PixelTestPage((f'pixel_video_backdrop_filter.html?' |
| f'width=240&height=135&{swap_param}'), |
| base_name + '_DirectComposition_Video_BackdropFilter', |
| crop_action=standard_crop, |
| browser_args=browser_args, |
| other_args={ |
| 'no_overlay': True, |
| }), |
| PixelTestPage( |
| f'pixel_video_mp4.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_Disable_Overlays', |
| crop_action=standard_crop, |
| browser_args=[cba.DISABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS], |
| other_args={'no_overlay': True}, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage(f'pixel_video_mp4.html?width=240&height=135&{swap_param}', |
| base_name + '_DirectComposition_Video_SW_Decode', |
| crop_action=standard_crop, |
| browser_args=browser_args_sw_decode, |
| other_args={ |
| 'zero_copy': False, |
| }, |
| matching_algorithm=very_permissive_dc_sobel_algorithm), |
| PixelTestPage( |
| 'pixel_media_foundation_clear_dcomp.html?src=' |
| '/media/test/data/four-colors.mp4', |
| base_name + '_MediaFoundationClearDirectComposition', |
| crop_action=standard_crop, |
| browser_args=[ |
| '--enable-features=MediaFoundationClearPlayback, \ |
| MediaFoundationClearRendering:strategy/direct-composition' |
| ], |
| matching_algorithm=VERY_PERMISSIVE_SOBEL_ALGO), |
| ] |
| |
| # pylint: enable=too-many-locals |
| |
| @staticmethod |
| def VideoFromCanvasPages(base_name: str) -> list[PixelTestPage]: |
| # Tests for <video> element rendering results of <canvas> capture. |
| # It's important for video conference software. |
| |
| match_algo = VERY_PERMISSIVE_SOBEL_ALGO |
| # Use shorter timeout since the tests are not supposed to be long. |
| timeout = 150 |
| standard_crop = ca.NonWhiteContentCropAction( |
| initial_crop=ca.FixedRectCropAction(0, 0, 250, 200)) |
| |
| return [ |
| PixelTestPage('pixel_video_from_canvas_2d.html', |
| base_name + '_VideoStreamFrom2DCanvas', |
| crop_action=standard_crop, |
| browser_args=[], |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| PixelTestPage('pixel_video_from_canvas_2d_alpha.html', |
| base_name + '_VideoStreamFrom2DAlphaCanvas', |
| crop_action=standard_crop, |
| browser_args=[], |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| PixelTestPage('pixel_video_from_canvas_webgl2_alpha.html', |
| base_name + '_VideoStreamFromWebGLAlphaCanvas', |
| crop_action=standard_crop, |
| browser_args=[], |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| PixelTestPage('pixel_video_from_canvas_webgl2.html', |
| base_name + '_VideoStreamFromWebGLCanvas', |
| crop_action=standard_crop, |
| browser_args=[], |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| |
| # Safeguard against repeating crbug.com/1371308 |
| PixelTestPage( |
| 'pixel_video_from_canvas_2d.html', |
| base_name + |
| '_VideoStreamFrom2DAlphaCanvas_DisableReadbackFromTexture', |
| crop_action=standard_crop, |
| browser_args=[ |
| '--disable-features=GpuMemoryBufferReadbackFromTexture' |
| ], |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| |
| # Test OneCopyCanvasCapture |
| PixelTestPage('pixel_video_from_canvas_webgl2.html', |
| base_name + '_VideoStreamFromWebGLCanvas_OneCopy', |
| crop_action=standard_crop, |
| browser_args=['--enable-features=OneCopyCanvasCapture'], |
| other_args={'one_copy': True}, |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| # TwoCopyCanvasCapture |
| PixelTestPage('pixel_video_from_canvas_webgl2.html', |
| base_name + |
| '_VideoStreamFromWebGLCanvas_TwoCopy_Accelerated', |
| crop_action=standard_crop, |
| browser_args=['--disable-features=OneCopyCanvasCapture'], |
| other_args={ |
| 'one_copy': False, |
| 'accelerated_two_copy': True |
| }, |
| matching_algorithm=match_algo, |
| timeout=timeout), |
| ] |
| |
| @staticmethod |
| def HdrTestPages(base_name: str) -> list[PixelTestPage]: |
| standard_crop = ca.NonWhiteContentCropAction( |
| ca.FixedRectCropAction(0, 0, 300, 300)) |
| |
| return [ |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBoxScrgbLinear', |
| crop_action=standard_crop, |
| browser_args=['--force-color-profile=scrgb-linear']), |
| PixelTestPage('pixel_canvas2d.html', |
| base_name + '_Canvas2DRedBoxHdr10', |
| crop_action=standard_crop, |
| browser_args=['--force-color-profile=hdr10']), |
| ] |
| |
| # This should only be used with the cast_streaming suite. |
| @staticmethod |
| def CastStreamingReceiverPages(base_name) -> list[PixelTestPage]: |
| return [ |
| PixelTestPage( |
| 'receiver.html', |
| base_name + '_VP8_1Frame', |
| crop_action=ca.NoOpCropAction(), |
| ), |
| ] |
| |
| @staticmethod |
| def MeetEffectsPages(base_name: str) -> list[PixelTestPage]: |
| test_cases_path = os.path.join(gpu_path_util.MEET_EFFECTS_VIDEO_DIR, |
| 'test_cases.json') |
| video_path = os.path.join(gpu_path_util.MEET_EFFECTS_VIDEO_DIR, |
| 'effects-normal-light.y4m') |
| video_args = [ |
| '--auto-accept-camera-and-microphone-capture', |
| '--use-fake-device-for-media-stream', |
| f'--use-file-for-fake-video-capture={video_path}' |
| ] |
| meet_sample_area_matching = algo.SampleAreaMatchingAlgorithm( |
| sample_area_width=5, |
| max_different_pixels_per_area=2, |
| sample_area_channel_delta_threshold=5, |
| combine_inexact_matches=True) |
| # The video is rather large on the page, which can cause a horizontal |
| # scrollbar to appear along the bottom. So, crop that first. |
| standard_crop = ca.NonWhiteContentCropAction( |
| ca.FixedRectCropAction(0, 60, None, -20)) |
| # These tests are known to produce flaky output that cannot be consistently |
| # handled by inexact matching without relaxing inexact matching parameters |
| # to the point of letting basically any image through. This is mostly |
| # caused by rendered content shifting by a fraction of a pixel, which causes |
| # a large number of differences along edges. See b/434910221 for more |
| # information. |
| output = [] |
| with open(test_cases_path, 'r', encoding='utf-8') as f: |
| for name, value in json.load(f).items(): |
| query_params = {'config': json.dumps(value['processingConfig'])} |
| if 'extraFlags' in value: |
| query_params['extraFlags'] = json.dumps(value['extraFlags']) |
| params = urllib.parse.urlencode(query_params) |
| output.append( |
| PixelTestPage(f'meet_effects/meet-gpu-tests/index.html?{params}', |
| f'{base_name}_MeetEffects_{name.replace(" ", "_")}', |
| crop_action=standard_crop, |
| browser_args=video_args, |
| matching_algorithm=meet_sample_area_matching, |
| known_flaky_output_test=True)) |
| |
| return output |