Jan Grulich f2177f6612 PipeWire capturer: implement proper DMA-BUFs support
Currently both KWin (KDE) and Mutter (GNOME) window managers don't
use DMA-BUFs by default, but only when client asks specifically for
them (KWin) or when experimental DMA-BUF support is enabled (Mutter).
While current implementation works just fine on integrated graphics
cards, it causes issues on dedicated GPUs (AMD and NVidia) where the
code either crashes or screensharing is slow and unusable.

To fix this, DMA-BUFs has to be opened using OpenGL context and not
being directly mmaped(). This implementation requires to use DMA-BUF
modifiers, as they are now mandatory for DMA-BUFs usage.

Documentation for this behavior can be found here:
https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/doc/dma-buf.dox

Bug: chromium:1233417, webrtc:13137
Change-Id: I0cecf16d6bb0f576954b9e8f071cab526f7baf2c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/227022
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34889}
2021-09-01 08:10:40 +00:00

606 lines
16 KiB
Plaintext

# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("//build/config/linux/pkg_config.gni")
import("//build/config/ui.gni")
import("//tools/generate_stubs/rules.gni")
import("../../webrtc.gni")
use_desktop_capture_differ_sse2 = current_cpu == "x86" || current_cpu == "x64"
config("x11_config") {
if (rtc_use_x11_extensions) {
defines = [ "WEBRTC_USE_X11" ]
}
}
rtc_library("primitives") {
visibility = [ "*" ]
sources = [
"desktop_capture_types.h",
"desktop_frame.cc",
"desktop_frame.h",
"desktop_geometry.cc",
"desktop_geometry.h",
"desktop_region.cc",
"desktop_region.h",
"shared_desktop_frame.cc",
"shared_desktop_frame.h",
"shared_memory.cc",
"shared_memory.h",
]
deps = [
"../../api:scoped_refptr",
"../../rtc_base:checks",
"../../rtc_base/system:rtc_export",
"//third_party/libyuv",
]
if (!build_with_mozilla) {
deps += [ "../../rtc_base" ] # TODO(kjellander): Cleanup in
# bugs.webrtc.org/3806.
}
}
if (rtc_include_tests) {
rtc_library("desktop_capture_modules_tests") {
testonly = true
defines = []
sources = []
deps = [
"../../api:function_view",
"../../api:scoped_refptr",
"../../rtc_base:checks",
]
if (rtc_desktop_capture_supported) {
deps += [
":desktop_capture_mock",
":primitives",
":screen_drawer",
"../../rtc_base",
"../../rtc_base:rtc_base_approved",
"../../rtc_base/third_party/base64",
"../../system_wrappers",
"../../test:test_support",
"../../test:video_test_support",
]
sources += [
"screen_capturer_integration_test.cc",
"screen_drawer_unittest.cc",
"window_finder_unittest.cc",
]
public_configs = [ ":x11_config" ]
if (is_win) {
deps += [ "../../rtc_base:win32" ]
}
}
}
rtc_library("desktop_capture_unittests") {
testonly = true
defines = []
sources = [
"blank_detector_desktop_capturer_wrapper_unittest.cc",
"cropped_desktop_frame_unittest.cc",
"desktop_and_cursor_composer_unittest.cc",
"desktop_capturer_differ_wrapper_unittest.cc",
"desktop_frame_rotation_unittest.cc",
"desktop_frame_unittest.cc",
"desktop_geometry_unittest.cc",
"desktop_region_unittest.cc",
"differ_block_unittest.cc",
"fallback_desktop_capturer_wrapper_unittest.cc",
"mouse_cursor_monitor_unittest.cc",
"rgba_color_unittest.cc",
"test_utils.cc",
"test_utils.h",
"test_utils_unittest.cc",
]
if (is_win) {
sources += [
"win/cursor_unittest.cc",
"win/cursor_unittest_resources.h",
"win/cursor_unittest_resources.rc",
"win/screen_capture_utils_unittest.cc",
"win/screen_capturer_win_directx_unittest.cc",
"win/test_support/test_window.cc",
"win/test_support/test_window.h",
"win/window_capture_utils_unittest.cc",
]
}
deps = [
":desktop_capture",
":desktop_capture_mock",
":primitives",
"../../rtc_base:checks",
# TODO(bugs.webrtc.org/9987): Remove this dep on rtc_base:rtc_base once
# rtc_base:threading is fully defined.
"../../rtc_base:rtc_base",
"../../rtc_base:rtc_base_approved",
"../../rtc_base:threading",
"../../system_wrappers",
"../../test:test_support",
]
if (rtc_desktop_capture_supported) {
sources += [
"screen_capturer_helper_unittest.cc",
"screen_capturer_unittest.cc",
"window_capturer_unittest.cc",
]
if (is_mac) {
sources += [ "screen_capturer_mac_unittest.cc" ]
}
if (rtc_enable_win_wgc) {
sources += [
"win/wgc_capture_source_unittest.cc",
"win/wgc_capturer_win_unittest.cc",
]
}
deps += [
":desktop_capture_mock",
"../../system_wrappers:metrics",
]
public_configs = [ ":x11_config" ]
}
}
rtc_library("screen_drawer") {
testonly = true
public_deps = [ ":desktop_capture" ] # no-presubmit-check TODO(webrtc:8603)
sources = [
"screen_drawer.cc",
"screen_drawer.h",
]
if (is_linux || is_chromeos) {
sources += [ "screen_drawer_linux.cc" ]
}
if (is_mac) {
sources += [ "screen_drawer_mac.cc" ]
}
if (is_win) {
sources += [ "screen_drawer_win.cc" ]
}
deps = [
":primitives",
"../../api:scoped_refptr",
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
"../../system_wrappers",
]
if (is_posix || is_fuchsia) {
sources += [
"screen_drawer_lock_posix.cc",
"screen_drawer_lock_posix.h",
]
}
}
rtc_library("desktop_capture_mock") {
testonly = true
public_deps = [ ":desktop_capture" ] # no-presubmit-check TODO(webrtc:8603)
sources = [
"mock_desktop_capturer_callback.cc",
"mock_desktop_capturer_callback.h",
]
deps = [
":primitives",
"../../rtc_base:rtc_base_approved",
"../../test:test_support",
]
}
}
if (is_linux || is_chromeos) {
if (rtc_use_pipewire) {
pkg_config("gio") {
packages = [
"gio-2.0",
"gio-unix-2.0",
]
}
pkg_config("pipewire") {
packages = [ "libpipewire-0.3" ]
if (!rtc_link_pipewire) {
ignore_libs = true
}
}
pkg_config("gbm") {
packages = [ "gbm" ]
}
pkg_config("egl") {
packages = [ "egl" ]
}
pkg_config("epoxy") {
packages = [ "epoxy" ]
}
pkg_config("libdrm") {
packages = [ "libdrm" ]
}
if (!rtc_link_pipewire) {
# When libpipewire is not directly linked, use stubs to allow for dlopening of
# the binary.
generate_stubs("pipewire_stubs") {
configs = [
"../../:common_config",
":pipewire",
]
deps = [ "../../rtc_base" ]
extra_header = "linux/pipewire_stub_header.fragment"
logging_function = "RTC_LOG(LS_VERBOSE)"
logging_include = "rtc_base/logging.h"
output_name = "linux/pipewire_stubs"
path_from_source = "modules/desktop_capture/linux"
sigs = [ "linux/pipewire03.sigs" ]
}
}
config("pipewire_config") {
defines = [ "WEBRTC_USE_PIPEWIRE" ]
if (!rtc_link_pipewire) {
defines += [ "WEBRTC_DLOPEN_PIPEWIRE" ]
}
}
}
}
rtc_source_set("desktop_capture") {
visibility = [ "*" ]
public_deps = # no-presubmit-check TODO(webrtc:8603)
[ ":desktop_capture_generic" ]
if (is_mac) {
public_deps += [ ":desktop_capture_objc" ]
}
}
if (is_mac) {
rtc_library("desktop_capture_objc") {
visibility = [ ":desktop_capture" ]
sources = [
"mac/desktop_configuration.mm",
"mac/desktop_frame_cgimage.h",
"mac/desktop_frame_cgimage.mm",
"mac/desktop_frame_iosurface.h",
"mac/desktop_frame_iosurface.mm",
"mac/desktop_frame_provider.h",
"mac/desktop_frame_provider.mm",
"mac/screen_capturer_mac.h",
"mac/screen_capturer_mac.mm",
"mouse_cursor_monitor_mac.mm",
"screen_capturer_darwin.mm",
"window_capturer_mac.mm",
"window_finder_mac.h",
"window_finder_mac.mm",
]
deps = [
":desktop_capture_generic",
":primitives",
"../../api:scoped_refptr",
"../../rtc_base",
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
"../../rtc_base/system:rtc_export",
"../../sdk:helpers_objc",
]
frameworks = [
"AppKit.framework",
"IOKit.framework",
"IOSurface.framework",
]
}
}
rtc_library("desktop_capture_generic") {
defines = []
public_configs = [ ":x11_config" ]
visibility = [
":desktop_capture",
":desktop_capture_objc",
]
sources = [
"blank_detector_desktop_capturer_wrapper.cc",
"blank_detector_desktop_capturer_wrapper.h",
"cropped_desktop_frame.cc",
"cropped_desktop_frame.h",
"cropping_window_capturer.cc",
"cropping_window_capturer.h",
"desktop_and_cursor_composer.cc",
"desktop_and_cursor_composer.h",
"desktop_capture_metrics_helper.cc",
"desktop_capture_metrics_helper.h",
"desktop_capture_options.cc",
"desktop_capture_options.h",
"desktop_capturer.cc",
"desktop_capturer.h",
"desktop_capturer_differ_wrapper.cc",
"desktop_capturer_differ_wrapper.h",
"desktop_capturer_wrapper.cc",
"desktop_capturer_wrapper.h",
"desktop_frame_generator.cc",
"desktop_frame_generator.h",
"desktop_frame_rotation.cc",
"desktop_frame_rotation.h",
"differ_block.cc",
"differ_block.h",
"fake_desktop_capturer.cc",
"fake_desktop_capturer.h",
"fallback_desktop_capturer_wrapper.cc",
"fallback_desktop_capturer_wrapper.h",
"full_screen_application_handler.cc",
"full_screen_application_handler.h",
"full_screen_window_detector.cc",
"full_screen_window_detector.h",
"mouse_cursor.cc",
"mouse_cursor.h",
"mouse_cursor_monitor.h",
"resolution_tracker.cc",
"resolution_tracker.h",
"rgba_color.cc",
"rgba_color.h",
"screen_capture_frame_queue.h",
"screen_capturer_helper.cc",
"screen_capturer_helper.h",
"window_finder.cc",
"window_finder.h",
]
if (is_mac) {
sources += [
"mac/desktop_configuration.h",
"mac/desktop_configuration_monitor.cc",
"mac/desktop_configuration_monitor.h",
"mac/full_screen_mac_application_handler.cc",
"mac/full_screen_mac_application_handler.h",
"mac/window_list_utils.cc",
"mac/window_list_utils.h",
]
}
if (build_with_mozilla) {
sources += [
"desktop_device_info.cc",
"desktop_device_info.h",
]
if (is_win) {
sources += [
"app_capturer_win.cc",
"win/desktop_device_info_win.cc",
"win/win_shared.cc",
]
}
}
if (rtc_use_x11_extensions || rtc_use_pipewire) {
sources += [
"mouse_cursor_monitor_linux.cc",
"screen_capturer_linux.cc",
"window_capturer_linux.cc",
]
if (build_with_mozilla && (is_linux || is_chromeos)) {
sources += [
"app_capturer_linux.cc",
"linux/app_capturer_x11.cc",
"linux/desktop_device_info_linux.cc",
"linux/desktop_device_info_linux.h",
"linux/shared_x_util.cc",
"linux/shared_x_util.h",
]
}
}
if (rtc_use_x11_extensions) {
sources += [
"linux/mouse_cursor_monitor_x11.cc",
"linux/mouse_cursor_monitor_x11.h",
"linux/screen_capturer_x11.cc",
"linux/screen_capturer_x11.h",
"linux/shared_x_display.cc",
"linux/shared_x_display.h",
"linux/window_capturer_x11.cc",
"linux/window_capturer_x11.h",
"linux/window_finder_x11.cc",
"linux/window_finder_x11.h",
"linux/window_list_utils.cc",
"linux/window_list_utils.h",
"linux/x_atom_cache.cc",
"linux/x_atom_cache.h",
"linux/x_error_trap.cc",
"linux/x_error_trap.h",
"linux/x_server_pixel_buffer.cc",
"linux/x_server_pixel_buffer.h",
"linux/x_window_property.cc",
"linux/x_window_property.h",
]
libs = [
"X11",
"Xcomposite",
"Xdamage",
"Xext",
"Xfixes",
"Xrender",
"Xrandr",
"Xtst",
]
}
if (!is_win && !is_mac && !rtc_use_x11_extensions && !rtc_use_pipewire) {
sources += [
"mouse_cursor_monitor_null.cc",
"screen_capturer_null.cc",
"window_capturer_null.cc",
]
}
deps = [
":primitives",
"../../api:function_view",
"../../api:refcountedbase",
"../../api:scoped_refptr",
"../../api:sequence_checker",
"../../rtc_base", # TODO(kjellander): Cleanup in bugs.webrtc.org/3806.
"../../rtc_base:checks",
"../../rtc_base/synchronization:mutex",
"../../rtc_base/system:arch",
"../../rtc_base/system:rtc_export",
"../../system_wrappers",
"../../system_wrappers:metrics",
]
if (is_win) {
sources += [
"cropping_window_capturer_win.cc",
"desktop_frame_win.cc",
"desktop_frame_win.h",
"mouse_cursor_monitor_win.cc",
"screen_capturer_win.cc",
"win/cursor.cc",
"win/cursor.h",
"win/d3d_device.cc",
"win/d3d_device.h",
"win/desktop.cc",
"win/desktop.h",
"win/desktop_capture_utils.cc",
"win/desktop_capture_utils.h",
"win/display_configuration_monitor.cc",
"win/display_configuration_monitor.h",
"win/dxgi_adapter_duplicator.cc",
"win/dxgi_adapter_duplicator.h",
"win/dxgi_context.cc",
"win/dxgi_context.h",
"win/dxgi_duplicator_controller.cc",
"win/dxgi_duplicator_controller.h",
"win/dxgi_frame.cc",
"win/dxgi_frame.h",
"win/dxgi_output_duplicator.cc",
"win/dxgi_output_duplicator.h",
"win/dxgi_texture.cc",
"win/dxgi_texture.h",
"win/dxgi_texture_mapping.cc",
"win/dxgi_texture_mapping.h",
"win/dxgi_texture_staging.cc",
"win/dxgi_texture_staging.h",
"win/full_screen_win_application_handler.cc",
"win/full_screen_win_application_handler.h",
"win/scoped_gdi_object.h",
"win/scoped_thread_desktop.cc",
"win/scoped_thread_desktop.h",
"win/screen_capture_utils.cc",
"win/screen_capture_utils.h",
"win/screen_capturer_win_directx.cc",
"win/screen_capturer_win_directx.h",
"win/screen_capturer_win_gdi.cc",
"win/screen_capturer_win_gdi.h",
"win/screen_capturer_win_magnifier.cc",
"win/screen_capturer_win_magnifier.h",
"win/selected_window_context.cc",
"win/selected_window_context.h",
"win/window_capture_utils.cc",
"win/window_capture_utils.h",
"win/window_capturer_win_gdi.cc",
"win/window_capturer_win_gdi.h",
"window_capturer_win.cc",
"window_finder_win.cc",
"window_finder_win.h",
]
libs = [
"d3d11.lib",
"dxgi.lib",
]
deps += [ "../../rtc_base:win32" ]
}
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
if (rtc_use_x11_extensions) {
deps += [ "../../rtc_base:sanitizer" ]
}
if (build_with_mozilla) {
deps += [ "../../rtc_base:rtc_base_approved" ]
} else {
deps += [ "//third_party/libyuv" ]
}
if (use_desktop_capture_differ_sse2) {
deps += [ ":desktop_capture_differ_sse2" ]
}
if (rtc_use_pipewire) {
sources += [
"linux/base_capturer_pipewire.cc",
"linux/base_capturer_pipewire.h",
"linux/egl_dmabuf.cc",
"linux/egl_dmabuf.h",
]
configs += [
":pipewire_config",
":gio",
":pipewire",
":gbm",
":egl",
":epoxy",
":libdrm",
]
if (!rtc_link_pipewire) {
deps += [ ":pipewire_stubs" ]
}
}
if (rtc_enable_win_wgc) {
sources += [
"win/wgc_capture_session.cc",
"win/wgc_capture_session.h",
"win/wgc_capture_source.cc",
"win/wgc_capture_source.h",
"win/wgc_capturer_win.cc",
"win/wgc_capturer_win.h",
"win/wgc_desktop_frame.cc",
"win/wgc_desktop_frame.h",
]
}
}
if (use_desktop_capture_differ_sse2) {
# Have to be compiled as a separate target because it needs to be compiled
# with SSE2 enabled.
rtc_library("desktop_capture_differ_sse2") {
visibility = [ ":*" ]
sources = [
"differ_vector_sse2.cc",
"differ_vector_sse2.h",
]
if (is_posix || is_fuchsia) {
cflags = [ "-msse2" ]
}
}
}