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
VERY_PERMISSIVE_SOBEL_ALGO = algo.SobelMatchingAlgorithm(
max_different_pixels=100000000,
pixel_delta_threshold=255,
edge_threshold=0,
ignored_border_thickness=1)
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__(
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):
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
self.restart_browser_after_test = restart_browser_after_test
self.other_args = other_args
self.expected_per_process_crashes = expected_per_process_crashes or {}
self.timeout = timeout
if should_capture_full_screenshot_func is None:
should_capture_full_screenshot_func = DoNotCaptureFullScreenshot
self.ShouldCaptureFullScreenshot = should_capture_full_screenshot_func
if requires_fullscreen_os_screenshot_func is None:
requires_fullscreen_os_screenshot_func = (
DoNotRequireFullscreenOsScreenshot)
self.RequiresFullScreenOSScreenshot = requires_fullscreen_os_screenshot_func
self.known_flaky_output_test = known_flaky_output_test
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()
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()
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()')
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)')
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():
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
time.sleep(5)
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()
time.sleep(15)
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)})')
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),
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={
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={
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),
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,
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),
PixelTestPage(
'pixel_video_context_loss.html?src='
'/media/test/data/four-colors.mp4',
base_name + '_Video_Context_Loss_MP4',
crop_action=standard_crop,
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),
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)),
),
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,
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),
should_capture_full_screenshot_func=(
CaptureFullScreenshotOnFuchsia),
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'
standard_crop = ca.NonWhiteContentCropAction(
initial_crop=ca.FixedRectCropAction(0, 0, 500, 500))
fixed_crop = ca.FixedRectCropAction(0, 0, 300, 300)
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 [
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),
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
if method == 'captureStream' and canvas_type != 'onscreen':
continue
if method == 'transferToImageBitmap' and canvas_type == 'onscreen':
continue
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
@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',
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),
should_capture_full_screenshot_func=CaptureFullScreenshotOnFuchsia),
]
@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),
]
@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,
]
srgb_fuzzy_algo = algo.FuzzyMatchingAlgorithm(
max_different_pixels=20000, pixel_per_channel_delta_threshold=2)
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}),
]
@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),
]
@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),
]
@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),
]
@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']
no_overlays_args = ['--disable-features=CoreAnimationRenderer']
angle_gl = ['--use-angle=gl']
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))
filter_effects_crop = ca.FixedRectCropAction(0, 0, 300, 300)
return [
PixelTestPage('pixel_canvas2d_webgl.html',
base_name + '_IOSurface2DCanvasWebGL',
crop_action=standard_crop),
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),
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),
PixelTestPage('pixel_webgl_premultiplied_alpha_false.html',
base_name + '_WebGL_PremultipliedAlpha_False_NoOverlays',
crop_action=standard_crop,
browser_args=no_overlays_args),
PixelTestPage('core_animation_status_api.html?error=0',
base_name + '_CoreAnimationStatusApiNoError',
crop_action=standard_crop),
PixelTestPage('core_animation_status_api.html?error=32',
base_name + '_CoreAnimationStatusApiWithError',
crop_action=standard_crop,
browser_args=no_overlays_args),
PixelTestPage('canvas_uses_overlay.html',
base_name + '_CanvasUsesOverlay',
crop_action=standard_crop),
PixelTestPage('canvas_uses_overlay.html',
base_name + '_UnacceleratedCanvasUsesOverlay',
crop_action=standard_crop,
browser_args=unaccelerated_2d_canvas_args),
PixelTestPage(
'offscreencanvas_imagebitmap_from_worker_uses_overlay.html',
base_name + '_OffscreenCanvasImageBitmapWorkerUsesOverlay',
crop_action=standard_crop),
PixelTestPage(
'offscreencanvas_imagebitmap_from_worker_uses_overlay.html',
base_name +
'_UnacceleratedOffscreenCanvasImageBitmapWorkerUsesOverlay',
crop_action=standard_crop,
browser_args=unaccelerated_2d_canvas_args),
PixelTestPage('offscreencanvas_imagebitmap_uses_overlay.html',
base_name + '_OffscreenCanvasImageBitmapUsesOverlay',
crop_action=standard_crop),
PixelTestPage('offscreencanvas_imagebitmap_uses_overlay.html',
base_name +
'_UnacceleratedOffscreenCanvasImageBitmapUsesOverlay',
crop_action=standard_crop,
browser_args=unaccelerated_2d_canvas_args),
PixelTestPage('pixel_offscreenCanvas_ibrc_worker.html',
base_name + '_OffscreenCanvasIBRCWorkerAngleGL',
crop_action=standard_crop,
browser_args=angle_gl),
]
@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),
]
@staticmethod
def DirectCompositionPages(base_name: str,
swap_count: int | None = None
) -> list[PixelTestPage]:
browser_args = [
cba.ENABLE_DIRECT_COMPOSITION_VIDEO_OVERLAYS,
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
]
swap_count = swap_count or 16
swap_param = f'swaps={swap_count}'
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,
},
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,
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,
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),
]
@staticmethod
def VideoFromCanvasPages(base_name: str) -> list[PixelTestPage]:
match_algo = VERY_PERMISSIVE_SOBEL_ALGO
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),
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),
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),
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']),
]
@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)
standard_crop = ca.NonWhiteContentCropAction(
ca.FixedRectCropAction(0, 60, None, -20))
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