summaryrefslogtreecommitdiff
path: root/chromium/ui/ozone
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-17 17:24:03 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-06-22 07:51:41 +0000
commit774f54339e5db91f785733232d3950366db65d07 (patch)
tree068e1b47bd1af94d77094ed12b604a6b83d9c22a /chromium/ui/ozone
parentf7eaed5286974984ba5f9e3189d8f49d03e99f81 (diff)
downloadqtwebengine-chromium-774f54339e5db91f785733232d3950366db65d07.tar.gz
BASELINE: Update Chromium to 102.0.5005.57
Change-Id: I885f714bb40ee724c28f94ca6bd8dbdb39915158 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/ui/ozone')
-rw-r--r--chromium/ui/ozone/BUILD.gn26
-rw-r--r--chromium/ui/ozone/common/egl_util.cc35
-rw-r--r--chromium/ui/ozone/common/gl_ozone_egl.cc3
-rw-r--r--chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc4
-rw-r--r--chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h1
-rw-r--r--chromium/ui/ozone/demo/simple_renderer_factory.cc3
-rw-r--r--chromium/ui/ozone/demo/skia/skia_renderer_factory.cc2
-rw-r--r--chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc8
-rw-r--r--chromium/ui/ozone/demo/software_renderer.h1
-rw-r--r--chromium/ui/ozone/demo/surfaceless_gl_renderer.cc10
-rw-r--r--chromium/ui/ozone/demo/vulkan_overlay_renderer.cc12
-rw-r--r--chromium/ui/ozone/demo/vulkan_renderer.cc9
-rw-r--r--chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc10
-rw-r--r--chromium/ui/ozone/platform/cast/gl_surface_cast.cc2
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.cc5
-rw-r--r--chromium/ui/ozone/platform/drm/BUILD.gn6
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util.cc47
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util.h7
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_util.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc20
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h19
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc33
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_unittest.cc56
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc106
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h16
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc100
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc40
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc18
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc12
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc45
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/page_flip_request.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.cc75
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.h27
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc20
-rw-r--r--chromium/ui/ozone/platform/flatland/flatland_surface.h1
-rw-r--r--chromium/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc3
-rw-r--r--chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.cc7
-rw-r--r--chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.h1
-rw-r--r--chromium/ui/ozone/platform/flatland/flatland_window.cc6
-rw-r--r--chromium/ui/ozone/platform/flatland/vulkan_implementation_flatland.cc1
-rw-r--r--chromium/ui/ozone/platform/headless/BUILD.gn15
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.cc22
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform/headless/ozone_platform_headless.cc17
-rw-r--r--chromium/ui/ozone/platform/headless/vulkan_implementation_headless.cc157
-rw-r--r--chromium/ui/ozone/platform/headless/vulkan_implementation_headless.h60
-rw-r--r--chromium/ui/ozone/platform/headless/vulkan_surface_headless.cc38
-rw-r--r--chromium/ui/ozone/platform/headless/vulkan_surface_headless.h30
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_surface.h1
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window.cc15
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc3
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.cc5
-rw-r--r--chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.h1
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc1
-rw-r--r--chromium/ui/ozone/platform/wayland/BUILD.gn3
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_util.cc50
-rw-r--r--chromium/ui/ozone/platform/wayland/common/wayland_util.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc61
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h33
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc15
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc2
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc39
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h20
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc18
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc12
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc130
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h28
-rw-r--r--chromium/ui/ozone/platform/wayland/host/DEPS1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h5
-rw-r--r--chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc17
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc38
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc146
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_cursor_position.h8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc37
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device.h13
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.h8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc43
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc13
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc28
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc23
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_exchange_data_provider_unittest.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.cc61
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.h26
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc32
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h9
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc16
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_output.h2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_popup.cc2
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_screen.cc7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc17
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_serial_tracker.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_subsurface.cc54
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_subsurface.h12
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_surface.cc130
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_surface.h13
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc53
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h18
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_touch.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window.cc144
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window.h30
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc46
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc193
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc395
-rw-r--r--chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc1
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc79
-rw-r--r--chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h17
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc20
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom20
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_augmented_subsurface.cc3
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_augmented_surface.cc4
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_compositor.cc9
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_compositor.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_data_device.cc15
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_data_device.h7
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_data_device_manager.cc23
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_gtk_primary_selection.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.cc10
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.h10
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_subsurface.cc9
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_subsurface.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_viewport.cc10
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_viewport.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc11
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h9
-rw-r--r--chromium/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc8
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc321
-rw-r--r--chromium/ui/ozone/platform/windows/BUILD.gn39
-rw-r--r--chromium/ui/ozone/platform/windows/DEPS3
-rw-r--r--chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.cc16
-rw-r--r--chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.h19
-rw-r--r--chromium/ui/ozone/platform/windows/ozone_platform_windows.cc129
-rw-r--r--chromium/ui/ozone/platform/windows/ozone_platform_windows.h17
-rw-r--r--chromium/ui/ozone/platform/windows/windows_surface_factory.cc88
-rw-r--r--chromium/ui/ozone/platform/windows/windows_surface_factory.h36
-rw-r--r--chromium/ui/ozone/platform/windows/windows_window.cc21
-rw-r--r--chromium/ui/ozone/platform/windows/windows_window.h27
-rw-r--r--chromium/ui/ozone/platform/windows/windows_window_manager.cc27
-rw-r--r--chromium/ui/ozone/platform/windows/windows_window_manager.h43
-rw-r--r--chromium/ui/ozone/platform/x11/BUILD.gn25
-rw-r--r--chromium/ui/ozone/platform/x11/test/events_x_unittest.cc4
-rw-r--r--chromium/ui/ozone/platform/x11/test/x11_drag_drop_client_unittest.cc13
-rw-r--r--chromium/ui/ozone/platform/x11/test/x11_window_unittest.cc2
-rw-r--r--chromium/ui/ozone/platform/x11/vulkan_surface_x11.cc16
-rw-r--r--chromium/ui/ozone/platform/x11/x11_screen_ozone.cc42
-rw-r--r--chromium/ui/ozone/platform/x11/x11_screen_ozone.h3
-rw-r--r--chromium/ui/ozone/platform/x11/x11_surface_factory.cc4
-rw-r--r--chromium/ui/ozone/platform/x11/x11_topmost_window_finder.cc144
-rw-r--r--chromium/ui/ozone/platform/x11/x11_topmost_window_finder.h52
-rw-r--r--chromium/ui/ozone/platform/x11/x11_topmost_window_finder_interactive_uitest.cc504
-rw-r--r--chromium/ui/ozone/platform/x11/x11_window.cc33
-rw-r--r--chromium/ui/ozone/platform/x11/x11_window.h7
-rw-r--r--chromium/ui/ozone/platform/x11/x11_window_manager.cc8
-rw-r--r--chromium/ui/ozone/platform/x11/x11_window_manager.h2
-rw-r--r--chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc2
-rw-r--r--chromium/ui/ozone/public/hardware_capabilities.h23
-rw-r--r--chromium/ui/ozone/public/overlay_candidates_ozone.cc5
-rw-r--r--chromium/ui/ozone/public/overlay_candidates_ozone.h9
-rw-r--r--chromium/ui/ozone/public/ozone_switches.cc11
-rw-r--r--chromium/ui/ozone/public/ozone_switches.h6
-rw-r--r--chromium/ui/ozone/public/platform_screen.cc6
-rw-r--r--chromium/ui/ozone/public/platform_screen.h3
-rw-r--r--chromium/ui/ozone/public/surface_ozone_canvas.cc2
-rw-r--r--chromium/ui/ozone/public/system_input_injector.h8
202 files changed, 3263 insertions, 2215 deletions
diff --git a/chromium/ui/ozone/BUILD.gn b/chromium/ui/ozone/BUILD.gn
index d85d01f06f0..dc0b0ab02a9 100644
--- a/chromium/ui/ozone/BUILD.gn
+++ b/chromium/ui/ozone/BUILD.gn
@@ -62,8 +62,6 @@ if (ozone_platform_x11) {
ozone_platforms += [ "x11" ]
ozone_platform_deps += [ "platform/x11" ]
ozone_platform_ui_test_support_deps += [ "platform/x11:test_support" ]
- ozone_platform_interactive_ui_tests_sources +=
- [ "platform/x11:interactive_uitests" ]
}
if (ozone_platform_scenic) {
@@ -89,6 +87,7 @@ component("ozone_base") {
"public/gl_ozone.h",
"public/gpu_platform_support_host.cc",
"public/gpu_platform_support_host.h",
+ "public/hardware_capabilities.h",
"public/input_controller.cc",
"public/input_controller.h",
"public/overlay_candidates_ozone.cc",
@@ -183,7 +182,6 @@ source_set("platform") {
"platform_selection.cc",
"platform_selection.h",
"public/client_native_pixmap_factory_ozone.cc",
- "public/ozone_gpu_test_helper.cc",
"public/ozone_platform.cc",
constructor_list_cc_file,
platform_list_cc_file,
@@ -193,7 +191,6 @@ source_set("platform") {
public = [
"platform_object.h",
"public/client_native_pixmap_factory_ozone.h",
- "public/ozone_gpu_test_helper.h",
"public/ozone_platform.h",
]
@@ -241,7 +238,10 @@ source_set("ozone_switches") {
deps = [ "//base" ]
- visibility += [ "//chrome/test:browser_tests_runner" ]
+ visibility += [
+ "//chrome/test:browser_tests_runner",
+ "//content/public/browser:browser_sources",
+ ]
}
component("ozone") {
@@ -306,7 +306,7 @@ static_library("ui_test_support") {
source_set("ozone_interactive_ui_tests") {
visibility = []
- visibility = [ "//chrome/test:interactive_ui_tests" ]
+ visibility = [ "//chrome/test:interactive_ui_tests${exec_target_suffix}" ]
testonly = true
@@ -345,6 +345,20 @@ action("generate_ozone_platform_list") {
visibility += [ "//media:*" ]
}
+source_set("ozone_gpu_test_support") {
+ visibility = []
+ visibility = [ "//components/viz/demo:viz_demo" ]
+
+ sources = [ "public/ozone_gpu_test_helper.cc" ]
+
+ public = [ "public/ozone_gpu_test_helper.h" ]
+
+ public_deps = [
+ ":platform",
+ "//base",
+ ]
+}
+
action("generate_constructor_list") {
script = "generate_constructor_list.py"
diff --git a/chromium/ui/ozone/common/egl_util.cc b/chromium/ui/ozone/common/egl_util.cc
index 08d42145b1d..9ebf5d4d121 100644
--- a/chromium/ui/ozone/common/egl_util.cc
+++ b/chromium/ui/ozone/common/egl_util.cc
@@ -46,25 +46,6 @@ const base::FilePath::CharType kAngleGlesSoname[] =
FILE_PATH_LITERAL("libGLESv2.so");
#endif // BUILDFLAG(IS_WIN)
-#if BUILDFLAG(ENABLE_SWIFTSHADER)
-#if BUILDFLAG(IS_WIN)
-const base::FilePath::CharType kGLESv2SwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libGLESv2.dll");
-const base::FilePath::CharType kEGLSwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libEGL.dll");
-#elif BUILDFLAG(IS_FUCHSIA)
-const base::FilePath::CharType kGLESv2SwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libswiftshader_libGLESv2.so");
-const base::FilePath::CharType kEGLSwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libswiftshader_libEGL.so");
-#else
-const base::FilePath::CharType kGLESv2SwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libGLESv2.so");
-const base::FilePath::CharType kEGLSwiftShaderLibraryName[] =
- FILE_PATH_LITERAL("libEGL.so");
-#endif
-#endif // BUILDFLAG(ENABLE_SWIFTSHADER)
-
bool LoadEGLGLES2Bindings(const base::FilePath& egl_library_path,
const base::FilePath& gles_library_path) {
base::NativeLibraryLoadError error;
@@ -154,21 +135,7 @@ bool LoadDefaultEGLGLES2Bindings(
base::FilePath glesv2_path;
base::FilePath egl_path;
- if (implementation.gl == gl::kGLImplementationSwiftShaderGL) {
-#if BUILDFLAG(ENABLE_SWIFTSHADER)
- base::FilePath module_path;
-#if !BUILDFLAG(IS_FUCHSIA)
- if (!base::PathService::Get(base::DIR_MODULE, &module_path))
- return false;
- module_path = module_path.Append(FILE_PATH_LITERAL("swiftshader/"));
-#endif
-
- glesv2_path = module_path.Append(kGLESv2SwiftShaderLibraryName);
- egl_path = module_path.Append(kEGLSwiftShaderLibraryName);
-#else
- return false;
-#endif
- } else if (implementation.gl == gl::kGLImplementationEGLANGLE) {
+ if (implementation.gl == gl::kGLImplementationEGLANGLE) {
base::FilePath module_path;
#if !BUILDFLAG(IS_FUCHSIA)
if (!base::PathService::Get(base::DIR_MODULE, &module_path))
diff --git a/chromium/ui/ozone/common/gl_ozone_egl.cc b/chromium/ui/ozone/common/gl_ozone_egl.cc
index 194d29f754d..2034d0ab74d 100644
--- a/chromium/ui/ozone/common/gl_ozone_egl.cc
+++ b/chromium/ui/ozone/common/gl_ozone_egl.cc
@@ -16,7 +16,8 @@
namespace ui {
bool GLOzoneEGL::InitializeGLOneOffPlatform() {
- if (!gl::GLSurfaceEGL::InitializeOneOff(GetNativeDisplay())) {
+ if (!gl::GLSurfaceEGL::InitializeOneOff(GetNativeDisplay(),
+ /*system_device_id=*/0)) {
LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
return false;
}
diff --git a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc
index fd6026ae4f3..8990ef9fbf8 100644
--- a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc
+++ b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.cc
@@ -29,6 +29,10 @@ OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperScenic() {
return PrintErrorAndReturnNullptr();
}
+OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperFlatland() {
+ return PrintErrorAndReturnNullptr();
+}
+
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperHeadless() {
return PrintErrorAndReturnNullptr();
}
diff --git a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h
index 94fa715dc63..a8f4499e95e 100644
--- a/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h
+++ b/chromium/ui/ozone/common/test/stub_ozone_ui_controls_test_helper.h
@@ -12,6 +12,7 @@ class OzoneUIControlsTestHelper;
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperWindows();
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperDrm();
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperScenic();
+OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperFlatland();
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperHeadless();
OzoneUIControlsTestHelper* CreateOzoneUIControlsTestHelperCast();
diff --git a/chromium/ui/ozone/demo/simple_renderer_factory.cc b/chromium/ui/ozone/demo/simple_renderer_factory.cc
index 98ac818d159..da580102fa3 100644
--- a/chromium/ui/ozone/demo/simple_renderer_factory.cc
+++ b/chromium/ui/ozone/demo/simple_renderer_factory.cc
@@ -65,7 +65,8 @@ bool SimpleRendererFactory::Initialize() {
}
}
#endif
- if (!command_line->HasSwitch(kDisableGpu) && gl::init::InitializeGLOneOff()) {
+ if (!command_line->HasSwitch(kDisableGpu) &&
+ gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
type_ = GL;
} else {
type_ = SOFTWARE;
diff --git a/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc b/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
index 005c22488e3..bbad1dff348 100644
--- a/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
+++ b/chromium/ui/ozone/demo/skia/skia_renderer_factory.cc
@@ -38,7 +38,7 @@ SkiaRendererFactory::SkiaRendererFactory() {}
SkiaRendererFactory::~SkiaRendererFactory() {}
bool SkiaRendererFactory::Initialize() {
- if (!gl::init::InitializeGLOneOff()) {
+ if (!gl::init::InitializeGLOneOff(/*system_device_id=*/0)) {
LOG(FATAL) << "Failed to initialize GL";
}
diff --git a/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index 25bf025929d..9f41f94f991 100644
--- a/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -5,13 +5,13 @@
#include "ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h"
#include <stddef.h>
+
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
-#include "base/cxx17_backports.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
@@ -178,7 +178,7 @@ bool SurfacelessSkiaGlRenderer::Initialize() {
else
primary_plane_rect_ = gfx::Rect(size_);
- for (size_t i = 0; i < base::size(buffers_); ++i) {
+ for (size_t i = 0; i < std::size(buffers_); ++i) {
buffers_[i] = std::make_unique<BufferWrapper>();
if (!buffers_[i]->Initialize(gr_context_.get(), widget_,
primary_plane_rect_.size()))
@@ -187,7 +187,7 @@ bool SurfacelessSkiaGlRenderer::Initialize() {
if (command_line->HasSwitch(kEnableOverlay)) {
gfx::Size overlay_size = gfx::Size(size_.width() / 8, size_.height() / 8);
- for (size_t i = 0; i < base::size(overlay_buffer_); ++i) {
+ for (size_t i = 0; i < std::size(overlay_buffer_); ++i) {
overlay_buffer_[i] = std::make_unique<BufferWrapper>();
overlay_buffer_[i]->Initialize(gr_context_.get(),
gfx::kNullAcceleratedWidget, overlay_size);
@@ -284,7 +284,7 @@ void SurfacelessSkiaGlRenderer::PostRenderFrameTask(
gfx::SwapCompletionResult result) {
switch (result.swap_result) {
case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
- for (size_t i = 0; i < base::size(buffers_); ++i) {
+ for (size_t i = 0; i < std::size(buffers_); ++i) {
buffers_[i] = std::make_unique<BufferWrapper>();
if (!buffers_[i]->Initialize(gr_context_.get(), widget_,
primary_plane_rect_.size()))
diff --git a/chromium/ui/ozone/demo/software_renderer.h b/chromium/ui/ozone/demo/software_renderer.h
index 570f229626f..337b2b5e707 100644
--- a/chromium/ui/ozone/demo/software_renderer.h
+++ b/chromium/ui/ozone/demo/software_renderer.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/ozone/demo/renderer_base.h"
diff --git a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
index 4f033db976e..0c8db95634b 100644
--- a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -134,11 +134,11 @@ SurfacelessGlRenderer::~SurfacelessGlRenderer() {
// Need to make current when deleting the framebuffer resources allocated in
// the buffers.
context_->MakeCurrent(gl_surface_.get());
- for (size_t i = 0; i < base::size(buffers_); ++i)
+ for (size_t i = 0; i < std::size(buffers_); ++i)
buffers_[i].reset();
for (size_t i = 0; i < kMaxLayers; ++i) {
- for (size_t j = 0; j < base::size(overlay_buffers_[i]); ++j)
+ for (size_t j = 0; j < std::size(overlay_buffers_[i]); ++j)
overlay_buffers_[i][j].reset();
}
}
@@ -164,7 +164,7 @@ bool SurfacelessGlRenderer::Initialize() {
else
primary_plane_rect_ = gfx::Rect(size_);
- for (size_t i = 0; i < base::size(buffers_); ++i) {
+ for (size_t i = 0; i < std::size(buffers_); ++i) {
buffers_[i] = std::make_unique<BufferWrapper>();
if (!buffers_[i]->Initialize(widget_, primary_plane_rect_.size()))
return false;
@@ -180,7 +180,7 @@ bool SurfacelessGlRenderer::Initialize() {
const gfx::Size overlay_size =
gfx::Size(size_.width() / 8, size_.height() / 8);
for (size_t i = 0; i < overlay_cnt_; ++i) {
- for (size_t j = 0; j < base::size(overlay_buffers_[i]); ++j) {
+ for (size_t j = 0; j < std::size(overlay_buffers_[i]); ++j) {
overlay_buffers_[i][j] = std::make_unique<BufferWrapper>();
overlay_buffers_[i][j]->Initialize(gfx::kNullAcceleratedWidget,
overlay_size);
@@ -302,7 +302,7 @@ void SurfacelessGlRenderer::PostRenderFrameTask(
switch (result.swap_result) {
case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
- for (size_t i = 0; i < base::size(buffers_); ++i) {
+ for (size_t i = 0; i < std::size(buffers_); ++i) {
buffers_[i] = std::make_unique<BufferWrapper>();
if (!buffers_[i]->Initialize(widget_, primary_plane_rect_.size()))
LOG(FATAL) << "Failed to recreate buffer";
diff --git a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
index 4a648468de5..e32de9245a0 100644
--- a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
@@ -90,7 +90,7 @@ bool VulkanOverlayRenderer::Initialize() {
/* .pipelineBindPoint = */ VK_PIPELINE_BIND_POINT_GRAPHICS,
/* .inputAttachmentCount = */ 0,
/* .pInputAttachments = */ nullptr,
- /* .colorAttachmentCount = */ base::size(color_attachment_references),
+ /* .colorAttachmentCount = */ std::size(color_attachment_references),
/* .pColorAttachments = */ color_attachment_references,
/* .pResolveAttachments = */ nullptr,
/* .pDepthStencilAttachment = */ nullptr,
@@ -102,9 +102,9 @@ bool VulkanOverlayRenderer::Initialize() {
/* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
/* .pNext = */ nullptr,
/* .flags = */ 0,
- /* .attachmentCount = */ base::size(render_pass_attachments),
+ /* .attachmentCount = */ std::size(render_pass_attachments),
/* .pAttachments = */ render_pass_attachments,
- /* .subpassCount = */ base::size(render_pass_subpasses),
+ /* .subpassCount = */ std::size(render_pass_subpasses),
/* .pSubpasses = */ render_pass_subpasses,
/* .dependencyCount = */ 0,
/* .pDependencies = */ nullptr,
@@ -173,9 +173,9 @@ void VulkanOverlayRenderer::RenderFrame() {
const Buffer& buffer = *buffers_[next_buffer_];
next_buffer_++;
- next_buffer_ %= base::size(buffers_);
+ next_buffer_ %= std::size(buffers_);
++in_use_buffers_;
- DCHECK_LE(in_use_buffers_, base::size(buffers_));
+ DCHECK_LE(in_use_buffers_, std::size(buffers_));
gpu::VulkanCommandBuffer& command_buffer = *buffer.command_buffer();
@@ -218,7 +218,7 @@ std::unique_ptr<gfx::GpuFence> VulkanOverlayRenderer::SubmitFence(
VkFence fence) {
VkResult result;
VkFence fences[] = {fence};
- result = vkResetFences(device_queue_->GetVulkanDevice(), base::size(fences),
+ result = vkResetFences(device_queue_->GetVulkanDevice(), std::size(fences),
fences);
CHECK_EQ(result, VK_SUCCESS);
diff --git a/chromium/ui/ozone/demo/vulkan_renderer.cc b/chromium/ui/ozone/demo/vulkan_renderer.cc
index 8d2ea1659d1..20261982b12 100644
--- a/chromium/ui/ozone/demo/vulkan_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_renderer.cc
@@ -144,7 +144,7 @@ bool VulkanRenderer::Initialize() {
/* .pipelineBindPoint = */ VK_PIPELINE_BIND_POINT_GRAPHICS,
/* .inputAttachmentCount = */ 0,
/* .pInputAttachments = */ nullptr,
- /* .colorAttachmentCount = */ base::size(color_attachment_references),
+ /* .colorAttachmentCount = */ std::size(color_attachment_references),
/* .pColorAttachments = */ color_attachment_references,
/* .pResolveAttachments = */ nullptr,
/* .pDepthStencilAttachment = */ nullptr,
@@ -156,9 +156,9 @@ bool VulkanRenderer::Initialize() {
/* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
/* .pNext = */ nullptr,
/* .flags = */ 0,
- /* .attachmentCount = */ base::size(render_pass_attachments),
+ /* .attachmentCount = */ std::size(render_pass_attachments),
/* .pAttachments = */ render_pass_attachments,
- /* .subpassCount = */ base::size(render_pass_subpasses),
+ /* .subpassCount = */ std::size(render_pass_subpasses),
/* .pSubpasses = */ render_pass_subpasses,
/* .dependencyCount = */ 0,
/* .pDependencies = */ nullptr,
@@ -332,7 +332,8 @@ void VulkanRenderer::RenderFrame() {
VkSemaphore end_semaphore = scoped_write.end_semaphore();
CHECK(command_buffer.Submit(1, &begin_semaphore, 1, &end_semaphore));
}
- vulkan_surface_->SwapBuffers();
+ vulkan_surface_->SwapBuffers(
+ base::DoNothingAs<void(const gfx::PresentationFeedback&)>());
PostRenderFrameTask();
}
diff --git a/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc b/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
index 0cd79d34583..0bd8223bbcc 100644
--- a/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
+++ b/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
@@ -89,7 +89,15 @@ using GLImageScanoutType = testing::Types<
GLImageNativePixmapTestDelegate<gfx::BufferUsage::SCANOUT,
gfx::BufferFormat::BGRA_8888>>;
-INSTANTIATE_TYPED_TEST_SUITE_P(GLImageNativePixmapScanoutBGRA,
+#if BUILDFLAG(IS_CHROMEOS)
+// Disabled due to failures on ChromeOS MSan builder.
+// TODO(crbug.com/1314304) Reenable the test.
+#define MAYBE_GLImageNativePixmapScanoutBGRA \
+ DISABLED_GLImageNativePixmapScanoutBGRA
+#else
+#define MAYBE_GLImageNativePixmapScanoutBGRA GLImageNativePixmapScanoutBGRA
+#endif
+INSTANTIATE_TYPED_TEST_SUITE_P(MAYBE_GLImageNativePixmapScanoutBGRA,
GLImageTest,
GLImageScanoutType);
diff --git a/chromium/ui/ozone/platform/cast/gl_surface_cast.cc b/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
index 73457769c72..5057f342991 100644
--- a/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
+++ b/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
@@ -107,7 +107,7 @@ EGLConfig GLSurfaceCast::GetConfig() {
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE};
- config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
+ config_ = ChooseEGLConfig(GetEGLDisplay(), config_attribs);
}
return config_;
}
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
index 52d28595994..073671f166d 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -63,6 +63,11 @@ class CastPixmap : public gfx::NativePixmap {
return gfx::BufferFormat::BGRA_8888;
}
size_t GetNumberOfPlanes() const override { return 1; }
+ bool SupportsZeroCopyWebGPUImport() const override {
+ // TODO(crbug.com/1258986): Figure out how to import multi-planar pixmap
+ // into WebGPU without copy.
+ return false;
+ }
gfx::Size GetBufferSize() const override { return gfx::Size(); }
uint32_t GetUniqueId() const override { return 0; }
diff --git a/chromium/ui/ozone/platform/drm/BUILD.gn b/chromium/ui/ozone/platform/drm/BUILD.gn
index b6c498e888f..a35a83a6f0b 100644
--- a/chromium/ui/ozone/platform/drm/BUILD.gn
+++ b/chromium/ui/ozone/platform/drm/BUILD.gn
@@ -202,9 +202,13 @@ source_set("gbm_unittests") {
deps = [
":gbm",
"//base/test:test_support",
- "//build/config/linux/libdrm",
"//skia",
"//testing/gtest",
+
+ # We're using this instead of the config to ensure that our tests built for
+ # linux have a controllable dependency instead of relying on whatever is on
+ # the system.
+ "//third_party/libdrm",
"//ui/base/ime",
"//ui/gfx",
"//ui/gfx/linux:drm",
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util.cc b/chromium/ui/ozone/platform/drm/common/drm_util.cc
index 7f6f5ffd890..9bc3ecfbd79 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util.cc
+++ b/chromium/ui/ozone/platform/drm/common/drm_util.cc
@@ -25,6 +25,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "ui/base/ui_base_features.h"
#include "ui/display/types/display_mode.h"
#include "ui/display/util/display_util.h"
#include "ui/display/util/edid_parser.h"
@@ -136,12 +137,13 @@ display::DisplayConnectionType GetDisplayType(drmModeConnector* connector) {
}
}
+template <typename T>
int GetDrmProperty(int fd,
- drmModeConnector* connector,
+ T* object,
const std::string& name,
ScopedDrmPropertyPtr* property) {
- for (int i = 0; i < connector->count_props; ++i) {
- ScopedDrmPropertyPtr tmp(drmModeGetProperty(fd, connector->props[i]));
+ for (uint32_t i = 0; i < static_cast<uint32_t>(object->count_props); ++i) {
+ ScopedDrmPropertyPtr tmp(drmModeGetProperty(fd, object->props[i]));
if (!tmp)
continue;
@@ -245,6 +247,14 @@ display::PanelOrientation GetPanelOrientation(int fd,
int index = GetDrmProperty(fd, connector, "panel orientation", &property);
if (index < 0)
return display::PanelOrientation::kNormal;
+
+ // If the DRM driver doesn't provide panel orientation then this property
+ // will be DRM_MODE_PANEL_ORIENTATION_UNKNOWN (which is -1, except
+ // `prop_values` is unsigned, so compare against max uint64_t). Assume that
+ // panels with unknown orientation have normal orientation.
+ if (connector->prop_values[index] == std::numeric_limits<uint64_t>::max())
+ return display::PanelOrientation::kNormal;
+
DCHECK_LE(connector->prop_values[index], display::PanelOrientation::kLast);
return static_cast<display::PanelOrientation>(connector->prop_values[index]);
}
@@ -333,6 +343,30 @@ gfx::Size GetMaximumCursorSize(int fd) {
return gfx::Size(width, height);
}
+bool IsVrrCapable(int fd, drmModeConnector* connector) {
+ if (!features::IsVariableRefreshRateEnabled()) {
+ return false;
+ }
+
+ ScopedDrmPropertyPtr vrr_capable_property;
+ const int vrr_capable_index = GetDrmProperty(
+ fd, connector, kVrrCapablePropertyName, &vrr_capable_property);
+ return vrr_capable_index >= 0 && connector->prop_values[vrr_capable_index];
+}
+
+bool IsVrrEnabled(int fd, drmModeCrtc* crtc) {
+ if (!features::IsVariableRefreshRateEnabled()) {
+ return false;
+ }
+
+ ScopedDrmObjectPropertyPtr crtc_props(
+ drmModeObjectGetProperties(fd, crtc->crtc_id, DRM_MODE_OBJECT_CRTC));
+ ScopedDrmPropertyPtr vrr_enabled_property;
+ const int vrr_enabled_index = GetDrmProperty(
+ fd, crtc_props.get(), kVrrEnabledPropertyName, &vrr_enabled_property);
+ return vrr_enabled_index >= 0 && crtc_props->prop_values[vrr_enabled_index];
+}
+
HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
ScopedDrmConnectorPtr connector,
ScopedDrmCrtcPtr crtc,
@@ -737,9 +771,10 @@ std::vector<const char*> GetPreferredDrmDrivers() {
const auto sys_vendor = ReadFileAndTrim(dmi_dir.Append("sys_vendor"));
const auto product_name = ReadFileAndTrim(dmi_dir.Append("product_name"));
- // The iMac 12,1 has an integrated Intel GPU that isn't connected to
- // any real outputs. Prefer the Radeon card instead.
- if (sys_vendor == "Apple Inc." && product_name == "iMac12,1")
+ // The iMac 12.1 and 12.2 have an integrated Intel GPU that isn't connected
+ // to any real outputs. Prefer the Radeon card instead.
+ if (sys_vendor == "Apple Inc." &&
+ (product_name == "iMac12,1" || product_name == "iMac12,2"))
return {"radeon"};
// Default order.
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util.h b/chromium/ui/ozone/platform/drm/common/drm_util.h
index f6baf97b8e4..90e749c40f1 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util.h
+++ b/chromium/ui/ozone/platform/drm/common/drm_util.h
@@ -49,6 +49,9 @@ constexpr char kPrivacyScreenPropertyNameLegacy[] = "privacy-screen";
constexpr char kPrivacyScreenHwStatePropertyName[] = "privacy-screen hw-state";
constexpr char kPrivacyScreenSwStatePropertyName[] = "privacy-screen sw-state";
+constexpr char kVrrCapablePropertyName[] = "vrr_capable";
+constexpr char kVrrEnabledPropertyName[] = "VRR_ENABLED";
+
// DRM property enum to internal type mappings.
template <typename InternalType>
struct DrmPropertyEnumToInternalTypeMapping {
@@ -156,6 +159,10 @@ float ModeRefreshRate(const drmModeModeInfo& mode);
bool ModeIsInterlaced(const drmModeModeInfo& mode);
+bool IsVrrCapable(int fd, drmModeConnector* connector);
+
+bool IsVrrEnabled(int fd, drmModeCrtc* crtc);
+
uint64_t GetEnumValueForName(int fd, int property_id, const char* str);
std::vector<uint64_t> ParsePathBlob(const drmModePropertyBlobRes& path_blob);
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc b/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
index 7a40ed649fc..0edb8f69d18 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
@@ -9,7 +9,6 @@
#include <map>
-#include "skia/ext/skia_matrix_44.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "ui/display/types/display_snapshot.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index 0a8a95331b6..c6eeb8a72d8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -107,9 +107,9 @@ DrmGpuDisplayManager::DrmGpuDisplayManager(ScreenManager* screen_manager,
DrmGpuDisplayManager::~DrmGpuDisplayManager() = default;
-void DrmGpuDisplayManager::SetClearOverlayCacheCallback(
+void DrmGpuDisplayManager::SetDisplaysConfiguredCallback(
base::RepeatingClosure callback) {
- clear_overlay_cache_callback_ = std::move(callback);
+ displays_configured_callback_ = std::move(callback);
}
MovableDisplaySnapshots DrmGpuDisplayManager::GetDisplays() {
@@ -236,12 +236,13 @@ bool DrmGpuDisplayManager::ConfigureDisplays(
controllers_to_configure.push_back(std::move(params));
}
- if (clear_overlay_cache_callback_)
- clear_overlay_cache_callback_.Run();
-
bool config_success =
screen_manager_->ConfigureDisplayControllers(controllers_to_configure);
+ if (displays_configured_callback_) {
+ displays_configured_callback_.Run();
+ }
+
for (const auto& controller : controllers_to_configure) {
if (config_success) {
FindDisplay(controller.display_id)->SetOrigin(controller.origin);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index 0382fab55e5..009f0fb8ca8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -43,8 +43,8 @@ class DrmGpuDisplayManager {
~DrmGpuDisplayManager();
// Sets a callback that will be notified when display configuration may have
- // changed to clear the overlay configuration cache.
- void SetClearOverlayCacheCallback(base::RepeatingClosure callback);
+ // changed, so we should update state for managing overlays.
+ void SetDisplaysConfiguredCallback(base::RepeatingClosure callback);
// Returns a list of the connected displays. When this is called the list of
// displays is refreshed.
@@ -87,7 +87,7 @@ class DrmGpuDisplayManager {
std::vector<std::unique_ptr<DrmDisplay>> displays_;
- base::RepeatingClosure clear_overlay_cache_callback_;
+ base::RepeatingClosure displays_configured_callback_;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_util.cc b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
index b76943a8fa4..762024834bc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
@@ -75,8 +75,8 @@ ScopedDrmColorCtmPtr CreateCTMBlob(const std::vector<float>& color_matrix) {
ScopedDrmColorCtmPtr ctm(
static_cast<drm_color_ctm*>(malloc(sizeof(drm_color_ctm))));
- DCHECK_EQ(color_matrix.size(), base::size(ctm->matrix));
- for (size_t i = 0; i < base::size(ctm->matrix); ++i) {
+ DCHECK_EQ(color_matrix.size(), std::size(ctm->matrix));
+ for (size_t i = 0; i < std::size(ctm->matrix); ++i) {
if (color_matrix[i] < 0) {
ctm->matrix[i] = static_cast<uint64_t>(-color_matrix[i] * (1ull << 32));
ctm->matrix[i] |= static_cast<uint64_t>(1) << 63;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.cc
index 1ca27372af5..886e66cc8bc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.cc
@@ -16,6 +16,7 @@ DrmOverlayCandidates::DrmOverlayCandidates(DrmOverlayManager* manager,
DrmOverlayCandidates::~DrmOverlayCandidates() {
overlay_manager_->RegisterOverlayRequirement(widget_, false);
+ overlay_manager_->StopObservingHardwareCapabilities(widget_);
}
void DrmOverlayCandidates::CheckOverlaySupport(
@@ -23,6 +24,12 @@ void DrmOverlayCandidates::CheckOverlaySupport(
overlay_manager_->CheckOverlaySupport(candidates, widget_);
}
+void DrmOverlayCandidates::ObserveHardwareCapabilities(
+ HardwareCapabilitiesCallback receive_callback) {
+ overlay_manager_->StartObservingHardwareCapabilities(
+ widget_, std::move(receive_callback));
+}
+
void DrmOverlayCandidates::RegisterOverlayRequirement(bool requires_overlay) {
#if !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
DCHECK(!requires_overlay);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.h
index cbbd6d7b27d..c1f9cc42f84 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_candidates.h
@@ -8,6 +8,7 @@
#include <vector>
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
namespace ui {
@@ -29,6 +30,8 @@ class DrmOverlayCandidates : public OverlayCandidatesOzone {
// OverlayCandidatesOzone:
void CheckOverlaySupport(
std::vector<OverlaySurfaceCandidate>* candidates) override;
+ void ObserveHardwareCapabilities(
+ HardwareCapabilitiesCallback receive_callback) override;
void RegisterOverlayRequirement(bool requires_overlay) override;
private:
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
index 79227e5a59b..6f51baf3c8f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
@@ -54,10 +54,26 @@ DrmOverlayManager::CreateOverlayCandidates(gfx::AcceleratedWidget widget) {
return std::make_unique<DrmOverlayCandidates>(this, widget);
}
-void DrmOverlayManager::ResetCache() {
- TRACE_EVENT0("hwoverlays", "DrmOverlayManager::ResetCache");
+void DrmOverlayManager::DisplaysConfigured() {
+ TRACE_EVENT0("hwoverlays", "DrmOverlayManager::DisplaysConfigured");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
widget_cache_map_.clear();
+
+ for (auto& entry : hardware_capabilities_callbacks_) {
+ GetHardwareCapabilities(entry.first, entry.second);
+ }
+}
+
+void DrmOverlayManager::StartObservingHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ HardwareCapabilitiesCallback receive_callback) {
+ GetHardwareCapabilities(widget, receive_callback);
+ hardware_capabilities_callbacks_.emplace(widget, std::move(receive_callback));
+}
+
+void DrmOverlayManager::StopObservingHardwareCapabilities(
+ gfx::AcceleratedWidget widget) {
+ hardware_capabilities_callbacks_.erase(widget);
}
void DrmOverlayManager::CheckOverlaySupport(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
index c9927dd4953..28fa53038ed 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
@@ -12,6 +12,7 @@
#include "base/containers/lru_cache.h"
#include "base/threading/thread_checker.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
@@ -35,15 +36,26 @@ class DrmOverlayManager : public OverlayManagerOzone {
std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
gfx::AcceleratedWidget w) override;
+ // Called when notified by the DRM thread of a display configuration change.
// Resets the cache of OverlaySurfaceCandidates and if they can be displayed
- // as an overlay. For use when display configuration changes.
- void ResetCache();
+ // as an overlay. Requests an updated HardwareCapabilities for any observing
+ // OverlayProcessors.
+ void DisplaysConfigured();
// Checks if overlay candidates can be displayed as overlays. Modifies
// |candidates| to indicate if they can.
void CheckOverlaySupport(std::vector<OverlaySurfaceCandidate>* candidates,
gfx::AcceleratedWidget widget);
+ void StartObservingHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ HardwareCapabilitiesCallback receive_callback);
+ void StopObservingHardwareCapabilities(gfx::AcceleratedWidget widget);
+
+ virtual void GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ HardwareCapabilitiesCallback& receive_callback) = 0;
+
// Should be called by the overlay processor to indicate if a widget has a
// candidate that requires an overlay. This is to prioritize which display
// gets the overlay in a multiple display environment.
@@ -98,6 +110,9 @@ class DrmOverlayManager : public OverlayManagerOzone {
base::flat_set<gfx::AcceleratedWidget> widgets_with_required_overlays_;
+ std::map<gfx::AcceleratedWidget, HardwareCapabilitiesCallback>
+ hardware_capabilities_callbacks_;
+
THREAD_CHECKER(thread_checker_);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
index 13dc7cbbca6..803c45f278f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
@@ -28,7 +28,7 @@ void DrmOverlayManagerGpu::SendOverlayValidationRequest(
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
"hwoverlays", "DrmOverlayManagerGpu::SendOverlayValidationRequest",
TRACE_ID_LOCAL(this));
- SetClearCacheCallbackIfNecessary();
+ SetDisplaysConfiguredCallbackIfNecessary();
drm_thread_proxy_->CheckOverlayCapabilities(
widget, candidates,
base::BindOnce(&DrmOverlayManagerGpu::ReceiveOverlayValidationResponse,
@@ -41,21 +41,30 @@ DrmOverlayManagerGpu::SendOverlayValidationRequestSync(
gfx::AcceleratedWidget widget) {
TRACE_EVENT0("hwoverlays",
"DrmOverlayManagerGpu::SendOverlayValidationRequestSync");
- SetClearCacheCallbackIfNecessary();
+ SetDisplaysConfiguredCallbackIfNecessary();
return drm_thread_proxy_->CheckOverlayCapabilitiesSync(widget, candidates);
}
-void DrmOverlayManagerGpu::SetClearCacheCallbackIfNecessary() {
+void DrmOverlayManagerGpu::GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ HardwareCapabilitiesCallback& receive_callback) {
+ TRACE_EVENT0("hwoverlays",
+ "DrmOverlayManagerGpu::SendMaxOverlaysRequestSync");
+ SetDisplaysConfiguredCallbackIfNecessary();
+ drm_thread_proxy_->GetHardwareCapabilities(widget, receive_callback);
+}
+
+void DrmOverlayManagerGpu::SetDisplaysConfiguredCallbackIfNecessary() {
// Adds a callback for the DRM thread to let us know when display
- // configuration has changed and to reset cache of valid overlay
- // configurations. This happens in SendOverlayValidationRequest() because the
- // DrmThread has been started by this point *and* we are on the thread the
- // callback should run on. Those two conditions are not necessarily true in
- // the constructor.
- if (!has_set_clear_cache_callback_) {
- has_set_clear_cache_callback_ = true;
- drm_thread_proxy_->SetClearOverlayCacheCallback(base::BindRepeating(
- &DrmOverlayManagerGpu::ResetCache, weak_ptr_factory_.GetWeakPtr()));
+ // configuration may have changed.
+ // This happens in SendOverlayValidationRequest() because the DrmThread has
+ // been started by this point *and* we are on the thread the callback should
+ // run on. Those two conditions are not necessarily true in the constructor.
+ if (!has_set_displays_configured_callback_) {
+ has_set_displays_configured_callback_ = true;
+ drm_thread_proxy_->SetDisplaysConfiguredCallback(
+ base::BindRepeating(&DrmOverlayManagerGpu::DisplaysConfigured,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
index 93f77bb424e..1942d754538 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
@@ -35,7 +35,11 @@ class DrmOverlayManagerGpu : public DrmOverlayManager {
const std::vector<OverlaySurfaceCandidate>& candidates,
gfx::AcceleratedWidget widget) override;
- void SetClearCacheCallbackIfNecessary();
+ void GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ HardwareCapabilitiesCallback& receive_callback) override;
+
+ void SetDisplaysConfiguredCallbackIfNecessary();
void ReceiveOverlayValidationResponse(
gfx::AcceleratedWidget widget,
@@ -44,7 +48,7 @@ class DrmOverlayManagerGpu : public DrmOverlayManager {
DrmThreadProxy* const drm_thread_proxy_;
- bool has_set_clear_cache_callback_ = false;
+ bool has_set_displays_configured_callback_ = false;
base::WeakPtrFactory<DrmOverlayManagerGpu> weak_ptr_factory_{this};
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_unittest.cc
index 24e93a07671..47784e5fe9b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_unittest.cc
@@ -38,6 +38,16 @@ class TestDrmOverlayManager : public DrmOverlayManager {
gfx::AcceleratedWidget widget) override {
return {};
}
+ void GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ ui::HardwareCapabilitiesCallback& receive_callback) override {
+ ui::HardwareCapabilities hardware_capabilities;
+ hardware_capabilities.num_overlay_capable_planes = num_planes_response_;
+ // Immediately respond to the callback.
+ receive_callback.Run(hardware_capabilities);
+ }
+
+ int num_planes_response_ = 0;
private:
std::vector<std::vector<OverlaySurfaceCandidate>> requests_;
@@ -308,4 +318,50 @@ TEST(DrmOverlayManagerTest, RequiredOverlayMultiDisplay) {
EXPECT_EQ(manager.requests().size(), 1u);
}
+TEST(DrmOverlayManagerTest, ObservingHardwareCapabilities) {
+ TestDrmOverlayManager manager;
+ manager.num_planes_response_ = 2;
+
+ int primary_calls = 0;
+ HardwareCapabilitiesCallback primary_callback = base::BindRepeating(
+ [](int* calls, HardwareCapabilities hc) {
+ (*calls)++;
+ EXPECT_EQ(hc.num_overlay_capable_planes, 2);
+ },
+ &primary_calls);
+ manager.StartObservingHardwareCapabilities(kPrimaryWidget, primary_callback);
+ EXPECT_EQ(primary_calls, 1);
+
+ manager.DisplaysConfigured();
+
+ EXPECT_EQ(primary_calls, 2);
+
+ int secondary_calls = 0;
+ HardwareCapabilitiesCallback secondary_callback = base::BindRepeating(
+ [](int* calls, HardwareCapabilities hc) {
+ (*calls)++;
+ EXPECT_EQ(hc.num_overlay_capable_planes, 2);
+ },
+ &secondary_calls);
+ manager.StartObservingHardwareCapabilities(kSecondaryWidget,
+ secondary_callback);
+ // Only the secondary callback should be called.
+ EXPECT_EQ(primary_calls, 2);
+ EXPECT_EQ(secondary_calls, 1);
+
+ manager.DisplaysConfigured();
+
+ // Both callbacks are called.
+ EXPECT_EQ(primary_calls, 3);
+ EXPECT_EQ(secondary_calls, 2);
+
+ manager.StopObservingHardwareCapabilities(kPrimaryWidget);
+ manager.DisplaysConfigured();
+ manager.DisplaysConfigured();
+
+ // The primary callback won't be called anymore.
+ EXPECT_EQ(primary_calls, 3);
+ EXPECT_EQ(secondary_calls, 4);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
index 6e339c7cb63..a94d256ee92 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -89,6 +89,19 @@ DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) : window_(window) {}
DrmOverlayValidator::~DrmOverlayValidator() {}
+DrmOverlayPlane DrmOverlayValidator::MakeOverlayPlane(
+ const OverlaySurfaceCandidate& param,
+ std::vector<scoped_refptr<DrmFramebuffer>>& reusable_buffers,
+ size_t& total_allocated_memory_size) {
+ scoped_refptr<DrmFramebuffer> buffer = GetBufferForPageFlipTest(
+ window_, param, &reusable_buffers, &total_allocated_memory_size);
+
+ return DrmOverlayPlane(buffer, param.plane_z_order, param.transform,
+ gfx::ToNearestRect(param.display_rect),
+ param.crop_rect, !param.is_opaque,
+ /*gpu_fence=*/nullptr);
+}
+
OverlayStatusList DrmOverlayValidator::TestPageFlip(
const OverlaySurfaceCandidateList& params,
const DrmOverlayPlaneList& last_used_planes) {
@@ -96,8 +109,9 @@ OverlayStatusList DrmOverlayValidator::TestPageFlip(
HardwareDisplayController* controller = window_->GetController();
if (!controller) {
// The controller is not yet installed.
- for (auto& param : returns)
- param = OVERLAY_STATUS_NOT;
+ for (auto& status : returns) {
+ status = OVERLAY_STATUS_NOT;
+ }
return returns;
}
@@ -106,55 +120,77 @@ OverlayStatusList DrmOverlayValidator::TestPageFlip(
std::vector<scoped_refptr<DrmFramebuffer>> reusable_buffers;
scoped_refptr<DrmDevice> drm = controller->GetDrmDevice();
- for (const auto& plane : last_used_planes)
+ for (const auto& plane : last_used_planes) {
reusable_buffers.push_back(plane.buffer);
+ }
size_t total_allocated_memory_size = 0;
- int test_page_flip_count = 0;
+ std::vector<size_t> plane_indices;
for (size_t i = 0; i < params.size(); ++i) {
- if (!params[i].overlay_handled) {
+ auto& param = params[i];
+ // Skip candidates that have already been disqualified.
+ if (!param.overlay_handled) {
returns[i] = OVERLAY_STATUS_NOT;
continue;
}
- scoped_refptr<DrmFramebuffer> buffer = GetBufferForPageFlipTest(
- window_, params[i], &reusable_buffers, &total_allocated_memory_size);
+ DrmOverlayPlane plane =
+ MakeOverlayPlane(param, reusable_buffers, total_allocated_memory_size);
+ if (!plane.buffer) {
+ returns[i] = OVERLAY_STATUS_NOT;
+ continue;
+ }
- DrmOverlayPlane plane(buffer, params[i].plane_z_order, params[i].transform,
- gfx::ToNearestRect(params[i].display_rect),
- params[i].crop_rect, !params[i].is_opaque,
- /*gpu_fence=*/nullptr);
test_list.push_back(std::move(plane));
+ // We need to save the indices because we're skipping some planes.
+ plane_indices.push_back(i);
+ }
- bool result = false;
- if (buffer) {
- test_page_flip_count++;
- base::ElapsedTimer timer;
-
- result = controller->TestPageFlip(test_list);
+ int test_page_flip_count = 0;
- auto time = timer.Elapsed();
- static constexpr base::TimeDelta kMinTime = base::Microseconds(1);
- static constexpr base::TimeDelta kMaxTime = base::Milliseconds(10);
- static constexpr int kTimeBuckets = 50;
- UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
- "Compositing.Display.DrmOverlayManager.TestPageFlipUs", time,
- kMinTime, kMaxTime, kTimeBuckets);
+ // Test the whole list, then gradually remove the last plane and retest until
+ // we have success, or no more planes to test.
+ while (!test_list.empty()) {
+ test_page_flip_count++;
+ base::ElapsedTimer timer;
+
+ bool test_result = controller->TestPageFlip(test_list);
+
+ auto time = timer.Elapsed();
+ static constexpr base::TimeDelta kMinTime = base::Microseconds(1);
+ static constexpr base::TimeDelta kMaxTime = base::Milliseconds(10);
+ static constexpr int kTimeBuckets = 50;
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Compositing.Display.DrmOverlayManager.TestPageFlipUs", time, kMinTime,
+ kMaxTime, kTimeBuckets);
+
+ if (test_page_flip_count == 1) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Display.DrmOverlayManager.FirstTestPageFlipPassed",
+ test_result);
}
- if (result) {
- returns[i] = OVERLAY_STATUS_ABLE;
- } else {
- // If test failed here, platform cannot support this configuration
- // with current combination of layers. This is usually the case when this
- // plane has requested post processing capability which needs additional
- // hardware resources and they might be already in use by other planes.
- // For example this plane has requested scaling capabilities and all
- // available scalars are already in use by other planes.
- returns[i] = OVERLAY_STATUS_NOT;
- test_list.pop_back();
+ if (test_result) {
+ break;
}
+
+ // If test failed here, platform cannot support this configuration
+ // with current combination of layers. This is usually the case when this
+ // plane has requested post processing capability which needs additional
+ // hardware resources and they might be already in use by other planes.
+ // For example this plane has requested scaling capabilities and all
+ // available scalars are already in use by other planes.
+
+ // Drop the last plane from the test list and set it to OVERLAY_STATUS_NOT.
+ returns[plane_indices.back()] = OVERLAY_STATUS_NOT;
+ plane_indices.pop_back();
+ test_list.pop_back();
+ }
+
+ // Set OVERLAY_STATUS_ABLE for all planes left in the test_list.
+ for (size_t index : plane_indices) {
+ returns[index] = OVERLAY_STATUS_ABLE;
}
UMA_HISTOGRAM_MEMORY_KB(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
index 5b410997879..b7ccb7e406c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -5,6 +5,8 @@
#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_VALIDATOR_H_
#define UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_VALIDATOR_H_
+#include <vector>
+
#include "base/containers/lru_cache.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/public/overlay_surface_candidate.h"
@@ -22,13 +24,23 @@ class DrmOverlayValidator {
~DrmOverlayValidator();
- // Tests if configurations |params| are compatible with |window_| and finds
+ // Tests if configurations of |params| are compatible with |window_| and finds
// which of these configurations can be promoted to Overlay composition
- // without failing the page flip. It expects |params| to be sorted by z_order.
+ // without failing the page flip.
+ // If the complete list of planes fails we will remove planes from the end of
+ // the test list one at a time. This means that |params| should always have
+ // the primary plane at the beginning of the list, and the rest should be
+ // sorted based on expected power gain, so less impactful planes are dropped
+ // first.
OverlayStatusList TestPageFlip(const OverlaySurfaceCandidateList& params,
const DrmOverlayPlaneList& last_used_planes);
private:
+ DrmOverlayPlane MakeOverlayPlane(
+ const OverlaySurfaceCandidate& param,
+ std::vector<scoped_refptr<DrmFramebuffer>>& reusable_buffers,
+ size_t& total_allocated_memory_size);
+
DrmWindow* const window_; // Not owned.
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index a67ea0c5433..5a84f9565fe 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -27,6 +27,7 @@
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
#include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
#include "ui/ozone/platform/drm/gpu/screen_manager.h"
+#include "ui/ozone/public/overlay_surface_candidate.h"
namespace {
@@ -584,7 +585,7 @@ TEST_F(DrmOverlayValidatorTest, NonIntegerDisplayRect) {
{.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}}}};
InitDrmStatesAndControllers(std::vector<CrtcState>(1, state));
- overlay_params_.back().display_rect.Inset(0.005f, 0.005f);
+ overlay_params_.back().display_rect.Inset(0.005f);
plane_list_.pop_back();
AddPlane(overlay_params_.back());
@@ -594,3 +595,100 @@ TEST_F(DrmOverlayValidatorTest, NonIntegerDisplayRect) {
for (const auto& param : returns)
EXPECT_EQ(param, ui::OVERLAY_STATUS_ABLE);
}
+
+class TestAtOnceDrmOverlayValidatorTest
+ : public DrmOverlayValidatorTest,
+ public testing::WithParamInterface<bool> {};
+
+TEST_F(DrmOverlayValidatorTest, FourCandidates_OneCommit) {
+ // Four planes.
+ CrtcState crtc_state = {.planes = {{.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}}}};
+ InitDrmStatesAndControllers({crtc_state});
+ int setup_commits = drm_->get_commit_count();
+
+ // Add two more overlay candidates.
+ auto param3 = overlay_params_.back();
+ auto param4 = overlay_params_.back();
+ overlay_params_.push_back(param3);
+ overlay_params_.push_back(param4);
+
+ std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
+ overlay_params_, ui::DrmOverlayPlaneList());
+
+ // All planes promoted.
+ ASSERT_EQ(4u, returns.size());
+ EXPECT_EQ(returns[0], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[1], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[2], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[3], ui::OVERLAY_STATUS_ABLE);
+ // Only 1 commit was necessary.
+ EXPECT_EQ(drm_->get_commit_count() - setup_commits, 1);
+}
+
+TEST_F(DrmOverlayValidatorTest, FourCandidatesTwoPlanes_MoreThanOneCommit) {
+ // Only two planes.
+ CrtcState crtc_state = {.planes = {{.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}}}};
+ InitDrmStatesAndControllers({crtc_state});
+ int setup_commits = drm_->get_commit_count();
+
+ // Add two more overlay candidates.
+ auto param3 = overlay_params_.back();
+ auto param4 = overlay_params_.back();
+ overlay_params_.push_back(param3);
+ overlay_params_.push_back(param4);
+
+ std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
+ overlay_params_, ui::DrmOverlayPlaneList());
+
+ // All planes promoted.
+ ASSERT_EQ(4u, returns.size());
+ EXPECT_EQ(returns[0], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[1], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[2], ui::OVERLAY_STATUS_NOT);
+ EXPECT_EQ(returns[3], ui::OVERLAY_STATUS_NOT);
+ // First attempted with all 4 planes, then 3, then 2.
+ EXPECT_EQ(drm_->get_commit_count() - setup_commits, 3);
+}
+
+TEST_F(DrmOverlayValidatorTest, TwoOfSixIgnored_OneCommit) {
+ // Six planes.
+ CrtcState crtc_state = {.planes = {{.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}},
+ {.formats = {DRM_FORMAT_XRGB8888}}}};
+ InitDrmStatesAndControllers({crtc_state});
+ int setup_commits = drm_->get_commit_count();
+
+ auto param3 = overlay_params_.back();
+ auto param4 = overlay_params_.back();
+ auto param5 = overlay_params_.back();
+ auto param6 = overlay_params_.back();
+ // Candidate 3 and 5 are already disqualified.
+ param3.overlay_handled = false;
+ param5.overlay_handled = false;
+ overlay_params_.push_back(param3);
+ overlay_params_.push_back(param4);
+ overlay_params_.push_back(param5);
+ overlay_params_.push_back(param6);
+
+ std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
+ overlay_params_, ui::DrmOverlayPlaneList());
+
+ ASSERT_EQ(6u, returns.size());
+ // Third and Fifth candidate were ignored.
+ EXPECT_EQ(returns[0], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[1], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[2], ui::OVERLAY_STATUS_NOT);
+ EXPECT_EQ(returns[3], ui::OVERLAY_STATUS_ABLE);
+ EXPECT_EQ(returns[4], ui::OVERLAY_STATUS_NOT);
+ EXPECT_EQ(returns[5], ui::OVERLAY_STATUS_ABLE);
+ // Only 1 commit was needed because the two unpromoted candidates were
+ // excluded before testing.
+ EXPECT_EQ(drm_->get_commit_count() - setup_commits, 1);
+}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index 805e82b8d50..02066666364 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -26,6 +26,7 @@
#include "ui/gfx/presentation_feedback.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
+#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
#include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
@@ -214,8 +215,8 @@ void DrmThread::CreateBufferFromHandle(
*out_framebuffer = std::move(framebuffer);
}
-void DrmThread::SetClearOverlayCacheCallback(base::RepeatingClosure callback) {
- display_manager_->SetClearOverlayCacheCallback(std::move(callback));
+void DrmThread::SetDisplaysConfiguredCallback(base::RepeatingClosure callback) {
+ display_manager_->SetDisplaysConfiguredCallback(std::move(callback));
}
void DrmThread::SchedulePageFlip(
@@ -337,6 +338,41 @@ void DrmThread::CheckOverlayCapabilitiesSync(
kMinTime, kMaxTime, kTimeBuckets);
}
+void DrmThread::GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ ui::HardwareCapabilitiesCallback receive_callback) {
+ TRACE_EVENT0("drm,hwoverlays", "DrmThread::GetHardwareCapabilities");
+ DCHECK(screen_manager_->GetWindow(widget));
+ DCHECK(device_manager_->GetDrmDevice(widget));
+ HardwareDisplayController* hdc =
+ screen_manager_->GetWindow(widget)->GetController();
+ HardwareDisplayPlaneManager* plane_manager =
+ device_manager_->GetDrmDevice(widget)->plane_manager();
+
+ if (!hdc || !plane_manager) {
+ // Assume only the primary plane exists.
+ ui::HardwareCapabilities hardware_capabilities;
+ hardware_capabilities.num_overlay_capable_planes = 1;
+ std::move(receive_callback).Run(hardware_capabilities);
+ return;
+ }
+
+ const auto& crtc_controllers = hdc->crtc_controllers();
+ // We almost always expect only one CRTC. Multiple CRTCs for one widget was
+ // the old way mirror mode was supported.
+ if (crtc_controllers.size() == 1) {
+ std::move(receive_callback)
+ .Run(plane_manager->GetHardwareCapabilities(
+ crtc_controllers[0]->crtc()));
+ } else {
+ // If there are multiple CRTCs for this widget, we shouldn't rely on
+ // overlays working, so we'll say only the primary plane exists.
+ ui::HardwareCapabilities hardware_capabilities;
+ hardware_capabilities.num_overlay_capable_planes = 1;
+ std::move(receive_callback).Run(hardware_capabilities);
+ }
+}
+
void DrmThread::GetDeviceCursor(
mojo::PendingAssociatedReceiver<ozone::mojom::DeviceCursor> receiver) {
cursor_receivers_.Add(this, std::move(receiver));
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
index fa20e5b3515..0a1249e76af 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -25,6 +25,7 @@
#include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
#include "ui/ozone/platform/drm/mojom/device_cursor.mojom.h"
#include "ui/ozone/platform/drm/mojom/drm_device.mojom.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_surface_candidate.h"
#include "ui/ozone/public/swap_completion_callback.h"
@@ -107,7 +108,7 @@ class DrmThread : public base::Thread,
gfx::NativePixmapHandle handle,
std::unique_ptr<GbmBuffer>* buffer,
scoped_refptr<DrmFramebuffer>* framebuffer);
- void SetClearOverlayCacheCallback(base::RepeatingClosure callback);
+ void SetDisplaysConfiguredCallback(base::RepeatingClosure callback);
void AddDrmDeviceReceiver(
mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver);
@@ -128,6 +129,11 @@ class DrmThread : public base::Thread,
gfx::AcceleratedWidget widget,
const std::vector<OverlaySurfaceCandidate>& candidates,
std::vector<OverlayStatus>* result);
+ // Calls `receive_callback` with a `HardwareCapabilities` containing
+ // information about overlay support on the current hardware.
+ void GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ ui::HardwareCapabilitiesCallback receive_callback);
// DrmWindowProxy (on GPU thread) is the client for these methods.
void SchedulePageFlip(gfx::AcceleratedWidget widget,
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index a785ee1eec7..078ee8a975a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -130,13 +130,13 @@ void DrmThreadProxy::CreateBufferFromHandle(
base::Unretained(&drm_thread_), std::move(task)));
}
-void DrmThreadProxy::SetClearOverlayCacheCallback(
+void DrmThreadProxy::SetDisplaysConfiguredCallback(
base::RepeatingClosure callback) {
DCHECK(drm_thread_.task_runner());
drm_thread_.task_runner()->PostTask(
FROM_HERE,
- base::BindOnce(&DrmThread::SetClearOverlayCacheCallback,
+ base::BindOnce(&DrmThread::SetDisplaysConfiguredCallback,
base::Unretained(&drm_thread_),
CreateSafeRepeatingCallback(std::move(callback))));
}
@@ -172,6 +172,20 @@ std::vector<OverlayStatus> DrmThreadProxy::CheckOverlayCapabilitiesSync(
return result;
}
+void DrmThreadProxy::GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ const HardwareCapabilitiesCallback& receive_callback) {
+ TRACE_EVENT0("drm", "DrmThreadProxy::GetHardwareCapabilities");
+ DCHECK(drm_thread_.task_runner());
+ base::RepeatingClosure task = base::BindRepeating(
+ &DrmThread::GetHardwareCapabilities, base::Unretained(&drm_thread_),
+ widget, CreateSafeRepeatingCallback(receive_callback));
+ drm_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DrmThread::RunTaskAfterDeviceReady,
+ base::Unretained(&drm_thread_), std::move(task), nullptr));
+}
+
void DrmThreadProxy::AddDrmDeviceReceiver(
mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver) {
DCHECK(drm_thread_.task_runner()) << "DrmThreadProxy::AddDrmDeviceReceiver "
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index 16204ce4089..f50c939a8df 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -13,6 +13,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/ozone/platform/drm/gpu/drm_thread.h"
#include "ui/ozone/platform/drm/mojom/device_cursor.mojom.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_surface_candidate.h"
namespace ui {
@@ -66,9 +67,9 @@ class DrmThreadProxy {
scoped_refptr<DrmFramebuffer>* framebuffer);
// Sets a callback that will be notified when display configuration may have
- // changed to clear the overlay configuration cache. |callback| will be run on
- // origin thread.
- void SetClearOverlayCacheCallback(base::RepeatingClosure reset_callback);
+ // changed, so we should update state for managing overlays.
+ // |callback| will be run on origin thread.
+ void SetDisplaysConfiguredCallback(base::RepeatingClosure callback);
// Checks if overlay |candidates| can be displayed asynchronously and then
// runs |callback|. Testing the overlay configuration requires posting a task
@@ -83,6 +84,10 @@ class DrmThreadProxy {
gfx::AcceleratedWidget widget,
const std::vector<OverlaySurfaceCandidate>& candidates);
+ void GetHardwareCapabilities(
+ gfx::AcceleratedWidget widget,
+ const HardwareCapabilitiesCallback& receive_callback);
+
void AddDrmDeviceReceiver(
mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver);
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
index 92b95778f88..fdff43be050 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.cc
@@ -52,6 +52,10 @@ size_t GbmPixmap::GetNumberOfPlanes() const {
return buffer_->GetNumPlanes();
}
+bool GbmPixmap::SupportsZeroCopyWebGPUImport() const {
+ return buffer_->SupportsZeroCopyWebGPUImport();
+}
+
uint64_t GbmPixmap::GetBufferFormatModifier() const {
return buffer_->GetFormatModifier();
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
index a2192a3b2b0..c5abbdfde10 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
@@ -34,6 +34,7 @@ class GbmPixmap : public gfx::NativePixmap {
size_t GetDmaBufOffset(size_t plane) const override;
size_t GetDmaBufPlaneSize(size_t plane) const override;
size_t GetNumberOfPlanes() const override;
+ bool SupportsZeroCopyWebGPUImport() const override;
uint64_t GetBufferFormatModifier() const override;
gfx::BufferFormat GetBufferFormat() const override;
gfx::Size GetBufferSize() const override;
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index 5e5b8493a1b..0c54d912c79 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -270,15 +270,13 @@ GbmSurfaceFactory::GetAllowedGLImplementations() {
return std::vector<gl::GLImplementationParts>{
gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
- gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
- gl::GLImplementationParts(gl::kGLImplementationSwiftShaderGL)};
+ gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader)};
}
GLOzone* GbmSurfaceFactory::GetGLOzone(
const gl::GLImplementationParts& implementation) {
switch (implementation.gl) {
case gl::kGLImplementationEGLGLES2:
- case gl::kGLImplementationSwiftShaderGL:
case gl::kGLImplementationEGLANGLE:
return egl_implementation_.get();
default:
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 5279a9f9245..7cee75377b1 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/notreached.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/gpu_fence_handle.h"
@@ -166,7 +165,7 @@ void GbmSurfaceless::SwapBuffersAsync(
CHECK_NE(fence, EGL_NO_SYNC_KHR) << "eglCreateSyncKHR failed";
base::OnceClosure fence_wait_task =
- base::BindOnce(&WaitForFence, GetDisplay(), fence);
+ base::BindOnce(&WaitForFence, GetEGLDisplay(), fence);
base::OnceClosure fence_retired_callback = base::BindOnce(
&GbmSurfaceless::FenceRetired, weak_factory_.GetWeakPtr(), frame);
@@ -206,7 +205,7 @@ EGLConfig GbmSurfaceless::GetConfig() {
EGL_SURFACE_TYPE,
EGL_DONT_CARE,
EGL_NONE};
- config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
+ config_ = ChooseEGLConfig(GetEGLDisplay(), config_attribs);
}
return config_;
}
@@ -282,7 +281,7 @@ EGLSyncKHR GbmSurfaceless::InsertFence(bool implicit) {
const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
EGL_NONE};
- return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR,
+ return eglCreateSyncKHR(GetEGLDisplay(), EGL_SYNC_FENCE_KHR,
implicit ? attrib_list : NULL);
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 2809e5983e1..91b0861cbd4 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -517,7 +517,7 @@ void HardwareDisplayController::AllocateCursorBuffers() {
gfx::Size max_cursor_size = GetMaximumCursorSize(GetDrmDevice()->get_fd());
SkImageInfo info = SkImageInfo::MakeN32Premul(max_cursor_size.width(),
max_cursor_size.height());
- for (size_t i = 0; i < base::size(cursor_buffers_); ++i) {
+ for (size_t i = 0; i < std::size(cursor_buffers_); ++i) {
cursor_buffers_[i] = std::make_unique<DrmDumbBuffer>(GetDrmDevice());
// Don't register a framebuffer for cursors since they are special (they
// aren't modesetting buffers and drivers may fail to register them due to
@@ -531,7 +531,7 @@ void HardwareDisplayController::AllocateCursorBuffers() {
DrmDumbBuffer* HardwareDisplayController::NextCursorBuffer() {
++cursor_frontbuffer_;
- cursor_frontbuffer_ %= base::size(cursor_buffers_);
+ cursor_frontbuffer_ %= std::size(cursor_buffers_);
return cursor_buffers_[cursor_frontbuffer_].get();
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index 70bd00b8afc..689f636e634 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -520,4 +520,16 @@ void HardwareDisplayPlaneManager::ResetModesetStateForCrtc(uint32_t crtc_id) {
crtc_state.modeset_framebuffers.clear();
}
+ui::HardwareCapabilities HardwareDisplayPlaneManager::GetHardwareCapabilities(
+ uint32_t crtc_id) {
+ ui::HardwareCapabilities hc;
+ hc.num_overlay_capable_planes = std::count_if(
+ planes_.begin(), planes_.end(),
+ [crtc_id](const std::unique_ptr<HardwareDisplayPlane>& plane) {
+ return plane->type() != DRM_PLANE_TYPE_CURSOR &&
+ plane->CanUseForCrtcId(crtc_id);
+ });
+ return hc;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index b5761650e75..ba1ee1685eb 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <xf86drmMode.h>
#include <cstdint>
+#include <map>
#include <memory>
#include <vector>
@@ -19,6 +20,7 @@
#include "ui/ozone/platform/drm/gpu/crtc_commit_request.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/swap_completion_callback.h"
namespace gfx {
@@ -204,6 +206,11 @@ class HardwareDisplayPlaneManager {
// caller.
void ResetModesetStateForCrtc(uint32_t crtc_id);
+ // Gets `HardwareCapabilities` based on planes available to the specified
+ // CRTC. num_overlay_capable_planes counts both `DRM_PLANE_TYPE_PRIMARY` and
+ // `DRM_PLANE_TYPE_OVERLAY` planes.
+ ui::HardwareCapabilities GetHardwareCapabilities(uint32_t crtc_id);
+
protected:
struct ConnectorProperties {
uint32_t id;
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
index 3c8592f3259..4bd30ea831d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/presentation_feedback.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index 8af1afef63c..2b129797f29 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -1180,6 +1180,51 @@ TEST_P(HardwareDisplayPlaneManagerTest, ForceOpaqueFormatsForAddFramebuffer) {
}
}
+TEST_P(HardwareDisplayPlaneManagerTest, GetHardwareCapabilities) {
+ InitializeDrmState(/*crtc_count=*/4, /*planes_per_crtc=*/7);
+ fake_drm_->InitializeState(crtc_properties_, connector_properties_,
+ plane_properties_, property_names_, use_atomic_);
+
+ for (int i = 0; i < 4; ++i) {
+ // Legacy doesn't support OVERLAY planes.
+ int expected_planes = use_atomic_ ? 7 : 1;
+ EXPECT_EQ(fake_drm_->plane_manager()
+ ->GetHardwareCapabilities(kCrtcIdBase + i)
+ .num_overlay_capable_planes,
+ expected_planes);
+ }
+
+ {
+ // Change the last (CURSOR) plane into a PRIMARY plane that is available to
+ // only the first two CRTCs.
+ auto& last_props = plane_properties_[plane_properties_.size() - 1];
+ last_props.crtc_mask = (1 << 0) | (1 << 1);
+ // Find the type property and change it to PRIMARY.
+ for (auto& property : last_props.properties) {
+ if (property.id == kTypePropId) {
+ property.value = DRM_PLANE_TYPE_PRIMARY;
+ break;
+ }
+ }
+
+ fake_drm_->InitializeState(crtc_properties_, connector_properties_,
+ plane_properties_, property_names_, use_atomic_);
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ // Legacy doesn't support OVERLAY planes.
+ int expected_planes = use_atomic_ ? 7 : 1;
+ // First two CRTCs have the newly added plane available.
+ if (i == 0 || i == 1) {
+ expected_planes++;
+ }
+ EXPECT_EQ(fake_drm_->plane_manager()
+ ->GetHardwareCapabilities(kCrtcIdBase + i)
+ .num_overlay_capable_planes,
+ expected_planes);
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(All,
HardwareDisplayPlaneManagerTest,
testing::Values(false, true));
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index 1ef0fe9f11f..6501e9a0906 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
+#include <stdint.h>
#include <xf86drm.h>
#include <memory>
#include <utility>
@@ -24,6 +25,7 @@ struct drmModeAtomicReqItem {
uint32_t object_id;
uint32_t property_id;
uint64_t value;
+ uint32_t cursor;
};
typedef drmModeAtomicReqItem* drmModeAtomicReqItemPtr;
diff --git a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
index 40923002821..030b4922fc7 100644
--- a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
+++ b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
@@ -5,9 +5,9 @@
#ifndef UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
#define UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
-
#include "base/atomic_ref_count.h"
#include "base/callback.h"
+#include "base/time/time.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/public/swap_completion_callback.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index b605816e01c..dc0c7ff05a4 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -986,7 +986,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) {
new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
window->Initialize();
gfx::Rect new_bounds = GetPrimaryBounds();
- new_bounds.Inset(0, 0, 1, 1);
+ new_bounds.Inset(gfx::Insets::TLBR(0, 0, 1, 1));
window->SetBounds(new_bounds);
screen_manager_->AddWindow(1, std::move(window));
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
index 38b8e5ce65e..8695aafd157 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
@@ -8,6 +8,8 @@
#include <utility>
#include "base/memory/scoped_refptr.h"
+#include "base/task/current_thread.h"
+#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
@@ -28,12 +30,12 @@ using mojom::CursorType;
class NullProxy : public DrmCursorProxy {
public:
- NullProxy() {}
+ NullProxy() = default;
NullProxy(const NullProxy&) = delete;
NullProxy& operator=(const NullProxy&) = delete;
- ~NullProxy() override {}
+ ~NullProxy() override = default;
void CursorSet(gfx::AcceleratedWidget window,
const std::vector<SkBitmap>& bitmaps,
@@ -46,17 +48,18 @@ class NullProxy : public DrmCursorProxy {
} // namespace
DrmCursor::DrmCursor(DrmWindowHostManager* window_manager)
- : window_(gfx::kNullAcceleratedWidget),
+ : ui_thread_(base::ThreadTaskRunnerHandle::Get()),
+ window_(gfx::kNullAcceleratedWidget),
window_manager_(window_manager),
proxy_(new NullProxy()) {
- evdev_thread_checker_.DetachFromThread();
+ DETACH_FROM_THREAD(evdev_thread_checker_);
}
-DrmCursor::~DrmCursor() {}
+DrmCursor::~DrmCursor() = default;
void DrmCursor::SetDrmCursorProxy(std::unique_ptr<DrmCursorProxy> proxy) {
TRACE_EVENT0("drmcursor", "DrmCursor::SetDrmCursorProxy");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
base::AutoLock lock(lock_);
proxy_ = std::move(proxy);
if (window_ != gfx::kNullAcceleratedWidget)
@@ -65,21 +68,22 @@ void DrmCursor::SetDrmCursorProxy(std::unique_ptr<DrmCursorProxy> proxy) {
void DrmCursor::ResetDrmCursorProxy() {
TRACE_EVENT0("drmcursor", "DrmCursor::ResetDrmCursorProxy");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
NullProxy* np = new NullProxy();
base::AutoLock lock(lock_);
proxy_.reset(np);
}
-gfx::Point DrmCursor::GetBitmapLocationLocked() {
+gfx::Point DrmCursor::GetBitmapLocationLocked()
+ EXCLUSIVE_LOCKS_REQUIRED(lock_) {
return gfx::ToFlooredPoint(location_) - cursor_->hotspot().OffsetFromOrigin();
}
void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
scoped_refptr<BitmapCursor> platform_cursor) {
TRACE_EVENT0("drmcursor", "DrmCursor::SetCursor");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
DCHECK_NE(window, gfx::kNullAcceleratedWidget);
DCHECK(platform_cursor);
@@ -97,7 +101,7 @@ void DrmCursor::OnWindowAdded(gfx::AcceleratedWidget window,
const gfx::Rect& bounds_in_screen,
const gfx::Rect& cursor_confined_bounds) {
TRACE_EVENT0("drmcursor", "DrmCursor::OnWindowAdded");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
base::AutoLock lock(lock_);
if (window_ == gfx::kNullAcceleratedWidget) {
@@ -111,7 +115,7 @@ void DrmCursor::OnWindowAdded(gfx::AcceleratedWidget window,
void DrmCursor::OnWindowRemoved(gfx::AcceleratedWidget window) {
TRACE_EVENT0("drmcursor", "DrmCursor::OnWindowRemoved");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
base::AutoLock lock(lock_);
if (window_ == window) {
@@ -138,7 +142,7 @@ void DrmCursor::CommitBoundsChange(
const gfx::Rect& new_display_bounds_in_screen,
const gfx::Rect& new_confined_bounds) {
TRACE_EVENT0("drmcursor", "DrmCursor::CommitBoundsChange");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
base::AutoLock lock(lock_);
if (window_ == window) {
@@ -152,7 +156,7 @@ void DrmCursor::CommitBoundsChange(
void DrmCursor::MoveCursorTo(gfx::AcceleratedWidget window,
const gfx::PointF& location) {
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursorTo (window)");
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
base::AutoLock lock(lock_);
gfx::AcceleratedWidget old_window = window_;
@@ -178,7 +182,31 @@ void DrmCursor::MoveCursorTo(gfx::AcceleratedWidget window,
void DrmCursor::MoveCursorTo(const gfx::PointF& screen_location) {
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursorTo");
- DCHECK(thread_checker_.CalledOnValidThread());
+ if (ui_thread_->BelongsToCurrentThread())
+ MoveCursorToOnUiThread(screen_location);
+ else
+ MoveCursorToOnEvdevThread(screen_location);
+}
+
+void DrmCursor::MoveCursorToOnUiThread(const gfx::PointF& screen_location) {
+ DCHECK_CALLED_ON_VALID_THREAD(ui_thread_checker_);
+
+ const auto* window =
+ window_manager_->GetWindowAt(gfx::ToRoundedPoint(screen_location));
+ if (!window) {
+ // See b/221758935#comment18 for why we need to silently ignore this error
+ // here.
+ return;
+ }
+
+ auto location_in_window =
+ screen_location - window->GetBounds().OffsetFromOrigin();
+ MoveCursorTo(window->GetAcceleratedWidget(), location_in_window);
+}
+
+void DrmCursor::MoveCursorToOnEvdevThread(const gfx::PointF& screen_location) {
+ DCHECK_CALLED_ON_VALID_THREAD(evdev_thread_checker_);
+
base::AutoLock lock(lock_);
// TODO(spang): Moving between windows doesn't work here, but
@@ -190,7 +218,12 @@ void DrmCursor::MoveCursorTo(const gfx::PointF& screen_location) {
}
void DrmCursor::MoveCursor(const gfx::Vector2dF& delta) {
- DCHECK(evdev_thread_checker_.CalledOnValidThread());
+#if DCHECK_IS_ON()
+ // We explicitly check for DCHECK_IS_ON() as |ui_thread_checker_| and
+ // |evdev_thread_checker_| do not exist on non-DCHECK builds.
+ DCHECK(evdev_thread_checker_.CalledOnValidThread() ||
+ ui_thread_checker_.CalledOnValidThread());
+#endif
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursor");
base::AutoLock lock(lock_);
@@ -224,12 +257,13 @@ gfx::Rect DrmCursor::GetCursorConfinedBounds() {
}
void DrmCursor::InitializeOnEvdev() {
- DCHECK(evdev_thread_checker_.CalledOnValidThread());
+ DCHECK_CALLED_ON_VALID_THREAD(evdev_thread_checker_);
base::AutoLock lock(lock_);
proxy_->InitializeOnEvdevIfNecessary();
}
-void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) {
+void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location)
+ EXCLUSIVE_LOCKS_REQUIRED(lock_) {
gfx::PointF clamped_location = location;
clamped_location.SetToMax(gfx::PointF(confined_bounds_.origin()));
// Right and bottom edges are exclusive.
@@ -242,7 +276,7 @@ void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) {
#endif
}
-void DrmCursor::SendCursorShowLocked() {
+void DrmCursor::SendCursorShowLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
if (!cursor_ || cursor_->type() == CursorType::kNone) {
SendCursorHideLocked();
return;
@@ -252,12 +286,12 @@ void DrmCursor::SendCursorShowLocked() {
cursor_->frame_delay());
}
-void DrmCursor::SendCursorHideLocked() {
+void DrmCursor::SendCursorHideLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
CursorSetLockTested(window_, std::vector<SkBitmap>(), gfx::Point(),
base::TimeDelta());
}
-void DrmCursor::SendCursorMoveLocked() {
+void DrmCursor::SendCursorMoveLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_) {
if (!cursor_ || cursor_->type() == CursorType::kNone)
return;
@@ -279,5 +313,4 @@ void DrmCursor::MoveLockTested(gfx::AcceleratedWidget window,
proxy_->Move(window, point);
}
-
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.h b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
index e0d2a65476b..b9e90735861 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
+#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
#include "ui/gfx/geometry/rect.h"
@@ -27,7 +28,7 @@ class DrmWindowHostManager;
// processes. The proxy implementation must satisfy DrmCursorProxy.
class DrmCursorProxy {
public:
- virtual ~DrmCursorProxy() {}
+ virtual ~DrmCursorProxy() = default;
// Sets the cursor |bitmaps| on |window| at |point| with |frame_delay|.
virtual void CursorSet(gfx::AcceleratedWidget window,
@@ -88,6 +89,9 @@ class DrmCursor : public CursorDelegateEvdev {
void SendCursorHideLocked();
void SendCursorMoveLocked();
+ void MoveCursorToOnEvdevThread(const gfx::PointF& screen_location);
+ void MoveCursorToOnUiThread(const gfx::PointF& screen_location);
+
// Lock-testing helpers.
void CursorSetLockTested(gfx::AcceleratedWidget window,
const std::vector<SkBitmap>& bitmaps,
@@ -99,30 +103,33 @@ class DrmCursor : public CursorDelegateEvdev {
base::Lock lock_;
// Enforce our threading constraints.
- base::ThreadChecker thread_checker_;
- base::ThreadChecker evdev_thread_checker_;
+ THREAD_CHECKER(ui_thread_checker_);
+ THREAD_CHECKER(evdev_thread_checker_);
+
+ scoped_refptr<base::SingleThreadTaskRunner> ui_thread_;
// The location of the bitmap (the cursor location is the hotspot location).
gfx::Point GetBitmapLocationLocked();
// The current cursor bitmap (immutable).
- scoped_refptr<BitmapCursor> cursor_;
+ scoped_refptr<BitmapCursor> cursor_ GUARDED_BY(lock_);
// The window under the cursor.
- gfx::AcceleratedWidget window_;
+ gfx::AcceleratedWidget window_ GUARDED_BY(lock_);
// The location of the cursor within the window.
- gfx::PointF location_;
+ gfx::PointF location_ GUARDED_BY(lock_);
// The bounds of the display under the cursor.
- gfx::Rect display_bounds_in_screen_;
+ gfx::Rect display_bounds_in_screen_ GUARDED_BY(lock_);
// The bounds that the cursor is confined to in |window|.
- gfx::Rect confined_bounds_;
+ gfx::Rect confined_bounds_ GUARDED_BY(lock_);
- DrmWindowHostManager* const window_manager_; // Not owned.
+ DrmWindowHostManager* const window_manager_
+ GUARDED_BY_CONTEXT(ui_thread_checker_); // Not owned.
- std::unique_ptr<DrmCursorProxy> proxy_;
+ std::unique_ptr<DrmCursorProxy> proxy_ GUARDED_BY(lock_);
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
index 6bda9fb2df7..f8cc4fce0cc 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -11,11 +11,11 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -27,6 +27,7 @@
#include "ui/ozone/platform/drm/host/drm_display_host.h"
#include "ui/ozone/platform/drm/host/drm_native_display_delegate.h"
#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
+#include "ui/ozone/public/ozone_switches.h"
namespace ui {
@@ -108,8 +109,12 @@ base::FilePath GetPrimaryDisplayCardPath() {
for (int i = 0; /* end on first card# that does not exist */; i++) {
std::string card_path = base::StringPrintf(kDefaultGraphicsCardPattern, i);
- if (access(card_path.c_str(), F_OK) != 0)
- break;
+ if (access(card_path.c_str(), F_OK) != 0) {
+ if (i == 0) /* card paths may start with 0 or 1 */
+ continue;
+ else
+ break;
+ }
base::ScopedFD fd(open(card_path.c_str(), O_RDWR | O_CLOEXEC));
if (!fd.is_valid()) {
@@ -184,6 +189,15 @@ DrmDisplayHostManager::DrmDisplayHostManager(
}
host_properties->supports_overlays =
primary_drm_device_handle_->has_atomic_capabilities();
+ // TODO(b/192563524): The legacy video decoder wraps its frames with legacy
+ // mailboxes instead of SharedImages. The display compositor can composite
+ // these quads, but does not support promoting them to overlays. Thus, we
+ // disable overlays on platforms using the legacy video decoder.
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(
+ switches::kPlatformDisallowsChromeOSDirectVideoDecoder)) {
+ host_properties->supports_overlays = false;
+ }
drm_devices_[primary_graphics_card_path_] =
primary_graphics_card_path_sysfs;
}
diff --git a/chromium/ui/ozone/platform/flatland/flatland_surface.h b/chromium/ui/ozone/platform/flatland/flatland_surface.h
index fb344468c7a..e2fa3a7f98d 100644
--- a/chromium/ui/ozone/platform/flatland/flatland_surface.h
+++ b/chromium/ui/ozone/platform/flatland/flatland_surface.h
@@ -12,6 +12,7 @@
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc b/chromium/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
index 06b1c49e713..de5cfbdc782 100644
--- a/chromium/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
+++ b/chromium/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
@@ -648,8 +648,7 @@ void FlatlandSysmemBufferCollection::InitializeImageCreateInfo(
vk_image_info->usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (usage_ == gfx::BufferUsage::SCANOUT ||
- usage_ == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE) {
+ if (usage_ == gfx::BufferUsage::SCANOUT) {
vk_image_info->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
diff --git a/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.cc b/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.cc
index 54d79fa2fe6..0423510e873 100644
--- a/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.cc
+++ b/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.cc
@@ -46,6 +46,13 @@ size_t FlatlandSysmemNativePixmap::GetNumberOfPlanes() const {
return 0;
}
+bool FlatlandSysmemNativePixmap::SupportsZeroCopyWebGPUImport() const {
+ NOTREACHED();
+ // TODO(crbug.com/1304490): Figure out how to import multi-planar pixmap into
+ // WebGPU without copy.
+ return false;
+}
+
uint64_t FlatlandSysmemNativePixmap::GetBufferFormatModifier() const {
NOTREACHED();
return 0;
diff --git a/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.h b/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.h
index ad7d6a8f46c..a5d6d0d1c5e 100644
--- a/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.h
+++ b/chromium/ui/ozone/platform/flatland/flatland_sysmem_native_pixmap.h
@@ -27,6 +27,7 @@ class FlatlandSysmemNativePixmap : public gfx::NativePixmap {
size_t GetDmaBufOffset(size_t plane) const override;
size_t GetDmaBufPlaneSize(size_t plane) const override;
size_t GetNumberOfPlanes() const override;
+ bool SupportsZeroCopyWebGPUImport() const override;
uint64_t GetBufferFormatModifier() const override;
gfx::BufferFormat GetBufferFormat() const override;
gfx::Size GetBufferSize() const override;
diff --git a/chromium/ui/ozone/platform/flatland/flatland_window.cc b/chromium/ui/ozone/platform/flatland/flatland_window.cc
index c7663034038..5723c828001 100644
--- a/chromium/ui/ozone/platform/flatland/flatland_window.cc
+++ b/chromium/ui/ozone/platform/flatland/flatland_window.cc
@@ -213,7 +213,11 @@ PlatformWindowState FlatlandWindow::GetPlatformWindowState() const {
return PlatformWindowState::kFullScreen;
if (!is_view_attached_)
return PlatformWindowState::kMinimized;
- return PlatformWindowState::kNormal;
+
+ // TODO(crbug.com/1241868): We cannot tell what portion of the screen is
+ // occupied by the View, so report is as maximized to reduce the space used
+ // by any browser chrome.
+ return PlatformWindowState::kMaximized;
}
void FlatlandWindow::Activate() {
diff --git a/chromium/ui/ozone/platform/flatland/vulkan_implementation_flatland.cc b/chromium/ui/ozone/platform/flatland/vulkan_implementation_flatland.cc
index 60da05573a4..1653d4ec37c 100644
--- a/chromium/ui/ozone/platform/flatland/vulkan_implementation_flatland.cc
+++ b/chromium/ui/ozone/platform/flatland/vulkan_implementation_flatland.cc
@@ -225,6 +225,7 @@ VulkanImplementationFlatland::CreateImageFromGpuMemoryHandle(
return nullptr;
}
+ image->set_queue_family_index(VK_QUEUE_FAMILY_EXTERNAL);
image->set_native_pixmap(collection->CreateNativePixmap(
gmb_handle.native_pixmap_handle.buffer_index));
return image;
diff --git a/chromium/ui/ozone/platform/headless/BUILD.gn b/chromium/ui/ozone/platform/headless/BUILD.gn
index 16209948a6d..20a2ef3fb0f 100644
--- a/chromium/ui/ozone/platform/headless/BUILD.gn
+++ b/chromium/ui/ozone/platform/headless/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//gpu/vulkan/features.gni")
+
visibility = [ "//ui/ozone/*" ]
source_set("headless") {
@@ -24,6 +26,9 @@ source_set("headless") {
deps = [
"//base",
+ "//build:chromecast_buildflags",
+ "//build:chromeos_buildflags",
+ "//gpu/vulkan:buildflags",
"//skia",
"//ui/base",
"//ui/base/cursor",
@@ -41,4 +46,14 @@ source_set("headless") {
if (is_fuchsia) {
deps += [ "//ui/base/ime/fuchsia" ]
}
+
+ if (enable_vulkan && is_linux) {
+ sources += [
+ "vulkan_implementation_headless.cc",
+ "vulkan_implementation_headless.h",
+ "vulkan_surface_headless.cc",
+ "vulkan_surface_headless.h",
+ ]
+ deps += [ "//gpu/vulkan" ]
+ }
}
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
index cad85b0856a..95ee659bd66 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -11,12 +11,16 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "skia/ext/legacy_display_globals.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkPixmap.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/core/SkSurfaceProps.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/skia_conversions.h"
@@ -30,6 +34,10 @@
#include "ui/ozone/platform/headless/headless_window_manager.h"
#include "ui/ozone/public/surface_ozone_canvas.h"
+#if BUILDFLAG(ENABLE_VULKAN) && BUILDFLAG(IS_LINUX)
+#include "ui/ozone/platform/headless/vulkan_implementation_headless.h"
+#endif
+
namespace ui {
namespace {
@@ -156,6 +164,7 @@ class TestPixmap : public gfx::NativePixmap {
size_t GetNumberOfPlanes() const override {
return gfx::NumberOfPlanesForLinearBufferFormat(format_);
}
+ bool SupportsZeroCopyWebGPUImport() const override { return false; }
gfx::Size GetBufferSize() const override { return gfx::Size(); }
uint32_t GetUniqueId() const override { return 0; }
bool ScheduleOverlayPlane(
@@ -226,7 +235,6 @@ HeadlessSurfaceFactory::~HeadlessSurfaceFactory() = default;
std::vector<gl::GLImplementationParts>
HeadlessSurfaceFactory::GetAllowedGLImplementations() {
return std::vector<gl::GLImplementationParts>{
- gl::GLImplementationParts(gl::kGLImplementationSwiftShaderGL),
gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
gl::GLImplementationParts(gl::ANGLEImplementation::kDefault),
@@ -237,7 +245,6 @@ GLOzone* HeadlessSurfaceFactory::GetGLOzone(
const gl::GLImplementationParts& implementation) {
switch (implementation.gl) {
case gl::kGLImplementationEGLGLES2:
- case gl::kGLImplementationSwiftShaderGL:
case gl::kGLImplementationEGLANGLE:
return swiftshader_implementation_.get();
@@ -273,4 +280,13 @@ void HeadlessSurfaceFactory::CheckBasePath() const {
PLOG(FATAL) << "Unable to write to output location";
}
+#if BUILDFLAG(ENABLE_VULKAN) && BUILDFLAG(IS_LINUX)
+std::unique_ptr<gpu::VulkanImplementation>
+HeadlessSurfaceFactory::CreateVulkanImplementation(
+ bool use_swiftshader,
+ bool allow_protected_memory) {
+ return std::make_unique<VulkanImplementationHeadless>(use_swiftshader);
+}
+#endif
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.h b/chromium/ui/ozone/platform/headless/headless_surface_factory.h
index bbd129fbbc0..bf58e12f346 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.h
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.h
@@ -26,6 +26,11 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone {
// SurfaceFactoryOzone:
std::vector<gl::GLImplementationParts> GetAllowedGLImplementations() override;
GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override;
+#if BUILDFLAG(ENABLE_VULKAN) && BUILDFLAG(IS_LINUX)
+ std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
+ bool use_swiftshader,
+ bool allow_protected_memory) override;
+#endif
std::unique_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
gfx::AcceleratedWidget widget) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmap(
diff --git a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
index 9f489c75089..011827af226 100644
--- a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -8,7 +8,10 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
+#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/ime/input_method_minimal.h"
#include "ui/display/types/native_display_delegate.h"
@@ -98,6 +101,20 @@ class OzonePlatformHeadless : public OzonePlatform {
return std::make_unique<InputMethodMinimal>(delegate);
}
+// Desktop Linux, not ChromeOS.
+#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
+ !BUILDFLAG(IS_CHROMEOS_LACROS) && !BUILDFLAG(IS_CHROMECAST)
+ const PlatformProperties& GetPlatformProperties() override {
+ static base::NoDestructor<OzonePlatform::PlatformProperties> properties;
+ static bool initialized = false;
+ if (!initialized) {
+ properties->uses_external_vulkan_image_factory = true;
+ initialized = true;
+ }
+ return *properties;
+ }
+#endif
+
bool InitializeUI(const InitParams& params) override {
window_manager_ = std::make_unique<HeadlessWindowManager>();
surface_factory_ = std::make_unique<HeadlessSurfaceFactory>(file_path_);
diff --git a/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.cc b/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.cc
new file mode 100644
index 00000000000..e9c7feb22c6
--- /dev/null
+++ b/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/headless/vulkan_implementation_headless.h"
+
+#include "base/base_paths.h"
+#include "base/callback_helpers.h"
+#include "base/files/file_path.h"
+#include "base/notreached.h"
+#include "base/path_service.h"
+#include "base/scoped_environment_variable_override.h"
+#include "gpu/vulkan/vulkan_function_pointers.h"
+#include "gpu/vulkan/vulkan_image.h"
+#include "gpu/vulkan/vulkan_instance.h"
+#include "gpu/vulkan/vulkan_surface.h"
+#include "gpu/vulkan/vulkan_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/ozone/platform/headless/vulkan_surface_headless.h"
+
+namespace ui {
+
+VulkanImplementationHeadless::VulkanImplementationHeadless(bool use_swiftshader)
+ : gpu::VulkanImplementation(use_swiftshader) {}
+
+bool VulkanImplementationHeadless::InitializeVulkanInstance(
+ bool using_surface) {
+ using_surface_ = using_surface;
+
+ std::vector<const char*> required_extensions = {
+ VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME};
+ if (using_surface_) {
+ required_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
+ required_extensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME);
+ }
+
+ base::FilePath path;
+ if (use_swiftshader()) {
+ if (!base::PathService::Get(base::DIR_MODULE, &path))
+ return false;
+ path = path.Append("libvk_swiftshader.so");
+ } else {
+ path = base::FilePath("libvulkan.so.1");
+ }
+
+ return vulkan_instance_.Initialize(path, required_extensions, {});
+}
+
+gpu::VulkanInstance* VulkanImplementationHeadless::GetVulkanInstance() {
+ return &vulkan_instance_;
+}
+
+std::unique_ptr<gpu::VulkanSurface>
+VulkanImplementationHeadless::CreateViewSurface(gfx::AcceleratedWidget window) {
+ if (!using_surface_)
+ return nullptr;
+ return VulkanSurfaceHeadless::Create(vulkan_instance_.vk_instance(), window);
+}
+
+bool VulkanImplementationHeadless::GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice device,
+ const std::vector<VkQueueFamilyProperties>& queue_family_properties,
+ uint32_t queue_family_index) {
+ // TODO(samans): Don't early out once Swiftshader supports this method.
+ // https://crbug.com/swiftshader/129
+ if (use_swiftshader())
+ return true;
+ // Should this be false?
+ return true;
+}
+
+std::vector<const char*>
+VulkanImplementationHeadless::GetRequiredDeviceExtensions() {
+ std::vector<const char*> extensions;
+ if (using_surface_)
+ extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+ return extensions;
+}
+
+std::vector<const char*>
+VulkanImplementationHeadless::GetOptionalDeviceExtensions() {
+ return {
+ VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
+ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
+ VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
+ VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
+ };
+}
+
+VkFence VulkanImplementationHeadless::CreateVkFenceForGpuFence(
+ VkDevice vk_device) {
+ NOTREACHED();
+ return VK_NULL_HANDLE;
+}
+
+std::unique_ptr<gfx::GpuFence>
+VulkanImplementationHeadless::ExportVkFenceToGpuFence(VkDevice vk_device,
+ VkFence vk_fence) {
+ NOTREACHED();
+ return nullptr;
+}
+
+VkSemaphore VulkanImplementationHeadless::CreateExternalSemaphore(
+ VkDevice vk_device) {
+ return gpu::CreateExternalVkSemaphore(
+ vk_device, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
+}
+
+VkSemaphore VulkanImplementationHeadless::ImportSemaphoreHandle(
+ VkDevice vk_device,
+ gpu::SemaphoreHandle sync_handle) {
+ return ImportVkSemaphoreHandle(vk_device, std::move(sync_handle));
+}
+
+gpu::SemaphoreHandle VulkanImplementationHeadless::GetSemaphoreHandle(
+ VkDevice vk_device,
+ VkSemaphore vk_semaphore) {
+ return gpu::GetVkSemaphoreHandle(
+ vk_device, vk_semaphore, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
+}
+
+VkExternalMemoryHandleTypeFlagBits
+VulkanImplementationHeadless::GetExternalImageHandleType() {
+ return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+}
+
+bool VulkanImplementationHeadless::CanImportGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType memory_buffer_type) {
+ if (memory_buffer_type == gfx::GpuMemoryBufferType::NATIVE_PIXMAP)
+ return true;
+ return false;
+}
+
+std::unique_ptr<gpu::VulkanImage>
+VulkanImplementationHeadless::CreateImageFromGpuMemoryHandle(
+ gpu::VulkanDeviceQueue* device_queue,
+ gfx::GpuMemoryBufferHandle gmb_handle,
+ gfx::Size size,
+ VkFormat vk_format) {
+ constexpr auto kUsage =
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ auto tiling = gmb_handle.native_pixmap_handle.modifier ==
+ gfx::NativePixmapHandle::kNoModifier
+ ? VK_IMAGE_TILING_OPTIMAL
+ : VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
+ return gpu::VulkanImage::CreateFromGpuMemoryBufferHandle(
+ device_queue, std::move(gmb_handle), size, vk_format, kUsage, /*flags=*/0,
+ tiling, VK_QUEUE_FAMILY_EXTERNAL);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.h b/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.h
new file mode 100644
index 00000000000..7d4912d9d51
--- /dev/null
+++ b/chromium/ui/ozone/platform/headless/vulkan_implementation_headless.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_HEADLESS_VULKAN_IMPLEMENTATION_HEADLESS_H_
+#define UI_OZONE_PLATFORM_HEADLESS_VULKAN_IMPLEMENTATION_HEADLESS_H_
+
+#include <memory>
+#include <vector>
+
+#include "gpu/vulkan/vulkan_implementation.h"
+#include "gpu/vulkan/vulkan_instance.h"
+
+namespace ui {
+
+class VulkanImplementationHeadless : public gpu::VulkanImplementation {
+ public:
+ explicit VulkanImplementationHeadless(bool use_swiftshader = false);
+
+ VulkanImplementationHeadless(const VulkanImplementationHeadless&) = delete;
+ VulkanImplementationHeadless& operator=(const VulkanImplementationHeadless&) =
+ delete;
+
+ // VulkanImplementation:
+ bool InitializeVulkanInstance(bool using_surface) override;
+ gpu::VulkanInstance* GetVulkanInstance() override;
+ std::unique_ptr<gpu::VulkanSurface> CreateViewSurface(
+ gfx::AcceleratedWidget window) override;
+ bool GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice device,
+ const std::vector<VkQueueFamilyProperties>& queue_family_properties,
+ uint32_t queue_family_index) override;
+ std::vector<const char*> GetRequiredDeviceExtensions() override;
+ std::vector<const char*> GetOptionalDeviceExtensions() override;
+ VkFence CreateVkFenceForGpuFence(VkDevice vk_device) override;
+ std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(
+ VkDevice vk_device,
+ VkFence vk_fence) override;
+ VkSemaphore CreateExternalSemaphore(VkDevice vk_device) override;
+ VkSemaphore ImportSemaphoreHandle(VkDevice vk_device,
+ gpu::SemaphoreHandle handle) override;
+ gpu::SemaphoreHandle GetSemaphoreHandle(VkDevice vk_device,
+ VkSemaphore vk_semaphore) override;
+ VkExternalMemoryHandleTypeFlagBits GetExternalImageHandleType() override;
+ bool CanImportGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType memory_buffer_type) override;
+ std::unique_ptr<gpu::VulkanImage> CreateImageFromGpuMemoryHandle(
+ gpu::VulkanDeviceQueue* device_queue,
+ gfx::GpuMemoryBufferHandle gmb_handle,
+ gfx::Size size,
+ VkFormat vk_formae) override;
+
+ private:
+ bool using_surface_ = true;
+ gpu::VulkanInstance vulkan_instance_;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_HEADLESS_VULKAN_IMPLEMENTATION_HEADLESS_H_
diff --git a/chromium/ui/ozone/platform/headless/vulkan_surface_headless.cc b/chromium/ui/ozone/platform/headless/vulkan_surface_headless.cc
new file mode 100644
index 00000000000..e421a7e5f3a
--- /dev/null
+++ b/chromium/ui/ozone/platform/headless/vulkan_surface_headless.cc
@@ -0,0 +1,38 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/headless/vulkan_surface_headless.h"
+
+#include "base/logging.h"
+#include "gpu/vulkan/vulkan_function_pointers.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+
+// static
+std::unique_ptr<VulkanSurfaceHeadless> VulkanSurfaceHeadless::Create(
+ VkInstance vk_instance,
+ gfx::AcceleratedWidget widget) {
+ VkSurfaceKHR vk_surface;
+ const VkHeadlessSurfaceCreateInfoEXT surface_create_info = {
+ .sType = VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT,
+ .pNext = nullptr,
+ .flags = 0,
+ };
+ VkResult result = vkCreateHeadlessSurfaceEXT(
+ vk_instance, &surface_create_info, nullptr, &vk_surface);
+ if (VK_SUCCESS != result) {
+ DLOG(ERROR) << "vkCreateHeadlessSurfaceEXT() failed: " << result;
+ return nullptr;
+ }
+ return std::make_unique<VulkanSurfaceHeadless>(vk_instance, vk_surface,
+ widget);
+}
+
+VulkanSurfaceHeadless::VulkanSurfaceHeadless(VkInstance vk_instance,
+ VkSurfaceKHR vk_surface,
+ gfx::AcceleratedWidget widget)
+ : gpu::VulkanSurface(vk_instance, widget, vk_surface) {}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/headless/vulkan_surface_headless.h b/chromium/ui/ozone/platform/headless/vulkan_surface_headless.h
new file mode 100644
index 00000000000..fb9ded1823c
--- /dev/null
+++ b/chromium/ui/ozone/platform/headless/vulkan_surface_headless.h
@@ -0,0 +1,30 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_HEADLESS_VULKAN_SURFACE_HEADLESS_H_
+#define UI_OZONE_PLATFORM_HEADLESS_VULKAN_SURFACE_HEADLESS_H_
+
+#include <vulkan/vulkan.h>
+#include <memory>
+
+#include "gpu/vulkan/vulkan_surface.h"
+
+namespace ui {
+
+class VulkanSurfaceHeadless : public gpu::VulkanSurface {
+ public:
+ static std::unique_ptr<VulkanSurfaceHeadless> Create(
+ VkInstance vk_instance,
+ gfx::AcceleratedWidget widget);
+ VulkanSurfaceHeadless(VkInstance vk_instance,
+ VkSurfaceKHR vk_surface,
+ gfx::AcceleratedWidget widget);
+
+ VulkanSurfaceHeadless(const VulkanSurfaceHeadless&) = delete;
+ VulkanSurfaceHeadless& operator=(const VulkanSurfaceHeadless&) = delete;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_HEADLESS_VULKAN_SURFACE_HEADLESS_H_
diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface.h b/chromium/ui/ozone/platform/scenic/scenic_surface.h
index 485bae74328..e2a3344ae81 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_surface.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_surface.h
@@ -18,6 +18,7 @@
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.cc b/chromium/ui/ozone/platform/scenic/scenic_window.cc
index 4a6589222e8..22b8fbab2ad 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_window.cc
@@ -35,10 +35,11 @@ namespace {
gfx::Insets ConvertInsets(
float device_pixel_ratio,
const fuchsia::ui::gfx::ViewProperties& view_properties) {
- return gfx::Insets(device_pixel_ratio * view_properties.inset_from_min.y,
- device_pixel_ratio * view_properties.inset_from_min.x,
- device_pixel_ratio * view_properties.inset_from_max.y,
- device_pixel_ratio * view_properties.inset_from_max.x);
+ return gfx::Insets::TLBR(
+ device_pixel_ratio * view_properties.inset_from_min.y,
+ device_pixel_ratio * view_properties.inset_from_min.x,
+ device_pixel_ratio * view_properties.inset_from_max.y,
+ device_pixel_ratio * view_properties.inset_from_max.x);
}
} // namespace
@@ -206,7 +207,11 @@ PlatformWindowState ScenicWindow::GetPlatformWindowState() const {
return PlatformWindowState::kFullScreen;
if (!is_view_attached_)
return PlatformWindowState::kMinimized;
- return PlatformWindowState::kNormal;
+
+ // TODO(crbug.com/1241868): We cannot tell what portion of the screen is
+ // occupied by the View, so report is as maximized to reduce the space used
+ // by any browser chrome.
+ return PlatformWindowState::kMaximized;
}
void ScenicWindow::Activate() {
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
index fb585e20a71..4b86c0ce869 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
+++ b/chromium/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
@@ -634,8 +634,7 @@ void SysmemBufferCollection::InitializeImageCreateInfo(
vk_image_info->usage = VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (usage_ == gfx::BufferUsage::SCANOUT ||
- usage_ == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE) {
+ if (usage_ == gfx::BufferUsage::SCANOUT) {
vk_image_info->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.cc b/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.cc
index 0322f07e497..868120934d5 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.cc
+++ b/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.cc
@@ -59,6 +59,11 @@ size_t SysmemNativePixmap::GetNumberOfPlanes() const {
return 0;
}
+bool SysmemNativePixmap::SupportsZeroCopyWebGPUImport() const {
+ NOTREACHED();
+ return false;
+}
+
uint64_t SysmemNativePixmap::GetBufferFormatModifier() const {
NOTREACHED();
return 0;
diff --git a/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.h b/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.h
index b54eca948a5..80b97dda569 100644
--- a/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.h
+++ b/chromium/ui/ozone/platform/scenic/sysmem_native_pixmap.h
@@ -27,6 +27,7 @@ class SysmemNativePixmap : public gfx::NativePixmap {
size_t GetDmaBufOffset(size_t plane) const override;
size_t GetDmaBufPlaneSize(size_t plane) const override;
size_t GetNumberOfPlanes() const override;
+ bool SupportsZeroCopyWebGPUImport() const override;
uint64_t GetBufferFormatModifier() const override;
gfx::BufferFormat GetBufferFormat() const override;
gfx::Size GetBufferSize() const override;
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
index ed80cab4ce4..4ab374d9d26 100644
--- a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
+++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
@@ -284,6 +284,7 @@ VulkanImplementationScenic::CreateImageFromGpuMemoryHandle(
return nullptr;
}
+ image->set_queue_family_index(VK_QUEUE_FAMILY_EXTERNAL);
image->set_native_pixmap(collection->CreateNativePixmap(
gmb_handle.native_pixmap_handle.buffer_index));
return image;
diff --git a/chromium/ui/ozone/platform/wayland/BUILD.gn b/chromium/ui/ozone/platform/wayland/BUILD.gn
index aeaf7b8d94e..cb575394306 100644
--- a/chromium/ui/ozone/platform/wayland/BUILD.gn
+++ b/chromium/ui/ozone/platform/wayland/BUILD.gn
@@ -218,6 +218,7 @@ source_set("wayland") {
"//mojo/public/cpp/system",
"//skia",
"//third_party/libsync",
+ "//third_party/re2",
"//third_party/wayland:wayland_util",
"//third_party/wayland-protocols:alpha_compositing_protocol",
"//third_party/wayland-protocols:cursor_shapes_protocol",
@@ -245,6 +246,7 @@ source_set("wayland") {
"//ui/base",
"//ui/base:buildflags",
"//ui/base:data_exchange",
+ "//ui/base:features",
"//ui/base/cursor",
"//ui/base/cursor:theme_manager",
"//ui/base/cursor/mojom:cursor_type",
@@ -601,6 +603,7 @@ source_set("ui_test_support") {
deps = [
":wayland_proxy",
"//base",
+ "//third_party/wayland:wayland_util",
"//third_party/wayland-protocols:weston_test",
"//ui/base:test_support",
"//ui/events",
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_util.cc b/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
index 8823a541576..372e0e48dc4 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_util.cc
@@ -190,6 +190,54 @@ wl_output_transform ToWaylandTransform(gfx::OverlayTransform transform) {
return WL_OUTPUT_TRANSFORM_NORMAL;
}
+gfx::RectF ApplyWaylandTransform(const gfx::RectF& rect,
+ const gfx::SizeF& bounds,
+ wl_output_transform transform) {
+ gfx::RectF result = rect;
+ switch (transform) {
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ result.set_x(bounds.width() - rect.x() - rect.width());
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ result.set_x(rect.y());
+ result.set_y(rect.x());
+ result.set_width(rect.height());
+ result.set_height(rect.width());
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ result.set_y(bounds.height() - rect.y() - rect.height());
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ result.set_x(bounds.height() - rect.y() - rect.height());
+ result.set_y(bounds.width() - rect.x() - rect.width());
+ result.set_width(rect.height());
+ result.set_height(rect.width());
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ result.set_x(rect.y());
+ result.set_y(bounds.width() - rect.x() - rect.width());
+ result.set_width(rect.height());
+ result.set_height(rect.width());
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ result.set_x(bounds.width() - rect.x() - rect.width());
+ result.set_y(bounds.height() - rect.y() - rect.height());
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ result.set_x(bounds.height() - rect.y() - rect.height());
+ result.set_y(rect.x());
+ result.set_width(rect.height());
+ result.set_height(rect.width());
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
gfx::Rect ApplyWaylandTransform(const gfx::Rect& rect,
const gfx::Size& bounds,
wl_output_transform transform) {
@@ -301,7 +349,7 @@ SkPath ConvertPathToDIP(const SkPath& path_in_pixels, float scale) {
gfx::Transform transform;
transform.Scale(sk_scale, sk_scale);
SkPath path_in_dips;
- path_in_pixels.transform(SkMatrix(transform.matrix()), &path_in_dips);
+ path_in_pixels.transform(transform.matrix().asM33(), &path_in_dips);
return path_in_dips;
}
diff --git a/chromium/ui/ozone/platform/wayland/common/wayland_util.h b/chromium/ui/ozone/platform/wayland/common/wayland_util.h
index b8f298328ff..305dd91b123 100644
--- a/chromium/ui/ozone/platform/wayland/common/wayland_util.h
+++ b/chromium/ui/ozone/platform/wayland/common/wayland_util.h
@@ -73,6 +73,13 @@ gfx::Rect ApplyWaylandTransform(const gfx::Rect& rect,
const gfx::Size& bounds,
wl_output_transform transform);
+// |bounds| contains |rect|. ApplyWaylandTransform() returns the resulted
+// |rect| after transformation is applied to |bounds| containing |rect| as a
+// whole.
+gfx::RectF ApplyWaylandTransform(const gfx::RectF& rect,
+ const gfx::SizeF& bounds,
+ wl_output_transform transform);
+
// Applies transformation to |size|.
gfx::SizeF ApplyWaylandTransform(const gfx::SizeF& size,
wl_output_transform transform);
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 4a634386361..3d6d59d0b8a 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -34,7 +34,7 @@ GbmPixmapWayland::GbmPixmapWayland(WaylandBufferManagerGpu* buffer_manager)
GbmPixmapWayland::~GbmPixmapWayland() {
if (gbm_bo_ && widget_ != gfx::kNullAcceleratedWidget)
- buffer_manager_->DestroyBuffer(widget_, buffer_id_);
+ buffer_manager_->DestroyBuffer(buffer_id_);
}
bool GbmPixmapWayland::InitializeBuffer(
@@ -141,6 +141,12 @@ size_t GbmPixmapWayland::GetNumberOfPlanes() const {
return gbm_bo_->GetNumPlanes();
}
+bool GbmPixmapWayland::SupportsZeroCopyWebGPUImport() const {
+ // TODO(crbug.com/1258986): Figure out how to import multi-planar pixmap into
+ // WebGPU without copy.
+ return false;
+}
+
uint64_t GbmPixmapWayland::GetBufferFormatModifier() const {
return gbm_bo_->GetFormatModifier();
}
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
index e9b25a74528..49b038ba0dd 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
@@ -57,6 +57,7 @@ class GbmPixmapWayland : public gfx::NativePixmap {
size_t GetDmaBufOffset(size_t plane) const override;
size_t GetDmaBufPlaneSize(size_t plane) const override;
size_t GetNumberOfPlanes() const override;
+ bool SupportsZeroCopyWebGPUImport() const override;
uint64_t GetBufferFormatModifier() const override;
gfx::BufferFormat GetBufferFormat() const override;
gfx::Size GetBufferSize() const override;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
index d3cd4021741..380c31fb067 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -6,10 +6,11 @@
#include <sync/sync.h>
#include <cmath>
+#include <cstdint>
#include <memory>
+#include <utility>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/gpu_fence.h"
@@ -77,8 +78,7 @@ GbmSurfacelessWayland::SolidColorBufferHolder::GetOrCreateSolidColorBuffer(
void GbmSurfacelessWayland::SolidColorBufferHolder::OnSubmission(
BufferId buffer_id,
- WaylandBufferManagerGpu* buffer_manager,
- gfx::AcceleratedWidget widget) {
+ WaylandBufferManagerGpu* buffer_manager) {
// Solid color buffers do not require on submission as skia doesn't track
// them. Instead, they are tracked by GbmSurfacelessWayland. In the future,
// when SharedImageFactory allows to create non-backed shared images, this
@@ -96,7 +96,7 @@ void GbmSurfacelessWayland::SolidColorBufferHolder::OnSubmission(
// ones until the maximum number of available solid color buffer.
while (available_solid_color_buffers_.size() > kMaxSolidColorBuffers) {
buffer_manager->DestroyBuffer(
- widget, available_solid_color_buffers_.begin()->buffer_id);
+ available_solid_color_buffers_.begin()->buffer_id);
available_solid_color_buffers_.erase(
available_solid_color_buffers_.begin());
}
@@ -104,10 +104,9 @@ void GbmSurfacelessWayland::SolidColorBufferHolder::OnSubmission(
}
void GbmSurfacelessWayland::SolidColorBufferHolder::EraseBuffers(
- WaylandBufferManagerGpu* buffer_manager,
- gfx::AcceleratedWidget widget) {
+ WaylandBufferManagerGpu* buffer_manager) {
for (const auto& buffer : available_solid_color_buffers_)
- buffer_manager->DestroyBuffer(widget, buffer.buffer_id);
+ buffer_manager->DestroyBuffer(buffer.buffer_id);
available_solid_color_buffers_.clear();
}
@@ -122,12 +121,13 @@ GbmSurfacelessWayland::GbmSurfacelessWayland(
solid_color_buffers_holder_(std::make_unique<SolidColorBufferHolder>()),
weak_factory_(this) {
buffer_manager_->RegisterSurface(widget_, this);
- unsubmitted_frames_.push_back(std::make_unique<PendingFrame>());
+ unsubmitted_frames_.push_back(
+ std::make_unique<PendingFrame>(next_frame_id()));
}
void GbmSurfacelessWayland::QueueOverlayPlane(OverlayPlane plane,
BufferId buffer_id) {
- unsubmitted_frames_.back()->planes.emplace(buffer_id, std::move(plane));
+ unsubmitted_frames_.back()->planes.emplace_back(buffer_id, std::move(plane));
}
bool GbmSurfacelessWayland::ScheduleOverlayPlane(
@@ -198,7 +198,8 @@ void GbmSurfacelessWayland::SwapBuffersAsync(
frame->presentation_callback = std::move(presentation_callback);
frame->ScheduleOverlayPlanes(this);
- unsubmitted_frames_.push_back(std::make_unique<PendingFrame>());
+ unsubmitted_frames_.push_back(
+ std::make_unique<PendingFrame>(next_frame_id()));
// If Wayland server supports linux_explicit_synchronization_protocol, fences
// should be shipped with buffers. Otherwise, we will wait for fences.
@@ -255,7 +256,7 @@ EGLConfig GbmSurfacelessWayland::GetConfig() {
EGL_SURFACE_TYPE,
EGL_DONT_CARE,
EGL_NONE};
- config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
+ config_ = ChooseEGLConfig(GetEGLDisplay(), config_attribs);
}
return config_;
}
@@ -289,7 +290,7 @@ bool GbmSurfacelessWayland::Resize(const gfx::Size& size,
surface_scale_factor_ = scale_factor;
// Remove all the buffers.
- solid_color_buffers_holder_->EraseBuffers(buffer_manager_, widget_);
+ solid_color_buffers_holder_->EraseBuffers(buffer_manager_);
return gl::SurfacelessEGL::Resize(size, scale_factor, color_space, has_alpha);
}
@@ -298,7 +299,8 @@ GbmSurfacelessWayland::~GbmSurfacelessWayland() {
buffer_manager_->UnregisterSurface(widget_);
}
-GbmSurfacelessWayland::PendingFrame::PendingFrame() = default;
+GbmSurfacelessWayland::PendingFrame::PendingFrame(uint32_t frame_id)
+ : frame_id(frame_id) {}
GbmSurfacelessWayland::PendingFrame::~PendingFrame() = default;
@@ -368,14 +370,11 @@ void GbmSurfacelessWayland::MaybeSubmitFrames() {
// The current scale factor of the surface, which is used to determine
// the size in pixels of resources allocated by the GPU process.
overlay_configs.back()->surface_scale_factor = surface_scale_factor_;
-#if DCHECK_IS_ON()
- if (plane.second.overlay_plane_data.z_order == INT32_MIN)
- background_buffer_id_ = plane.first;
-#endif
plane.second.gpu_fence.reset();
}
- buffer_manager_->CommitOverlays(widget_, std::move(overlay_configs));
+ buffer_manager_->CommitOverlays(widget_, submitted_frame->frame_id,
+ std::move(overlay_configs));
submitted_frames_.push_back(std::move(submitted_frame));
}
}
@@ -384,7 +383,7 @@ EGLSyncKHR GbmSurfacelessWayland::InsertFence(bool implicit) {
const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
EGL_NONE};
- return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR,
+ return eglCreateSyncKHR(GetEGLDisplay(), EGL_SYNC_FENCE_KHR,
implicit ? attrib_list : nullptr);
}
@@ -397,19 +396,21 @@ void GbmSurfacelessWayland::SetNoGLFlushForTests() {
no_gl_flush_for_tests_ = true;
}
-void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
+void GbmSurfacelessWayland::OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) {
- DCHECK(!submitted_frames_.empty());
- DCHECK(submitted_frames_.front()->planes.count(buffer_id) ||
- buffer_id == background_buffer_id_);
+ // If the frame_id is stale, the gpu process just recovered from a crash so
+ // this frame_id can be ignored.
+ if (submitted_frames_.empty() ||
+ submitted_frames_.front()->frame_id != frame_id) {
+ return;
+ }
auto submitted_frame = std::move(submitted_frames_.front());
submitted_frames_.erase(submitted_frames_.begin());
for (auto& plane : submitted_frame->planes) {
// Let the holder mark this buffer as free to reuse.
- solid_color_buffers_holder_->OnSubmission(plane.first, buffer_manager_,
- widget_);
+ solid_color_buffers_holder_->OnSubmission(plane.first, buffer_manager_);
}
submitted_frame->planes.clear();
submitted_frame->overlays.clear();
@@ -417,7 +418,6 @@ void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
std::move(submitted_frame->completion_callback)
.Run(gfx::SwapCompletionResult(swap_result, std::move(release_fence)));
- submitted_frame->pending_presentation_buffer = buffer_id;
pending_presentation_frames_.push_back(std::move(submitted_frame));
if (swap_result != gfx::SwapResult::SWAP_ACK) {
@@ -429,11 +429,12 @@ void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id,
}
void GbmSurfacelessWayland::OnPresentation(
- BufferId buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) {
- DCHECK(!pending_presentation_frames_.empty());
- DCHECK_EQ(pending_presentation_frames_.front()->pending_presentation_buffer,
- buffer_id);
+ if (pending_presentation_frames_.empty() ||
+ pending_presentation_frames_.front()->frame_id != frame_id) {
+ return;
+ }
std::move(pending_presentation_frames_.front()->presentation_callback)
.Run(feedback);
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
index fd3911ee557..be8bc9c890e 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -5,10 +5,9 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_GBM_SURFACELESS_WAYLAND_H_
#define UI_OZONE_PLATFORM_WAYLAND_GPU_GBM_SURFACELESS_WAYLAND_H_
-#include <map>
#include <memory>
+#include <vector>
-#include "base/containers/small_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/native_widget_types.h"
@@ -79,6 +78,8 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
GbmSurfacelessWaylandCommitOverlaysCallbacksTest);
FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest,
GbmSurfacelessWaylandGroupOnSubmissionCallbacksTest);
+ FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryCompositorV3,
+ SurfaceDamageTest);
// Holds solid color buffers.
class SolidColorBufferHolder {
@@ -91,10 +92,8 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
WaylandBufferManagerGpu* buffer_manager);
void OnSubmission(BufferId buffer_id,
- WaylandBufferManagerGpu* buffer_manager,
- gfx::AcceleratedWidget widget);
- void EraseBuffers(WaylandBufferManagerGpu* buffer_manager,
- gfx::AcceleratedWidget widget);
+ WaylandBufferManagerGpu* buffer_manager);
+ void EraseBuffers(WaylandBufferManagerGpu* buffer_manager);
private:
// Gpu-size holder for the solid color buffers. These are not backed by
@@ -121,10 +120,10 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
~GbmSurfacelessWayland() override;
// WaylandSurfaceGpu overrides:
- void OnSubmission(BufferId buffer_id,
+ void OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) override;
- void OnPresentation(BufferId buffer_id,
+ void OnPresentation(uint32_t frame_id,
const gfx::PresentationFeedback& feedback) override;
// PendingFrame here is a post-SkiaRenderer struct that contains overlays +
@@ -132,13 +131,16 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
// level. This information gets into browser process and overlays are
// translated to be attached to WaylandSurfaces of the AcceleratedWidget.
struct PendingFrame {
- PendingFrame();
+ explicit PendingFrame(uint32_t frame_id);
~PendingFrame();
// Queues overlay configs to |planes|.
void ScheduleOverlayPlanes(GbmSurfacelessWayland* surfaceless);
void Flush();
+ // Unique identifier of the frame within this AcceleratedWidget.
+ uint32_t frame_id;
+
bool ready = false;
// TODO(fangzhoug): This should be changed to support Vulkan.
@@ -150,10 +152,9 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
// fences for a particular OnSubmission.
bool schedule_planes_succeeded = false;
- // Maps |buffer_id| to one or more OverlayPlanes, used for committing
- // overlays and wait for OnSubmission's.
- std::multimap<BufferId, OverlayPlane> planes;
- BufferId pending_presentation_buffer;
+ // Contains |buffer_id|s to OverlayPlanes, used for committing overlays and
+ // wait for OnSubmission's.
+ std::vector<std::pair<BufferId, OverlayPlane>> planes;
};
void MaybeSubmitFrames();
@@ -166,12 +167,6 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL,
WaylandBufferManagerGpu* const buffer_manager_;
- // |background_buffer_id| is sent to WaylandBufferManagerHost once per
- // background_buffer allocation. However WaylandBufferManagerHost may commit
- // this buffer more often b/c buffers needs to be re-attached when wl_surface
- // is reshown.
- BufferId background_buffer_id_;
-
// The native surface. Deleting this is allowed to free the EGLNativeWindow.
gfx::AcceleratedWidget widget_;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
index 8df7730acd4..9e955388c5f 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.cc
@@ -117,7 +117,8 @@ void GLSurfaceEglReadbackWayland::SwapBuffersAsync(
ReadPixels(next_buffer->shm_mapping_.memory());
const auto bounds = gfx::Rect(GetSize());
- buffer_manager_->CommitBuffer(widget_, next_buffer->buffer_id_, bounds,
+ buffer_manager_->CommitBuffer(widget_, next_buffer->buffer_id_,
+ /*frame_id*/ next_buffer->buffer_id_, bounds,
surface_scale_factor_, bounds);
}
@@ -132,7 +133,7 @@ GLSurfaceEglReadbackWayland::~GLSurfaceEglReadbackWayland() {
}
void GLSurfaceEglReadbackWayland::OnSubmission(
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) {
DCHECK(release_fence.is_null());
@@ -142,7 +143,7 @@ void GLSurfaceEglReadbackWayland::OnSubmission(
if (displayed_buffer_)
available_buffers_.push_back(std::move(displayed_buffer_));
displayed_buffer_ = std::move(in_flight_pixel_buffers_.front());
- DCHECK_EQ(displayed_buffer_->buffer_id_, buffer_id);
+ DCHECK_EQ(displayed_buffer_->buffer_id_, frame_id);
}
in_flight_pixel_buffers_.pop_front();
@@ -154,7 +155,7 @@ void GLSurfaceEglReadbackWayland::OnSubmission(
}
void GLSurfaceEglReadbackWayland::OnPresentation(
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) {
DCHECK(!presentation_callbacks_.empty());
std::move(presentation_callbacks_.front()).Run(feedback);
@@ -163,12 +164,12 @@ void GLSurfaceEglReadbackWayland::OnPresentation(
void GLSurfaceEglReadbackWayland::DestroyBuffers() {
for (const auto& pixel_buffer : available_buffers_)
- buffer_manager_->DestroyBuffer(widget_, pixel_buffer->buffer_id_);
+ buffer_manager_->DestroyBuffer(pixel_buffer->buffer_id_);
for (const auto& pixel_buffer : in_flight_pixel_buffers_)
- buffer_manager_->DestroyBuffer(widget_, pixel_buffer->buffer_id_);
+ buffer_manager_->DestroyBuffer(pixel_buffer->buffer_id_);
if (displayed_buffer_)
- buffer_manager_->DestroyBuffer(widget_, displayed_buffer_->buffer_id_);
+ buffer_manager_->DestroyBuffer(displayed_buffer_->buffer_id_);
available_buffers_.clear();
in_flight_pixel_buffers_.clear();
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
index af65f174902..8d8f915307d 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h
@@ -71,10 +71,10 @@ class GLSurfaceEglReadbackWayland : public GLSurfaceEglReadback,
~GLSurfaceEglReadbackWayland() override;
// WaylandSurfaceGpu:
- void OnSubmission(uint32_t buffer_id,
+ void OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) override;
- void OnPresentation(uint32_t buffer_id,
+ void OnPresentation(uint32_t frame_id,
const gfx::PresentationFeedback& feedback) override;
void DestroyBuffers();
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc
index b8993c995cd..d79ce4f3df5 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gl_surface_wayland.cc
@@ -70,7 +70,7 @@ EGLConfig GLSurfaceWayland::GetConfig() {
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE};
- config_ = ChooseEGLConfig(GetDisplay(), config_attribs);
+ config_ = ChooseEGLConfig(GetEGLDisplay(), config_attribs);
}
return config_;
}
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
index 84c70912c3f..32ceabf355d 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.cc
@@ -259,6 +259,7 @@ void WaylandBufferManagerGpu::CreateSolidColorBuffer(SkColor color,
}
void WaylandBufferManagerGpu::CommitBuffer(gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
uint32_t buffer_id,
const gfx::Rect& bounds_rect,
float surface_scale_factor,
@@ -273,42 +274,42 @@ void WaylandBufferManagerGpu::CommitBuffer(gfx::AcceleratedWidget widget,
1.0f /*opacity*/, gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone,
gfx::RRectF()));
- CommitOverlays(widget, std::move(overlay_configs));
+ CommitOverlays(widget, frame_id, std::move(overlay_configs));
}
void WaylandBufferManagerGpu::CommitOverlays(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays) {
DCHECK(gpu_thread_runner_);
if (!gpu_thread_runner_->BelongsToCurrentThread()) {
// Do the mojo call on the GpuMainThread.
gpu_thread_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WaylandBufferManagerGpu::CommitOverlays,
- base::Unretained(this), widget, std::move(overlays)));
+ FROM_HERE, base::BindOnce(&WaylandBufferManagerGpu::CommitOverlays,
+ base::Unretained(this), widget, frame_id,
+ std::move(overlays)));
return;
}
- base::OnceClosure task =
- base::BindOnce(&WaylandBufferManagerGpu::CommitOverlaysTask,
- base::Unretained(this), widget, std::move(overlays));
+ base::OnceClosure task = base::BindOnce(
+ &WaylandBufferManagerGpu::CommitOverlaysTask, base::Unretained(this),
+ widget, frame_id, std::move(overlays));
RunOrQueueTask(std::move(task));
}
-void WaylandBufferManagerGpu::DestroyBuffer(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
+void WaylandBufferManagerGpu::DestroyBuffer(uint32_t buffer_id) {
DCHECK(gpu_thread_runner_);
if (!gpu_thread_runner_->BelongsToCurrentThread()) {
// Do the mojo call on the GpuMainThread.
gpu_thread_runner_->PostTask(
FROM_HERE, base::BindOnce(&WaylandBufferManagerGpu::DestroyBuffer,
- base::Unretained(this), widget, buffer_id));
+ base::Unretained(this), buffer_id));
return;
}
base::OnceClosure task =
base::BindOnce(&WaylandBufferManagerGpu::DestroyBufferTask,
- base::Unretained(this), widget, buffer_id);
+ base::Unretained(this), buffer_id);
RunOrQueueTask(std::move(task));
}
@@ -398,26 +399,26 @@ void WaylandBufferManagerGpu::ForgetTaskRunnerForWidgetOnIOThread(
void WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread(
gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
gfx::SwapResult swap_result,
gfx::GpuFenceHandle release_fence) {
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
auto* surface = GetSurface(widget);
// The surface might be destroyed by the time the swap result is provided.
if (surface)
- surface->OnSubmission(buffer_id, swap_result, std::move(release_fence));
+ surface->OnSubmission(frame_id, swap_result, std::move(release_fence));
}
void WaylandBufferManagerGpu::SubmitPresentationOnOriginThread(
gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) {
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
auto* surface = GetSurface(widget);
// The surface might be destroyed by the time the presentation feedback is
// provided.
if (surface)
- surface->OnPresentation(buffer_id, feedback);
+ surface->OnPresentation(frame_id, feedback);
}
#if defined(WAYLAND_GBM)
@@ -508,19 +509,19 @@ void WaylandBufferManagerGpu::CreateSolidColorBufferTask(SkColor color,
void WaylandBufferManagerGpu::CommitOverlaysTask(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
DCHECK(remote_host_);
- remote_host_->CommitOverlays(widget, std::move(overlays));
+ remote_host_->CommitOverlays(widget, frame_id, std::move(overlays));
}
-void WaylandBufferManagerGpu::DestroyBufferTask(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
+void WaylandBufferManagerGpu::DestroyBufferTask(uint32_t buffer_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_);
DCHECK(remote_host_);
- remote_host_->DestroyBuffer(widget, buffer_id);
+ remote_host_->DestroyBuffer(buffer_id);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
index 69dd6538053..662db319757 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h
@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_
#define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_BUFFER_MANAGER_GPU_H_
+#include <cstdint>
#include <map>
#include <memory>
@@ -63,13 +64,13 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// These two calls get the surface, which backs the |widget| and notifies it
// about the submission and the presentation. After the surface receives the
- // OnSubmission call, it can schedule a new buffer for swap.
+ // OnSubmission call, it can schedule a new frame for swap.
void OnSubmission(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
gfx::SwapResult swap_result,
gfx::GpuFenceHandle release_fence_handle) override;
void OnPresentation(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) override;
// If the client, which uses this manager and implements WaylandSurfaceGpu,
@@ -122,6 +123,7 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// CommitBuffer() calls CommitOverlays() to commit only a primary plane
// buffer.
void CommitBuffer(gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
uint32_t buffer_id,
const gfx::Rect& bounds_rect,
float surface_scale_factor,
@@ -130,10 +132,11 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// |widget|.
void CommitOverlays(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays);
// Asks Wayland to destroy a wl_buffer.
- void DestroyBuffer(gfx::AcceleratedWidget widget, uint32_t buffer_id);
+ void DestroyBuffer(uint32_t buffer_id);
#if defined(WAYLAND_GBM)
// Returns a gbm_device based on a DRM render node.
@@ -166,6 +169,8 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
GbmSurfacelessWaylandCommitOverlaysCallbacksTest);
FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryTest,
GbmSurfacelessWaylandGroupOnSubmissionCallbacksTest);
+ FRIEND_TEST_ALL_PREFIXES(WaylandSurfaceFactoryCompositorV3,
+ SurfaceDamageTest);
FRIEND_TEST_ALL_PREFIXES(WaylandBufferManagerTest,
ExecutesTasksAfterInitialization);
FRIEND_TEST_ALL_PREFIXES(WaylandOverlayManagerTest,
@@ -182,12 +187,12 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
// Provides the WaylandSurfaceGpu, which backs the |widget|, with swap and
// presentation results.
void SubmitSwapResultOnOriginThread(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
gfx::SwapResult swap_result,
gfx::GpuFenceHandle release_fence);
void SubmitPresentationOnOriginThread(
gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback);
void OnHostDisconnected();
@@ -217,8 +222,9 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
uint32_t buf_id);
void CommitOverlaysTask(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ozone::mojom::WaylandOverlayConfigPtr> overlays);
- void DestroyBufferTask(gfx::AcceleratedWidget widget, uint32_t buffer_id);
+ void DestroyBufferTask(uint32_t buffer_id);
#if defined(WAYLAND_GBM)
// Finds drm render node, opens it and stores the handle into
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
index a88a6161faf..a58e342a74f 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.cc
@@ -45,7 +45,7 @@ class WaylandCanvasSurface::SharedMemoryBuffer {
SharedMemoryBuffer(const SharedMemoryBuffer&) = delete;
SharedMemoryBuffer& operator=(const SharedMemoryBuffer&) = delete;
- ~SharedMemoryBuffer() { buffer_manager_->DestroyBuffer(widget_, buffer_id_); }
+ ~SharedMemoryBuffer() { buffer_manager_->DestroyBuffer(buffer_id_); }
// Returns SkSurface, which the client can use to write to this buffer.
sk_sp<SkSurface> sk_surface() const { return sk_surface_; }
@@ -95,8 +95,8 @@ class WaylandCanvasSurface::SharedMemoryBuffer {
}
void CommitBuffer(const gfx::Rect& damage, float buffer_scale) {
- buffer_manager_->CommitBuffer(widget_, buffer_id_, gfx::Rect(size_),
- buffer_scale, damage);
+ buffer_manager_->CommitBuffer(widget_, buffer_id_, /*frame_id*/ buffer_id_,
+ gfx::Rect(size_), buffer_scale, damage);
}
void OnUse() {
@@ -313,7 +313,7 @@ void WaylandCanvasSurface::ProcessUnsubmittedBuffers() {
current_buffer_->CommitBuffer(damage, viewport_scale_);
}
-void WaylandCanvasSurface::OnSubmission(uint32_t buffer_id,
+void WaylandCanvasSurface::OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) {
DCHECK(release_fence.is_null());
@@ -323,15 +323,15 @@ void WaylandCanvasSurface::OnSubmission(uint32_t buffer_id,
// it must be |current_buffer_| because we only submit new buffers when
// |current_buffer_| is nullptr, and it is only set to nullptr in
// |OnSubmission| and |ResizeCanvas|. In |ResizeCanvas|, |buffers_| is cleared
- // so we will not know about |buffer_id|.
+ // so we will not know about |frame_id|.
if (std::none_of(buffers_.begin(), buffers_.end(),
- [buffer_id](const auto& buffer) {
- return buffer->buffer_id() == buffer_id;
+ [frame_id](const auto& buffer) {
+ return buffer->buffer_id() == frame_id;
}))
return;
DCHECK(current_buffer_);
- DCHECK_EQ(current_buffer_->buffer_id(), buffer_id);
+ DCHECK_EQ(current_buffer_->buffer_id(), frame_id);
if (previous_buffer_)
previous_buffer_->OnRelease();
@@ -344,7 +344,7 @@ void WaylandCanvasSurface::OnSubmission(uint32_t buffer_id,
}
void WaylandCanvasSurface::OnPresentation(
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) {
last_timestamp_ = feedback.timestamp;
last_interval_ = feedback.interval;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
index a7f60c10928..cbf4414ee6d 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/size.h"
@@ -73,10 +74,10 @@ class WaylandCanvasSurface : public SurfaceOzoneCanvas,
void ProcessUnsubmittedBuffers();
// WaylandSurfaceGpu overrides:
- void OnSubmission(uint32_t buffer_id,
+ void OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) override;
- void OnPresentation(uint32_t buffer_id,
+ void OnPresentation(uint32_t frame_id,
const gfx::PresentationFeedback& feedback) override;
sk_sp<SkSurface> GetNextSurface();
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
index 1c44f05f722..e4cb8ec1dcf 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
@@ -80,6 +80,18 @@ bool WaylandOverlayManager::CanHandleCandidate(
kAssumedMaxDeviceScaleFactor) == 0)
return false;
+ // Passing an empty surface size through wayland will actually clear the size
+ // restriction and display the buffer at full size. The function
+ // 'set_destination_size' in augmenter will accept empty sizes without
+ // protocol error but interprets this as a clear.
+ // TODO(https://crbug.com/1306230) : Move and generalize this fix in wayland
+ // host.
+ if (wl_fixed_from_double(candidate.display_rect.width() /
+ kAssumedMaxDeviceScaleFactor) == 0 ||
+ wl_fixed_from_double(candidate.display_rect.height() /
+ kAssumedMaxDeviceScaleFactor) == 0)
+ return false;
+
if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID)
return false;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index df94127bc6e..73ac0a0a672 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -852,13 +852,143 @@ TEST_P(WaylandSurfaceFactoryTest, CreateSurfaceCheckGbm) {
EXPECT_FALSE(gl_surface);
}
+class WaylandSurfaceFactoryCompositorV3 : public WaylandSurfaceFactoryTest {};
+
+TEST_P(WaylandSurfaceFactoryCompositorV3, SurfaceDamageTest) {
+ // This tests multiple buffers per-frame and order of SwapCompletionCallbacks.
+ // Even when all OnSubmission from later frames are called, their
+ // SwapCompletionCallbacks should not run until previous frames'
+ // SwapCompletionCallbacks run.
+ gl::SetGLImplementation(gl::kGLImplementationEGLGLES2);
+
+ buffer_manager_gpu_->use_fake_gbm_device_for_test_ = true;
+ buffer_manager_gpu_->gbm_device_ = std::make_unique<MockGbmDevice>();
+ buffer_manager_gpu_->supports_dmabuf_ = true;
+
+ auto* gl_ozone = surface_factory_->GetGLOzone(
+ gl::GLImplementationParts(gl::kGLImplementationEGLGLES2));
+ auto gl_surface = gl_ozone->CreateSurfacelessViewGLSurface(widget_);
+ EXPECT_TRUE(gl_surface);
+ gl_surface->SetRelyOnImplicitSync();
+ static_cast<ui::GbmSurfacelessWayland*>(gl_surface.get())
+ ->SetNoGLFlushForTests();
+
+ // Expect to create 4 buffers.
+ EXPECT_CALL(*server_.zwp_linux_dmabuf_v1(), CreateParams(_, _, _)).Times(4);
+
+ gfx::Size test_buffer_size = {300, 100};
+ gfx::RectF test_buffer_dmg_uv = {0.2f, 0.3f, 0.6, 0.32f};
+ gfx::Rect test_buffer_dmg = gfx::ToEnclosingRect(gfx::ScaleRect(
+ test_buffer_dmg_uv, test_buffer_size.width(), test_buffer_size.height()));
+ gfx::RectF crop_uv = {0.1f, 0.2f, 0.5, 0.5f};
+ gfx::RectF expected_combined_uv = {0.2, 0.2, 0.8, 0.64};
+ gfx::Rect expected_surface_dmg = gfx::ToEnclosingRect(
+ gfx::ScaleRect(expected_combined_uv, window_->GetBounds().width(),
+ window_->GetBounds().height()));
+
+ // Create buffers and FakeGlImageNativePixmap.
+ std::vector<scoped_refptr<FakeGLImageNativePixmap>> fake_gl_image;
+ for (int i = 0; i < 4; ++i) {
+ auto native_pixmap = surface_factory_->CreateNativePixmap(
+ widget_, nullptr, test_buffer_size, gfx::BufferFormat::BGRA_8888,
+ gfx::BufferUsage::SCANOUT);
+ fake_gl_image.push_back(base::MakeRefCounted<FakeGLImageNativePixmap>(
+ native_pixmap, test_buffer_size));
+
+ Sync();
+
+ // Create one buffer at a time.
+ auto params_vector = server_.zwp_linux_dmabuf_v1()->buffer_params();
+ DCHECK_EQ(params_vector.size(), 1u);
+ zwp_linux_buffer_params_v1_send_created(
+ params_vector.front()->resource(),
+ params_vector.front()->buffer_resource());
+
+ Sync();
+ }
+
+ auto* root_surface = server_.GetObject<wl::MockSurface>(
+ window_->root_surface()->GetSurfaceId());
+ auto* mock_primary_surface = server_.GetObject<wl::MockSurface>(
+ window_->primary_subsurface()->wayland_surface()->GetSurfaceId());
+
+ CallbacksHelper cbs_helper;
+ // Submit a frame with an overlay and background.
+ {
+ // Associate each image with swap id so that we could track released
+ // buffers.
+ auto swap_id = cbs_helper.GetNextLocalSwapId();
+ // Associate the image with the next swap id so that we can easily track if
+ // it became free to reuse.
+ fake_gl_image[0]->AssociateWithSwapId(swap_id);
+ // And set it to be busy...
+ fake_gl_image[0]->SetBusy(true);
+
+ // Prepare background.
+ gl_surface->ScheduleOverlayPlane(
+ fake_gl_image[0].get(), nullptr,
+ gfx::OverlayPlaneData(
+ INT32_MIN, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE,
+ gfx::RectF(window_->GetBounds()), crop_uv, false,
+ gfx::Rect(test_buffer_dmg), 1.0f, gfx::OverlayPriorityHint::kNone,
+ gfx::RRectF(), gfx::ColorSpace::CreateSRGB(), absl::nullopt));
+
+ std::vector<scoped_refptr<FakeGLImageNativePixmap>> gl_images;
+ gl_images.push_back(fake_gl_image[0]);
+
+ // And submit each image. They will be executed in FIFO manner.
+ gl_surface->SwapBuffersAsync(
+ base::BindOnce(&CallbacksHelper::FinishSwapBuffersAsync,
+ base::Unretained(&cbs_helper), swap_id, gl_images),
+ base::BindOnce(&CallbacksHelper::BufferPresented,
+ base::Unretained(&cbs_helper), swap_id));
+ }
+
+ // Let's sync so that 1) GbmSurfacelessWayland submits the buffer according to
+ // internal queue and fake server processes the request.
+
+ // Wait until the mojo calls are done.
+ base::RunLoop().RunUntilIdle();
+
+ Expectation damage =
+ EXPECT_CALL(*surface_, Damage(expected_surface_dmg.origin().x(),
+ expected_surface_dmg.origin().y(),
+ expected_surface_dmg.width(),
+ expected_surface_dmg.height()));
+ wl_resource* buffer_resource = nullptr;
+ Expectation attach = EXPECT_CALL(*surface_, Attach(_, 0, 0))
+ .WillOnce(SaveArg<0>(&buffer_resource));
+ EXPECT_CALL(*surface_, Commit()).After(damage, attach);
+
+ Sync();
+
+ testing::Mock::VerifyAndClearExpectations(mock_primary_surface);
+ testing::Mock::VerifyAndClearExpectations(root_surface);
+
+ // Give mojo the chance to pass the callbacks.
+ base::RunLoop().RunUntilIdle();
+
+ // We have just received Attach/DamageBuffer/Commit for buffer with swap
+ // id=0u. The SwapCompletionCallback must be executed automatically as long as
+ // we didn't have any buffers attached to the surface before.
+ EXPECT_EQ(cbs_helper.GetLastFinishedSwapId(), 0u);
+
+ cbs_helper.ResetLastFinishedSwapId();
+}
+
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandSurfaceFactoryTest,
Values(wl::ServerConfig{
.shell_version = wl::ShellVersion::kStable}));
+
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
WaylandSurfaceFactoryTest,
Values(wl::ServerConfig{
.shell_version = wl::ShellVersion::kV6}));
+INSTANTIATE_TEST_SUITE_P(
+ CompositorVersionV3Test,
+ WaylandSurfaceFactoryCompositorV3,
+ Values(wl::ServerConfig{.compositor_version = wl::CompositorVersion::kV3}));
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
index 64f3aba5dec..e6b755c8674 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_surface_gpu.h
@@ -20,22 +20,28 @@ namespace ui {
// the buffer.
class WaylandSurfaceGpu {
public:
- virtual ~WaylandSurfaceGpu() {}
-
- // Tells the surface the result of the last swap of buffer with the
- // |buffer_id|. After this callback, the previously (before |buffer_id|)
- // submitted buffer may be reused. This is guaranteed to be called
- // in the same order that buffers were submitted.
- virtual void OnSubmission(uint32_t buffer_id,
+ virtual ~WaylandSurfaceGpu() = default;
+
+ // Tells the surface the result of the last swap of frame with the |frame_id|.
+ // After this callback, the previously (before |frame_id|) submitted buffers
+ // may be reused. This is guaranteed to be called in the same order that
+ // frames were submitted. If not, there's been a GPU process crash and the
+ // stale |frame_id| can be ignored.
+ virtual void OnSubmission(uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) = 0;
// Tells the surface the result of the last presentation of buffer with the
- // |buffer_id|. This is guaranteed to be called in the same order that
- // buffers were submitted, and is guaranteed to be called after the
- // corresponding call to |OnSubmission| for this buffer.
- virtual void OnPresentation(uint32_t buffer_id,
+ // |frame_id|. This is guaranteed to be called in the same order that frames
+ // were submitted, and is guaranteed to be called after the corresponding call
+ // to |OnSubmission| for this frame.
+ virtual void OnPresentation(uint32_t frame_id,
const gfx::PresentationFeedback& feedback) = 0;
+
+ uint32_t next_frame_id() { return ++frame_id_; }
+
+ private:
+ uint32_t frame_id_ = 0u;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/DEPS b/chromium/ui/ozone/platform/wayland/host/DEPS
index 02595ff5fc8..bae43b4dd25 100644
--- a/chromium/ui/ozone/platform/wayland/host/DEPS
+++ b/chromium/ui/ozone/platform/wayland/host/DEPS
@@ -9,4 +9,5 @@ include_rules = [
"+components/crash/core/common",
"+dbus",
"+ui/base/linux",
+ "+third_party/re2",
]
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
index 59ac3767f7d..92bb004a390 100644
--- a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.cc
@@ -6,7 +6,6 @@
#include <gtk-primary-selection-client-protocol.h>
-#include "base/logging.h"
#include "ui/ozone/platform/wayland/host/gtk_primary_selection_offer.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
@@ -27,15 +26,11 @@ GtkPrimarySelectionDevice::GtkPrimarySelectionDevice(
GtkPrimarySelectionDevice::~GtkPrimarySelectionDevice() = default;
void GtkPrimarySelectionDevice::SetSelectionSource(
- GtkPrimarySelectionSource* source) {
- auto serial = GetSerialForSelection();
- if (!serial.has_value()) {
- LOG(ERROR) << "Failed to set selection. No serial found.";
- return;
- }
+ GtkPrimarySelectionSource* source,
+ uint32_t serial) {
auto* data_source = source ? source->data_source() : nullptr;
gtk_primary_selection_device_set_selection(data_device_.get(), data_source,
- serial->value);
+ serial);
connection()->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
index a9bcdb06623..219db517859 100644
--- a/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
+++ b/chromium/ui/ozone/platform/wayland/host/gtk_primary_selection_device.h
@@ -5,7 +5,8 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_GTK_PRIMARY_SELECTION_DEVICE_H_
-#include "base/callback.h"
+#include <cstdint>
+
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device_base.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
@@ -32,7 +33,7 @@ class GtkPrimarySelectionDevice : public WaylandDataDeviceBase {
return data_device_.get();
}
- void SetSelectionSource(GtkPrimarySelectionSource* source);
+ void SetSelectionSource(GtkPrimarySelectionSource* source, uint32_t serial);
private:
// gtk_primary_selection_device_listener callbacks
diff --git a/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h b/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
index 7e67dc95085..35151f7e32e 100644
--- a/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
+++ b/chromium/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
@@ -76,9 +76,14 @@ class ShellToplevelWrapper {
// Tells if the surface has been AckConfigured at least once.
virtual bool IsConfigured() = 0;
- // Sets a desired window geometry once wayland requests client to do so.
+ // Sets a desired window geometry in surface local coordinates that specifies
+ // the content area of the surface.
virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0;
+ // Requests a desired window position and size in global screen coordinates.
+ // The compositor may or may not filfill the request.
+ virtual void RequestWindowBounds(const gfx::Rect& bounds) = 0;
+
// Sets the minimum size for the top level.
virtual void SetMinSize(int32_t width, int32_t height) = 0;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.cc b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.cc
index 19fbfac4222..43f7d2592ca 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/wayland/host/wayland_buffer_backing_shm.h"
+#include "build/chromeos_buildflags.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_shm.h"
@@ -24,6 +25,7 @@ WaylandBufferBackingShm::~WaylandBufferBackingShm() = default;
void WaylandBufferBackingShm::RequestBufferHandle(
base::OnceCallback<void(wl::Object<wl_buffer>)> callback) {
DCHECK(!callback.is_null());
+ DCHECK(fd_.is_valid());
// Given that buffers for canvas surfaces are submitted with alpha disabled,
// using a format with alpha channel results in popup surfaces that have black
@@ -39,6 +41,8 @@ void WaylandBufferBackingShm::RequestBufferHandle(
#endif
std::move(callback).Run(connection_->shm()->CreateBuffer(fd_, length_, size(),
with_alpha_channel));
+ if (UseExplicitSyncRelease())
+ auto close = std::move(fd_);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
index bdd437618e9..3e3dea901fd 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -256,6 +256,7 @@ WaylandBufferHandle* WaylandBufferManagerHost::GetBufferHandle(
void WaylandBufferManagerHost::CommitOverlays(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr> overlays) {
DCHECK(base::CurrentUIThread::IsSet());
@@ -282,14 +283,10 @@ void WaylandBufferManagerHost::CommitOverlays(
}
}
- window->CommitOverlays(overlays);
+ window->CommitOverlays(frame_id, overlays);
}
-void WaylandBufferManagerHost::DestroyBuffer(
- [[maybe_unused]] gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
- // TODO(fangzhoug): Remove |widget| from the argument list of the mojo
- // interface.
+void WaylandBufferManagerHost::DestroyBuffer(uint32_t buffer_id) {
DCHECK(base::CurrentUIThread::IsSet());
TRACE_EVENT1("wayland", "WaylandBufferManagerHost::DestroyBuffer",
@@ -429,24 +426,24 @@ bool WaylandBufferManagerHost::ValidateOverlayData(
}
void WaylandBufferManagerHost::OnSubmission(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence) {
DCHECK(base::CurrentUIThread::IsSet());
DCHECK(buffer_manager_gpu_associated_);
- buffer_manager_gpu_associated_->OnSubmission(widget, buffer_id, swap_result,
+ buffer_manager_gpu_associated_->OnSubmission(widget, frame_id, swap_result,
std::move(release_fence));
}
void WaylandBufferManagerHost::OnPresentation(
gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback) {
DCHECK(base::CurrentUIThread::IsSet());
DCHECK(buffer_manager_gpu_associated_);
- buffer_manager_gpu_associated_->OnPresentation(widget, buffer_id, feedback);
+ buffer_manager_gpu_associated_->OnPresentation(widget, frame_id, feedback);
}
void WaylandBufferManagerHost::TerminateGpuProcess() {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
index e0862674f77..3e2e079f2ad 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h
@@ -103,13 +103,13 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost {
uint32_t buffer_id) override;
// Called by the GPU to destroy the imported wl_buffer with a |buffer_id|.
- void DestroyBuffer(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) override;
+ void DestroyBuffer(uint32_t buffer_id) override;
// Called by the GPU and asks to configure the surface/subsurfaces and attach
// wl_buffers to WaylandWindow with the specified |widget|. Calls OnSubmission
// and OnPresentation on successful swap and pixels presented.
void CommitOverlays(
gfx::AcceleratedWidget widget,
+ uint32_t frame_id,
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr> overlays) override;
// Ensures a WaylandBufferHandle of |buffer_id| is created for the
@@ -125,11 +125,11 @@ class WaylandBufferManagerHost : public ozone::mojom::WaylandBufferManagerHost {
// Tells the |buffer_manager_gpu_ptr_| the result of a swap call and provides
// it with the presentation feedback.
void OnSubmission(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::SwapResult& swap_result,
gfx::GpuFenceHandle release_fence);
void OnPresentation(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
+ uint32_t frame_id,
const gfx::PresentationFeedback& feedback);
private:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
index 52a1af56d1f..b7fa2877766 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -4,11 +4,13 @@
#include "ui/ozone/platform/wayland/host/wayland_clipboard.h"
+#include <cstdint>
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/check.h"
+#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
@@ -24,6 +26,7 @@
#include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_data_offer_base.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
+#include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
#include "ui/ozone/platform/wayland/host/zwp_primary_selection_device.h"
#include "ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.h"
#include "ui/ozone/public/platform_clipboard.h"
@@ -69,8 +72,10 @@ template <typename Manager,
typename DataDevice = typename Manager::DataDevice>
class ClipboardImpl final : public Clipboard, public DataSource::Delegate {
public:
- explicit ClipboardImpl(Manager* manager, ui::ClipboardBuffer buffer)
- : manager_(manager), buffer_(buffer) {
+ ClipboardImpl(Manager* manager,
+ ui::ClipboardBuffer buffer,
+ ui::WaylandConnection* connection)
+ : manager_(manager), buffer_(buffer), connection_(connection) {
GetDevice()->set_selection_offer_callback(base::BindRepeating(
&ClipboardImpl::HandleNewSelectionOffer, weak_factory_.GetWeakPtr()));
}
@@ -93,6 +98,10 @@ class ClipboardImpl final : public Clipboard, public DataSource::Delegate {
// responsible for writing the clipboard contents into the supplied fd. This
// client can only drop the clipboard contents when it receives a
// wl_data_source::cancelled event.
+ //
+ // This is supposedly responding to an input event, i.e: there is a valid
+ // corresponding serial number (provided by wl::SerialTracker). Otherwise,
+ // this function will no-op.
void Write(const ui::PlatformClipboard::DataMap* data) final {
if (!data || data->empty()) {
offered_data_.clear();
@@ -102,7 +111,21 @@ class ClipboardImpl final : public Clipboard, public DataSource::Delegate {
source_ = manager_->CreateSource(this);
source_->Offer(GetOfferedMimeTypes());
}
- GetDevice()->SetSelectionSource(source_.get());
+
+ // TODO(nickdiego): This function should just no-op if no serial is found
+ // (ie: no recent input event has been processed yet), though several unit
+ // and browser tests do not satisfy this precondition so would fail [1].
+ // Revisit this once those tests are fixed.
+ //
+ // [1] https://chromium-review.googlesource.com/c/chromium/src/+/3527605/2
+ auto& serial_tracker = connection_->serial_tracker();
+ auto serial = serial_tracker.GetSerial({wl::SerialType::kTouchPress,
+ wl::SerialType::kMousePress,
+ wl::SerialType::kKeyPress});
+ if (serial.has_value())
+ GetDevice()->SetSelectionSource(source_.get(), serial->value);
+ else
+ LOG(WARNING) << "No serial found for selection.";
if (!clipboard_changed_callback_.is_null())
clipboard_changed_callback_.Run(buffer_);
@@ -180,6 +203,8 @@ class ClipboardImpl final : public Clipboard, public DataSource::Delegate {
// Notifies when clipboard data changes. Can be empty if not set.
ClipboardDataChangedCallback clipboard_changed_callback_;
+ ui::WaylandConnection* const connection_;
+
base::WeakPtrFactory<ClipboardImpl> weak_factory_{this};
};
@@ -193,7 +218,8 @@ WaylandClipboard::WaylandClipboard(WaylandConnection* connection,
copypaste_clipboard_(
std::make_unique<wl::ClipboardImpl<WaylandDataDeviceManager>>(
manager,
- ClipboardBuffer::kCopyPaste)) {
+ ClipboardBuffer::kCopyPaste,
+ connection)) {
DCHECK(manager);
DCHECK(connection_);
DCHECK(copypaste_clipboard_);
@@ -257,7 +283,7 @@ wl::Clipboard* WaylandClipboard::GetClipboard(ClipboardBuffer buffer) {
if (!primary_selection_clipboard_) {
primary_selection_clipboard_ = std::make_unique<
wl::ClipboardImpl<ZwpPrimarySelectionDeviceManager>>(
- zwp_manager, ClipboardBuffer::kSelection);
+ zwp_manager, ClipboardBuffer::kSelection, connection_);
}
return primary_selection_clipboard_.get();
}
@@ -266,7 +292,7 @@ wl::Clipboard* WaylandClipboard::GetClipboard(ClipboardBuffer buffer) {
if (!primary_selection_clipboard_) {
primary_selection_clipboard_ = std::make_unique<
wl::ClipboardImpl<GtkPrimarySelectionDeviceManager>>(
- gtk_manager, ClipboardBuffer::kSelection);
+ gtk_manager, ClipboardBuffer::kSelection, connection_);
}
return primary_selection_clipboard_.get();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
index 40be06ab34b..2b7955dc7b1 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <linux/input.h>
#include <wayland-server.h>
#include <cstring>
@@ -10,6 +11,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback_forward.h"
#include "base/containers/flat_set.h"
#include "base/location.h"
#include "base/run_loop.h"
@@ -22,14 +24,19 @@
#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/events/base_event_utils.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/ozone/platform/wayland/host/wayland_clipboard.h"
#include "ui/ozone/platform/wayland/host/wayland_connection_test_api.h"
+#include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
+#include "ui/ozone/platform/wayland/test/mock_pointer.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h"
#include "ui/ozone/platform/wayland/test/test_data_device.h"
#include "ui/ozone/platform/wayland/test/test_data_device_manager.h"
#include "ui/ozone/platform/wayland/test/test_data_offer.h"
#include "ui/ozone/platform/wayland/test/test_data_source.h"
+#include "ui/ozone/platform/wayland/test/test_keyboard.h"
#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h"
+#include "ui/ozone/platform/wayland/test/test_touch.h"
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/ozone/public/platform_clipboard.h"
@@ -61,6 +68,21 @@ class WaylandClipboardTestBase : public WaylandTest {
void SetUp() override {
WaylandTest::SetUp();
+ wl_seat_send_capabilities(server_.seat()->resource(),
+ WL_SEAT_CAPABILITY_POINTER |
+ WL_SEAT_CAPABILITY_TOUCH |
+ WL_SEAT_CAPABILITY_KEYBOARD);
+ Sync();
+
+ pointer_ = server_.seat()->pointer();
+ ASSERT_TRUE(pointer_);
+
+ touch_ = server_.seat()->touch();
+ ASSERT_TRUE(touch_);
+
+ keyboard_ = server_.seat()->keyboard();
+ ASSERT_TRUE(keyboard_);
+
// As of now, WaylandClipboard::RequestClipboardData is implemented in a
// blocking way, which requires a roundtrip before attempting the data
// from the selection fd. As Wayland events polling is single-threaded for
@@ -94,7 +116,43 @@ class WaylandClipboardTestBase : public WaylandTest {
base::RunLoop().RunUntilIdle();
}
+ void SentPointerButtonPress(const gfx::Point& location) {
+ wl_pointer_send_enter(pointer_->resource(), ++serial_, surface_->resource(),
+ location.x(), location.y());
+ wl_pointer_send_button(pointer_->resource(), ++serial_, ++timestamp_,
+ BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
+ }
+ void SendTouchDown(const gfx::Point& location) {
+ wl_touch_send_down(touch_->resource(), ++serial_, ++timestamp_,
+ surface_->resource(), /*touch_id=*/0,
+ wl_fixed_from_int(location.x()),
+ wl_fixed_from_int(location.y()));
+ }
+
+ void SendTouchUp() {
+ wl_touch_send_up(touch_->resource(), ++serial_, ++timestamp_,
+ /*touch_id=*/0);
+ }
+
+ void SendKeyboardKey() {
+ struct wl_array empty;
+ wl_array_init(&empty);
+ wl_keyboard_send_enter(keyboard_->resource(), 1, surface_->resource(),
+ &empty);
+ wl_array_release(&empty);
+ wl_keyboard_send_key(keyboard_->resource(), 2, 0, 30 /* a */,
+ WL_KEYBOARD_KEY_STATE_PRESSED);
+ }
+
+ /* Server objects */
+ wl::MockPointer* pointer_;
+ wl::TestTouch* touch_;
+ wl::TestKeyboard* keyboard_;
+
WaylandClipboard* clipboard_ = nullptr;
+
+ uint32_t serial_ = 0;
+ uint32_t timestamp_ = 0;
};
class WaylandClipboardTest : public WaylandClipboardTestBase {
@@ -145,6 +203,15 @@ class WaylandClipboardTest : public WaylandClipboardTestBase {
: ClipboardBuffer::kCopyPaste;
}
+ void ResetServerSelectionSource() {
+ if (GetParam().primary_selection_protocol !=
+ wl::PrimarySelectionProtocol::kNone) {
+ server_.primary_selection_device_manager()->set_source(nullptr);
+ } else {
+ server_.data_device_manager()->set_data_source(nullptr);
+ }
+ }
+
// Fill the clipboard backing store with sample data.
void OfferData(ClipboardBuffer buffer,
const char* data,
@@ -174,22 +241,66 @@ class CopyPasteOnlyClipboardTest : public WaylandClipboardTestBase {
}
};
+// Verifies that copy-to-clipboard works as expected. Actual Wayland input
+// events are used in order to exercise all the components involved, e.g:
+// Wayland{Pointer,Keyboard,Touch}, Serial tracker and WaylandClipboard.
+//
+// Regression test for https://crbug.com/1282220.
TEST_P(WaylandClipboardTest, WriteToClipboard) {
- // 1. Offer sample text as selection data.
- OfferData(GetBuffer(), kSampleClipboardText, {kMimeTypeTextUtf8});
- Sync();
-
- // 2. Emulate an external client requesting to read the offered data and make
- // sure the appropriate string gets delivered.
- std::string delivered_text;
- base::MockCallback<wl::TestSelectionSource::ReadDataCallback> callback;
- EXPECT_CALL(callback, Run(_)).WillOnce([&](std::vector<uint8_t>&& data) {
- delivered_text = std::string(data.begin(), data.end());
- });
- GetServerSelectionSource()->ReadData(kMimeTypeTextUtf8, callback.Get());
+ const base::RepeatingClosure send_input_event_closures[]{
+ // Mouse button press
+ base::BindLambdaForTesting([&]() {
+ SentPointerButtonPress({10, 10});
+ }),
+ // Key press
+ base::BindLambdaForTesting([&]() { SendKeyboardKey(); }),
+ // Touch down
+ base::BindLambdaForTesting([&]() {
+ SendTouchDown({200, 200});
+ }),
+ // Touch tap (down > up)
+ base::BindLambdaForTesting([&]() {
+ SendTouchDown({300, 300});
+ SendTouchUp();
+ })};
+
+ auto* window_manager = connection_->wayland_window_manager();
+
+ // Triggering copy on touch-down event.
+ for (auto send_input_event : send_input_event_closures) {
+ ResetServerSelectionSource();
+
+ send_input_event.Run();
+ Sync();
+ auto client_selection_serial = connection_->serial_tracker().GetSerial(
+ {wl::SerialType::kTouchPress, wl::SerialType::kMousePress,
+ wl::SerialType::kKeyPress});
+ ASSERT_TRUE(client_selection_serial.has_value());
- WaitForClipboardTasks();
- ASSERT_EQ(kSampleClipboardText, delivered_text);
+ // 1. Offer sample text as selection data.
+ OfferData(GetBuffer(), kSampleClipboardText, {kMimeTypeTextUtf8});
+ Sync();
+ ASSERT_TRUE(GetServerSelectionSource());
+
+ EXPECT_EQ(client_selection_serial->value,
+ GetServerSelectionDevice()->selection_serial());
+
+ // 2. Emulate an external client requesting to read the offered data and
+ // make sure the appropriate string gets delivered.
+ std::string delivered_text;
+ base::MockCallback<wl::TestSelectionSource::ReadDataCallback> callback;
+ EXPECT_CALL(callback, Run(_)).WillOnce([&](std::vector<uint8_t>&& data) {
+ delivered_text = std::string(data.begin(), data.end());
+ });
+ GetServerSelectionSource()->ReadData(kMimeTypeTextUtf8, callback.Get());
+
+ WaitForClipboardTasks();
+ ASSERT_EQ(kSampleClipboardText, delivered_text);
+
+ window_manager->SetPointerFocusedWindow(nullptr);
+ window_manager->SetTouchFocusedWindow(nullptr);
+ window_manager->SetKeyboardFocusedWindow(nullptr);
+ }
}
TEST_P(WaylandClipboardTest, ReadFromClipboard) {
@@ -251,8 +362,11 @@ TEST_P(WaylandClipboardTest, ReadFromClipboardWithoutOffer) {
}
TEST_P(WaylandClipboardTest, IsSelectionOwner) {
+ connection_->serial_tracker().UpdateSerial(wl::SerialType::kMousePress, 1);
+
OfferData(GetBuffer(), kSampleClipboardText, {kMimeTypeTextUtf8});
Sync();
+ ASSERT_TRUE(GetServerSelectionSource());
ASSERT_TRUE(clipboard_->IsSelectionOwner(GetBuffer()));
// The compositor sends OnCancelled whenever another application on the system
@@ -262,6 +376,7 @@ TEST_P(WaylandClipboardTest, IsSelectionOwner) {
Sync();
ASSERT_FALSE(clipboard_->IsSelectionOwner(GetBuffer()));
+ connection_->serial_tracker().ResetSerial(wl::SerialType::kMousePress);
}
// Ensures WaylandClipboard correctly handles overlapping read requests for
@@ -320,10 +435,13 @@ TEST_P(WaylandClipboardTest, ClipboardChangeNotifications) {
EXPECT_FALSE(clipboard_->IsSelectionOwner(buffer));
// 2. For selection offered by Chromium.
+ connection_->serial_tracker().UpdateSerial(wl::SerialType::kMousePress, 1);
EXPECT_CALL(clipboard_changed_callback, Run(buffer)).Times(1);
OfferData(buffer, kSampleClipboardText, {kMimeTypeTextUtf8});
Sync();
+ ASSERT_TRUE(GetServerSelectionSource());
EXPECT_TRUE(clipboard_->IsSelectionOwner(buffer));
+ connection_->serial_tracker().ResetSerial(wl::SerialType::kMousePress);
}
// Verifies clipboard calls targeting primary selection buffer no-op and run
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
index 6ef944f632f..d67b664a994 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_connection_unittest.cc
@@ -20,7 +20,9 @@ TEST(WaylandConnectionTest, Ping) {
base::test::SingleThreadTaskEnvironment task_environment(
base::test::SingleThreadTaskEnvironment::MainThreadType::UI);
wl::TestWaylandServerThread server;
- ASSERT_TRUE(server.Start({.shell_version = wl::ShellVersion::kStable}));
+ constexpr uint32_t expected_compositor_version = 4;
+ ASSERT_TRUE(server.Start({.shell_version = wl::ShellVersion::kStable,
+ .compositor_version = wl::CompositorVersion::kV4}));
WaylandConnection connection;
ASSERT_TRUE(connection.Initialize());
connection.event_source()->StartProcessingEvents();
@@ -28,7 +30,7 @@ TEST(WaylandConnectionTest, Ping) {
base::RunLoop().RunUntilIdle();
server.Pause();
- EXPECT_EQ(wl::TestCompositor::kVersion,
+ EXPECT_EQ(expected_compositor_version,
wl::get_version_of_object(connection.compositor()));
xdg_wm_base_send_ping(server.xdg_shell()->resource(), 1234);
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
index d9895e42592..d72ff37b737 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_factory.cc
@@ -6,7 +6,6 @@
#include <wayland-cursor.h>
-#include "base/task/post_task.h"
#include "base/task/task_runner_util.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_position.h b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_position.h
index f10bed74d7f..3bc75a27304 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_cursor_position.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_cursor_position.h
@@ -9,8 +9,8 @@
namespace ui {
-// Stores last known cursor pointer position in regards to top-level windows'
-// coordinates and returns it on request.
+// Stores last known cursor pointer position relative to 0,0 origin
+// and returns it on request.
class WaylandCursorPosition {
public:
WaylandCursorPosition();
@@ -22,8 +22,8 @@ class WaylandCursorPosition {
void OnCursorPositionChanged(const gfx::Point& cursor_position);
- // Returns last known cursor position in regards to top-level surface local
- // coordinates. It is unknown what surface receives that cursor position.
+ // Returns last known cursor position relative to 0,0 origin.
+ // It is unknown what surface receives that cursor position.
gfx::Point GetCursorSurfacePoint() const;
private:
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
index 65c218342f2..6e798918525 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.cc
@@ -73,14 +73,10 @@ void WaylandDataDevice::RequestData(WaylandDataOffer* offer,
RegisterDeferredReadCallback();
}
-void WaylandDataDevice::SetSelectionSource(WaylandDataSource* source) {
- auto serial = GetSerialForSelection();
- if (!serial.has_value()) {
- LOG(ERROR) << "Failed to set selection. No serial found.";
- return;
- }
+void WaylandDataDevice::SetSelectionSource(WaylandDataSource* source,
+ uint32_t serial) {
auto* data_source = source ? source->data_source() : nullptr;
- wl_data_device_set_selection(data_device_.get(), data_source, serial->value);
+ wl_data_device_set_selection(data_device_.get(), data_source, serial);
connection()->ScheduleFlush();
}
@@ -92,6 +88,14 @@ void WaylandDataDevice::ReadDragDataFromFD(base::ScopedFD fd,
base::RefCountedBytes::TakeVector(&contents)));
}
+void WaylandDataDevice::ResetDragDelegateIfNeeded() {
+ // When in an active drag-and-drop session initiated by an external Wayland
+ // client, |drag_delegate_| is set at OnEnter, and must be reset upon
+ // OnLeave/OnDrop in order to avoid potential memory corruption issues.
+ if (drag_delegate_ && !drag_delegate_->IsDragSource())
+ ResetDragDelegate();
+}
+
// static
void WaylandDataDevice::OnOffer(void* data,
wl_data_device* data_device,
@@ -155,6 +159,15 @@ void WaylandDataDevice::OnDrop(void* data, wl_data_device* data_device) {
self->drag_delegate_->OnDragDrop();
self->connection()->ScheduleFlush();
}
+
+ // There are buggy Exo versions, which send 'drop' event (even for
+ // unsuccessful drops) without a subsequent 'leave'. In order to mitigate
+ // potential leaks and/or UAFs, forcibly call corresponding delegate callback
+ // here, in Lacros. TODO(crbug.com/1293415): Remove once Exo bug is fixed.
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ self->drag_delegate_->OnDragLeave();
+ self->ResetDragDelegateIfNeeded();
+#endif
}
void WaylandDataDevice::OnLeave(void* data, wl_data_device* data_device) {
@@ -163,15 +176,7 @@ void WaylandDataDevice::OnLeave(void* data, wl_data_device* data_device) {
self->drag_delegate_->OnDragLeave();
self->connection()->ScheduleFlush();
}
-
- // When in a DND session initiated by an external application,
- // |drag_delegate_| is set at OnEnter, and must be reset here to avoid
- // potential use-after-free.
- //
- // NOTE: Above call to OnDragLeave() may result in |drag_delegate_| being
- // reset, so it must be checked here as well.
- if (self->drag_delegate_ && !self->drag_delegate_->IsDragSource())
- self->ResetDragDelegate();
+ self->ResetDragDelegateIfNeeded();
}
void WaylandDataDevice::OnSelection(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.h b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.h
index 218dd06b33b..9c0328ae994 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device.h
@@ -77,19 +77,16 @@ class WaylandDataDevice : public WaylandDataDeviceBase {
// wl_data_device::set_selection makes the corresponding wl_data_source the
// target of future wl_data_device::data_offer events. In non-Wayland terms,
- // this is equivalent to "writing" to the clipboard or DnD, although the
- // actual transfer of data happens asynchronously, on-demand-only.
- //
- // The API relies on the assumption that the Wayland client is responding to a
- // keyboard or mouse event with a serial number. This is cached in
- // WaylandConnection. However, this may not exist or be set properly in tests,
- // resulting in the Wayland server ignoring the set_selection() request.
- void SetSelectionSource(WaylandDataSource* source);
+ // this is equivalent to "writing" to the clipboard, although the actual
+ // transfer of data happens asynchronously, on-demand-only.
+ void SetSelectionSource(WaylandDataSource* source, uint32_t serial);
private:
FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDrag);
+ FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, ReceiveDrag);
void ReadDragDataFromFD(base::ScopedFD fd, RequestDataCallback callback);
+ void ResetDragDelegateIfNeeded();
// wl_data_device_listener callbacks
static void OnOffer(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
index 43044c510e5..95965e5bc78 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
@@ -14,7 +14,6 @@
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_data_offer_base.h"
#include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
-#include "wayland-client-core.h"
namespace ui {
@@ -109,11 +108,4 @@ void WaylandDataDeviceBase::NotifySelectionOffer(
selection_offer_callback_.Run(offer);
}
-absl::optional<wl::Serial> WaylandDataDeviceBase::GetSerialForSelection()
- const {
- return connection_->serial_tracker().GetSerial({wl::SerialType::kTouchPress,
- wl::SerialType::kMousePress,
- wl::SerialType::kKeyPress});
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.h b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.h
index 99c74499169..eac004dc7c8 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_device_base.h
@@ -8,17 +8,11 @@
#include <string>
#include "base/callback.h"
-#include "base/callback_forward.h"
#include "base/files/scoped_file.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_offer_base.h"
#include "ui/ozone/public/platform_clipboard.h"
-namespace wl {
-struct Serial;
-}
-
namespace ui {
class WaylandConnection;
@@ -72,8 +66,6 @@ class WaylandDataDeviceBase {
void NotifySelectionOffer(WaylandDataOfferBase* offer) const;
- absl::optional<wl::Serial> GetSerialForSelection() const;
-
private:
// wl_callback_listener callback
static void DeferredReadCallback(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index 04f35c33ba9..d972fe438e4 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -188,22 +188,45 @@ bool WaylandDataDragController::IsDragSource() const {
}
void WaylandDataDragController::DrawIcon() {
- if (!icon_bitmap_)
+ if (!icon_surface_ || !icon_bitmap_)
+ return;
+
+ static const wl_callback_listener kFrameListener{
+ .done = WaylandDataDragController::OnDragSurfaceFrame};
+
+ wl_surface* const surface = icon_surface_->surface();
+ icon_frame_callback_.reset(wl_surface_frame(surface));
+ wl_callback_add_listener(icon_frame_callback_.get(), &kFrameListener, this);
+ wl_surface_commit(surface);
+}
+
+void WaylandDataDragController::OnDragSurfaceFrame(void* data,
+ struct wl_callback* callback,
+ uint32_t time) {
+ auto* self = static_cast<WaylandDataDragController*>(data);
+ DCHECK(self);
+ self->DrawIconInternal();
+ self->icon_frame_callback_.reset();
+ self->connection_->ScheduleFlush();
+}
+
+void WaylandDataDragController::DrawIconInternal() {
+ if (!icon_surface_ || !icon_bitmap_)
return;
DCHECK(!icon_bitmap_->empty());
gfx::Size size(icon_bitmap_->width(), icon_bitmap_->height());
- if (!shm_buffer_ || shm_buffer_->size() != size) {
- shm_buffer_ = std::make_unique<WaylandShmBuffer>(connection_->shm(), size);
- if (!shm_buffer_->IsValid()) {
- LOG(ERROR) << "Failed to create drag icon buffer.";
- return;
- }
+ icon_buffer_ = std::make_unique<WaylandShmBuffer>(connection_->shm(), size);
+ if (!icon_buffer_->IsValid()) {
+ LOG(ERROR) << "Failed to create drag icon buffer.";
+ return;
}
- wl::DrawBitmap(*icon_bitmap_, shm_buffer_.get());
+
+ DVLOG(3) << "Drawing drag icon. size=" << size.ToString();
+ wl::DrawBitmap(*icon_bitmap_, icon_buffer_.get());
auto* const surface = icon_surface_->surface();
- wl_surface_attach(surface, shm_buffer_->get(), icon_offset_.x(),
+ wl_surface_attach(surface, icon_buffer_->get(), icon_offset_.x(),
icon_offset_.y());
wl_surface_damage(surface, 0, 0, size.width(), size.height());
wl_surface_commit(surface);
@@ -332,6 +355,8 @@ void WaylandDataDragController::OnDataSourceFinish(bool completed) {
window_manager_->RemoveObserver(this);
data_source_.reset();
data_offer_.reset();
+ icon_buffer_.reset();
+ icon_frame_callback_.reset();
offered_exchange_data_provider_.reset();
data_device_->ResetDragDelegate();
state_ = State::kIdle;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
index df0cdbd952a..f8f8266eae2 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
@@ -171,6 +171,11 @@ class WaylandDataDragController : public WaylandDataDevice::DragDelegate,
bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override;
+ void DrawIconInternal();
+ static void OnDragSurfaceFrame(void* data,
+ struct wl_callback* callback,
+ uint32_t time);
+
WaylandConnection* const connection_;
WaylandDataDeviceManager* const data_device_manager_;
WaylandDataDevice* const data_device_;
@@ -217,9 +222,10 @@ class WaylandDataDragController : public WaylandDataDevice::DragDelegate,
// Drag icon related variables.
std::unique_ptr<WaylandSurface> icon_surface_;
- std::unique_ptr<WaylandShmBuffer> shm_buffer_;
+ std::unique_ptr<WaylandShmBuffer> icon_buffer_;
const SkBitmap* icon_bitmap_ = nullptr;
gfx::Point icon_offset_;
+ wl::Object<wl_callback> icon_frame_callback_;
// Keeps track of the window that holds the pointer grab, i.e. the window that
// will receive the mouse release event from DispatchPointerRelease().
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
index d759b57bfbe..f94209e8726 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -50,6 +50,7 @@
#include "url/gurl.h"
using ::testing::_;
+using ::testing::AtMost;
using ::testing::Eq;
using ::testing::Mock;
using ::testing::Values;
@@ -440,6 +441,7 @@ TEST_P(WaylandDataDragControllerTest, ReceiveDrag) {
wl_fixed_from_int(entered_point.y()), data_offer);
Sync();
+ ASSERT_EQ(drag_controller(), data_device()->drag_delegate_);
// In 2x window scale, we expect received coordinates to be multiplied.
EXPECT_CALL(*drop_handler_,
@@ -463,6 +465,8 @@ TEST_P(WaylandDataDragControllerTest, ReceiveDrag) {
Sync();
data_device_manager_->data_device()->OnLeave();
+ Sync();
+ ASSERT_FALSE(data_device()->drag_delegate_);
}
TEST_P(WaylandDataDragControllerTest, ReceiveDragPixelSurface) {
@@ -605,7 +609,7 @@ TEST_P(WaylandDataDragControllerTest, ValidateDroppedUriList) {
EXPECT_EQ(kCase.expected_uris.count(filename.path.AsUTF8Unsafe()), 1U);
}
- EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(1);
+ EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(AtMost(1));
data_device_manager_->data_device()->OnLeave();
Sync();
Mock::VerifyAndClearExpectations(drop_handler_.get());
@@ -661,7 +665,7 @@ TEST_P(WaylandDataDragControllerTest, ValidateDroppedXMozUrl) {
EXPECT_EQ(title, kCase.expected_title);
}
- EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(1);
+ EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(AtMost(1));
data_device_manager_->data_device()->OnLeave();
Sync();
Mock::VerifyAndClearExpectations(drop_handler_.get());
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
index 0b2bd19561f..74bc3db6435 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -373,6 +373,19 @@ void WaylandEventSource::OnTouchReleaseEvent(base::TimeTicks timestamp,
keyboard_modifiers_);
DispatchEvent(&event);
+ // It is possible that an user interaction triggers nested loops
+ // in higher levels of the application stack in order to process a
+ // given touch down/up action.
+ // For instance, a modal dialog might block this execution point,
+ // and trigger thread to continue to process events.
+ // The auxiliary flow might clear entries in touch_points_.
+ //
+ // Hence, we check whether the TouchId is still being held.
+ if (touch_points_.find(id) == touch_points_.end()) {
+ LOG(WARNING) << "Touch has been released during processing.";
+ return;
+ }
+
HandleTouchFocusChange(touch_point->window, false, id);
touch_points_.erase(it);
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
index 9405055f6d0..ec764c34b44 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher.cc
@@ -10,11 +10,22 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "components/crash/core/common/crash_key.h"
+#include "third_party/re2/src/re2/re2.h"
namespace ui {
namespace {
+// Formats the |message| by removing '@' char followed by any digits until the
+// next char. Also removes new line, tab and carriage-return.
+void FormatErrorMessage(std::string* message) {
+ const re2::RE2 kInvalidChars[] = {"\n", "\r", "\t", "[@]+[0-9]+"};
+ if (message) {
+ for (const auto& pattern : kInvalidChars)
+ re2::RE2::Replace(message, pattern, "");
+ }
+}
+
// Wayland error log that will be stored if the client (Chromium) is
// disconnected due to a protocol error.
static std::string* g_error_log = nullptr;
@@ -23,6 +34,9 @@ void wayland_log(const char* fmt, va_list argp) {
DCHECK(!g_error_log);
g_error_log = new std::string(base::StringPrintV(fmt, argp));
LOG(ERROR) << "libwayland: " << *g_error_log;
+ // Format the error message only after it's printed. Otherwise, object id will
+ // be lost and local development and debugging will be harder to do.
+ FormatErrorMessage(g_error_log);
}
std::string GetWaylandProtocolError(int err, wl_display* display) {
@@ -36,17 +50,18 @@ std::string GetWaylandProtocolError(int err, wl_display* display) {
"Fatal Wayland protocol error %u on interface %s (object %u). "
"Shutting down..",
ec, intf->name, id);
- LOG(ERROR) << error_string;
} else {
error_string = base::StringPrintf(
"Fatal Wayland protocol error %u. Shutting down..", ec);
- LOG(ERROR) << error_string;
}
} else {
- error_string = base::StringPrintf("Fatal Wayland communication error %s.",
+ error_string = base::StringPrintf("Fatal Wayland communication error: %s.",
std::strerror(err));
- LOG(ERROR) << error_string;
}
+ LOG(ERROR) << error_string;
+ // Format the error message only after it's printed. Otherwise, object id will
+ // be lost and local development and debugging will be harder to do.
+ FormatErrorMessage(&error_string);
return error_string;
}
@@ -171,8 +186,9 @@ void WaylandEventWatcher::WlDisplayCheckForErrors() {
// This can be null in tests.
if (!shutdown_cb_.is_null()) {
- // Force a crash so that a crash report is generated.
- CHECK(false) << "Wayland protocol error.";
+ // If Wayland compositor died, it'll be shutdown gracefully. In all the
+ // other cases, force a crash so that a crash report is generated.
+ CHECK(err == EPIPE || err == ECONNRESET) << "Wayland protocol error.";
std::move(shutdown_cb_).Run();
}
StopProcessingEvents();
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc
index 809e92b0d25..0c9f0c295c8 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_event_watcher_unittest.cc
@@ -38,12 +38,11 @@ TEST_P(WaylandEventWatcherTest, CrashKeyResourceError) {
auto* xdg_surface = mock_surface->xdg_surface();
// Prepare the expectation error string.
- const std::string expected_error_code = base::StrCat(
- {wl_resource_get_class(xdg_surface->resource()), "@",
- NumberToString(wl_resource_get_id(xdg_surface->resource())), ": error ",
- NumberToString(
- static_cast<uint32_t>(XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER)),
- ": ", kTestErrorString, "\n"});
+ const std::string expected_error_code =
+ base::StrCat({wl_resource_get_class(xdg_surface->resource()), ": error ",
+ NumberToString(static_cast<uint32_t>(
+ XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER)),
+ ": ", kTestErrorString});
wl_resource_post_error(xdg_surface->resource(),
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER, "%s",
@@ -62,9 +61,9 @@ TEST_P(WaylandEventWatcherTest, CrashKeyResourceNoMemory) {
// Prepare the expectation error string.
const std::string expected_error_code = base::StrCat(
- {"wl_display@1: error ",
+ {"wl_display: error ",
NumberToString(static_cast<uint32_t>(WL_DISPLAY_ERROR_NO_MEMORY)),
- ": no memory\n"});
+ ": no memory"});
wl_resource_post_no_memory(xdg_surface->resource());
@@ -76,9 +75,9 @@ TEST_P(WaylandEventWatcherTest, CrashKeyResourceNoMemory) {
TEST_P(WaylandEventWatcherTest, CrashKeyClientNoMemoryError) {
const std::string expected_error_code = base::StrCat(
- {"wl_display@1: error ",
+ {"wl_display: error ",
NumberToString(static_cast<uint32_t>(WL_DISPLAY_ERROR_NO_MEMORY)),
- ": no memory\n"});
+ ": no memory"});
wl_client_post_no_memory(server_.client());
@@ -91,9 +90,9 @@ TEST_P(WaylandEventWatcherTest, CrashKeyClientNoMemoryError) {
TEST_P(WaylandEventWatcherTest, CrashKeyClientImplementationError) {
const std::string kError = "A nice error.";
const std::string expected_error_code = base::StrCat(
- {"wl_display@1: error ",
+ {"wl_display: error ",
NumberToString(static_cast<uint32_t>(WL_DISPLAY_ERROR_IMPLEMENTATION)),
- ": ", kError, "\n"});
+ ": ", kError});
wl_client_post_implementation_error(server_.client(), "%s", kError.c_str());
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_exchange_data_provider_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_exchange_data_provider_unittest.cc
index ddf5a365600..a852290685e 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_exchange_data_provider_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_exchange_data_provider_unittest.cc
@@ -14,7 +14,7 @@
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
-#include "url/origin.h"
+#include "url/gurl.h"
namespace ui {
@@ -66,9 +66,9 @@ TEST(WaylandExchangeDataProviderTest, ExtractPickledData) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST(WaylandExchangeDataProviderTest, AddAndExtractDataTransferEndpoint) {
std::string kExpectedEncodedDte =
- R"({"endpoint_type":"url","url_origin":"https://www.google.com"})";
- const DataTransferEndpoint expected_dte = ui::DataTransferEndpoint(
- url::Origin::Create(GURL("https://www.google.com")));
+ R"({"endpoint_type":"url","url":"https://www.google.com/","url_origin":"https://www.google.com"})";
+ const DataTransferEndpoint expected_dte =
+ ui::DataTransferEndpoint(GURL("https://www.google.com"));
WaylandExchangeDataProvider provider;
std::string extracted;
@@ -80,8 +80,7 @@ TEST(WaylandExchangeDataProviderTest, AddAndExtractDataTransferEndpoint) {
provider.AddData(ToClipboardData(kExpectedEncodedDte),
kMimeTypeDataTransferEndpoint);
DataTransferEndpoint* actual_dte = provider.GetSource();
- EXPECT_TRUE(
- expected_dte.GetOrigin()->IsSameOriginWith(*actual_dte->GetOrigin()));
+ EXPECT_TRUE(expected_dte.IsSameURLWith(*actual_dte));
std::vector<std::string> mime_types = provider.BuildMimeTypesList();
EXPECT_THAT(mime_types, ::testing::Contains(kMimeTypeDataTransferEndpoint));
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.cc b/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
index 4cdeebdd8d6..f429cc59927 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
@@ -7,6 +7,7 @@
#include <presentation-time-client-protocol.h>
#include <sync/sync.h>
+#include "base/containers/adapters.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/ozone/platform/wayland/host/wayland_buffer_handle.h"
@@ -40,18 +41,30 @@ uint32_t GetPresentationKindFlags(uint32_t flags) {
} // namespace
WaylandFrame::WaylandFrame(
+ uint32_t frame_id,
WaylandSurface* root_surface,
ui::ozone::mojom::WaylandOverlayConfigPtr root_config,
base::circular_deque<std::pair<WaylandSubsurface*,
ui::ozone::mojom::WaylandOverlayConfigPtr>>
- subsurfaces_to_overlays,
- bool expects_ack)
+ subsurfaces_to_overlays)
+ : frame_id(frame_id),
+ root_surface(root_surface),
+ root_config(std::move(root_config)),
+ subsurfaces_to_overlays(std::move(subsurfaces_to_overlays)),
+ submission_acked(false),
+ presentation_acked(false) {}
+
+WaylandFrame::WaylandFrame(
+ WaylandSurface* root_surface,
+ ui::ozone::mojom::WaylandOverlayConfigPtr root_config,
+ base::circular_deque<std::pair<WaylandSubsurface*,
+ ui::ozone::mojom::WaylandOverlayConfigPtr>>
+ subsurfaces_to_overlays)
: root_surface(root_surface),
root_config(std::move(root_config)),
subsurfaces_to_overlays(std::move(subsurfaces_to_overlays)),
- buffer_id(this->root_config ? this->root_config->buffer_id : 0),
- submission_acked(!expects_ack),
- presentation_acked(!expects_ack) {}
+ submission_acked(true),
+ presentation_acked(true) {}
WaylandFrame::~WaylandFrame() = default;
@@ -106,7 +119,6 @@ void WaylandFrameManager::MaybeProcessPendingFrame() {
subsurface_to_overlay.second->buffer_id);
// Buffer is gone while this frame is pending, remove this config.
if (!handle) {
- frame->buffer_id = subsurface_to_overlay.second->buffer_id;
frame->buffer_lost = true;
subsurface_to_overlay.second.reset();
} else if (!handle->wl_buffer() && !handle_pending_creation) {
@@ -120,7 +132,6 @@ void WaylandFrameManager::MaybeProcessPendingFrame() {
auto* handle = connection_->buffer_manager_host()->EnsureBufferHandle(
frame->root_surface, frame->root_config->buffer_id);
if (!handle) {
- frame->buffer_id = frame->root_config->buffer_id;
frame->buffer_lost = true;
frame->root_config.reset();
} else if (!handle->wl_buffer() && !handle_pending_creation) {
@@ -180,13 +191,11 @@ void WaylandFrameManager::PlayBackFrame(std::unique_ptr<WaylandFrame> frame) {
// Configure subsurfaces. Traverse the deque backwards s.t. we can set
// frame_callback and presentation_feedback on the top-most possible surface.
- WaylandSurface* reference_above = nullptr;
- for (auto r_iter = frame->subsurfaces_to_overlays.rbegin();
- r_iter != frame->subsurfaces_to_overlays.rend(); ++r_iter) {
- auto* subsurface = r_iter->first;
+ WaylandSubsurface* reference_above = nullptr;
+ for (auto& [subsurface, config] :
+ base::Reversed(frame->subsurfaces_to_overlays)) {
DCHECK(subsurface);
auto* surface = subsurface->wayland_surface();
- auto& config = r_iter->second;
if (empty_frame || config.is_null() ||
wl_fixed_from_double(config->opacity) == 0) {
subsurface->Hide();
@@ -203,11 +212,12 @@ void WaylandFrameManager::PlayBackFrame(std::unique_ptr<WaylandFrame> frame) {
}
}
} else {
+ subsurface->Show();
subsurface->ConfigureAndShowSurface(
config->bounds_rect, root_config->bounds_rect,
root_config->surface_scale_factor, nullptr, reference_above);
ApplySurfaceConfigure(frame.get(), surface, config, true);
- reference_above = surface;
+ reference_above = subsurface;
surface->Commit(false);
}
}
@@ -286,7 +296,6 @@ void WaylandFrameManager::ApplySurfaceConfigure(
// new wl_buffer, which leads to graphics freeze. So only setup
// frame_callback when we're attaching a different buffer.
if (!frame->wl_frame_callback) {
- frame->buffer_id = config->buffer_id;
frame->wl_frame_callback.reset(wl_surface_frame(surface->surface()));
wl_callback_add_listener(frame->wl_frame_callback.get(), &frame_listener,
this);
@@ -433,10 +442,9 @@ void WaylandFrameManager::VerifyNumberOfSubmittedFrames() {
}
}
-void WaylandFrameManager::OnExplicitBufferRelease(
- WaylandSurface* surface,
- struct wl_buffer* wl_buffer,
- absl::optional<int32_t> fence) {
+void WaylandFrameManager::OnExplicitBufferRelease(WaylandSurface* surface,
+ struct wl_buffer* wl_buffer,
+ base::ScopedFD fence) {
DCHECK(wl_buffer);
// Releases may not necessarily come in order, so search the submitted
@@ -449,14 +457,12 @@ void WaylandFrameManager::OnExplicitBufferRelease(
// linux_explicit_synchronization is used.
result->second->OnExplicitRelease();
- if (fence.has_value()) {
- base::ScopedFD fd{fence.value()};
- // Accumulate release fences into a single fence.
+ if (fence.is_valid()) {
if (frame->merged_release_fence_fd.is_valid()) {
- frame->merged_release_fence_fd.reset(
- sync_merge("", frame->merged_release_fence_fd.get(), fd.get()));
+ frame->merged_release_fence_fd.reset(sync_merge(
+ "", frame->merged_release_fence_fd.get(), fence.get()));
} else {
- frame->merged_release_fence_fd = std::move(fd);
+ frame->merged_release_fence_fd = std::move(fence);
}
DCHECK(frame->merged_release_fence_fd.is_valid());
}
@@ -541,8 +547,7 @@ void WaylandFrameManager::MaybeProcessSubmittedFrames() {
continue;
frame->presentation_acked = true;
connection_->buffer_manager_host()->OnPresentation(
- window_->GetWidget(), /*buffer_id*/ frame->buffer_id,
- frame->feedback.value());
+ window_->GetWidget(), frame->frame_id, frame->feedback.value());
}
// Clear frames that are fully released and has already called
@@ -571,8 +576,8 @@ void WaylandFrameManager::ProcessOldSubmittedFrame(
// release because SwapCompletionCallback indicates to the client that the
// buffers in previous frame is available for reuse.
connection_->buffer_manager_host()->OnSubmission(
- window_->GetWidget(), /*buffer_id*/ frame->buffer_id,
- gfx::SwapResult::SWAP_ACK, std::move(release_fence_handle));
+ window_->GetWidget(), frame->frame_id, gfx::SwapResult::SWAP_ACK,
+ std::move(release_fence_handle));
// If presentation feedback is not supported, use a fake feedback. This
// literally means there are no presentation feedback callbacks created.
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.h b/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.h
index 2ccc2522b3e..789fc5ed25a 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_frame_manager.h
@@ -32,13 +32,23 @@ class WaylandSubsurface;
// presented and released.
struct WaylandFrame {
public:
+ // A frame originated from gpu process, and hence, requires acknowledgements.
WaylandFrame(
+ uint32_t frame_id,
WaylandSurface* root_surface,
ui::ozone::mojom::WaylandOverlayConfigPtr root_config,
base::circular_deque<std::pair<WaylandSubsurface*,
ui::ozone::mojom::WaylandOverlayConfigPtr>>
- subsurfaces_to_overlays = {},
- bool expects_ack = true);
+ subsurfaces_to_overlays = {});
+
+ // A frame that does not require acknowledgements.
+ WaylandFrame(
+ WaylandSurface* root_surface,
+ ui::ozone::mojom::WaylandOverlayConfigPtr root_config,
+ base::circular_deque<std::pair<WaylandSubsurface*,
+ ui::ozone::mojom::WaylandOverlayConfigPtr>>
+ subsurfaces_to_overlays = {});
+
WaylandFrame() = delete;
WaylandFrame(const WaylandFrame&) = delete;
WaylandFrame& operator=(const WaylandFrame&) = delete;
@@ -47,6 +57,7 @@ struct WaylandFrame {
private:
friend class WaylandFrameManager;
+ uint32_t frame_id;
WaylandSurface* root_surface;
ui::ozone::mojom::WaylandOverlayConfigPtr root_config;
base::circular_deque<
@@ -55,11 +66,6 @@ struct WaylandFrame {
base::flat_map<WaylandSurface*, WaylandBufferHandle*> submitted_buffers;
- // ID of one of the buffers that will be attached to the subsurfaces. If none
- // of the buffers will be attached, this is |root_config->buffer_id|.
- // Used to invoke buffer_manager_host OnSubmission and OnPrensentation calls.
- uint32_t buffer_id;
-
// An indicator that there are buffers destrotyed before frame playback. This
// frame should be skipped.
bool buffer_lost = false;
@@ -73,7 +79,7 @@ struct WaylandFrame {
// for this frame.
base::ScopedFD merged_release_fence_fd;
// Whether this frame has had OnSubmission sent for it.
- bool submission_acked = false;
+ bool submission_acked;
// The wayland object identifying this feedback.
wl::Object<struct wp_presentation_feedback> pending_feedback;
@@ -81,7 +87,7 @@ struct WaylandFrame {
// Wayland server has not arrived yet.
absl::optional<gfx::PresentationFeedback> feedback = absl::nullopt;
// Whether this frame has had OnPresentation sent for it.
- bool presentation_acked = false;
+ bool presentation_acked;
};
// This is the frame update manager that configures graphical window/surface
@@ -129,7 +135,7 @@ class WaylandFrameManager {
gfx::GpuFenceHandle release_fence_handle);
void OnExplicitBufferRelease(WaylandSurface* surface,
struct wl_buffer* wl_buffer,
- absl::optional<int32_t> fence);
+ base::ScopedFD fence);
void OnWlBufferRelease(WaylandSurface* surface, struct wl_buffer* wl_buffer);
// wl_callback_listener
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
index 512a6153b26..ab716d20a64 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -388,12 +388,15 @@ void WaylandInputMethodContext::SetSurroundingText(
}
void WaylandInputMethodContext::SetContentType(TextInputType input_type,
- int input_flags) {
+ int input_flags,
+ bool should_do_learning) {
if (!text_input_)
return;
uint32_t content_purpose = InputTypeToContentPurpose(input_type);
uint32_t content_hint = InputFlagsToContentHint(input_flags);
+ if (!should_do_learning)
+ content_hint |= ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA;
text_input_->SetContentType(content_hint, content_purpose);
}
@@ -519,12 +522,32 @@ void WaylandInputMethodContext::OnDeleteSurroundingText(int32_t index,
void WaylandInputMethodContext::OnKeysym(uint32_t keysym,
uint32_t state,
- uint32_t modifiers) {
+ uint32_t modifiers_bits) {
#if BUILDFLAG(USE_XKBCOMMON)
auto* layout_engine = KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
if (!layout_engine)
return;
+ // TODO(crbug.com/1289236): This is for the backward compatibility with older
+ // ash-chrome (M101 and earlier). In that version of ash-chrome didn't send
+ // CapsLock so that we hit an issue on using it.
+ // Because newer ash-chrome always sends CapsLock modifier map, as short term
+ // workaround, check the condition to identify whether Lacros is running
+ // on top of enough newer ash-chrome.
+ // To avoid accident, we also check text_input_extension, which is available
+ // only on ash-chrome.
+ // We can remove this workaround check in M104 or later.
+ absl::optional<std::vector<base::StringPiece>> modifiers;
+ if (!connection_->text_input_extension_v1() ||
+ base::Contains(modifiers_map_, XKB_MOD_NAME_CAPS)) {
+ std::vector<base::StringPiece> modifier_content;
+ for (size_t i = 0; i < modifiers_map_.size(); ++i) {
+ if (modifiers_bits & (1 << i))
+ modifier_content.emplace_back(modifiers_map_[i]);
+ }
+ modifiers = std::move(modifier_content);
+ }
+
DomCode dom_code = static_cast<XkbKeyboardLayoutEngine*>(layout_engine)
->GetDomCodeByKeysym(keysym, modifiers);
if (dom_code == DomCode::NONE)
@@ -614,6 +637,11 @@ void WaylandInputMethodContext::OnInputPanelState(uint32_t state) {
// region somehow.
}
+void WaylandInputMethodContext::OnModifiersMap(
+ std::vector<std::string> modifiers_map) {
+ modifiers_map_ = std::move(modifiers_map);
+}
+
void WaylandInputMethodContext::OnKeyboardFocusedWindowChanged() {
MaybeUpdateActivated();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h
index d2b7082de56..4d11108cc35 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/observer_list.h"
#include "base/strings/string_piece.h"
#include "ui/base/ime/character_composer.h"
#include "ui/base/ime/linux/linux_input_method_context.h"
@@ -49,7 +48,9 @@ class WaylandInputMethodContext : public LinuxInputMethodContext,
void SetCursorLocation(const gfx::Rect& rect) override;
void SetSurroundingText(const std::u16string& text,
const gfx::Range& selection_range) override;
- void SetContentType(TextInputType input_type, int input_flags) override;
+ void SetContentType(TextInputType input_type,
+ int input_flags,
+ bool should_do_learning) override;
void Reset() override;
void Focus() override;
void Blur() override;
@@ -76,6 +77,7 @@ class WaylandInputMethodContext : public LinuxInputMethodContext,
uint32_t length,
const std::vector<SpanStyle>& spans) override;
void OnInputPanelState(uint32_t state) override;
+ void OnModifiersMap(std::vector<std::string> modifiers_map) override;
private:
void UpdatePreeditText(const std::u16string& preedit_text);
@@ -113,6 +115,9 @@ class WaylandInputMethodContext : public LinuxInputMethodContext,
// Caches VirtualKeyboard visibility.
bool virtual_keyboard_visible_ = false;
+
+ // Keeps modifiers_map sent from the wayland compositor.
+ std::vector<std::string> modifiers_map_;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
index 70b566e2b67..e9e09d700b0 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -388,7 +388,21 @@ TEST_P(WaylandInputMethodContextTest, SetContentType) {
ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL))
.Times(1);
input_method_context_->SetContentType(TEXT_INPUT_TYPE_URL,
- TEXT_INPUT_FLAG_AUTOCOMPLETE_ON);
+ TEXT_INPUT_FLAG_AUTOCOMPLETE_ON,
+ /*should_do_learning=*/true);
+ connection_->ScheduleFlush();
+ Sync();
+}
+
+TEST_P(WaylandInputMethodContextTest, SetContentTypeWithoutLearning) {
+ EXPECT_CALL(*zwp_text_input_,
+ SetContentType(ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION |
+ ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA,
+ ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL))
+ .Times(1);
+ input_method_context_->SetContentType(TEXT_INPUT_TYPE_URL,
+ TEXT_INPUT_FLAG_AUTOCOMPLETE_ON,
+ /*should_do_learning=*/false);
connection_->ScheduleFlush();
Sync();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_output.h b/chromium/ui/ozone/platform/wayland/host/wayland_output.h
index 68bd62c85ca..c36c7c77763 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_output.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_output.h
@@ -63,6 +63,8 @@ class WaylandOutput : public wl::GlobalObjectRegistrar<WaylandOutput> {
// global compositor space.
bool is_ready() const { return !rect_in_physical_pixels_.IsEmpty(); }
+ wl_output* get_output() { return output_.get(); }
+
private:
static constexpr int32_t kDefaultScaleFactor = 1;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
index c4d8ca41bcf..25d1fce653f 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_popup.cc
@@ -205,7 +205,7 @@ void WaylandPopup::ApplyPendingBounds() {
return;
base::AutoReset<bool> auto_reset(&wayland_sets_bounds_, true);
- SetBoundsDip(pending_configures_.back().bounds_dip);
+ WaylandWindow::ApplyPendingBounds();
}
void WaylandPopup::OnCloseRequest() {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc b/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc
index 3fde4d13c9b..241b037b5b3 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/containers/contains.h"
+#include "base/observer_list.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -224,9 +225,9 @@ display::Display WaylandScreen::GetDisplayForAcceleratedWidget(
}
gfx::Point WaylandScreen::GetCursorScreenPoint() const {
- // Wayland does not provide either location of surfaces in global space
- // coordinate system or location of a pointer. Instead, only locations of
- // mouse/touch events are known. Given that Chromium assumes top-level
+ // wl_shell/xdg-shell do not provide either location of surfaces in global
+ // space coordinate system or location of a pointer. Instead, only locations
+ // of mouse/touch events are known. Given that Chromium assumes top-level
// windows are located at origin, always provide a cursor point in regards
// to surfaces' location.
//
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
index f159a5b1dbc..6021298006f 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -764,12 +764,11 @@ TEST_P(WaylandScreenTest, SetWindowScale) {
display::Display::ResetForceDeviceScaleFactorForTesting();
}
-// Checks that transform is properly translated to Display orientation. The
-// first one is counter-clockwise, and the second is clockwise.
+// Checks that output transform is properly translated into Display orientation.
+// The first one is counter-clockwise, while the latter is clockwise.
TEST_P(WaylandScreenTest, Transform) {
- constexpr std::array<
- std::pair<wl_output_transform, display::Display::Rotation>, 8>
- test_data = {{
+ constexpr std::pair<wl_output_transform, display::Display::Rotation>
+ kTestData[] = {
{WL_OUTPUT_TRANSFORM_NORMAL, display::Display::ROTATE_0},
{WL_OUTPUT_TRANSFORM_90, display::Display::ROTATE_270},
{WL_OUTPUT_TRANSFORM_180, display::Display::ROTATE_180},
@@ -779,16 +778,16 @@ TEST_P(WaylandScreenTest, Transform) {
{WL_OUTPUT_TRANSFORM_FLIPPED_90, display::Display::ROTATE_0},
{WL_OUTPUT_TRANSFORM_FLIPPED_180, display::Display::ROTATE_0},
{WL_OUTPUT_TRANSFORM_FLIPPED_270, display::Display::ROTATE_0},
- }};
+ };
- for (const auto& i : test_data) {
- output_->SetTransform(i.first);
+ for (const auto& [transform, expected_rotation] : kTestData) {
+ output_->SetTransform(transform);
output_->Flush();
Sync();
auto main_display = platform_screen_->GetPrimaryDisplay();
- EXPECT_EQ(main_display.rotation(), i.second);
+ EXPECT_EQ(main_display.rotation(), expected_rotation);
}
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_serial_tracker.h b/chromium/ui/ozone/platform/wayland/host/wayland_serial_tracker.h
index 66de9a05e16..5230119838f 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_serial_tracker.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_serial_tracker.h
@@ -18,6 +18,10 @@ namespace wl {
// meta-data, received through Wayland protocol events. Each serial value is
// associated with an event type, which is represented by a SerialType enum
// entry.
+//
+// Note: SerialTracker must not be used to track related input object states,
+// e.g: whether a pointer button is pressed, or whether there are active touch
+// points. Instead, other specific APIs should be added/used for that.
enum class SerialType {
kMouseEnter,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.cc b/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.cc
index aa2f3dc483c..5f573173a23 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.cc
@@ -62,6 +62,9 @@ void WaylandSubsurface::Hide() {
if (!subsurface_)
return;
+ // Remove it from the stack.
+ RemoveFromList();
+
augmented_subsurface_.reset();
subsurface_.reset();
}
@@ -76,6 +79,10 @@ void WaylandSubsurface::CreateSubsurface() {
wl_subcompositor* subcompositor = connection_->subcompositor();
DCHECK(subcompositor);
subsurface_ = wayland_surface()->CreateSubsurface(parent_->root_surface());
+ position_dip_ = {0, 0};
+
+ // A new sub-surface is initially added as the top-most in the stack.
+ parent_->subsurface_stack_committed()->Append(this);
DCHECK(subsurface_);
wl_subsurface_set_sync(subsurface_.get());
@@ -99,8 +106,8 @@ void WaylandSubsurface::ConfigureAndShowSurface(
const gfx::RectF& bounds_px,
const gfx::RectF& parent_bounds_px,
float buffer_scale,
- const WaylandSurface* reference_below,
- const WaylandSurface* reference_above) {
+ WaylandSubsurface* new_below,
+ WaylandSubsurface* new_above) {
Show();
// Chromium positions quads in display::Display coordinates in physical
@@ -110,26 +117,35 @@ void WaylandSubsurface::ConfigureAndShowSurface(
bounds_px, parent_bounds_px,
connection_->surface_submission_in_pixel_coordinates() ? 1.f
: buffer_scale);
- if (augmented_subsurface_) {
- DCHECK(
- connection_->surface_augmenter()->SupportsSubpixelAccuratePosition());
- augmented_sub_surface_set_position(
- augmented_subsurface_.get(),
- wl_fixed_from_double(bounds_dip_in_parent_surface.x()),
- wl_fixed_from_double(bounds_dip_in_parent_surface.y()));
- } else {
- gfx::Rect enclosed_rect_in_parent =
- gfx::ToEnclosedRect(bounds_dip_in_parent_surface);
- wl_subsurface_set_position(subsurface_.get(), enclosed_rect_in_parent.x(),
- enclosed_rect_in_parent.y());
+ if (bounds_dip_in_parent_surface.origin() != position_dip_) {
+ position_dip_ = bounds_dip_in_parent_surface.origin();
+ if (augmented_subsurface_) {
+ DCHECK(
+ connection_->surface_augmenter()->SupportsSubpixelAccuratePosition());
+ augmented_sub_surface_set_position(
+ augmented_subsurface_.get(),
+ wl_fixed_from_double(bounds_dip_in_parent_surface.x()),
+ wl_fixed_from_double(bounds_dip_in_parent_surface.y()));
+ } else {
+ gfx::Rect enclosed_rect_in_parent =
+ gfx::ToEnclosedRect(bounds_dip_in_parent_surface);
+ wl_subsurface_set_position(subsurface_.get(), enclosed_rect_in_parent.x(),
+ enclosed_rect_in_parent.y());
+ }
}
// Setup the stacking order of this subsurface.
- DCHECK(!reference_above || !reference_below);
- if (reference_below) {
- wl_subsurface_place_above(subsurface_.get(), reference_below->surface());
- } else if (reference_above) {
- wl_subsurface_place_below(subsurface_.get(), reference_above->surface());
+ DCHECK(!new_above || !new_below);
+ if (new_below && new_below != previous()) {
+ DCHECK_EQ(parent_, new_below->parent_);
+ RemoveFromList();
+ InsertAfter(new_below);
+ wl_subsurface_place_above(subsurface_.get(), new_below->surface());
+ } else if (new_above && new_above != next()) {
+ DCHECK_EQ(parent_, new_above->parent_);
+ RemoveFromList();
+ InsertBefore(new_above);
+ wl_subsurface_place_below(subsurface_.get(), new_above->surface());
}
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.h b/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.h
index cedfff72f5c..db2455a47b7 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_subsurface.h
@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SUBSURFACE_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_SUBSURFACE_H_
+#include "base/containers/linked_list.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_surface.h"
@@ -15,7 +16,11 @@ class WaylandWindow;
// Wraps a wl_surface with a wl_subsurface role assigned. It is used to submit a
// buffer as a sub region of WaylandWindow.
-class WaylandSubsurface {
+//
+// Inherits base::LinkNode<> s.t. it's location in the subsurface stack can be
+// tracked and prevent us from sending excessive wl_subsurface.place_below/above
+// requests.
+class WaylandSubsurface : public base::LinkNode<WaylandSubsurface> {
public:
WaylandSubsurface(WaylandConnection* connection, WaylandWindow* parent);
WaylandSubsurface(const WaylandSubsurface&) = delete;
@@ -39,8 +44,8 @@ class WaylandSubsurface {
void ConfigureAndShowSurface(const gfx::RectF& bounds_px,
const gfx::RectF& parent_bounds_px,
float buffer_scale,
- const WaylandSurface* reference_below,
- const WaylandSurface* reference_above);
+ WaylandSubsurface* reference_below,
+ WaylandSubsurface* reference_above);
// Assigns wl_subsurface role to the wl_surface so it is visible when a
// wl_buffer is attached.
@@ -56,6 +61,7 @@ class WaylandSubsurface {
WaylandSurface wayland_surface_;
wl::Object<wl_subsurface> subsurface_;
wl::Object<augmented_sub_surface> augmented_subsurface_;
+ gfx::PointF position_dip_;
WaylandConnection* const connection_;
// |parent_| refers to the WaylandWindow whose wl_surface is the parent to
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
index 3eca6cd8951..0ff844dda1d 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -18,6 +18,7 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/overlay_prioritizer.h"
@@ -74,7 +75,13 @@ WaylandSurface::WaylandSurface(WaylandConnection* connection,
root_window_(root_window),
surface_(connection->CreateSurface()) {}
-WaylandSurface::~WaylandSurface() = default;
+WaylandSurface::~WaylandSurface() {
+ if (explicit_release_callback_.is_null())
+ return;
+ for (auto& release : linux_buffer_releases_) {
+ explicit_release_callback_.Run(release.second.buffer, base::ScopedFD());
+ }
+}
uint32_t WaylandSurface::GetSurfaceId() const {
if (!surface_)
@@ -210,7 +217,13 @@ void WaylandSurface::SetSurfaceBufferScale(float scale) {
void WaylandSurface::SetOpaqueRegion(const std::vector<gfx::Rect>* region_px) {
pending_state_.opaque_region_px.clear();
- if (!root_window_ || !root_window_->IsOpaqueWindow())
+ if (!root_window_)
+ return;
+ bool is_primary_or_root =
+ root_window_->root_surface() == this ||
+ (root_window()->primary_subsurface() &&
+ root_window()->primary_subsurface()->wayland_surface() == this);
+ if (is_primary_or_root && !root_window_->IsOpaqueWindow())
return;
if (region_px)
pending_state_.opaque_region_px = *region_px;
@@ -229,8 +242,12 @@ void WaylandSurface::SetOpaqueRegion(const std::vector<gfx::Rect>* region_px) {
void WaylandSurface::SetInputRegion(const gfx::Rect* region_px) {
pending_state_.input_region_px.reset();
- if (!root_window_ || root_window_->ShouldUseNativeFrame())
+ if (!root_window_)
+ return;
+ if (root_window_->root_surface() == this &&
+ root_window_->ShouldUseNativeFrame()) {
return;
+ }
if (region_px)
pending_state_.input_region_px = *region_px;
@@ -483,7 +500,7 @@ void WaylandSurface::ApplyPendingState() {
gfx::SizeF bounds = wl::ApplyWaylandTransform(
gfx::SizeF(pending_state_.buffer_size_px),
wl::ToWaylandTransform(pending_state_.buffer_transform));
- int32_t applying_surface_scale;
+ int32_t applying_surface_scale = surface_scale_set_;
// When viewport_px is set, wp_viewport will scale the surface accordingly.
// Thus, there is no need to downscale bounds as Wayland compositor
@@ -495,35 +512,38 @@ void WaylandSurface::ApplyPendingState() {
applying_surface_scale = pending_state_.buffer_scale;
bounds = gfx::ScaleSize(bounds, 1.f / pending_state_.buffer_scale);
}
- if (!SurfaceSubmissionInPixelCoordinates())
+ if (!SurfaceSubmissionInPixelCoordinates() &&
+ surface_scale_set_ != applying_surface_scale) {
wl_surface_set_buffer_scale(surface_.get(), applying_surface_scale);
+ surface_scale_set_ = applying_surface_scale;
+ }
+ DCHECK_GE(surface_scale_set_, 1);
gfx::RectF viewport_src_dip;
+ wl_fixed_t src_to_set[4] = {wl_fixed_from_int(-1), wl_fixed_from_int(-1),
+ wl_fixed_from_int(-1), wl_fixed_from_int(-1)};
if (pending_state_.crop.IsEmpty()) {
viewport_src_dip = gfx::RectF(bounds);
- // Unset crop (wp_viewport.set_source).
- if (viewport()) {
- wp_viewport_set_source(viewport(), wl_fixed_from_int(-1),
- wl_fixed_from_int(-1), wl_fixed_from_int(-1),
- wl_fixed_from_int(-1));
- }
} else {
viewport_src_dip =
gfx::ScaleRect(pending_state_.crop, bounds.width(), bounds.height());
- // Apply crop (wp_viewport.set_source).
DCHECK(viewport());
if (wl_fixed_from_double(viewport_src_dip.width()) == 0 ||
wl_fixed_from_double(viewport_src_dip.height()) == 0) {
LOG(ERROR) << "Sending viewport src with width/height zero will result "
"in wayland disconnection";
}
- if (viewport()) {
- wp_viewport_set_source(viewport(),
- wl_fixed_from_double(viewport_src_dip.x()),
- wl_fixed_from_double(viewport_src_dip.y()),
- wl_fixed_from_double(viewport_src_dip.width()),
- wl_fixed_from_double(viewport_src_dip.height()));
- }
+ src_to_set[0] = wl_fixed_from_double(viewport_src_dip.x()),
+ src_to_set[1] = wl_fixed_from_double(viewport_src_dip.y());
+ src_to_set[2] = wl_fixed_from_double(viewport_src_dip.width());
+ src_to_set[3] = wl_fixed_from_double(viewport_src_dip.height());
+ }
+ // Apply crop (wp_viewport.set_source).
+ if (viewport() && !std::equal(std::begin(src_to_set), std::end(src_to_set),
+ std::begin(src_set_))) {
+ wp_viewport_set_source(viewport(), src_to_set[0], src_to_set[1],
+ src_to_set[2], src_to_set[3]);
+ memcpy(src_set_, src_to_set, 4 * sizeof(*src_to_set));
}
gfx::SizeF viewport_dst_dip =
@@ -531,10 +551,16 @@ void WaylandSurface::ApplyPendingState() {
? viewport_src_dip.size()
: gfx::ScaleSize(pending_state_.viewport_px,
1.f / pending_state_.buffer_scale);
+ float dst_to_set[2] = {-1.f, -1.f};
if (viewport_dst_dip != viewport_src_dip.size()) {
- // Apply viewport scale (wp_viewport.set_destination).
+ dst_to_set[0] = viewport_dst_dip.width();
+ dst_to_set[1] = viewport_dst_dip.height();
+ }
+ // Apply viewport scale (wp_viewport.set_destination).
+ if (!std::equal(std::begin(dst_to_set), std::end(dst_to_set),
+ std::begin(dst_set_))) {
auto* augmented_surface = GetAugmentedSurface();
- if (augmented_surface &&
+ if (dst_to_set[0] > 0.f && augmented_surface &&
connection_->surface_augmenter()->SupportsSubpixelAccuratePosition()) {
// Subpixel accurate positioning is available since the surface augmenter
// version 2. Since that version, the augmented surface also supports
@@ -547,13 +573,14 @@ void WaylandSurface::ApplyPendingState() {
augmented_surface, wl_fixed_from_double(viewport_dst_dip.width()),
wl_fixed_from_double(viewport_dst_dip.height()));
} else if (viewport()) {
- wp_viewport_set_destination(viewport(),
- base::ClampCeil(viewport_dst_dip.width()),
- base::ClampCeil(viewport_dst_dip.height()));
+ wp_viewport_set_destination(
+ viewport(),
+ dst_to_set[0] > 0.f ? base::ClampCeil(viewport_dst_dip.width())
+ : static_cast<int>(dst_to_set[0]),
+ dst_to_set[1] > 0.f ? base::ClampCeil(viewport_dst_dip.height())
+ : static_cast<int>(dst_to_set[1]));
}
- } else if (viewport()) {
- // Unset viewport scale (wp_viewport.set_destination).
- wp_viewport_set_destination(viewport(), -1, -1);
+ memcpy(dst_set_, dst_to_set, 2 * sizeof(*dst_to_set));
}
DCHECK_LE(pending_state_.damage_px.size(), 1u);
@@ -577,28 +604,28 @@ void WaylandSurface::ApplyPendingState() {
pending_state_.damage_px.back().width(),
pending_state_.damage_px.back().height());
} else {
- // Calculate the damage region in surface coordinates.
- // The calculation for damage region relies on the assumption: The buffer is
- // always attached at surface location (0, 0).
- // It's possible to write logic that accounts for attaching buffer at other
- // locations, but it's currently unnecessary.
-
- // Apply buffer_transform (wl_surface.set_buffer_transform).
- gfx::Rect damage = wl::ApplyWaylandTransform(
- pending_state_.damage_px.back(), pending_state_.buffer_size_px,
- wl::ToWaylandTransform(pending_state_.buffer_transform));
- // Apply buffer_scale (wl_surface.set_buffer_scale).
- damage = gfx::ScaleToEnclosingRect(damage, 1.f / applying_surface_scale);
- // Adjust coordinates to |viewport_src| (wp_viewport.set_source).
- damage = wl::TranslateBoundsToParentCoordinates(
- damage, gfx::ToEnclosingRect(viewport_src_dip));
- // Apply viewport scale (wp_viewport.set_destination).
- if (viewport_dst_dip != viewport_src_dip.size()) {
- damage = gfx::ScaleToEnclosingRect(
- damage, viewport_dst_dip.width() / viewport_src_dip.width(),
- viewport_dst_dip.height() / viewport_src_dip.height());
+ gfx::RectF damage_uv =
+ gfx::ScaleRect(gfx::RectF(pending_state_.damage_px.back()),
+ 1.0f / pending_state_.buffer_size_px.width(),
+ 1.0f / pending_state_.buffer_size_px.height());
+
+ if (!pending_state_.crop.IsEmpty()) {
+ damage_uv.Offset(-pending_state_.crop.OffsetFromOrigin());
+ damage_uv.Scale(1.0f / pending_state_.crop.width(),
+ 1.0f / pending_state_.crop.height());
}
+ damage_uv.Intersect(gfx::RectF(1, 1));
+
+ gfx::RectF damage_uv_transformed = wl::ApplyWaylandTransform(
+ damage_uv, gfx::SizeF(1, 1),
+ wl::ToWaylandTransform(pending_state_.buffer_transform));
+ gfx::RectF damage_float =
+ gfx::ScaleRect(damage_uv_transformed, viewport_dst_dip.width(),
+ viewport_dst_dip.height());
+ constexpr float kAcceptableSubDipDamageError = 0.001f;
+ gfx::Rect damage = gfx::ToEnclosingRectIgnoringError(
+ damage_float, kAcceptableSubDipDamageError);
wl_surface_damage(surface_.get(), damage.x(), damage.y(), damage.width(),
damage.height());
}
@@ -613,12 +640,12 @@ void WaylandSurface::SetApplyStateImmediately() {
void WaylandSurface::ExplicitRelease(
struct zwp_linux_buffer_release_v1* linux_buffer_release,
- absl::optional<int32_t> fence) {
+ base::ScopedFD fence) {
auto iter = linux_buffer_releases_.find(linux_buffer_release);
DCHECK(iter != linux_buffer_releases_.end());
DCHECK(iter->second.buffer);
if (!explicit_release_callback_.is_null())
- explicit_release_callback_.Run(iter->second.buffer, fence);
+ explicit_release_callback_.Run(iter->second.buffer, std::move(fence));
linux_buffer_releases_.erase(iter);
}
@@ -717,8 +744,9 @@ void WaylandSurface::FencedRelease(
void* data,
struct zwp_linux_buffer_release_v1* linux_buffer_release,
int32_t fence) {
+ auto fd = base::ScopedFD(fence);
static_cast<WaylandSurface*>(data)->ExplicitRelease(linux_buffer_release,
- fence);
+ std::move(fd));
}
// static
@@ -726,7 +754,7 @@ void WaylandSurface::ImmediateRelease(
void* data,
struct zwp_linux_buffer_release_v1* linux_buffer_release) {
static_cast<WaylandSurface*>(data)->ExplicitRelease(linux_buffer_release,
- absl::nullopt);
+ base::ScopedFD());
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_surface.h b/chromium/ui/ozone/platform/wayland/host/wayland_surface.h
index 1e78c3ddeb1..e6b4e2f07f1 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_surface.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_surface.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
+#include "base/files/scoped_file.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -34,7 +35,7 @@ class WaylandBufferHandle;
class WaylandSurface {
public:
using ExplicitReleaseCallback =
- base::RepeatingCallback<void(wl_buffer*, absl::optional<int32_t>)>;
+ base::RepeatingCallback<void(wl_buffer*, base::ScopedFD)>;
WaylandSurface(WaylandConnection* connection, WaylandWindow* ro_window);
WaylandSurface(const WaylandSurface&) = delete;
@@ -238,6 +239,14 @@ class WaylandSurface {
gfx::OverlayPriorityHint priority_hint = gfx::OverlayPriorityHint::kRegular;
};
+ // Tracks the last sent src and dst values across wayland protocol s.t. we
+ // skip resending them when possible.
+ wl_fixed_t src_set_[4] = {wl_fixed_from_int(-1), wl_fixed_from_int(-1),
+ wl_fixed_from_int(-1), wl_fixed_from_int(-1)};
+ float dst_set_[2] = {-1.f, -1.f};
+ // Tracks the last sent surface_scale value s.t. we skip resending.
+ int32_t surface_scale_set_ = 1;
+
wl::Object<wl_region> CreateAndAddRegion(
const std::vector<gfx::Rect>& region_px,
int32_t buffer_scale);
@@ -281,7 +290,7 @@ class WaylandSurface {
std::vector<uint32_t> entered_outputs_;
void ExplicitRelease(struct zwp_linux_buffer_release_v1* linux_buffer_release,
- absl::optional<int32_t> fence);
+ base::ScopedFD fence);
// wl_surface_listener
static void Enter(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
index 215cbc9d915..c0843b39d4f 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -14,6 +14,7 @@
#include "build/chromeos_buildflags.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/hit_test.h"
+#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/gtk_shell1.h"
@@ -45,7 +46,9 @@ constexpr int kVisibleOnAllWorkspaces = -1;
WaylandToplevelWindow::WaylandToplevelWindow(PlatformWindowDelegate* delegate,
WaylandConnection* connection)
: WaylandWindow(delegate, connection),
- state_(PlatformWindowState::kNormal) {
+ state_(PlatformWindowState::kNormal),
+ screen_coordinates_enabled_(
+ features::IsWaylandScreenCoordinatesEnabled()) {
// Set a class property key, which allows |this| to be used for interactive
// events, e.g. move or resize.
SetWmMoveResizeHandler(this, AsWmMoveResizeHandler());
@@ -76,6 +79,10 @@ bool WaylandToplevelWindow::CreateShellToplevel() {
TriggerStateChanges();
SetUpShellIntegration();
OnDecorationModeChanged();
+
+ if (screen_coordinates_enabled_)
+ SetBounds(GetBounds());
+
// This could be the proper time to update window mask using
// NonClientView::GetWindowMask, since |non_client_view| is not created yet
// during the call to WaylandWindow::Initialize().
@@ -89,7 +96,7 @@ void WaylandToplevelWindow::ApplyPendingBounds() {
return;
DCHECK(shell_toplevel_);
- SetBoundsDip(pending_configures_.back().bounds_dip);
+ WaylandWindow::ApplyPendingBounds();
}
void WaylandToplevelWindow::DispatchHostWindowDragMovement(
@@ -319,6 +326,17 @@ void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width_dip,
bool is_maximized,
bool is_fullscreen,
bool is_activated) {
+ HandleAuraToplevelConfigure(0, 0, width_dip, height_dip, is_maximized,
+ is_fullscreen, is_activated);
+}
+
+void WaylandToplevelWindow::HandleAuraToplevelConfigure(int32_t x,
+ int32_t y,
+ int32_t width_dip,
+ int32_t height_dip,
+ bool is_maximized,
+ bool is_fullscreen,
+ bool is_activated) {
// Store the old state to propagte state changes if Wayland decides to change
// the state to something else.
PlatformWindowState old_state = state_;
@@ -359,11 +377,11 @@ void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width_dip,
// explicitly set the bounds to the current desired ones or the previous
// bounds.
if (width_dip > 1 && height_dip > 1) {
- pending_bounds_dip_ = gfx::Rect(0, 0, width_dip, height_dip);
+ pending_bounds_dip_ = gfx::Rect(x, y, width_dip, height_dip);
if (is_normal && frame_insets_px()) {
pending_bounds_dip_.Inset(
-gfx::ScaleToRoundedInsets(*frame_insets_px(), 1.f / window_scale()));
- pending_bounds_dip_.set_origin({0, 0});
+ pending_bounds_dip_.set_origin({x, y});
}
} else if (is_normal) {
pending_bounds_dip_.set_size(
@@ -373,6 +391,11 @@ void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width_dip,
1.0 / window_scale()));
}
+ pending_bounds_dip_ = gfx::ScaleToRoundedRect(
+ AdjustBoundsToConstraintsPx(
+ gfx::ScaleToRoundedRect(pending_bounds_dip_, window_scale())),
+ 1 / window_scale());
+
// Store the restored bounds if current state differs from the normal state.
// It can be client or compositor side change from normal to something else.
// Thus, we must store previous bounds to restore later.
@@ -389,6 +412,22 @@ void WaylandToplevelWindow::HandleToplevelConfigure(int32_t width_dip,
state_change_in_transit_ = false;
}
+void WaylandToplevelWindow::SetBounds(const gfx::Rect& bounds) {
+ if (!shell_toplevel_ || !screen_coordinates_enabled_) {
+ WaylandWindow::SetBounds(bounds);
+ return;
+ }
+ gfx::Rect bounds_in_dip =
+ gfx::ScaleToEnclosingRect(bounds, 1.f / window_scale());
+ shell_toplevel_->RequestWindowBounds(bounds_in_dip);
+}
+
+void WaylandToplevelWindow::SetOrigin(const gfx::Point& origin) {
+ gfx::Point origin_px =
+ gfx::ScaleToFlooredPoint(origin, window_scale(), window_scale());
+ WaylandWindow::SetBounds(gfx::Rect(origin_px, GetBounds().size()));
+}
+
void WaylandToplevelWindow::HandleSurfaceConfigure(uint32_t serial) {
ProcessPendingBoundsDip(serial);
pending_bounds_dip_ = gfx::Rect();
@@ -454,11 +493,13 @@ void WaylandToplevelWindow::SetWindowGeometry(gfx::Rect bounds_dip) {
if (!shell_toplevel_)
return;
+ gfx::Rect geometry_dip(bounds_dip.size());
+
if (state_ == PlatformWindowState::kNormal && frame_insets_px()) {
- bounds_dip.Inset(
+ geometry_dip.Inset(
gfx::ScaleToRoundedInsets(*frame_insets_px(), 1.f / window_scale()));
}
- shell_toplevel_->SetWindowGeometry(bounds_dip);
+ shell_toplevel_->SetWindowGeometry(geometry_dip);
}
void WaylandToplevelWindow::AckConfigure(uint32_t serial) {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
index 928f5ad52b1..f1887b3f2e7 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -69,10 +69,18 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetOpaqueRegion(const std::vector<gfx::Rect>* region_px) override;
void SetInputRegion(const gfx::Rect* region_px) override;
void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
+ void SetBounds(const gfx::Rect& bounds) override;
+
+ // Sets the window's origin.
+ void SetOrigin(const gfx::Point& origin);
// WaylandWindow overrides:
absl::optional<std::vector<gfx::Rect>> GetWindowShape() const override;
+ bool screen_coordinates_enabled() const {
+ return screen_coordinates_enabled_;
+ }
+
// Client-side decorations on Wayland take some portion of the window surface,
// and when they are turned on or off, the window geometry is changed. That
// happens only once at the moment of switching the decoration mode, and has
@@ -89,6 +97,13 @@ class WaylandToplevelWindow : public WaylandWindow,
bool is_maximized,
bool is_fullscreen,
bool is_activated) override;
+ void HandleAuraToplevelConfigure(int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height,
+ bool is_maximized,
+ bool is_fullscreen,
+ bool is_activated) override;
void HandleSurfaceConfigure(uint32_t serial) override;
void UpdateVisualSize(const gfx::Size& size_px, float scale_factor) override;
bool OnInitialize(PlatformWindowInitProperties properties) override;
@@ -273,6 +288,9 @@ class WaylandToplevelWindow : public WaylandWindow,
// If |workspace_| is -1, window is visible on all workspaces.
absl::optional<int> workspace_ = absl::nullopt;
+ // True when screen coordinates is enabled.
+ bool screen_coordinates_enabled_;
+
WorkspaceExtensionDelegate* workspace_extension_delegate_ = nullptr;
};
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_touch.cc b/chromium/ui/ozone/platform/wayland/host/wayland_touch.cc
index 77629d7c52f..8b5c21639be 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_touch.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_touch.cc
@@ -62,12 +62,6 @@ void WaylandTouch::Up(void* data,
base::TimeTicks timestamp = base::TimeTicks() + base::Milliseconds(time);
touch->delegate_->OnTouchReleaseEvent(timestamp, id);
-
- // Reset kTouchPress serial only after dispatching touch-up event, so popups
- // may detect if they were triggered by a tap gesture, and avoid grab in such
- // case, which, per the spec, is illegal and may lead to instant popup
- // dismissal by the compositor.
- touch->connection_->serial_tracker().ResetSerial(wl::SerialType::kTouchPress);
}
void WaylandTouch::Motion(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
index 7a707aee4fd..273f4b514ad 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom.h"
@@ -93,6 +94,9 @@ WaylandWindow::~WaylandWindow() {
// Thus, the parent will have another child window. Do not reset it.
if (parent_window_ && parent_window_->child_window() == this)
parent_window_->set_child_window(nullptr);
+
+ if (child_window_)
+ child_window_->set_parent_window(nullptr);
}
void WaylandWindow::OnWindowLostCapture() {
@@ -252,8 +256,7 @@ void WaylandWindow::OnChannelDestroyed() {
subsurfaces_to_overlays.emplace_back(subsurface.get(), nullptr);
frame_manager_->RecordFrame(std::make_unique<WaylandFrame>(
- root_surface(), nullptr, std::move(subsurfaces_to_overlays),
- /*expects_ack=*/false));
+ root_surface(), nullptr, std::move(subsurfaces_to_overlays)));
}
void WaylandWindow::Close() {
@@ -271,23 +274,7 @@ void WaylandWindow::PrepareForShutdown() {
}
void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) {
- gfx::Rect adjusted_bounds_px = bounds_px;
-
- if (const auto min_size = delegate_->GetMinimumSizeForWindow()) {
- if (min_size->width() > 0 && adjusted_bounds_px.width() < min_size->width())
- adjusted_bounds_px.set_width(min_size->width());
- if (min_size->height() > 0 &&
- adjusted_bounds_px.height() < min_size->height())
- adjusted_bounds_px.set_height(min_size->height());
- }
- if (const auto max_size = delegate_->GetMaximumSizeForWindow()) {
- if (max_size->width() > 0 && adjusted_bounds_px.width() > max_size->width())
- adjusted_bounds_px.set_width(max_size->width());
- if (max_size->height() > 0 &&
- adjusted_bounds_px.height() > max_size->height())
- adjusted_bounds_px.set_height(max_size->height());
- }
-
+ gfx::Rect adjusted_bounds_px = AdjustBoundsToConstraintsPx(bounds_px);
if (bounds_px_ == adjusted_bounds_px)
return;
bounds_px_ = adjusted_bounds_px;
@@ -496,6 +483,17 @@ void WaylandWindow::HandleToplevelConfigure(int32_t widht,
<< "Only shell toplevels must receive HandleToplevelConfigure calls.";
}
+void WaylandWindow::HandleAuraToplevelConfigure(int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height,
+ bool is_maximized,
+ bool is_fullscreen,
+ bool is_activated) {
+ NOTREACHED()
+ << "Only shell toplevels must receive HandleAuraToplevelConfigure calls.";
+}
+
void WaylandWindow::HandlePopupConfigure(const gfx::Rect& bounds_dip) {
NOTREACHED() << "Only shell popups must receive HandlePopupConfigure calls.";
}
@@ -576,7 +574,10 @@ void WaylandWindow::OnDragSessionClose(DragOperation operation) {
}
void WaylandWindow::SetBoundsDip(const gfx::Rect& bounds_dip) {
- SetBounds(gfx::ScaleToRoundedRect(bounds_dip, window_scale()));
+ // This method is used to update the content size, and this method is calling
+ // WindowWindow's SetBounds to avoid calling into
+ // WaylandToplevelWindow::SetBounds which sends a request to a compostior.
+ WaylandWindow::SetBounds(gfx::ScaleToRoundedRect(bounds_dip, window_scale()));
}
bool WaylandWindow::Initialize(PlatformWindowInitProperties properties) {
@@ -663,11 +664,11 @@ void WaylandWindow::UpdateCursorPositionFromEvent(
//
// Basically, this method must translate coordinates of all events
// in regards to top-level windows' coordinates as it's always located at
- // origin (0,0) from Chromium point of view (remember that Wayland doesn't
- // provide global coordinates to its clients). And it's totally fine to use it
- // as the target. Thus, the location of the |event| is always converted using
- // the top-level window's bounds as the target excluding cases, when the
- // mouse/touch is over a top-level window.
+ // origin (0,0) from Chromium point of view (remember that wl_shell/xdg_shell
+ // doesn't provide global coordinates to its clients). And it's totally fine
+ // to use it as the target. Thus, the location of the |event| is always
+ // converted using the top-level window's bounds as the target excluding
+ // cases, when the mouse/touch is over a top-level window.
auto* toplevel_window = GetRootParentWindow();
if (toplevel_window != this) {
ConvertEventLocationToTargetWindowLocation(
@@ -677,7 +678,8 @@ void WaylandWindow::UpdateCursorPositionFromEvent(
auto* cursor_position = connection_->wayland_cursor_position();
if (cursor_position) {
cursor_position->OnCursorPositionChanged(
- event->AsLocatedEvent()->location());
+ event->AsLocatedEvent()->location() +
+ toplevel_window->GetBoundsInDIP().origin().OffsetFromOrigin());
}
}
@@ -704,7 +706,8 @@ gfx::PointF WaylandWindow::ToRootWindowPixel(const gfx::PointF& location_dp) {
if (!connection_->surface_submission_in_pixel_coordinates())
location_px.Scale(window_scale());
- return location_px;
+ auto* root_window = GetRootParentWindow();
+ return location_px + root_window->GetBounds().origin().OffsetFromOrigin();
}
WaylandWindow* WaylandWindow::GetTopMostChildWindow() {
@@ -783,6 +786,7 @@ bool WaylandWindow::ArrangeSubsurfaceStack(size_t above, size_t below) {
}
bool WaylandWindow::CommitOverlays(
+ uint32_t frame_id,
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr>& overlays) {
if (overlays.empty())
return true;
@@ -795,7 +799,7 @@ bool WaylandWindow::CommitOverlays(
ozone::mojom::WaylandOverlayConfig::New();
auto split = std::lower_bound(overlays.begin(), overlays.end(), value,
OverlayStackOrderCompare);
- CHECK(split == overlays.end() || (*split)->z_order >= 0);
+ DCHECK(split == overlays.end() || (*split)->z_order >= 0);
size_t num_primary_planes =
(split != overlays.end() && (*split)->z_order == 0) ? 1 : 0;
size_t num_background_planes =
@@ -809,18 +813,14 @@ bool WaylandWindow::CommitOverlays(
if (!ArrangeSubsurfaceStack(above, below))
return false;
- auto main_overlay = split;
- if (split == overlays.end() && overlays.front()->z_order == INT32_MIN)
- main_overlay = overlays.begin();
-
- gfx::SizeF visual_size = (*main_overlay)->bounds_rect.size();
- float buffer_scale = (*main_overlay)->surface_scale_factor;
- auto& rounded_clip_bounds = (*main_overlay)->rounded_clip_bounds;
+ gfx::SizeF visual_size = (*overlays.begin())->bounds_rect.size();
+ float buffer_scale = (*overlays.begin())->surface_scale_factor;
+ auto& rounded_clip_bounds = (*overlays.begin())->rounded_clip_bounds;
if (!wayland_overlay_delegation_enabled_) {
DCHECK_EQ(overlays.size(), 1u);
frame_manager_->RecordFrame(std::make_unique<WaylandFrame>(
- root_surface(), std::move(*main_overlay)));
+ frame_id, root_surface(), std::move(*overlays.begin())));
return true;
}
@@ -831,10 +831,8 @@ bool WaylandWindow::CommitOverlays(
std::max(overlays.size() - num_background_planes,
wayland_subsurfaces_.size() + 1));
- if (num_primary_planes) {
- subsurfaces_to_overlays.emplace_back(primary_subsurface(),
- std::move(*split));
- }
+ subsurfaces_to_overlays.emplace_back(
+ primary_subsurface(), num_primary_planes ? std::move(*split) : nullptr);
{
// Iterate through |subsurface_stack_below_|, setup subsurfaces and place
@@ -873,21 +871,17 @@ bool WaylandWindow::CommitOverlays(
if (num_background_planes) {
root_config = std::move(overlays.front());
} else {
- root_config = ui::ozone::mojom::WaylandOverlayConfig::New();
- root_config->z_order = INT32_MIN;
- root_config->transform = gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE;
- root_config->buffer_id = root_surface()->buffer_id();
- root_config->enable_blend = root_surface()->use_blending();
- root_config->opacity = root_surface()->opacity();
- root_config->priority_hint = gfx::OverlayPriorityHint::kNone;
+ root_config = ui::ozone::mojom::WaylandOverlayConfig::New(
+ INT32_MIN, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE,
+ root_surface()->buffer_id(), buffer_scale, gfx::RectF(visual_size),
+ gfx::RectF(), gfx::Rect(), root_surface()->use_blending(),
+ root_surface()->opacity(), gfx::GpuFenceHandle(),
+ gfx::OverlayPriorityHint::kNone, rounded_clip_bounds);
}
- root_config->bounds_rect.set_size(visual_size);
- root_config->surface_scale_factor = buffer_scale;
- root_config->rounded_clip_bounds = rounded_clip_bounds;
- frame_manager_->RecordFrame(
- std::make_unique<WaylandFrame>(root_surface(), std::move(root_config),
- std::move(subsurfaces_to_overlays)));
+ frame_manager_->RecordFrame(std::make_unique<WaylandFrame>(
+ frame_id, root_surface(), std::move(root_config),
+ std::move(subsurfaces_to_overlays)));
return true;
}
@@ -981,18 +975,47 @@ void WaylandWindow::ProcessPendingBoundsDip(uint32_t serial) {
}
}
+gfx::Rect WaylandWindow::AdjustBoundsToConstraintsPx(
+ const gfx::Rect& bounds_px) {
+ gfx::Rect adjusted_bounds_px = bounds_px;
+ if (const auto min_size = delegate_->GetMinimumSizeForWindow()) {
+ if (min_size->width() > 0 && adjusted_bounds_px.width() < min_size->width())
+ adjusted_bounds_px.set_width(min_size->width());
+ if (min_size->height() > 0 &&
+ adjusted_bounds_px.height() < min_size->height())
+ adjusted_bounds_px.set_height(min_size->height());
+ }
+ if (const auto max_size = delegate_->GetMaximumSizeForWindow()) {
+ if (max_size->width() > 0 && adjusted_bounds_px.width() > max_size->width())
+ adjusted_bounds_px.set_width(max_size->width());
+ if (max_size->height() > 0 &&
+ adjusted_bounds_px.height() > max_size->height())
+ adjusted_bounds_px.set_height(max_size->height());
+ }
+ return adjusted_bounds_px;
+}
+
bool WaylandWindow::ProcessVisualSizeUpdate(const gfx::Size& size_px,
float scale_factor) {
+ // TODO(crbug.com/1307501): Optimize this to be less expensive. Maybe
+ // precompute in pixels for configure events. pending_configures_ can have 10s
+ // of elements in it for several frames under some conditions.
auto result = std::find_if(
pending_configures_.begin(), pending_configures_.end(),
- [&size_px, &scale_factor](auto& configure) {
- return gfx::ScaleToRoundedRect(configure.bounds_dip, scale_factor)
- .size() == size_px;
+ [this, &size_px, &scale_factor](auto& configure) {
+ // Since size_px comes from SetBounds via UpdateVisualSize in
+ // WaylandTopLevelWindow, we also need to adjust it for bounds to see if
+ // we match.
+ return AdjustBoundsToConstraintsPx(
+ gfx::ScaleToRoundedRect(configure.bounds_dip, scale_factor))
+ .size() == size_px &&
+ configure.set;
});
if (result != pending_configures_.end()) {
+ auto serial = result->serial;
SetWindowGeometry(result->bounds_dip);
- AckConfigure(result->serial);
+ AckConfigure(serial);
connection()->ScheduleFlush();
pending_configures_.erase(pending_configures_.begin(), ++result);
return true;
@@ -1000,4 +1023,11 @@ bool WaylandWindow::ProcessVisualSizeUpdate(const gfx::Size& size_px,
return false;
}
+void WaylandWindow::ApplyPendingBounds() {
+ DCHECK(!pending_configures_.empty());
+ for (auto& configure : pending_configures_)
+ configure.set = true;
+ SetBoundsDip(pending_configures_.back().bounds_dip);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window.h b/chromium/ui/ozone/platform/wayland/host/wayland_window.h
index 8015c35c5e7..52472f360ae 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window.h
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/containers/circular_deque.h"
#include "base/containers/flat_set.h"
+#include "base/containers/linked_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
@@ -78,6 +79,10 @@ class WaylandWindow : public PlatformWindow,
return wayland_subsurfaces_;
}
+ base::LinkedList<WaylandSubsurface>* subsurface_stack_committed() {
+ return &subsurface_stack_committed_;
+ }
+
void set_parent_window(WaylandWindow* parent_window) {
parent_window_ = parent_window;
}
@@ -93,6 +98,7 @@ class WaylandWindow : public PlatformWindow,
// subsurface_stack_below_.size() >= below.
bool ArrangeSubsurfaceStack(size_t above, size_t below);
bool CommitOverlays(
+ uint32_t frame_id,
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr>& overlays);
// Set whether this window has pointer focus and should dispatch mouse events.
@@ -202,11 +208,18 @@ class WaylandWindow : public PlatformWindow,
// The width and height come in DIP of the output that the surface is
// currently bound to.
virtual void HandleSurfaceConfigure(uint32_t serial);
- virtual void HandleToplevelConfigure(int32_t widht,
+ virtual void HandleToplevelConfigure(int32_t width,
int32_t height,
bool is_maximized,
bool is_fullscreen,
bool is_activated);
+ virtual void HandleAuraToplevelConfigure(int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height,
+ bool is_maximized,
+ bool is_fullscreen,
+ bool is_activated);
virtual void HandlePopupConfigure(const gfx::Rect& bounds);
// The final size of the Wayland surface is determined by the buffer size in
// px * scale that the Chromium compositor renders at. If the window changes a
@@ -318,12 +331,16 @@ class WaylandWindow : public PlatformWindow,
// Processes the pending bounds in dip.
void ProcessPendingBoundsDip(uint32_t serial);
+ // If the given |bounds_px| violate size constraints set for this window,
+ // fixes them so they wouldn't.
+ gfx::Rect AdjustBoundsToConstraintsPx(const gfx::Rect& bounds_px);
+
// Processes the size information form visual size update and returns true if
// any pending configure is fulfilled.
bool ProcessVisualSizeUpdate(const gfx::Size& size_px, float scale_factor);
// Applies pending bounds.
- virtual void ApplyPendingBounds() = 0;
+ virtual void ApplyPendingBounds();
// These bounds attributes below have suffixes that indicate units used.
// Wayland operates in DIP but the platform operates in physical pixels so
@@ -342,11 +359,14 @@ class WaylandWindow : public PlatformWindow,
struct PendingConfigure {
gfx::Rect bounds_dip;
uint32_t serial;
+ // True if this configure has been passed to the compositor for rendering.
+ bool set = false;
};
base::circular_deque<PendingConfigure> pending_configures_;
private:
friend class WaylandBufferManagerViewportTest;
+ friend class BlockableWaylandToplevelWindow;
FRIEND_TEST_ALL_PREFIXES(WaylandScreenTest, SetWindowScale);
FRIEND_TEST_ALL_PREFIXES(WaylandBufferManagerTest, CanSubmitOverlayPriority);
@@ -404,11 +424,15 @@ class WaylandWindow : public PlatformWindow,
// The stack of sub-surfaces to take effect when Commit() is called.
// |subsurface_stack_above_| refers to subsurfaces that are stacked above the
- // primary.
+ // primary. These include the subsurfaces to be hidden as well.
// Subsurface at the front of the list is the closest to the primary.
std::list<WaylandSubsurface*> subsurface_stack_above_;
std::list<WaylandSubsurface*> subsurface_stack_below_;
+ // The stack of sub-surfaces currently committed. This list is altered when
+ // the subsurface arrangement are played back by WaylandFrameManager.
+ base::LinkedList<WaylandSubsurface> subsurface_stack_committed_;
+
// The current cursor bitmap (immutable).
scoped_refptr<BitmapCursor> cursor_;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
index e993f399190..84ac475378b 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/check.h"
+#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
@@ -108,12 +109,6 @@ bool WaylandWindowDragController::StartDragSession() {
if (state_ != State::kIdle)
return true;
- origin_window_ = window_manager_->GetCurrentPointerOrTouchFocusedWindow();
- if (!origin_window_) {
- LOG(ERROR) << "Failed to get origin window.";
- return false;
- }
-
auto serial = connection_->serial_tracker().GetSerial(
{wl::SerialType::kTouchPress, wl::SerialType::kMousePress});
if (!serial.has_value()) {
@@ -127,6 +122,14 @@ bool WaylandWindowDragController::StartDragSession() {
? DragSource::kTouch
: DragSource::kMouse;
+ origin_window_ = *drag_source_ == DragSource::kMouse
+ ? window_manager_->GetCurrentPointerFocusedWindow()
+ : window_manager_->GetCurrentTouchFocusedWindow();
+ if (!origin_window_) {
+ LOG(ERROR) << "Failed to get origin window.";
+ return false;
+ }
+
DCHECK(!data_source_);
data_source_ = data_device_manager_->CreateSource(this);
data_source_->Offer({kMimeTypeChromiumWindow});
@@ -186,7 +189,6 @@ void WaylandWindowDragController::StopDragging() {
state_ = State::kAttaching;
pointer_grab_owner_ =
window_manager_->GetCurrentPointerOrTouchFocusedWindow();
- DCHECK(pointer_grab_owner_);
QuitLoop();
}
@@ -232,12 +234,10 @@ void WaylandWindowDragController::OnDragEnter(WaylandWindow* window,
// TODO(crbug.com/1102946): Exo does not support custom mime types. In this
// case, |data_offer_| will hold an empty mime_types list and, at this point,
// it's safe just to skip the offer checks and requests here.
- if (data_offer_->mime_types().empty())
+ if (!base::Contains(data_offer_->mime_types(), kMimeTypeChromiumWindow)) {
+ DVLOG(1) << "OnEnter. No valid mime type found.";
return;
-
- // Ensure this is a valid "window drag" offer.
- DCHECK_EQ(data_offer_->mime_types().size(), 1u);
- DCHECK_EQ(data_offer_->mime_types().front(), kMimeTypeChromiumWindow);
+ }
// Accept the offer and set the dnd action.
data_offer_->SetDndActions(kDndActionWindowDrag);
@@ -360,7 +360,7 @@ void WaylandWindowDragController::OnDataSourceFinish(bool completed) {
pointer_delegate_->OnPointerFocusChanged(dragged_window_,
pointer_location_);
} else {
- touch_delegate_->OnTouchFocusChanged(nullptr);
+ touch_delegate_->OnTouchFocusChanged(dragged_window_);
}
}
dragged_window_ = nullptr;
@@ -421,7 +421,6 @@ void WaylandWindowDragController::OnToplevelWindowCreated(
void WaylandWindowDragController::OnWindowRemoved(WaylandWindow* window) {
DCHECK_NE(state_, State::kIdle);
- DCHECK_NE(window, dragged_window_);
DVLOG(1) << "Window being destroyed. widget=" << window->GetWidget();
if (window == pointer_grab_owner_)
@@ -429,29 +428,34 @@ void WaylandWindowDragController::OnWindowRemoved(WaylandWindow* window) {
if (window == origin_window_)
origin_surface_ = origin_window_->TakeWaylandSurface();
+
+ if (window == dragged_window_)
+ SetDraggedWindow(nullptr, {});
}
void WaylandWindowDragController::HandleMotionEvent(LocatedEvent* event) {
DCHECK_EQ(state_, State::kDetached);
- DCHECK(dragged_window_);
DCHECK(event);
if (!should_process_drag_event_)
return;
- // Update current cursor position, so it can be retrieved later on through
+ // Update current cursor position relative to the event source
+ // (pointer_grab_owner_) so it can be retrieved later on through
// |Screen::GetCursorScreenPoint| API.
- connection_->wayland_cursor_position()->OnCursorPositionChanged(
- event->location());
+ if (pointer_grab_owner_)
+ pointer_grab_owner_->UpdateCursorPositionFromEvent(Event::Clone(*event));
// Notify listeners about window bounds change (i.e: re-positioning) event.
// To do so, set the new bounds as per the motion event location and the drag
// offset. Note that setting a new location (i.e: bounds.origin()) for a
// surface has no visual effect in ozone/wayland backend. Actual window
// re-positioning during dragging session is done through the drag icon.
- gfx::Point new_location = event->location() - drag_offset_;
- gfx::Size size = dragged_window_->GetBounds().size();
- dragged_window_->SetBounds({new_location, size});
+ if (dragged_window_) {
+ gfx::Point new_location = event->location() - drag_offset_;
+ gfx::Size size = dragged_window_->GetBounds().size();
+ dragged_window_->SetBounds({new_location, size});
+ }
should_process_drag_event_ = false;
}
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
index 0d3f9fbe21e..152b2de28fb 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller.h
@@ -88,11 +88,13 @@ class WaylandWindowDragController : public WaylandDataDevice::DragDelegate,
set_extended_drag_available_for_testing_ = true;
}
+ WaylandWindow* origin_window_for_testing() { return origin_window_; }
+
private:
class ExtendedDragSource;
FRIEND_TEST_ALL_PREFIXES(WaylandWindowDragControllerTest,
- HandleDraggedWindowDestruction);
+ HandleDraggedWindowDestructionAfterMoveLoop);
// WaylandDataDevice::DragDelegate:
bool IsDragSource() const override;
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
index db03b4b9326..3ea8233f99c 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -20,6 +20,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device.h"
#include "ui/ozone/platform/wayland/host/wayland_screen.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
@@ -189,15 +190,17 @@ TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) {
SendDndMotion({20, 20});
test_step = kDragging;
break;
- case kDropping:
+ case kDropping: {
EXPECT_EQ(ET_MOUSE_RELEASED, event->type());
EXPECT_EQ(State::kDropped, drag_controller()->state());
// Ensure PlatformScreen keeps consistent.
- EXPECT_EQ(gfx::Point(20, 20), screen_->GetCursorScreenPoint());
+ gfx::Point expected_point{20, 20};
+ expected_point += window_->GetBoundsInDIP().origin().OffsetFromOrigin();
EXPECT_EQ(window_->GetWidget(),
screen_->GetLocalProcessWidgetAtPoint({20, 20}, {}));
test_step = kDone;
break;
+ }
case kDone:
EXPECT_EQ(ET_MOUSE_EXITED, event->type());
EXPECT_EQ(window_->GetWidget(),
@@ -280,7 +283,9 @@ TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) {
EXPECT_EQ(ET_TOUCH_RELEASED, event->type());
EXPECT_EQ(State::kDropped, drag_controller()->state());
// Ensure PlatformScreen keeps consistent.
- EXPECT_EQ(gfx::Point(20, 20), screen_->GetCursorScreenPoint());
+ gfx::Point expected_point{20, 20};
+ expected_point += window_->GetBoundsInDIP().origin().OffsetFromOrigin();
+ EXPECT_EQ(expected_point, screen_->GetCursorScreenPoint());
EXPECT_EQ(window_->GetWidget(),
screen_->GetLocalProcessWidgetAtPoint({20, 20}, {}));
test_step = kDone;
@@ -320,6 +325,60 @@ TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) {
}
// Check the following flow works as expected:
+// 1. With two windows open,
+// 2. Touch down and start drag a window,
+// 3. Emulate the compositor sending an unexpected `pointer enter` event
+// to another window, when the drag is ongoing.
+//
+// NOTE: This bug isn't noticed on DUT, but seems to be frequent on ash/chrome
+// linux desktop builds (with ozone/x11 underneath).
+TEST_P(WaylandWindowDragControllerTest,
+ DragAndDropWithExtraneousPointerEnterEvent_TOUCH) {
+ // Init and open |target_window|.
+ PlatformWindowInitProperties properties{gfx::Rect{80, 80}};
+ properties.type = PlatformWindowType::kWindow;
+ EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(_)).Times(1);
+ auto window_2 = WaylandWindow::Create(&delegate_, connection_.get(),
+ std::move(properties));
+ ASSERT_NE(gfx::kNullAcceleratedWidget, window_2->GetWidget());
+ Sync();
+
+ // Ensure there is no window currently focused
+ EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow());
+ EXPECT_EQ(gfx::kNullAcceleratedWidget,
+ screen_->GetLocalProcessWidgetAtPoint({10, 10}, {}));
+
+ ASSERT_TRUE(GetWmMoveLoopHandler(*window_2));
+ ASSERT_TRUE(GetWaylandExtension(*window_2));
+
+ // Start triggering a drag operation.
+ SendTouchDown(window_2.get(), &delegate_, 0 /*point id*/,
+ {0, 0} /*location*/);
+
+ // This operation simulates bogus Wayland compositor that might send out
+ // unexpected pointer enter events.
+ SendPointerEnter(window_.get(), &delegate_);
+ Sync();
+ EXPECT_EQ(window_.get(),
+ window_manager()->GetCurrentPointerOrTouchFocusedWindow());
+ EXPECT_EQ(window_.get(), window_manager()->GetCurrentPointerFocusedWindow());
+ EXPECT_EQ(window_2.get(), window_manager()->GetCurrentTouchFocusedWindow());
+
+ // Set up an "interaction flow", start the drag session, run move loop
+ // and verify the window effectively being dragged.
+ GetWaylandExtension(*window_2)->StartWindowDraggingSessionIfNeeded(
+ /*allow_system_drag=*/false);
+
+ Sync();
+ // Verify that the proper window is being dragged.
+ EXPECT_EQ(window_2.get(), drag_controller()->origin_window_for_testing());
+ Mock::VerifyAndClearExpectations(&delegate_);
+
+ SendTouchUp(0 /*touch id*/);
+ Sync();
+}
+
+// Check the following flow works as expected:
// 1. With only 1 window open;
// 2. Move pointer into it, press left button, move cursor a bit (drag);
// 3. Run move loop,
@@ -364,15 +423,17 @@ TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) {
SendDndMotion({20, 20});
test_step = kDragging;
break;
- case kExitedDropping:
+ case kExitedDropping: {
EXPECT_EQ(ET_MOUSE_RELEASED, event->type());
EXPECT_EQ(State::kDropped, drag_controller()->state());
// Ensure PlatformScreen keeps consistent.
- EXPECT_EQ(gfx::Point(20, 20), screen_->GetCursorScreenPoint());
+ gfx::Point expected_point{20, 20};
+ expected_point += window_->GetBoundsInDIP().origin().OffsetFromOrigin();
+ EXPECT_EQ(expected_point, screen_->GetCursorScreenPoint());
EXPECT_EQ(window_->GetWidget(),
screen_->GetLocalProcessWidgetAtPoint({20, 20}, {}));
test_step = kDone;
- break;
+ } break;
case kDone:
EXPECT_EQ(ET_MOUSE_EXITED, event->type());
break;
@@ -876,7 +937,7 @@ TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) {
SendDndMotion({100, 100});
test_step = kDragging;
break;
- case kDropping:
+ case kDropping: {
EXPECT_EQ(ET_MOUSE_RELEASED, event->type());
EXPECT_EQ(State::kDropped, drag_controller()->state());
@@ -888,9 +949,11 @@ TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) {
screen_->GetLocalProcessWidgetAtPoint({100, 100}, {}));
// Rather, only PlatformScreen's cursor position is updated accordingly.
- EXPECT_EQ(gfx::Point(20, 20), screen_->GetCursorScreenPoint());
+ gfx::Point expected_point{20, 20};
+ expected_point += window_->GetBoundsInDIP().origin().OffsetFromOrigin();
+ EXPECT_EQ(expected_point, screen_->GetCursorScreenPoint());
test_step = kDone;
- break;
+ } break;
case kDone:
EXPECT_EQ(ET_MOUSE_EXITED, event->type());
EXPECT_EQ(window_->GetWidget(),
@@ -1044,16 +1107,20 @@ TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) {
WmMoveLoopHandler* move_loop_handler,
bool in_pixel_coordinates) {
for (auto* output : *outputs) {
- // Resetting cursor to the initial position.
gfx::Point p0{10, 10};
- self->SendDndMotion(p0);
- self->Sync();
+ // Compute the expected point first as drag operation will move the
+ // window.
gfx::Point expected_point =
in_pixel_coordinates
? gfx::ScaleToRoundedPoint(p0, 1.0f / window->window_scale())
: p0;
+ expected_point += window->GetBoundsInDIP().origin().OffsetFromOrigin();
EXPECT_EQ(expected_point, screen->GetCursorScreenPoint());
+ // Resetting cursor to the initial position.
+ self->SendDndMotion(p0);
+ self->Sync();
+
// Send the window to |output|.
wl::MockSurface* surface = server->GetObject<wl::MockSurface>(
window->root_surface()->GetSurfaceId());
@@ -1063,13 +1130,15 @@ TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) {
EXPECT_EQ(output->GetScale(), window->window_scale());
gfx::Point p1{20, 20};
+ expected_point =
+ (in_pixel_coordinates
+ ? gfx::ScaleToRoundedPoint(p1, 1.0f / window->window_scale())
+ : p1);
+ expected_point += window->GetBoundsInDIP().origin().OffsetFromOrigin();
+
self->SendDndMotion(p1);
self->Sync();
- expected_point =
- in_pixel_coordinates
- ? gfx::ScaleToRoundedPoint(p1, 1.0f / window->window_scale())
- : p1;
EXPECT_EQ(expected_point, screen->GetCursorScreenPoint());
wl_surface_send_leave(surface->resource(), output->resource());
}
@@ -1090,7 +1159,8 @@ TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) {
// after quitting the move loop. Regression test for crbug.com/1267791 and
// should be caught in both regular and ASAN builds, where more details about
// the actual memory issue is provided.
-TEST_P(WaylandWindowDragControllerTest, HandleDraggedWindowDestruction) {
+TEST_P(WaylandWindowDragControllerTest,
+ HandleDraggedWindowDestructionAfterMoveLoop) {
// 1. Ensure there is no window currently focused
EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow());
SendPointerEnter(window_.get(), &delegate_);
@@ -1135,6 +1205,95 @@ TEST_P(WaylandWindowDragControllerTest, HandleDraggedWindowDestruction) {
screen_->GetLocalProcessWidgetAtPoint({20, 20}, {}));
}
+// Ensure no memory issues happen when the dragged and/or events grabber windows
+// get destroyed while the move loop is running.
+TEST_P(WaylandWindowDragControllerTest,
+ HandleWindowsDestructionDuringMoveLoop) {
+ // 1. Send some initial pointer events to |window_|.
+ ASSERT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow());
+ SendPointerEnter(window_.get(), &delegate_);
+ SendPointerPress(window_.get(), &delegate_, BTN_LEFT);
+ SendPointerMotion(window_.get(), &delegate_, {10, 10});
+ Mock::VerifyAndClearExpectations(&delegate_);
+
+ // 2. Start the window drag session.
+ auto* wayland_extension = GetWaylandExtension(*window_);
+ wayland_extension->StartWindowDraggingSessionIfNeeded(
+ /*allow_system_drag=*/false);
+ EXPECT_EQ(State::kAttached, drag_controller()->state());
+
+ // 3. Spawns a new toplevel |window_2| out of the origin |window_|. Similarly
+ // to when a tab is detached in a Chrome's tab drag session.
+ PlatformWindowInitProperties properties{gfx::Rect{80, 80}};
+ properties.type = PlatformWindowType::kWindow;
+ MockPlatformWindowDelegate delegate_2;
+ EXPECT_CALL(delegate_2, OnAcceleratedWidgetAvailable(_)).Times(1);
+ auto window_2 = WaylandWindow::Create(&delegate_2, connection_.get(),
+ std::move(properties));
+ ASSERT_NE(gfx::kNullAcceleratedWidget, window_2->GetWidget());
+ Sync();
+
+ // Spin the nested move loop and schedule a sequence of test steps to be
+ // pefomed while it is running.
+ ScheduleTestTask(base::BindLambdaForTesting([&]() {
+ auto* cursor_tracker = connection_->wayland_cursor_position();
+ ASSERT_TRUE(cursor_tracker);
+
+ // Send a motion event and verify it is correctly propagated.
+ EXPECT_CALL(delegate_2, OnBoundsChanged(_)).Times(1);
+ SendDndMotion({11, 10});
+ Sync();
+ EXPECT_EQ(gfx::Point(11, 10), cursor_tracker->GetCursorSurfacePoint());
+ Mock::VerifyAndClearExpectations(&delegate_2);
+
+ // Destroy the window being currently dragged.
+ window_2.reset();
+ Sync();
+
+ // Verifies that motion events are no longer propagated, as the dragged
+ // window was just destroyed.
+ EXPECT_CALL(delegate_2, OnBoundsChanged(_)).Times(0);
+ SendDndMotion({12, 10});
+ Sync();
+ EXPECT_EQ(gfx::Point(12, 10), cursor_tracker->GetCursorSurfacePoint());
+ Mock::VerifyAndClearExpectations(&delegate_2);
+
+ // Destroy the current drag controler's pointer events grabber.
+ window_.reset();
+ Sync();
+
+ // And verifies neither motion events are propagated nor internal "last
+ // cursor position" gets updated.
+ EXPECT_CALL(delegate_, OnBoundsChanged(_)).Times(0);
+ SendDndMotion({13, 10});
+ Sync();
+ EXPECT_EQ(gfx::Point(12, 10), cursor_tracker->GetCursorSurfacePoint());
+ Mock::VerifyAndClearExpectations(&delegate_);
+
+ drag_controller()->StopDragging();
+ }));
+
+ ASSERT_TRUE(GetWmMoveLoopHandler(*window_2));
+ GetWmMoveLoopHandler(*window_2)->RunMoveLoop({});
+ Sync();
+
+ EXPECT_EQ(State::kAttached, drag_controller()->state());
+
+ // 5. Ensure no events are dispatched for drop. Which indirectly means that
+ // drop handling code at window drag controller does not call into the above
+ // destroyed dragged window.
+ EXPECT_CALL(delegate_2, DispatchEvent(_)).Times(0);
+ SendDndDrop();
+ Sync();
+ Mock::VerifyAndClearExpectations(&delegate_);
+
+ // 6. Verifies that related state is correctly reset after drop.
+ EXPECT_EQ(State::kIdle, drag_controller()->state());
+ EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow());
+ EXPECT_EQ(gfx::kNullAcceleratedWidget,
+ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {}));
+}
+
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandWindowDragControllerTest,
Values(wl::ServerConfig{
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc
index 52f17a55f6f..e92e4cb5bf5 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_manager.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
+#include "base/observer_list.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
namespace ui {
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
index e8d7cda5074..d83449063e3 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -4,8 +4,10 @@
#include "ui/ozone/platform/wayland/host/wayland_window.h"
+#include <cstddef>
#include <memory>
#include <utility>
+#include <vector>
#include <cursor-shapes-unstable-v1-client-protocol.h>
#include <linux/input.h>
@@ -19,6 +21,7 @@
#include "base/nix/xdg_util.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
#include "base/test/scoped_command_line.h"
#include "build/chromeos_buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -44,6 +47,7 @@
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_seat.h"
#include "ui/ozone/platform/wayland/host/wayland_subsurface.h"
+#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
#include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h"
#include "ui/ozone/platform/wayland/mojom/wayland_overlay_config.mojom.h"
#include "ui/ozone/platform/wayland/test/mock_pointer.h"
@@ -387,7 +391,7 @@ TEST_P(WaylandWindowTest, SetDecorationInsets) {
Sync();
// Set insets for normal DPI.
- const gfx::Insets kDecorationInsets = {24, 28, 32, 28};
+ const auto kDecorationInsets = gfx::Insets::TLBR(24, 28, 32, 28);
auto bounds_with_insets = kNormalBounds;
bounds_with_insets.Inset(kDecorationInsets);
EXPECT_CALL(delegate_, OnBoundsChanged(_)).Times(0);
@@ -424,7 +428,7 @@ TEST_P(WaylandWindowTest, SetDecorationInsets) {
window_->root_surface()->SetSurfaceBufferScale(kHiDpiScale);
// Set new insets so that rounding does not result in integer.
- const gfx::Insets kDecorationInsets_2x = {48, 55, 63, 55};
+ const auto kDecorationInsets_2x = gfx::Insets::TLBR(48, 55, 63, 55);
EXPECT_CALL(*xdg_surface_,
SetWindowGeometry(bounds_with_insets.x(), bounds_with_insets.y(),
bounds_with_insets.width(),
@@ -451,7 +455,7 @@ TEST_P(WaylandWindowTest, SetDecorationInsets) {
}
}
-TEST_P(WaylandWindowTest, ShuffledUpdateVisualSizeOrder) {
+TEST_P(WaylandWindowTest, DisregardUnpassedWindowConfigure) {
const auto kNormalBounds1 = gfx::Rect{0, 0, 500, 300};
const auto kNormalBounds2 = gfx::Rect{0, 0, 800, 600};
const auto kNormalBounds3 = gfx::Rect{0, 0, 700, 400};
@@ -459,15 +463,17 @@ TEST_P(WaylandWindowTest, ShuffledUpdateVisualSizeOrder) {
window_->set_update_visual_size_immediately(false);
- // Send 3 configures and only ack the second one, the first pending configure
- // is cleared. The second can still be ack'ed.
+ // Send 3 configures, and call UpdateVisualSize out of order. The out-of-order
+ // UpdateVisualSize(kNormalBounds2) should disregarded b/c kNormalBounds2
+ // never reached UI Compositor when UpdateVisualSize(kNormalBounds2) is
+ // called.
EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds1.width(),
- kNormalBounds1.height()))
- .Times(0);
- EXPECT_CALL(*xdg_surface_, AckConfigure(2)).Times(0);
+ kNormalBounds1.height()));
+ EXPECT_CALL(*xdg_surface_, AckConfigure(2));
EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds2.width(),
- kNormalBounds2.height()));
- EXPECT_CALL(*xdg_surface_, AckConfigure(3));
+ kNormalBounds2.height()))
+ .Times(0);
+ EXPECT_CALL(*xdg_surface_, AckConfigure(3)).Times(0);
EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds3.width(),
kNormalBounds3.height()));
EXPECT_CALL(*xdg_surface_, AckConfigure(4));
@@ -528,8 +534,10 @@ TEST_P(WaylandWindowTest, UpdateVisualSizeClearsPreviousUnackedConfigures) {
window_->set_update_visual_size_immediately(false);
- // Send 3 configures and only ack the second one, the first pending configure
- // is cleared. The second can still be ack'ed.
+ // Send 3 configures. Calling UpdateVisualSize(kNormalBounds3) will cause the
+ // kNormalBounds3 to be passed onto UI compositor. Hence, kNormalBounds1/2/3
+ // configs will be acknowledgeable. The next UpdateVisualSize(kNormalBounds3)
+ // wiil ack kNormalBounds3 and skip kNormalBounds1/2.
EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds1.width(),
kNormalBounds1.height()))
.Times(0);
@@ -539,8 +547,9 @@ TEST_P(WaylandWindowTest, UpdateVisualSizeClearsPreviousUnackedConfigures) {
Sync();
EXPECT_CALL(*xdg_surface_, SetWindowGeometry(0, 0, kNormalBounds2.width(),
- kNormalBounds2.height()));
- EXPECT_CALL(*xdg_surface_, AckConfigure(3));
+ kNormalBounds2.height()))
+ .Times(0);
+ EXPECT_CALL(*xdg_surface_, AckConfigure(3)).Times(0);
state = InitializeWlArrayWithActivatedState();
SendConfigureEvent(xdg_surface_, kNormalBounds2.width(),
kNormalBounds2.height(), ++serial, state.get());
@@ -554,8 +563,7 @@ TEST_P(WaylandWindowTest, UpdateVisualSizeClearsPreviousUnackedConfigures) {
kNormalBounds3.height(), ++serial, state.get());
Sync();
- window_->UpdateVisualSize(kNormalBounds2.size(), 1.0f);
- window_->UpdateVisualSize(kNormalBounds1.size(), 1.0f);
+ window_->UpdateVisualSize(kNormalBounds3.size(), 1.0f);
window_->UpdateVisualSize(kNormalBounds3.size(), 1.0f);
}
@@ -807,7 +815,7 @@ TEST_P(WaylandWindowTest, StartMaximized) {
TEST_P(WaylandWindowTest, CompositorSideStateChanges) {
// Real insets used by default on HiDPI.
- const auto kInsets = gfx::Insets{38, 44, 55, 44};
+ const auto kInsets = gfx::Insets::TLBR(38, 44, 55, 44);
const auto kNormalBounds = window_->GetBounds();
EXPECT_EQ(window_->GetPlatformWindowState(), PlatformWindowState::kNormal);
@@ -2523,6 +2531,87 @@ TEST_P(WaylandWindowTest, WaylandPopupNestedParent) {
}
}
+// Tests that size constraints returned by the `ui::PlatformWindowDelegate` are
+// obeyed by the window when its bounds are set internally via its SetBounds()
+// implementation.
+TEST_P(WaylandWindowTest, SizeConstraintsInternal) {
+ const gfx::Rect kMinBounds{0, 0, 100, 100};
+ const gfx::Rect kMaxBounds{0, 0, 300, 300};
+
+ window_->SetBounds({0, 0, 200, 200});
+ Sync();
+
+ auto even_smaller_bounds = kMinBounds;
+ even_smaller_bounds.Inset(10);
+ even_smaller_bounds.set_origin({0, 0});
+
+ EXPECT_CALL(delegate_, GetMinimumSizeForWindow())
+ .WillOnce(Return(kMinBounds.size()));
+ EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMinBounds)));
+
+ window_->SetBounds(even_smaller_bounds);
+ Sync();
+
+ VerifyAndClearExpectations();
+
+ auto even_greater_bounds = kMaxBounds;
+ even_greater_bounds.Outset(10);
+ even_greater_bounds.set_origin({0, 0});
+
+ EXPECT_CALL(delegate_, GetMaximumSizeForWindow())
+ .WillOnce(Return(kMaxBounds.size()));
+ EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMaxBounds)));
+
+ window_->SetBounds(even_greater_bounds);
+ Sync();
+}
+
+// Tests that size constraints returned by the `ui::PlatformWindowDelegate` are
+// obeyed by the window when its bounds are set externally via the configure
+// event sent by the compositor.
+TEST_P(WaylandWindowTest, SizeConstraintsExternal) {
+ const gfx::Rect kMinBounds{0, 0, 100, 100};
+ const gfx::Rect kMaxBounds{0, 0, 300, 300};
+
+ EXPECT_CALL(delegate_, GetMinimumSizeForWindow())
+ .WillRepeatedly(Return(kMinBounds.size()));
+ EXPECT_CALL(delegate_, GetMaximumSizeForWindow())
+ .WillRepeatedly(Return(kMaxBounds.size()));
+
+ window_->SetBounds({0, 0, 200, 200});
+ Sync();
+
+ uint32_t serial = 0;
+ auto state = InitializeWlArrayWithActivatedState();
+
+ auto even_smaller_bounds = kMinBounds;
+ even_smaller_bounds.Inset(10);
+ even_smaller_bounds.set_origin({0, 0});
+
+ EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMinBounds)));
+
+ SendConfigureEvent(xdg_surface_, even_smaller_bounds.width(),
+ even_smaller_bounds.height(), ++serial, state.get());
+ Sync();
+
+ VerifyAndClearExpectations();
+
+ EXPECT_CALL(delegate_, GetMinimumSizeForWindow())
+ .WillRepeatedly(Return(kMinBounds.size()));
+ EXPECT_CALL(delegate_, GetMaximumSizeForWindow())
+ .WillRepeatedly(Return(kMaxBounds.size()));
+
+ auto even_greater_bounds = kMaxBounds;
+ even_greater_bounds.Outset(10);
+ even_greater_bounds.set_origin({0, 0});
+
+ EXPECT_CALL(delegate_, OnBoundsChanged(Eq(kMaxBounds)));
+
+ SendConfigureEvent(xdg_surface_, even_greater_bounds.width(),
+ even_greater_bounds.height(), ++serial, state.get());
+ Sync();
+}
+
TEST_P(WaylandWindowTest, OnSizeConstraintsChanged) {
const bool kBooleans[] = {false, true};
for (bool has_min_size : kBooleans) {
@@ -2661,7 +2750,8 @@ TEST_P(WaylandWindowTest, ReattachesBackgroundOnShow) {
background->surface_scale_factor = 1;
background->opacity = 1.f;
overlays.push_back(std::move(background));
- buffer_manager_gpu_->CommitOverlays(window->GetWidget(), std::move(overlays));
+ buffer_manager_gpu_->CommitOverlays(window->GetWidget(), 1u,
+ std::move(overlays));
mock_surface->SendFrameCallback();
Sync();
@@ -2693,7 +2783,8 @@ TEST_P(WaylandWindowTest, ReattachesBackgroundOnShow) {
primary->surface_scale_factor = 1;
primary->opacity = 1.f;
overlays.push_back(std::move(primary));
- buffer_manager_gpu_->CommitOverlays(window->GetWidget(), std::move(overlays));
+ buffer_manager_gpu_->CommitOverlays(window->GetWidget(), 2u,
+ std::move(overlays));
Sync();
@@ -2878,10 +2969,11 @@ TEST_P(WaylandWindowTest, CreatesPopupOnTouchDownSerial) {
auto* test_popup = GetTestXdgPopupByWindow(popup.get());
ASSERT_TRUE(test_popup);
- // Touch events are the exception. We can't use the serial that was sent
- // before the "up" event. Otherwise, some compositors may dismiss popups.
- // Thus, no serial must be used.
- EXPECT_EQ(test_popup->grab_serial(), 0U);
+ // Unless the use-wayland-explicit-grab switch is set, touch events are the
+ // exception, i.e: the serial sent before the "up" event (latest) cannot be
+ // used, otherwise, some compositors may dismiss popups.
+ if (!use_explicit_grab)
+ EXPECT_EQ(test_popup->grab_serial(), 0U);
popup->Hide();
@@ -3085,6 +3177,19 @@ class WaylandSubsurfaceTest : public WaylandWindowTest {
EXPECT_EQ(test_subsurface->position(), expected_position);
EXPECT_TRUE(test_subsurface->sync());
}
+
+ std::vector<WaylandSubsurface*> RequestWaylandSubsurface(uint32_t n) {
+ VerifyAndClearExpectations();
+ std::vector<WaylandSubsurface*> res =
+ std::vector<WaylandSubsurface*>{window_->primary_subsurface()};
+ for (uint32_t i = 0; i < n - 1; ++i) {
+ window_->RequestSubsurface();
+ }
+ for (auto& subsurface : window_->wayland_subsurfaces()) {
+ res.push_back(subsurface.get());
+ }
+ return res;
+ }
};
} // namespace
@@ -3127,6 +3232,144 @@ TEST_P(WaylandSubsurfaceTest, OneWaylandSubsurfaceNonInteger) {
}
}
+TEST_P(WaylandSubsurfaceTest, NoDuplicateSubsurfaceRequests) {
+ auto subsurfaces = RequestWaylandSubsurface(3);
+ for (auto* subsurface : subsurfaces) {
+ subsurface->ConfigureAndShowSurface(gfx::RectF(1.f, 2.f, 10.f, 20.f),
+ gfx::RectF(0.f, 0.f, 800.f, 600.f), 1.f,
+ nullptr, nullptr);
+ }
+ connection_->ScheduleFlush();
+
+ Sync();
+
+ // From top to bottom: subsurfaces[2], subsurfaces[1], subsurfaces[0].
+ wl::TestSubSurface* test_subs[3] = {
+ server_
+ .GetObject<wl::MockSurface>(
+ subsurfaces[0]->wayland_surface()->GetSurfaceId())
+ ->sub_surface(),
+ server_
+ .GetObject<wl::MockSurface>(
+ subsurfaces[1]->wayland_surface()->GetSurfaceId())
+ ->sub_surface(),
+ server_
+ .GetObject<wl::MockSurface>(
+ subsurfaces[2]->wayland_surface()->GetSurfaceId())
+ ->sub_surface()};
+
+ EXPECT_CALL(*test_subs[0], PlaceAbove(_)).Times(1);
+ EXPECT_CALL(*test_subs[0], PlaceBelow(_)).Times(0);
+ EXPECT_CALL(*test_subs[0], SetPosition(_, _)).Times(1);
+ EXPECT_CALL(*test_subs[1], PlaceAbove(_)).Times(0);
+ EXPECT_CALL(*test_subs[1], PlaceBelow(_)).Times(0);
+ EXPECT_CALL(*test_subs[1], SetPosition(_, _)).Times(0);
+ EXPECT_CALL(*test_subs[2], PlaceAbove(_)).Times(0);
+ EXPECT_CALL(*test_subs[2], PlaceBelow(_)).Times(0);
+ EXPECT_CALL(*test_subs[2], SetPosition(_, _)).Times(0);
+
+ // Stack subsurfaces[0] to be from bottom to top, and change its position.
+ subsurfaces[0]->ConfigureAndShowSurface(gfx::RectF(0.f, 0.f, 10.f, 20.f),
+ gfx::RectF(0.f, 0.f, 800.f, 600.f),
+ 1.f, subsurfaces[2], nullptr);
+ subsurfaces[1]->ConfigureAndShowSurface(gfx::RectF(1.f, 2.f, 10.f, 20.f),
+ gfx::RectF(0.f, 0.f, 800.f, 600.f),
+ 1.f, nullptr, subsurfaces[2]);
+ subsurfaces[2]->ConfigureAndShowSurface(gfx::RectF(1.f, 2.f, 10.f, 20.f),
+ gfx::RectF(0.f, 0.f, 800.f, 600.f),
+ 1.f, nullptr, subsurfaces[0]);
+ connection_->ScheduleFlush();
+
+ Sync();
+ VerifyAndClearExpectations();
+}
+
+TEST_P(WaylandWindowTest, NoDuplicateViewporterRequests) {
+ EXPECT_TRUE(connection_->buffer_manager_host());
+
+ auto interface_ptr = connection_->buffer_manager_host()->BindInterface();
+ buffer_manager_gpu_->Initialize(
+ std::move(interface_ptr), {}, false, true, false,
+ /*supports_non_backed_solid_color_buffers*/ false,
+ /*supports_subpixel_accurate_position*/ false);
+
+ // Setup wl_buffers.
+ constexpr uint32_t buffer_id = 1;
+ gfx::Size buffer_size(1024, 768);
+ auto length = 1024 * 768 * 4;
+ buffer_manager_gpu_->CreateShmBasedBuffer(MakeFD(), length, buffer_size,
+ buffer_id);
+ Sync();
+
+ auto* surface = window_->root_surface();
+ auto* test_viewport =
+ server_.GetObject<wl::MockSurface>(surface->GetSurfaceId())->viewport();
+
+ // Set viewport src and dst.
+ EXPECT_CALL(*test_viewport, SetSource(512, 384, 512, 384)).Times(1);
+ EXPECT_CALL(*test_viewport, SetDestination(800, 600)).Times(1);
+
+ surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle(
+ surface, buffer_id));
+
+ surface->SetViewportSource({0.5, 0.5, 0.5, 0.5});
+ surface->SetViewportDestination({800, 600});
+ surface->ApplyPendingState();
+ surface->Commit();
+ connection_->ScheduleFlush();
+
+ Sync();
+ VerifyAndClearExpectations();
+
+ // Duplicate viewport requests are not sent.
+ EXPECT_CALL(*test_viewport, SetSource(_, _, _, _)).Times(0);
+ EXPECT_CALL(*test_viewport, SetDestination(_, _)).Times(0);
+
+ surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle(
+ surface, buffer_id));
+
+ surface->SetViewportSource({0.5, 0.5, 0.5, 0.5});
+ surface->SetViewportDestination({800, 600});
+ surface->ApplyPendingState();
+ surface->Commit();
+ connection_->ScheduleFlush();
+
+ Sync();
+ VerifyAndClearExpectations();
+
+ // Unset viewport src and dst.
+ EXPECT_CALL(*test_viewport, SetSource(-1, -1, -1, -1)).Times(1);
+ EXPECT_CALL(*test_viewport, SetDestination(-1, -1)).Times(1);
+
+ surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle(
+ surface, buffer_id));
+
+ surface->SetViewportSource({0., 0., 1., 1.});
+ surface->SetViewportDestination({1024, 768});
+ surface->ApplyPendingState();
+ surface->Commit();
+ connection_->ScheduleFlush();
+
+ Sync();
+ VerifyAndClearExpectations();
+
+ // Duplicate viewport requests are not sent.
+ EXPECT_CALL(*test_viewport, SetSource(_, _, _, _)).Times(0);
+ EXPECT_CALL(*test_viewport, SetDestination(_, _)).Times(0);
+
+ surface->AttachBuffer(connection_->buffer_manager_host()->EnsureBufferHandle(
+ surface, buffer_id));
+
+ surface->SetViewportSource({0., 0., 1., 1.});
+ surface->SetViewportDestination({1024, 768});
+ surface->ApplyPendingState();
+ surface->Commit();
+ connection_->ScheduleFlush();
+
+ Sync();
+ VerifyAndClearExpectations();
+}
+
// Tests that WaylandPopups can be repositioned.
TEST_P(WaylandWindowTest, RepositionPopups) {
VerifyAndClearExpectations();
@@ -3227,6 +3470,112 @@ TEST_P(WaylandWindowTest, StartWithMinimized) {
Sync();
}
+class BlockableWaylandToplevelWindow : public WaylandToplevelWindow {
+ public:
+ BlockableWaylandToplevelWindow(MockPlatformWindowDelegate* delegate,
+ WaylandConnection* connection)
+ : WaylandToplevelWindow(delegate, connection) {}
+
+ static std::unique_ptr<BlockableWaylandToplevelWindow> Create(
+ const gfx::Rect bounds,
+ WaylandConnection* connection,
+ MockPlatformWindowDelegate* delegate) {
+ auto window =
+ std::make_unique<BlockableWaylandToplevelWindow>(delegate, connection);
+ window->set_update_visual_size_immediately(/*update_immediately=*/true);
+ window->set_apply_pending_state_on_update_visual_size(
+ /*apply_immediately=*/true);
+
+ PlatformWindowInitProperties properties;
+ properties.bounds = bounds;
+ properties.type = PlatformWindowType::kWindow;
+ properties.parent_widget = gfx::kNullAcceleratedWidget;
+ window->Initialize(std::move(properties));
+ window->Show(false);
+ return window;
+ }
+
+ // WaylandToplevelWindow overrides:
+ uint32_t DispatchEvent(const PlatformEvent& platform_event) override {
+ ui::Event* event(platform_event);
+ if (event->type() == ET_TOUCH_RELEASED && !blocked_) {
+ base::RunLoop run_loop{base::RunLoop::Type::kNestableTasksAllowed};
+ blocked_ = true;
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(async_task_), run_loop.QuitClosure()));
+ run_loop.Run();
+ blocked_ = false;
+ }
+
+ return WaylandToplevelWindow::DispatchEvent(platform_event);
+ }
+
+ void SetAsyncTask(
+ base::RepeatingCallback<void(base::OnceClosure)> async_task) {
+ async_task_ = std::move(async_task);
+ }
+
+ private:
+ bool blocked_ = false;
+ base::RepeatingCallback<void(base::OnceClosure)> async_task_;
+};
+
+// This test ensures that Ozone/Wayland does not crash while handling a
+// sequence of two or more touch down/up actions, where the first one blocks
+// unfinished before the second pair comes in.
+//
+// This mimics the behavior of a modal dialog that comes up as a result of
+// the first touch down/up action, and blocks the original flow, before it gets
+// handled completely.
+// The test is flaky. https://crbug.com/1305272.
+TEST_P(WaylandWindowTest, DISABLED_BlockingTouchDownUp_NoCrash) {
+ window_.reset();
+
+ MockPlatformWindowDelegate delegate;
+ auto window = BlockableWaylandToplevelWindow::Create(
+ gfx::Rect(0, 0, 800, 600), connection_.get(), &delegate);
+
+ wl_seat_send_capabilities(
+ server_.seat()->resource(),
+ WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_TOUCH);
+ Sync();
+ ASSERT_TRUE(connection_->seat()->pointer());
+ ASSERT_TRUE(connection_->seat()->touch());
+ window->set_touch_focus(true);
+
+ uint32_t serial = 0;
+
+ // Test that CanDispatchEvent is set correctly.
+ wl::MockSurface* toplevel_surface = server_.GetObject<wl::MockSurface>(
+ window->root_surface()->GetSurfaceId());
+ Sync();
+ VerifyCanDispatchTouchEvents({window.get()}, {});
+
+ // Steps to be executed after the handling of the first touch down/up
+ // pair blocks.
+ auto async_task = base::BindLambdaForTesting([&](base::OnceClosure closure) {
+ wl_touch_send_down(server_.seat()->touch()->resource(), ++serial, 0,
+ toplevel_surface->resource(), 0 /* id */,
+ wl_fixed_from_int(100), wl_fixed_from_int(100));
+ wl_touch_send_up(server_.seat()->touch()->resource(), ++serial, 2000,
+ 0 /* id */);
+ Sync();
+
+ std::move(closure).Run();
+ });
+ window->SetAsyncTask(std::move(async_task));
+
+ // Start executing the first touch down/up pair.
+ wl_touch_send_down(server_.seat()->touch()->resource(), ++serial, 0,
+ toplevel_surface->resource(), 0 /* id */,
+ wl_fixed_from_int(50), wl_fixed_from_int(50));
+ wl_touch_send_up(server_.seat()->touch()->resource(), ++serial, 1000,
+ 0 /* id */);
+ Sync();
+}
+
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
WaylandWindowTest,
Values(wl::ServerConfig{
diff --git a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
index f1b492fc5e1..a0d9ec7ba07 100644
--- a/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
+++ b/chromium/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
@@ -8,6 +8,7 @@
#include <wayland-util.h>
#include "base/logging.h"
+#include "build/chromeos_buildflags.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc
index 3116311fb6f..32c9079069f 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc
@@ -70,8 +70,15 @@ void XDGSurfaceWrapperImpl::Configure(void* data,
auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data);
DCHECK(surface);
- surface->wayland_window_->HandleSurfaceConfigure(serial);
- surface->wayland_window_->OnSurfaceConfigureEvent();
+ // Calls to HandleSurfaceConfigure() might end up hiding the enclosing
+ // toplevel window, and deleting this object.
+ auto weak_window = surface->wayland_window_->AsWeakPtr();
+ weak_window->HandleSurfaceConfigure(serial);
+
+ if (!weak_window)
+ return;
+
+ weak_window->OnSurfaceConfigureEvent();
}
xdg_surface* XDGSurfaceWrapperImpl::xdg_surface() const {
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
index 2571aac25d5..a44a5d82d0e 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
@@ -35,14 +35,14 @@ class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper {
bool IsConfigured() override;
void SetWindowGeometry(const gfx::Rect& bounds) override;
+ struct xdg_surface* xdg_surface() const;
+
+ private:
// xdg_surface_listener
static void Configure(void* data,
struct xdg_surface* xdg_surface,
uint32_t serial);
- struct xdg_surface* xdg_surface() const;
-
- private:
// Non-owing WaylandWindow that uses this surface wrapper.
WaylandWindow* const wayland_window_;
WaylandConnection* const connection_;
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
index c2f1a62cf81..caec9df233a 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
@@ -13,12 +13,16 @@
#include "base/strings/utf_string_conversions.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/hit_test.h"
+#include "ui/base/ui_base_features.h"
#include "ui/ozone/common/features.h"
#include "ui/ozone/platform/wayland/common/wayland_util.h"
#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
+#include "ui/ozone/platform/wayland/host/wayland_output.h"
+#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_seat.h"
#include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
+#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h"
#include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h"
@@ -99,11 +103,25 @@ bool XDGToplevelWrapperImpl::Initialize() {
ZAURA_SHELL_GET_AURA_TOPLEVEL_FOR_XDG_TOPLEVEL_SINCE_VERSION) {
aura_toplevel_.reset(zaura_shell_get_aura_toplevel_for_xdg_toplevel(
connection_->zaura_shell()->wl_object(), xdg_toplevel_.get()));
- if (IsWaylandSurfaceSubmissionInPixelCoordinatesEnabled() &&
+ if (ui::IsWaylandSurfaceSubmissionInPixelCoordinatesEnabled() &&
version >=
- ZAURA_TOPLEVEL_SURFACE_SUBMISSION_IN_PIXEL_COORDINATES_SINCE_VERSION)
+ ZAURA_TOPLEVEL_SURFACE_SUBMISSION_IN_PIXEL_COORDINATES_SINCE_VERSION) {
zaura_toplevel_surface_submission_in_pixel_coordinates(
aura_toplevel_.get());
+ }
+
+ if (features::IsWaylandScreenCoordinatesEnabled()) {
+ DCHECK(ProtocolSupportsScreenCoordinates());
+ zaura_toplevel_set_supports_screen_coordinates(aura_toplevel_.get());
+
+ static constexpr zaura_toplevel_listener aura_toplevel_listener = {
+ &ConfigureAuraTopLevel,
+ &OnOriginChange,
+ };
+
+ zaura_toplevel_add_listener(aura_toplevel_.get(),
+ &aura_toplevel_listener, this);
+ }
}
}
@@ -230,6 +248,42 @@ void XDGToplevelWrapperImpl::ConfigureTopLevel(
}
// static
+void XDGToplevelWrapperImpl::ConfigureAuraTopLevel(
+ void* data,
+ struct zaura_toplevel* zaura_toplevel,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height,
+ struct wl_array* states) {
+ auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
+ DCHECK(surface);
+
+ bool is_maximized =
+ CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_MAXIMIZED);
+ bool is_fullscreen =
+ CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_FULLSCREEN);
+ bool is_activated =
+ CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_ACTIVATED);
+
+ surface->wayland_window_->HandleAuraToplevelConfigure(
+ x, y, width, height, is_maximized, is_fullscreen, is_activated);
+}
+
+// static
+void XDGToplevelWrapperImpl::OnOriginChange(
+ void* data,
+ struct zaura_toplevel* zaura_toplevel,
+ int32_t x,
+ int32_t y) {
+ auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
+ DCHECK(surface);
+ auto* wayland_toplevel_window =
+ static_cast<WaylandToplevelWindow*>(surface->wayland_window_);
+ wayland_toplevel_window->SetOrigin(gfx::Point(x, y));
+}
+
+// static
void XDGToplevelWrapperImpl::CloseTopLevel(void* data,
struct xdg_toplevel* xdg_toplevel) {
auto* surface = static_cast<XDGToplevelWrapperImpl*>(data);
@@ -315,4 +369,25 @@ void XDGToplevelWrapperImpl::Unlock() {
}
}
+void XDGToplevelWrapperImpl::RequestWindowBounds(const gfx::Rect& bounds) {
+ DCHECK(ProtocolSupportsScreenCoordinates());
+ uint32_t id = wayland_window_->GetPreferredEnteredOutputId();
+ auto* output = connection_->wayland_output_manager()->GetOutput(id);
+ if (!output) {
+ // output can be null when the surfae is just created. output should
+ // probably be inferred in that case.
+ LOG(WARNING) << "Output Not found for id=" << id;
+ output = connection_->wayland_output_manager()->GetPrimaryOutput();
+ }
+ zaura_toplevel_set_window_bounds(aura_toplevel_.get(), bounds.x(), bounds.y(),
+ bounds.width(), bounds.height(),
+ output->get_output());
+}
+
+bool XDGToplevelWrapperImpl::ProtocolSupportsScreenCoordinates() {
+ return aura_toplevel_ &&
+ zaura_toplevel_get_version(aura_toplevel_.get()) >=
+ ZAURA_TOPLEVEL_SET_SUPPORTS_SCREEN_COORDINATES_SINCE_VERSION;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
index c8a58680faf..77706b7b372 100644
--- a/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -44,10 +44,13 @@ class XDGToplevelWrapperImpl : public ShellToplevelWrapper {
void SetDecoration(DecorationMode decoration) override;
void Lock(WaylandOrientationLockType lock_type) override;
void Unlock() override;
+ void RequestWindowBounds(const gfx::Rect& bounds) override;
XDGSurfaceWrapperImpl* xdg_surface_wrapper() const;
private:
+ bool ProtocolSupportsScreenCoordinates();
+
// xdg_toplevel_listener
static void ConfigureTopLevel(void* data,
struct xdg_toplevel* xdg_toplevel,
@@ -62,6 +65,20 @@ class XDGToplevelWrapperImpl : public ShellToplevelWrapper {
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode);
+ // aura_toplevel_listener
+ static void ConfigureAuraTopLevel(void* data,
+ struct zaura_toplevel* zaura_toplevel,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height,
+ struct wl_array* states);
+
+ static void OnOriginChange(void* data,
+ struct zaura_toplevel* zaura_toplevel,
+ int32_t x,
+ int32_t y);
+
// Send request to wayland compositor to enable a requested decoration mode.
void SetTopLevelDecorationMode(DecorationMode requested_mode);
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
index b052dab80b4..28f3e8c3c35 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.cc
@@ -6,7 +6,6 @@
#include <primary-selection-unstable-v1-client-protocol.h>
-#include "base/logging.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
#include "ui/ozone/platform/wayland/host/zwp_primary_selection_offer.h"
@@ -27,15 +26,11 @@ ZwpPrimarySelectionDevice::ZwpPrimarySelectionDevice(
ZwpPrimarySelectionDevice::~ZwpPrimarySelectionDevice() = default;
void ZwpPrimarySelectionDevice::SetSelectionSource(
- ZwpPrimarySelectionSource* source) {
- auto serial = GetSerialForSelection();
- if (!serial.has_value()) {
- LOG(ERROR) << "Failed to set selection. No serial found.";
- return;
- }
+ ZwpPrimarySelectionSource* source,
+ uint32_t serial) {
auto* data_source = source ? source->data_source() : nullptr;
zwp_primary_selection_device_v1_set_selection(data_device_.get(), data_source,
- serial->value);
+ serial);
connection()->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
index 764d8bae45f..a1196a0da96 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_primary_selection_device.h
@@ -5,6 +5,8 @@
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZWP_PRIMARY_SELECTION_DEVICE_H_
+#include <cstdint>
+
#include "ui/ozone/platform/wayland/common/wayland_object.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device_base.h"
#include "ui/ozone/platform/wayland/host/wayland_data_source.h"
@@ -31,7 +33,7 @@ class ZwpPrimarySelectionDevice : public WaylandDataDeviceBase {
return data_device_.get();
}
- void SetSelectionSource(ZwpPrimarySelectionSource* source);
+ void SetSelectionSource(ZwpPrimarySelectionSource* source, uint32_t serial);
private:
// primary_selection_device_listener callbacks
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
index 4bd183397c4..18ad5e60748 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper.h
@@ -73,6 +73,13 @@ class ZWPTextInputWrapperClient {
// (visible=1/invisible=0), and ignore other bits for future compatibility.
// This behavior must be consistent with components/exo.
virtual void OnInputPanelState(uint32_t state) = 0;
+
+ // Called when the modifiers map is updated.
+ // Each element holds the XKB name represents a modifier, such as "Shift".
+ // The position of the element represents the bit position of modifiers
+ // on OnKeysym. E.g., if LSB of modifiers is set, modifiers_map[0] is
+ // set, if (1 << 1) of modifiers is set, modifiers_map[1] is set, and so on.
+ virtual void OnModifiersMap(std::vector<std::string> modifiers_map) = 0;
};
// A wrapper around different versions of wayland text input protocols.
diff --git a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
index 09245d9b217..834e43dd907 100644
--- a/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
+++ b/chromium/ui/ozone/platform/wayland/host/zwp_text_input_wrapper_v1.cc
@@ -7,12 +7,29 @@
#include <string>
#include <utility>
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
#include "ui/gfx/range/range.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_seat.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
namespace ui {
+namespace {
+
+// Parses the content of |array|, and creates a map of modifiers.
+// The content of array is just a concat of modifier names in c-style string
+// (i.e., '\0' terminated string), thus this splits the whole byte array by
+// '\0' character.
+std::vector<std::string> ParseModifiersMap(wl_array* array) {
+ return base::SplitString(
+ base::StringPiece(static_cast<char*>(array->data),
+ array->size - 1), // exclude trailing '\0'.
+ base::StringPiece("\0", 1), // '\0' as a delimiter.
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+}
+
+} // namespace
ZWPTextInputWrapperV1::ZWPTextInputWrapperV1(
WaylandConnection* connection,
@@ -126,7 +143,8 @@ void ZWPTextInputWrapperV1::OnLeave(void* data,
void ZWPTextInputWrapperV1::OnModifiersMap(void* data,
struct zwp_text_input_v1* text_input,
struct wl_array* map) {
- NOTIMPLEMENTED_LOG_ONCE();
+ auto* self = static_cast<ZWPTextInputWrapperV1*>(data);
+ self->client_->OnModifiersMap(ParseModifiersMap(map));
}
// static
diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc
index 18b35a2d95b..20138f2e255 100644
--- a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc
+++ b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc
@@ -193,4 +193,8 @@ void ZXDGToplevelV6WrapperImpl::Lock(WaylandOrientationLockType lock_type) {}
void ZXDGToplevelV6WrapperImpl::Unlock() {}
+void ZXDGToplevelV6WrapperImpl::RequestWindowBounds(const gfx::Rect& bounds) {
+ NOTREACHED();
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h
index d55a373b881..caf4cc90a02 100644
--- a/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h
+++ b/chromium/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h
@@ -45,6 +45,7 @@ class ZXDGToplevelV6WrapperImpl : public ShellToplevelWrapper {
void SetDecoration(DecorationMode decoration) override;
void Lock(WaylandOrientationLockType lock_type) override;
void Unlock() override;
+ void RequestWindowBounds(const gfx::Rect& geometry) override;
ZXDGSurfaceV6WrapperImpl* zxdg_surface_v6_wrapper() const;
diff --git a/chromium/ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom b/chromium/ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom
index 36461071a82..73f211f1c28 100644
--- a/chromium/ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom
+++ b/chromium/ui/ozone/platform/wayland/mojom/wayland_buffer_manager.mojom
@@ -73,18 +73,16 @@ interface WaylandBufferManagerHost {
// These two methods are independent from the type of rendering.
//
- // Destroys a wl_buffer created by WaylandConnection based on the |buffer_id|
- // for the WaylandWindow, which has the following |widget|. The |buffer_id|
- // is the unique id of the buffer objects being destroyed on the browser
- // process side. If the buffer with |buffer_id| has never been assigned to an
- // AcceleratedWidget, it can be destroyed by passing a null widget
- // with a correct buffer id. Providing wrong pair of the |widget| and the
- // |buffer_id| will result in the termination of the GPU process.
- DestroyBuffer(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id);
+ // Destroys a wl_buffer created by WaylandConnection based on the |buffer_id|.
+ // The |buffer_id| is the unique id of the buffer objects being destroyed on
+ // the browser process side. Providing wrong |buffer_id| will result in the
+ // termination of the GPU process.
+ DestroyBuffer(uint32 buffer_id);
// Send overlay configurations for a frame to a WaylandWindow with the
- // following |widget|.
+ // following |widget| and |frame_id|.
CommitOverlays(gfx.mojom.AcceleratedWidget widget,
+ uint32 frame_id,
array<WaylandOverlayConfig> overlays);
};
@@ -123,12 +121,12 @@ interface WaylandBufferManagerGpu {
// Signals about swap completion.
OnSubmission(gfx.mojom.AcceleratedWidget widget,
- uint32 buffer_id,
+ uint32 frame_id,
gfx.mojom.SwapResult swap_result,
gfx.mojom.GpuFenceHandle? release_fence_handle);
// Signals about presentation.
OnPresentation(gfx.mojom.AcceleratedWidget widget,
- uint32 buffer_id,
+ uint32 frame_id,
gfx.mojom.PresentationFeedback feedback);
};
diff --git a/chromium/ui/ozone/platform/wayland/test/test_augmented_subsurface.cc b/chromium/ui/ozone/platform/wayland/test/test_augmented_subsurface.cc
index 23b8916308b..8df4c6adfa7 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_augmented_subsurface.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_augmented_subsurface.cc
@@ -25,7 +25,8 @@ void SetPosition(struct wl_client* client,
auto* test_subsurface =
GetUserDataAs<TestSubSurface>(test_augmented_subsurface->sub_surface());
DCHECK(test_subsurface);
- test_subsurface->SetPosition(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ test_subsurface->SetPositionImpl(wl_fixed_to_double(x),
+ wl_fixed_to_double(y));
}
} // namespace
diff --git a/chromium/ui/ozone/platform/wayland/test/test_augmented_surface.cc b/chromium/ui/ozone/platform/wayland/test/test_augmented_surface.cc
index 5e570026c8a..0220f5ba150 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_augmented_surface.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_augmented_surface.cc
@@ -33,8 +33,8 @@ void SetDestinationSize(struct wl_client* client,
auto* viewport = mock_surface->viewport();
DCHECK(viewport);
- viewport->SetDestination(wl_fixed_to_double(width),
- wl_fixed_to_double(height));
+ viewport->SetDestinationImpl(wl_fixed_to_double(width),
+ wl_fixed_to_double(height));
}
void SetRoundedClipBounds(struct wl_client* client,
diff --git a/chromium/ui/ozone/platform/wayland/test/test_compositor.cc b/chromium/ui/ozone/platform/wayland/test/test_compositor.cc
index 80fab9ab4bb..e02e57f37d2 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_compositor.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_compositor.cc
@@ -12,8 +12,6 @@
namespace wl {
-constexpr uint32_t TestCompositor::kVersion;
-
namespace {
void CreateSurface(wl_client* client,
@@ -41,8 +39,11 @@ const struct wl_compositor_interface kTestCompositorImpl = {
CreateRegion, // create_region
};
-TestCompositor::TestCompositor()
- : GlobalObject(&wl_compositor_interface, &kTestCompositorImpl, kVersion) {}
+TestCompositor::TestCompositor(uint32_t intended_version)
+ : GlobalObject(&wl_compositor_interface,
+ &kTestCompositorImpl,
+ intended_version),
+ version_(intended_version) {}
TestCompositor::~TestCompositor() = default;
diff --git a/chromium/ui/ozone/platform/wayland/test/test_compositor.h b/chromium/ui/ozone/platform/wayland/test/test_compositor.h
index ca7c32200d1..1b268d20f62 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_compositor.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_compositor.h
@@ -16,9 +16,7 @@ class MockSurface;
// Manage wl_compositor object.
class TestCompositor : public GlobalObject {
public:
- static constexpr uint32_t kVersion = 4;
-
- TestCompositor();
+ explicit TestCompositor(uint32_t intended_version);
TestCompositor(const TestCompositor&) = delete;
TestCompositor& operator=(const TestCompositor&) = delete;
@@ -26,8 +24,10 @@ class TestCompositor : public GlobalObject {
~TestCompositor() override;
void AddSurface(MockSurface* surface);
+ uint32_t GetVersion() { return version_; }
private:
+ uint32_t version_;
std::vector<MockSurface*> surfaces_;
};
diff --git a/chromium/ui/ozone/platform/wayland/test/test_data_device.cc b/chromium/ui/ozone/platform/wayland/test/test_data_device.cc
index e2a8a8bc9bc..ee3fc397545 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_data_device.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_data_device.cc
@@ -11,6 +11,7 @@
#include "base/notreached.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h"
#include "ui/ozone/platform/wayland/test/server_object.h"
+#include "ui/ozone/platform/wayland/test/test_data_device_manager.h"
#include "ui/ozone/platform/wayland/test/test_data_offer.h"
#include "ui/ozone/platform/wayland/test/test_data_source.h"
#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h"
@@ -75,15 +76,19 @@ const struct wl_data_device_interface kTestDataDeviceImpl = {
&DataDeviceStartDrag, &TestSelectionDevice::SetSelection,
&DataDeviceRelease};
-TestDataDevice::TestDataDevice(wl_resource* resource, wl_client* client)
+TestDataDevice::TestDataDevice(wl_resource* resource,
+ wl_client* client,
+ TestDataDeviceManager* manager)
: TestSelectionDevice(resource, new WlDataDeviceImpl(this)),
- client_(client) {}
+ client_(client),
+ manager_(manager) {}
TestDataDevice::~TestDataDevice() = default;
void TestDataDevice::SetSelection(TestDataSource* data_source,
uint32_t serial) {
- NOTIMPLEMENTED();
+ CHECK(manager_);
+ manager_->set_data_source(data_source);
}
TestDataOffer* TestDataDevice::CreateAndSendDataOffer() {
@@ -95,6 +100,10 @@ void TestDataDevice::StartDrag(TestDataSource* source,
uint32_t serial) {
DCHECK(source);
DCHECK(origin);
+
+ CHECK(manager_);
+ manager_->set_data_source(source);
+
if (drag_delegate_)
drag_delegate_->StartDrag(source, origin, serial);
wl_client_flush(client_);
diff --git a/chromium/ui/ozone/platform/wayland/test/test_data_device.h b/chromium/ui/ozone/platform/wayland/test/test_data_device.h
index ba2b2c4d183..16242fb49ca 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_data_device.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_data_device.h
@@ -21,6 +21,7 @@ extern const struct wl_data_device_interface kTestDataDeviceImpl;
class TestDataOffer;
class TestDataSource;
+class TestDataDeviceManager;
class TestDataDevice : public TestSelectionDevice {
public:
@@ -30,7 +31,9 @@ class TestDataDevice : public TestSelectionDevice {
uint32_t serial) = 0;
};
- TestDataDevice(wl_resource* resource, wl_client* client);
+ TestDataDevice(wl_resource* resource,
+ wl_client* client,
+ TestDataDeviceManager* manager);
TestDataDevice(const TestDataDevice&) = delete;
TestDataDevice& operator=(const TestDataDevice&) = delete;
@@ -59,6 +62,8 @@ class TestDataDevice : public TestSelectionDevice {
private:
wl_client* client_ = nullptr;
DragDelegate* drag_delegate_ = nullptr;
+
+ TestDataDeviceManager* const manager_;
};
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/test/test_data_device_manager.cc b/chromium/ui/ozone/platform/wayland/test/test_data_device_manager.cc
index e54efbf8aea..5e774db05aa 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_data_device_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_data_device_manager.cc
@@ -8,6 +8,7 @@
#include "ui/ozone/platform/wayland/test/test_data_device.h"
#include "ui/ozone/platform/wayland/test/test_data_source.h"
+#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h"
namespace wl {
@@ -16,23 +17,25 @@ namespace {
constexpr uint32_t kDataDeviceManagerVersion = 3;
void CreateDataSource(wl_client* client, wl_resource* resource, uint32_t id) {
- wl_resource* data_source_resource = CreateResourceWithImpl<TestDataSource>(
- client, &wl_data_source_interface, wl_resource_get_version(resource),
- &kTestDataSourceImpl, id);
- GetUserDataAs<TestDataDeviceManager>(resource)->set_data_source(
- GetUserDataAs<TestDataSource>(data_source_resource));
+ CreateResourceWithImpl<TestDataSource>(client, &wl_data_source_interface,
+ wl_resource_get_version(resource),
+ &kTestDataSourceImpl, id);
}
void GetDataDevice(wl_client* client,
- wl_resource* data_device_manager_resource,
+ wl_resource* manager_resource,
uint32_t id,
wl_resource* seat_resource) {
+ auto* manager = GetUserDataAs<TestDataDeviceManager>(manager_resource);
+ CHECK(manager);
+
wl_resource* resource = CreateResourceWithImpl<TestDataDevice>(
client, &wl_data_device_interface,
- wl_resource_get_version(data_device_manager_resource),
- &kTestDataDeviceImpl, id, client);
- GetUserDataAs<TestDataDeviceManager>(data_device_manager_resource)
- ->set_data_device(GetUserDataAs<TestDataDevice>(resource));
+ wl_resource_get_version(manager_resource), &kTestDataDeviceImpl, id,
+ client, manager);
+
+ CHECK(GetUserDataAs<TestDataDevice>(resource));
+ manager->set_data_device(GetUserDataAs<TestDataDevice>(resource));
}
} // namespace
diff --git a/chromium/ui/ozone/platform/wayland/test/test_gtk_primary_selection.cc b/chromium/ui/ozone/platform/wayland/test/test_gtk_primary_selection.cc
index a027fdaee04..7d9e2290498 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_gtk_primary_selection.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_gtk_primary_selection.cc
@@ -37,7 +37,7 @@ struct GtkPrimarySelectionOffer final : public TestSelectionOffer::Delegate {
struct GtkPrimarySelectionDevice final : public TestSelectionDevice::Delegate {
TestSelectionOffer* CreateAndSendOffer() override {
- const struct gtk_primary_selection_offer_interface kOfferImpl = {
+ static const struct gtk_primary_selection_offer_interface kOfferImpl = {
&TestSelectionOffer::Receive, &Destroy};
wl_resource* device_resource = device->resource();
const int version = wl_resource_get_version(device_resource);
@@ -98,7 +98,7 @@ struct GtkPrimarySelectionDeviceManager
~GtkPrimarySelectionDeviceManager() override = default;
TestSelectionDevice* CreateDevice(wl_client* client, uint32_t id) override {
- const struct gtk_primary_selection_device_interface
+ static const struct gtk_primary_selection_device_interface
kTestSelectionDeviceImpl = {&TestSelectionDevice::SetSelection,
&Destroy};
auto* delegate = new GtkPrimarySelectionDevice;
@@ -110,7 +110,7 @@ struct GtkPrimarySelectionDeviceManager
}
TestSelectionSource* CreateSource(wl_client* client, uint32_t id) override {
- const struct gtk_primary_selection_source_interface
+ static const struct gtk_primary_selection_source_interface
kTestSelectionSourceImpl = {&TestSelectionSource::Offer, &Destroy};
auto* delegate = new GtkPrimarySelectionSource;
wl_resource* resource = CreateResourceWithImpl<TestSelectionSource>(
@@ -130,7 +130,7 @@ struct GtkPrimarySelectionDeviceManager
TestSelectionDeviceManager* CreateTestSelectionManagerGtk() {
constexpr uint32_t kVersion = 1;
- const struct gtk_primary_selection_device_manager_interface
+ static const struct gtk_primary_selection_device_manager_interface
kTestSelectionManagerImpl = {&TestSelectionDeviceManager::CreateSource,
&TestSelectionDeviceManager::GetDevice,
&Destroy};
diff --git a/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.cc b/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.cc
index b9747902e1a..ec2626d0f42 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.cc
@@ -15,7 +15,6 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/notreached.h"
-#include "base/task/post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_runner_util.h"
#include "base/task/task_traits.h"
@@ -153,7 +152,10 @@ void TestSelectionDevice::SetSelection(struct wl_client* client,
CHECK(GetUserDataAs<TestSelectionDevice>(resource));
auto* self = GetUserDataAs<TestSelectionDevice>(resource);
auto* src = source ? GetUserDataAs<TestSelectionSource>(source) : nullptr;
+ self->selection_serial_ = serial;
self->delegate_->HandleSetSelection(src, serial);
+ if (self->manager_)
+ self->manager_->set_source(src);
}
TestSelectionDeviceManager::TestSelectionDeviceManager(
@@ -171,7 +173,7 @@ void TestSelectionDeviceManager::CreateSource(wl_client* client,
uint32_t id) {
CHECK(GetUserDataAs<TestSelectionDeviceManager>(manager_resource));
auto* manager = GetUserDataAs<TestSelectionDeviceManager>(manager_resource);
- manager->source_ = manager->delegate_->CreateSource(client, id);
+ manager->delegate_->CreateSource(client, id);
}
void TestSelectionDeviceManager::GetDevice(wl_client* client,
@@ -180,7 +182,9 @@ void TestSelectionDeviceManager::GetDevice(wl_client* client,
wl_resource* seat_resource) {
CHECK(GetUserDataAs<TestSelectionDeviceManager>(manager_resource));
auto* manager = GetUserDataAs<TestSelectionDeviceManager>(manager_resource);
- manager->device_ = manager->delegate_->CreateDevice(client, id);
+ auto* new_device = manager->delegate_->CreateDevice(client, id);
+ new_device->set_manager(manager);
+ manager->device_ = new_device;
}
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.h b/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.h
index 0d542d65a35..bf4c9578f00 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_selection_device_manager.h
@@ -60,6 +60,8 @@ class TestSelectionDeviceManager : public GlobalObject {
TestSelectionDevice* device() { return device_; }
TestSelectionSource* source() { return source_; }
+ void set_source(TestSelectionSource* source) { source_ = source; }
+
// Protocol object requests:
static void CreateSource(wl_client* client,
wl_resource* manager_resource,
@@ -165,14 +167,22 @@ class TestSelectionDevice : public ServerObject {
TestSelectionOffer* OnDataOffer();
void OnSelection(TestSelectionOffer* offer);
+ void set_manager(TestSelectionDeviceManager* manager) { manager_ = manager; }
+
// Protocol object requests:
static void SetSelection(struct wl_client* client,
struct wl_resource* resource,
struct wl_resource* source,
uint32_t serial);
+ uint32_t selection_serial() const { return selection_serial_; }
+
private:
Delegate* const delegate_;
+
+ uint32_t selection_serial_ = 0;
+
+ TestSelectionDeviceManager* manager_ = nullptr;
};
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/test/test_subsurface.cc b/chromium/ui/ozone/platform/wayland/test/test_subsurface.cc
index 90ba375ba6a..49d946453da 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_subsurface.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_subsurface.cc
@@ -15,19 +15,19 @@ void SetPosition(wl_client* client,
wl_resource* resource,
int32_t x,
int32_t y) {
- GetUserDataAs<TestSubSurface>(resource)->SetPosition(x, y);
+ GetUserDataAs<TestSubSurface>(resource)->SetPositionImpl(x, y);
}
void PlaceAbove(wl_client* client,
wl_resource* resource,
wl_resource* reference_resource) {
- NOTIMPLEMENTED_LOG_ONCE();
+ GetUserDataAs<TestSubSurface>(resource)->PlaceAbove(reference_resource);
}
void PlaceBelow(wl_client* client,
wl_resource* resource,
wl_resource* sibling_resource) {
- NOTIMPLEMENTED_LOG_ONCE();
+ GetUserDataAs<TestSubSurface>(resource)->PlaceBelow(sibling_resource);
}
void SetSync(wl_client* client, wl_resource* resource) {
@@ -61,8 +61,9 @@ TestSubSurface::~TestSubSurface() {
wl_resource_destroy(augmented_subsurface_->resource());
}
-void TestSubSurface::SetPosition(float x, float y) {
+void TestSubSurface::SetPositionImpl(float x, float y) {
position_ = gfx::PointF(x, y);
+ SetPosition(x, y);
}
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/test/test_subsurface.h b/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
index eb4f1678781..833248e4d4a 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_subsurface.h
@@ -29,7 +29,11 @@ class TestSubSurface : public ServerObject {
TestSubSurface(const TestSubSurface& rhs) = delete;
TestSubSurface& operator=(const TestSubSurface& rhs) = delete;
- void SetPosition(float x, float y);
+ MOCK_METHOD1(PlaceAbove, void(wl_resource* reference_resource));
+ MOCK_METHOD1(PlaceBelow, void(wl_resource* sibling_resource));
+ MOCK_METHOD2(SetPosition, void(float x, float y));
+
+ void SetPositionImpl(float x, float y);
gfx::PointF position() const { return position_; }
void set_sync(bool sync) { sync_ = sync; }
diff --git a/chromium/ui/ozone/platform/wayland/test/test_viewport.cc b/chromium/ui/ozone/platform/wayland/test/test_viewport.cc
index 04b2ea2c391..8d6cd572d9c 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_viewport.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_viewport.cc
@@ -17,7 +17,10 @@ void SetSource(wl_client* client,
wl_fixed_t y,
wl_fixed_t width,
wl_fixed_t height) {
- NOTIMPLEMENTED_LOG_ONCE();
+ auto* test_vp = GetUserDataAs<TestViewport>(resource);
+ DCHECK(test_vp);
+ test_vp->SetSource(wl_fixed_to_double(x), wl_fixed_to_double(y),
+ wl_fixed_to_double(width), wl_fixed_to_double(height));
}
void SetDestination(wl_client* client,
@@ -26,7 +29,7 @@ void SetDestination(wl_client* client,
int32_t height) {
auto* test_vp = GetUserDataAs<TestViewport>(resource);
DCHECK(test_vp);
- test_vp->SetDestination(width, height);
+ test_vp->SetDestinationImpl(width, height);
}
} // namespace
@@ -48,8 +51,9 @@ TestViewport::~TestViewport() {
mock_surface->set_viewport(nullptr);
}
-void TestViewport::SetDestination(float width, float height) {
+void TestViewport::SetDestinationImpl(float width, float height) {
destination_size_ = gfx::SizeF(width, height);
+ SetDestination(width, height);
}
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/test/test_viewport.h b/chromium/ui/ozone/platform/wayland/test/test_viewport.h
index 7be156bbe40..4ac792a0c24 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_viewport.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_viewport.h
@@ -7,6 +7,7 @@
#include <viewporter-server-protocol.h>
+#include "testing/gmock/include/gmock/gmock.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/ozone/platform/wayland/test/server_object.h"
@@ -23,8 +24,11 @@ class TestViewport : public ServerObject {
TestViewport(const TestViewport& rhs) = delete;
TestViewport& operator=(const TestViewport& rhs) = delete;
+ MOCK_METHOD2(SetDestination, void(float x, float y));
+ MOCK_METHOD4(SetSource, void(float x, float y, float width, float height));
+
gfx::SizeF destination_size() const { return destination_size_; }
- void SetDestination(float x, float y);
+ void SetDestinationImpl(float x, float y);
private:
// Surface resource that is the ground for this Viewport.
diff --git a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
index 686c350a99e..964d1445f61 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -32,6 +32,8 @@ TestWaylandServerThread::TestWaylandServerThread()
base::WaitableEvent::InitialState::NOT_SIGNALED),
resume_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED),
+ compositor_v4_(4),
+ compositor_v3_(3),
controller_(FROM_HERE) {}
TestWaylandServerThread::~TestWaylandServerThread() {
@@ -60,8 +62,13 @@ bool TestWaylandServerThread::Start(const ServerConfig& config) {
if (wl_display_init_shm(display_.get()) < 0)
return false;
- if (!compositor_.Initialize(display_.get()))
- return false;
+ if (config.compositor_version == CompositorVersion::kV3) {
+ if (!compositor_v3_.Initialize(display_.get()))
+ return false;
+ } else {
+ if (!compositor_v4_.Initialize(display_.get()))
+ return false;
+ }
if (!sub_compositor_.Initialize(display_.get()))
return false;
if (!viewporter_.Initialize(display_.get()))
diff --git a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
index 4dfe8a53668..2c40b46b4f6 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
+++ b/chromium/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -46,9 +46,11 @@ struct DisplayDeleter {
// Server configuration related enums and structs.
enum class ShellVersion { kV6, kStable };
enum class PrimarySelectionProtocol { kNone, kGtk, kZwp };
+enum class CompositorVersion { kV3, kV4 };
struct ServerConfig {
ShellVersion shell_version = ShellVersion::kStable;
+ CompositorVersion compositor_version = CompositorVersion::kV4;
PrimarySelectionProtocol primary_selection_protocol =
PrimarySelectionProtocol::kNone;
};
@@ -151,7 +153,12 @@ class TestWaylandServerThread : public base::Thread,
base::WaitableEvent resume_event_;
// Represent Wayland global objects
- TestCompositor compositor_;
+ // Compositor version is selected dynamically by server config but version is
+ // actually set on construction thus both compositor version objects appear
+ // here.
+ // TODO(crbug.com/1315587): Refactor this pattern when required.
+ TestCompositor compositor_v4_;
+ TestCompositor compositor_v3_;
TestSubCompositor sub_compositor_;
TestViewporter viewporter_;
TestAlphaCompositing alpha_compositing_;
diff --git a/chromium/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc b/chromium/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc
index 6e22a3a4388..447fa6e3568 100644
--- a/chromium/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc
+++ b/chromium/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc
@@ -37,7 +37,7 @@ struct ZwpPrimarySelectionOffer final : public TestSelectionOffer::Delegate {
struct ZwpPrimarySelectionDevice final : public TestSelectionDevice::Delegate {
TestSelectionOffer* CreateAndSendOffer() override {
- const struct zwp_primary_selection_offer_v1_interface kOfferImpl = {
+ static const struct zwp_primary_selection_offer_v1_interface kOfferImpl = {
&TestSelectionOffer::Receive, &Destroy};
wl_resource* device_resource = device->resource();
const int version = wl_resource_get_version(device_resource);
@@ -98,7 +98,7 @@ struct ZwpPrimarySelectionDeviceManager
~ZwpPrimarySelectionDeviceManager() override = default;
TestSelectionDevice* CreateDevice(wl_client* client, uint32_t id) override {
- const struct zwp_primary_selection_device_v1_interface
+ static const struct zwp_primary_selection_device_v1_interface
kTestSelectionDeviceImpl = {&TestSelectionDevice::SetSelection,
&Destroy};
auto* delegate = new ZwpPrimarySelectionDevice;
@@ -110,7 +110,7 @@ struct ZwpPrimarySelectionDeviceManager
}
TestSelectionSource* CreateSource(wl_client* client, uint32_t id) override {
- const struct zwp_primary_selection_source_v1_interface
+ static const struct zwp_primary_selection_source_v1_interface
kTestSelectionSourceImpl = {&TestSelectionSource::Offer, &Destroy};
auto* delegate = new ZwpPrimarySelectionSource;
wl_resource* resource = CreateResourceWithImpl<TestSelectionSource>(
@@ -130,7 +130,7 @@ struct ZwpPrimarySelectionDeviceManager
TestSelectionDeviceManager* CreateTestSelectionManagerZwp() {
constexpr uint32_t kVersion = 1;
- const struct zwp_primary_selection_device_manager_v1_interface
+ static const struct zwp_primary_selection_device_manager_v1_interface
kTestSelectionManagerImpl = {&TestSelectionDeviceManager::CreateSource,
&TestSelectionDeviceManager::GetDevice,
&Destroy};
diff --git a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
index 87d7814b43a..ef4c9720cd9 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
@@ -16,6 +16,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/gfx/geometry/rrect_f.h"
+#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/overlay_priority_hint.h"
@@ -198,12 +199,10 @@ class WaylandBufferManagerTest : public WaylandTest {
Sync();
}
- void DestroyBufferAndSetTerminateExpectation(gfx::AcceleratedWidget widget,
- uint32_t buffer_id,
- bool fail) {
+ void DestroyBufferAndSetTerminateExpectation(uint32_t buffer_id, bool fail) {
SetTerminateCallbackExpectationAndDestroyChannel(&callback_, fail);
- buffer_manager_gpu_->DestroyBuffer(widget, buffer_id);
+ buffer_manager_gpu_->DestroyBuffer(buffer_id);
Sync();
}
@@ -255,8 +254,7 @@ TEST_P(WaylandBufferManagerTest, CreateDmabufBasedBuffers) {
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kDmabufBufferId);
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kDmabufBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, VerifyModifiers) {
@@ -306,8 +304,7 @@ TEST_P(WaylandBufferManagerTest, VerifyModifiers) {
EXPECT_EQ(params_vector[0]->modifier_lo_, kFormatModiferLinear & UINT32_MAX);
// Clean up.
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kDmabufBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, CreateShmBasedBuffers) {
@@ -315,8 +312,7 @@ TEST_P(WaylandBufferManagerTest, CreateShmBasedBuffers) {
CreateShmBasedBufferAndSetTerminateExpecation(false /*fail*/, kShmBufferId);
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kShmBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kShmBufferId, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, ValidateDataFromGpu) {
@@ -377,8 +373,9 @@ TEST_P(WaylandBufferManagerTest, CreateAndDestroyBuffer) {
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, window_->GetBounds(),
- kDefaultScale, window_->GetBounds());
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1,
+ window_->GetBounds(), kDefaultScale,
+ window_->GetBounds());
CreateDmabufBasedBufferAndSetTerminateExpectation(true /*fail*/,
kBufferId1);
@@ -387,11 +384,10 @@ TEST_P(WaylandBufferManagerTest, CreateAndDestroyBuffer) {
// ... impossible to destroy non-existing buffer.
{
// Either it is attached...
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, true /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, true /*fail*/);
// Or not attached.
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId1, true /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, true /*fail*/);
}
// Can destroy the buffer without specifying the widget.
@@ -400,11 +396,11 @@ TEST_P(WaylandBufferManagerTest, CreateAndDestroyBuffer) {
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, window_->GetBounds(),
- kDefaultScale, window_->GetBounds());
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1,
+ window_->GetBounds(), kDefaultScale,
+ window_->GetBounds());
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
}
// Still can destroy the buffer even if it has not been attached to any
@@ -413,7 +409,7 @@ TEST_P(WaylandBufferManagerTest, CreateAndDestroyBuffer) {
EXPECT_CALL(*server_.zwp_linux_dmabuf_v1(), CreateParams(_, _, _)).Times(1);
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId1);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
}
// ... impossible to destroy buffers twice.
@@ -422,30 +418,28 @@ TEST_P(WaylandBufferManagerTest, CreateAndDestroyBuffer) {
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId1);
// Attach to a surface.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, window_->GetBounds(),
- kDefaultScale, window_->GetBounds());
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1,
+ window_->GetBounds(), kDefaultScale,
+ window_->GetBounds());
// Created non-attached buffer as well.
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId2);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
// Can't destroy the buffer with non-existing id (the manager cleared the
// state after the previous failure).
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, true /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, true /*fail*/);
// Non-attached buffer must have been also destroyed (we can't destroy it
// twice) if there was a failure.
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId2, true /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, true /*fail*/);
// Create and destroy non-attached buffer twice.
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kBufferId2);
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId2, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId2, true /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, true /*fail*/);
}
}
@@ -455,7 +449,7 @@ TEST_P(WaylandBufferManagerTest, CommitBufferNonExistingBufferId) {
// Can't commit for non-existing buffer id.
SetTerminateCallbackExpectationAndDestroyChannel(&callback_, true /*fail*/);
- buffer_manager_gpu_->CommitBuffer(window_->GetWidget(), 5u,
+ buffer_manager_gpu_->CommitBuffer(window_->GetWidget(), 1u, 5u,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
@@ -483,7 +477,7 @@ TEST_P(WaylandBufferManagerTest, CommitOverlaysNonExistingBufferId) {
false, 1.0f, gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone,
gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
@@ -508,7 +502,7 @@ TEST_P(WaylandBufferManagerTest, CommitOverlaysWithSameBufferId) {
false, 1.0f, gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone,
gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
@@ -516,10 +510,9 @@ TEST_P(WaylandBufferManagerTest, CommitOverlaysWithSameBufferId) {
false /* fail */);
// Destroying the buffer causes all wl_buffer objects to be destroyed.
- DestroyBufferAndSetTerminateExpectation(window_->GetWidget(), 1u,
- false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(1u, false /*fail*/);
SetTerminateCallbackExpectationAndDestroyChannel(&callback_, true /*fail*/);
- buffer_manager_gpu_->CommitBuffer(window_->GetWidget(), 1u,
+ buffer_manager_gpu_->CommitBuffer(window_->GetWidget(), 1u, 1u,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
Sync();
@@ -532,7 +525,7 @@ TEST_P(WaylandBufferManagerTest, CommitBufferNullWidget) {
// Can't commit for non-existing widget.
SetTerminateCallbackExpectationAndDestroyChannel(&callback_, true /*fail*/);
- buffer_manager_gpu_->CommitBuffer(gfx::kNullAcceleratedWidget, kBufferId,
+ buffer_manager_gpu_->CommitBuffer(gfx::kNullAcceleratedWidget, 1u, kBufferId,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
@@ -564,7 +557,7 @@ TEST_P(WaylandBufferManagerTest, CommitOverlaysNonsensicalBoundsRect) {
bounds_rect, gfx::RectF(), window_->GetBounds(), false, 1.0f,
gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone, gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
@@ -612,8 +605,8 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
ASSERT_TRUE(!connection_->presentation());
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -624,8 +617,8 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
Sync();
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -654,8 +647,8 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
.Times(1);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -680,8 +673,8 @@ TEST_P(WaylandBufferManagerTest, EnsureCorrectOrderOfCallbacks) {
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest,
@@ -732,8 +725,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(mock_surface_gpu,
OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -742,8 +735,8 @@ TEST_P(WaylandBufferManagerTest,
mock_wp_presentation->set_presentation_callback(nullptr);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -752,7 +745,7 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(mock_surface_gpu,
OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(1);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, /*fail=*/false);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, /*fail=*/false);
mock_surface->DestroyPrevAttachedBuffer();
mock_surface->SendFrameCallback();
Sync();
@@ -764,8 +757,8 @@ TEST_P(WaylandBufferManagerTest,
// Commit buffer 3 then send the presentation callback for it. This should
// not call OnPresentation as OnSubmission hasn't been called yet.
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, kBufferId3, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
mock_wp_presentation->SendPresentationCallback();
Sync();
@@ -792,13 +785,13 @@ TEST_P(WaylandBufferManagerTest,
::testing::Eq(gfx::PresentationFeedback::Flags::kFailure))))
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(1);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, /*fail=*/false);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, /*fail=*/false);
mock_surface->DestroyPrevAttachedBuffer();
mock_surface->SendFrameCallback();
mock_wp_presentation->SendPresentationCallback();
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId3, false /*fail*/);
}
// This test ensures that a discarded presentation feedback sent prior receiving
@@ -847,8 +840,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
// Commit first buffer
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -866,8 +859,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
// Commit second buffer
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -887,8 +880,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
// Commit third buffer
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, kBufferId3, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -944,9 +937,9 @@ TEST_P(WaylandBufferManagerTest,
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId3, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, TestCommitBufferConditions) {
@@ -972,7 +965,7 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditions) {
EXPECT_CALL(*mock_surface, Frame(_)).Times(0);
EXPECT_CALL(*mock_surface, Commit()).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId,
+ buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId, kDmabufBufferId,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
Sync();
@@ -1006,7 +999,7 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditions) {
EXPECT_CALL(*mock_surface, Frame(_)).Times(0);
EXPECT_CALL(*mock_surface, Commit()).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId2,
+ buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId2, kDmabufBufferId2,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
@@ -1021,10 +1014,8 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditions) {
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kDmabufBufferId,
- false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kDmabufBufferId2,
- false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId2, false /*fail*/);
}
// Tests the surface does not have buffers attached until it's configured at
@@ -1069,7 +1060,7 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditionsAckConfigured) {
EXPECT_CALL(*mock_surface, Frame(_)).Times(0);
EXPECT_CALL(*mock_surface, Commit()).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId,
+ buffer_manager_gpu_->CommitBuffer(widget, kDmabufBufferId, kDmabufBufferId,
window_->GetBounds(), kDefaultScale,
window_->GetBounds());
Sync();
@@ -1085,8 +1076,7 @@ TEST_P(WaylandBufferManagerTest, TestCommitBufferConditionsAckConfigured) {
window_->SetPointerFocus(false);
temp_window.reset();
- DestroyBufferAndSetTerminateExpectation(widget, kDmabufBufferId,
- false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId, false /*fail*/);
Sync();
}
@@ -1132,8 +1122,8 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1157,8 +1147,8 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1182,8 +1172,8 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
.Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId3, _)).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, kBufferId3, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1203,9 +1193,9 @@ TEST_P(WaylandBufferManagerTest, AnonymousBufferAttachedAndReleased) {
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId3, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, DestroyBufferForDestroyedWindow) {
@@ -1219,13 +1209,14 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferForDestroyedWindow) {
Sync();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId, temp_window->GetBounds(),
- kDefaultScale, temp_window->GetBounds());
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId, kBufferId,
+ temp_window->GetBounds(), kDefaultScale,
+ temp_window->GetBounds());
Sync();
temp_window.reset();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionSingleBuffer) {
@@ -1252,12 +1243,12 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionSingleBuffer) {
temp_window.reset();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId, kBufferId, bounds,
+ kDefaultScale, bounds);
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
@@ -1294,8 +1285,8 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1315,8 +1306,8 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1328,13 +1319,13 @@ TEST_P(WaylandBufferManagerTest, DestroyedWindowNoSubmissionMultipleBuffers) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
temp_window.reset();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
}
// Tests that OnSubmission and OnPresentation are properly triggered if a buffer
@@ -1365,8 +1356,8 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
@@ -1375,20 +1366,20 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
// Destroying buffer2 should do nothing yet.
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
@@ -1398,7 +1389,7 @@ TEST_P(WaylandBufferManagerTest, DestroyBufferCommittedTwiceInARow) {
OnSubmission(kBufferId2, gfx::SwapResult::SWAP_ACK, _))
.Times(2);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId2, _)).Times(2);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
@@ -1432,8 +1423,8 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
@@ -1443,13 +1434,13 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
EXPECT_CALL(mock_surface_gpu, OnSubmission(_, _, _)).Times(0);
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -1465,8 +1456,8 @@ TEST_P(WaylandBufferManagerTest, ReleaseBufferCommittedTwiceInARow) {
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
}
// Tests that OnSubmission and OnPresentation callbacks are properly called
@@ -1500,8 +1491,8 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
@@ -1512,14 +1503,14 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(2);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
auto* wl_buffer2 = mock_surface->attached_buffer();
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, kBufferId3, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -1547,9 +1538,9 @@ TEST_P(WaylandBufferManagerTest, ReleaseOrderDifferentToCommitOrder) {
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId3, false /*fail*/);
}
// This test verifies that submitting the buffer more than once results in
@@ -1589,8 +1580,8 @@ TEST_P(WaylandBufferManagerTest,
.Times(1);
EXPECT_CALL(*mock_surface, Commit()).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1612,8 +1603,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(*mock_surface, Commit()).Times(1);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1654,8 +1645,8 @@ TEST_P(WaylandBufferManagerTest,
EXPECT_CALL(*mock_surface, Commit()).Times(1);
// Commit second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1689,8 +1680,8 @@ TEST_P(WaylandBufferManagerTest,
.Times(1);
EXPECT_CALL(*mock_surface, Commit()).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
@@ -1710,8 +1701,8 @@ TEST_P(WaylandBufferManagerTest,
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
}
// Tests that submitting a single buffer only receives an OnSubmission. This is
@@ -1739,11 +1730,11 @@ TEST_P(WaylandBufferManagerTest, OnSubmissionCalledForSingleBuffer) {
.Times(1);
EXPECT_CALL(mock_surface_gpu, OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
}
// Tests that when CommitOverlays(), root_surface can only be committed once all
@@ -1796,7 +1787,7 @@ TEST_P(WaylandBufferManagerTest, RootSurfaceIsCommittedLast) {
1, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE, kBufferId3,
kDefaultScale, gfx::RectF(bounds), gfx::RectF(), bounds, false, 1.0f,
gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone, gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
testing::Mock::VerifyAndClearExpectations(mock_surface);
@@ -1854,14 +1845,14 @@ TEST_P(WaylandBufferManagerTest, FencedRelease) {
OnSubmission(kBufferId1, gfx::SwapResult::SWAP_ACK,
Truly([](const auto& fence) { return fence.is_null(); })))
.Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
// Commit the second buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId2, kBufferId2, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -1881,8 +1872,8 @@ TEST_P(WaylandBufferManagerTest, FencedRelease) {
Sync();
// Commit the third buffer now.
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId3, kBufferId3, bounds,
+ kDefaultScale, bounds);
mock_surface->SendFrameCallback();
Sync();
@@ -1899,9 +1890,9 @@ TEST_P(WaylandBufferManagerTest, FencedRelease) {
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId3, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId3, false /*fail*/);
}
// Tests that destroying a channel doesn't result in resetting surface state
@@ -1937,8 +1928,8 @@ TEST_P(WaylandBufferManagerTest,
.Times(1);
EXPECT_CALL(*mock_surface_gpu.get(), OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
// The root surface shouldn't get null buffer attached.
@@ -1989,11 +1980,11 @@ TEST_P(WaylandBufferManagerTest,
.Times(1);
EXPECT_CALL(*mock_surface_gpu.get(), OnPresentation(kBufferId1, _)).Times(1);
- buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, bounds, kDefaultScale,
- bounds);
+ buffer_manager_gpu_->CommitBuffer(widget, kBufferId1, kBufferId1, bounds,
+ kDefaultScale, bounds);
Sync();
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
}
// Tests that destroying a channel results in attaching null buffers to the root
@@ -2035,7 +2026,7 @@ TEST_P(WaylandBufferManagerTest, HidesSubsurfacesOnChannelDestroyed) {
1, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE, kBufferId3,
kDefaultScale, gfx::RectF(bounds), gfx::RectF(), bounds, false, 1.0f,
gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone, gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
@@ -2097,7 +2088,7 @@ TEST_P(WaylandBufferManagerTest, HidesSubsurfacesOnChannelDestroyed) {
kDefaultScale, gfx::RectF(bounds), gfx::RectF(), bounds, false, 1.0f,
gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone, gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), 2u,
std::move(overlay_configs2));
Sync();
@@ -2170,6 +2161,7 @@ TEST_P(WaylandBufferManagerTest, CanSubmitOverlayPriority) {
{gfx::OverlayPriorityHint::kHardwareProtection,
OVERLAY_PRIORITIZED_SURFACE_OVERLAY_PRIORITY_REQUIRED_HARDWARE_PROTECTION}};
+ uint32_t frame_id = 0u;
for (const auto& priority : priorities) {
std::vector<ui::ozone::mojom::WaylandOverlayConfigPtr> overlay_configs;
for (auto id : kBufferIds) {
@@ -2180,7 +2172,7 @@ TEST_P(WaylandBufferManagerTest, CanSubmitOverlayPriority) {
false, 1.0f, gfx::GpuFenceHandle(), priority.first, gfx::RRectF()));
}
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), ++frame_id,
std::move(overlay_configs));
Sync();
@@ -2246,6 +2238,7 @@ TEST_P(WaylandBufferManagerTest, CanSetRoundedCorners) {
// Exo may allow to submit values in px.
std::vector<bool> in_pixels = {true, false};
+ uint32_t frame_id = 0u;
for (auto is_in_px : in_pixels) {
connection_->set_surface_submission_in_pixel_coordinates(is_in_px);
for (auto scale_factor : scale_factors) {
@@ -2260,7 +2253,7 @@ TEST_P(WaylandBufferManagerTest, CanSetRoundedCorners) {
gfx::OverlayPriorityHint::kNone, rounded_corners));
}
- buffer_manager_gpu_->CommitOverlays(window_->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(window_->GetWidget(), ++frame_id,
std::move(overlay_configs));
Sync();
@@ -2367,7 +2360,8 @@ TEST_P(WaylandBufferManagerTest, FeedbacksAreDiscardedIfClientMisbehaves) {
EXPECT_CALL(mock_surface_gpu, OnPresentation(_, _)).Times(0);
}
- buffer_manager_gpu_->CommitBuffer(widget, next_buffer_id_commit, bounds,
+ buffer_manager_gpu_->CommitBuffer(widget, next_buffer_id_commit,
+ next_buffer_id_commit, bounds,
kDefaultScale, bounds);
Sync();
@@ -2384,8 +2378,8 @@ TEST_P(WaylandBufferManagerTest, FeedbacksAreDiscardedIfClientMisbehaves) {
testing::Mock::VerifyAndClearExpectations(&mock_surface_gpu);
}
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId1, false /*fail*/);
- DestroyBufferAndSetTerminateExpectation(widget, kBufferId2, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false /*fail*/);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false /*fail*/);
}
TEST_P(WaylandBufferManagerTest, ExecutesTasksAfterInitialization) {
@@ -2401,10 +2395,9 @@ TEST_P(WaylandBufferManagerTest, ExecutesTasksAfterInitialization) {
CreateDmabufBasedBufferAndSetTerminateExpectation(false /*fail*/,
kDmabufBufferId);
buffer_manager_gpu_->CommitBuffer(window_->GetWidget(), kDmabufBufferId,
- window_->GetBounds(), kDefaultScale,
- window_->GetBounds());
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kDmabufBufferId, false /*fail*/);
+ kDmabufBufferId, window_->GetBounds(),
+ kDefaultScale, window_->GetBounds());
+ DestroyBufferAndSetTerminateExpectation(kDmabufBufferId, false /*fail*/);
base::RunLoop().RunUntilIdle();
@@ -2478,7 +2471,7 @@ class WaylandBufferManagerViewportTest : public WaylandBufferManagerTest {
bounds_rect, gfx::RectF(), temp_window->GetBounds(), false, 1.0f,
gfx::GpuFenceHandle(), gfx::OverlayPriorityHint::kNone, gfx::RRectF()));
- buffer_manager_gpu_->CommitOverlays(temp_window->GetWidget(),
+ buffer_manager_gpu_->CommitOverlays(temp_window->GetWidget(), 1u,
std::move(overlay_configs));
Sync();
@@ -2513,10 +2506,8 @@ class WaylandBufferManagerViewportTest : public WaylandBufferManagerTest {
mock_surface_of_subsurface->SendFrameCallback();
mock_surface->SendFrameCallback();
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId1, false);
- DestroyBufferAndSetTerminateExpectation(gfx::kNullAcceleratedWidget,
- kBufferId2, false);
+ DestroyBufferAndSetTerminateExpectation(kBufferId1, false);
+ DestroyBufferAndSetTerminateExpectation(kBufferId2, false);
}
};
diff --git a/chromium/ui/ozone/platform/windows/BUILD.gn b/chromium/ui/ozone/platform/windows/BUILD.gn
deleted file mode 100644
index f5f44c2d3a3..00000000000
--- a/chromium/ui/ozone/platform/windows/BUILD.gn
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-visibility = [ "//ui/ozone/*" ]
-
-source_set("windows") {
- sources = [
- "client_native_pixmap_factory_windows.cc",
- "client_native_pixmap_factory_windows.h",
- "ozone_platform_windows.cc",
- "ozone_platform_windows.h",
- "windows_surface_factory.cc",
- "windows_surface_factory.h",
- "windows_window.cc",
- "windows_window.h",
- "windows_window_manager.cc",
- "windows_window_manager.h",
- ]
-
- defines = [ "OZONE_IMPLEMENTATION" ]
-
- deps = [
- "//base",
- "//skia",
- "//ui/base",
- "//ui/base/cursor",
- "//ui/display/fake",
- "//ui/events",
- "//ui/events/ozone/layout",
- "//ui/events/platform",
- "//ui/gfx/geometry",
- "//ui/gl",
- "//ui/ozone:ozone_base",
- "//ui/ozone/common",
- "//ui/platform_window",
- "//ui/platform_window/win",
- ]
-}
diff --git a/chromium/ui/ozone/platform/windows/DEPS b/chromium/ui/ozone/platform/windows/DEPS
deleted file mode 100644
index c73fab35723..00000000000
--- a/chromium/ui/ozone/platform/windows/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+ui/base/win",
-]
diff --git a/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.cc b/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.cc
deleted file mode 100644
index 30187da1ea6..00000000000
--- a/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/windows/client_native_pixmap_factory_windows.h"
-
-#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
-
-namespace ui {
-
-gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryWindows() {
- // TODO(camurcu): Implement the better (more performant) way.
- return CreateStubClientNativePixmapFactory();
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.h b/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.h
deleted file mode 100644
index 542e448d042..00000000000
--- a/chromium/ui/ozone/platform/windows/client_native_pixmap_factory_windows.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WINDOWS_CLIENT_NATIVE_PIXMAP_FACTORY_WINDOWS_H_
-#define UI_OZONE_PLATFORM_WINDOWS_CLIENT_NATIVE_PIXMAP_FACTORY_WINDOWS_H_
-
-namespace gfx {
-class ClientNativePixmapFactory;
-}
-
-namespace ui {
-
-// Constructor hook for use in constructor_list.cc
-gfx::ClientNativePixmapFactory* CreateClientNativePixmapFactoryWindows();
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WINDOWS_CLIENT_NATIVE_PIXMAP_FACTORY_WINDOWS_H_
diff --git a/chromium/ui/ozone/platform/windows/ozone_platform_windows.cc b/chromium/ui/ozone/platform/windows/ozone_platform_windows.cc
deleted file mode 100644
index 2e37a740197..00000000000
--- a/chromium/ui/ozone/platform/windows/ozone_platform_windows.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/windows/ozone_platform_windows.h"
-
-#include <memory>
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
-#include "ui/base/cursor/cursor_factory.h"
-#include "ui/base/win/win_cursor_factory.h"
-#include "ui/display/fake/fake_display_delegate.h"
-#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
-#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/common/stub_overlay_manager.h"
-#include "ui/ozone/platform/windows/windows_surface_factory.h"
-#include "ui/ozone/platform/windows/windows_window.h"
-#include "ui/ozone/platform/windows/windows_window_manager.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/ozone_switches.h"
-#include "ui/ozone/public/system_input_injector.h"
-#include "ui/platform_window/platform_window_init_properties.h"
-
-namespace ui {
-
-namespace {
-
-// dummy class
-class WindowsPlatformEventSource : public ui::PlatformEventSource {
- public:
- WindowsPlatformEventSource() = default;
-
- WindowsPlatformEventSource(const WindowsPlatformEventSource&) = delete;
- WindowsPlatformEventSource& operator=(const WindowsPlatformEventSource&) =
- delete;
-
- ~WindowsPlatformEventSource() override = default;
-};
-
-// OzonePlatform for Windows
-class OzonePlatformWindows : public OzonePlatform {
- public:
- OzonePlatformWindows() {}
-
- OzonePlatformWindows(const OzonePlatformWindows&) = delete;
- OzonePlatformWindows& operator=(const OzonePlatformWindows&) = delete;
-
- ~OzonePlatformWindows() override {}
-
- // OzonePlatform:
- ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
- return surface_factory_.get();
- }
- OverlayManagerOzone* GetOverlayManager() override {
- return overlay_manager_.get();
- }
- CursorFactory* GetCursorFactory() override { return cursor_factory_.get(); }
- InputController* GetInputController() override {
- return input_controller_.get();
- }
- GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
- return gpu_platform_support_host_.get();
- }
- std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
- return nullptr; // no input injection support.
- }
- std::unique_ptr<PlatformWindow> CreatePlatformWindow(
- PlatformWindowDelegate* delegate,
- PlatformWindowInitProperties properties) override {
- return std::make_unique<WindowsWindow>(delegate, properties.bounds);
- }
- std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
- override {
- return std::make_unique<display::FakeDisplayDelegate>();
- }
- std::unique_ptr<InputMethod> CreateInputMethod(
- internal::InputMethodDelegate* delegate,
- gfx::AcceleratedWidget) override {
- NOTREACHED();
- return nullptr;
- }
-
- bool InitializeUI(const InitParams& params) override {
- window_manager_ = std::make_unique<WindowsWindowManager>();
- surface_factory_ = std::make_unique<WindowsSurfaceFactory>();
- // This unbreaks tests that create their own.
- if (!PlatformEventSource::GetInstance())
- platform_event_source_ = std::make_unique<WindowsPlatformEventSource>();
- keyboard_layout_engine_ = std::make_unique<StubKeyboardLayoutEngine>();
- KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
- keyboard_layout_engine_.get());
-
- overlay_manager_ = std::make_unique<StubOverlayManager>();
- input_controller_ = CreateStubInputController();
- cursor_factory_ = std::make_unique<WinCursorFactory>();
- gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
-
- return true;
- }
-
- void InitializeGPU(const InitParams& params) override {
- if (!surface_factory_)
- surface_factory_ = std::make_unique<WindowsSurfaceFactory>();
- }
-
- private:
- std::unique_ptr<KeyboardLayoutEngine> keyboard_layout_engine_;
- std::unique_ptr<WindowsWindowManager> window_manager_;
- std::unique_ptr<WindowsSurfaceFactory> surface_factory_;
- std::unique_ptr<PlatformEventSource> platform_event_source_;
- std::unique_ptr<CursorFactory> cursor_factory_;
- std::unique_ptr<InputController> input_controller_;
- std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
- std::unique_ptr<OverlayManagerOzone> overlay_manager_;
-};
-
-} // namespace
-
-OzonePlatform* CreateOzonePlatformWindows() {
- return new OzonePlatformWindows;
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/ozone_platform_windows.h b/chromium/ui/ozone/platform/windows/ozone_platform_windows.h
deleted file mode 100644
index 07169e74690..00000000000
--- a/chromium/ui/ozone/platform/windows/ozone_platform_windows.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WINDOWS_OZONE_PLATFORM_WINDOWS_H_
-#define UI_OZONE_PLATFORM_WINDOWS_OZONE_PLATFORM_WINDOWS_H_
-
-namespace ui {
-
-class OzonePlatform;
-
-// Constructor hook for use in ozone_platform_list.cc
-OzonePlatform* CreateOzonePlatformWindows();
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WINDOWS_OZONE_PLATFORM_WINDOWS_H_
diff --git a/chromium/ui/ozone/platform/windows/windows_surface_factory.cc b/chromium/ui/ozone/platform/windows/windows_surface_factory.cc
deleted file mode 100644
index 5d525bd5ae4..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_surface_factory.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/windows/windows_surface_factory.h"
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "build/build_config.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/geometry/skia_conversions.h"
-#include "ui/gfx/vsync_provider.h"
-#include "ui/gl/gl_surface_egl.h"
-#include "ui/gl/vsync_provider_win.h"
-#include "ui/ozone/common/egl_util.h"
-#include "ui/ozone/common/gl_ozone_egl.h"
-#include "ui/ozone/platform/windows/windows_window.h"
-#include "ui/ozone/platform/windows/windows_window_manager.h"
-
-namespace ui {
-
-namespace {
-
-class GLOzoneEGLWindows : public GLOzoneEGL {
- public:
- GLOzoneEGLWindows() = default;
-
- GLOzoneEGLWindows(const GLOzoneEGLWindows&) = delete;
- GLOzoneEGLWindows& operator=(const GLOzoneEGLWindows&) = delete;
-
- ~GLOzoneEGLWindows() override = default;
-
- // GLOzone:
- scoped_refptr<gl::GLSurface> CreateViewGLSurface(
- gfx::AcceleratedWidget window) override {
- return InitializeGLSurface(base::MakeRefCounted<gl::NativeViewGLSurfaceEGL>(
- window, std::make_unique<gl::VSyncProviderWin>(window)));
- }
-
- scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(
- const gfx::Size& size) override {
- return gl::InitializeGLSurface(
- base::MakeRefCounted<gl::PbufferGLSurfaceEGL>(size));
- }
-
- protected:
- // GLOzoneEGL:
- gl::EGLDisplayPlatform GetNativeDisplay() override {
- return gl::EGLDisplayPlatform(GetWindowDC(nullptr));
- }
-
- bool LoadGLES2Bindings(
- const gl::GLImplementationParts& implementation) override {
- return LoadDefaultEGLGLES2Bindings(implementation);
- }
-};
-
-} // namespace
-
-WindowsSurfaceFactory::WindowsSurfaceFactory()
- : egl_implementation_(std::make_unique<GLOzoneEGLWindows>()) {}
-
-WindowsSurfaceFactory::~WindowsSurfaceFactory() = default;
-
-std::vector<gl::GLImplementationParts>
-WindowsSurfaceFactory::GetAllowedGLImplementations() {
- return std::vector<gl::GLImplementationParts>{
- gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
- gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
- gl::GLImplementationParts(gl::kGLImplementationEGLANGLE)};
-}
-
-GLOzone* WindowsSurfaceFactory::GetGLOzone(
- const gl::GLImplementationParts& implementation) {
- switch (implementation.gl) {
- case gl::kGLImplementationEGLGLES2:
- case gl::kGLImplementationEGLANGLE:
- return egl_implementation_.get();
- default:
- return nullptr;
- }
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/windows_surface_factory.h b/chromium/ui/ozone/platform/windows/windows_surface_factory.h
deleted file mode 100644
index 9e146e8f8e4..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_surface_factory.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WINDOWS_WINDOWS_SURFACE_FACTORY_H_
-#define UI_OZONE_PLATFORM_WINDOWS_WINDOWS_SURFACE_FACTORY_H_
-
-#include <memory>
-#include <vector>
-
-#include "ui/ozone/public/gl_ozone.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-
-namespace ui {
-
-// Handles GL initialization and surface/context creation for Windows
-class WindowsSurfaceFactory : public SurfaceFactoryOzone {
- public:
- WindowsSurfaceFactory();
-
- WindowsSurfaceFactory(const WindowsSurfaceFactory&) = delete;
- WindowsSurfaceFactory& operator=(const WindowsSurfaceFactory&) = delete;
-
- ~WindowsSurfaceFactory() override;
-
- // SurfaceFactoryOzone:
- std::vector<gl::GLImplementationParts> GetAllowedGLImplementations() override;
- GLOzone* GetGLOzone(const gl::GLImplementationParts& implementation) override;
-
- private:
- std::unique_ptr<GLOzone> egl_implementation_;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WINDOWS_WINDOWS_SURFACE_FACTORY_H_
diff --git a/chromium/ui/ozone/platform/windows/windows_window.cc b/chromium/ui/ozone/platform/windows/windows_window.cc
deleted file mode 100644
index 1e0ecdc03e5..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_window.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/windows/windows_window.h"
-
-#include <string>
-
-#include "build/build_config.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/ozone/platform/windows/windows_window_manager.h"
-
-namespace ui {
-
-WindowsWindow::WindowsWindow(PlatformWindowDelegate* delegate,
- const gfx::Rect& bounds)
- : WinWindow(delegate, bounds) {}
-
-WindowsWindow::~WindowsWindow() {}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/windows_window.h b/chromium/ui/ozone/platform/windows/windows_window.h
deleted file mode 100644
index 0641d7fbf2e..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_window.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_H_
-#define UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_H_
-
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/platform_window/platform_window_delegate.h"
-#include "ui/platform_window/win/win_window.h"
-
-namespace ui {
-
-class WindowsWindow : public WinWindow {
- public:
- WindowsWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
-
- WindowsWindow(const WindowsWindow&) = delete;
- WindowsWindow& operator=(const WindowsWindow&) = delete;
-
- ~WindowsWindow() override;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_H_
diff --git a/chromium/ui/ozone/platform/windows/windows_window_manager.cc b/chromium/ui/ozone/platform/windows/windows_window_manager.cc
deleted file mode 100644
index c9a4858feee..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_window_manager.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/windows/windows_window_manager.h"
-
-namespace ui {
-
-WindowsWindowManager::WindowsWindowManager() = default;
-
-WindowsWindowManager::~WindowsWindowManager() {}
-
-int32_t WindowsWindowManager::AddWindow(WindowsWindow* window) {
- return windows_.Add(window);
-}
-
-void WindowsWindowManager::RemoveWindow(int32_t window_id,
- WindowsWindow* window) {
- DCHECK_EQ(window, windows_.Lookup(window_id));
- windows_.Remove(window_id);
-}
-
-WindowsWindow* WindowsWindowManager::GetWindow(int32_t window_id) {
- return windows_.Lookup(window_id);
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/windows/windows_window_manager.h b/chromium/ui/ozone/platform/windows/windows_window_manager.h
deleted file mode 100644
index 9f516fbcb1f..00000000000
--- a/chromium/ui/ozone/platform/windows/windows_window_manager.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_MANAGER_H_
-#define UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_MANAGER_H_
-
-#include <stdint.h>
-
-#include "base/containers/id_map.h"
-#include "base/threading/thread_checker.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-
-namespace ui {
-
-class WindowsWindow;
-
-class WindowsWindowManager {
- public:
- WindowsWindowManager();
-
- WindowsWindowManager(const WindowsWindowManager&) = delete;
- WindowsWindowManager& operator=(const WindowsWindowManager&) = delete;
-
- ~WindowsWindowManager();
-
- // Register a new window. Returns the window id.
- int32_t AddWindow(WindowsWindow* window);
-
- // Remove a window.
- void RemoveWindow(int32_t window_id, WindowsWindow* window);
-
- // Find a window object by id;
- WindowsWindow* GetWindow(int32_t window_id);
-
- private:
- base::IDMap<WindowsWindow*> windows_;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WINDOWS_WINDOWS_WINDOW_MANAGER_H_
diff --git a/chromium/ui/ozone/platform/x11/BUILD.gn b/chromium/ui/ozone/platform/x11/BUILD.gn
index dd65850ec13..b1180a85530 100644
--- a/chromium/ui/ozone/platform/x11/BUILD.gn
+++ b/chromium/ui/ozone/platform/x11/BUILD.gn
@@ -42,8 +42,6 @@ source_set("x11") {
"x11_screen_ozone.h",
"x11_surface_factory.cc",
"x11_surface_factory.h",
- "x11_topmost_window_finder.cc",
- "x11_topmost_window_finder.h",
"x11_user_input_monitor.cc",
"x11_user_input_monitor.h",
"x11_utils.cc",
@@ -165,7 +163,7 @@ source_set("x11_unittests") {
"//ui/ozone/common",
]
- if (!is_chromeos && !is_chromeos_ash && !is_chromeos_lacros) {
+ if (!is_chromeos && !is_chromeos) {
sources += [ "test/os_exchange_data_provider_x11_unittest.cc" ]
deps += [ "//ui/base/clipboard:clipboard_types" ]
@@ -193,24 +191,3 @@ source_set("test_support") {
"//ui/base/x:test_support",
]
}
-
-source_set("interactive_uitests") {
- testonly = true
- sources = [ "x11_topmost_window_finder_interactive_uitest.cc" ]
-
- deps = [
- ":x11",
- "//base",
- "//base/test:test_support",
- "//testing/gmock",
- "//testing/gtest",
- "//ui/base/x",
- "//ui/base/x:test_support",
- "//ui/events/platform/x11",
- "//ui/gfx",
- "//ui/gfx/x",
- "//ui/ozone",
- "//ui/ozone:platform",
- "//ui/platform_window",
- ]
-}
diff --git a/chromium/ui/ozone/platform/x11/test/events_x_unittest.cc b/chromium/ui/ozone/platform/x11/test/events_x_unittest.cc
index 86964207bbc..125ecac8d64 100644
--- a/chromium/ui/ozone/platform/x11/test/events_x_unittest.cc
+++ b/chromium/ui/ozone/platform/x11/test/events_x_unittest.cc
@@ -783,17 +783,14 @@ TEST_F(EventsXTest, EventLatencyOSTouchHistograms) {
scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchBegin, 5,
gfx::Point(10, 10), {});
auto touch_begin = ui::BuildTouchEventFromXEvent(*scoped_xevent);
- histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_PRESSED", 1);
histogram_tester.ExpectTotalCount("Event.Latency.OS2.TOUCH_PRESSED", 1);
scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchUpdate, 5,
gfx::Point(20, 20), {});
auto touch_update = ui::BuildTouchEventFromXEvent(*scoped_xevent);
- histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_MOVED", 1);
histogram_tester.ExpectTotalCount("Event.Latency.OS2.TOUCH_MOVED", 1);
scoped_xevent.InitTouchEvent(0, x11::Input::DeviceEvent::TouchEnd, 5,
gfx::Point(30, 30), {});
auto touch_end = ui::BuildTouchEventFromXEvent(*scoped_xevent);
- histogram_tester.ExpectTotalCount("Event.Latency.OS.TOUCH_RELEASED", 1);
histogram_tester.ExpectTotalCount("Event.Latency.OS2.TOUCH_RELEASED", 1);
}
@@ -809,7 +806,6 @@ TEST_F(EventsXTest, EventLatencyOSMouseWheelHistogram) {
.detail = static_cast<x11::Button>(4),
});
auto mouse_ev = ui::BuildMouseWheelEventFromXEvent(native_event);
- histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
histogram_tester.ExpectTotalCount("Event.Latency.OS2.MOUSE_WHEEL", 1);
}
diff --git a/chromium/ui/ozone/platform/x11/test/x11_drag_drop_client_unittest.cc b/chromium/ui/ozone/platform/x11/test/x11_drag_drop_client_unittest.cc
index e4e915b8e50..e4f8670646a 100644
--- a/chromium/ui/ozone/platform/x11/test/x11_drag_drop_client_unittest.cc
+++ b/chromium/ui/ozone/platform/x11/test/x11_drag_drop_client_unittest.cc
@@ -19,6 +19,8 @@
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@@ -128,7 +130,7 @@ class SimpleTestDragDropClient : public XDragDropClient,
private:
// XDragDropClient::Delegate:
- std::unique_ptr<XTopmostWindowFinder> CreateWindowFinder() override;
+ absl::optional<gfx::AcceleratedWidget> GetDragWidget() override;
int UpdateDrag(const gfx::Point& screen_point) override;
void UpdateCursor(DragOperation negotiated_operation) override;
void OnBeginForeignDrag(x11::Window window) override;
@@ -314,14 +316,15 @@ DragOperation SimpleTestDragDropClient::StartDragAndDrop(
return resulting_operation;
}
+absl::optional<gfx::AcceleratedWidget>
+SimpleTestDragDropClient::GetDragWidget() {
+ return absl::nullopt;
+}
+
int SimpleTestDragDropClient::UpdateDrag(const gfx::Point& screen_point) {
return 0;
}
-std::unique_ptr<XTopmostWindowFinder>
-SimpleTestDragDropClient::CreateWindowFinder() {
- return {};
-}
void SimpleTestDragDropClient::UpdateCursor(
DragOperation negotiated_operation) {}
void SimpleTestDragDropClient::OnBeginForeignDrag(x11::Window window) {}
diff --git a/chromium/ui/ozone/platform/x11/test/x11_window_unittest.cc b/chromium/ui/ozone/platform/x11/test/x11_window_unittest.cc
index f6e41d42bd7..b4fc4d623a7 100644
--- a/chromium/ui/ozone/platform/x11/test/x11_window_unittest.cc
+++ b/chromium/ui/ozone/platform/x11/test/x11_window_unittest.cc
@@ -169,7 +169,7 @@ class TestScreen : public display::ScreenBase {
display.SetScaleAndBounds(scale, bounds_in_pixels);
ProcessDisplayChanged(display, true);
}
-}; // namespace
+};
// Returns the list of rectangles which describe |window|'s bounding region via
// the X shape extension.
diff --git a/chromium/ui/ozone/platform/x11/vulkan_surface_x11.cc b/chromium/ui/ozone/platform/x11/vulkan_surface_x11.cc
index 5a94e513688..7f7a6ca796b 100644
--- a/chromium/ui/ozone/platform/x11/vulkan_surface_x11.cc
+++ b/chromium/ui/ozone/platform/x11/vulkan_surface_x11.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "ui/base/x/x11_util.h"
+#include "ui/base/x/x11_xrandr_interval_only_vsync_provider.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/x11_window_event_manager.h"
@@ -39,9 +40,6 @@ std::unique_ptr<VulkanSurfaceX11> VulkanSurfaceX11::Create(
LOG(ERROR) << "Failed to create or map window.";
return nullptr;
}
- // Flush the connection, otherwise other Vulkan WSI calls may fail with some
- // drivers.
- connection->Flush();
VkSurfaceKHR vk_surface;
const VkXcbSurfaceCreateInfoKHR surface_create_info = {
@@ -72,11 +70,13 @@ VulkanSurfaceX11::VulkanSurfaceX11(VkInstance vk_instance,
VkSurfaceKHR vk_surface,
x11::Window parent_window,
x11::Window window)
- : gpu::VulkanSurface(vk_instance,
- static_cast<gfx::AcceleratedWidget>(window),
- vk_surface,
- base::Time::kNanosecondsPerSecond *
- 2 /* acquire_next_image_timeout_ns */),
+ : gpu::VulkanSurface(
+ vk_instance,
+ static_cast<gfx::AcceleratedWidget>(window),
+ vk_surface,
+ /*acquire_next_image_timeout_ns=*/base::Time::kNanosecondsPerSecond *
+ 2,
+ std::make_unique<ui::XrandrIntervalOnlyVSyncProvider>()),
parent_window_(parent_window),
window_(window),
event_selector_(std::make_unique<x11::XScopedEventSelector>(
diff --git a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
index f69a5443e5b..9a7240a1eac 100644
--- a/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
+++ b/chromium/ui/ozone/platform/x11/x11_screen_ozone.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/platform/x11/x11_screen_ozone.h"
+#include "base/containers/flat_set.h"
#include "ui/base/linux/linux_desktop.h"
#include "ui/base/x/x11_idle_query.h"
#include "ui/base/x/x11_screensaver.h"
@@ -16,27 +17,28 @@
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/platform/x11/x11_topmost_window_finder.h"
+#include "ui/gfx/x/window_cache.h"
#include "ui/ozone/platform/x11/x11_window.h"
#include "ui/ozone/platform/x11/x11_window_manager.h"
namespace ui {
X11ScreenOzone::X11ScreenOzone()
- : window_manager_(X11WindowManager::GetInstance()),
+ : connection_(x11::Connection::Get()),
+ window_manager_(X11WindowManager::GetInstance()),
x11_display_manager_(std::make_unique<XDisplayManager>(this)) {
DCHECK(window_manager_);
}
X11ScreenOzone::~X11ScreenOzone() {
if (x11_display_manager_->IsXrandrAvailable())
- x11::Connection::Get()->RemoveEventObserver(this);
+ connection_->RemoveEventObserver(this);
}
void X11ScreenOzone::Init() {
initialized_ = true;
if (x11_display_manager_->IsXrandrAvailable())
- x11::Connection::Get()->AddEventObserver(this);
+ connection_->AddEventObserver(this);
x11_display_manager_->Init();
}
@@ -79,23 +81,41 @@ gfx::Point X11ScreenOzone::GetCursorScreenPoint() const {
gfx::ConvertPointToDips(*point_in_pixels, GetXDisplayScaleFactor()));
}
+bool X11ScreenOzone::IsAcceleratedWidgetUnderCursor(
+ gfx::AcceleratedWidget widget) const {
+ // Only ask the X11Window for its pointer state when some other window does
+ // not have mouse capture because capture disrupts pointer event tracking.
+ if (!window_manager_->located_events_grabber()) {
+ if (X11Window* window = window_manager_->GetWindow(widget))
+ return window->has_pointer();
+ }
+ return GetAcceleratedWidgetAtScreenPoint(GetCursorScreenPoint()) == widget;
+}
+
gfx::AcceleratedWidget X11ScreenOzone::GetAcceleratedWidgetAtScreenPoint(
const gfx::Point& point) const {
gfx::Point point_in_pixels = gfx::ToFlooredPoint(
gfx::ConvertPointToPixels(point, GetXDisplayScaleFactor()));
- X11TopmostWindowFinder finder({});
return static_cast<gfx::AcceleratedWidget>(
- finder.FindWindowAt(point_in_pixels));
+ x11::GetWindowAtPoint(point_in_pixels));
}
gfx::AcceleratedWidget X11ScreenOzone::GetLocalProcessWidgetAtPoint(
const gfx::Point& point,
const std::set<gfx::AcceleratedWidget>& ignore) const {
- gfx::Point point_in_pixels = gfx::ToFlooredPoint(
- gfx::ConvertPointToPixels(point, GetXDisplayScaleFactor()));
- X11TopmostWindowFinder finder(ignore);
- return static_cast<gfx::AcceleratedWidget>(
- finder.FindLocalProcessWindowAt(point_in_pixels));
+ gfx::AcceleratedWidget widget{};
+ if (ignore.empty()) {
+ widget = GetAcceleratedWidgetAtScreenPoint(point);
+ } else {
+ gfx::Point point_in_pixels = gfx::ToFlooredPoint(
+ gfx::ConvertPointToPixels(point, GetXDisplayScaleFactor()));
+ base::flat_set<x11::Window> ignore_windows;
+ for (auto widget : ignore)
+ ignore_windows.insert(static_cast<x11::Window>(widget));
+ widget = static_cast<gfx::AcceleratedWidget>(
+ x11::GetWindowAtPoint(point_in_pixels, &ignore_windows));
+ }
+ return window_manager_->GetWindow(widget) ? widget : gfx::AcceleratedWidget{};
}
display::Display X11ScreenOzone::GetDisplayNearestPoint(
diff --git a/chromium/ui/ozone/platform/x11/x11_screen_ozone.h b/chromium/ui/ozone/platform/x11/x11_screen_ozone.h
index c197be1f59b..d86acae9aa9 100644
--- a/chromium/ui/ozone/platform/x11/x11_screen_ozone.h
+++ b/chromium/ui/ozone/platform/x11/x11_screen_ozone.h
@@ -39,6 +39,8 @@ class X11ScreenOzone : public PlatformScreen,
display::Display GetDisplayForAcceleratedWidget(
gfx::AcceleratedWidget widget) const override;
gfx::Point GetCursorScreenPoint() const override;
+ bool IsAcceleratedWidgetUnderCursor(
+ gfx::AcceleratedWidget widget) const override;
gfx::AcceleratedWidget GetAcceleratedWidgetAtScreenPoint(
const gfx::Point& point) const override;
gfx::AcceleratedWidget GetLocalProcessWidgetAtPoint(
@@ -70,6 +72,7 @@ class X11ScreenOzone : public PlatformScreen,
gfx::Point GetCursorLocation() const;
+ x11::Connection* const connection_;
X11WindowManager* const window_manager_;
std::unique_ptr<ui::XDisplayManager> x11_display_manager_;
diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
index c915c87be7f..67c8073143f 100644
--- a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
+++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -107,8 +107,7 @@ X11SurfaceFactory::GetAllowedGLImplementations() {
gl::GLImplementationParts(gl::kGLImplementationDesktopGL),
gl::GLImplementationParts(gl::kGLImplementationEGLGLES2),
gl::GLImplementationParts(gl::kGLImplementationEGLANGLE),
- gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader),
- gl::GLImplementationParts(gl::kGLImplementationSwiftShaderGL)};
+ gl::GLImplementationParts(gl::ANGLEImplementation::kSwiftShader)};
}
GLOzone* X11SurfaceFactory::GetGLOzone(
@@ -118,7 +117,6 @@ GLOzone* X11SurfaceFactory::GetGLOzone(
return glx_implementation_.get();
case gl::kGLImplementationEGLGLES2:
case gl::kGLImplementationEGLANGLE:
- case gl::kGLImplementationSwiftShaderGL:
return egl_implementation_.get();
default:
return nullptr;
diff --git a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.cc b/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.cc
deleted file mode 100644
index e5e051c0f63..00000000000
--- a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/x11/x11_topmost_window_finder.h"
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/bind.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/gfx/x/xproto_util.h"
-#include "ui/ozone/platform/x11/x11_window.h"
-#include "ui/ozone/platform/x11/x11_window_manager.h"
-
-namespace ui {
-
-namespace {
-
-using ShouldStopIteratingCallback = base::RepeatingCallback<bool(x11::Window)>;
-
-// Returns true if |window| is a named window.
-bool IsWindowNamed(x11::Window window) {
- return PropertyExists(window, x11::Atom::WM_NAME);
-}
-
-bool EnumerateChildren(ShouldStopIteratingCallback should_stop_iterating,
- x11::Window window,
- const int max_depth,
- int depth) {
- if (depth > max_depth)
- return false;
-
- auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync();
- if (!query_tree)
- return false;
- std::vector<x11::Window> windows = std::move(query_tree->children);
-
- // XQueryTree returns the children of |window| in bottom-to-top order, so
- // reverse-iterate the list to check the windows from top-to-bottom.
- std::vector<x11::Window>::reverse_iterator iter;
- for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
- if (depth < max_depth) {
- if (EnumerateChildren(should_stop_iterating, *iter, max_depth, depth + 1))
- return true;
- }
- if (IsWindowNamed(*iter) && should_stop_iterating.Run(*iter))
- return true;
- }
-
- return false;
-}
-
-bool EnumerateAllWindows(ShouldStopIteratingCallback should_stop_iterating,
- int max_depth) {
- x11::Window root = GetX11RootWindow();
- return EnumerateChildren(should_stop_iterating, root, max_depth, 0);
-}
-
-void EnumerateTopLevelWindows(
- ui::ShouldStopIteratingCallback should_stop_iterating) {
- // WMs may reparent toplevel windows inside their own containers, so extend
- // the search to all grandchildren of all toplevel windows.
- const int kMaxSearchDepth = 2;
- ui::EnumerateAllWindows(should_stop_iterating, kMaxSearchDepth);
-}
-
-} // namespace
-
-X11TopmostWindowFinder::X11TopmostWindowFinder(
- const std::set<gfx::AcceleratedWidget>& ignore)
- : ignore_(ignore) {}
-
-X11TopmostWindowFinder::~X11TopmostWindowFinder() = default;
-
-x11::Window X11TopmostWindowFinder::FindLocalProcessWindowAt(
- const gfx::Point& screen_loc_in_pixels) {
- screen_loc_in_pixels_ = screen_loc_in_pixels;
-
- std::vector<X11Window*> local_process_windows =
- X11WindowManager::GetInstance()->GetAllOpenWindows();
- if (std::none_of(local_process_windows.cbegin(), local_process_windows.cend(),
- [this](auto* window) {
- return ShouldStopIteratingAtLocalProcessWindow(window);
- })) {
- return x11::Window::None;
- }
-
- EnumerateTopLevelWindows(base::BindRepeating(
- &X11TopmostWindowFinder::ShouldStopIterating, base::Unretained(this)));
- return toplevel_;
-}
-
-x11::Window X11TopmostWindowFinder::FindWindowAt(
- const gfx::Point& screen_loc_in_pixels) {
- screen_loc_in_pixels_ = screen_loc_in_pixels;
- EnumerateTopLevelWindows(base::BindRepeating(
- &X11TopmostWindowFinder::ShouldStopIterating, base::Unretained(this)));
- return toplevel_;
-}
-
-bool X11TopmostWindowFinder::ShouldStopIterating(x11::Window xwindow) {
- if (!IsWindowVisible(xwindow))
- return false;
-
- auto* window = X11WindowManager::GetInstance()->GetWindow(
- static_cast<gfx::AcceleratedWidget>(xwindow));
- if (window) {
- if (ShouldStopIteratingAtLocalProcessWindow(window)) {
- toplevel_ = xwindow;
- return true;
- }
- return false;
- }
-
- if (WindowContainsPoint(xwindow, screen_loc_in_pixels_)) {
- toplevel_ = xwindow;
- return true;
- }
- return false;
-}
-
-bool X11TopmostWindowFinder::ShouldStopIteratingAtLocalProcessWindow(
- X11Window* window) {
- if (ignore_.find(window->GetWidget()) != ignore_.end())
- return false;
-
- // Currently |window|->IsVisible() always returns true.
- // TODO(pkotwicz): Fix this. crbug.com/353038
- if (!window->IsVisible())
- return false;
-
- gfx::Rect window_bounds = window->GetOuterBounds();
- if (!window_bounds.Contains(screen_loc_in_pixels_))
- return false;
-
- gfx::Point window_point(screen_loc_in_pixels_);
- window_point.Offset(-window_bounds.origin().x(), -window_bounds.origin().y());
- return window->ContainsPointInXRegion(window_point);
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.h b/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.h
deleted file mode 100644
index 934045c6e72..00000000000
--- a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_X11_X11_TOPMOST_WINDOW_FINDER_H_
-#define UI_OZONE_PLATFORM_X11_X11_TOPMOST_WINDOW_FINDER_H_
-
-#include <set>
-
-#include "ui/base/x/x11_topmost_window_finder.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace ui {
-
-class X11Window;
-
-// Utility class for finding the topmost window at a given screen position.
-class X11TopmostWindowFinder : public ui::XTopmostWindowFinder {
- public:
- // Create finder, specifying a set of windows to |ignore|.
- explicit X11TopmostWindowFinder(
- const std::set<gfx::AcceleratedWidget>& ignore);
-
- X11TopmostWindowFinder(const X11TopmostWindowFinder&) = delete;
- X11TopmostWindowFinder& operator=(const X11TopmostWindowFinder&) = delete;
-
- ~X11TopmostWindowFinder() override;
-
- // Returns the topmost window at |screen_loc_in_pixels|. Returns null widget
- // if the topmost window at |screen_loc_in_pixels| does not belong to Chrome.
- x11::Window FindLocalProcessWindowAt(const gfx::Point& screen_loc_in_pixels);
-
- // Returns the topmost window at |screen_loc_in_pixels|.
- x11::Window FindWindowAt(const gfx::Point& screen_loc_in_pixels) override;
-
- private:
- bool ShouldStopIterating(x11::Window window);
-
- // Returns true if |window| does not not belong to |ignore|, is visible and
- // contains |screen_loc_|.
- bool ShouldStopIteratingAtLocalProcessWindow(ui::X11Window* window);
-
- gfx::Point screen_loc_in_pixels_;
- std::set<gfx::AcceleratedWidget> ignore_;
- x11::Window toplevel_ = x11::Window::None;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_X11_X11_TOPMOST_WINDOW_FINDER_H_
diff --git a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder_interactive_uitest.cc b/chromium/ui/ozone/platform/x11/x11_topmost_window_finder_interactive_uitest.cc
deleted file mode 100644
index 346a45ef8c5..00000000000
--- a/chromium/ui/ozone/platform/x11/x11_topmost_window_finder_interactive_uitest.cc
+++ /dev/null
@@ -1,504 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/x11/x11_topmost_window_finder.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-#include "base/containers/contains.h"
-#include "base/test/task_environment.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/base/x/test/x11_property_change_waiter.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/events/platform/x11/x11_event_source.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/x/connection.h"
-#include "ui/gfx/x/event.h"
-#include "ui/gfx/x/shape.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/gfx/x/x11_path.h"
-#include "ui/gfx/x/xproto.h"
-#include "ui/gfx/x/xproto_util.h"
-#include "ui/ozone/platform/x11/x11_window.h"
-#include "ui/ozone/platform/x11/x11_window_manager.h"
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/platform_window/platform_window_init_properties.h"
-
-namespace ui {
-
-namespace {
-
-// Waits until the |x11_window| is mapped and becomes viewable.
-class X11VisibilityWaiter : public x11::EventObserver {
- public:
- X11VisibilityWaiter() = default;
- X11VisibilityWaiter(const X11VisibilityWaiter&) = delete;
- X11VisibilityWaiter& operator=(const X11VisibilityWaiter&) = delete;
- ~X11VisibilityWaiter() override = default;
-
- void WaitUntilWindowIsVisible(x11::Window x11_window) {
- if (IsWindowVisible(x11_window))
- return;
-
- event_selector_ = std::make_unique<x11::XScopedEventSelector>(
- x11_window,
- x11::EventMask::StructureNotify | x11::EventMask::SubstructureNotify);
- x11_window_ = x11_window;
-
- x11::Connection::Get()->AddEventObserver(this);
-
- base::RunLoop run_loop;
- quit_closure_ = run_loop.QuitClosure();
- run_loop.Run();
- DCHECK(IsWindowVisible(x11_window));
- }
-
- private:
- // x11::EventObserver:
- void OnEvent(const x11::Event& event) override {
- auto* map = event.As<x11::MapNotifyEvent>();
- if (map && map->window == x11_window_) {
- DCHECK(!quit_closure_.is_null());
- std::move(quit_closure_).Run();
- x11::Connection::Get()->RemoveEventObserver(this);
- }
- }
-
- x11::Window x11_window_;
- std::unique_ptr<x11::XScopedEventSelector> event_selector_;
- // Ends the run loop.
- base::OnceClosure quit_closure_;
-};
-
-class TestPlatformWindowDelegate : public PlatformWindowDelegate {
- public:
- TestPlatformWindowDelegate() = default;
- TestPlatformWindowDelegate(const TestPlatformWindowDelegate&) = delete;
- TestPlatformWindowDelegate& operator=(const TestPlatformWindowDelegate&) =
- delete;
- ~TestPlatformWindowDelegate() override = default;
-
- PlatformWindowState state() { return state_; }
-
- // PlatformWindowDelegate:
- void OnBoundsChanged(const BoundsChange& change) override {}
- void OnDamageRect(const gfx::Rect& damaged_region) override {}
- void DispatchEvent(Event* event) override {}
- void OnCloseRequest() override {}
- void OnClosed() override {}
- void OnWindowStateChanged(PlatformWindowState old_state,
- PlatformWindowState new_state) override {
- state_ = new_state;
- }
- void OnLostCapture() override {}
- void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override {
- widget_ = widget;
- }
- void OnWillDestroyAcceleratedWidget() override {}
- void OnAcceleratedWidgetDestroyed() override {
- widget_ = gfx::kNullAcceleratedWidget;
- }
- void OnActivationChanged(bool active) override {}
- void OnMouseEnter() override {}
-
- private:
- gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
- PlatformWindowState state_ = PlatformWindowState::kUnknown;
-};
-
-// Waits till |window| is minimized.
-class MinimizeWaiter : public X11PropertyChangeWaiter {
- public:
- explicit MinimizeWaiter(x11::Window window)
- : X11PropertyChangeWaiter(window, "_NET_WM_STATE") {}
-
- MinimizeWaiter(const MinimizeWaiter&) = delete;
- MinimizeWaiter& operator=(const MinimizeWaiter&) = delete;
-
- ~MinimizeWaiter() override = default;
-
- private:
- // X11PropertyChangeWaiter:
- bool ShouldKeepOnWaiting() override {
- std::vector<x11::Atom> wm_states;
- if (GetArrayProperty(xwindow(), x11::GetAtom("_NET_WM_STATE"),
- &wm_states)) {
- return !base::Contains(wm_states, x11::GetAtom("_NET_WM_STATE_HIDDEN"));
- }
- return true;
- }
-};
-
-void IconifyWindow(x11::Connection* connection, x11::Window window) {
- SendClientMessage(window, GetX11RootWindow(), x11::GetAtom("WM_CHANGE_STATE"),
- {WM_STATE_ICONIC, 0, 0, 0, 0});
-}
-
-} // namespace
-
-class X11TopmostWindowFinderTest : public testing::Test {
- public:
- X11TopmostWindowFinderTest()
- : task_env_(base::test::TaskEnvironment::MainThreadType::UI) {}
-
- X11TopmostWindowFinderTest(const X11TopmostWindowFinderTest&) = delete;
- X11TopmostWindowFinderTest& operator=(const X11TopmostWindowFinderTest&) =
- delete;
-
- ~X11TopmostWindowFinderTest() override = default;
-
- // testing::Test:
- void SetUp() override {
- // Run tests only for X11.
- if (OzonePlatform::GetPlatformNameForTest() != "x11")
- GTEST_SKIP();
-
- auto* connection = x11::Connection::Get();
- // Not initialized when runs on CrOS builds.
- if (!X11EventSource::GetInstance())
- event_source_ = std::make_unique<X11EventSource>(connection);
- // Make X11 synchronous for our display connection. This does not force the
- // window manager to behave synchronously.
- connection->SynchronizeForTest(true);
- testing::Test::SetUp();
- }
-
- void TearDown() override {
- if (!IsSkipped())
- connection()->SynchronizeForTest(false);
- }
-
- // Creates and shows an X11Window with |bounds|. The caller takes ownership of
- // the returned window.
- std::unique_ptr<X11Window> CreateAndShowX11Window(
- PlatformWindowDelegate* delegate,
- const gfx::Rect& bounds) {
- PlatformWindowInitProperties init_params(bounds);
- init_params.type = PlatformWindowType::kWindow;
- init_params.remove_standard_frame = true;
- auto window = std::make_unique<X11Window>(delegate);
- window->Initialize(std::move(init_params));
- window->Show(true);
- // The window must have a title. Otherwise, the X11TopmostWindowFinder
- // refuses to use this window.
- window->SetTitle(u"X11FinderTest");
-
- // Wait until the window becomes visible so that window finder doesn't skip
- // these windows (it's required to wait because mapping and searching for
- // toplevel window is a subject to races).
- X11VisibilityWaiter waiter;
- waiter.WaitUntilWindowIsVisible(
- static_cast<x11::Window>(window->GetWidget()));
- return window;
- }
-
- // Creates and shows an X window with |bounds|.
- x11::Window CreateAndShowXWindow(const gfx::Rect& bounds) {
- x11::Window root = GetX11RootWindow();
- auto window = connection()->GenerateId<x11::Window>();
- connection()->CreateWindow({
- .wid = window,
- .parent = root,
- .width = 1,
- .height = 1,
- });
-
- // This is necessary because X11TopmostWindowFinder skips over unnamed
- // windows.
- SetStringProperty(window, x11::Atom::WM_NAME, x11::Atom::STRING, "");
-
- SetUseOSWindowFrame(window, false);
- ShowAndSetXWindowBounds(window, bounds);
-
- // Wait until the window becomes visible so that window finder doesn't skip
- // these windows (it's required to wait because mapping and searching for
- // toplevel window is a subject to races).
- X11VisibilityWaiter waiter;
- waiter.WaitUntilWindowIsVisible(static_cast<x11::Window>(window));
- return window;
- }
-
- // Shows |window| and sets its bounds.
- void ShowAndSetXWindowBounds(x11::Window window, const gfx::Rect& bounds) {
- connection()->MapWindow({window});
-
- connection()->ConfigureWindow({
- .window = window,
- .x = bounds.x(),
- .y = bounds.y(),
- .width = bounds.width(),
- .height = bounds.height(),
- });
- }
-
- x11::Connection* connection() { return x11::Connection::Get(); }
-
- // Returns the topmost X window at the passed in screen position.
- x11::Window FindTopmostXWindowAt(int screen_x, int screen_y) {
- X11TopmostWindowFinder finder({});
- return finder.FindWindowAt(gfx::Point(screen_x, screen_y));
- }
-
- // Returns the topmost X window at the passed in screen position ignoring
- // |ignore_window|.
- x11::Window FindTopmostXWindowWithIgnore(int screen_x,
- int screen_y,
- x11::Window ignore_window) {
- std::set<gfx::AcceleratedWidget> ignore;
- ignore.insert(static_cast<gfx::AcceleratedWidget>(ignore_window));
- X11TopmostWindowFinder finder(ignore);
- return finder.FindWindowAt(gfx::Point(screen_x, screen_y));
- }
-
- // Returns the topmost X11Window at the passed in screen position. Returns
- // nullptr if the topmost window does not have an associated X11Window.
- X11Window* FindTopmostLocalProcessWindowAt(int screen_x, int screen_y) {
- X11TopmostWindowFinder finder({});
- auto x11_window =
- finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y));
- return x11_window == x11::Window::None
- ? nullptr
- : X11WindowManager::GetInstance()->GetWindow(
- static_cast<gfx::AcceleratedWidget>(x11_window));
- }
-
- // Returns the topmost X11Window at the passed in screen position ignoring
- // |ignore_window|. Returns nullptr if the topmost window does not have an
- // associated X11Window.
- X11Window* FindTopmostLocalProcessWindowWithIgnore(
- int screen_x,
- int screen_y,
- x11::Window ignore_window) {
- std::set<gfx::AcceleratedWidget> ignore;
- ignore.insert(static_cast<gfx::AcceleratedWidget>(ignore_window));
- X11TopmostWindowFinder finder(ignore);
- auto x11_window =
- finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y));
- return x11_window == x11::Window::None
- ? nullptr
- : X11WindowManager::GetInstance()->GetWindow(
- static_cast<gfx::AcceleratedWidget>(x11_window));
- }
-
- private:
- base::test::TaskEnvironment task_env_;
- std::unique_ptr<X11EventSource> event_source_;
-};
-
-TEST_F(X11TopmostWindowFinderTest, Basic) {
- // Avoid positioning test windows at 0x0 because window managers often have a
- // panel/launcher along one of the screen edges and do not allow windows to
- // position themselves to overlap the panel/launcher.
- TestPlatformWindowDelegate delegate;
- auto window1 = CreateAndShowX11Window(&delegate, {100, 100, 200, 100});
- auto x11_window1 = static_cast<x11::Window>(window1->GetWidget());
-
- x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(200, 100, 100, 200));
-
- TestPlatformWindowDelegate delegate2;
- auto window3 = CreateAndShowX11Window(&delegate2, {100, 190, 200, 110});
- auto x11_window3 = static_cast<x11::Window>(window3->GetWidget());
-
- connection()->DispatchAll();
-
- EXPECT_EQ(x11_window1, FindTopmostXWindowAt(150, 150));
- EXPECT_EQ(window1.get(), FindTopmostLocalProcessWindowAt(150, 150));
-
- EXPECT_EQ(x11_window2, FindTopmostXWindowAt(250, 150));
- EXPECT_FALSE(FindTopmostLocalProcessWindowAt(250, 150));
-
- EXPECT_EQ(x11_window3, FindTopmostXWindowAt(250, 250));
- EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(250, 250));
-
- EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 250));
- EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(150, 250));
-
- EXPECT_EQ(x11_window3, FindTopmostXWindowAt(150, 195));
- EXPECT_EQ(window3.get(), FindTopmostLocalProcessWindowAt(150, 195));
-
- EXPECT_NE(x11_window1, FindTopmostXWindowAt(1000, 1000));
- EXPECT_NE(x11_window2, FindTopmostXWindowAt(1000, 1000));
- EXPECT_NE(x11_window3, FindTopmostXWindowAt(1000, 1000));
- EXPECT_FALSE(FindTopmostLocalProcessWindowAt(1000, 1000));
-
- EXPECT_EQ(x11_window1, FindTopmostXWindowWithIgnore(150, 150, x11_window3));
- EXPECT_EQ(window1.get(),
- FindTopmostLocalProcessWindowWithIgnore(150, 150, x11_window3));
- EXPECT_EQ(x11_window2, FindTopmostXWindowWithIgnore(250, 250, x11_window3));
- EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(250, 250, x11_window3));
- EXPECT_EQ(x11::Window::None,
- FindTopmostXWindowWithIgnore(150, 250, x11_window3));
- EXPECT_FALSE(FindTopmostLocalProcessWindowWithIgnore(150, 250, x11_window3));
- EXPECT_EQ(x11_window1, FindTopmostXWindowWithIgnore(150, 195, x11_window3));
- EXPECT_EQ(window1.get(),
- FindTopmostLocalProcessWindowWithIgnore(150, 195, x11_window3));
-
- connection()->DestroyWindow({x11_window2});
-}
-
-// Test that the minimized state is properly handled.
-// The test is flaky (https://crbug.com/955316)
-TEST_F(X11TopmostWindowFinderTest, DISABLED_Minimized) {
- TestPlatformWindowDelegate delegate;
- auto window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100});
- auto x11_window1 = static_cast<x11::Window>(window1->GetWidget());
- x11::Window x11_window2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
-
- connection()->DispatchAll();
-
- EXPECT_EQ(x11_window1, FindTopmostXWindowAt(150, 150));
- {
- MinimizeWaiter minimize_waiter(x11_window1);
- IconifyWindow(connection(), x11_window1);
- minimize_waiter.Wait();
- }
- EXPECT_NE(x11_window1, FindTopmostXWindowAt(150, 150));
- EXPECT_NE(x11_window2, FindTopmostXWindowAt(150, 150));
-
- // Repeat test for an X window which does not belong to a views::Widget
- // because the code path is different.
- EXPECT_EQ(x11_window2, FindTopmostXWindowAt(350, 150));
- {
- MinimizeWaiter minimize_waiter(x11_window2);
- IconifyWindow(connection(), x11_window2);
- minimize_waiter.Wait();
- }
- EXPECT_NE(x11_window1, FindTopmostXWindowAt(350, 150));
- EXPECT_NE(x11_window2, FindTopmostXWindowAt(350, 150));
-
- connection()->DestroyWindow({x11_window2});
-}
-
-// Test that non-rectangular windows are properly handled.
-TEST_F(X11TopmostWindowFinderTest, NonRectangular) {
- if (!IsShapeExtensionAvailable())
- return;
-
- TestPlatformWindowDelegate delegate;
- auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100});
- auto window1 = static_cast<x11::Window>(x11_window1->GetWidget());
- auto shape1 = std::make_unique<std::vector<gfx::Rect>>();
- shape1->emplace_back(0, 10, 10, 90);
- shape1->emplace_back(10, 0, 90, 100);
- gfx::Transform transform;
- transform.Scale(1.0f, 1.0f);
- x11_window1->SetShape(std::move(shape1), transform);
-
- SkRegion skregion2;
- skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
- skregion2.op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
- x11::Window window2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
- auto region2 = x11::CreateRegionFromSkRegion(skregion2);
- x11::Connection::Get()->shape().Rectangles({
- .operation = x11::Shape::So::Set,
- .destination_kind = x11::Shape::Sk::Bounding,
- .ordering = x11::ClipOrdering::YXBanded,
- .destination_window = window2,
- .rectangles = *region2,
- });
- connection()->DispatchAll();
-
- EXPECT_EQ(window1, FindTopmostXWindowAt(105, 120));
- EXPECT_NE(window1, FindTopmostXWindowAt(105, 105));
- EXPECT_NE(window2, FindTopmostXWindowAt(105, 105));
-
- // Repeat test for an X window which does not belong to a views::Widget
- // because the code path is different.
- EXPECT_EQ(window2, FindTopmostXWindowAt(305, 120));
- EXPECT_NE(window1, FindTopmostXWindowAt(305, 105));
- EXPECT_NE(window2, FindTopmostXWindowAt(305, 105));
-
- connection()->DestroyWindow({window2});
-}
-
-// Test that a window with an empty shape are properly handled.
-TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) {
- if (!IsShapeExtensionAvailable())
- return;
-
- TestPlatformWindowDelegate delegate;
- auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100});
- auto window1 = static_cast<x11::Window>(x11_window1->GetWidget());
-
- auto shape1 = std::make_unique<std::vector<gfx::Rect>>();
- shape1->emplace_back();
- gfx::Transform transform;
- transform.Scale(1.0f, 1.0f);
- x11_window1->SetShape(std::move(shape1), transform);
-
- connection()->DispatchAll();
-
- EXPECT_NE(window1, FindTopmostXWindowAt(105, 105));
-}
-
-// Test that setting a Null shape removes the shape.
-// crbug.com/955316: flaky on Linux
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#define MAYBE_NonRectangularNullShape DISABLED_NonRectangularNullShape
-#else
-#define MAYBE_NonRectangularNullShape NonRectangularNullShape
-#endif
-TEST_F(X11TopmostWindowFinderTest, MAYBE_NonRectangularNullShape) {
- if (!IsShapeExtensionAvailable())
- return;
-
- TestPlatformWindowDelegate delegate;
- auto x11_window1 = CreateAndShowX11Window(&delegate, {100, 100, 100, 100});
- auto window1 = static_cast<x11::Window>(x11_window1->GetWidget());
-
- auto shape1 = std::make_unique<std::vector<gfx::Rect>>();
- shape1->emplace_back();
- gfx::Transform transform;
- transform.Scale(1.0f, 1.0f);
- x11_window1->SetShape(std::move(shape1), transform);
-
- // Remove the shape - this is now just a normal window.
- x11_window1->SetShape(nullptr, transform);
-
- connection()->DispatchAll();
-
- EXPECT_EQ(window1, FindTopmostXWindowAt(105, 105));
-}
-
-// Test that the TopmostWindowFinder finds windows which belong to menus
-// (which may or may not belong to Chrome).
-//
-// Flakes (https://crbug.com/955316)
-TEST_F(X11TopmostWindowFinderTest, DISABLED_Menu) {
- x11::Window window = CreateAndShowXWindow(gfx::Rect(100, 100, 100, 100));
-
- x11::Window root = GetX11RootWindow();
- auto menu_window = connection()->GenerateId<x11::Window>();
- connection()->CreateWindow({
- .wid = menu_window,
- .parent = root,
- .width = 1,
- .height = 1,
- .c_class = x11::WindowClass::CopyFromParent,
- .override_redirect = x11::Bool32(true),
- });
-
- SetProperty(menu_window, x11::GetAtom("_NET_WM_WINDOW_TYPE"), x11::Atom::ATOM,
- x11::GetAtom("_NET_WM_WINDOW_TYPE_MENU"));
-
- SetUseOSWindowFrame(menu_window, false);
- ShowAndSetXWindowBounds(menu_window, gfx::Rect(140, 110, 100, 100));
- connection()->DispatchAll();
-
- EXPECT_EQ(window, FindTopmostXWindowAt(110, 110));
- EXPECT_EQ(menu_window, FindTopmostXWindowAt(150, 120));
- EXPECT_EQ(menu_window, FindTopmostXWindowAt(210, 120));
-
- connection()->DestroyWindow({window});
- connection()->DestroyWindow({menu_window});
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_window.cc b/chromium/ui/ozone/platform/x11/x11_window.cc
index 15b5f6ff21d..3f696838ee7 100644
--- a/chromium/ui/ozone/platform/x11/x11_window.cc
+++ b/chromium/ui/ozone/platform/x11/x11_window.cc
@@ -22,7 +22,6 @@
#include "ui/base/x/x11_cursor.h"
#include "ui/base/x/x11_os_exchange_data_provider.h"
#include "ui/base/x/x11_pointer_grab.h"
-#include "ui/base/x/x11_topmost_window_finder.h"
#include "ui/base/x/x11_util.h"
#include "ui/display/screen.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
@@ -34,13 +33,13 @@
#include "ui/events/x/events_x_utils.h"
#include "ui/events/x/x11_event_translation.h"
#include "ui/gfx/geometry/skia_conversions.h"
+#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_path.h"
#include "ui/gfx/x/x11_window_event_manager.h"
#include "ui/gfx/x/xproto.h"
#include "ui/gfx/x/xproto_util.h"
#include "ui/ozone/platform/x11/hit_test_x11.h"
-#include "ui/ozone/platform/x11/x11_topmost_window_finder.h"
#include "ui/ozone/platform/x11/x11_window_manager.h"
#include "ui/platform_window/common/platform_window_defaults.h"
#include "ui/platform_window/extensions/workspace_extension_delegate.h"
@@ -925,7 +924,7 @@ void X11Window::SetShape(std::unique_ptr<ShapeRects> native_shape,
SkPath path_in_dip;
if (native_region.getBoundaryPath(&path_in_dip)) {
SkPath path_in_pixels;
- path_in_dip.transform(SkMatrix(transform.matrix()), &path_in_pixels);
+ path_in_dip.transform(transform.matrix().asM33(), &path_in_pixels);
xregion = x11::CreateRegionFromSkPath(path_in_pixels);
} else {
xregion = std::make_unique<std::vector<x11::Rectangle>>();
@@ -1153,17 +1152,6 @@ gfx::Rect X11Window::GetXRootWindowOuterBounds() const {
return GetOuterBounds();
}
-bool X11Window::ContainsPointInXRegion(const gfx::Point& point) const {
- if (!shape())
- return true;
-
- for (const auto& rect : *shape()) {
- if (gfx::Rect(rect.x, rect.y, rect.width, rect.height).Contains(point))
- return true;
- }
- return false;
-}
-
void X11Window::LowerXWindow() {
ui::LowerWindow(xwindow_);
}
@@ -1468,13 +1456,9 @@ void X11Window::CancelDrag() {
QuitDragLoop();
}
-std::unique_ptr<XTopmostWindowFinder> X11Window::CreateWindowFinder() {
+absl::optional<gfx::AcceleratedWidget> X11Window::GetDragWidget() {
DCHECK(drag_handler_delegate_);
- std::set<gfx::AcceleratedWidget> ignore;
- auto drag_widget = drag_handler_delegate_->GetDragWidget();
- if (drag_widget)
- ignore.insert(*drag_widget);
- return std::make_unique<X11TopmostWindowFinder>(ignore);
+ return drag_handler_delegate_->GetDragWidget();
}
int X11Window::UpdateDrag(const gfx::Point& screen_point) {
@@ -2184,9 +2168,14 @@ void X11Window::OnWindowMapped() {
void X11Window::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure,
bool send_event) {
- DCHECK_EQ(xwindow_, configure.window);
DCHECK_EQ(xwindow_, configure.event);
+ // ConfigureNotifyEvent could be received for child windows. Ignore events for
+ // child windows.
+ if (xwindow_ != configure.window) {
+ return;
+ }
+
if (pending_counter_value_) {
DCHECK(!configure_counter_value_);
configure_counter_value_ = pending_counter_value_;
@@ -2290,7 +2279,7 @@ void X11Window::OnFrameExtentsUpdated() {
insets.size() == 4) {
// |insets| are returned in the order: [left, right, top, bottom].
native_window_frame_borders_in_pixels_ =
- gfx::Insets(insets[2], insets[0], insets[3], insets[1]);
+ gfx::Insets::TLBR(insets[2], insets[0], insets[3], insets[1]);
} else {
native_window_frame_borders_in_pixels_ = gfx::Insets();
}
diff --git a/chromium/ui/ozone/platform/x11/x11_window.h b/chromium/ui/ozone/platform/x11/x11_window.h
index 0b4ccfed941..81d42ae3167 100644
--- a/chromium/ui/ozone/platform/x11/x11_window.h
+++ b/chromium/ui/ozone/platform/x11/x11_window.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/cancelable_callback.h"
+#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
#include "ui/base/x/x11_desktop_window_move_client.h"
@@ -62,7 +63,6 @@ class X11Window : public PlatformWindow,
virtual void Initialize(PlatformWindowInitProperties properties);
// X11WindowManager calls this.
- // XWindow override:
void OnXWindowLostCapture();
void OnMouseEnter();
@@ -71,6 +71,8 @@ class X11Window : public PlatformWindow,
gfx::Rect GetOuterBounds() const;
void SetTransientWindow(x11::Window window);
+ bool has_pointer() const { return has_pointer_; }
+
// PlatformWindow:
void Show(bool inactive) override;
void Hide() override;
@@ -128,7 +130,6 @@ class X11Window : public PlatformWindow,
bool IsWmTiling() const override;
void OnCompleteSwapAfterResize() override;
gfx::Rect GetXRootWindowOuterBounds() const override;
- bool ContainsPointInXRegion(const gfx::Point& point) const override;
void LowerXWindow() override;
void SetOverrideRedirect(bool override_redirect) override;
bool CanResetOverrideRedirect() const override;
@@ -186,7 +187,7 @@ class X11Window : public PlatformWindow,
void CancelDrag() override;
// XDragDropClient::Delegate
- std::unique_ptr<XTopmostWindowFinder> CreateWindowFinder() override;
+ absl::optional<gfx::AcceleratedWidget> GetDragWidget() override;
int UpdateDrag(const gfx::Point& screen_point) override;
void UpdateCursor(mojom::DragOperation negotiated_operation) override;
void OnBeginForeignDrag(x11::Window window) override;
diff --git a/chromium/ui/ozone/platform/x11/x11_window_manager.cc b/chromium/ui/ozone/platform/x11/x11_window_manager.cc
index eaa7c5803c6..2db427e0fcd 100644
--- a/chromium/ui/ozone/platform/x11/x11_window_manager.cc
+++ b/chromium/ui/ozone/platform/x11/x11_window_manager.cc
@@ -87,7 +87,6 @@ void X11WindowManager::RemoveWindow(X11Window* window) {
}
X11Window* X11WindowManager::GetWindow(gfx::AcceleratedWidget widget) const {
- DCHECK_NE(gfx::kNullAcceleratedWidget, widget);
auto it = windows_.find(widget);
return it != windows_.end() ? it->second : nullptr;
}
@@ -100,11 +99,4 @@ void X11WindowManager::MouseOnWindow(X11Window* window) {
window->OnMouseEnter();
}
-std::vector<X11Window*> X11WindowManager::GetAllOpenWindows() const {
- std::vector<X11Window*> all_windows;
- for (const auto& item : windows_)
- all_windows.push_back(item.second);
- return all_windows;
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_window_manager.h b/chromium/ui/ozone/platform/x11/x11_window_manager.h
index 80e05108aee..0ca496cb4a5 100644
--- a/chromium/ui/ozone/platform/x11/x11_window_manager.h
+++ b/chromium/ui/ozone/platform/x11/x11_window_manager.h
@@ -47,8 +47,6 @@ class X11WindowManager {
return window_mouse_currently_on_;
}
- std::vector<X11Window*> GetAllOpenWindows() const;
-
private:
X11Window* located_events_grabber_ = nullptr;
X11Window* window_mouse_currently_on_ = nullptr;
diff --git a/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
index 2d02e1ef523..f130507c508 100644
--- a/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
+++ b/chromium/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
@@ -60,7 +60,7 @@ class TestScreen : public display::ScreenBase {
display.SetScaleAndBounds(scale, bounds_in_pixels);
ProcessDisplayChanged(display, true);
}
-}; // namespace
+};
} // namespace
diff --git a/chromium/ui/ozone/public/hardware_capabilities.h b/chromium/ui/ozone/public/hardware_capabilities.h
new file mode 100644
index 00000000000..16bebaf0545
--- /dev/null
+++ b/chromium/ui/ozone/public/hardware_capabilities.h
@@ -0,0 +1,23 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PUBLIC_HARDWARE_CAPABILITIES_H_
+#define UI_OZONE_PUBLIC_HARDWARE_CAPABILITIES_H_
+
+#include "base/callback.h"
+
+namespace ui {
+
+struct HardwareCapabilities {
+ // Number of planes available to the current CRTC(s).
+ // This is specifically the count of non-CURSOR planes, because some boards
+ // may have extra PRIMARY planes that could be used for overlays.
+ int num_overlay_capable_planes = 0;
+};
+using HardwareCapabilitiesCallback =
+ base::RepeatingCallback<void(HardwareCapabilities)>;
+
+} // namespace ui
+
+#endif // UI_OZONE_PUBLIC_HARDWARE_CAPABILITIES_H_
diff --git a/chromium/ui/ozone/public/overlay_candidates_ozone.cc b/chromium/ui/ozone/public/overlay_candidates_ozone.cc
index 29730279999..36be2a38f7b 100644
--- a/chromium/ui/ozone/public/overlay_candidates_ozone.cc
+++ b/chromium/ui/ozone/public/overlay_candidates_ozone.cc
@@ -13,6 +13,9 @@ void OverlayCandidatesOzone::CheckOverlaySupport(
NOTREACHED();
}
-OverlayCandidatesOzone::~OverlayCandidatesOzone() {}
+void OverlayCandidatesOzone::ObserveHardwareCapabilities(
+ ui::HardwareCapabilitiesCallback receive_callback) {}
+
+OverlayCandidatesOzone::~OverlayCandidatesOzone() = default;
} // namespace ui
diff --git a/chromium/ui/ozone/public/overlay_candidates_ozone.h b/chromium/ui/ozone/public/overlay_candidates_ozone.h
index 27e32a9abcf..f6d2db2eb98 100644
--- a/chromium/ui/ozone/public/overlay_candidates_ozone.h
+++ b/chromium/ui/ozone/public/overlay_candidates_ozone.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/component_export.h"
+#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_surface_candidate.h"
namespace ui {
@@ -27,6 +28,14 @@ class COMPONENT_EXPORT(OZONE_BASE) OverlayCandidatesOzone {
// if necessary.
virtual void CheckOverlaySupport(OverlaySurfaceCandidateList* surfaces);
+ // Register `receive_callback` to be called with the latest
+ // HardwareCapbalitites, whenever displays are configured.
+ // `receive_callback` may be called once after OverlayCandidatesOzone is
+ // destroyed if there is an in-flight callback, so it should be bound with a
+ // WeakPtr.
+ virtual void ObserveHardwareCapabilities(
+ ui::HardwareCapabilitiesCallback receive_callback);
+
// This should be invoked during overlay processing to indicate if there are
// any candidates for this processor that have an overlay requirement.
virtual void RegisterOverlayRequirement(bool requires_overlay) {}
diff --git a/chromium/ui/ozone/public/ozone_switches.cc b/chromium/ui/ozone/public/ozone_switches.cc
index 60ff1cd4763..1f6ccc48ff3 100644
--- a/chromium/ui/ozone/public/ozone_switches.cc
+++ b/chromium/ui/ozone/public/ozone_switches.cc
@@ -26,11 +26,6 @@ const char kDisableWaylandIme[] = "disable-wayland-ime";
// See https://crbug.com/1220274
const char kUseWaylandExplicitGrab[] = "use-wayland-explicit-grab";
-// Use normal priority (ThreadPriority::NORMAL) for Wayland event watcher
-// thread ("wayland-fd"). See https://crbug.com/1262133
-const char kUseWaylandNormalThreadPriority[] =
- "use-wayland-normal-thread-priority";
-
// Disable explicit DMA-fences
const char kDisableExplicitDmaFences[] = "disable-explicit-dma-fences";
@@ -44,4 +39,10 @@ const char kDisableBufferBWCompression[] = "disable-buffer-bw-compression";
// Specifies ozone screen size.
const char kOzoneOverrideScreenSize[] = "ozone-override-screen-size";
+// ChromeOS uses one of two VideoDecoder implementations based on SoC/board
+// specific configurations that are signalled via this command line flag.
+// TODO(b/159825227): remove when the "old" video decoder is fully launched.
+const char kPlatformDisallowsChromeOSDirectVideoDecoder[] =
+ "platform-disallows-chromeos-direct-video-decoder";
+
} // namespace switches
diff --git a/chromium/ui/ozone/public/ozone_switches.h b/chromium/ui/ozone/public/ozone_switches.h
index 3a56b500e21..ca63b0d2626 100644
--- a/chromium/ui/ozone/public/ozone_switches.h
+++ b/chromium/ui/ozone/public/ozone_switches.h
@@ -23,9 +23,6 @@ COMPONENT_EXPORT(OZONE_SWITCHES) extern const char kDisableWaylandIme[];
COMPONENT_EXPORT(OZONE_SWITCHES) extern const char kUseWaylandExplicitGrab[];
-COMPONENT_EXPORT(OZONE_SWITCHES)
-extern const char kUseWaylandNormalThreadPriority[];
-
COMPONENT_EXPORT(OZONE_SWITCHES) extern const char kDisableExplicitDmaFences[];
COMPONENT_EXPORT(OZONE_SWITCHES)
@@ -36,6 +33,9 @@ extern const char kDisableBufferBWCompression[];
COMPONENT_EXPORT(OZONE_SWITCHES) extern const char kOzoneOverrideScreenSize[];
+COMPONENT_EXPORT(OZONE_SWITCHES)
+extern const char kPlatformDisallowsChromeOSDirectVideoDecoder[];
+
} // namespace switches
#endif // UI_OZONE_PUBLIC_OZONE_SWITCHES_H_
diff --git a/chromium/ui/ozone/public/platform_screen.cc b/chromium/ui/ozone/public/platform_screen.cc
index bc517733f58..98f599aa41d 100644
--- a/chromium/ui/ozone/public/platform_screen.cc
+++ b/chromium/ui/ozone/public/platform_screen.cc
@@ -6,6 +6,7 @@
#include "base/notreached.h"
#include "base/time/time.h"
+#include "ui/gfx/geometry/point.h"
namespace ui {
@@ -19,6 +20,11 @@ gfx::AcceleratedWidget PlatformScreen::GetLocalProcessWidgetAtPoint(
return gfx::kNullAcceleratedWidget;
}
+bool PlatformScreen::IsAcceleratedWidgetUnderCursor(
+ gfx::AcceleratedWidget widget) const {
+ return GetAcceleratedWidgetAtScreenPoint(GetCursorScreenPoint()) == widget;
+}
+
std::string PlatformScreen::GetCurrentWorkspace() {
NOTIMPLEMENTED_LOG_ONCE();
return {};
diff --git a/chromium/ui/ozone/public/platform_screen.h b/chromium/ui/ozone/public/platform_screen.h
index 43dc9984bd8..091220a99f7 100644
--- a/chromium/ui/ozone/public/platform_screen.h
+++ b/chromium/ui/ozone/public/platform_screen.h
@@ -68,6 +68,9 @@ class COMPONENT_EXPORT(OZONE_BASE) PlatformScreen {
// TODO(rjkroege): Verify these semantics.
virtual gfx::Point GetCursorScreenPoint() const = 0;
+ virtual bool IsAcceleratedWidgetUnderCursor(
+ gfx::AcceleratedWidget widget) const;
+
virtual gfx::AcceleratedWidget GetAcceleratedWidgetAtScreenPoint(
const gfx::Point& point) const = 0;
diff --git a/chromium/ui/ozone/public/surface_ozone_canvas.cc b/chromium/ui/ozone/public/surface_ozone_canvas.cc
index eb506f97f02..d3de60cafd0 100644
--- a/chromium/ui/ozone/public/surface_ozone_canvas.cc
+++ b/chromium/ui/ozone/public/surface_ozone_canvas.cc
@@ -6,6 +6,8 @@
#include "base/notreached.h"
+#include <ostream>
+
namespace ui {
SurfaceOzoneCanvas::~SurfaceOzoneCanvas() = default;
diff --git a/chromium/ui/ozone/public/system_input_injector.h b/chromium/ui/ozone/public/system_input_injector.h
index d69d128e261..68acb1b8850 100644
--- a/chromium/ui/ozone/public/system_input_injector.h
+++ b/chromium/ui/ozone/public/system_input_injector.h
@@ -19,12 +19,16 @@ namespace ui {
// native events.
class COMPONENT_EXPORT(OZONE) SystemInputInjector {
public:
- SystemInputInjector() {}
+ SystemInputInjector() = default;
SystemInputInjector(const SystemInputInjector&) = delete;
SystemInputInjector& operator=(const SystemInputInjector&) = delete;
- virtual ~SystemInputInjector() {}
+ virtual ~SystemInputInjector() = default;
+
+ // Set the device id that will be used for all the generated events.
+ // The device id is set to |ui::ED_UNKNOWN_DEVICE| by default.
+ virtual void SetDeviceId(int device_id) = 0;
// Moves the cursor on the screen and generates the corresponding MouseMove or
// MouseDragged event. |location| is in physical screen coordinates,