diff --git a/.gitignore b/.gitignore index 469572522566f..d69c2f1ff6978 100644 --- a/.gitignore +++ b/.gitignore @@ -213,6 +213,8 @@ vs-chromium-project.txt /content/test/data/gpu/gpu_reference/ /content/test/data/gpu/mediapipe/ /content/test/data/gpu/mediapipe_zip/mediapipe_chromium_tests.zip +/content/test/data/gpu/meet_effects/ +/content/test/data/gpu/meet_effects_videos/ /content/test/data/layout_tests/ /content/test/data/plugin/ /content/test/gpu/.webgpu_typescript/ diff --git a/DEPS b/DEPS index f325f7be51c81..9af37bd192ad8 100644 --- a/DEPS +++ b/DEPS @@ -1058,6 +1058,28 @@ deps = { 'dep_type': 'cipd', }, + 'src/content/test/data/gpu/meet_effects_videos': { + 'packages': [ + { + 'package': 'chromium/testing/meet-effects-videos', + 'version': 'version:1.0', + } + ], + 'dep_type': 'cipd', + }, + 'src/content/test/data/gpu/meet_effects': { + 'dep_type': 'gcs', + 'bucket': 'chromium-telemetry', + 'objects': [ + { + 'object_name': 'meet-gpu-tests/750908933.tar.gz', + 'sha256sum': '687f07f3963ca30339aae16bd053357a1d632db67dc744539f43bf9c83b137e5', + 'size_bytes': 192267405, + 'generation': 1747334995545331, + }, + ], + }, + # We don't know target_cpu at deps time. At least until there's a universal # binary of httpd-php, pull both intel and arm versions in DEPS and then pick # the right one at runtime. diff --git a/content/test/gpu/gpu_path_util/__init__.py b/content/test/gpu/gpu_path_util/__init__.py index 1b7bd252a7a98..91205a86b86dc 100644 --- a/content/test/gpu/gpu_path_util/__init__.py +++ b/content/test/gpu/gpu_path_util/__init__.py @@ -15,6 +15,9 @@ _GPU_DATA_RELATIVE_PATH_COMPONENTS = ('content', 'test', 'data', 'gpu') GPU_DATA_RELATIVE_PATH = os.path.join(*_GPU_DATA_RELATIVE_PATH_COMPONENTS) GPU_DATA_DIR = os.path.join(CHROMIUM_SRC_DIR, *_GPU_DATA_RELATIVE_PATH_COMPONENTS) +MEET_EFFECTS_ASSETS_DIR = os.path.join(GPU_DATA_DIR, 'meet_effects', + 'meet-gpu-tests') +MEET_EFFECTS_VIDEO_DIR = os.path.join(GPU_DATA_DIR, 'meet_effects_videos') GPU_TESTS_DIR = os.path.join(GPU_DIR, 'gpu_tests') GPU_EXPECTATIONS_DIR = os.path.join(GPU_TESTS_DIR, 'test_expectations') GPU_TEST_HARNESS_JAVASCRIPT_DIR = os.path.join(GPU_TESTS_DIR, 'javascript') diff --git a/content/test/gpu/gpu_tests/crop_actions.py b/content/test/gpu/gpu_tests/crop_actions.py index 7cc6dd211d33f..a51749a1d936b 100644 --- a/content/test/gpu/gpu_tests/crop_actions.py +++ b/content/test/gpu/gpu_tests/crop_actions.py @@ -51,37 +51,50 @@ class FixedRectCropAction(BaseCropAction): rectangle x2: An int specifying the x coordinate of the bottom right corner of the crop rectangle. Can be None to explicitly specify the right side of - the image, although clamping will be performed regardless. + the image, although clamping will be performed regardless. Can be + negative to specify an offset relative to the right edge. y2: An int specifying the y coordinate of the bottom right corner of the crop rectangle. Can be None to explicitly specify the bottom of the - image, although clamping will be performed regardless. + image, although clamping will be performed regardless. Can be + negative to specify an offset relative to the bottom. """ assert x1 >= 0 assert y1 >= 0 - assert x2 is None or x2 > x1 - assert y2 is None or y2 > y1 + assert x2 is None or x2 > x1 or x2 < 0 + assert y2 is None or y2 > y1 or y2 < 0 self._x1 = x1 self._y1 = y1 self._x2 = x2 self._y2 = y2 + # pylint: disable=too-many-locals def CropScreenshot(self, screenshot: ct.Screenshot, dpr: float, device_type: str, os_name: str) -> ct.Screenshot: del device_type, os_name # unused start_x = int(self._x1 * dpr) start_y = int(self._y1 * dpr) + image_width = image_util.Width(screenshot) + image_height = image_util.Height(screenshot) + # When actually clamping the value, it's possible we'll catch the # scrollbar, so account for its width in the clamp. - max_x = image_util.Width(screenshot) - FixedRectCropAction.SCROLLBAR_WIDTH - max_y = image_util.Height(screenshot) + max_x = image_width - FixedRectCropAction.SCROLLBAR_WIDTH + max_y = image_height if self._x2 is None: end_x = max_x + elif self._x2 < 0: + tentative_x = max(start_x + 1, int(self._x2 * dpr) + image_width) + end_x = min(tentative_x, max_x) else: end_x = min(int(self._x2 * dpr), max_x) + if self._y2 is None: end_y = max_y + elif self._y2 < 0: + tentative_y = max(start_y + 1, int(self._y2 * dpr) + image_height) + end_y = min(tentative_y, max_y) else: end_y = min(int(self._y2 * dpr), max_y) @@ -89,6 +102,7 @@ class FixedRectCropAction(BaseCropAction): crop_height = end_y - start_y return image_util.Crop(screenshot, start_x, start_y, crop_width, crop_height) + # pylint: enable=too-many-locals class NonWhiteContentCropAction(BaseCropAction): diff --git a/content/test/gpu/gpu_tests/crop_actions_unittest.py b/content/test/gpu/gpu_tests/crop_actions_unittest.py index 4f719b7907b0c..0babae5d46c5e 100644 --- a/content/test/gpu/gpu_tests/crop_actions_unittest.py +++ b/content/test/gpu/gpu_tests/crop_actions_unittest.py @@ -149,6 +149,30 @@ class FixedRectCropActionUnittest(unittest.TestCase): tolerance=0, likely_equal=True)) + def testNegativeBounds(self): + """Tests that negative numbers can be used to specify offsets.""" + image_width = 20 + # 20 x 5 green image with a group of 4 red pixels towards the top left. + # yapf: disable + pixels = [ + *(GREEN * image_width), + *(GREEN * image_width), + *GREEN, *GREEN, *RED, *RED, *(GREEN * (image_width - 4)), + *GREEN, *GREEN, *RED, *RED, *(GREEN * (image_width - 4)), + *(GREEN * image_width), + ] + # yapf: enable + image = image_util.FromRGBPixels(20, 5, pixels, bpp=3) + action = ca.FixedRectCropAction(2, 2, -16, -1) + cropped_image = action.CropScreenshot(image, 1, '', '') + expected_pixels = [*(RED * 4)] + expected_image = image_util.FromRGBPixels(2, 2, expected_pixels, bpp=3) + self.assertTrue( + image_util.AreEqual(cropped_image, + expected_image, + tolerance=0, + likely_equal=True)) + class NonWhiteContentCropAction(unittest.TestCase): diff --git a/content/test/gpu/gpu_tests/pixel_integration_test.py b/content/test/gpu/gpu_tests/pixel_integration_test.py index f8356f9d76592..17d095f6df552 100644 --- a/content/test/gpu/gpu_tests/pixel_integration_test.py +++ b/content/test/gpu/gpu_tests/pixel_integration_test.py @@ -100,6 +100,7 @@ class PixelIntegrationTest(sghitb.SkiaGoldHeartbeatIntegrationTestBase): pages += namespace.PaintWorkletPages(cls.test_base_name) pages += namespace.VideoFromCanvasPages(cls.test_base_name) pages += namespace.NoGpuProcessPages(cls.test_base_name) + pages += namespace.MeetEffectsPages(cls.test_base_name) if host_information.IsMac(): pages += namespace.MacSpecificPages(cls.test_base_name) # Unfortunately we don't have a browser instance here so can't tell @@ -109,12 +110,11 @@ class PixelIntegrationTest(sghitb.SkiaGoldHeartbeatIntegrationTestBase): if host_information.IsWindows(): pages += namespace.DirectCompositionPages(cls.test_base_name) pages += namespace.HdrTestPages(cls.test_base_name) + pages += namespace.WARPPages(cls.test_base_name) # Only run SwiftShader tests on platforms that support it. if host_information.IsLinux() or (host_information.IsWindows() and not host_information.IsArmCpu()): pages += namespace.SwiftShaderPages(cls.test_base_name) - if host_information.IsWindows(): - pages += namespace.WARPPages(cls.test_base_name) for p in pages: yield (p.name, posixpath.join(gpu_path_util.GPU_DATA_RELATIVE_PATH, p.url), [p]) diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 106984b1c0bc1..81d062a68151f 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py @@ -6,6 +6,7 @@ # pylint: disable=too-many-lines from collections.abc import Callable +from datetime import date from enum import Enum import json import logging @@ -1758,3 +1759,40 @@ class PixelTestPages(): crop_action=ca.NoOpCropAction(), ), ] + + @staticmethod + def MeetEffectsPages(base_name: str) -> list[PixelTestPage]: + 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}' + ] + # 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)) + # Run the tests on CI for a while to see how stable they are with + # fuzzy matching enabled. + grace_period_end = date(2025, 7, 1) + return [ + PixelTestPage('meet_effects/meet-gpu-tests/index.html?effectId=359', + f'{base_name}_MeetEffectsCatOnHead', + crop_action=standard_crop, + browser_args=video_args, + matching_algorithm=ROUNDING_ERROR_ALGO, + grace_period_end=grace_period_end), + PixelTestPage('meet_effects/meet-gpu-tests/index.html?effectId=539', + f'{base_name}_MeetEffectsRainbowWig', + crop_action=standard_crop, + browser_args=video_args, + matching_algorithm=ROUNDING_ERROR_ALGO, + grace_period_end=grace_period_end), + PixelTestPage('meet_effects/meet-gpu-tests/index.html?effectId=530', + f'{base_name}_MeetEffectsTruckerHat', + crop_action=standard_crop, + browser_args=video_args, + matching_algorithm=ROUNDING_ERROR_ALGO, + grace_period_end=grace_period_end), + ] diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index f2511cb26c2ee..f4032193cccf7 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt @@ -280,6 +280,10 @@ crbug.com/1426664 [ monterey ] Pixel_WebGPU* [ Skip ] # on these devices. crbug.com/1372155 [ android android-sm-a137f ] Pixel_WebGLFloat [ Skip ] +# Meet Effects tests are only supported on desktop platforms. +[ android ] Pixel_MeetEffects* [ Skip ] +[ fuchsia ] Pixel_MeetEffects* [ Skip ] + ############################### # Temporary Skip Expectations # ############################### @@ -341,6 +345,9 @@ crbug.com/1345777 [ android ] Pixel_VideoStreamFromWebGLCanvas [ Skip ] crbug.com/1456360 [ chromeos chromeos-board-amd64-generic ] Pixel_WebGLCopyImage [ Skip ] crbug.com/1456360 [ chromeos chromeos-board-amd64-generic ] Pixel_WebGLSadCanvas [ Skip ] +# Currently has flaky test setup hangs on Mac. +crbug.com/286989320 [ mac ] Pixel_MeetEffects* [ Skip ] + ############################### # Permanent Slow Expectations # ############################### @@ -384,6 +391,11 @@ crbug.com/403252788 [ mac angle-metal asan graphite-enabled intel-0x3e9b passthr # devices crbug.com/349132647 [ android android-sm-s911u1 android-chromium ] Pixel_WebGLContextRestored [ Slow ] +# Meet effects tests currently take a while to actually start, which can cause +# the initial heartbeat message to be delayed significantly. +crbug.com/286989320 [ linux ] Pixel_MeetEffects* [ Slow ] +crbug.com/286989320 [ win ] Pixel_MeetEffects* [ Slow ] + ################### # Failures/Flakes # ################### @@ -445,6 +457,9 @@ crbug.com/40937765 [ android android-pixel-6 renderer-skia-vulkan ] Pixel_Video_ # ChromeOS failures crbug.com/345146895 [ chromeos cros-chrome chromeos-board-amd64-generic renderer-skia-gl ] Pixel_RenderPasses [ Failure ] +# Times out on ChromeOS devices even when marked as Slow. +crbug.com/286989320 [ chromeos ] Pixel_MeetEffects* [ Failure ] + # Failures on fuchsia crbug.com/40935289 [ fuchsia fuchsia-board-qemu-x64 ] Pixel_WebGLFloat [ Failure ] crbug.com/40935289 [ fuchsia no-asan web-engine-shell ] Pixel_Video_AV1 [ Failure ]