diff --git a/firefox/.signature b/firefox/.signature index d484ab345..99ad3dba7 100644 --- a/firefox/.signature +++ b/firefox/.signature @@ -1,6 +1,44 @@ untrusted comment: verify with /etc/ports/contrib.pub -RWSagIOpLGJF30xCrWcuIMa3tkXZP1B3Dqb29EHWs/kqMsH7YK0KMXkcES3nBZgVLDB4zmfXHb8Ms6oVNNfc2WrTy4fCXdhzqwc= -SHA256 (Pkgfile) = 0d67ca9b24d62da678ad9f6e887e6cbe01e5dd4cf89b0971682267f28f7d4619 +RWSagIOpLGJF3/slVbBgAxPneZMx7BptybCq3o8h2TvYcDWGnglcb1X93V0D+WWA90cnJiFN/kA6IZXVCxtDBselpDQgS1+CQgo= +SHA256 (Pkgfile) = 91ea1a35fbaaaf2975cbbbdf31d276b8a699d7daac0e336d26a97322fb08c121 SHA256 (.footprint) = c8226cc240304363b6289982601426f70c5cd4e82ac62feff3485bee4f48e050 -SHA256 (firefox-104.0.source.tar.xz) = 1a294a651dc6260f9a72a3ab9f10e7792a4ab41a9cfa8527ad3dd9979cdc98ce +SHA256 (firefox-104.0.2.source.tar.xz) = 72bba06f04e7745f6b02951906413eb1c15a7e253e06e373302162c6219f286a SHA256 (firefox.desktop) = 8ba3439f3dfc5cab883641969c93d8d15f8f20d7188d9568346b2edad52d6f91 +SHA256 (node-stdout-nonblocking-wrapper) = bb8c503015e49ed1b152225bdc56cf502cd831f35962d113dcbb9121967f3523 +SHA256 (0001-Don-t-use-build-id.patch) = f55742252e6005670d05606e18ed7fb64369d8f12ff41993b8d713f468fd3465 +SHA256 (0002-Fortify-sources-properly.patch) = 92d88a6cfd0bbf9a07f1171e6c3f65b8fb6863e286639867009f3f8712682a31 +SHA256 (0003-Check-additional-plugins-dir.patch) = f97f2676182519c973a772bfca2cccdf1f4f31fd653c5ce044623a96270cac8b +SHA256 (0004-bmo-847568-Support-system-harfbuzz.patch) = a014deff6d8e12a3c1e394e90c404d635e5fa45ef0c0c4844c3619f37ce0d050 +SHA256 (0005-bmo-847568-Support-system-graphite2.patch) = 27961704acd49fde267aaccd3067361658fb236d917e48bdc05a0d5380153292 +SHA256 (0006-bmo-1559213-Support-system-av1.patch) = 7c6db1dd501c99cd5d4ba59e66dd1f5d3065008b2c343e733201982de0a89ac6 +SHA256 (0007-bmo-878089-Don-t-fail-when-TERM-is-not-set.patch) = 816c463b39779bc97ded28ed3e98ef91708e63edc51bfde1b612a03608ae0da8 +SHA256 (0008-bmo-1516803-Fix-building-sandbox.patch) = 8e74496c183f0b8f13a55d50c502d583315872d43893c8649c38f7b3eea526eb +SHA256 (0009-musl-Add-alternate-name-for-private-siginfo-struct-m.patch) = 8d34520b8a8a5c6b0633a59a72e076df9621cf6e93e5e70f036223fbbab4a254 +SHA256 (0010-musl-Fix-syscall-wrappers.patch) = 4d9d7ac287b37c950c70640addace870ee9a0c16d8e30d54883ee545bf77527b +SHA256 (0011-musl-Only-use-system-heap-reporter-with-glibc.patch) = 8b6c802f6f429b2385cba2c8b2a68ee0b40adeeaa4dbcc9cb535ab379494b150 +SHA256 (0012-musl-Set-pthread-name-for-non-glibc-systems.patch) = a3472d0922a800b2c3043089f13cc8f2dd5f6448af3a1dcb23f385783c91c75f +SHA256 (0013-musl-getcontext-is-only-avaliable-on-glibc-systems.patch) = 6d4652c0be993c224a657ae19371dd4b88c80e293c6775c8a6006899123bc9d8 +SHA256 (0014-musl-sys-auvx.h-avaliable-on-more-then-just-glibc-sy.patch) = dc373813110d7a1035e8615ce5598e119b74c8c6d5c27dae09a79727933f4672 +SHA256 (0015-musl-make-SYS_fork-non-fatal-musl-uses-it-for-fork-2.patch) = d32b4cc299882a6ca86ef231b3dcb6d44f517070656daae2143915894915d3a4 +SHA256 (0016-musl-include-net-if.h-before-linux-if.h-to-avoid-red.patch) = 9628553d4d7f14eb54b21d48c3f56a863c905e0d27bffaaaf597e9359d6086ed +SHA256 (0017-Make-PGO-use-toolchain.patch) = 7b45e98356e6afbb67e0ff005cedd5b2022093bf1716ef0936ab3f6615f787da +SHA256 (0018-bmo-1516081-Disable-watchdog-during-PGO-builds.patch) = 1d713370fe5a8788aa1723ca291ae2f96635b92bc3cb80aea85d21847c59ed6d +SHA256 (0019-bmo-1516803-force-one-LTO-partition-for-sandbox-when.patch) = 7f070620a393d283b488c263bf8a871c1a0afe5801d963316e14474c27dd3d6d +SHA256 (0020-Fix-building-with-PGO-when-using-GCC.patch) = ccad3e01df1229ca55f526073f9e5e37005042cc9b46ef578907577e6b590e0e +SHA256 (0021-libaom-Use-NEON_FLAGS-instead-of-VPX_ASFLAGS-for-lib.patch) = ef3bcc8bea2660b56927c6b00031db99efe8a5ecdcc947456b7bab0f7a7ff7e2 +SHA256 (0022-build-Disable-Werror.patch) = b1ff9ae63dd0e581546d93abbb4fe770645ca75572b0a7c2a0d26d06e396241f +SHA256 (0023-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch) = 18fc8bab428137702d6774a93d3cc8d8f6b8ea68e1d86b32591e2c242e80e767 +SHA256 (0024-Enable-FLAC-on-platforms-without-ffvpx-via-ffmpeg.patch) = eb83aa50ee543be99705994ff827805fad1e9c679f0402a8735651357bb8856c +SHA256 (0025-bmo-1670333-OpenH264-Fix-decoding-if-it-starts-on-no.patch) = e828b8b48c55601de0fc3c244ff83ee5a0d48267de7c14eeeabc26487d8e747d +SHA256 (0026-bmo-1663844-OpenH264-Allow-using-OpenH264-GMP-decode.patch) = 26f950b6681eb67234649668d9d67ad4b6c5ca5025457f440778ff31066cfdf2 +SHA256 (0027-bgo-816975-fix-build-on-x86.patch) = 1d4add2a4afff50e4067ef4c404f781513c1c388126754fba1bf0323b1e093b3 +SHA256 (0028-bmo-1559213-fix-system-av1-libs.patch) = 344482f28d4512718320e7396706982f149d20459ae43c9e5b838753fb8ee905 +SHA256 (0029-bmo-1196777-Set-GDK_FOCUS_CHANGE_MASK.patch) = b47ea62937d7f87485e0f372c0110785bbb6f4dbc79d3d139d54887cac0773e3 +SHA256 (0030-bmo-1754469-memory_mozalloc_throw.patch) = ba1013f0b5a76312802ac62cc5dbc35ecdcd3d4946df78c4b3fc144afc829023 +SHA256 (0031-bmo-1769631-python-3.11-compatibility.patch) = 5b0aad43012e4c175a6dde70b006fa9f07c4b0d70e9632414f16ac55d5243be4 +SHA256 (0032-bmo-1773336-disable_audio_thread_priority_default_features.patch) = 4bbd43f7dbe7e01f168264dd3c02fd32c9e3b341b8eff297e4d98c7bba6a5d3a +SHA256 (0033-rhbz-2115253-vaapi-fixes.patch) = f2b19e14d8add13930e2ce89fa5e1b252ac979c8177a78a6fa3eb4ae2ad56633 +SHA256 (0034-bgo-860033-firefox-wayland-no-dbus.patch) = efdf58e256b298bf8f0c0b7ead119830e99d1b2bf29ba1e43a9e0eeb8ac2e538 +SHA256 (arc4random.patch) = 714ca50b2ce0cac470dbd5a60e9a0101b28072f08a5e7a9bba94fef2058321c4 +SHA256 (libwebrtc-screen-cast-sync-1.patch) = c8b07fce4bb923cdac621ab8c53de7dcb5e5a37891b883524de86546976b1779 +SHA256 (no-ccache-stats.patch) = dc164e37ccf78d9a83dded7d7e52f091a703b650967ed8888120689c213eb1ab diff --git a/firefox/0001-Don-t-use-build-id.patch b/firefox/0001-Don-t-use-build-id.patch new file mode 100644 index 000000000..27c2fc399 --- /dev/null +++ b/firefox/0001-Don-t-use-build-id.patch @@ -0,0 +1,54 @@ +From db2794973f8a5e580fbceacbfb1b6469c9f162d7 Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 19:14:26 +0200 +Subject: [PATCH 01/30] Don't use build id + +We must drop build id as it causes conflicts when merging +thunderbird/firefox/seamonkey on same system when using +splitdebug. + +Signed-off-by: Thomas Deutschmann +--- + js/src/old-configure.in | 7 ------- + old-configure.in | 7 ------- + 2 files changed, 14 deletions(-) + +diff --git a/js/src/old-configure.in b/js/src/old-configure.in +index 905494b784..15a7a2a852 100644 +--- a/js/src/old-configure.in ++++ b/js/src/old-configure.in +@@ -350,13 +350,6 @@ if test "$GNU_CC"; then + AC_MSG_RESULT([no]) + LDFLAGS=$_SAVE_LDFLAGS) + +- AC_MSG_CHECKING([for --build-id=sha1 option to ld]) +- _SAVE_LDFLAGS=$LDFLAGS +- LDFLAGS="$LDFLAGS -Wl,--build-id=sha1" +- AC_TRY_LINK(,,AC_MSG_RESULT([yes]), +- AC_MSG_RESULT([no]) +- LDFLAGS=$_SAVE_LDFLAGS) +- + _DEFINES_CFLAGS="-include $jsconfdefs -DMOZILLA_CLIENT" + fi + +diff --git a/old-configure.in b/old-configure.in +index d1479574d1..f69f5f5456 100644 +--- a/old-configure.in ++++ b/old-configure.in +@@ -337,13 +337,6 @@ if test "$GNU_CC"; then + AC_MSG_RESULT([no]) + LDFLAGS=$_SAVE_LDFLAGS) + +- AC_MSG_CHECKING([for --build-id=sha1 option to ld]) +- _SAVE_LDFLAGS=$LDFLAGS +- LDFLAGS="$LDFLAGS -Wl,--build-id=sha1" +- AC_TRY_LINK(,,AC_MSG_RESULT([yes]), +- AC_MSG_RESULT([no]) +- LDFLAGS=$_SAVE_LDFLAGS) +- + AC_MSG_CHECKING([for --ignore-unresolved-symbol option to ld]) + HAVE_LINKER_SUPPORT_IGNORE_UNRESOLVED= + _SAVE_LDFLAGS=$LDFLAGS +-- +2.34.1 + diff --git a/firefox/0002-Fortify-sources-properly.patch b/firefox/0002-Fortify-sources-properly.patch new file mode 100644 index 000000000..3abe8b01b --- /dev/null +++ b/firefox/0002-Fortify-sources-properly.patch @@ -0,0 +1,41 @@ +From a1395e97ffdbc9404a343b76fd731dc7ef385ffc Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 19:16:36 +0200 +Subject: [PATCH 02/30] Fortify sources properly + +Ensure we fortify properly, features.h is pulled in via fortification. + +Signed-off-by: Thomas Deutschmann +--- + config/system-headers.mozbuild | 1 - + third_party/sipcc/sdp_os_defs.h | 3 --- + 2 files changed, 4 deletions(-) + +diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild +index a1b58eb59b..ae0c9d6d7c 100644 +--- a/config/system-headers.mozbuild ++++ b/config/system-headers.mozbuild +@@ -229,7 +229,6 @@ system_headers = [ + 'execinfo.h', + 'extras.h', + 'fcntl.h', +- 'features.h', + 'fenv.h', + 'ffi.h', + 'fibdef.h', +diff --git a/third_party/sipcc/sdp_os_defs.h b/third_party/sipcc/sdp_os_defs.h +index 16c9b33329..df38d9336c 100644 +--- a/third_party/sipcc/sdp_os_defs.h ++++ b/third_party/sipcc/sdp_os_defs.h +@@ -20,8 +20,5 @@ + typedef uint8_t tinybool; + typedef unsigned short ushort; + typedef unsigned long ulong; +-#ifndef __GNUC_STDC_INLINE__ +-#define inline +-#endif + + #endif /* _SDP_OS_DEFS_H_ */ +-- +2.34.1 + diff --git a/firefox/0003-Check-additional-plugins-dir.patch b/firefox/0003-Check-additional-plugins-dir.patch new file mode 100644 index 000000000..ef66d9b4f --- /dev/null +++ b/firefox/0003-Check-additional-plugins-dir.patch @@ -0,0 +1,58 @@ +From 4d5eb53fa2ca9eeeadbfcd2be832aa8e97d413fc Mon Sep 17 00:00:00 2001 +From: Arfrever Frehtes Taifersar Arahesis +Date: Mon, 6 Apr 2020 19:17:43 +0200 +Subject: [PATCH 03/30] Check additional plugins dir + +Check original plugins dir along with default plugins dir. + +Signed-off-by: Thomas Deutschmann +--- + xpcom/io/nsAppFileLocationProvider.cpp | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp +index ef974f9904..6261eafcc8 100644 +--- a/xpcom/io/nsAppFileLocationProvider.cpp ++++ b/xpcom/io/nsAppFileLocationProvider.cpp +@@ -50,6 +50,7 @@ + # define NS_MACOSX_LOCAL_PLUGIN_DIR "OSXLocalPlugins" + #elif XP_UNIX + # define NS_SYSTEM_PLUGINS_DIR "SysPlugins" ++# define NS_SYSTEM_NSBROWSER_PLUGINS_DIR "SysNsBrowserPlugins" + #endif + + #define DEFAULTS_DIR_NAME "defaults"_ns +@@ -172,6 +173,21 @@ nsAppFileLocationProvider::GetFile(const char* aProp, bool* aPersistent, + getter_AddRefs(localFile)); + # else + rv = NS_ERROR_FAILURE; ++# endif ++ } else if (nsCRT::strcmp(aProp, NS_SYSTEM_NSBROWSER_PLUGINS_DIR) == 0) { ++# ifdef ENABLE_SYSTEM_EXTENSION_DIRS ++ static const char* const sysLPlgDir = ++# if defined(HAVE_USR_LIB64_DIR) && defined(__LP64__) ++ "/usr/lib64/nsbrowser/plugins"; ++# elif defined(__OpenBSD__) || defined(__FreeBSD__) ++ "/usr/local/lib/nsbrowser/plugins"; ++# else ++ "/usr/lib/nsbrowser/plugins"; ++# endif ++ rv = NS_NewNativeLocalFile(nsDependentCString(sysLPlgDir), false, ++ getter_AddRefs(localFile)); ++# else ++ rv = NS_ERROR_FAILURE; + # endif + } + # endif +@@ -418,7 +434,7 @@ nsAppFileLocationProvider::GetFiles(const char* aProp, + #else + # ifdef XP_UNIX + static const char* keys[] = {NS_USER_PLUGINS_DIR, NS_SYSTEM_PLUGINS_DIR, +- nullptr}; ++ NS_SYSTEM_NSBROWSER_PLUGINS_DIR, nullptr}; + # else + static const char* keys[] = {NS_USER_PLUGINS_DIR, nullptr}; + # endif +-- +2.34.1 + diff --git a/firefox/0004-bmo-847568-Support-system-harfbuzz.patch b/firefox/0004-bmo-847568-Support-system-harfbuzz.patch new file mode 100644 index 000000000..37ecef55a --- /dev/null +++ b/firefox/0004-bmo-847568-Support-system-harfbuzz.patch @@ -0,0 +1,181 @@ +From 61e8f03c526a40dda89b57aad6aec3f37d7125cd Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 19:32:39 +0200 +Subject: [PATCH 04/30] bmo#847568: Support system harfbuzz + +Allow building against system-wide harfbuzz. + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=847568 +Signed-off-by: Thomas Deutschmann +--- + config/system-headers.mozbuild | 7 +++++++ + dom/base/moz.build | 3 +++ + gfx/moz.build | 4 +++- + gfx/skia/generate_mozbuild.py | 3 +++ + gfx/skia/moz.build | 3 +++ + gfx/thebes/moz.build | 3 +++ + intl/unicharutil/util/moz.build | 3 +++ + netwerk/dns/moz.build | 3 +++ + toolkit/library/moz.build | 3 +++ + toolkit/moz.configure | 9 +++++++++ + 10 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild +index ae0c9d6d7c..44d08cf06b 100644 +--- a/config/system-headers.mozbuild ++++ b/config/system-headers.mozbuild +@@ -1237,6 +1237,13 @@ if CONFIG['OS_TARGET'] == 'Android': + 'vr/gvr/capi/include/gvr.h', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ system_headers += [ ++ 'harfbuzz/hb-glib.h', ++ 'harfbuzz/hb-ot.h', ++ 'harfbuzz/hb.h', ++ ] ++ + if CONFIG['MOZ_JACK']: + system_headers += [ + 'jack/jack.h', +diff --git a/dom/base/moz.build b/dom/base/moz.build +index d390adfc49..4508f19cb6 100644 +--- a/dom/base/moz.build ++++ b/dom/base/moz.build +@@ -567,6 +567,9 @@ FINAL_LIBRARY = "xul" + if CONFIG["MOZ_X11"]: + CXXFLAGS += CONFIG["TK_CFLAGS"] + ++if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ CXXFLAGS += CONFIG["MOZ_HARFBUZZ_CFLAGS"] ++ + GeneratedFile( + "UseCounterList.h", + script="gen-usecounters.py", +diff --git a/gfx/moz.build b/gfx/moz.build +index 4d6d63da9d..8222b72333 100644 +--- a/gfx/moz.build ++++ b/gfx/moz.build +@@ -10,6 +10,9 @@ with Files("**"): + with Files("wr/**"): + BUG_COMPONENT = ("Core", "Graphics: WebRender") + ++if not CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ DIRS += ["harfbuzz/src"] ++ + DIRS += [ + "cairo", + "2d", +@@ -20,7 +23,6 @@ DIRS += [ + "gl", + "layers", + "graphite2/src", +- "harfbuzz/src", + "ots/src", + "thebes", + "ipc", +diff --git a/gfx/skia/generate_mozbuild.py b/gfx/skia/generate_mozbuild.py +index 5e0fd17d79..860b80af4f 100755 +--- a/gfx/skia/generate_mozbuild.py ++++ b/gfx/skia/generate_mozbuild.py +@@ -96,6 +96,9 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): + '-Wno-unused-private-field', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'android'): + LOCAL_INCLUDES += [ + "/gfx/cairo/cairo/src", +diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build +index 524bd28dac..615c93b266 100755 +--- a/gfx/skia/moz.build ++++ b/gfx/skia/moz.build +@@ -488,6 +488,9 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): + '-Wno-unused-private-field', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'android'): + LOCAL_INCLUDES += [ + "/gfx/cairo/cairo/src", +diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build +index baa6f090a9..c51c36e2b4 100644 +--- a/gfx/thebes/moz.build ++++ b/gfx/thebes/moz.build +@@ -288,6 +288,9 @@ LOCAL_INCLUDES += CONFIG["SKIA_INCLUDES"] + + DEFINES["GRAPHITE2_STATIC"] = True + ++if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ CXXFLAGS += CONFIG["MOZ_HARFBUZZ_CFLAGS"] ++ + if CONFIG["CC_TYPE"] in ("clang", "clang-cl"): + # Suppress warnings from Skia header files. + SOURCES["gfxPlatform.cpp"].flags += ["-Wno-implicit-fallthrough"] +diff --git a/intl/unicharutil/util/moz.build b/intl/unicharutil/util/moz.build +index 301eb9a854..7cece5e06c 100644 +--- a/intl/unicharutil/util/moz.build ++++ b/intl/unicharutil/util/moz.build +@@ -25,6 +25,9 @@ UNIFIED_SOURCES += [ + "nsUnicodeProperties.cpp", + ] + ++if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ CXXFLAGS += CONFIG["MOZ_HARFBUZZ_CFLAGS"] ++ + include("/ipc/chromium/chromium-config.mozbuild") + + GeneratedFile( +diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build +index f769e270fa..8f64710257 100644 +--- a/netwerk/dns/moz.build ++++ b/netwerk/dns/moz.build +@@ -109,4 +109,7 @@ LOCAL_INCLUDES += [ + "/netwerk/protocol/http", + ] + ++if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ CXXFLAGS += CONFIG["MOZ_HARFBUZZ_CFLAGS"] ++ + USE_LIBS += ["icu"] +diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build +index 2c3f86948e..dd6901ba9a 100644 +--- a/toolkit/library/moz.build ++++ b/toolkit/library/moz.build +@@ -260,6 +260,9 @@ if CONFIG["MOZ_ANDROID_GOOGLE_VR"]: + "-lgvr", + ] + ++if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: ++ OS_LIBS += CONFIG["MOZ_HARFBUZZ_LIBS"] ++ + if CONFIG["MOZ_SYSTEM_JPEG"]: + OS_LIBS += CONFIG["MOZ_JPEG_LIBS"] + +diff --git a/toolkit/moz.configure b/toolkit/moz.configure +index 00698656f6..1843188d11 100644 +--- a/toolkit/moz.configure ++++ b/toolkit/moz.configure +@@ -460,6 +460,15 @@ add_old_configure_assignment( + ) + set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)) + ++# HarfBuzz ++# ============================================================== ++option('--with-system-harfbuzz', help="Use system harfbuzz (located with pkgconfig)") ++ ++system_harfbuzz = pkg_check_modules('MOZ_HARFBUZZ', 'harfbuzz >= 2.7.4', ++ when='--with-system-harfbuzz') ++ ++set_config('MOZ_SYSTEM_HARFBUZZ', depends_if(system_harfbuzz)(lambda _: True)) ++ + # Apple platform decoder support + # ============================================================== + @depends(toolkit) +-- +2.34.1 + diff --git a/firefox/0005-bmo-847568-Support-system-graphite2.patch b/firefox/0005-bmo-847568-Support-system-graphite2.patch new file mode 100644 index 000000000..74d9b24f1 --- /dev/null +++ b/firefox/0005-bmo-847568-Support-system-graphite2.patch @@ -0,0 +1,208 @@ +From a7761d4886498eaa0e83d1c9b4399632cdbf314e Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 19:34:44 +0200 +Subject: [PATCH 05/30] bmo#847568: Support system graphite2 + +Allow building against system-wide graphite2. + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=847568 +Signed-off-by: Thomas Deutschmann +--- + config/system-headers.mozbuild | 6 ++++++ + gfx/graphite2/geckoextra/moz.build | 21 +++++++++++++++++++++ + gfx/graphite2/moz-gr-update.sh | 7 ++++++- + gfx/moz.build | 6 +++++- + gfx/thebes/moz.build | 5 ++++- + old-configure.in | 21 +++++++++++++++++++++ + toolkit/library/moz.build | 3 +++ + toolkit/moz.configure | 13 +++++++++++++ + 8 files changed, 79 insertions(+), 3 deletions(-) + create mode 100644 gfx/graphite2/geckoextra/moz.build + +diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild +index 44d08cf06b..2f7ae39515 100644 +--- a/config/system-headers.mozbuild ++++ b/config/system-headers.mozbuild +@@ -1244,6 +1244,12 @@ if CONFIG['MOZ_SYSTEM_HARFBUZZ']: + 'harfbuzz/hb.h', + ] + ++if CONFIG['MOZ_SYSTEM_GRAPHITE2']: ++ system_headers += [ ++ 'graphite2/Font.h', ++ 'graphite2/Segment.h', ++ ] ++ + if CONFIG['MOZ_JACK']: + system_headers += [ + 'jack/jack.h', +diff --git a/gfx/graphite2/geckoextra/moz.build b/gfx/graphite2/geckoextra/moz.build +new file mode 100644 +index 0000000000..24e8d7a032 +--- /dev/null ++++ b/gfx/graphite2/geckoextra/moz.build +@@ -0,0 +1,21 @@ ++# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- ++# vim: set filetype=python: ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++EXPORTS.graphite2 += [ ++ 'include/GraphiteExtra.h', ++ 'include/GraphiteStructsForRLBox.h', ++] ++ ++UNIFIED_SOURCES += [ ++ '../geckoextra/src/GraphiteExtra.cpp', ++] ++ ++CXXFLAGS += CONFIG['MOZ_GRAPHITE2_CFLAGS'] ++ ++# Match bundled graphite2 configuration ++AllowCompilerWarnings() ++ ++FINAL_LIBRARY = 'gkmedias' +diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh +index b91d9c161c..a97e6eb203 100755 +--- a/gfx/graphite2/moz-gr-update.sh ++++ b/gfx/graphite2/moz-gr-update.sh +@@ -1,6 +1,7 @@ + #!/bin/bash + + # Script used to update the Graphite2 library in the mozilla source tree ++# and bump version for --with-system-graphite2 + + # This script lives in gfx/graphite2, along with the library source, + # but must be run from the top level of the mozilla-central tree. +@@ -37,12 +38,16 @@ echo "See" $0 "for update procedure." >> gfx/graphite2/README.mozilla + #find gfx/graphite2/ -name "*.cpp" -exec perl -p -i -e "s///;s/Windows.h/windows.h/;" {} \; + #find gfx/graphite2/ -name "*.h" -exec perl -p -i -e "s///;s/Windows.h/windows.h/;" {} \; + ++# chase version for --with-system-graphite2 ++perl -p -i -e "s/[0-9]+\,[0-9]+\,[0-9]+/$RELEASE/ and tr/./,/ \ ++ if /GR2_VERSION_REQUIRE/" old-configure.in ++ + # summarize what's been touched + echo Updated to $RELEASE. + echo Here is what changed in the gfx/graphite2 directory: + echo + +-hg stat gfx/graphite2 ++hg stat old-configure.in gfx/graphite2 + + echo + echo If gfx/graphite2/src/files.mk has changed, please make corresponding +diff --git a/gfx/moz.build b/gfx/moz.build +index 8222b72333..16a2b401db 100644 +--- a/gfx/moz.build ++++ b/gfx/moz.build +@@ -10,6 +10,11 @@ with Files("**"): + with Files("wr/**"): + BUG_COMPONENT = ("Core", "Graphics: WebRender") + ++if CONFIG["MOZ_SYSTEM_GRAPHITE2"]: ++ DIRS += ["graphite2/geckoextra"] ++else: ++ DIRS += ["graphite2/src"] ++ + if not CONFIG["MOZ_SYSTEM_HARFBUZZ"]: + DIRS += ["harfbuzz/src"] + +@@ -22,7 +27,6 @@ DIRS += [ + "qcms", + "gl", + "layers", +- "graphite2/src", + "ots/src", + "thebes", + "ipc", +diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build +index c51c36e2b4..4f02a9e2a5 100644 +--- a/gfx/thebes/moz.build ++++ b/gfx/thebes/moz.build +@@ -286,7 +286,10 @@ if CONFIG["MOZ_WAYLAND"]: + + LOCAL_INCLUDES += CONFIG["SKIA_INCLUDES"] + +-DEFINES["GRAPHITE2_STATIC"] = True ++if CONFIG["MOZ_SYSTEM_GRAPHITE2"]: ++ CXXFLAGS += CONFIG["MOZ_GRAPHITE2_CFLAGS"] ++else: ++ DEFINES["GRAPHITE2_STATIC"] = True + + if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: + CXXFLAGS += CONFIG["MOZ_HARFBUZZ_CFLAGS"] +diff --git a/old-configure.in b/old-configure.in +index f69f5f5456..1c1c8ecef3 100644 +--- a/old-configure.in ++++ b/old-configure.in +@@ -2204,6 +2204,27 @@ if test "$USE_FC_FREETYPE"; then + fi + fi + ++dnl ======================================================== ++dnl Check for graphite2 ++dnl ======================================================== ++if test -n "$MOZ_SYSTEM_GRAPHITE2"; then ++ dnl graphite2.pc has bogus version, check manually ++ _SAVE_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS $MOZ_GRAPHITE2_CFLAGS" ++ AC_TRY_COMPILE([ #include ++ #define GR2_VERSION_REQUIRE(major,minor,bugfix) \ ++ ( GR2_VERSION_MAJOR * 10000 + GR2_VERSION_MINOR \ ++ * 100 + GR2_VERSION_BUGFIX >= \ ++ (major) * 10000 + (minor) * 100 + (bugfix) ) ++ ], [ ++ #if !GR2_VERSION_REQUIRE(1,3,8) ++ #error "Insufficient graphite2 version." ++ #endif ++ ], [], ++ [AC_MSG_ERROR([--with-system-graphite2 requested but no working libgraphite2 found])]) ++ CFLAGS=$_SAVE_CFLAGS ++fi ++ + dnl ======================================================== + dnl Check if we need the 32-bit Linux SSE2 error dialog + dnl ======================================================== +diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build +index dd6901ba9a..be73ac4bee 100644 +--- a/toolkit/library/moz.build ++++ b/toolkit/library/moz.build +@@ -260,6 +260,9 @@ if CONFIG["MOZ_ANDROID_GOOGLE_VR"]: + "-lgvr", + ] + ++if CONFIG["MOZ_SYSTEM_GRAPHITE2"]: ++ OS_LIBS += CONFIG["MOZ_GRAPHITE2_LIBS"] ++ + if CONFIG["MOZ_SYSTEM_HARFBUZZ"]: + OS_LIBS += CONFIG["MOZ_HARFBUZZ_LIBS"] + +diff --git a/toolkit/moz.configure b/toolkit/moz.configure +index 1843188d11..a68e1b347d 100644 +--- a/toolkit/moz.configure ++++ b/toolkit/moz.configure +@@ -460,6 +460,19 @@ add_old_configure_assignment( + ) + set_define("MOZ_HAVE_FREETYPE2", depends_if(freetype2_info)(lambda _: True)) + ++# Graphite2 ++# ============================================================== ++option('--with-system-graphite2', help="Use system graphite2 (located with pkgconfig)") ++ ++@depends('--with-system-graphite2') ++def check_for_graphite2(value): ++ return bool(value) ++ ++system_graphite2 = pkg_check_modules('MOZ_GRAPHITE2', 'graphite2', ++ when=check_for_graphite2) ++ ++set_config('MOZ_SYSTEM_GRAPHITE2', depends_if(system_graphite2)(lambda _: True)) ++ + # HarfBuzz + # ============================================================== + option('--with-system-harfbuzz', help="Use system harfbuzz (located with pkgconfig)") +-- +2.34.1 + diff --git a/firefox/0006-bmo-1559213-Support-system-av1.patch b/firefox/0006-bmo-1559213-Support-system-av1.patch new file mode 100644 index 000000000..e89425812 --- /dev/null +++ b/firefox/0006-bmo-1559213-Support-system-av1.patch @@ -0,0 +1,114 @@ +From 8a4627c0c910415b00bebeb976dc6ea8c3e0d5d0 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 19:36:02 +0200 +Subject: [PATCH 06/30] bmo#1559213: Support system av1 + +Allow building against system-wide av1. + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1559213 +Signed-off-by: Thomas Deutschmann +--- + config/external/moz.build | 5 +++-- + config/system-headers.mozbuild | 8 ++++++++ + dom/media/platforms/moz.build | 5 +++++ + toolkit/moz.configure | 20 ++++++++++++++++++-- + 4 files changed, 34 insertions(+), 4 deletions(-) + +diff --git a/config/external/moz.build b/config/external/moz.build +index ab771212bf..75595d999c 100644 +--- a/config/external/moz.build ++++ b/config/external/moz.build +@@ -49,8 +49,9 @@ if not CONFIG["MOZ_SYSTEM_LIBVPX"]: + external_dirs += ["media/libvpx"] + + if CONFIG["MOZ_AV1"]: +- external_dirs += ["media/libaom"] +- external_dirs += ["media/libdav1d"] ++ if not CONFIG["MOZ_SYSTEM_AV1"]: ++ external_dirs += ["media/libaom"] ++ external_dirs += ["media/libdav1d"] + + if not CONFIG["MOZ_SYSTEM_PNG"]: + external_dirs += ["media/libpng"] +diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild +index 2f7ae39515..96ab3a6466 100644 +--- a/config/system-headers.mozbuild ++++ b/config/system-headers.mozbuild +@@ -1301,6 +1301,14 @@ if CONFIG['MOZ_ENABLE_LIBPROXY']: + 'proxy.h', + ] + ++if CONFIG['MOZ_SYSTEM_AV1']: ++ system_headers += [ ++ 'aom/aom_decoder.h', ++ 'aom/aomdx.h', ++ 'aom/aom_image.h', ++ 'dav1d/dav1d.h', ++ ] ++ + if CONFIG['MOZ_SYSTEM_LIBVPX']: + system_headers += [ + 'vpx_mem/vpx_mem.h', +diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build +index 8509aec6ef..7c5a1df63d 100644 +--- a/dom/media/platforms/moz.build ++++ b/dom/media/platforms/moz.build +@@ -78,6 +78,11 @@ if CONFIG["MOZ_AV1"]: + "agnostic/AOMDecoder.cpp", + "agnostic/DAV1DDecoder.cpp", + ] ++ if CONFIG["MOZ_SYSTEM_AV1"]: ++ CXXFLAGS += CONFIG["MOZ_SYSTEM_LIBAOM_CFLAGS"] ++ OS_LIBS += CONFIG["MOZ_SYSTEM_LIBAOM_LIBS"] ++ CXXFLAGS += CONFIG["MOZ_SYSTEM_LIBDAV1D_CFLAGS"] ++ OS_LIBS += CONFIG["MOZ_SYSTEM_LIBDAV1D_LIBS"] + + if CONFIG["MOZ_OMX"]: + EXPORTS += [ +diff --git a/toolkit/moz.configure b/toolkit/moz.configure +index a68e1b347d..7b7975bd12 100644 +--- a/toolkit/moz.configure ++++ b/toolkit/moz.configure +@@ -544,14 +544,29 @@ def av1(value): + if value: + return True + ++option("--with-system-av1", help="Use system av1 (located with pkg-config)") + +-@depends(target, when=av1 & compile_environment) ++system_libaom_info = pkg_check_modules('MOZ_SYSTEM_LIBAOM', 'aom >= 1.0.0', ++ when='--with-system-av1') ++ ++system_libdav1d_info = pkg_check_modules('MOZ_SYSTEM_LIBDAV1D', 'dav1d >= 0.1.1', ++ when='--with-system-av1') ++ ++@depends(system_libaom_info, system_libdav1d_info) ++def system_av1(system_libaom_info, system_libdav1d_info): ++ has_av1_libs = False ++ if system_libaom_info and system_libdav1d_info: ++ has_av1_libs = True ++ return has_av1_libs ++ ++ ++@depends(target, when=av1 & depends(system_av1)(lambda v: not v) & compile_environment) + def dav1d_asm(target): + if target.cpu in ("aarch64", "x86", "x86_64"): + return True + + +-@depends(target, when=av1 & compile_environment) ++@depends(target, when=av1 & depends(system_av1)(lambda v: not v) & compile_environment) + def dav1d_nasm(target): + if target.cpu in ("x86", "x86_64"): + return namespace(version="2.14", what="AV1") +@@ -561,6 +576,7 @@ set_config("MOZ_DAV1D_ASM", dav1d_asm) + set_define("MOZ_DAV1D_ASM", dav1d_asm) + set_config("MOZ_AV1", av1) + set_define("MOZ_AV1", av1) ++set_config("MOZ_SYSTEM_AV1", depends_if(system_av1)(lambda _: True)) + + # JXL Image Codec Support + # ============================================================== +-- +2.34.1 + diff --git a/firefox/0007-bmo-878089-Don-t-fail-when-TERM-is-not-set.patch b/firefox/0007-bmo-878089-Don-t-fail-when-TERM-is-not-set.patch new file mode 100644 index 000000000..6b1cde0bb --- /dev/null +++ b/firefox/0007-bmo-878089-Don-t-fail-when-TERM-is-not-set.patch @@ -0,0 +1,36 @@ +From e43f7431036904989cfd520f19de28a72be97ad9 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 19:41:43 +0200 +Subject: [PATCH 08/30] bmo#878089: Don't fail when TERM is not set + +Link: https://github.com/erikrose/blessings/pull/137 +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=878089 +Bug: https://bugs.gentoo.org/654316 +Signed-off-by: Thomas Deutschmann +--- + third_party/python/blessings/blessings/__init__.py | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/third_party/python/blessings/blessings/__init__.py b/third_party/python/blessings/blessings/__init__.py +index 388cece0b8..1283460cc9 100644 +--- a/third_party/python/blessings/blessings/__init__.py ++++ b/third_party/python/blessings/blessings/__init__.py +@@ -94,8 +94,13 @@ class Terminal(object): + # init sequences to the stream if it has a file descriptor, and + # send them to stdout as a fallback, since they have to go + # somewhere. +- setupterm(kind or environ.get('TERM', 'unknown'), +- self._init_descriptor) ++ try: ++ setupterm(kind or environ.get('TERM', 'dumb') or 'dumb', ++ self._init_descriptor) ++ except curses.error: ++ # There was an error setting up the terminal, either curses is ++ # not supported or TERM is incorrectly set. Fall back to dumb. ++ self._does_styling = False + + self.stream = stream + +-- +2.34.1 + diff --git a/firefox/0008-bmo-1516803-Fix-building-sandbox.patch b/firefox/0008-bmo-1516803-Fix-building-sandbox.patch new file mode 100644 index 000000000..24333b2d4 --- /dev/null +++ b/firefox/0008-bmo-1516803-Fix-building-sandbox.patch @@ -0,0 +1,28 @@ +From 6eeeca1b673a60d3e51427b2a5cf3e916bdb012b Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 19:44:28 +0200 +Subject: [PATCH 09/30] bmo#1516803: Fix building sandbox + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1516803 +Bug: https://bugs.gentoo.org/666580 +Signed-off-by: Thomas Deutschmann +--- + security/sandbox/linux/moz.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/sandbox/linux/moz.build b/security/sandbox/linux/moz.build +index 573f667812..e62d1a99a4 100644 +--- a/security/sandbox/linux/moz.build ++++ b/security/sandbox/linux/moz.build +@@ -116,7 +116,7 @@ if CONFIG["CC_TYPE"] in ("clang", "gcc"): + # forcing there to be only one partition. + for f in CONFIG["OS_CXXFLAGS"]: + if f.startswith("-flto") and CONFIG["CC_TYPE"] != "clang": +- LDFLAGS += ["--param lto-partitions=1"] ++ LDFLAGS += ["--param", "lto-partitions=1"] + + DEFINES["NS_NO_XPCOM"] = True + DisableStlWrapping() +-- +2.34.1 + diff --git a/firefox/0009-musl-Add-alternate-name-for-private-siginfo-struct-m.patch b/firefox/0009-musl-Add-alternate-name-for-private-siginfo-struct-m.patch new file mode 100644 index 000000000..300846f46 --- /dev/null +++ b/firefox/0009-musl-Add-alternate-name-for-private-siginfo-struct-m.patch @@ -0,0 +1,35 @@ +From d8ec0bd6f3b0ad2dfd8a97a864f08decaafdea69 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 8 Jan 2017 19:16:38 -0600 +Subject: [PATCH 10/30] musl: Add alternate name for private siginfo struct + member + +musl does not provide a macro for detecting its presence. For now, +assume that it is the only non-glibc-based libc on Linux systems. + +Signed-off-by: Samuel Holland +Signed-off-by: Thomas Deutschmann +--- + security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc +index 9884be8bb2..86d8f88e30 100644 +--- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc ++++ b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc +@@ -174,7 +174,11 @@ void Trap::SigSys(int nr, LinuxSigInfo* info, ucontext_t* ctx) { + // If the version of glibc doesn't include this information in + // siginfo_t (older than 2.17), we need to explicitly copy it + // into an arch_sigsys structure. +- memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); ++#if defined(__GLIBC__) ++ memcpy(&sigsys, &info->_sifields, sizeof(sigsys)); ++#else ++ memcpy(&sigsys, &info->__si_fields, sizeof(sigsys)); ++#endif + #endif + + #if defined(__mips__) +-- +2.34.1 + diff --git a/firefox/0010-musl-Fix-syscall-wrappers.patch b/firefox/0010-musl-Fix-syscall-wrappers.patch new file mode 100644 index 000000000..d9dda4991 --- /dev/null +++ b/firefox/0010-musl-Fix-syscall-wrappers.patch @@ -0,0 +1,42 @@ +From 1b46c0fc085fe93c36320d7ac1004c83efccdccc Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 8 Jan 2017 19:19:23 -0600 +Subject: [PATCH 11/30] musl: Fix syscall wrappers + +musl defines p{read,write}64 to their non-suffixed equivalents to avoid +duplication in its syscall wrappers. This breaks macro expansion here, +leading to errors such as: + +In function size_t sys_pread64(int, void*, size_t, off_t): + error: '__NR_pread' was not declared in this scope + +The fix here is to undefine the p{read,write}64 macros, so the syscall +expands to (e.g.) __NR_pread64 instead. + +Signed-off-by: Samuel Holland +Signed-off-by: Thomas Deutschmann +--- + .../src/third_party/lss/linux_syscall_support.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h +index 1abe0ba5b0..d6087a1674 100644 +--- a/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/lss/linux_syscall_support.h +@@ -173,6 +173,13 @@ extern "C" { + # undef __NR_waitpid + #endif + ++#ifdef pread64 ++#undef pread64 ++#endif ++#ifdef pwrite64 ++#undef pwrite64 ++#endif ++ + /* As glibc often provides subtly incompatible data structures (and implicit + * wrapper functions that convert them), we provide our own kernel data + * structures for use by the system calls. +-- +2.34.1 + diff --git a/firefox/0011-musl-Only-use-system-heap-reporter-with-glibc.patch b/firefox/0011-musl-Only-use-system-heap-reporter-with-glibc.patch new file mode 100644 index 000000000..08f02149a --- /dev/null +++ b/firefox/0011-musl-Only-use-system-heap-reporter-with-glibc.patch @@ -0,0 +1,33 @@ +From 68dd87a3dc06cf59396dccc3e031761f7237656e Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 20:09:26 +0200 +Subject: [PATCH 12/30] musl: Only use system heap reporter with glibc + +Signed-off-by: Thomas Deutschmann +--- + xpcom/base/nsMemoryReporterManager.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp +index bd4629c785..b513f81216 100644 +--- a/xpcom/base/nsMemoryReporterManager.cpp ++++ b/xpcom/base/nsMemoryReporterManager.cpp +@@ -647,6 +647,7 @@ static bool InSharedRegion(mach_vm_address_t aAddr, cpu_type_t aType) { + return NS_OK; + } + ++#ifdef __GLIBC__ + # define HAVE_SYSTEM_HEAP_REPORTER 1 + // Windows can have multiple separate heaps, but we should not touch non-default + // heaps because they may be destroyed at anytime while we hold a handle. So we +@@ -679,6 +680,7 @@ static bool InSharedRegion(mach_vm_address_t aAddr, cpu_type_t aType) { + *aSizeOut = heapSize; + return NS_OK; + } ++#endif + + struct SegmentKind { + DWORD mState; +-- +2.34.1 + diff --git a/firefox/0012-musl-Set-pthread-name-for-non-glibc-systems.patch b/firefox/0012-musl-Set-pthread-name-for-non-glibc-systems.patch new file mode 100644 index 000000000..fe74bb1b1 --- /dev/null +++ b/firefox/0012-musl-Set-pthread-name-for-non-glibc-systems.patch @@ -0,0 +1,29 @@ +From 70d47d18420fe9e3de8f896c08f97ef2596c9c84 Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 20:10:03 +0200 +Subject: [PATCH 13/30] musl: Set pthread name for non glibc systems + +Signed-off-by: Thomas Deutschmann +--- + js/src/threading/posix/PosixThread.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/js/src/threading/posix/PosixThread.cpp b/js/src/threading/posix/PosixThread.cpp +index 35532e375b..983da45326 100644 +--- a/js/src/threading/posix/PosixThread.cpp ++++ b/js/src/threading/posix/PosixThread.cpp +@@ -115,8 +115,10 @@ void ThisThread::SetName(const char* name) { + rv = 0; + #elif defined(__NetBSD__) + rv = pthread_setname_np(pthread_self(), "%s", (void*)name); +-#else ++#elif defined(__GLIBC__) + rv = pthread_setname_np(pthread_self(), name); ++#else ++ rv = 0; + #endif + MOZ_RELEASE_ASSERT(!rv); + } +-- +2.34.1 + diff --git a/firefox/0013-musl-getcontext-is-only-avaliable-on-glibc-systems.patch b/firefox/0013-musl-getcontext-is-only-avaliable-on-glibc-systems.patch new file mode 100644 index 000000000..e9cf02e67 --- /dev/null +++ b/firefox/0013-musl-getcontext-is-only-avaliable-on-glibc-systems.patch @@ -0,0 +1,28 @@ +From 3283cc3981f99894dec1219fbf380489905827a9 Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 20:10:47 +0200 +Subject: [PATCH 14/30] musl: getcontext is only avaliable on glibc systems + +Signed-off-by: Thomas Deutschmann +--- + tools/profiler/core/platform-linux-android.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/profiler/core/platform-linux-android.cpp b/tools/profiler/core/platform-linux-android.cpp +index d065387552..aaca9e81e4 100644 +--- a/tools/profiler/core/platform-linux-android.cpp ++++ b/tools/profiler/core/platform-linux-android.cpp +@@ -603,8 +603,10 @@ static void PlatformInit(PSLockRef aLock) {} + + #if defined(HAVE_NATIVE_UNWIND) + void Registers::SyncPopulate() { ++#if defined(__GLIBC__) + if (!getcontext(&mContextSyncStorage)) { + PopulateRegsFromContext(*this, &mContextSyncStorage); + } ++#endif + } + #endif +-- +2.34.1 + diff --git a/firefox/0014-musl-sys-auvx.h-avaliable-on-more-then-just-glibc-sy.patch b/firefox/0014-musl-sys-auvx.h-avaliable-on-more-then-just-glibc-sy.patch new file mode 100644 index 000000000..121c8cdc2 --- /dev/null +++ b/firefox/0014-musl-sys-auvx.h-avaliable-on-more-then-just-glibc-sy.patch @@ -0,0 +1,51 @@ +From beed745f96bbc18a3c22a728095c9a2eef7435ee Mon Sep 17 00:00:00 2001 +From: "Jory A. Pratt" +Date: Mon, 6 Apr 2020 20:12:09 +0200 +Subject: [PATCH 15/30] musl: sys/auvx.h avaliable on more then just glibc + systems + +Signed-off-by: Thomas Deutschmann +--- + .../system_wrappers/source/cpu_features_linux.cc | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/third_party/libwebrtc/system_wrappers/source/cpu_features_linux.cc b/third_party/libwebrtc/system_wrappers/source/cpu_features_linux.cc +index 335bed4da3..c2c98dae8a 100644 +--- a/third_party/libwebrtc/system_wrappers/source/cpu_features_linux.cc ++++ b/third_party/libwebrtc/system_wrappers/source/cpu_features_linux.cc +@@ -12,13 +12,7 @@ + #include + #include + +-#ifdef __GLIBC_PREREQ +-#define WEBRTC_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b) +-#else +-#define WEBRTC_GLIBC_PREREQ(a, b) 0 +-#endif +- +-#if WEBRTC_GLIBC_PREREQ(2, 16) ++#if defined(__linux__) + #include + #else + #include +@@ -40,7 +34,7 @@ uint64_t GetCPUFeaturesARM(void) { + int architecture = 0; + uint64_t hwcap = 0; + const char* platform = NULL; +-#if WEBRTC_GLIBC_PREREQ(2, 16) ++#if defined(__linux__) + hwcap = getauxval(AT_HWCAP); + platform = (const char*)getauxval(AT_PLATFORM); + #else +@@ -64,7 +58,7 @@ uint64_t GetCPUFeaturesARM(void) { + } + close(fd); + } +-#endif // WEBRTC_GLIBC_PREREQ(2, 16) ++#endif // (__linux__) + #if defined(__aarch64__) + architecture = 8; + if ((hwcap & HWCAP_FP) != 0) +-- +2.34.1 + diff --git a/firefox/0015-musl-make-SYS_fork-non-fatal-musl-uses-it-for-fork-2.patch b/firefox/0015-musl-make-SYS_fork-non-fatal-musl-uses-it-for-fork-2.patch new file mode 100644 index 000000000..9de0db79f --- /dev/null +++ b/firefox/0015-musl-make-SYS_fork-non-fatal-musl-uses-it-for-fork-2.patch @@ -0,0 +1,28 @@ +From 6d36ed9e971861321bb381e25516500069314eb6 Mon Sep 17 00:00:00 2001 +From: Johannes +Date: Fri, 1 May 2020 17:20:29 +0200 +Subject: [PATCH 16/30] musl: make SYS_fork non-fatal, musl uses it for fork(2) + +Signed-off-by: Thomas Deutschmann +--- + security/sandbox/linux/SandboxFilter.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp +index eb72d944c8..8ce22d6f65 100644 +--- a/security/sandbox/linux/SandboxFilter.cpp ++++ b/security/sandbox/linux/SandboxFilter.cpp +@@ -1537,6 +1537,10 @@ class ContentSandboxPolicy : public SandboxPolicyCommon { + // usually do something reasonable on error. + case __NR_clone: + return ClonePolicy(Error(EPERM)); ++# ifdef __NR_fork ++ case __NR_fork: ++ return Error(ENOSYS); ++# endif + + case __NR_clone3: + return Error(ENOSYS); +-- +2.34.1 + diff --git a/firefox/0016-musl-include-net-if.h-before-linux-if.h-to-avoid-red.patch b/firefox/0016-musl-include-net-if.h-before-linux-if.h-to-avoid-red.patch new file mode 100644 index 000000000..de7778009 --- /dev/null +++ b/firefox/0016-musl-include-net-if.h-before-linux-if.h-to-avoid-red.patch @@ -0,0 +1,27 @@ +From 08a7a0d7fa52e1bdacdcb47e847cf5ecd980ee6f Mon Sep 17 00:00:00 2001 +From: Rasmus Thomsen +Date: Wed, 28 Oct 2020 17:50:24 +0100 +Subject: [PATCH 17/30] musl: include net/if.h before linux/if.h to avoid + redefinition + +Bug: https://bugs.gentoo.org/751469 +Signed-off-by: Thomas Deutschmann +--- + .../webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c +index 73e85c6ccc..9eca548638 100644 +--- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c ++++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs-netlink.c +@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + #if defined(LINUX) ++#include + #include "addrs-netlink.h" + #include + #include +-- +2.34.1 + diff --git a/firefox/0017-Make-PGO-use-toolchain.patch b/firefox/0017-Make-PGO-use-toolchain.patch new file mode 100644 index 000000000..3f72b0529 --- /dev/null +++ b/firefox/0017-Make-PGO-use-toolchain.patch @@ -0,0 +1,33 @@ +From 45d43bb2dc1c1c033c860951c93261e98647f851 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 20:13:34 +0200 +Subject: [PATCH 18/30] Make PGO use toolchain + +Signed-off-by: Thomas Deutschmann +--- + build/unix/mozconfig.unix | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/build/unix/mozconfig.unix b/build/unix/mozconfig.unix +index 9ca9c97fce..9f86fe0940 100644 +--- a/build/unix/mozconfig.unix ++++ b/build/unix/mozconfig.unix +@@ -4,6 +4,15 @@ if [ -n "$FORCE_GCC" ]; then + CC="$MOZ_FETCHES_DIR/gcc/bin/gcc" + CXX="$MOZ_FETCHES_DIR/gcc/bin/g++" + ++ if [ -n "$MOZ_PGO" ]; then ++ if [ -z "$USE_ARTIFACT" ]; then ++ ac_add_options --enable-lto ++ fi ++ export AR="$topsrcdir/gcc/bin/gcc-ar" ++ export NM="$topsrcdir/gcc/bin/gcc-nm" ++ export RANLIB="$topsrcdir/gcc/bin/gcc-ranlib" ++ fi ++ + # We want to make sure we use binutils and other binaries in the tooltool + # package. + mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$PATH" +-- +2.34.1 + diff --git a/firefox/0018-bmo-1516081-Disable-watchdog-during-PGO-builds.patch b/firefox/0018-bmo-1516081-Disable-watchdog-during-PGO-builds.patch new file mode 100644 index 000000000..70cf5c3c7 --- /dev/null +++ b/firefox/0018-bmo-1516081-Disable-watchdog-during-PGO-builds.patch @@ -0,0 +1,55 @@ +From 2502829abc1a02a08cc1934538c3d30e6f4f6fae Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Mon, 6 Apr 2020 20:27:06 +0200 +Subject: [PATCH 19/30] bmo#1516081: Disable watchdog during PGO builds + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1516081 +Signed-off-by: Thomas Deutschmann +--- + build/moz.configure/lto-pgo.configure | 4 ++-- + toolkit/components/terminator/nsTerminator.cpp | 7 +++++++ + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/build/moz.configure/lto-pgo.configure b/build/moz.configure/lto-pgo.configure +index e5a4e6f913..567ccf0ba4 100644 +--- a/build/moz.configure/lto-pgo.configure ++++ b/build/moz.configure/lto-pgo.configure +@@ -84,7 +84,7 @@ set_config("PGO_PROFILE_PATH", pgo_profile_path) + def pgo_flags(compiler, profdata, target_is_windows): + if compiler.type == "gcc": + return namespace( +- gen_cflags=["-fprofile-generate"], ++ gen_cflags=["-fprofile-generate", "-DMOZ_PROFILE_INSTRUMENTATION"], + gen_ldflags=["-fprofile-generate"], + use_cflags=["-fprofile-use", "-fprofile-correction", "-Wcoverage-mismatch"], + use_ldflags=["-fprofile-use"], +@@ -98,7 +98,7 @@ def pgo_flags(compiler, profdata, target_is_windows): + else: + gen_ldflags = ["-fprofile-generate"] + +- gen_cflags = [prefix + "-fprofile-generate"] ++ gen_cflags = [prefix + "-fprofile-generate", "-DMOZ_PROFILE_INSTRUMENTATION"] + if target_is_windows: + # native llvm-profdata.exe on Windows can't read profile data + # if name compression is enabled (which cross-compiling enables +diff --git a/toolkit/components/terminator/nsTerminator.cpp b/toolkit/components/terminator/nsTerminator.cpp +index 194bb36e2d..c960d44137 100644 +--- a/toolkit/components/terminator/nsTerminator.cpp ++++ b/toolkit/components/terminator/nsTerminator.cpp +@@ -466,6 +466,13 @@ void nsTerminator::StartWatchdog() { + } + #endif + ++ // Disable watchdog for PGO train builds - writting profile information at ++ // exit may take time and it is better to make build hang rather than ++ // silently produce poorly performing binary. ++#ifdef MOZ_PROFILE_INSTRUMENTATION ++ crashAfterMS = INT32_MAX; ++#endif ++ + UniquePtr options(new Options()); + const PRIntervalTime ticksDuration = + PR_MillisecondsToInterval(HEARTBEAT_INTERVAL_MS); +-- +2.34.1 + diff --git a/firefox/0019-bmo-1516803-force-one-LTO-partition-for-sandbox-when.patch b/firefox/0019-bmo-1516803-force-one-LTO-partition-for-sandbox-when.patch new file mode 100644 index 000000000..ef8f9b2e6 --- /dev/null +++ b/firefox/0019-bmo-1516803-force-one-LTO-partition-for-sandbox-when.patch @@ -0,0 +1,32 @@ +From 0501ed4bbdbf8d16a69a4460d2ada33ac259365d Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Wed, 15 Apr 2020 00:27:25 +0200 +Subject: [PATCH 20/30] bmo#1516803: force one LTO partition for sandbox when + using GCC + +Signed-off-by: Thomas Deutschmann +--- + security/sandbox/linux/moz.build | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/security/sandbox/linux/moz.build b/security/sandbox/linux/moz.build +index e62d1a99a4..913b9ba2ce 100644 +--- a/security/sandbox/linux/moz.build ++++ b/security/sandbox/linux/moz.build +@@ -114,9 +114,10 @@ if CONFIG["CC_TYPE"] in ("clang", "gcc"): + # gcc lto likes to put the top level asm in syscall.cc in a different partition + # from the function using it which breaks the build. Work around that by + # forcing there to be only one partition. +-for f in CONFIG["OS_CXXFLAGS"]: +- if f.startswith("-flto") and CONFIG["CC_TYPE"] != "clang": +- LDFLAGS += ["--param", "lto-partitions=1"] ++if CONFIG["CC_TYPE"] != "clang" and CONFIG["MOZ_LTO_LDFLAGS"] is not None: ++ for f in CONFIG["MOZ_LTO_LDFLAGS"]: ++ if f.startswith("-flto"): ++ LDFLAGS += ["--param", "lto-partitions=1"] + + DEFINES["NS_NO_XPCOM"] = True + DisableStlWrapping() +-- +2.34.1 + diff --git a/firefox/0020-Fix-building-with-PGO-when-using-GCC.patch b/firefox/0020-Fix-building-with-PGO-when-using-GCC.patch new file mode 100644 index 000000000..81de54b8f --- /dev/null +++ b/firefox/0020-Fix-building-with-PGO-when-using-GCC.patch @@ -0,0 +1,84 @@ +From 98e1e605c8fdf7b021d6f1888ce6baed5c1097b5 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Thu, 2 Jul 2020 18:05:03 +0200 +Subject: [PATCH 22/30] Fix building with PGO when using GCC + +Signed-off-by: Thomas Deutschmann +--- + build/moz.configure/lto-pgo.configure | 5 +++-- + build/pgo/profileserver.py | 26 ++++++++++++++++++++++---- + 2 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/build/moz.configure/lto-pgo.configure b/build/moz.configure/lto-pgo.configure +index 567ccf0ba4..c6470ef829 100644 +--- a/build/moz.configure/lto-pgo.configure ++++ b/build/moz.configure/lto-pgo.configure +@@ -83,11 +83,12 @@ set_config("PGO_PROFILE_PATH", pgo_profile_path) + @imports("multiprocessing") + def pgo_flags(compiler, profdata, target_is_windows): + if compiler.type == "gcc": ++ profile_use = "-fprofile-use" + return namespace( + gen_cflags=["-fprofile-generate", "-DMOZ_PROFILE_INSTRUMENTATION"], + gen_ldflags=["-fprofile-generate"], +- use_cflags=["-fprofile-use", "-fprofile-correction", "-Wcoverage-mismatch"], +- use_ldflags=["-fprofile-use"], ++ use_cflags=[profile_use, "-fprofile-correction", "-Wcoverage-mismatch"], ++ use_ldflags=[profile_use], + ) + + if compiler.type in ("clang-cl", "clang"): +diff --git a/build/pgo/profileserver.py b/build/pgo/profileserver.py +index 7f3de106ab..89289a7756 100755 +--- a/build/pgo/profileserver.py ++++ b/build/pgo/profileserver.py +@@ -11,7 +11,7 @@ import glob + import subprocess + + import mozcrash +-from mozbuild.base import MozbuildObject, BinaryNotFoundException ++from mozbuild.base import MozbuildObject, BinaryNotFoundException, BuildEnvironmentNotFoundException + from mozfile import TemporaryDirectory + from mozhttpd import MozHttpd + from mozprofile import FirefoxProfile, Preferences +@@ -87,9 +87,22 @@ if __name__ == "__main__": + locations = ServerLocations() + locations.add_host(host="127.0.0.1", port=PORT, options="primary,privileged") + +- old_profraw_files = glob.glob("*.profraw") +- for f in old_profraw_files: +- os.remove(f) ++ using_gcc = False ++ try: ++ if build.config_environment.substs.get("CC_TYPE") == "gcc": ++ using_gcc = True ++ except BuildEnvironmentNotFoundException: ++ pass ++ ++ if using_gcc: ++ for dirpath, _, filenames in os.walk("."): ++ for f in filenames: ++ if f.endswith(".gcda"): ++ os.remove(os.path.join(dirpath, f)) ++ else: ++ old_profraw_files = glob.glob("*.profraw") ++ for f in old_profraw_files: ++ os.remove(f) + + with TemporaryDirectory() as profilePath: + # TODO: refactor this into mozprofile +@@ -212,6 +225,11 @@ if __name__ == "__main__": + print("Firefox exited successfully, but produced a crashreport") + sys.exit(1) + ++ if using_gcc: ++ print("Copying profile data...") ++ os.system("pwd"); ++ os.system('tar cf profdata.tar.gz `find . -name "*.gcda"`; cd ..; tar xf instrumented/profdata.tar.gz;'); ++ + llvm_profdata = env.get("LLVM_PROFDATA") + if llvm_profdata: + profraw_files = glob.glob("*.profraw") +-- +2.34.1 + diff --git a/firefox/0021-libaom-Use-NEON_FLAGS-instead-of-VPX_ASFLAGS-for-lib.patch b/firefox/0021-libaom-Use-NEON_FLAGS-instead-of-VPX_ASFLAGS-for-lib.patch new file mode 100644 index 000000000..85c305f07 --- /dev/null +++ b/firefox/0021-libaom-Use-NEON_FLAGS-instead-of-VPX_ASFLAGS-for-lib.patch @@ -0,0 +1,28 @@ +From 6e220b49aee7dbdcafd255f6260517c5c551f9b1 Mon Sep 17 00:00:00 2001 +From: Mike Hommey +Date: Mon, 26 Nov 2018 09:59:56 +0900 +Subject: [PATCH 23/30] libaom: Use NEON_FLAGS instead of VPX_ASFLAGS for + libaom neon code + +Bug: https://bugs.gentoo.org/730606 +Signed-off-by: Thomas Deutschmann +--- + media/libaom/moz.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/media/libaom/moz.build b/media/libaom/moz.build +index fd8c7f2b33..db3f9ca6ec 100644 +--- a/media/libaom/moz.build ++++ b/media/libaom/moz.build +@@ -55,7 +55,7 @@ elif CONFIG['CPU_ARCH'] == 'arm': + + for f in SOURCES: + if f.endswith('neon.c'): +- SOURCES[f].flags += CONFIG['VPX_ASFLAGS'] ++ SOURCES[f].flags += CONFIG['NEON_FLAGS'] + + if CONFIG['OS_TARGET'] == 'Android': + # For cpu-features.h +-- +2.34.1 + diff --git a/firefox/0022-build-Disable-Werror.patch b/firefox/0022-build-Disable-Werror.patch new file mode 100644 index 000000000..1e831ae67 --- /dev/null +++ b/firefox/0022-build-Disable-Werror.patch @@ -0,0 +1,13 @@ +diff -Naur a/build/moz.configure/warnings.configure b/build/moz.configure/warnings.configure +--- a/build/moz.configure/warnings.configure 2022-05-27 02:16:52.000000000 +0300 ++++ b/build/moz.configure/warnings.configure 2022-05-31 10:48:22.990378071 +0300 +@@ -293,7 +293,8 @@ + check_and_add_warning("-Wno-gnu-zero-variadic-macro-arguments") + + # Make it an error to be missing function declarations for C code. +-check_and_add_warning("-Werror=implicit-function-declaration", c_compiler) ++check_and_add_warning("-Werror=implicit-function-declaration", ++ when="--enable-warnings-as-errors") + + # New in clang 11. We can't really do anything about this warning. + check_and_add_warning("-Wno-psabi") diff --git a/firefox/0023-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch b/firefox/0023-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch new file mode 100644 index 000000000..32bd0eb89 --- /dev/null +++ b/firefox/0023-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch @@ -0,0 +1,34 @@ +From 685e82ac82921720c6cd9c6c45703ff034f081e7 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Sat, 29 Aug 2020 22:30:59 +0200 +Subject: [PATCH 25/30] LTO: Only enable LTO for Rust when complete build uses + LTO + +Signed-off-by: Thomas Deutschmann +--- + config/makefiles/rust.mk | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/config/makefiles/rust.mk b/config/makefiles/rust.mk +index 75570d32b9..924722a506 100644 +--- a/config/makefiles/rust.mk ++++ b/config/makefiles/rust.mk +@@ -87,6 +87,7 @@ endif + # These flags are passed via `cargo rustc` and only apply to the final rustc + # invocation (i.e., only the top-level crate, not its dependencies). + cargo_rustc_flags = $(CARGO_RUSTCFLAGS) ++ifdef MOZ_LTO + ifndef DEVELOPER_OPTIONS + ifndef MOZ_DEBUG_RUST + # Enable link-time optimization for release builds, but not when linking +@@ -106,6 +107,7 @@ endif + endif + endif + endif ++endif + + ifdef CARGO_INCREMENTAL + export CARGO_INCREMENTAL +-- +2.34.1 + diff --git a/firefox/0024-Enable-FLAC-on-platforms-without-ffvpx-via-ffmpeg.patch b/firefox/0024-Enable-FLAC-on-platforms-without-ffvpx-via-ffmpeg.patch new file mode 100644 index 000000000..2c6a27121 --- /dev/null +++ b/firefox/0024-Enable-FLAC-on-platforms-without-ffvpx-via-ffmpeg.patch @@ -0,0 +1,36 @@ +From 58b0385412c6d96eb745e2fc5902df347e629f6d Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Thu, 29 Apr 2021 18:48:06 +0200 +Subject: [PATCH 28/30] Enable FLAC on platforms without ffvpx via ffmpeg + +Signed-off-by: Thomas Deutschmann +--- + dom/media/flac/FlacDecoder.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/dom/media/flac/FlacDecoder.cpp b/dom/media/flac/FlacDecoder.cpp +index 2f205c9aae..68847b0952 100644 +--- a/dom/media/flac/FlacDecoder.cpp ++++ b/dom/media/flac/FlacDecoder.cpp +@@ -7,6 +7,7 @@ + #include "FlacDecoder.h" + #include "MediaContainerType.h" + #include "mozilla/StaticPrefs_media.h" ++#include "PDMFactory.h" + + namespace mozilla { + +@@ -14,6 +15,10 @@ namespace mozilla { + bool FlacDecoder::IsEnabled() { + #ifdef MOZ_FFVPX + return StaticPrefs::media_flac_enabled(); ++#elif defined(MOZ_FFMPEG) ++ RefPtr platform = new PDMFactory(); ++ return StaticPrefs::media_flac_enabled() && ++ platform->SupportsMimeType("audio/flac"_ns); + #else + return false; + #endif +-- +2.34.1 + diff --git a/firefox/0025-bmo-1670333-OpenH264-Fix-decoding-if-it-starts-on-no.patch b/firefox/0025-bmo-1670333-OpenH264-Fix-decoding-if-it-starts-on-no.patch new file mode 100644 index 000000000..856361df3 --- /dev/null +++ b/firefox/0025-bmo-1670333-OpenH264-Fix-decoding-if-it-starts-on-no.patch @@ -0,0 +1,96 @@ +From 0b53fcfa8ee76ccc2d77abb947810f631efaecd9 Mon Sep 17 00:00:00 2001 +From: Thomas Deutschmann +Date: Fri, 11 Dec 2020 15:37:38 +0100 +Subject: [PATCH 29/30] bmo#1670333: OpenH264: Fix decoding if it starts on non + IDR I-frame + +Signed-off-by: Thomas Deutschmann +--- + dom/media/mp4/MP4Demuxer.cpp | 8 ++++++++ + dom/media/platforms/PDMFactory.cpp | 15 ++++++++++----- + dom/media/platforms/PDMFactory.h | 2 ++ + 3 files changed, 20 insertions(+), 5 deletions(-) + +diff --git a/dom/media/mp4/MP4Demuxer.cpp b/dom/media/mp4/MP4Demuxer.cpp +index 59bba16577..0304e3e89f 100644 +--- a/dom/media/mp4/MP4Demuxer.cpp ++++ b/dom/media/mp4/MP4Demuxer.cpp +@@ -31,6 +31,8 @@ mozilla::LogModule* GetDemuxerLog() { return gMediaDemuxerLog; } + DDMOZ_LOG(gMediaDemuxerLog, mozilla::LogLevel::Debug, "::%s: " arg, \ + __func__, ##__VA_ARGS__) + ++extern bool gUseKeyframeFromContainer; ++ + namespace mozilla { + + DDLoggedTypeDeclNameAndBase(MP4TrackDemuxer, MediaTrackDemuxer); +@@ -394,6 +396,12 @@ already_AddRefed MP4TrackDemuxer::GetNextSample() { + [[fallthrough]]; + case H264::FrameType::OTHER: { + bool keyframe = type == H264::FrameType::I_FRAME; ++ if (gUseKeyframeFromContainer) { ++ if (sample->mKeyframe && sample->mKeyframe != keyframe) { ++ sample->mKeyframe = keyframe; ++ } ++ break; ++ } + if (sample->mKeyframe != keyframe) { + NS_WARNING(nsPrintfCString("Frame incorrectly marked as %skeyframe " + "@ pts:%" PRId64 " dur:%" PRId64 +diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp +index 4e377082ae..e778eb9948 100644 +--- a/dom/media/platforms/PDMFactory.cpp ++++ b/dom/media/platforms/PDMFactory.cpp +@@ -58,6 +58,8 @@ + + #include + ++bool gUseKeyframeFromContainer = false; ++ + namespace mozilla { + + #define PDM_INIT_LOG(msg, ...) \ +@@ -536,10 +538,12 @@ void PDMFactory::CreateContentPDMs() { + } + #endif + #ifdef MOZ_FFMPEG +- if (StaticPrefs::media_ffmpeg_enabled() && +- !CreateAndStartupPDM()) { +- mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( +- FFmpegRuntimeLinker::LinkStatusCode()); ++ if (StaticPrefs::media_ffmpeg_enabled()) { ++ mFFmpegUsed = CreateAndStartupPDM(); ++ if (!mFFmpegUsed) { ++ mFailureFlags += GetFailureFlagBasedOnFFmpegStatus( ++ FFmpegRuntimeLinker::LinkStatusCode()); ++ } + } + #endif + #ifdef MOZ_FFVPX +@@ -556,8 +560,9 @@ void PDMFactory::CreateContentPDMs() { + + CreateAndStartupPDM(); + +- if (StaticPrefs::media_gmp_decoder_enabled() && ++ if (StaticPrefs::media_gmp_decoder_enabled() && !mFFmpegUsed && + !CreateAndStartupPDM()) { ++ gUseKeyframeFromContainer = true; + mFailureFlags += DecoderDoctorDiagnostics::Flags::GMPPDMFailedToStartup; + } + } +diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h +index 4fc81c0b37..72f3255b6f 100644 +--- a/dom/media/platforms/PDMFactory.h ++++ b/dom/media/platforms/PDMFactory.h +@@ -122,6 +122,8 @@ class PDMFactory final { + + DecoderDoctorDiagnostics::FlagsSet mFailureFlags; + ++ bool mFFmpegUsed = false; ++ + friend class RemoteVideoDecoderParent; + static void EnsureInit(); + }; +-- +2.34.1 + diff --git a/firefox/0026-bmo-1663844-OpenH264-Allow-using-OpenH264-GMP-decode.patch b/firefox/0026-bmo-1663844-OpenH264-Allow-using-OpenH264-GMP-decode.patch new file mode 100644 index 000000000..4cc43ea5d --- /dev/null +++ b/firefox/0026-bmo-1663844-OpenH264-Allow-using-OpenH264-GMP-decode.patch @@ -0,0 +1,37 @@ +diff -up firefox-101.0.1/dom/media/gmp/GMPSharedMemManager.h.1663844 firefox-101.0.1/dom/media/gmp/GMPSharedMemManager.h +--- firefox-101.0.1/dom/media/gmp/GMPSharedMemManager.h.1663844 2022-06-08 23:06:36.000000000 +0200 ++++ firefox-101.0.1/dom/media/gmp/GMPSharedMemManager.h 2022-06-09 17:17:04.775008085 +0200 +@@ -27,7 +27,7 @@ class GMPSharedMem { + // returned to the parent pool (which is not included). If more than + // this are needed, we presume the client has either crashed or hung + // (perhaps temporarily). +- static const uint32_t kGMPBufLimit = 20; ++ static const uint32_t kGMPBufLimit = 40; + + GMPSharedMem() { + for (size_t i = 0; i < sizeof(mGmpAllocated) / sizeof(mGmpAllocated[0]); +diff -up firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844 firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp +--- firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844 2022-06-08 16:10:21.000000000 +0200 ++++ firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp 2022-06-09 20:31:25.120035588 +0200 +@@ -84,6 +84,9 @@ media::DecodeSupportSet GMPDecoderModule + + media::DecodeSupportSet GMPDecoderModule::SupportsMimeType( + const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { ++ if (MP4Decoder::IsH264(aMimeType)) { ++ return media::DecodeSupport::SoftwareDecode; ++ } + return media::DecodeSupport::Unsupported; + } + +diff -up firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844 firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp +--- firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844 2022-06-08 16:10:21.000000000 +0200 ++++ firefox-101.0.1/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp 2022-06-09 17:17:04.776008117 +0200 +@@ -70,6 +70,8 @@ void GMPVideoDecoder::Decoded(GMPVideoi4 + RefPtr self = this; + if (v) { + mDecodedData.AppendElement(std::move(v)); ++ mDecodePromise.ResolveIfExists(std::move(mDecodedData), __func__); ++ mDecodedData = DecodedData(); + } else { + mDecodedData.Clear(); + mDecodePromise.RejectIfExists( diff --git a/firefox/0027-bgo-816975-fix-build-on-x86.patch b/firefox/0027-bgo-816975-fix-build-on-x86.patch new file mode 100644 index 000000000..4b2289fab --- /dev/null +++ b/firefox/0027-bgo-816975-fix-build-on-x86.patch @@ -0,0 +1,16 @@ +diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h +index 51d79f9c2ec59..fafd7d6fc1e0d 100644 +--- a/modules/fdlibm/src/math_private.h ++++ b/modules/fdlibm/src/math_private.h +@@ -30,7 +30,11 @@ + * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t + */ + ++#if defined __FLT_EVAL_METHOD__ && (__FLT_EVAL_METHOD__ == 2) ++typedef long double __double_t; ++#else + typedef double __double_t; ++#endif + typedef __double_t double_t; + + /* diff --git a/firefox/0028-bmo-1559213-fix-system-av1-libs.patch b/firefox/0028-bmo-1559213-fix-system-av1-libs.patch new file mode 100644 index 000000000..2423ccaca --- /dev/null +++ b/firefox/0028-bmo-1559213-fix-system-av1-libs.patch @@ -0,0 +1,22 @@ +diff --git a/media/ffvpx/libavcodec/moz.build b/media/ffvpx/libavcodec/moz.build +index 0069865..e806fc8 100644 +--- a/media/ffvpx/libavcodec/moz.build ++++ b/media/ffvpx/libavcodec/moz.build +@@ -112,9 +112,15 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: + 'vaapi_vp8.c', + 'vaapi_vp9.c', + ] ++ if CONFIG["MOZ_SYSTEM_AV1"]: ++ CFLAGS += CONFIG['MOZ_SYSTEM_LIBDAV1D_CFLAGS'] ++ OS_LIBS += CONFIG['MOZ_SYSTEM_LIBDAV1D_LIBS'] ++ else: ++ USE_LIBS += [ ++ 'dav1d', ++ 'media_libdav1d_asm', ++ ] + USE_LIBS += [ +- 'dav1d', +- 'media_libdav1d_asm', + 'mozva' + ] + diff --git a/firefox/0029-bmo-1196777-Set-GDK_FOCUS_CHANGE_MASK.patch b/firefox/0029-bmo-1196777-Set-GDK_FOCUS_CHANGE_MASK.patch new file mode 100644 index 000000000..864741e5b --- /dev/null +++ b/firefox/0029-bmo-1196777-Set-GDK_FOCUS_CHANGE_MASK.patch @@ -0,0 +1,13 @@ +diff -up firefox-100.0/widget/gtk/nsWindow.cpp.1196777 firefox-100.0/widget/gtk/nsWindow.cpp +--- firefox-100.0/widget/gtk/nsWindow.cpp.1196777 2022-05-02 11:29:06.763325015 +0200 ++++ firefox-100.0/widget/gtk/nsWindow.cpp 2022-05-02 11:30:49.100717334 +0200 +@@ -163,7 +163,8 @@ const gint kEvents = GDK_TOUCHPAD_GESTUR + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SCROLL_MASK | +- GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK; ++ GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK | ++ GDK_FOCUS_CHANGE_MASK; + + /* utility functions */ + static bool is_mouse_in_window(GdkWindow* aWindow, gdouble aMouseX, diff --git a/firefox/0030-bmo-1754469-memory_mozalloc_throw.patch b/firefox/0030-bmo-1754469-memory_mozalloc_throw.patch new file mode 100644 index 000000000..634892be7 --- /dev/null +++ b/firefox/0030-bmo-1754469-memory_mozalloc_throw.patch @@ -0,0 +1,69 @@ +--- a/memory/mozalloc/throw_gcc.h 2022-02-02 17:33:38 UTC ++++ b/memory/mozalloc/throw_gcc.h +@@ -74,50 +74,66 @@ __throw_bad_function_call(void) { + mozalloc_abort("fatal: STL threw bad_function_call"); + } + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_logic_error( + const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_domain_error( + const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void + __throw_invalid_argument(const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_length_error( + const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_out_of_range( + const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_runtime_error( + const char* msg) { + mozalloc_abort(msg); + } + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_range_error( + const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void + __throw_overflow_error(const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + ++#if !defined(_LIBCPP_VERSION) + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void + __throw_underflow_error(const char* msg) { + mozalloc_abort(msg); + } ++#endif // _LIBCPP_VERSION + + MOZ_THROW_NORETURN MOZ_THROW_EXPORT MOZ_THROW_INLINE void __throw_ios_failure( + const char* msg) { diff --git a/firefox/0031-bmo-1769631-python-3.11-compatibility.patch b/firefox/0031-bmo-1769631-python-3.11-compatibility.patch new file mode 100644 index 000000000..97ac3ceff --- /dev/null +++ b/firefox/0031-bmo-1769631-python-3.11-compatibility.patch @@ -0,0 +1,30 @@ +# https://src.fedoraproject.org/rpms/firefox/c/4d45de9bff7b7ef01f7d3c9e53a61adc9cf3ce9e?branch=4d45de9bff7b7ef01f7d3c9e53a61adc9cf3ce9e + +diff -up firefox-102.0/xpcom/idl-parser/xpidl/xpidl.py.build-python-3.11 firefox-102.0/xpcom/idl-parser/xpidl/xpidl.py +--- firefox-102.0/xpcom/idl-parser/xpidl/xpidl.py.build-python-3.11 2022-06-23 09:10:31.000000000 +0200 ++++ firefox-102.0/xpcom/idl-parser/xpidl/xpidl.py 2022-07-15 16:18:52.048351493 +0200 +@@ -1572,13 +1572,13 @@ class IDLParser(object): + t_ignore = " \t" + + def t_multilinecomment(self, t): +- r"/\*(?s).*?\*/" ++ r"/\*(?s:.)*?\*/" + t.lexer.lineno += t.value.count("\n") + if t.value.startswith("/**"): + self._doccomments.append(t.value) + + def t_singlelinecomment(self, t): +- r"(?m)//.*?$" ++ r"(?m://.*?$)" + + def t_IID(self, t): + return t +@@ -1591,7 +1591,7 @@ class IDLParser(object): + return t + + def t_LCDATA(self, t): +- r"(?s)%\{[ ]*C\+\+[ ]*\n(?P.*?\n?)%\}[ ]*(C\+\+)?" ++ r"(?s:%\{[ ]*C\+\+[ ]*\n(?P.*?\n?)%\}[ ]*(C\+\+)?)" + t.type = "CDATA" + t.value = t.lexer.lexmatch.group("cdata") + t.lexer.lineno += t.value.count("\n") diff --git a/firefox/0032-bmo-1773336-disable_audio_thread_priority_default_features.patch b/firefox/0032-bmo-1773336-disable_audio_thread_priority_default_features.patch new file mode 100644 index 000000000..4f96eae7b --- /dev/null +++ b/firefox/0032-bmo-1773336-disable_audio_thread_priority_default_features.patch @@ -0,0 +1,45 @@ +From 64d822a598f46f9d08a41eab6a7d416a6c54927b Mon Sep 17 00:00:00 2001 +From: Mike Hommey +Date: Wed, 8 Jun 2022 16:03:49 +0900 +Subject: [PATCH] Disable audio_thread_priority default features + +with_dbus is supposed to be optional in gecko, but in practice, the +audio_thread_priority defaults force it on. +# https://github.com/kinetiknz/audioipc/pull/5/ +--- + audioipc/Cargo.toml | 1 + + client/Cargo.toml | 1 + + server/Cargo.toml | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/third_party/rust/audioipc/Cargo.toml b/third_party/rust/audioipc/Cargo.toml +index d69c56d..8a9dd3d 100644 +--- a/third_party/rust/audioipc/Cargo.toml ++++ b/third_party/rust/audioipc/Cargo.toml +@@ -30,6 +30,7 @@ memmap2 = "0.2" + + [target.'cfg(target_os = "linux")'.dependencies.audio_thread_priority] + version = "0.26.1" ++default-features = false + + [target.'cfg(windows)'.dependencies] + mio = "0.6.19" +diff --git a/third_party/rust/audioipc-client/Cargo.toml b/third_party/rust/audioipc-client/Cargo.toml +index 3ffb268..5dbf5f6 100644 +--- a/third_party/rust/audioipc-client/Cargo.toml ++++ b/third_party/rust/audioipc-client/Cargo.toml +@@ -19,3 +19,4 @@ tokio = { version="0.1", default-features=false, features = ["rt-full"] } + + [dependencies.audio_thread_priority] + version = "0.26.1" ++default-features = false +diff --git a/third_party/rust/audioipc-server/Cargo.toml b/third_party/rust/audioipc-server/Cargo.toml +index 2c82fbf..b2b710c 100644 +--- a/third_party/rust/audioipc-server/Cargo.toml ++++ b/third_party/rust/audioipc-server/Cargo.toml +@@ -24,3 +24,4 @@ default-features = false + + [dependencies.audio_thread_priority] + version = "0.26.1" ++default-features = false + diff --git a/firefox/0033-rhbz-2115253-vaapi-fixes.patch b/firefox/0033-rhbz-2115253-vaapi-fixes.patch new file mode 100644 index 000000000..ddf30d15c --- /dev/null +++ b/firefox/0033-rhbz-2115253-vaapi-fixes.patch @@ -0,0 +1,20 @@ +diff -up firefox-104.0/gfx/thebes/gfxPlatformGtk.cpp.firefox-enable-vaapi firefox-104.0/gfx/thebes/gfxPlatformGtk.cpp +diff -up firefox-104.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi firefox-104.0/widget/gtk/GfxInfo.cpp +--- firefox-104.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi 2022-08-16 15:14:53.014042400 +0200 ++++ firefox-104.0/widget/gtk/GfxInfo.cpp 2022-08-16 15:15:30.482301677 +0200 +@@ -873,15 +873,6 @@ const nsTArray& GfxInfo:: + nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED, + V(0, 0, 0, 0), "FEATURE_HARDWARE_VIDEO_DECODING_NO_LINUX_AMD", ""); + +- // Disable on Release/late Beta +-#if !defined(EARLY_BETA_OR_EARLIER) +- APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Linux, DeviceFamily::All, +- nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING, +- nsIGfxInfo::FEATURE_BLOCKED_DEVICE, +- DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0), +- "FEATURE_HARDWARE_VIDEO_DECODING_DISABLE", ""); +-#endif +- + //////////////////////////////////// + // FEATURE_WEBRENDER_PARTIAL_PRESENT + APPEND_TO_DRIVER_BLOCKLIST_EXT( diff --git a/firefox/0034-bgo-860033-firefox-wayland-no-dbus.patch b/firefox/0034-bgo-860033-firefox-wayland-no-dbus.patch new file mode 100644 index 000000000..7cf532a68 --- /dev/null +++ b/firefox/0034-bgo-860033-firefox-wayland-no-dbus.patch @@ -0,0 +1,49 @@ +diff --git a/toolkit/moz.configure b/toolkit/moz.configure +--- a/toolkit/moz.configure ++++ b/toolkit/moz.configure +@@ -2353,18 +2353,6 @@ with only_when(compile_environment & tar + ) + set_config("MOZ_D3DCOMPILER_VISTA_DLL_PATH", d3d_compiler_dll.path) + +-# Remoting protocol support +-# ============================================================== +- +- +-@depends(toolkit) +-def has_remote(toolkit): +- if toolkit in ("gtk", "windows", "cocoa"): +- return True +- +- +-set_config("MOZ_HAS_REMOTE", has_remote) +-set_define("MOZ_HAS_REMOTE", has_remote) + + # RLBox Library Sandboxing wasm support + # ============================================================== +@@ -2900,6 +2888,26 @@ with only_when(toolkit_gtk): + set_config("MOZ_ENABLE_DBUS", True) + set_define("MOZ_ENABLE_DBUS", True) + ++# Remoting protocol support ++# ============================================================== ++ ++@depends( ++ toolkit, ++ depends("--enable-dbus", when=toolkit_gtk)(lambda x: x), ++ depends(wayland_headers, when=toolkit_gtk)(lambda x: x), ++ depends(x11_headers, when=toolkit_gtk)(lambda x: x), ++) ++def has_remote(toolkit, dbus, wayland, x11): ++ if toolkit in ("windows", "cocoa"): ++ return True ++ if toolkit == "gtk": ++ if not dbus and wayland and not x11: ++ return ++ return True ++ ++ ++set_config("MOZ_HAS_REMOTE", has_remote) ++set_define("MOZ_HAS_REMOTE", has_remote) + + # Necko's wifi scanner + # ============================================================== diff --git a/firefox/Pkgfile b/firefox/Pkgfile index dc939afdf..946b22ff7 100644 --- a/firefox/Pkgfile +++ b/firefox/Pkgfile @@ -1,18 +1,68 @@ # Description: The Mozilla Firefox browser with Alsa support # URL: https://www.mozilla.com/firefox/ # Maintainer: Danny Rawlins, crux at romster dot me -# Depends on: alsa-lib autoconf-2.13 brotli cbindgen dbus-glib ffmpeg4 libevent libnotify libvpx libwebp libxkbcommon lld nodejs nss unzip wasi-libc++ xorg-libxcomposite xorg-libxcursor xorg-libxinerama xorg-libxt zip +# Depends on: alsa-lib autoconf-2.13 brotli cbindgen dav1d dbus-glib ffmpeg graphite2 libaom libdav1d libevent libnotify libvpx libwebp libxkbcommon lld nodejs nss unzip wasi-libc++ xorg-libxcomposite xorg-libxcursor xorg-libxinerama xorg-libxt zip # Optional: sccache jack name=firefox -version=104.0 +version=104.0.2 release=1 source=(https://archive.mozilla.org/pub/firefox/releases/$version/source/$name-$version.source.tar.xz - firefox.desktop) + firefox.desktop + node-stdout-nonblocking-wrapper + 0001-Don-t-use-build-id.patch + 0002-Fortify-sources-properly.patch + 0003-Check-additional-plugins-dir.patch + 0004-bmo-847568-Support-system-harfbuzz.patch + 0005-bmo-847568-Support-system-graphite2.patch + 0006-bmo-1559213-Support-system-av1.patch + 0007-bmo-878089-Don-t-fail-when-TERM-is-not-set.patch + 0008-bmo-1516803-Fix-building-sandbox.patch + 0009-musl-Add-alternate-name-for-private-siginfo-struct-m.patch + 0010-musl-Fix-syscall-wrappers.patch + 0011-musl-Only-use-system-heap-reporter-with-glibc.patch + 0012-musl-Set-pthread-name-for-non-glibc-systems.patch + 0013-musl-getcontext-is-only-avaliable-on-glibc-systems.patch + 0014-musl-sys-auvx.h-avaliable-on-more-then-just-glibc-sy.patch + 0015-musl-make-SYS_fork-non-fatal-musl-uses-it-for-fork-2.patch + 0016-musl-include-net-if.h-before-linux-if.h-to-avoid-red.patch + 0017-Make-PGO-use-toolchain.patch + 0018-bmo-1516081-Disable-watchdog-during-PGO-builds.patch + 0019-bmo-1516803-force-one-LTO-partition-for-sandbox-when.patch + 0020-Fix-building-with-PGO-when-using-GCC.patch + 0021-libaom-Use-NEON_FLAGS-instead-of-VPX_ASFLAGS-for-lib.patch + 0022-build-Disable-Werror.patch + 0023-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch + 0024-Enable-FLAC-on-platforms-without-ffvpx-via-ffmpeg.patch + 0025-bmo-1670333-OpenH264-Fix-decoding-if-it-starts-on-no.patch + 0026-bmo-1663844-OpenH264-Allow-using-OpenH264-GMP-decode.patch + 0027-bgo-816975-fix-build-on-x86.patch + 0028-bmo-1559213-fix-system-av1-libs.patch + 0029-bmo-1196777-Set-GDK_FOCUS_CHANGE_MASK.patch + 0030-bmo-1754469-memory_mozalloc_throw.patch + 0031-bmo-1769631-python-3.11-compatibility.patch + 0032-bmo-1773336-disable_audio_thread_priority_default_features.patch + 0033-rhbz-2115253-vaapi-fixes.patch + 0034-bgo-860033-firefox-wayland-no-dbus.patch + arc4random.patch + libwebrtc-screen-cast-sync-1.patch + no-ccache-stats.patch) + +_clear_vendor_checksums() { + sed -i 's/\("files":{\)[^}]*/\1/' third_party/rust/$1/.cargo-checksum.json +} build() { cd $name-$version + for p in $SRC/*.patch; do + patch -p1 -i $p + done + + _clear_vendor_checksums audioipc + _clear_vendor_checksums audioipc-client + _clear_vendor_checksums audioipc-server + if [ "$(/usr/bin/python3 -c "import sys; print(sys.stdout.encoding)")" != 'utf-8' ]; then printf "\e[031mError: set an UTF-8 locale to compile this!\033[0m\n" exit 1 @@ -29,10 +79,14 @@ build() { export CARGO_HOME="$PKGMK_SOURCE_DIR/rust" cat <<- EOF > .mozconfig + export NODEJS="$SRC/node-stdout-nonblocking-wrapper" mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/firefox-shared unset MOZ_TELEMETRY_REPORTING ac_add_options --prefix=/usr ac_add_options --enable-application=browser + ac_add_options --with-system-harfbuzz + #ac_add_options --with-system-graphite2 + ac_add_options --with-system-av1 ac_add_options --with-system-jpeg ac_add_options --with-system-zlib ac_add_options --with-system-png @@ -72,16 +126,22 @@ EOF [[ -e '/usr/bin/ccache' ]] && echo 'ac_add_options --enable-ccache' >> .mozconfig - export CC=clang CXX=clang++ AR=llvm-ar NM=llvm-nm RANLIB=llvm-ranlib + export CC=clang CXX=clang++ AR=llvm-ar NM=llvm-nm RANLIB=llvm-ranlib RUSTFLAGS="-C opt-level=2 $RUSTFLAGS" export MOZ_MAKE_FLAGS="-j ${JOBS-1}" - export MOZBUILD_STATE_PATH="$PKGMK_SOURCE_DIR/.mozbuild" + export MOZBUILD_STATE_PATH="$SRC"/mozbuild # Disable notification when build system has finished export MOZ_NOSPAM=1 # Use system's Python environment - export MACH_USE_SYSTEM_PYTHON=1 - + export PIP_NETWORK_INSTALL_RESTRICTED_VIRTUALENVS=mach + #export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=system + export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=pip + mkdir $SRC/bin + ln -s /usr/bin/pip3 $SRC/bin/pip + ln -s /usr/bin/python3 $SRC/bin/python + export PATH="$SRC/bin:$PATH" + # Show flags set at the beginning echo "Current BINDGEN_CFLAGS:\t${BINDGEN_CFLAGS:-no value set}" echo "Current CFLAGS:\t\t${CFLAGS:-no value set}" diff --git a/firefox/arc4random.patch b/firefox/arc4random.patch new file mode 100644 index 000000000..c877d54c1 --- /dev/null +++ b/firefox/arc4random.patch @@ -0,0 +1,33 @@ +diff --git i/ipc/chromium/src/third_party/libevent/linux/event2/event-config.h w/ipc/chromium/src/third_party/libevent/linux/event2/event-config.h +index 101d39d455107..3764806240f9f 100644 +--- i/ipc/chromium/src/third_party/libevent/linux/event2/event-config.h ++++ w/ipc/chromium/src/third_party/libevent/linux/event2/event-config.h +@@ -30,13 +30,13 @@ + /* #undef EVENT__HAVE_AFUNIX_H 1 */ + + /* Define to 1 if you have the `arc4random' function. */ +-/* #undef EVENT__HAVE_ARC4RANDOM */ ++#define EVENT__HAVE_ARC4RANDOM 1 + + /* Define to 1 if you have the `arc4random_addrandom' function. */ + /* #undef EVENT__HAVE_ARC4RANDOM_ADDRANDOM */ + + /* Define to 1 if you have the `arc4random_buf' function. */ +-/* #undef EVENT__HAVE_ARC4RANDOM_BUF */ ++#define EVENT__HAVE_ARC4RANDOM_BUF 1 + + /* Define to 1 if you have the header file. */ + #define EVENT__HAVE_ARPA_INET_H 1 +diff --git i/toolkit/crashreporter/client/ping.cpp w/toolkit/crashreporter/client/ping.cpp +index 57cf85de80b79..93a2f6e80ad0b 100644 +--- i/toolkit/crashreporter/client/ping.cpp ++++ w/toolkit/crashreporter/client/ping.cpp +@@ -53,7 +53,7 @@ static string GenerateUUID() { + + CFRelease(uuid); + #elif defined(HAVE_ARC4RANDOM_BUF) // Android, BSD, ... +- arc4random_buf(id, sizeof(UUID)); ++ arc4random_buf(&id, sizeof(UUID)); + #else // Linux + int fd = open("/dev/urandom", O_RDONLY); + diff --git a/firefox/libwebrtc-screen-cast-sync-1.patch b/firefox/libwebrtc-screen-cast-sync-1.patch new file mode 100644 index 000000000..07025b17f --- /dev/null +++ b/firefox/libwebrtc-screen-cast-sync-1.patch @@ -0,0 +1,9776 @@ +diff -up firefox-103.0/dom/media/webrtc/moz.build.libwebrtc-screen-cast-sync firefox-103.0/dom/media/webrtc/moz.build +--- firefox-103.0/dom/media/webrtc/moz.build.libwebrtc-screen-cast-sync 2022-07-18 20:44:03.000000000 +0200 ++++ firefox-103.0/dom/media/webrtc/moz.build 2022-07-28 11:45:30.321408998 +0200 +@@ -85,6 +85,8 @@ if CONFIG["MOZ_WEBRTC_SIGNALING"]: + + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + DIRS += ["/third_party/pipewire/libpipewire"] ++ DIRS += ["/third_party/drm/libdrm"] ++ DIRS += ["/third_party/gbm/libgbm"] + + # Avoid warnings from third-party code that we can not modify. + if CONFIG["CC_TYPE"] == "clang-cl": +diff -up firefox-103.0/third_party/drm/drm/drm_fourcc.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/drm/drm_fourcc.h +--- firefox-103.0/third_party/drm/drm/drm_fourcc.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.317409023 +0200 ++++ firefox-103.0/third_party/drm/drm/drm_fourcc.h 2022-07-28 11:45:30.317409023 +0200 +@@ -0,0 +1,1377 @@ ++/* ++ * Copyright 2011 Intel Corporation ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef DRM_FOURCC_H ++#define DRM_FOURCC_H ++ ++#include "drm.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++/** ++ * DOC: overview ++ * ++ * In the DRM subsystem, framebuffer pixel formats are described using the ++ * fourcc codes defined in `include/uapi/drm/drm_fourcc.h`. In addition to the ++ * fourcc code, a Format Modifier may optionally be provided, in order to ++ * further describe the buffer's format - for example tiling or compression. ++ * ++ * Format Modifiers ++ * ---------------- ++ * ++ * Format modifiers are used in conjunction with a fourcc code, forming a ++ * unique fourcc:modifier pair. This format:modifier pair must fully define the ++ * format and data layout of the buffer, and should be the only way to describe ++ * that particular buffer. ++ * ++ * Having multiple fourcc:modifier pairs which describe the same layout should ++ * be avoided, as such aliases run the risk of different drivers exposing ++ * different names for the same data format, forcing userspace to understand ++ * that they are aliases. ++ * ++ * Format modifiers may change any property of the buffer, including the number ++ * of planes and/or the required allocation size. Format modifiers are ++ * vendor-namespaced, and as such the relationship between a fourcc code and a ++ * modifier is specific to the modifer being used. For example, some modifiers ++ * may preserve meaning - such as number of planes - from the fourcc code, ++ * whereas others may not. ++ * ++ * Modifiers must uniquely encode buffer layout. In other words, a buffer must ++ * match only a single modifier. A modifier must not be a subset of layouts of ++ * another modifier. For instance, it's incorrect to encode pitch alignment in ++ * a modifier: a buffer may match a 64-pixel aligned modifier and a 32-pixel ++ * aligned modifier. That said, modifiers can have implicit minimal ++ * requirements. ++ * ++ * For modifiers where the combination of fourcc code and modifier can alias, ++ * a canonical pair needs to be defined and used by all drivers. Preferred ++ * combinations are also encouraged where all combinations might lead to ++ * confusion and unnecessarily reduced interoperability. An example for the ++ * latter is AFBC, where the ABGR layouts are preferred over ARGB layouts. ++ * ++ * There are two kinds of modifier users: ++ * ++ * - Kernel and user-space drivers: for drivers it's important that modifiers ++ * don't alias, otherwise two drivers might support the same format but use ++ * different aliases, preventing them from sharing buffers in an efficient ++ * format. ++ * - Higher-level programs interfacing with KMS/GBM/EGL/Vulkan/etc: these users ++ * see modifiers as opaque tokens they can check for equality and intersect. ++ * These users musn't need to know to reason about the modifier value ++ * (i.e. they are not expected to extract information out of the modifier). ++ * ++ * Vendors should document their modifier usage in as much detail as ++ * possible, to ensure maximum compatibility across devices, drivers and ++ * applications. ++ * ++ * The authoritative list of format modifier codes is found in ++ * `include/uapi/drm/drm_fourcc.h` ++ */ ++ ++#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ ++ ((__u32)(c) << 16) | ((__u32)(d) << 24)) ++ ++#define DRM_FORMAT_BIG_ENDIAN (1U<<31) /* format is big endian instead of little endian */ ++ ++/* Reserve 0 for the invalid format specifier */ ++#define DRM_FORMAT_INVALID 0 ++ ++/* color index */ ++#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ ++ ++/* 8 bpp Red */ ++#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ ++ ++/* 10 bpp Red */ ++#define DRM_FORMAT_R10 fourcc_code('R', '1', '0', ' ') /* [15:0] x:R 6:10 little endian */ ++ ++/* 12 bpp Red */ ++#define DRM_FORMAT_R12 fourcc_code('R', '1', '2', ' ') /* [15:0] x:R 4:12 little endian */ ++ ++/* 16 bpp Red */ ++#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ ++ ++/* 16 bpp RG */ ++#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */ ++#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ ++ ++/* 32 bpp RG */ ++#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */ ++#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ ++ ++/* 8 bpp RGB */ ++#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ ++#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ ++ ++/* 16 bpp RGB */ ++#define DRM_FORMAT_XRGB4444 fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ ++#define DRM_FORMAT_XBGR4444 fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ ++#define DRM_FORMAT_RGBX4444 fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ ++#define DRM_FORMAT_BGRX4444 fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ ++ ++#define DRM_FORMAT_ARGB4444 fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ ++#define DRM_FORMAT_ABGR4444 fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ ++#define DRM_FORMAT_RGBA4444 fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ ++#define DRM_FORMAT_BGRA4444 fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ ++ ++#define DRM_FORMAT_XRGB1555 fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ ++#define DRM_FORMAT_XBGR1555 fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ ++#define DRM_FORMAT_RGBX5551 fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ ++#define DRM_FORMAT_BGRX5551 fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ ++ ++#define DRM_FORMAT_ARGB1555 fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ ++#define DRM_FORMAT_ABGR1555 fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ ++#define DRM_FORMAT_RGBA5551 fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ ++#define DRM_FORMAT_BGRA5551 fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ ++ ++#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ ++#define DRM_FORMAT_BGR565 fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ ++ ++/* 24 bpp RGB */ ++#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ ++#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ ++ ++/* 32 bpp RGB */ ++#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ ++#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ ++#define DRM_FORMAT_RGBX8888 fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ ++#define DRM_FORMAT_BGRX8888 fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ ++ ++#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ ++#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ ++#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ ++#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ ++ ++#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ ++#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ ++#define DRM_FORMAT_RGBX1010102 fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ ++#define DRM_FORMAT_BGRX1010102 fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ ++ ++#define DRM_FORMAT_ARGB2101010 fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ ++#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ ++#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ ++#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ ++ ++/* 64 bpp RGB */ ++#define DRM_FORMAT_XRGB16161616 fourcc_code('X', 'R', '4', '8') /* [63:0] x:R:G:B 16:16:16:16 little endian */ ++#define DRM_FORMAT_XBGR16161616 fourcc_code('X', 'B', '4', '8') /* [63:0] x:B:G:R 16:16:16:16 little endian */ ++ ++#define DRM_FORMAT_ARGB16161616 fourcc_code('A', 'R', '4', '8') /* [63:0] A:R:G:B 16:16:16:16 little endian */ ++#define DRM_FORMAT_ABGR16161616 fourcc_code('A', 'B', '4', '8') /* [63:0] A:B:G:R 16:16:16:16 little endian */ ++ ++/* ++ * Floating point 64bpp RGB ++ * IEEE 754-2008 binary16 half-precision float ++ * [15:0] sign:exponent:mantissa 1:5:10 ++ */ ++#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H') /* [63:0] x:R:G:B 16:16:16:16 little endian */ ++#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ ++ ++#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H') /* [63:0] A:R:G:B 16:16:16:16 little endian */ ++#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ ++ ++/* ++ * RGBA format with 10-bit components packed in 64-bit per pixel, with 6 bits ++ * of unused padding per component: ++ */ ++#define DRM_FORMAT_AXBXGXRX106106106106 fourcc_code('A', 'B', '1', '0') /* [63:0] A:x:B:x:G:x:R:x 10:6:10:6:10:6:10:6 little endian */ ++ ++/* packed YCbCr */ ++#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ ++#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ ++#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ ++#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ ++ ++#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ ++#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */ ++#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */ ++#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */ ++ ++/* ++ * packed Y2xx indicate for each component, xx valid data occupy msb ++ * 16-xx padding occupy lsb ++ */ ++#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels */ ++#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2') /* [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels */ ++#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6') /* [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels */ ++ ++/* ++ * packed Y4xx indicate for each component, xx valid data occupy msb ++ * 16-xx padding occupy lsb except Y410 ++ */ ++#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0') /* [31:0] A:Cr:Y:Cb 2:10:10:10 little endian */ ++#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2') /* [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ ++#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6') /* [63:0] A:Cr:Y:Cb 16:16:16:16 little endian */ ++ ++#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0') /* [31:0] X:Cr:Y:Cb 2:10:10:10 little endian */ ++#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6') /* [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian */ ++#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8') /* [63:0] X:Cr:Y:Cb 16:16:16:16 little endian */ ++ ++/* ++ * packed YCbCr420 2x2 tiled formats ++ * first 64 bits will contain Y,Cb,Cr components for a 2x2 tile ++ */ ++/* [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ ++#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0') ++/* [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian */ ++#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0') ++ ++/* [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ ++#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2') ++/* [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian */ ++#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2') ++ ++/* ++ * 1-plane YUV 4:2:0 ++ * In these formats, the component ordering is specified (Y, followed by U ++ * then V), but the exact Linear layout is undefined. ++ * These formats can only be used with a non-Linear modifier. ++ */ ++#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8') ++#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0') ++ ++/* ++ * 2 plane RGB + A ++ * index 0 = RGB plane, same format as the corresponding non _A8 format has ++ * index 1 = A plane, [7:0] A ++ */ ++#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8') ++#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8') ++#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8') ++#define DRM_FORMAT_BGRX8888_A8 fourcc_code('B', 'X', 'A', '8') ++#define DRM_FORMAT_RGB888_A8 fourcc_code('R', '8', 'A', '8') ++#define DRM_FORMAT_BGR888_A8 fourcc_code('B', '8', 'A', '8') ++#define DRM_FORMAT_RGB565_A8 fourcc_code('R', '5', 'A', '8') ++#define DRM_FORMAT_BGR565_A8 fourcc_code('B', '5', 'A', '8') ++ ++/* ++ * 2 plane YCbCr ++ * index 0 = Y plane, [7:0] Y ++ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian ++ * or ++ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian ++ */ ++#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ ++#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ ++#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ ++/* ++ * 2 plane YCbCr ++ * index 0 = Y plane, [39:0] Y3:Y2:Y1:Y0 little endian ++ * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian ++ */ ++#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ ++ ++/* ++ * 2 plane YCbCr MSB aligned ++ * index 0 = Y plane, [15:0] Y:x [10:6] little endian ++ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian ++ */ ++#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0') /* 2x1 subsampled Cr:Cb plane, 10 bit per channel */ ++ ++/* ++ * 2 plane YCbCr MSB aligned ++ * index 0 = Y plane, [15:0] Y:x [10:6] little endian ++ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian ++ */ ++#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ ++ ++/* ++ * 2 plane YCbCr MSB aligned ++ * index 0 = Y plane, [15:0] Y:x [12:4] little endian ++ * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian ++ */ ++#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cr:Cb plane 12 bits per channel */ ++ ++/* ++ * 2 plane YCbCr MSB aligned ++ * index 0 = Y plane, [15:0] Y little endian ++ * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian ++ */ ++#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ ++ ++/* 3 plane non-subsampled (444) YCbCr ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cb plane, [15:0] Cb:x [10:6] little endian ++ * index 2: Cr plane, [15:0] Cr:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q410 fourcc_code('Q', '4', '1', '0') ++ ++/* 3 plane non-subsampled (444) YCrCb ++ * 16 bits per component, but only 10 bits are used and 6 bits are padded ++ * index 0: Y plane, [15:0] Y:x [10:6] little endian ++ * index 1: Cr plane, [15:0] Cr:x [10:6] little endian ++ * index 2: Cb plane, [15:0] Cb:x [10:6] little endian ++ */ ++#define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1') ++ ++/* ++ * 3 plane YCbCr ++ * index 0: Y plane, [7:0] Y ++ * index 1: Cb plane, [7:0] Cb ++ * index 2: Cr plane, [7:0] Cr ++ * or ++ * index 1: Cr plane, [7:0] Cr ++ * index 2: Cb plane, [7:0] Cb ++ */ ++#define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ ++#define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ ++#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ ++#define DRM_FORMAT_YVU411 fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ ++#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ ++#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ ++#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ ++#define DRM_FORMAT_YVU422 fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ ++#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ ++#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ ++ ++ ++/* ++ * Format Modifiers: ++ * ++ * Format modifiers describe, typically, a re-ordering or modification ++ * of the data in a plane of an FB. This can be used to express tiled/ ++ * swizzled formats, or compression, or a combination of the two. ++ * ++ * The upper 8 bits of the format modifier are a vendor-id as assigned ++ * below. The lower 56 bits are assigned as vendor sees fit. ++ */ ++ ++/* Vendor Ids: */ ++#define DRM_FORMAT_MOD_VENDOR_NONE 0 ++#define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 ++#define DRM_FORMAT_MOD_VENDOR_AMD 0x02 ++#define DRM_FORMAT_MOD_VENDOR_NVIDIA 0x03 ++#define DRM_FORMAT_MOD_VENDOR_SAMSUNG 0x04 ++#define DRM_FORMAT_MOD_VENDOR_QCOM 0x05 ++#define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06 ++#define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07 ++#define DRM_FORMAT_MOD_VENDOR_ARM 0x08 ++#define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09 ++#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a ++ ++/* add more to the end as needed */ ++ ++#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1) ++ ++#define fourcc_mod_get_vendor(modifier) \ ++ (((modifier) >> 56) & 0xff) ++ ++#define fourcc_mod_is_vendor(modifier, vendor) \ ++ (fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor) ++ ++#define fourcc_mod_code(vendor, val) \ ++ ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL)) ++ ++/* ++ * Format Modifier tokens: ++ * ++ * When adding a new token please document the layout with a code comment, ++ * similar to the fourcc codes above. drm_fourcc.h is considered the ++ * authoritative source for all of these. ++ * ++ * Generic modifier names: ++ * ++ * DRM_FORMAT_MOD_GENERIC_* definitions are used to provide vendor-neutral names ++ * for layouts which are common across multiple vendors. To preserve ++ * compatibility, in cases where a vendor-specific definition already exists and ++ * a generic name for it is desired, the common name is a purely symbolic alias ++ * and must use the same numerical value as the original definition. ++ * ++ * Note that generic names should only be used for modifiers which describe ++ * generic layouts (such as pixel re-ordering), which may have ++ * independently-developed support across multiple vendors. ++ * ++ * In future cases where a generic layout is identified before merging with a ++ * vendor-specific modifier, a new 'GENERIC' vendor or modifier using vendor ++ * 'NONE' could be considered. This should only be for obvious, exceptional ++ * cases to avoid polluting the 'GENERIC' namespace with modifiers which only ++ * apply to a single vendor. ++ * ++ * Generic names should not be used for cases where multiple hardware vendors ++ * have implementations of the same standardised compression scheme (such as ++ * AFBC). In those cases, all implementations should use the same format ++ * modifier(s), reflecting the vendor of the standard. ++ */ ++ ++#define DRM_FORMAT_MOD_GENERIC_16_16_TILE DRM_FORMAT_MOD_SAMSUNG_16_16_TILE ++ ++/* ++ * Invalid Modifier ++ * ++ * This modifier can be used as a sentinel to terminate the format modifiers ++ * list, or to initialize a variable with an invalid modifier. It might also be ++ * used to report an error back to userspace for certain APIs. ++ */ ++#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) ++ ++/* ++ * Linear Layout ++ * ++ * Just plain linear layout. Note that this is different from no specifying any ++ * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), ++ * which tells the driver to also take driver-internal information into account ++ * and so might actually result in a tiled framebuffer. ++ */ ++#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) ++ ++/* ++ * Deprecated: use DRM_FORMAT_MOD_LINEAR instead ++ * ++ * The "none" format modifier doesn't actually mean that the modifier is ++ * implicit, instead it means that the layout is linear. Whether modifiers are ++ * used is out-of-band information carried in an API-specific way (e.g. in a ++ * flag for drm_mode_fb_cmd2). ++ */ ++#define DRM_FORMAT_MOD_NONE 0 ++ ++/* Intel framebuffer modifiers */ ++ ++/* ++ * Intel X-tiling layout ++ * ++ * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) ++ * in row-major layout. Within the tile bytes are laid out row-major, with ++ * a platform-dependent stride. On top of that the memory can apply ++ * platform-depending swizzling of some higher address bits into bit6. ++ * ++ * Note that this layout is only accurate on intel gen 8+ or valleyview chipsets. ++ * On earlier platforms the is highly platforms specific and not useful for ++ * cross-driver sharing. It exists since on a given platform it does uniquely ++ * identify the layout in a simple way for i915-specific userspace, which ++ * facilitated conversion of userspace to modifiers. Additionally the exact ++ * format on some really old platforms is not known. ++ */ ++#define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1) ++ ++/* ++ * Intel Y-tiling layout ++ * ++ * This is a tiled layout using 4Kb tiles (except on gen2 where the tiles 2Kb) ++ * in row-major layout. Within the tile bytes are laid out in OWORD (16 bytes) ++ * chunks column-major, with a platform-dependent height. On top of that the ++ * memory can apply platform-depending swizzling of some higher address bits ++ * into bit6. ++ * ++ * Note that this layout is only accurate on intel gen 8+ or valleyview chipsets. ++ * On earlier platforms the is highly platforms specific and not useful for ++ * cross-driver sharing. It exists since on a given platform it does uniquely ++ * identify the layout in a simple way for i915-specific userspace, which ++ * facilitated conversion of userspace to modifiers. Additionally the exact ++ * format on some really old platforms is not known. ++ */ ++#define I915_FORMAT_MOD_Y_TILED fourcc_mod_code(INTEL, 2) ++ ++/* ++ * Intel Yf-tiling layout ++ * ++ * This is a tiled layout using 4Kb tiles in row-major layout. ++ * Within the tile pixels are laid out in 16 256 byte units / sub-tiles which ++ * are arranged in four groups (two wide, two high) with column-major layout. ++ * Each group therefore consits out of four 256 byte units, which are also laid ++ * out as 2x2 column-major. ++ * 256 byte units are made out of four 64 byte blocks of pixels, producing ++ * either a square block or a 2:1 unit. ++ * 64 byte blocks of pixels contain four pixel rows of 16 bytes, where the width ++ * in pixel depends on the pixel depth. ++ */ ++#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3) ++ ++/* ++ * Intel color control surface (CCS) for render compression ++ * ++ * The framebuffer format must be one of the 8:8:8:8 RGB formats. ++ * The main surface will be plane index 0 and must be Y/Yf-tiled, ++ * the CCS will be plane index 1. ++ * ++ * Each CCS tile matches a 1024x512 pixel area of the main surface. ++ * To match certain aspects of the 3D hardware the CCS is ++ * considered to be made up of normal 128Bx32 Y tiles, Thus ++ * the CCS pitch must be specified in multiples of 128 bytes. ++ * ++ * In reality the CCS tile appears to be a 64Bx64 Y tile, composed ++ * of QWORD (8 bytes) chunks instead of OWORD (16 bytes) chunks. ++ * But that fact is not relevant unless the memory is accessed ++ * directly. ++ */ ++#define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) ++#define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) ++ ++/* ++ * Intel color control surfaces (CCS) for Gen-12 render compression. ++ * ++ * The main surface is Y-tiled and at plane index 0, the CCS is linear and ++ * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in ++ * main surface. In other words, 4 bits in CCS map to a main surface cache ++ * line pair. The main surface pitch is required to be a multiple of four ++ * Y-tile widths. ++ */ ++#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6) ++ ++/* ++ * Intel color control surfaces (CCS) for Gen-12 media compression ++ * ++ * The main surface is Y-tiled and at plane index 0, the CCS is linear and ++ * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in ++ * main surface. In other words, 4 bits in CCS map to a main surface cache ++ * line pair. The main surface pitch is required to be a multiple of four ++ * Y-tile widths. For semi-planar formats like NV12, CCS planes follow the ++ * Y and UV planes i.e., planes 0 and 1 are used for Y and UV surfaces, ++ * planes 2 and 3 for the respective CCS. ++ */ ++#define I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS fourcc_mod_code(INTEL, 7) ++ ++/* ++ * Intel Color Control Surface with Clear Color (CCS) for Gen-12 render ++ * compression. ++ * ++ * The main surface is Y-tiled and is at plane index 0 whereas CCS is linear ++ * and at index 1. The clear color is stored at index 2, and the pitch should ++ * be ignored. The clear color structure is 256 bits. The first 128 bits ++ * represents Raw Clear Color Red, Green, Blue and Alpha color each represented ++ * by 32 bits. The raw clear color is consumed by the 3d engine and generates ++ * the converted clear color of size 64 bits. The first 32 bits store the Lower ++ * Converted Clear Color value and the next 32 bits store the Higher Converted ++ * Clear Color value when applicable. The Converted Clear Color values are ++ * consumed by the DE. The last 64 bits are used to store Color Discard Enable ++ * and Depth Clear Value Valid which are ignored by the DE. A CCS cache line ++ * corresponds to an area of 4x1 tiles in the main surface. The main surface ++ * pitch is required to be a multiple of 4 tile widths. ++ */ ++#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8) ++ ++/* ++ * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks ++ * ++ * Macroblocks are laid in a Z-shape, and each pixel data is following the ++ * standard NV12 style. ++ * As for NV12, an image is the result of two frame buffers: one for Y, ++ * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer). ++ * Alignment requirements are (for each buffer): ++ * - multiple of 128 pixels for the width ++ * - multiple of 32 pixels for the height ++ * ++ * For more information: see https://linuxtv.org/downloads/v4l-dvb-apis/re32.html ++ */ ++#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1) ++ ++/* ++ * Tiled, 16 (pixels) x 16 (lines) - sized macroblocks ++ * ++ * This is a simple tiled layout using tiles of 16x16 pixels in a row-major ++ * layout. For YCbCr formats Cb/Cr components are taken in such a way that ++ * they correspond to their 16x16 luma block. ++ */ ++#define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2) ++ ++/* ++ * Qualcomm Compressed Format ++ * ++ * Refers to a compressed variant of the base format that is compressed. ++ * Implementation may be platform and base-format specific. ++ * ++ * Each macrotile consists of m x n (mostly 4 x 4) tiles. ++ * Pixel data pitch/stride is aligned with macrotile width. ++ * Pixel data height is aligned with macrotile height. ++ * Entire pixel data buffer is aligned with 4k(bytes). ++ */ ++#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) ++ ++/* Vivante framebuffer modifiers */ ++ ++/* ++ * Vivante 4x4 tiling layout ++ * ++ * This is a simple tiled layout using tiles of 4x4 pixels in a row-major ++ * layout. ++ */ ++#define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1) ++ ++/* ++ * Vivante 64x64 super-tiling layout ++ * ++ * This is a tiled layout using 64x64 pixel super-tiles, where each super-tile ++ * contains 8x4 groups of 2x4 tiles of 4x4 pixels (like above) each, all in row- ++ * major layout. ++ * ++ * For more information: see ++ * https://github.com/etnaviv/etna_viv/blob/master/doc/hardware.md#texture-tiling ++ */ ++#define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2) ++ ++/* ++ * Vivante 4x4 tiling layout for dual-pipe ++ * ++ * Same as the 4x4 tiling layout, except every second 4x4 pixel tile starts at a ++ * different base address. Offsets from the base addresses are therefore halved ++ * compared to the non-split tiled layout. ++ */ ++#define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3) ++ ++/* ++ * Vivante 64x64 super-tiling layout for dual-pipe ++ * ++ * Same as the 64x64 super-tiling layout, except every second 4x4 pixel tile ++ * starts at a different base address. Offsets from the base addresses are ++ * therefore halved compared to the non-split super-tiled layout. ++ */ ++#define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4) ++ ++/* NVIDIA frame buffer modifiers */ ++ ++/* ++ * Tegra Tiled Layout, used by Tegra 2, 3 and 4. ++ * ++ * Pixels are arranged in simple tiles of 16 x 16 bytes. ++ */ ++#define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1) ++ ++/* ++ * Generalized Block Linear layout, used by desktop GPUs starting with NV50/G80, ++ * and Tegra GPUs starting with Tegra K1. ++ * ++ * Pixels are arranged in Groups of Bytes (GOBs). GOB size and layout varies ++ * based on the architecture generation. GOBs themselves are then arranged in ++ * 3D blocks, with the block dimensions (in terms of GOBs) always being a power ++ * of two, and hence expressible as their log2 equivalent (E.g., "2" represents ++ * a block depth or height of "4"). ++ * ++ * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format ++ * in full detail. ++ * ++ * Macro ++ * Bits Param Description ++ * ---- ----- ----------------------------------------------------------------- ++ * ++ * 3:0 h log2(height) of each block, in GOBs. Placed here for ++ * compatibility with the existing ++ * DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK()-based modifiers. ++ * ++ * 4:4 - Must be 1, to indicate block-linear layout. Necessary for ++ * compatibility with the existing ++ * DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK()-based modifiers. ++ * ++ * 8:5 - Reserved (To support 3D-surfaces with variable log2(depth) block ++ * size). Must be zero. ++ * ++ * Note there is no log2(width) parameter. Some portions of the ++ * hardware support a block width of two gobs, but it is impractical ++ * to use due to lack of support elsewhere, and has no known ++ * benefits. ++ * ++ * 11:9 - Reserved (To support 2D-array textures with variable array stride ++ * in blocks, specified via log2(tile width in blocks)). Must be ++ * zero. ++ * ++ * 19:12 k Page Kind. This value directly maps to a field in the page ++ * tables of all GPUs >= NV50. It affects the exact layout of bits ++ * in memory and can be derived from the tuple ++ * ++ * (format, GPU model, compression type, samples per pixel) ++ * ++ * Where compression type is defined below. If GPU model were ++ * implied by the format modifier, format, or memory buffer, page ++ * kind would not need to be included in the modifier itself, but ++ * since the modifier should define the layout of the associated ++ * memory buffer independent from any device or other context, it ++ * must be included here. ++ * ++ * 21:20 g GOB Height and Page Kind Generation. The height of a GOB changed ++ * starting with Fermi GPUs. Additionally, the mapping between page ++ * kind and bit layout has changed at various points. ++ * ++ * 0 = Gob Height 8, Fermi - Volta, Tegra K1+ Page Kind mapping ++ * 1 = Gob Height 4, G80 - GT2XX Page Kind mapping ++ * 2 = Gob Height 8, Turing+ Page Kind mapping ++ * 3 = Reserved for future use. ++ * ++ * 22:22 s Sector layout. On Tegra GPUs prior to Xavier, there is a further ++ * bit remapping step that occurs at an even lower level than the ++ * page kind and block linear swizzles. This causes the layout of ++ * surfaces mapped in those SOC's GPUs to be incompatible with the ++ * equivalent mapping on other GPUs in the same system. ++ * ++ * 0 = Tegra K1 - Tegra Parker/TX2 Layout. ++ * 1 = Desktop GPU and Tegra Xavier+ Layout ++ * ++ * 25:23 c Lossless Framebuffer Compression type. ++ * ++ * 0 = none ++ * 1 = ROP/3D, layout 1, exact compression format implied by Page ++ * Kind field ++ * 2 = ROP/3D, layout 2, exact compression format implied by Page ++ * Kind field ++ * 3 = CDE horizontal ++ * 4 = CDE vertical ++ * 5 = Reserved for future use ++ * 6 = Reserved for future use ++ * 7 = Reserved for future use ++ * ++ * 55:25 - Reserved for future use. Must be zero. ++ */ ++#define DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(c, s, g, k, h) \ ++ fourcc_mod_code(NVIDIA, (0x10 | \ ++ ((h) & 0xf) | \ ++ (((k) & 0xff) << 12) | \ ++ (((g) & 0x3) << 20) | \ ++ (((s) & 0x1) << 22) | \ ++ (((c) & 0x7) << 23))) ++ ++/* To grandfather in prior block linear format modifiers to the above layout, ++ * the page kind "0", which corresponds to "pitch/linear" and hence is unusable ++ * with block-linear layouts, is remapped within drivers to the value 0xfe, ++ * which corresponds to the "generic" kind used for simple single-sample ++ * uncompressed color formats on Fermi - Volta GPUs. ++ */ ++static __inline__ __u64 ++drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) ++{ ++ if (!(modifier & 0x10) || (modifier & (0xff << 12))) ++ return modifier; ++ else ++ return modifier | (0xfe << 12); ++} ++ ++/* ++ * 16Bx2 Block Linear layout, used by Tegra K1 and later ++ * ++ * Pixels are arranged in 64x8 Groups Of Bytes (GOBs). GOBs are then stacked ++ * vertically by a power of 2 (1 to 32 GOBs) to form a block. ++ * ++ * Within a GOB, data is ordered as 16B x 2 lines sectors laid in Z-shape. ++ * ++ * Parameter 'v' is the log2 encoding of the number of GOBs stacked vertically. ++ * Valid values are: ++ * ++ * 0 == ONE_GOB ++ * 1 == TWO_GOBS ++ * 2 == FOUR_GOBS ++ * 3 == EIGHT_GOBS ++ * 4 == SIXTEEN_GOBS ++ * 5 == THIRTYTWO_GOBS ++ * ++ * Chapter 20 "Pixel Memory Formats" of the Tegra X1 TRM describes this format ++ * in full detail. ++ */ ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) \ ++ DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0, (v)) ++ ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0) ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1) ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2) ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3) ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4) ++#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB \ ++ DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5) ++ ++/* ++ * Some Broadcom modifiers take parameters, for example the number of ++ * vertical lines in the image. Reserve the lower 32 bits for modifier ++ * type, and the next 24 bits for parameters. Top 8 bits are the ++ * vendor code. ++ */ ++#define __fourcc_mod_broadcom_param_shift 8 ++#define __fourcc_mod_broadcom_param_bits 48 ++#define fourcc_mod_broadcom_code(val, params) \ ++ fourcc_mod_code(BROADCOM, ((((__u64)params) << __fourcc_mod_broadcom_param_shift) | val)) ++#define fourcc_mod_broadcom_param(m) \ ++ ((int)(((m) >> __fourcc_mod_broadcom_param_shift) & \ ++ ((1ULL << __fourcc_mod_broadcom_param_bits) - 1))) ++#define fourcc_mod_broadcom_mod(m) \ ++ ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << \ ++ __fourcc_mod_broadcom_param_shift)) ++ ++/* ++ * Broadcom VC4 "T" format ++ * ++ * This is the primary layout that the V3D GPU can texture from (it ++ * can't do linear). The T format has: ++ * ++ * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4 ++ * pixels at 32 bit depth. ++ * ++ * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually ++ * 16x16 pixels). ++ * ++ * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On ++ * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows ++ * they're (TR, BR, BL, TL), where bottom left is start of memory. ++ * ++ * - an image made of 4k tiles in rows either left-to-right (even rows of 4k ++ * tiles) or right-to-left (odd rows of 4k tiles). ++ */ ++#define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1) ++ ++/* ++ * Broadcom SAND format ++ * ++ * This is the native format that the H.264 codec block uses. For VC4 ++ * HVS, it is only valid for H.264 (NV12/21) and RGBA modes. ++ * ++ * The image can be considered to be split into columns, and the ++ * columns are placed consecutively into memory. The width of those ++ * columns can be either 32, 64, 128, or 256 pixels, but in practice ++ * only 128 pixel columns are used. ++ * ++ * The pitch between the start of each column is set to optimally ++ * switch between SDRAM banks. This is passed as the number of lines ++ * of column width in the modifier (we can't use the stride value due ++ * to various core checks that look at it , so you should set the ++ * stride to width*cpp). ++ * ++ * Note that the column height for this format modifier is the same ++ * for all of the planes, assuming that each column contains both Y ++ * and UV. Some SAND-using hardware stores UV in a separate tiled ++ * image from Y to reduce the column height, which is not supported ++ * with these modifiers. ++ */ ++ ++#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ ++ fourcc_mod_broadcom_code(2, v) ++#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) \ ++ fourcc_mod_broadcom_code(3, v) ++#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) \ ++ fourcc_mod_broadcom_code(4, v) ++#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) \ ++ fourcc_mod_broadcom_code(5, v) ++ ++#define DRM_FORMAT_MOD_BROADCOM_SAND32 \ ++ DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0) ++#define DRM_FORMAT_MOD_BROADCOM_SAND64 \ ++ DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0) ++#define DRM_FORMAT_MOD_BROADCOM_SAND128 \ ++ DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0) ++#define DRM_FORMAT_MOD_BROADCOM_SAND256 \ ++ DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0) ++ ++/* Broadcom UIF format ++ * ++ * This is the common format for the current Broadcom multimedia ++ * blocks, including V3D 3.x and newer, newer video codecs, and ++ * displays. ++ * ++ * The image consists of utiles (64b blocks), UIF blocks (2x2 utiles), ++ * and macroblocks (4x4 UIF blocks). Those 4x4 UIF block groups are ++ * stored in columns, with padding between the columns to ensure that ++ * moving from one column to the next doesn't hit the same SDRAM page ++ * bank. ++ * ++ * To calculate the padding, it is assumed that each hardware block ++ * and the software driving it knows the platform's SDRAM page size, ++ * number of banks, and XOR address, and that it's identical between ++ * all blocks using the format. This tiling modifier will use XOR as ++ * necessary to reduce the padding. If a hardware block can't do XOR, ++ * the assumption is that a no-XOR tiling modifier will be created. ++ */ ++#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6) ++ ++/* ++ * Arm Framebuffer Compression (AFBC) modifiers ++ * ++ * AFBC is a proprietary lossless image compression protocol and format. ++ * It provides fine-grained random access and minimizes the amount of data ++ * transferred between IP blocks. ++ * ++ * AFBC has several features which may be supported and/or used, which are ++ * represented using bits in the modifier. Not all combinations are valid, ++ * and different devices or use-cases may support different combinations. ++ * ++ * Further information on the use of AFBC modifiers can be found in ++ * Documentation/gpu/afbc.rst ++ */ ++ ++/* ++ * The top 4 bits (out of the 56 bits alloted for specifying vendor specific ++ * modifiers) denote the category for modifiers. Currently we have three ++ * categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of ++ * sixteen different categories. ++ */ ++#define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \ ++ fourcc_mod_code(ARM, ((__u64)(__type) << 52) | ((__val) & 0x000fffffffffffffULL)) ++ ++#define DRM_FORMAT_MOD_ARM_TYPE_AFBC 0x00 ++#define DRM_FORMAT_MOD_ARM_TYPE_MISC 0x01 ++ ++#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) \ ++ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFBC, __afbc_mode) ++ ++/* ++ * AFBC superblock size ++ * ++ * Indicates the superblock size(s) used for the AFBC buffer. The buffer ++ * size (in pixels) must be aligned to a multiple of the superblock size. ++ * Four lowest significant bits(LSBs) are reserved for block size. ++ * ++ * Where one superblock size is specified, it applies to all planes of the ++ * buffer (e.g. 16x16, 32x8). When multiple superblock sizes are specified, ++ * the first applies to the Luma plane and the second applies to the Chroma ++ * plane(s). e.g. (32x8_64x4 means 32x8 Luma, with 64x4 Chroma). ++ * Multiple superblock sizes are only valid for multi-plane YCbCr formats. ++ */ ++#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf ++#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL) ++#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL) ++#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 (3ULL) ++#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 (4ULL) ++ ++/* ++ * AFBC lossless colorspace transform ++ * ++ * Indicates that the buffer makes use of the AFBC lossless colorspace ++ * transform. ++ */ ++#define AFBC_FORMAT_MOD_YTR (1ULL << 4) ++ ++/* ++ * AFBC block-split ++ * ++ * Indicates that the payload of each superblock is split. The second ++ * half of the payload is positioned at a predefined offset from the start ++ * of the superblock payload. ++ */ ++#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5) ++ ++/* ++ * AFBC sparse layout ++ * ++ * This flag indicates that the payload of each superblock must be stored at a ++ * predefined position relative to the other superblocks in the same AFBC ++ * buffer. This order is the same order used by the header buffer. In this mode ++ * each superblock is given the same amount of space as an uncompressed ++ * superblock of the particular format would require, rounding up to the next ++ * multiple of 128 bytes in size. ++ */ ++#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6) ++ ++/* ++ * AFBC copy-block restrict ++ * ++ * Buffers with this flag must obey the copy-block restriction. The restriction ++ * is such that there are no copy-blocks referring across the border of 8x8 ++ * blocks. For the subsampled data the 8x8 limitation is also subsampled. ++ */ ++#define AFBC_FORMAT_MOD_CBR (1ULL << 7) ++ ++/* ++ * AFBC tiled layout ++ * ++ * The tiled layout groups superblocks in 8x8 or 4x4 tiles, where all ++ * superblocks inside a tile are stored together in memory. 8x8 tiles are used ++ * for pixel formats up to and including 32 bpp while 4x4 tiles are used for ++ * larger bpp formats. The order between the tiles is scan line. ++ * When the tiled layout is used, the buffer size (in pixels) must be aligned ++ * to the tile size. ++ */ ++#define AFBC_FORMAT_MOD_TILED (1ULL << 8) ++ ++/* ++ * AFBC solid color blocks ++ * ++ * Indicates that the buffer makes use of solid-color blocks, whereby bandwidth ++ * can be reduced if a whole superblock is a single color. ++ */ ++#define AFBC_FORMAT_MOD_SC (1ULL << 9) ++ ++/* ++ * AFBC double-buffer ++ * ++ * Indicates that the buffer is allocated in a layout safe for front-buffer ++ * rendering. ++ */ ++#define AFBC_FORMAT_MOD_DB (1ULL << 10) ++ ++/* ++ * AFBC buffer content hints ++ * ++ * Indicates that the buffer includes per-superblock content hints. ++ */ ++#define AFBC_FORMAT_MOD_BCH (1ULL << 11) ++ ++/* AFBC uncompressed storage mode ++ * ++ * Indicates that the buffer is using AFBC uncompressed storage mode. ++ * In this mode all superblock payloads in the buffer use the uncompressed ++ * storage mode, which is usually only used for data which cannot be compressed. ++ * The buffer layout is the same as for AFBC buffers without USM set, this only ++ * affects the storage mode of the individual superblocks. Note that even a ++ * buffer without USM set may use uncompressed storage mode for some or all ++ * superblocks, USM just guarantees it for all. ++ */ ++#define AFBC_FORMAT_MOD_USM (1ULL << 12) ++ ++/* ++ * Arm Fixed-Rate Compression (AFRC) modifiers ++ * ++ * AFRC is a proprietary fixed rate image compression protocol and format, ++ * designed to provide guaranteed bandwidth and memory footprint ++ * reductions in graphics and media use-cases. ++ * ++ * AFRC buffers consist of one or more planes, with the same components ++ * and meaning as an uncompressed buffer using the same pixel format. ++ * ++ * Within each plane, the pixel/luma/chroma values are grouped into ++ * "coding unit" blocks which are individually compressed to a ++ * fixed size (in bytes). All coding units within a given plane of a buffer ++ * store the same number of values, and have the same compressed size. ++ * ++ * The coding unit size is configurable, allowing different rates of compression. ++ * ++ * The start of each AFRC buffer plane must be aligned to an alignment granule which ++ * depends on the coding unit size. ++ * ++ * Coding Unit Size Plane Alignment ++ * ---------------- --------------- ++ * 16 bytes 1024 bytes ++ * 24 bytes 512 bytes ++ * 32 bytes 2048 bytes ++ * ++ * Coding units are grouped into paging tiles. AFRC buffer dimensions must be aligned ++ * to a multiple of the paging tile dimensions. ++ * The dimensions of each paging tile depend on whether the buffer is optimised for ++ * scanline (SCAN layout) or rotated (ROT layout) access. ++ * ++ * Layout Paging Tile Width Paging Tile Height ++ * ------ ----------------- ------------------ ++ * SCAN 16 coding units 4 coding units ++ * ROT 8 coding units 8 coding units ++ * ++ * The dimensions of each coding unit depend on the number of components ++ * in the compressed plane and whether the buffer is optimised for ++ * scanline (SCAN layout) or rotated (ROT layout) access. ++ * ++ * Number of Components in Plane Layout Coding Unit Width Coding Unit Height ++ * ----------------------------- --------- ----------------- ------------------ ++ * 1 SCAN 16 samples 4 samples ++ * Example: 16x4 luma samples in a 'Y' plane ++ * 16x4 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 1 ROT 8 samples 8 samples ++ * Example: 8x8 luma samples in a 'Y' plane ++ * 8x8 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 2 DONT CARE 8 samples 4 samples ++ * Example: 8x4 chroma pairs in the 'UV' plane of a semi-planar YUV buffer ++ * ----------------------------- --------- ----------------- ------------------ ++ * 3 DONT CARE 4 samples 4 samples ++ * Example: 4x4 pixels in an RGB buffer without alpha ++ * ----------------------------- --------- ----------------- ------------------ ++ * 4 DONT CARE 4 samples 4 samples ++ * Example: 4x4 pixels in an RGB buffer with alpha ++ */ ++ ++#define DRM_FORMAT_MOD_ARM_TYPE_AFRC 0x02 ++ ++#define DRM_FORMAT_MOD_ARM_AFRC(__afrc_mode) \ ++ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFRC, __afrc_mode) ++ ++/* ++ * AFRC coding unit size modifier. ++ * ++ * Indicates the number of bytes used to store each compressed coding unit for ++ * one or more planes in an AFRC encoded buffer. The coding unit size for chrominance ++ * is the same for both Cb and Cr, which may be stored in separate planes. ++ * ++ * AFRC_FORMAT_MOD_CU_SIZE_P0 indicates the number of bytes used to store ++ * each compressed coding unit in the first plane of the buffer. For RGBA buffers ++ * this is the only plane, while for semi-planar and fully-planar YUV buffers, ++ * this corresponds to the luma plane. ++ * ++ * AFRC_FORMAT_MOD_CU_SIZE_P12 indicates the number of bytes used to store ++ * each compressed coding unit in the second and third planes in the buffer. ++ * For semi-planar and fully-planar YUV buffers, this corresponds to the chroma plane(s). ++ * ++ * For single-plane buffers, AFRC_FORMAT_MOD_CU_SIZE_P0 must be specified ++ * and AFRC_FORMAT_MOD_CU_SIZE_P12 must be zero. ++ * For semi-planar and fully-planar buffers, both AFRC_FORMAT_MOD_CU_SIZE_P0 and ++ * AFRC_FORMAT_MOD_CU_SIZE_P12 must be specified. ++ */ ++#define AFRC_FORMAT_MOD_CU_SIZE_MASK 0xf ++#define AFRC_FORMAT_MOD_CU_SIZE_16 (1ULL) ++#define AFRC_FORMAT_MOD_CU_SIZE_24 (2ULL) ++#define AFRC_FORMAT_MOD_CU_SIZE_32 (3ULL) ++ ++#define AFRC_FORMAT_MOD_CU_SIZE_P0(__afrc_cu_size) (__afrc_cu_size) ++#define AFRC_FORMAT_MOD_CU_SIZE_P12(__afrc_cu_size) ((__afrc_cu_size) << 4) ++ ++/* ++ * AFRC scanline memory layout. ++ * ++ * Indicates if the buffer uses the scanline-optimised layout ++ * for an AFRC encoded buffer, otherwise, it uses the rotation-optimised layout. ++ * The memory layout is the same for all planes. ++ */ ++#define AFRC_FORMAT_MOD_LAYOUT_SCAN (1ULL << 8) ++ ++/* ++ * Arm 16x16 Block U-Interleaved modifier ++ * ++ * This is used by Arm Mali Utgard and Midgard GPUs. It divides the image ++ * into 16x16 pixel blocks. Blocks are stored linearly in order, but pixels ++ * in the block are reordered. ++ */ ++#define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED \ ++ DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 1ULL) ++ ++/* ++ * Allwinner tiled modifier ++ * ++ * This tiling mode is implemented by the VPU found on all Allwinner platforms, ++ * codenamed sunxi. It is associated with a YUV format that uses either 2 or 3 ++ * planes. ++ * ++ * With this tiling, the luminance samples are disposed in tiles representing ++ * 32x32 pixels and the chrominance samples in tiles representing 32x64 pixels. ++ * The pixel order in each tile is linear and the tiles are disposed linearly, ++ * both in row-major order. ++ */ ++#define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1) ++ ++/* ++ * Amlogic Video Framebuffer Compression modifiers ++ * ++ * Amlogic uses a proprietary lossless image compression protocol and format ++ * for their hardware video codec accelerators, either video decoders or ++ * video input encoders. ++ * ++ * It considerably reduces memory bandwidth while writing and reading ++ * frames in memory. ++ * ++ * The underlying storage is considered to be 3 components, 8bit or 10-bit ++ * per component YCbCr 420, single plane : ++ * - DRM_FORMAT_YUV420_8BIT ++ * - DRM_FORMAT_YUV420_10BIT ++ * ++ * The first 8 bits of the mode defines the layout, then the following 8 bits ++ * defines the options changing the layout. ++ * ++ * Not all combinations are valid, and different SoCs may support different ++ * combinations of layout and options. ++ */ ++#define __fourcc_mod_amlogic_layout_mask 0xff ++#define __fourcc_mod_amlogic_options_shift 8 ++#define __fourcc_mod_amlogic_options_mask 0xff ++ ++#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ ++ fourcc_mod_code(AMLOGIC, \ ++ ((__layout) & __fourcc_mod_amlogic_layout_mask) | \ ++ (((__options) & __fourcc_mod_amlogic_options_mask) \ ++ << __fourcc_mod_amlogic_options_shift)) ++ ++/* Amlogic FBC Layouts */ ++ ++/* ++ * Amlogic FBC Basic Layout ++ * ++ * The basic layout is composed of: ++ * - a body content organized in 64x32 superblocks with 4096 bytes per ++ * superblock in default mode. ++ * - a 32 bytes per 128x64 header block ++ * ++ * This layout is transferrable between Amlogic SoCs supporting this modifier. ++ */ ++#define AMLOGIC_FBC_LAYOUT_BASIC (1ULL) ++ ++/* ++ * Amlogic FBC Scatter Memory layout ++ * ++ * Indicates the header contains IOMMU references to the compressed ++ * frames content to optimize memory access and layout. ++ * ++ * In this mode, only the header memory address is needed, thus the ++ * content memory organization is tied to the current producer ++ * execution and cannot be saved/dumped neither transferrable between ++ * Amlogic SoCs supporting this modifier. ++ * ++ * Due to the nature of the layout, these buffers are not expected to ++ * be accessible by the user-space clients, but only accessible by the ++ * hardware producers and consumers. ++ * ++ * The user-space clients should expect a failure while trying to mmap ++ * the DMA-BUF handle returned by the producer. ++ */ ++#define AMLOGIC_FBC_LAYOUT_SCATTER (2ULL) ++ ++/* Amlogic FBC Layout Options Bit Mask */ ++ ++/* ++ * Amlogic FBC Memory Saving mode ++ * ++ * Indicates the storage is packed when pixel size is multiple of word ++ * boudaries, i.e. 8bit should be stored in this mode to save allocation ++ * memory. ++ * ++ * This mode reduces body layout to 3072 bytes per 64x32 superblock with ++ * the basic layout and 3200 bytes per 64x32 superblock combined with ++ * the scatter layout. ++ */ ++#define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0) ++ ++/* ++ * AMD modifiers ++ * ++ * Memory layout: ++ * ++ * without DCC: ++ * - main surface ++ * ++ * with DCC & without DCC_RETILE: ++ * - main surface in plane 0 ++ * - DCC surface in plane 1 (RB-aligned, pipe-aligned if DCC_PIPE_ALIGN is set) ++ * ++ * with DCC & DCC_RETILE: ++ * - main surface in plane 0 ++ * - displayable DCC surface in plane 1 (not RB-aligned & not pipe-aligned) ++ * - pipe-aligned DCC surface in plane 2 (RB-aligned & pipe-aligned) ++ * ++ * For multi-plane formats the above surfaces get merged into one plane for ++ * each format plane, based on the required alignment only. ++ * ++ * Bits Parameter Notes ++ * ----- ------------------------ --------------------------------------------- ++ * ++ * 7:0 TILE_VERSION Values are AMD_FMT_MOD_TILE_VER_* ++ * 12:8 TILE Values are AMD_FMT_MOD_TILE__* ++ * 13 DCC ++ * 14 DCC_RETILE ++ * 15 DCC_PIPE_ALIGN ++ * 16 DCC_INDEPENDENT_64B ++ * 17 DCC_INDEPENDENT_128B ++ * 19:18 DCC_MAX_COMPRESSED_BLOCK Values are AMD_FMT_MOD_DCC_BLOCK_* ++ * 20 DCC_CONSTANT_ENCODE ++ * 23:21 PIPE_XOR_BITS Only for some chips ++ * 26:24 BANK_XOR_BITS Only for some chips ++ * 29:27 PACKERS Only for some chips ++ * 32:30 RB Only for some chips ++ * 35:33 PIPE Only for some chips ++ * 55:36 - Reserved for future use, must be zero ++ */ ++#define AMD_FMT_MOD fourcc_mod_code(AMD, 0) ++ ++#define IS_AMD_FMT_MOD(val) (((val) >> 56) == DRM_FORMAT_MOD_VENDOR_AMD) ++ ++/* Reserve 0 for GFX8 and older */ ++#define AMD_FMT_MOD_TILE_VER_GFX9 1 ++#define AMD_FMT_MOD_TILE_VER_GFX10 2 ++#define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3 ++ ++/* ++ * 64K_S is the same for GFX9/GFX10/GFX10_RBPLUS and hence has GFX9 as canonical ++ * version. ++ */ ++#define AMD_FMT_MOD_TILE_GFX9_64K_S 9 ++ ++/* ++ * 64K_D for non-32 bpp is the same for GFX9/GFX10/GFX10_RBPLUS and hence has ++ * GFX9 as canonical version. ++ */ ++#define AMD_FMT_MOD_TILE_GFX9_64K_D 10 ++#define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25 ++#define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26 ++#define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27 ++ ++#define AMD_FMT_MOD_DCC_BLOCK_64B 0 ++#define AMD_FMT_MOD_DCC_BLOCK_128B 1 ++#define AMD_FMT_MOD_DCC_BLOCK_256B 2 ++ ++#define AMD_FMT_MOD_TILE_VERSION_SHIFT 0 ++#define AMD_FMT_MOD_TILE_VERSION_MASK 0xFF ++#define AMD_FMT_MOD_TILE_SHIFT 8 ++#define AMD_FMT_MOD_TILE_MASK 0x1F ++ ++/* Whether DCC compression is enabled. */ ++#define AMD_FMT_MOD_DCC_SHIFT 13 ++#define AMD_FMT_MOD_DCC_MASK 0x1 ++ ++/* ++ * Whether to include two DCC surfaces, one which is rb & pipe aligned, and ++ * one which is not-aligned. ++ */ ++#define AMD_FMT_MOD_DCC_RETILE_SHIFT 14 ++#define AMD_FMT_MOD_DCC_RETILE_MASK 0x1 ++ ++/* Only set if DCC_RETILE = false */ ++#define AMD_FMT_MOD_DCC_PIPE_ALIGN_SHIFT 15 ++#define AMD_FMT_MOD_DCC_PIPE_ALIGN_MASK 0x1 ++ ++#define AMD_FMT_MOD_DCC_INDEPENDENT_64B_SHIFT 16 ++#define AMD_FMT_MOD_DCC_INDEPENDENT_64B_MASK 0x1 ++#define AMD_FMT_MOD_DCC_INDEPENDENT_128B_SHIFT 17 ++#define AMD_FMT_MOD_DCC_INDEPENDENT_128B_MASK 0x1 ++#define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_SHIFT 18 ++#define AMD_FMT_MOD_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 ++ ++/* ++ * DCC supports embedding some clear colors directly in the DCC surface. ++ * However, on older GPUs the rendering HW ignores the embedded clear color ++ * and prefers the driver provided color. This necessitates doing a fastclear ++ * eliminate operation before a process transfers control. ++ * ++ * If this bit is set that means the fastclear eliminate is not needed for these ++ * embeddable colors. ++ */ ++#define AMD_FMT_MOD_DCC_CONSTANT_ENCODE_SHIFT 20 ++#define AMD_FMT_MOD_DCC_CONSTANT_ENCODE_MASK 0x1 ++ ++/* ++ * The below fields are for accounting for per GPU differences. These are only ++ * relevant for GFX9 and later and if the tile field is *_X/_T. ++ * ++ * PIPE_XOR_BITS = always needed ++ * BANK_XOR_BITS = only for TILE_VER_GFX9 ++ * PACKERS = only for TILE_VER_GFX10_RBPLUS ++ * RB = only for TILE_VER_GFX9 & DCC ++ * PIPE = only for TILE_VER_GFX9 & DCC & (DCC_RETILE | DCC_PIPE_ALIGN) ++ */ ++#define AMD_FMT_MOD_PIPE_XOR_BITS_SHIFT 21 ++#define AMD_FMT_MOD_PIPE_XOR_BITS_MASK 0x7 ++#define AMD_FMT_MOD_BANK_XOR_BITS_SHIFT 24 ++#define AMD_FMT_MOD_BANK_XOR_BITS_MASK 0x7 ++#define AMD_FMT_MOD_PACKERS_SHIFT 27 ++#define AMD_FMT_MOD_PACKERS_MASK 0x7 ++#define AMD_FMT_MOD_RB_SHIFT 30 ++#define AMD_FMT_MOD_RB_MASK 0x7 ++#define AMD_FMT_MOD_PIPE_SHIFT 33 ++#define AMD_FMT_MOD_PIPE_MASK 0x7 ++ ++#define AMD_FMT_MOD_SET(field, value) \ ++ ((uint64_t)(value) << AMD_FMT_MOD_##field##_SHIFT) ++#define AMD_FMT_MOD_GET(field, value) \ ++ (((value) >> AMD_FMT_MOD_##field##_SHIFT) & AMD_FMT_MOD_##field##_MASK) ++#define AMD_FMT_MOD_CLEAR(field) \ ++ (~((uint64_t)AMD_FMT_MOD_##field##_MASK << AMD_FMT_MOD_##field##_SHIFT)) ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif /* DRM_FOURCC_H */ +diff -up firefox-103.0/third_party/drm/drm/drm.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/drm/drm.h +--- firefox-103.0/third_party/drm/drm/drm.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.317409023 +0200 ++++ firefox-103.0/third_party/drm/drm/drm.h 2022-07-28 11:45:30.317409023 +0200 +@@ -0,0 +1,1193 @@ ++/* ++ * Header for the Direct Rendering Manager ++ * ++ * Author: Rickard E. (Rik) Faith ++ * ++ * Acknowledgments: ++ * Dec 1999, Richard Henderson , move to generic cmpxchg. ++ */ ++ ++/* ++ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. ++ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. ++ * All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef _DRM_H_ ++#define _DRM_H_ ++ ++#if defined(__linux__) ++ ++#include ++#include ++typedef unsigned int drm_handle_t; ++ ++#else /* One of the BSDs */ ++ ++#include ++#include ++#include ++typedef int8_t __s8; ++typedef uint8_t __u8; ++typedef int16_t __s16; ++typedef uint16_t __u16; ++typedef int32_t __s32; ++typedef uint32_t __u32; ++typedef int64_t __s64; ++typedef uint64_t __u64; ++typedef size_t __kernel_size_t; ++typedef unsigned long drm_handle_t; ++ ++#endif ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ ++#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ ++#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ ++#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ ++ ++#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ ++#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ ++#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) ++#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) ++#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) ++ ++typedef unsigned int drm_context_t; ++typedef unsigned int drm_drawable_t; ++typedef unsigned int drm_magic_t; ++ ++/* ++ * Cliprect. ++ * ++ * \warning: If you change this structure, make sure you change ++ * XF86DRIClipRectRec in the server as well ++ * ++ * \note KW: Actually it's illegal to change either for ++ * backwards-compatibility reasons. ++ */ ++struct drm_clip_rect { ++ unsigned short x1; ++ unsigned short y1; ++ unsigned short x2; ++ unsigned short y2; ++}; ++ ++/* ++ * Drawable information. ++ */ ++struct drm_drawable_info { ++ unsigned int num_rects; ++ struct drm_clip_rect *rects; ++}; ++ ++/* ++ * Texture region, ++ */ ++struct drm_tex_region { ++ unsigned char next; ++ unsigned char prev; ++ unsigned char in_use; ++ unsigned char padding; ++ unsigned int age; ++}; ++ ++/* ++ * Hardware lock. ++ * ++ * The lock structure is a simple cache-line aligned integer. To avoid ++ * processor bus contention on a multiprocessor system, there should not be any ++ * other data stored in the same cache line. ++ */ ++struct drm_hw_lock { ++ __volatile__ unsigned int lock; /**< lock variable */ ++ char padding[60]; /**< Pad to cache line */ ++}; ++ ++/* ++ * DRM_IOCTL_VERSION ioctl argument type. ++ * ++ * \sa drmGetVersion(). ++ */ ++struct drm_version { ++ int version_major; /**< Major version */ ++ int version_minor; /**< Minor version */ ++ int version_patchlevel; /**< Patch level */ ++ __kernel_size_t name_len; /**< Length of name buffer */ ++ char *name; /**< Name of driver */ ++ __kernel_size_t date_len; /**< Length of date buffer */ ++ char *date; /**< User-space buffer to hold date */ ++ __kernel_size_t desc_len; /**< Length of desc buffer */ ++ char *desc; /**< User-space buffer to hold desc */ ++}; ++ ++/* ++ * DRM_IOCTL_GET_UNIQUE ioctl argument type. ++ * ++ * \sa drmGetBusid() and drmSetBusId(). ++ */ ++struct drm_unique { ++ __kernel_size_t unique_len; /**< Length of unique */ ++ char *unique; /**< Unique name for driver instantiation */ ++}; ++ ++struct drm_list { ++ int count; /**< Length of user-space structures */ ++ struct drm_version *version; ++}; ++ ++struct drm_block { ++ int unused; ++}; ++ ++/* ++ * DRM_IOCTL_CONTROL ioctl argument type. ++ * ++ * \sa drmCtlInstHandler() and drmCtlUninstHandler(). ++ */ ++struct drm_control { ++ enum { ++ DRM_ADD_COMMAND, ++ DRM_RM_COMMAND, ++ DRM_INST_HANDLER, ++ DRM_UNINST_HANDLER ++ } func; ++ int irq; ++}; ++ ++/* ++ * Type of memory to map. ++ */ ++enum drm_map_type { ++ _DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */ ++ _DRM_REGISTERS = 1, /**< no caching, no core dump */ ++ _DRM_SHM = 2, /**< shared, cached */ ++ _DRM_AGP = 3, /**< AGP/GART */ ++ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ ++ _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ ++}; ++ ++/* ++ * Memory mapping flags. ++ */ ++enum drm_map_flags { ++ _DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */ ++ _DRM_READ_ONLY = 0x02, ++ _DRM_LOCKED = 0x04, /**< shared, cached, locked */ ++ _DRM_KERNEL = 0x08, /**< kernel requires access */ ++ _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */ ++ _DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */ ++ _DRM_REMOVABLE = 0x40, /**< Removable mapping */ ++ _DRM_DRIVER = 0x80 /**< Managed by driver */ ++}; ++ ++struct drm_ctx_priv_map { ++ unsigned int ctx_id; /**< Context requesting private mapping */ ++ void *handle; /**< Handle of map */ ++}; ++ ++/* ++ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls ++ * argument type. ++ * ++ * \sa drmAddMap(). ++ */ ++struct drm_map { ++ unsigned long offset; /**< Requested physical address (0 for SAREA)*/ ++ unsigned long size; /**< Requested physical size (bytes) */ ++ enum drm_map_type type; /**< Type of memory to map */ ++ enum drm_map_flags flags; /**< Flags */ ++ void *handle; /**< User-space: "Handle" to pass to mmap() */ ++ /**< Kernel-space: kernel-virtual address */ ++ int mtrr; /**< MTRR slot used */ ++ /* Private data */ ++}; ++ ++/* ++ * DRM_IOCTL_GET_CLIENT ioctl argument type. ++ */ ++struct drm_client { ++ int idx; /**< Which client desired? */ ++ int auth; /**< Is client authenticated? */ ++ unsigned long pid; /**< Process ID */ ++ unsigned long uid; /**< User ID */ ++ unsigned long magic; /**< Magic */ ++ unsigned long iocs; /**< Ioctl count */ ++}; ++ ++enum drm_stat_type { ++ _DRM_STAT_LOCK, ++ _DRM_STAT_OPENS, ++ _DRM_STAT_CLOSES, ++ _DRM_STAT_IOCTLS, ++ _DRM_STAT_LOCKS, ++ _DRM_STAT_UNLOCKS, ++ _DRM_STAT_VALUE, /**< Generic value */ ++ _DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */ ++ _DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */ ++ ++ _DRM_STAT_IRQ, /**< IRQ */ ++ _DRM_STAT_PRIMARY, /**< Primary DMA bytes */ ++ _DRM_STAT_SECONDARY, /**< Secondary DMA bytes */ ++ _DRM_STAT_DMA, /**< DMA */ ++ _DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */ ++ _DRM_STAT_MISSED /**< Missed DMA opportunity */ ++ /* Add to the *END* of the list */ ++}; ++ ++/* ++ * DRM_IOCTL_GET_STATS ioctl argument type. ++ */ ++struct drm_stats { ++ unsigned long count; ++ struct { ++ unsigned long value; ++ enum drm_stat_type type; ++ } data[15]; ++}; ++ ++/* ++ * Hardware locking flags. ++ */ ++enum drm_lock_flags { ++ _DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ ++ _DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ ++ _DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ ++ _DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ ++ /* These *HALT* flags aren't supported yet ++ -- they will be used to support the ++ full-screen DGA-like mode. */ ++ _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ ++ _DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ ++}; ++ ++/* ++ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type. ++ * ++ * \sa drmGetLock() and drmUnlock(). ++ */ ++struct drm_lock { ++ int context; ++ enum drm_lock_flags flags; ++}; ++ ++/* ++ * DMA flags ++ * ++ * \warning ++ * These values \e must match xf86drm.h. ++ * ++ * \sa drm_dma. ++ */ ++enum drm_dma_flags { ++ /* Flags for DMA buffer dispatch */ ++ _DRM_DMA_BLOCK = 0x01, /**< ++ * Block until buffer dispatched. ++ * ++ * \note The buffer may not yet have ++ * been processed by the hardware -- ++ * getting a hardware lock with the ++ * hardware quiescent will ensure ++ * that the buffer has been ++ * processed. ++ */ ++ _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ ++ _DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ ++ ++ /* Flags for DMA buffer request */ ++ _DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ ++ _DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ ++ _DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ ++}; ++ ++/* ++ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type. ++ * ++ * \sa drmAddBufs(). ++ */ ++struct drm_buf_desc { ++ int count; /**< Number of buffers of this size */ ++ int size; /**< Size in bytes */ ++ int low_mark; /**< Low water mark */ ++ int high_mark; /**< High water mark */ ++ enum { ++ _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ ++ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ ++ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ ++ _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ ++ _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ ++ } flags; ++ unsigned long agp_start; /**< ++ * Start address of where the AGP buffers are ++ * in the AGP aperture ++ */ ++}; ++ ++/* ++ * DRM_IOCTL_INFO_BUFS ioctl argument type. ++ */ ++struct drm_buf_info { ++ int count; /**< Entries in list */ ++ struct drm_buf_desc *list; ++}; ++ ++/* ++ * DRM_IOCTL_FREE_BUFS ioctl argument type. ++ */ ++struct drm_buf_free { ++ int count; ++ int *list; ++}; ++ ++/* ++ * Buffer information ++ * ++ * \sa drm_buf_map. ++ */ ++struct drm_buf_pub { ++ int idx; /**< Index into the master buffer list */ ++ int total; /**< Buffer size */ ++ int used; /**< Amount of buffer in use (for DMA) */ ++ void *address; /**< Address of buffer */ ++}; ++ ++/* ++ * DRM_IOCTL_MAP_BUFS ioctl argument type. ++ */ ++struct drm_buf_map { ++ int count; /**< Length of the buffer list */ ++#ifdef __cplusplus ++ void *virt; ++#else ++ void *virtual; /**< Mmap'd area in user-virtual */ ++#endif ++ struct drm_buf_pub *list; /**< Buffer information */ ++}; ++ ++/* ++ * DRM_IOCTL_DMA ioctl argument type. ++ * ++ * Indices here refer to the offset into the buffer list in drm_buf_get. ++ * ++ * \sa drmDMA(). ++ */ ++struct drm_dma { ++ int context; /**< Context handle */ ++ int send_count; /**< Number of buffers to send */ ++ int *send_indices; /**< List of handles to buffers */ ++ int *send_sizes; /**< Lengths of data to send */ ++ enum drm_dma_flags flags; /**< Flags */ ++ int request_count; /**< Number of buffers requested */ ++ int request_size; /**< Desired size for buffers */ ++ int *request_indices; /**< Buffer information */ ++ int *request_sizes; ++ int granted_count; /**< Number of buffers granted */ ++}; ++ ++enum drm_ctx_flags { ++ _DRM_CONTEXT_PRESERVED = 0x01, ++ _DRM_CONTEXT_2DONLY = 0x02 ++}; ++ ++/* ++ * DRM_IOCTL_ADD_CTX ioctl argument type. ++ * ++ * \sa drmCreateContext() and drmDestroyContext(). ++ */ ++struct drm_ctx { ++ drm_context_t handle; ++ enum drm_ctx_flags flags; ++}; ++ ++/* ++ * DRM_IOCTL_RES_CTX ioctl argument type. ++ */ ++struct drm_ctx_res { ++ int count; ++ struct drm_ctx *contexts; ++}; ++ ++/* ++ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type. ++ */ ++struct drm_draw { ++ drm_drawable_t handle; ++}; ++ ++/* ++ * DRM_IOCTL_UPDATE_DRAW ioctl argument type. ++ */ ++typedef enum { ++ DRM_DRAWABLE_CLIPRECTS ++} drm_drawable_info_type_t; ++ ++struct drm_update_draw { ++ drm_drawable_t handle; ++ unsigned int type; ++ unsigned int num; ++ unsigned long long data; ++}; ++ ++/* ++ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. ++ */ ++struct drm_auth { ++ drm_magic_t magic; ++}; ++ ++/* ++ * DRM_IOCTL_IRQ_BUSID ioctl argument type. ++ * ++ * \sa drmGetInterruptFromBusID(). ++ */ ++struct drm_irq_busid { ++ int irq; /**< IRQ number */ ++ int busnum; /**< bus number */ ++ int devnum; /**< device number */ ++ int funcnum; /**< function number */ ++}; ++ ++enum drm_vblank_seq_type { ++ _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ ++ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ ++ /* bits 1-6 are reserved for high crtcs */ ++ _DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, ++ _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ ++ _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ ++ _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ ++ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ ++ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */ ++}; ++#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1 ++ ++#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) ++#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ ++ _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) ++ ++struct drm_wait_vblank_request { ++ enum drm_vblank_seq_type type; ++ unsigned int sequence; ++ unsigned long signal; ++}; ++ ++struct drm_wait_vblank_reply { ++ enum drm_vblank_seq_type type; ++ unsigned int sequence; ++ long tval_sec; ++ long tval_usec; ++}; ++ ++/* ++ * DRM_IOCTL_WAIT_VBLANK ioctl argument type. ++ * ++ * \sa drmWaitVBlank(). ++ */ ++union drm_wait_vblank { ++ struct drm_wait_vblank_request request; ++ struct drm_wait_vblank_reply reply; ++}; ++ ++#define _DRM_PRE_MODESET 1 ++#define _DRM_POST_MODESET 2 ++ ++/* ++ * DRM_IOCTL_MODESET_CTL ioctl argument type ++ * ++ * \sa drmModesetCtl(). ++ */ ++struct drm_modeset_ctl { ++ __u32 crtc; ++ __u32 cmd; ++}; ++ ++/* ++ * DRM_IOCTL_AGP_ENABLE ioctl argument type. ++ * ++ * \sa drmAgpEnable(). ++ */ ++struct drm_agp_mode { ++ unsigned long mode; /**< AGP mode */ ++}; ++ ++/* ++ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type. ++ * ++ * \sa drmAgpAlloc() and drmAgpFree(). ++ */ ++struct drm_agp_buffer { ++ unsigned long size; /**< In bytes -- will round to page boundary */ ++ unsigned long handle; /**< Used for binding / unbinding */ ++ unsigned long type; /**< Type of memory to allocate */ ++ unsigned long physical; /**< Physical used by i810 */ ++}; ++ ++/* ++ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type. ++ * ++ * \sa drmAgpBind() and drmAgpUnbind(). ++ */ ++struct drm_agp_binding { ++ unsigned long handle; /**< From drm_agp_buffer */ ++ unsigned long offset; /**< In bytes -- will round to page boundary */ ++}; ++ ++/* ++ * DRM_IOCTL_AGP_INFO ioctl argument type. ++ * ++ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(), ++ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(), ++ * drmAgpVendorId() and drmAgpDeviceId(). ++ */ ++struct drm_agp_info { ++ int agp_version_major; ++ int agp_version_minor; ++ unsigned long mode; ++ unsigned long aperture_base; /* physical address */ ++ unsigned long aperture_size; /* bytes */ ++ unsigned long memory_allowed; /* bytes */ ++ unsigned long memory_used; ++ ++ /* PCI information */ ++ unsigned short id_vendor; ++ unsigned short id_device; ++}; ++ ++/* ++ * DRM_IOCTL_SG_ALLOC ioctl argument type. ++ */ ++struct drm_scatter_gather { ++ unsigned long size; /**< In bytes -- will round to page boundary */ ++ unsigned long handle; /**< Used for mapping / unmapping */ ++}; ++ ++/* ++ * DRM_IOCTL_SET_VERSION ioctl argument type. ++ */ ++struct drm_set_version { ++ int drm_di_major; ++ int drm_di_minor; ++ int drm_dd_major; ++ int drm_dd_minor; ++}; ++ ++/* DRM_IOCTL_GEM_CLOSE ioctl argument type */ ++struct drm_gem_close { ++ /** Handle of the object to be closed. */ ++ __u32 handle; ++ __u32 pad; ++}; ++ ++/* DRM_IOCTL_GEM_FLINK ioctl argument type */ ++struct drm_gem_flink { ++ /** Handle for the object being named */ ++ __u32 handle; ++ ++ /** Returned global name */ ++ __u32 name; ++}; ++ ++/* DRM_IOCTL_GEM_OPEN ioctl argument type */ ++struct drm_gem_open { ++ /** Name of object being opened */ ++ __u32 name; ++ ++ /** Returned handle for the object */ ++ __u32 handle; ++ ++ /** Returned size of the object */ ++ __u64 size; ++}; ++ ++/** ++ * DRM_CAP_DUMB_BUFFER ++ * ++ * If set to 1, the driver supports creating dumb buffers via the ++ * &DRM_IOCTL_MODE_CREATE_DUMB ioctl. ++ */ ++#define DRM_CAP_DUMB_BUFFER 0x1 ++/** ++ * DRM_CAP_VBLANK_HIGH_CRTC ++ * ++ * If set to 1, the kernel supports specifying a :ref:`CRTC index` ++ * in the high bits of &drm_wait_vblank_request.type. ++ * ++ * Starting kernel version 2.6.39, this capability is always set to 1. ++ */ ++#define DRM_CAP_VBLANK_HIGH_CRTC 0x2 ++/** ++ * DRM_CAP_DUMB_PREFERRED_DEPTH ++ * ++ * The preferred bit depth for dumb buffers. ++ * ++ * The bit depth is the number of bits used to indicate the color of a single ++ * pixel excluding any padding. This is different from the number of bits per ++ * pixel. For instance, XRGB8888 has a bit depth of 24 but has 32 bits per ++ * pixel. ++ * ++ * Note that this preference only applies to dumb buffers, it's irrelevant for ++ * other types of buffers. ++ */ ++#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 ++/** ++ * DRM_CAP_DUMB_PREFER_SHADOW ++ * ++ * If set to 1, the driver prefers userspace to render to a shadow buffer ++ * instead of directly rendering to a dumb buffer. For best speed, userspace ++ * should do streaming ordered memory copies into the dumb buffer and never ++ * read from it. ++ * ++ * Note that this preference only applies to dumb buffers, it's irrelevant for ++ * other types of buffers. ++ */ ++#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 ++/** ++ * DRM_CAP_PRIME ++ * ++ * Bitfield of supported PRIME sharing capabilities. See &DRM_PRIME_CAP_IMPORT ++ * and &DRM_PRIME_CAP_EXPORT. ++ * ++ * PRIME buffers are exposed as dma-buf file descriptors. See ++ * Documentation/gpu/drm-mm.rst, section "PRIME Buffer Sharing". ++ */ ++#define DRM_CAP_PRIME 0x5 ++/** ++ * DRM_PRIME_CAP_IMPORT ++ * ++ * If this bit is set in &DRM_CAP_PRIME, the driver supports importing PRIME ++ * buffers via the &DRM_IOCTL_PRIME_FD_TO_HANDLE ioctl. ++ */ ++#define DRM_PRIME_CAP_IMPORT 0x1 ++/** ++ * DRM_PRIME_CAP_EXPORT ++ * ++ * If this bit is set in &DRM_CAP_PRIME, the driver supports exporting PRIME ++ * buffers via the &DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl. ++ */ ++#define DRM_PRIME_CAP_EXPORT 0x2 ++/** ++ * DRM_CAP_TIMESTAMP_MONOTONIC ++ * ++ * If set to 0, the kernel will report timestamps with ``CLOCK_REALTIME`` in ++ * struct drm_event_vblank. If set to 1, the kernel will report timestamps with ++ * ``CLOCK_MONOTONIC``. See ``clock_gettime(2)`` for the definition of these ++ * clocks. ++ * ++ * Starting from kernel version 2.6.39, the default value for this capability ++ * is 1. Starting kernel version 4.15, this capability is always set to 1. ++ */ ++#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 ++/** ++ * DRM_CAP_ASYNC_PAGE_FLIP ++ * ++ * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. ++ */ ++#define DRM_CAP_ASYNC_PAGE_FLIP 0x7 ++/** ++ * DRM_CAP_CURSOR_WIDTH ++ * ++ * The ``CURSOR_WIDTH`` and ``CURSOR_HEIGHT`` capabilities return a valid ++ * width x height combination for the hardware cursor. The intention is that a ++ * hardware agnostic userspace can query a cursor plane size to use. ++ * ++ * Note that the cross-driver contract is to merely return a valid size; ++ * drivers are free to attach another meaning on top, eg. i915 returns the ++ * maximum plane size. ++ */ ++#define DRM_CAP_CURSOR_WIDTH 0x8 ++/** ++ * DRM_CAP_CURSOR_HEIGHT ++ * ++ * See &DRM_CAP_CURSOR_WIDTH. ++ */ ++#define DRM_CAP_CURSOR_HEIGHT 0x9 ++/** ++ * DRM_CAP_ADDFB2_MODIFIERS ++ * ++ * If set to 1, the driver supports supplying modifiers in the ++ * &DRM_IOCTL_MODE_ADDFB2 ioctl. ++ */ ++#define DRM_CAP_ADDFB2_MODIFIERS 0x10 ++/** ++ * DRM_CAP_PAGE_FLIP_TARGET ++ * ++ * If set to 1, the driver supports the &DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE and ++ * &DRM_MODE_PAGE_FLIP_TARGET_RELATIVE flags in ++ * &drm_mode_crtc_page_flip_target.flags for the &DRM_IOCTL_MODE_PAGE_FLIP ++ * ioctl. ++ */ ++#define DRM_CAP_PAGE_FLIP_TARGET 0x11 ++/** ++ * DRM_CAP_CRTC_IN_VBLANK_EVENT ++ * ++ * If set to 1, the kernel supports reporting the CRTC ID in ++ * &drm_event_vblank.crtc_id for the &DRM_EVENT_VBLANK and ++ * &DRM_EVENT_FLIP_COMPLETE events. ++ * ++ * Starting kernel version 4.12, this capability is always set to 1. ++ */ ++#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12 ++/** ++ * DRM_CAP_SYNCOBJ ++ * ++ * If set to 1, the driver supports sync objects. See ++ * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". ++ */ ++#define DRM_CAP_SYNCOBJ 0x13 ++/** ++ * DRM_CAP_SYNCOBJ_TIMELINE ++ * ++ * If set to 1, the driver supports timeline operations on sync objects. See ++ * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects". ++ */ ++#define DRM_CAP_SYNCOBJ_TIMELINE 0x14 ++ ++/* DRM_IOCTL_GET_CAP ioctl argument type */ ++struct drm_get_cap { ++ __u64 capability; ++ __u64 value; ++}; ++ ++/** ++ * DRM_CLIENT_CAP_STEREO_3D ++ * ++ * If set to 1, the DRM core will expose the stereo 3D capabilities of the ++ * monitor by advertising the supported 3D layouts in the flags of struct ++ * drm_mode_modeinfo. See ``DRM_MODE_FLAG_3D_*``. ++ * ++ * This capability is always supported for all drivers starting from kernel ++ * version 3.13. ++ */ ++#define DRM_CLIENT_CAP_STEREO_3D 1 ++ ++/** ++ * DRM_CLIENT_CAP_UNIVERSAL_PLANES ++ * ++ * If set to 1, the DRM core will expose all planes (overlay, primary, and ++ * cursor) to userspace. ++ * ++ * This capability has been introduced in kernel version 3.15. Starting from ++ * kernel version 3.17, this capability is always supported for all drivers. ++ */ ++#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 ++ ++/** ++ * DRM_CLIENT_CAP_ATOMIC ++ * ++ * If set to 1, the DRM core will expose atomic properties to userspace. This ++ * implicitly enables &DRM_CLIENT_CAP_UNIVERSAL_PLANES and ++ * &DRM_CLIENT_CAP_ASPECT_RATIO. ++ * ++ * If the driver doesn't support atomic mode-setting, enabling this capability ++ * will fail with -EOPNOTSUPP. ++ * ++ * This capability has been introduced in kernel version 4.0. Starting from ++ * kernel version 4.2, this capability is always supported for atomic-capable ++ * drivers. ++ */ ++#define DRM_CLIENT_CAP_ATOMIC 3 ++ ++/** ++ * DRM_CLIENT_CAP_ASPECT_RATIO ++ * ++ * If set to 1, the DRM core will provide aspect ratio information in modes. ++ * See ``DRM_MODE_FLAG_PIC_AR_*``. ++ * ++ * This capability is always supported for all drivers starting from kernel ++ * version 4.18. ++ */ ++#define DRM_CLIENT_CAP_ASPECT_RATIO 4 ++ ++/** ++ * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS ++ * ++ * If set to 1, the DRM core will expose special connectors to be used for ++ * writing back to memory the scene setup in the commit. The client must enable ++ * &DRM_CLIENT_CAP_ATOMIC first. ++ * ++ * This capability is always supported for atomic-capable drivers starting from ++ * kernel version 4.19. ++ */ ++#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 ++ ++/* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ ++struct drm_set_client_cap { ++ __u64 capability; ++ __u64 value; ++}; ++ ++#define DRM_RDWR O_RDWR ++#define DRM_CLOEXEC O_CLOEXEC ++struct drm_prime_handle { ++ __u32 handle; ++ ++ /** Flags.. only applicable for handle->fd */ ++ __u32 flags; ++ ++ /** Returned dmabuf file descriptor */ ++ __s32 fd; ++}; ++ ++struct drm_syncobj_create { ++ __u32 handle; ++#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0) ++ __u32 flags; ++}; ++ ++struct drm_syncobj_destroy { ++ __u32 handle; ++ __u32 pad; ++}; ++ ++#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) ++#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) ++struct drm_syncobj_handle { ++ __u32 handle; ++ __u32 flags; ++ ++ __s32 fd; ++ __u32 pad; ++}; ++ ++struct drm_syncobj_transfer { ++ __u32 src_handle; ++ __u32 dst_handle; ++ __u64 src_point; ++ __u64 dst_point; ++ __u32 flags; ++ __u32 pad; ++}; ++ ++#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) ++#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) ++#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ ++struct drm_syncobj_wait { ++ __u64 handles; ++ /* absolute timeout */ ++ __s64 timeout_nsec; ++ __u32 count_handles; ++ __u32 flags; ++ __u32 first_signaled; /* only valid when not waiting all */ ++ __u32 pad; ++}; ++ ++struct drm_syncobj_timeline_wait { ++ __u64 handles; ++ /* wait on specific timeline point for every handles*/ ++ __u64 points; ++ /* absolute timeout */ ++ __s64 timeout_nsec; ++ __u32 count_handles; ++ __u32 flags; ++ __u32 first_signaled; /* only valid when not waiting all */ ++ __u32 pad; ++}; ++ ++ ++struct drm_syncobj_array { ++ __u64 handles; ++ __u32 count_handles; ++ __u32 pad; ++}; ++ ++#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */ ++struct drm_syncobj_timeline_array { ++ __u64 handles; ++ __u64 points; ++ __u32 count_handles; ++ __u32 flags; ++}; ++ ++ ++/* Query current scanout sequence number */ ++struct drm_crtc_get_sequence { ++ __u32 crtc_id; /* requested crtc_id */ ++ __u32 active; /* return: crtc output is active */ ++ __u64 sequence; /* return: most recent vblank sequence */ ++ __s64 sequence_ns; /* return: most recent time of first pixel out */ ++}; ++ ++/* Queue event to be delivered at specified sequence. Time stamp marks ++ * when the first pixel of the refresh cycle leaves the display engine ++ * for the display ++ */ ++#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001 /* sequence is relative to current */ ++#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002 /* Use next sequence if we've missed */ ++ ++struct drm_crtc_queue_sequence { ++ __u32 crtc_id; ++ __u32 flags; ++ __u64 sequence; /* on input, target sequence. on output, actual sequence */ ++ __u64 user_data; /* user data passed to event */ ++}; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#include "drm_mode.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#define DRM_IOCTL_BASE 'd' ++#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) ++#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) ++#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type) ++#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) ++ ++#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version) ++#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique) ++#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth) ++#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid) ++#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map) ++#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) ++#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) ++#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) ++#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl) ++#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close) ++#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) ++#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) ++#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) ++#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap) ++ ++#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) ++#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) ++#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block) ++#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block) ++#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control) ++#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map) ++#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc) ++#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc) ++#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info) ++#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map) ++#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free) ++ ++#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map) ++ ++#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) ++#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) ++ ++#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) ++#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) ++ ++#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) ++#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) ++#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) ++#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx) ++#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx) ++#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx) ++#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res) ++#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw) ++#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw) ++#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma) ++#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock) ++#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock) ++#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock) ++ ++#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle) ++#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle) ++ ++#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) ++#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) ++#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode) ++#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info) ++#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer) ++#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer) ++#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding) ++#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding) ++ ++#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather) ++#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather) ++ ++#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank) ++ ++#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence) ++#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence) ++ ++#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw) ++ ++#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) ++#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) ++#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) ++#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) ++#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) ++#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) ++#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) ++#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) ++#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */ ++#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */ ++ ++#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) ++#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) ++#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) ++#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) ++#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) ++/** ++ * DRM_IOCTL_MODE_RMFB - Remove a framebuffer. ++ * ++ * This removes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL ++ * argument is a framebuffer object ID. ++ * ++ * Warning: removing a framebuffer currently in-use on an enabled plane will ++ * disable that plane. The CRTC the plane is linked to may also be disabled ++ * (depending on driver capabilities). ++ */ ++#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int) ++#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) ++#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) ++ ++#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb) ++#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb) ++#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb) ++#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) ++#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) ++#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) ++#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) ++#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) ++#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) ++#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) ++#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) ++#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob) ++#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob) ++ ++#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create) ++#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) ++#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) ++#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) ++#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait) ++#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array) ++#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array) ++ ++#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease) ++#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees) ++#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) ++#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) ++ ++#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) ++#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) ++#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) ++#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) ++ ++#define DRM_IOCTL_MODE_GETFB2 DRM_IOWR(0xCE, struct drm_mode_fb_cmd2) ++ ++/* ++ * Device specific ioctls should only be in their respective headers ++ * The device specific ioctl range is from 0x40 to 0x9f. ++ * Generic IOCTLS restart at 0xA0. ++ * ++ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and ++ * drmCommandReadWrite(). ++ */ ++#define DRM_COMMAND_BASE 0x40 ++#define DRM_COMMAND_END 0xA0 ++ ++/* ++ * Header for events written back to userspace on the drm fd. The ++ * type defines the type of event, the length specifies the total ++ * length of the event (including the header), and user_data is ++ * typically a 64 bit value passed with the ioctl that triggered the ++ * event. A read on the drm fd will always only return complete ++ * events, that is, if for example the read buffer is 100 bytes, and ++ * there are two 64 byte events pending, only one will be returned. ++ * ++ * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and ++ * up are chipset specific. ++ */ ++struct drm_event { ++ __u32 type; ++ __u32 length; ++}; ++ ++#define DRM_EVENT_VBLANK 0x01 ++#define DRM_EVENT_FLIP_COMPLETE 0x02 ++#define DRM_EVENT_CRTC_SEQUENCE 0x03 ++ ++struct drm_event_vblank { ++ struct drm_event base; ++ __u64 user_data; ++ __u32 tv_sec; ++ __u32 tv_usec; ++ __u32 sequence; ++ __u32 crtc_id; /* 0 on older kernels that do not support this */ ++}; ++ ++/* Event delivered at sequence. Time stamp marks when the first pixel ++ * of the refresh cycle leaves the display engine for the display ++ */ ++struct drm_event_crtc_sequence { ++ struct drm_event base; ++ __u64 user_data; ++ __s64 time_ns; ++ __u64 sequence; ++}; ++ ++/* typedef area */ ++typedef struct drm_clip_rect drm_clip_rect_t; ++typedef struct drm_drawable_info drm_drawable_info_t; ++typedef struct drm_tex_region drm_tex_region_t; ++typedef struct drm_hw_lock drm_hw_lock_t; ++typedef struct drm_version drm_version_t; ++typedef struct drm_unique drm_unique_t; ++typedef struct drm_list drm_list_t; ++typedef struct drm_block drm_block_t; ++typedef struct drm_control drm_control_t; ++typedef enum drm_map_type drm_map_type_t; ++typedef enum drm_map_flags drm_map_flags_t; ++typedef struct drm_ctx_priv_map drm_ctx_priv_map_t; ++typedef struct drm_map drm_map_t; ++typedef struct drm_client drm_client_t; ++typedef enum drm_stat_type drm_stat_type_t; ++typedef struct drm_stats drm_stats_t; ++typedef enum drm_lock_flags drm_lock_flags_t; ++typedef struct drm_lock drm_lock_t; ++typedef enum drm_dma_flags drm_dma_flags_t; ++typedef struct drm_buf_desc drm_buf_desc_t; ++typedef struct drm_buf_info drm_buf_info_t; ++typedef struct drm_buf_free drm_buf_free_t; ++typedef struct drm_buf_pub drm_buf_pub_t; ++typedef struct drm_buf_map drm_buf_map_t; ++typedef struct drm_dma drm_dma_t; ++typedef union drm_wait_vblank drm_wait_vblank_t; ++typedef struct drm_agp_mode drm_agp_mode_t; ++typedef enum drm_ctx_flags drm_ctx_flags_t; ++typedef struct drm_ctx drm_ctx_t; ++typedef struct drm_ctx_res drm_ctx_res_t; ++typedef struct drm_draw drm_draw_t; ++typedef struct drm_update_draw drm_update_draw_t; ++typedef struct drm_auth drm_auth_t; ++typedef struct drm_irq_busid drm_irq_busid_t; ++typedef enum drm_vblank_seq_type drm_vblank_seq_type_t; ++ ++typedef struct drm_agp_buffer drm_agp_buffer_t; ++typedef struct drm_agp_binding drm_agp_binding_t; ++typedef struct drm_agp_info drm_agp_info_t; ++typedef struct drm_scatter_gather drm_scatter_gather_t; ++typedef struct drm_set_version drm_set_version_t; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif +diff -up firefox-103.0/third_party/drm/drm/drm_mode.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/drm/drm_mode.h +--- firefox-103.0/third_party/drm/drm/drm_mode.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/drm/drm/drm_mode.h 2022-07-28 11:45:30.317409023 +0200 +@@ -0,0 +1,1217 @@ ++/* ++ * Copyright (c) 2007 Dave Airlie ++ * Copyright (c) 2007 Jakob Bornecrantz ++ * Copyright (c) 2008 Red Hat Inc. ++ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA ++ * Copyright (c) 2007-2008 Intel Corporation ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#ifndef _DRM_MODE_H ++#define _DRM_MODE_H ++ ++#include "drm.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++/** ++ * DOC: overview ++ * ++ * DRM exposes many UAPI and structure definition to have a consistent ++ * and standardized interface with user. ++ * Userspace can refer to these structure definitions and UAPI formats ++ * to communicate to driver ++ */ ++ ++#define DRM_CONNECTOR_NAME_LEN 32 ++#define DRM_DISPLAY_MODE_LEN 32 ++#define DRM_PROP_NAME_LEN 32 ++ ++#define DRM_MODE_TYPE_BUILTIN (1<<0) /* deprecated */ ++#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ ++#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) /* deprecated */ ++#define DRM_MODE_TYPE_PREFERRED (1<<3) ++#define DRM_MODE_TYPE_DEFAULT (1<<4) /* deprecated */ ++#define DRM_MODE_TYPE_USERDEF (1<<5) ++#define DRM_MODE_TYPE_DRIVER (1<<6) ++ ++#define DRM_MODE_TYPE_ALL (DRM_MODE_TYPE_PREFERRED | \ ++ DRM_MODE_TYPE_USERDEF | \ ++ DRM_MODE_TYPE_DRIVER) ++ ++/* Video mode flags */ ++/* bit compatible with the xrandr RR_ definitions (bits 0-13) ++ * ++ * ABI warning: Existing userspace really expects ++ * the mode flags to match the xrandr definitions. Any ++ * changes that don't match the xrandr definitions will ++ * likely need a new client cap or some other mechanism ++ * to avoid breaking existing userspace. This includes ++ * allocating new flags in the previously unused bits! ++ */ ++#define DRM_MODE_FLAG_PHSYNC (1<<0) ++#define DRM_MODE_FLAG_NHSYNC (1<<1) ++#define DRM_MODE_FLAG_PVSYNC (1<<2) ++#define DRM_MODE_FLAG_NVSYNC (1<<3) ++#define DRM_MODE_FLAG_INTERLACE (1<<4) ++#define DRM_MODE_FLAG_DBLSCAN (1<<5) ++#define DRM_MODE_FLAG_CSYNC (1<<6) ++#define DRM_MODE_FLAG_PCSYNC (1<<7) ++#define DRM_MODE_FLAG_NCSYNC (1<<8) ++#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ ++#define DRM_MODE_FLAG_BCAST (1<<10) /* deprecated */ ++#define DRM_MODE_FLAG_PIXMUX (1<<11) /* deprecated */ ++#define DRM_MODE_FLAG_DBLCLK (1<<12) ++#define DRM_MODE_FLAG_CLKDIV2 (1<<13) ++ /* ++ * When adding a new stereo mode don't forget to adjust DRM_MODE_FLAGS_3D_MAX ++ * (define not exposed to user space). ++ */ ++#define DRM_MODE_FLAG_3D_MASK (0x1f<<14) ++#define DRM_MODE_FLAG_3D_NONE (0<<14) ++#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14) ++#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (2<<14) ++#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (3<<14) ++#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) ++#define DRM_MODE_FLAG_3D_L_DEPTH (5<<14) ++#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) ++#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14) ++#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) ++ ++/* Picture aspect ratio options */ ++#define DRM_MODE_PICTURE_ASPECT_NONE 0 ++#define DRM_MODE_PICTURE_ASPECT_4_3 1 ++#define DRM_MODE_PICTURE_ASPECT_16_9 2 ++#define DRM_MODE_PICTURE_ASPECT_64_27 3 ++#define DRM_MODE_PICTURE_ASPECT_256_135 4 ++ ++/* Content type options */ ++#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 ++#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 ++#define DRM_MODE_CONTENT_TYPE_PHOTO 2 ++#define DRM_MODE_CONTENT_TYPE_CINEMA 3 ++#define DRM_MODE_CONTENT_TYPE_GAME 4 ++ ++/* Aspect ratio flag bitmask (4 bits 22:19) */ ++#define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) ++#define DRM_MODE_FLAG_PIC_AR_NONE \ ++ (DRM_MODE_PICTURE_ASPECT_NONE<<19) ++#define DRM_MODE_FLAG_PIC_AR_4_3 \ ++ (DRM_MODE_PICTURE_ASPECT_4_3<<19) ++#define DRM_MODE_FLAG_PIC_AR_16_9 \ ++ (DRM_MODE_PICTURE_ASPECT_16_9<<19) ++#define DRM_MODE_FLAG_PIC_AR_64_27 \ ++ (DRM_MODE_PICTURE_ASPECT_64_27<<19) ++#define DRM_MODE_FLAG_PIC_AR_256_135 \ ++ (DRM_MODE_PICTURE_ASPECT_256_135<<19) ++ ++#define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ ++ DRM_MODE_FLAG_NHSYNC | \ ++ DRM_MODE_FLAG_PVSYNC | \ ++ DRM_MODE_FLAG_NVSYNC | \ ++ DRM_MODE_FLAG_INTERLACE | \ ++ DRM_MODE_FLAG_DBLSCAN | \ ++ DRM_MODE_FLAG_CSYNC | \ ++ DRM_MODE_FLAG_PCSYNC | \ ++ DRM_MODE_FLAG_NCSYNC | \ ++ DRM_MODE_FLAG_HSKEW | \ ++ DRM_MODE_FLAG_DBLCLK | \ ++ DRM_MODE_FLAG_CLKDIV2 | \ ++ DRM_MODE_FLAG_3D_MASK) ++ ++/* DPMS flags */ ++/* bit compatible with the xorg definitions. */ ++#define DRM_MODE_DPMS_ON 0 ++#define DRM_MODE_DPMS_STANDBY 1 ++#define DRM_MODE_DPMS_SUSPEND 2 ++#define DRM_MODE_DPMS_OFF 3 ++ ++/* Scaling mode options */ ++#define DRM_MODE_SCALE_NONE 0 /* Unmodified timing (display or ++ software can still scale) */ ++#define DRM_MODE_SCALE_FULLSCREEN 1 /* Full screen, ignore aspect */ ++#define DRM_MODE_SCALE_CENTER 2 /* Centered, no scaling */ ++#define DRM_MODE_SCALE_ASPECT 3 /* Full screen, preserve aspect */ ++ ++/* Dithering mode options */ ++#define DRM_MODE_DITHERING_OFF 0 ++#define DRM_MODE_DITHERING_ON 1 ++#define DRM_MODE_DITHERING_AUTO 2 ++ ++/* Dirty info options */ ++#define DRM_MODE_DIRTY_OFF 0 ++#define DRM_MODE_DIRTY_ON 1 ++#define DRM_MODE_DIRTY_ANNOTATE 2 ++ ++/* Link Status options */ ++#define DRM_MODE_LINK_STATUS_GOOD 0 ++#define DRM_MODE_LINK_STATUS_BAD 1 ++ ++/* ++ * DRM_MODE_ROTATE_ ++ * ++ * Signals that a drm plane is been rotated degrees in counter ++ * clockwise direction. ++ * ++ * This define is provided as a convenience, looking up the property id ++ * using the name->prop id lookup is the preferred method. ++ */ ++#define DRM_MODE_ROTATE_0 (1<<0) ++#define DRM_MODE_ROTATE_90 (1<<1) ++#define DRM_MODE_ROTATE_180 (1<<2) ++#define DRM_MODE_ROTATE_270 (1<<3) ++ ++/* ++ * DRM_MODE_ROTATE_MASK ++ * ++ * Bitmask used to look for drm plane rotations. ++ */ ++#define DRM_MODE_ROTATE_MASK (\ ++ DRM_MODE_ROTATE_0 | \ ++ DRM_MODE_ROTATE_90 | \ ++ DRM_MODE_ROTATE_180 | \ ++ DRM_MODE_ROTATE_270) ++ ++/* ++ * DRM_MODE_REFLECT_ ++ * ++ * Signals that the contents of a drm plane is reflected along the axis, ++ * in the same way as mirroring. ++ * See kerneldoc chapter "Plane Composition Properties" for more details. ++ * ++ * This define is provided as a convenience, looking up the property id ++ * using the name->prop id lookup is the preferred method. ++ */ ++#define DRM_MODE_REFLECT_X (1<<4) ++#define DRM_MODE_REFLECT_Y (1<<5) ++ ++/* ++ * DRM_MODE_REFLECT_MASK ++ * ++ * Bitmask used to look for drm plane reflections. ++ */ ++#define DRM_MODE_REFLECT_MASK (\ ++ DRM_MODE_REFLECT_X | \ ++ DRM_MODE_REFLECT_Y) ++ ++/* Content Protection Flags */ ++#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 ++#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 ++#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 ++ ++/** ++ * struct drm_mode_modeinfo - Display mode information. ++ * @clock: pixel clock in kHz ++ * @hdisplay: horizontal display size ++ * @hsync_start: horizontal sync start ++ * @hsync_end: horizontal sync end ++ * @htotal: horizontal total size ++ * @hskew: horizontal skew ++ * @vdisplay: vertical display size ++ * @vsync_start: vertical sync start ++ * @vsync_end: vertical sync end ++ * @vtotal: vertical total size ++ * @vscan: vertical scan ++ * @vrefresh: approximate vertical refresh rate in Hz ++ * @flags: bitmask of misc. flags, see DRM_MODE_FLAG_* defines ++ * @type: bitmask of type flags, see DRM_MODE_TYPE_* defines ++ * @name: string describing the mode resolution ++ * ++ * This is the user-space API display mode information structure. For the ++ * kernel version see struct drm_display_mode. ++ */ ++struct drm_mode_modeinfo { ++ __u32 clock; ++ __u16 hdisplay; ++ __u16 hsync_start; ++ __u16 hsync_end; ++ __u16 htotal; ++ __u16 hskew; ++ __u16 vdisplay; ++ __u16 vsync_start; ++ __u16 vsync_end; ++ __u16 vtotal; ++ __u16 vscan; ++ ++ __u32 vrefresh; ++ ++ __u32 flags; ++ __u32 type; ++ char name[DRM_DISPLAY_MODE_LEN]; ++}; ++ ++struct drm_mode_card_res { ++ __u64 fb_id_ptr; ++ __u64 crtc_id_ptr; ++ __u64 connector_id_ptr; ++ __u64 encoder_id_ptr; ++ __u32 count_fbs; ++ __u32 count_crtcs; ++ __u32 count_connectors; ++ __u32 count_encoders; ++ __u32 min_width; ++ __u32 max_width; ++ __u32 min_height; ++ __u32 max_height; ++}; ++ ++struct drm_mode_crtc { ++ __u64 set_connectors_ptr; ++ __u32 count_connectors; ++ ++ __u32 crtc_id; /**< Id */ ++ __u32 fb_id; /**< Id of framebuffer */ ++ ++ __u32 x; /**< x Position on the framebuffer */ ++ __u32 y; /**< y Position on the framebuffer */ ++ ++ __u32 gamma_size; ++ __u32 mode_valid; ++ struct drm_mode_modeinfo mode; ++}; ++ ++#define DRM_MODE_PRESENT_TOP_FIELD (1<<0) ++#define DRM_MODE_PRESENT_BOTTOM_FIELD (1<<1) ++ ++/* Planes blend with or override other bits on the CRTC */ ++struct drm_mode_set_plane { ++ __u32 plane_id; ++ __u32 crtc_id; ++ __u32 fb_id; /* fb object contains surface format type */ ++ __u32 flags; /* see above flags */ ++ ++ /* Signed dest location allows it to be partially off screen */ ++ __s32 crtc_x; ++ __s32 crtc_y; ++ __u32 crtc_w; ++ __u32 crtc_h; ++ ++ /* Source values are 16.16 fixed point */ ++ __u32 src_x; ++ __u32 src_y; ++ __u32 src_h; ++ __u32 src_w; ++}; ++ ++/** ++ * struct drm_mode_get_plane - Get plane metadata. ++ * ++ * Userspace can perform a GETPLANE ioctl to retrieve information about a ++ * plane. ++ * ++ * To retrieve the number of formats supported, set @count_format_types to zero ++ * and call the ioctl. @count_format_types will be updated with the value. ++ * ++ * To retrieve these formats, allocate an array with the memory needed to store ++ * @count_format_types formats. Point @format_type_ptr to this array and call ++ * the ioctl again (with @count_format_types still set to the value returned in ++ * the first ioctl call). ++ */ ++struct drm_mode_get_plane { ++ /** ++ * @plane_id: Object ID of the plane whose information should be ++ * retrieved. Set by caller. ++ */ ++ __u32 plane_id; ++ ++ /** @crtc_id: Object ID of the current CRTC. */ ++ __u32 crtc_id; ++ /** @fb_id: Object ID of the current fb. */ ++ __u32 fb_id; ++ ++ /** ++ * @possible_crtcs: Bitmask of CRTC's compatible with the plane. CRTC's ++ * are created and they receive an index, which corresponds to their ++ * position in the bitmask. Bit N corresponds to ++ * :ref:`CRTC index` N. ++ */ ++ __u32 possible_crtcs; ++ /** @gamma_size: Never used. */ ++ __u32 gamma_size; ++ ++ /** @count_format_types: Number of formats. */ ++ __u32 count_format_types; ++ /** ++ * @format_type_ptr: Pointer to ``__u32`` array of formats that are ++ * supported by the plane. These formats do not require modifiers. ++ */ ++ __u64 format_type_ptr; ++}; ++ ++struct drm_mode_get_plane_res { ++ __u64 plane_id_ptr; ++ __u32 count_planes; ++}; ++ ++#define DRM_MODE_ENCODER_NONE 0 ++#define DRM_MODE_ENCODER_DAC 1 ++#define DRM_MODE_ENCODER_TMDS 2 ++#define DRM_MODE_ENCODER_LVDS 3 ++#define DRM_MODE_ENCODER_TVDAC 4 ++#define DRM_MODE_ENCODER_VIRTUAL 5 ++#define DRM_MODE_ENCODER_DSI 6 ++#define DRM_MODE_ENCODER_DPMST 7 ++#define DRM_MODE_ENCODER_DPI 8 ++ ++struct drm_mode_get_encoder { ++ __u32 encoder_id; ++ __u32 encoder_type; ++ ++ __u32 crtc_id; /**< Id of crtc */ ++ ++ __u32 possible_crtcs; ++ __u32 possible_clones; ++}; ++ ++/* This is for connectors with multiple signal types. */ ++/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ ++enum drm_mode_subconnector { ++ DRM_MODE_SUBCONNECTOR_Automatic = 0, /* DVI-I, TV */ ++ DRM_MODE_SUBCONNECTOR_Unknown = 0, /* DVI-I, TV, DP */ ++ DRM_MODE_SUBCONNECTOR_VGA = 1, /* DP */ ++ DRM_MODE_SUBCONNECTOR_DVID = 3, /* DVI-I DP */ ++ DRM_MODE_SUBCONNECTOR_DVIA = 4, /* DVI-I */ ++ DRM_MODE_SUBCONNECTOR_Composite = 5, /* TV */ ++ DRM_MODE_SUBCONNECTOR_SVIDEO = 6, /* TV */ ++ DRM_MODE_SUBCONNECTOR_Component = 8, /* TV */ ++ DRM_MODE_SUBCONNECTOR_SCART = 9, /* TV */ ++ DRM_MODE_SUBCONNECTOR_DisplayPort = 10, /* DP */ ++ DRM_MODE_SUBCONNECTOR_HDMIA = 11, /* DP */ ++ DRM_MODE_SUBCONNECTOR_Native = 15, /* DP */ ++ DRM_MODE_SUBCONNECTOR_Wireless = 18, /* DP */ ++}; ++ ++#define DRM_MODE_CONNECTOR_Unknown 0 ++#define DRM_MODE_CONNECTOR_VGA 1 ++#define DRM_MODE_CONNECTOR_DVII 2 ++#define DRM_MODE_CONNECTOR_DVID 3 ++#define DRM_MODE_CONNECTOR_DVIA 4 ++#define DRM_MODE_CONNECTOR_Composite 5 ++#define DRM_MODE_CONNECTOR_SVIDEO 6 ++#define DRM_MODE_CONNECTOR_LVDS 7 ++#define DRM_MODE_CONNECTOR_Component 8 ++#define DRM_MODE_CONNECTOR_9PinDIN 9 ++#define DRM_MODE_CONNECTOR_DisplayPort 10 ++#define DRM_MODE_CONNECTOR_HDMIA 11 ++#define DRM_MODE_CONNECTOR_HDMIB 12 ++#define DRM_MODE_CONNECTOR_TV 13 ++#define DRM_MODE_CONNECTOR_eDP 14 ++#define DRM_MODE_CONNECTOR_VIRTUAL 15 ++#define DRM_MODE_CONNECTOR_DSI 16 ++#define DRM_MODE_CONNECTOR_DPI 17 ++#define DRM_MODE_CONNECTOR_WRITEBACK 18 ++#define DRM_MODE_CONNECTOR_SPI 19 ++#define DRM_MODE_CONNECTOR_USB 20 ++ ++/** ++ * struct drm_mode_get_connector - Get connector metadata. ++ * ++ * User-space can perform a GETCONNECTOR ioctl to retrieve information about a ++ * connector. User-space is expected to retrieve encoders, modes and properties ++ * by performing this ioctl at least twice: the first time to retrieve the ++ * number of elements, the second time to retrieve the elements themselves. ++ * ++ * To retrieve the number of elements, set @count_props and @count_encoders to ++ * zero, set @count_modes to 1, and set @modes_ptr to a temporary struct ++ * drm_mode_modeinfo element. ++ * ++ * To retrieve the elements, allocate arrays for @encoders_ptr, @modes_ptr, ++ * @props_ptr and @prop_values_ptr, then set @count_modes, @count_props and ++ * @count_encoders to their capacity. ++ * ++ * Performing the ioctl only twice may be racy: the number of elements may have ++ * changed with a hotplug event in-between the two ioctls. User-space is ++ * expected to retry the last ioctl until the number of elements stabilizes. ++ * The kernel won't fill any array which doesn't have the expected length. ++ * ++ * **Force-probing a connector** ++ * ++ * If the @count_modes field is set to zero and the DRM client is the current ++ * DRM master, the kernel will perform a forced probe on the connector to ++ * refresh the connector status, modes and EDID. A forced-probe can be slow, ++ * might cause flickering and the ioctl will block. ++ * ++ * User-space needs to force-probe connectors to ensure their metadata is ++ * up-to-date at startup and after receiving a hot-plug event. User-space ++ * may perform a forced-probe when the user explicitly requests it. User-space ++ * shouldn't perform a forced-probe in other situations. ++ */ ++struct drm_mode_get_connector { ++ /** @encoders_ptr: Pointer to ``__u32`` array of object IDs. */ ++ __u64 encoders_ptr; ++ /** @modes_ptr: Pointer to struct drm_mode_modeinfo array. */ ++ __u64 modes_ptr; ++ /** @props_ptr: Pointer to ``__u32`` array of property IDs. */ ++ __u64 props_ptr; ++ /** @prop_values_ptr: Pointer to ``__u64`` array of property values. */ ++ __u64 prop_values_ptr; ++ ++ /** @count_modes: Number of modes. */ ++ __u32 count_modes; ++ /** @count_props: Number of properties. */ ++ __u32 count_props; ++ /** @count_encoders: Number of encoders. */ ++ __u32 count_encoders; ++ ++ /** @encoder_id: Object ID of the current encoder. */ ++ __u32 encoder_id; ++ /** @connector_id: Object ID of the connector. */ ++ __u32 connector_id; ++ /** ++ * @connector_type: Type of the connector. ++ * ++ * See DRM_MODE_CONNECTOR_* defines. ++ */ ++ __u32 connector_type; ++ /** ++ * @connector_type_id: Type-specific connector number. ++ * ++ * This is not an object ID. This is a per-type connector number. Each ++ * (type, type_id) combination is unique across all connectors of a DRM ++ * device. ++ */ ++ __u32 connector_type_id; ++ ++ /** ++ * @connection: Status of the connector. ++ * ++ * See enum drm_connector_status. ++ */ ++ __u32 connection; ++ /** @mm_width: Width of the connected sink in millimeters. */ ++ __u32 mm_width; ++ /** @mm_height: Height of the connected sink in millimeters. */ ++ __u32 mm_height; ++ /** ++ * @subpixel: Subpixel order of the connected sink. ++ * ++ * See enum subpixel_order. ++ */ ++ __u32 subpixel; ++ ++ /** @pad: Padding, must be zero. */ ++ __u32 pad; ++}; ++ ++#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ ++#define DRM_MODE_PROP_RANGE (1<<1) ++#define DRM_MODE_PROP_IMMUTABLE (1<<2) ++#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ ++#define DRM_MODE_PROP_BLOB (1<<4) ++#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */ ++ ++/* non-extended types: legacy bitmask, one bit per type: */ ++#define DRM_MODE_PROP_LEGACY_TYPE ( \ ++ DRM_MODE_PROP_RANGE | \ ++ DRM_MODE_PROP_ENUM | \ ++ DRM_MODE_PROP_BLOB | \ ++ DRM_MODE_PROP_BITMASK) ++ ++/* extended-types: rather than continue to consume a bit per type, ++ * grab a chunk of the bits to use as integer type id. ++ */ ++#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 ++#define DRM_MODE_PROP_TYPE(n) ((n) << 6) ++#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) ++#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) ++ ++/* the PROP_ATOMIC flag is used to hide properties from userspace that ++ * is not aware of atomic properties. This is mostly to work around ++ * older userspace (DDX drivers) that read/write each prop they find, ++ * witout being aware that this could be triggering a lengthy modeset. ++ */ ++#define DRM_MODE_PROP_ATOMIC 0x80000000 ++ ++/** ++ * struct drm_mode_property_enum - Description for an enum/bitfield entry. ++ * @value: numeric value for this enum entry. ++ * @name: symbolic name for this enum entry. ++ * ++ * See struct drm_property_enum for details. ++ */ ++struct drm_mode_property_enum { ++ __u64 value; ++ char name[DRM_PROP_NAME_LEN]; ++}; ++ ++/** ++ * struct drm_mode_get_property - Get property metadata. ++ * ++ * User-space can perform a GETPROPERTY ioctl to retrieve information about a ++ * property. The same property may be attached to multiple objects, see ++ * "Modeset Base Object Abstraction". ++ * ++ * The meaning of the @values_ptr field changes depending on the property type. ++ * See &drm_property.flags for more details. ++ * ++ * The @enum_blob_ptr and @count_enum_blobs fields are only meaningful when the ++ * property has the type &DRM_MODE_PROP_ENUM or &DRM_MODE_PROP_BITMASK. For ++ * backwards compatibility, the kernel will always set @count_enum_blobs to ++ * zero when the property has the type &DRM_MODE_PROP_BLOB. User-space must ++ * ignore these two fields if the property has a different type. ++ * ++ * User-space is expected to retrieve values and enums by performing this ioctl ++ * at least twice: the first time to retrieve the number of elements, the ++ * second time to retrieve the elements themselves. ++ * ++ * To retrieve the number of elements, set @count_values and @count_enum_blobs ++ * to zero, then call the ioctl. @count_values will be updated with the number ++ * of elements. If the property has the type &DRM_MODE_PROP_ENUM or ++ * &DRM_MODE_PROP_BITMASK, @count_enum_blobs will be updated as well. ++ * ++ * To retrieve the elements themselves, allocate an array for @values_ptr and ++ * set @count_values to its capacity. If the property has the type ++ * &DRM_MODE_PROP_ENUM or &DRM_MODE_PROP_BITMASK, allocate an array for ++ * @enum_blob_ptr and set @count_enum_blobs to its capacity. Calling the ioctl ++ * again will fill the arrays. ++ */ ++struct drm_mode_get_property { ++ /** @values_ptr: Pointer to a ``__u64`` array. */ ++ __u64 values_ptr; ++ /** @enum_blob_ptr: Pointer to a struct drm_mode_property_enum array. */ ++ __u64 enum_blob_ptr; ++ ++ /** ++ * @prop_id: Object ID of the property which should be retrieved. Set ++ * by the caller. ++ */ ++ __u32 prop_id; ++ /** ++ * @flags: ``DRM_MODE_PROP_*`` bitfield. See &drm_property.flags for ++ * a definition of the flags. ++ */ ++ __u32 flags; ++ /** ++ * @name: Symbolic property name. User-space should use this field to ++ * recognize properties. ++ */ ++ char name[DRM_PROP_NAME_LEN]; ++ ++ /** @count_values: Number of elements in @values_ptr. */ ++ __u32 count_values; ++ /** @count_enum_blobs: Number of elements in @enum_blob_ptr. */ ++ __u32 count_enum_blobs; ++}; ++ ++struct drm_mode_connector_set_property { ++ __u64 value; ++ __u32 prop_id; ++ __u32 connector_id; ++}; ++ ++#define DRM_MODE_OBJECT_CRTC 0xcccccccc ++#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 ++#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 ++#define DRM_MODE_OBJECT_MODE 0xdededede ++#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 ++#define DRM_MODE_OBJECT_FB 0xfbfbfbfb ++#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb ++#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee ++#define DRM_MODE_OBJECT_ANY 0 ++ ++struct drm_mode_obj_get_properties { ++ __u64 props_ptr; ++ __u64 prop_values_ptr; ++ __u32 count_props; ++ __u32 obj_id; ++ __u32 obj_type; ++}; ++ ++struct drm_mode_obj_set_property { ++ __u64 value; ++ __u32 prop_id; ++ __u32 obj_id; ++ __u32 obj_type; ++}; ++ ++struct drm_mode_get_blob { ++ __u32 blob_id; ++ __u32 length; ++ __u64 data; ++}; ++ ++struct drm_mode_fb_cmd { ++ __u32 fb_id; ++ __u32 width; ++ __u32 height; ++ __u32 pitch; ++ __u32 bpp; ++ __u32 depth; ++ /* driver specific handle */ ++ __u32 handle; ++}; ++ ++#define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ ++#define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */ ++ ++struct drm_mode_fb_cmd2 { ++ __u32 fb_id; ++ __u32 width; ++ __u32 height; ++ __u32 pixel_format; /* fourcc code from drm_fourcc.h */ ++ __u32 flags; /* see above flags */ ++ ++ /* ++ * In case of planar formats, this ioctl allows up to 4 ++ * buffer objects with offsets and pitches per plane. ++ * The pitch and offset order is dictated by the fourcc, ++ * e.g. NV12 (https://fourcc.org/yuv.php#NV12) is described as: ++ * ++ * YUV 4:2:0 image with a plane of 8 bit Y samples ++ * followed by an interleaved U/V plane containing ++ * 8 bit 2x2 subsampled colour difference samples. ++ * ++ * So it would consist of Y as offsets[0] and UV as ++ * offsets[1]. Note that offsets[0] will generally ++ * be 0 (but this is not required). ++ * ++ * To accommodate tiled, compressed, etc formats, a ++ * modifier can be specified. The default value of zero ++ * indicates "native" format as specified by the fourcc. ++ * Vendor specific modifier token. Note that even though ++ * it looks like we have a modifier per-plane, we in fact ++ * do not. The modifier for each plane must be identical. ++ * Thus all combinations of different data layouts for ++ * multi plane formats must be enumerated as separate ++ * modifiers. ++ */ ++ __u32 handles[4]; ++ __u32 pitches[4]; /* pitch for each plane */ ++ __u32 offsets[4]; /* offset of each plane */ ++ __u64 modifier[4]; /* ie, tiling, compress */ ++}; ++ ++#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 ++#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 ++#define DRM_MODE_FB_DIRTY_FLAGS 0x03 ++ ++#define DRM_MODE_FB_DIRTY_MAX_CLIPS 256 ++ ++/* ++ * Mark a region of a framebuffer as dirty. ++ * ++ * Some hardware does not automatically update display contents ++ * as a hardware or software draw to a framebuffer. This ioctl ++ * allows userspace to tell the kernel and the hardware what ++ * regions of the framebuffer have changed. ++ * ++ * The kernel or hardware is free to update more then just the ++ * region specified by the clip rects. The kernel or hardware ++ * may also delay and/or coalesce several calls to dirty into a ++ * single update. ++ * ++ * Userspace may annotate the updates, the annotates are a ++ * promise made by the caller that the change is either a copy ++ * of pixels or a fill of a single color in the region specified. ++ * ++ * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then ++ * the number of updated regions are half of num_clips given, ++ * where the clip rects are paired in src and dst. The width and ++ * height of each one of the pairs must match. ++ * ++ * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller ++ * promises that the region specified of the clip rects is filled ++ * completely with a single color as given in the color argument. ++ */ ++ ++struct drm_mode_fb_dirty_cmd { ++ __u32 fb_id; ++ __u32 flags; ++ __u32 color; ++ __u32 num_clips; ++ __u64 clips_ptr; ++}; ++ ++struct drm_mode_mode_cmd { ++ __u32 connector_id; ++ struct drm_mode_modeinfo mode; ++}; ++ ++#define DRM_MODE_CURSOR_BO 0x01 ++#define DRM_MODE_CURSOR_MOVE 0x02 ++#define DRM_MODE_CURSOR_FLAGS 0x03 ++ ++/* ++ * depending on the value in flags different members are used. ++ * ++ * CURSOR_BO uses ++ * crtc_id ++ * width ++ * height ++ * handle - if 0 turns the cursor off ++ * ++ * CURSOR_MOVE uses ++ * crtc_id ++ * x ++ * y ++ */ ++struct drm_mode_cursor { ++ __u32 flags; ++ __u32 crtc_id; ++ __s32 x; ++ __s32 y; ++ __u32 width; ++ __u32 height; ++ /* driver specific handle */ ++ __u32 handle; ++}; ++ ++struct drm_mode_cursor2 { ++ __u32 flags; ++ __u32 crtc_id; ++ __s32 x; ++ __s32 y; ++ __u32 width; ++ __u32 height; ++ /* driver specific handle */ ++ __u32 handle; ++ __s32 hot_x; ++ __s32 hot_y; ++}; ++ ++struct drm_mode_crtc_lut { ++ __u32 crtc_id; ++ __u32 gamma_size; ++ ++ /* pointers to arrays */ ++ __u64 red; ++ __u64 green; ++ __u64 blue; ++}; ++ ++struct drm_color_ctm { ++ /* ++ * Conversion matrix in S31.32 sign-magnitude ++ * (not two's complement!) format. ++ */ ++ __u64 matrix[9]; ++}; ++ ++struct drm_color_lut { ++ /* ++ * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and ++ * 0xffff == 1.0. ++ */ ++ __u16 red; ++ __u16 green; ++ __u16 blue; ++ __u16 reserved; ++}; ++ ++/** ++ * struct hdr_metadata_infoframe - HDR Metadata Infoframe Data. ++ * ++ * HDR Metadata Infoframe as per CTA 861.G spec. This is expected ++ * to match exactly with the spec. ++ * ++ * Userspace is expected to pass the metadata information as per ++ * the format described in this structure. ++ */ ++struct hdr_metadata_infoframe { ++ /** ++ * @eotf: Electro-Optical Transfer Function (EOTF) ++ * used in the stream. ++ */ ++ __u8 eotf; ++ /** ++ * @metadata_type: Static_Metadata_Descriptor_ID. ++ */ ++ __u8 metadata_type; ++ /** ++ * @display_primaries: Color Primaries of the Data. ++ * These are coded as unsigned 16-bit values in units of ++ * 0.00002, where 0x0000 represents zero and 0xC350 ++ * represents 1.0000. ++ * @display_primaries.x: X cordinate of color primary. ++ * @display_primaries.y: Y cordinate of color primary. ++ */ ++ struct { ++ __u16 x, y; ++ } display_primaries[3]; ++ /** ++ * @white_point: White Point of Colorspace Data. ++ * These are coded as unsigned 16-bit values in units of ++ * 0.00002, where 0x0000 represents zero and 0xC350 ++ * represents 1.0000. ++ * @white_point.x: X cordinate of whitepoint of color primary. ++ * @white_point.y: Y cordinate of whitepoint of color primary. ++ */ ++ struct { ++ __u16 x, y; ++ } white_point; ++ /** ++ * @max_display_mastering_luminance: Max Mastering Display Luminance. ++ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, ++ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. ++ */ ++ __u16 max_display_mastering_luminance; ++ /** ++ * @min_display_mastering_luminance: Min Mastering Display Luminance. ++ * This value is coded as an unsigned 16-bit value in units of ++ * 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF ++ * represents 6.5535 cd/m2. ++ */ ++ __u16 min_display_mastering_luminance; ++ /** ++ * @max_cll: Max Content Light Level. ++ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, ++ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. ++ */ ++ __u16 max_cll; ++ /** ++ * @max_fall: Max Frame Average Light Level. ++ * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, ++ * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. ++ */ ++ __u16 max_fall; ++}; ++ ++/** ++ * struct hdr_output_metadata - HDR output metadata ++ * ++ * Metadata Information to be passed from userspace ++ */ ++struct hdr_output_metadata { ++ /** ++ * @metadata_type: Static_Metadata_Descriptor_ID. ++ */ ++ __u32 metadata_type; ++ /** ++ * @hdmi_metadata_type1: HDR Metadata Infoframe. ++ */ ++ union { ++ struct hdr_metadata_infoframe hdmi_metadata_type1; ++ }; ++}; ++ ++#define DRM_MODE_PAGE_FLIP_EVENT 0x01 ++#define DRM_MODE_PAGE_FLIP_ASYNC 0x02 ++#define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 ++#define DRM_MODE_PAGE_FLIP_TARGET_RELATIVE 0x8 ++#define DRM_MODE_PAGE_FLIP_TARGET (DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE | \ ++ DRM_MODE_PAGE_FLIP_TARGET_RELATIVE) ++#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT | \ ++ DRM_MODE_PAGE_FLIP_ASYNC | \ ++ DRM_MODE_PAGE_FLIP_TARGET) ++ ++/* ++ * Request a page flip on the specified crtc. ++ * ++ * This ioctl will ask KMS to schedule a page flip for the specified ++ * crtc. Once any pending rendering targeting the specified fb (as of ++ * ioctl time) has completed, the crtc will be reprogrammed to display ++ * that fb after the next vertical refresh. The ioctl returns ++ * immediately, but subsequent rendering to the current fb will block ++ * in the execbuffer ioctl until the page flip happens. If a page ++ * flip is already pending as the ioctl is called, EBUSY will be ++ * returned. ++ * ++ * Flag DRM_MODE_PAGE_FLIP_EVENT requests that drm sends back a vblank ++ * event (see drm.h: struct drm_event_vblank) when the page flip is ++ * done. The user_data field passed in with this ioctl will be ++ * returned as the user_data field in the vblank event struct. ++ * ++ * Flag DRM_MODE_PAGE_FLIP_ASYNC requests that the flip happen ++ * 'as soon as possible', meaning that it not delay waiting for vblank. ++ * This may cause tearing on the screen. ++ * ++ * The reserved field must be zero. ++ */ ++ ++struct drm_mode_crtc_page_flip { ++ __u32 crtc_id; ++ __u32 fb_id; ++ __u32 flags; ++ __u32 reserved; ++ __u64 user_data; ++}; ++ ++/* ++ * Request a page flip on the specified crtc. ++ * ++ * Same as struct drm_mode_crtc_page_flip, but supports new flags and ++ * re-purposes the reserved field: ++ * ++ * The sequence field must be zero unless either of the ++ * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is specified. When ++ * the ABSOLUTE flag is specified, the sequence field denotes the absolute ++ * vblank sequence when the flip should take effect. When the RELATIVE ++ * flag is specified, the sequence field denotes the relative (to the ++ * current one when the ioctl is called) vblank sequence when the flip ++ * should take effect. NOTE: DRM_IOCTL_WAIT_VBLANK must still be used to ++ * make sure the vblank sequence before the target one has passed before ++ * calling this ioctl. The purpose of the ++ * DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags is merely to clarify ++ * the target for when code dealing with a page flip runs during a ++ * vertical blank period. ++ */ ++ ++struct drm_mode_crtc_page_flip_target { ++ __u32 crtc_id; ++ __u32 fb_id; ++ __u32 flags; ++ __u32 sequence; ++ __u64 user_data; ++}; ++ ++/* create a dumb scanout buffer */ ++struct drm_mode_create_dumb { ++ __u32 height; ++ __u32 width; ++ __u32 bpp; ++ __u32 flags; ++ /* handle, pitch, size will be returned */ ++ __u32 handle; ++ __u32 pitch; ++ __u64 size; ++}; ++ ++/* set up for mmap of a dumb scanout buffer */ ++struct drm_mode_map_dumb { ++ /** Handle for the object being mapped. */ ++ __u32 handle; ++ __u32 pad; ++ /** ++ * Fake offset to use for subsequent mmap call ++ * ++ * This is a fixed-size type for 32/64 compatibility. ++ */ ++ __u64 offset; ++}; ++ ++struct drm_mode_destroy_dumb { ++ __u32 handle; ++}; ++ ++/* page-flip flags are valid, plus: */ ++#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 ++#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 ++#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 ++ ++#define DRM_MODE_ATOMIC_FLAGS (\ ++ DRM_MODE_PAGE_FLIP_EVENT |\ ++ DRM_MODE_PAGE_FLIP_ASYNC |\ ++ DRM_MODE_ATOMIC_TEST_ONLY |\ ++ DRM_MODE_ATOMIC_NONBLOCK |\ ++ DRM_MODE_ATOMIC_ALLOW_MODESET) ++ ++struct drm_mode_atomic { ++ __u32 flags; ++ __u32 count_objs; ++ __u64 objs_ptr; ++ __u64 count_props_ptr; ++ __u64 props_ptr; ++ __u64 prop_values_ptr; ++ __u64 reserved; ++ __u64 user_data; ++}; ++ ++struct drm_format_modifier_blob { ++#define FORMAT_BLOB_CURRENT 1 ++ /* Version of this blob format */ ++ __u32 version; ++ ++ /* Flags */ ++ __u32 flags; ++ ++ /* Number of fourcc formats supported */ ++ __u32 count_formats; ++ ++ /* Where in this blob the formats exist (in bytes) */ ++ __u32 formats_offset; ++ ++ /* Number of drm_format_modifiers */ ++ __u32 count_modifiers; ++ ++ /* Where in this blob the modifiers exist (in bytes) */ ++ __u32 modifiers_offset; ++ ++ /* __u32 formats[] */ ++ /* struct drm_format_modifier modifiers[] */ ++}; ++ ++struct drm_format_modifier { ++ /* Bitmask of formats in get_plane format list this info applies to. The ++ * offset allows a sliding window of which 64 formats (bits). ++ * ++ * Some examples: ++ * In today's world with < 65 formats, and formats 0, and 2 are ++ * supported ++ * 0x0000000000000005 ++ * ^-offset = 0, formats = 5 ++ * ++ * If the number formats grew to 128, and formats 98-102 are ++ * supported with the modifier: ++ * ++ * 0x0000007c00000000 0000000000000000 ++ * ^ ++ * |__offset = 64, formats = 0x7c00000000 ++ * ++ */ ++ __u64 formats; ++ __u32 offset; ++ __u32 pad; ++ ++ /* The modifier that applies to the >get_plane format list bitmask. */ ++ __u64 modifier; ++}; ++ ++/** ++ * struct drm_mode_create_blob - Create New blob property ++ * ++ * Create a new 'blob' data property, copying length bytes from data pointer, ++ * and returning new blob ID. ++ */ ++struct drm_mode_create_blob { ++ /** @data: Pointer to data to copy. */ ++ __u64 data; ++ /** @length: Length of data to copy. */ ++ __u32 length; ++ /** @blob_id: Return: new property ID. */ ++ __u32 blob_id; ++}; ++ ++/** ++ * struct drm_mode_destroy_blob - Destroy user blob ++ * @blob_id: blob_id to destroy ++ * ++ * Destroy a user-created blob property. ++ * ++ * User-space can release blobs as soon as they do not need to refer to them by ++ * their blob object ID. For instance, if you are using a MODE_ID blob in an ++ * atomic commit and you will not make another commit re-using the same ID, you ++ * can destroy the blob as soon as the commit has been issued, without waiting ++ * for it to complete. ++ */ ++struct drm_mode_destroy_blob { ++ __u32 blob_id; ++}; ++ ++/** ++ * struct drm_mode_create_lease - Create lease ++ * ++ * Lease mode resources, creating another drm_master. ++ * ++ * The @object_ids array must reference at least one CRTC, one connector and ++ * one plane if &DRM_CLIENT_CAP_UNIVERSAL_PLANES is enabled. Alternatively, ++ * the lease can be completely empty. ++ */ ++struct drm_mode_create_lease { ++ /** @object_ids: Pointer to array of object ids (__u32) */ ++ __u64 object_ids; ++ /** @object_count: Number of object ids */ ++ __u32 object_count; ++ /** @flags: flags for new FD (O_CLOEXEC, etc) */ ++ __u32 flags; ++ ++ /** @lessee_id: Return: unique identifier for lessee. */ ++ __u32 lessee_id; ++ /** @fd: Return: file descriptor to new drm_master file */ ++ __u32 fd; ++}; ++ ++/** ++ * struct drm_mode_list_lessees - List lessees ++ * ++ * List lesses from a drm_master. ++ */ ++struct drm_mode_list_lessees { ++ /** ++ * @count_lessees: Number of lessees. ++ * ++ * On input, provides length of the array. ++ * On output, provides total number. No ++ * more than the input number will be written ++ * back, so two calls can be used to get ++ * the size and then the data. ++ */ ++ __u32 count_lessees; ++ /** @pad: Padding. */ ++ __u32 pad; ++ ++ /** ++ * @lessees_ptr: Pointer to lessees. ++ * ++ * Pointer to __u64 array of lessee ids ++ */ ++ __u64 lessees_ptr; ++}; ++ ++/** ++ * struct drm_mode_get_lease - Get Lease ++ * ++ * Get leased objects. ++ */ ++struct drm_mode_get_lease { ++ /** ++ * @count_objects: Number of leased objects. ++ * ++ * On input, provides length of the array. ++ * On output, provides total number. No ++ * more than the input number will be written ++ * back, so two calls can be used to get ++ * the size and then the data. ++ */ ++ __u32 count_objects; ++ /** @pad: Padding. */ ++ __u32 pad; ++ ++ /** ++ * @objects_ptr: Pointer to objects. ++ * ++ * Pointer to __u32 array of object ids. ++ */ ++ __u64 objects_ptr; ++}; ++ ++/** ++ * struct drm_mode_revoke_lease - Revoke lease ++ */ ++struct drm_mode_revoke_lease { ++ /** @lessee_id: Unique ID of lessee */ ++ __u32 lessee_id; ++}; ++ ++/** ++ * struct drm_mode_rect - Two dimensional rectangle. ++ * @x1: Horizontal starting coordinate (inclusive). ++ * @y1: Vertical starting coordinate (inclusive). ++ * @x2: Horizontal ending coordinate (exclusive). ++ * @y2: Vertical ending coordinate (exclusive). ++ * ++ * With drm subsystem using struct drm_rect to manage rectangular area this ++ * export it to user-space. ++ * ++ * Currently used by drm_mode_atomic blob property FB_DAMAGE_CLIPS. ++ */ ++struct drm_mode_rect { ++ __s32 x1; ++ __s32 y1; ++ __s32 x2; ++ __s32 y2; ++}; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif +diff -up firefox-103.0/third_party/drm/drm/xf86drm.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/drm/xf86drm.h +--- firefox-103.0/third_party/drm/drm/xf86drm.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/drm/drm/xf86drm.h 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,966 @@ ++/** ++ * \file xf86drm.h ++ * OS-independent header for DRM user-level library interface. ++ * ++ * \author Rickard E. (Rik) Faith ++ */ ++ ++/* ++ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. ++ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. ++ * All Rights Reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ */ ++ ++#ifndef _XF86DRM_H_ ++#define _XF86DRM_H_ ++ ++#include ++#include ++#include ++#include ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#ifndef DRM_MAX_MINOR ++#define DRM_MAX_MINOR 16 ++#endif ++ ++#if defined(__linux__) ++ ++#define DRM_IOCTL_NR(n) _IOC_NR(n) ++#define DRM_IOC_VOID _IOC_NONE ++#define DRM_IOC_READ _IOC_READ ++#define DRM_IOC_WRITE _IOC_WRITE ++#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE ++#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) ++ ++#else /* One of the *BSDs */ ++ ++#include ++#define DRM_IOCTL_NR(n) ((n) & 0xff) ++#define DRM_IOC_VOID IOC_VOID ++#define DRM_IOC_READ IOC_OUT ++#define DRM_IOC_WRITE IOC_IN ++#define DRM_IOC_READWRITE IOC_INOUT ++#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) ++ ++#endif ++ ++ /* Defaults, if nothing set in xf86config */ ++#define DRM_DEV_UID 0 ++#define DRM_DEV_GID 0 ++/* Default /dev/dri directory permissions 0755 */ ++#define DRM_DEV_DIRMODE \ ++ (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) ++#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) ++ ++#ifdef __OpenBSD__ ++#define DRM_DIR_NAME "/dev" ++#define DRM_PRIMARY_MINOR_NAME "drm" ++#define DRM_CONTROL_MINOR_NAME "drmC" ++#define DRM_RENDER_MINOR_NAME "drmR" ++#else ++#define DRM_DIR_NAME "/dev/dri" ++#define DRM_PRIMARY_MINOR_NAME "card" ++#define DRM_CONTROL_MINOR_NAME "controlD" ++#define DRM_RENDER_MINOR_NAME "renderD" ++#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ ++#endif ++ ++#define DRM_DEV_NAME "%s/" DRM_PRIMARY_MINOR_NAME "%d" ++#define DRM_CONTROL_DEV_NAME "%s/" DRM_CONTROL_MINOR_NAME "%d" ++#define DRM_RENDER_DEV_NAME "%s/" DRM_RENDER_MINOR_NAME "%d" ++ ++#define DRM_NODE_NAME_MAX \ ++ (sizeof(DRM_DIR_NAME) + 1 /* slash */ \ ++ + MAX3(sizeof(DRM_PRIMARY_MINOR_NAME), \ ++ sizeof(DRM_CONTROL_MINOR_NAME), \ ++ sizeof(DRM_RENDER_MINOR_NAME)) \ ++ + sizeof("144") /* highest possible node number */ \ ++ + 1) /* NULL-terminator */ ++ ++#define DRM_ERR_NO_DEVICE (-1001) ++#define DRM_ERR_NO_ACCESS (-1002) ++#define DRM_ERR_NOT_ROOT (-1003) ++#define DRM_ERR_INVALID (-1004) ++#define DRM_ERR_NO_FD (-1005) ++ ++#define DRM_AGP_NO_HANDLE 0 ++ ++typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ ++typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ ++ ++#if (__GNUC__ >= 3) ++#define DRM_PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) ++#else ++#define DRM_PRINTFLIKE(f, a) ++#endif ++ ++typedef struct _drmServerInfo { ++ int (*debug_print)(const char *format, va_list ap) DRM_PRINTFLIKE(1,0); ++ int (*load_module)(const char *name); ++ void (*get_perms)(gid_t *, mode_t *); ++} drmServerInfo, *drmServerInfoPtr; ++ ++typedef struct drmHashEntry { ++ int fd; ++ void (*f)(int, void *, void *); ++ void *tagTable; ++} drmHashEntry; ++ ++extern int drmIoctl(int fd, unsigned long request, void *arg); ++extern void *drmGetHashTable(void); ++extern drmHashEntry *drmGetEntry(int fd); ++ ++/** ++ * Driver version information. ++ * ++ * \sa drmGetVersion() and drmSetVersion(). ++ */ ++typedef struct _drmVersion { ++ int version_major; /**< Major version */ ++ int version_minor; /**< Minor version */ ++ int version_patchlevel; /**< Patch level */ ++ int name_len; /**< Length of name buffer */ ++ char *name; /**< Name of driver */ ++ int date_len; /**< Length of date buffer */ ++ char *date; /**< User-space buffer to hold date */ ++ int desc_len; /**< Length of desc buffer */ ++ char *desc; /**< User-space buffer to hold desc */ ++} drmVersion, *drmVersionPtr; ++ ++typedef struct _drmStats { ++ unsigned long count; /**< Number of data */ ++ struct { ++ unsigned long value; /**< Value from kernel */ ++ const char *long_format; /**< Suggested format for long_name */ ++ const char *long_name; /**< Long name for value */ ++ const char *rate_format; /**< Suggested format for rate_name */ ++ const char *rate_name; /**< Short name for value per second */ ++ int isvalue; /**< True if value (vs. counter) */ ++ const char *mult_names; /**< Multiplier names (e.g., "KGM") */ ++ int mult; /**< Multiplier value (e.g., 1024) */ ++ int verbose; /**< Suggest only in verbose output */ ++ } data[15]; ++} drmStatsT; ++ ++ ++ /* All of these enums *MUST* match with the ++ kernel implementation -- so do *NOT* ++ change them! (The drmlib implementation ++ will just copy the flags instead of ++ translating them.) */ ++typedef enum { ++ DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ ++ DRM_REGISTERS = 1, /**< no caching, no core dump */ ++ DRM_SHM = 2, /**< shared, cached */ ++ DRM_AGP = 3, /**< AGP/GART */ ++ DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */ ++ DRM_CONSISTENT = 5 /**< PCI consistent */ ++} drmMapType; ++ ++typedef enum { ++ DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ ++ DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ ++ DRM_LOCKED = 0x0004, /**< Physical pages locked */ ++ DRM_KERNEL = 0x0008, /**< Kernel requires access */ ++ DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ ++ DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ ++ DRM_REMOVABLE = 0x0040 /**< Removable mapping */ ++} drmMapFlags; ++ ++/** ++ * \warning These values *MUST* match drm.h ++ */ ++typedef enum { ++ /** \name Flags for DMA buffer dispatch */ ++ /*@{*/ ++ DRM_DMA_BLOCK = 0x01, /**< ++ * Block until buffer dispatched. ++ * ++ * \note the buffer may not yet have been ++ * processed by the hardware -- getting a ++ * hardware lock with the hardware quiescent ++ * will ensure that the buffer has been ++ * processed. ++ */ ++ DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ ++ DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ ++ /*@}*/ ++ ++ /** \name Flags for DMA buffer request */ ++ /*@{*/ ++ DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ ++ DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ ++ DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ ++ /*@}*/ ++} drmDMAFlags; ++ ++typedef enum { ++ DRM_PAGE_ALIGN = 0x01, ++ DRM_AGP_BUFFER = 0x02, ++ DRM_SG_BUFFER = 0x04, ++ DRM_FB_BUFFER = 0x08, ++ DRM_PCI_BUFFER_RO = 0x10 ++} drmBufDescFlags; ++ ++typedef enum { ++ DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ ++ DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ ++ DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ ++ DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ ++ /* These *HALT* flags aren't supported yet ++ -- they will be used to support the ++ full-screen DGA-like mode. */ ++ DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ ++ DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ ++} drmLockFlags; ++ ++typedef enum { ++ DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and ++ never swapped. */ ++ DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ ++} drm_context_tFlags, *drm_context_tFlagsPtr; ++ ++typedef struct _drmBufDesc { ++ int count; /**< Number of buffers of this size */ ++ int size; /**< Size in bytes */ ++ int low_mark; /**< Low water mark */ ++ int high_mark; /**< High water mark */ ++} drmBufDesc, *drmBufDescPtr; ++ ++typedef struct _drmBufInfo { ++ int count; /**< Number of buffers described in list */ ++ drmBufDescPtr list; /**< List of buffer descriptions */ ++} drmBufInfo, *drmBufInfoPtr; ++ ++typedef struct _drmBuf { ++ int idx; /**< Index into the master buffer list */ ++ int total; /**< Buffer size */ ++ int used; /**< Amount of buffer in use (for DMA) */ ++ drmAddress address; /**< Address */ ++} drmBuf, *drmBufPtr; ++ ++/** ++ * Buffer mapping information. ++ * ++ * Used by drmMapBufs() and drmUnmapBufs() to store information about the ++ * mapped buffers. ++ */ ++typedef struct _drmBufMap { ++ int count; /**< Number of buffers mapped */ ++ drmBufPtr list; /**< Buffers */ ++} drmBufMap, *drmBufMapPtr; ++ ++typedef struct _drmLock { ++ volatile unsigned int lock; ++ char padding[60]; ++ /* This is big enough for most current (and future?) architectures: ++ DEC Alpha: 32 bytes ++ Intel Merced: ? ++ Intel P5/PPro/PII/PIII: 32 bytes ++ Intel StrongARM: 32 bytes ++ Intel i386/i486: 16 bytes ++ MIPS: 32 bytes (?) ++ Motorola 68k: 16 bytes ++ Motorola PowerPC: 32 bytes ++ Sun SPARC: 32 bytes ++ */ ++} drmLock, *drmLockPtr; ++ ++/** ++ * Indices here refer to the offset into ++ * list in drmBufInfo ++ */ ++typedef struct _drmDMAReq { ++ drm_context_t context; /**< Context handle */ ++ int send_count; /**< Number of buffers to send */ ++ int *send_list; /**< List of handles to buffers */ ++ int *send_sizes; /**< Lengths of data to send, in bytes */ ++ drmDMAFlags flags; /**< Flags */ ++ int request_count; /**< Number of buffers requested */ ++ int request_size; /**< Desired size of buffers requested */ ++ int *request_list; /**< Buffer information */ ++ int *request_sizes; /**< Minimum acceptable sizes */ ++ int granted_count; /**< Number of buffers granted at this size */ ++} drmDMAReq, *drmDMAReqPtr; ++ ++typedef struct _drmRegion { ++ drm_handle_t handle; ++ unsigned int offset; ++ drmSize size; ++ drmAddress map; ++} drmRegion, *drmRegionPtr; ++ ++typedef struct _drmTextureRegion { ++ unsigned char next; ++ unsigned char prev; ++ unsigned char in_use; ++ unsigned char padding; /**< Explicitly pad this out */ ++ unsigned int age; ++} drmTextureRegion, *drmTextureRegionPtr; ++ ++ ++typedef enum { ++ DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ ++ DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ ++ /* bits 1-6 are reserved for high crtcs */ ++ DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e, ++ DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ ++ DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ ++ DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ ++ DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ ++ DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ ++} drmVBlankSeqType; ++#define DRM_VBLANK_HIGH_CRTC_SHIFT 1 ++ ++typedef struct _drmVBlankReq { ++ drmVBlankSeqType type; ++ unsigned int sequence; ++ unsigned long signal; ++} drmVBlankReq, *drmVBlankReqPtr; ++ ++typedef struct _drmVBlankReply { ++ drmVBlankSeqType type; ++ unsigned int sequence; ++ long tval_sec; ++ long tval_usec; ++} drmVBlankReply, *drmVBlankReplyPtr; ++ ++typedef union _drmVBlank { ++ drmVBlankReq request; ++ drmVBlankReply reply; ++} drmVBlank, *drmVBlankPtr; ++ ++typedef struct _drmSetVersion { ++ int drm_di_major; ++ int drm_di_minor; ++ int drm_dd_major; ++ int drm_dd_minor; ++} drmSetVersion, *drmSetVersionPtr; ++ ++#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) ++ ++#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ ++#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ ++ ++#if defined(__GNUC__) && (__GNUC__ >= 2) ++# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__) ++ /* Reflect changes here to drmP.h */ ++#define DRM_CAS(lock,old,new,__ret) \ ++ do { \ ++ int __dummy; /* Can't mark eax as clobbered */ \ ++ __asm__ __volatile__( \ ++ "lock ; cmpxchg %4,%1\n\t" \ ++ "setnz %0" \ ++ : "=d" (__ret), \ ++ "=m" (__drm_dummy_lock(lock)), \ ++ "=a" (__dummy) \ ++ : "2" (old), \ ++ "r" (new)); \ ++ } while (0) ++ ++#elif defined(__alpha__) ++ ++#define DRM_CAS(lock, old, new, ret) \ ++ do { \ ++ int tmp, old32; \ ++ __asm__ __volatile__( \ ++ " addl $31, %5, %3\n" \ ++ "1: ldl_l %0, %2\n" \ ++ " cmpeq %0, %3, %1\n" \ ++ " beq %1, 2f\n" \ ++ " mov %4, %0\n" \ ++ " stl_c %0, %2\n" \ ++ " beq %0, 3f\n" \ ++ " mb\n" \ ++ "2: cmpeq %1, 0, %1\n" \ ++ ".subsection 2\n" \ ++ "3: br 1b\n" \ ++ ".previous" \ ++ : "=&r"(tmp), "=&r"(ret), \ ++ "=m"(__drm_dummy_lock(lock)), \ ++ "=&r"(old32) \ ++ : "r"(new), "r"(old) \ ++ : "memory"); \ ++ } while (0) ++ ++#elif defined(__sparc__) ++ ++#define DRM_CAS(lock,old,new,__ret) \ ++do { register unsigned int __old __asm("o0"); \ ++ register unsigned int __new __asm("o1"); \ ++ register volatile unsigned int *__lock __asm("o2"); \ ++ __old = old; \ ++ __new = new; \ ++ __lock = (volatile unsigned int *)lock; \ ++ __asm__ __volatile__( \ ++ /*"cas [%2], %3, %0"*/ \ ++ ".word 0xd3e29008\n\t" \ ++ /*"membar #StoreStore | #StoreLoad"*/ \ ++ ".word 0x8143e00a" \ ++ : "=&r" (__new) \ ++ : "0" (__new), \ ++ "r" (__lock), \ ++ "r" (__old) \ ++ : "memory"); \ ++ __ret = (__new != __old); \ ++} while(0) ++ ++#elif defined(__ia64__) ++ ++#ifdef __INTEL_COMPILER ++/* this currently generates bad code (missing stop bits)... */ ++#include ++ ++#define DRM_CAS(lock,old,new,__ret) \ ++ do { \ ++ unsigned long __result, __old = (old) & 0xffffffff; \ ++ __mf(); \ ++ __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ ++ __ret = (__result) != (__old); \ ++/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ ++ (old), (new)) \ ++ != (old)); */\ ++ } while (0) ++ ++#else ++#define DRM_CAS(lock,old,new,__ret) \ ++ do { \ ++ unsigned int __result, __old = (old); \ ++ __asm__ __volatile__( \ ++ "mf\n" \ ++ "mov ar.ccv=%2\n" \ ++ ";;\n" \ ++ "cmpxchg4.acq %0=%1,%3,ar.ccv" \ ++ : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ ++ : "r" ((unsigned long)__old), "r" (new) \ ++ : "memory"); \ ++ __ret = (__result) != (__old); \ ++ } while (0) ++ ++#endif ++ ++#elif defined(__powerpc__) ++ ++#define DRM_CAS(lock,old,new,__ret) \ ++ do { \ ++ __asm__ __volatile__( \ ++ "sync;" \ ++ "0: lwarx %0,0,%1;" \ ++ " xor. %0,%3,%0;" \ ++ " bne 1f;" \ ++ " stwcx. %2,0,%1;" \ ++ " bne- 0b;" \ ++ "1: " \ ++ "sync;" \ ++ : "=&r"(__ret) \ ++ : "r"(lock), "r"(new), "r"(old) \ ++ : "cr0", "memory"); \ ++ } while (0) ++ ++# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ ++ || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ ++ || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \ ++ || defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ ++ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ ++ || defined(__ARM_ARCH_7EM__) ++ /* excluding ARMv4/ARMv5 and lower (lacking ldrex/strex support) */ ++ #undef DRM_DEV_MODE ++ #define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) ++ ++ #define DRM_CAS(lock,old,new,__ret) \ ++ do { \ ++ __asm__ __volatile__ ( \ ++ "1: ldrex %0, [%1]\n" \ ++ " teq %0, %2\n" \ ++ " ite eq\n" \ ++ " strexeq %0, %3, [%1]\n" \ ++ " movne %0, #1\n" \ ++ : "=&r" (__ret) \ ++ : "r" (lock), "r" (old), "r" (new) \ ++ : "cc","memory"); \ ++ } while (0) ++ ++#endif /* architecture */ ++#endif /* __GNUC__ >= 2 */ ++ ++#ifndef DRM_CAS ++#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ ++#endif ++ ++#if defined(__alpha__) ++#define DRM_CAS_RESULT(_result) long _result ++#elif defined(__powerpc__) ++#define DRM_CAS_RESULT(_result) int _result ++#else ++#define DRM_CAS_RESULT(_result) char _result ++#endif ++ ++#define DRM_LIGHT_LOCK(fd,lock,context) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ ++ if (__ret) drmGetLock(fd,context,0); \ ++ } while(0) ++ ++ /* This one counts fast locks -- for ++ benchmarking only. */ ++#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ ++ if (__ret) drmGetLock(fd,context,0); \ ++ else ++count; \ ++ } while(0) ++ ++#define DRM_LOCK(fd,lock,context,flags) \ ++ do { \ ++ if (flags) drmGetLock(fd,context,flags); \ ++ else DRM_LIGHT_LOCK(fd,lock,context); \ ++ } while(0) ++ ++#define DRM_UNLOCK(fd,lock,context) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ ++ if (__ret) drmUnlock(fd,context); \ ++ } while(0) ++ ++ /* Simple spin locks */ ++#define DRM_SPINLOCK(spin,val) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ do { \ ++ DRM_CAS(spin,0,val,__ret); \ ++ if (__ret) while ((spin)->lock); \ ++ } while (__ret); \ ++ } while(0) ++ ++#define DRM_SPINLOCK_TAKE(spin,val) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ int cur; \ ++ do { \ ++ cur = (*spin).lock; \ ++ DRM_CAS(spin,cur,val,__ret); \ ++ } while (__ret); \ ++ } while(0) ++ ++#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ ++ do { \ ++ int __i; \ ++ __ret = 1; \ ++ for (__i = 0; __ret && __i < count; __i++) { \ ++ DRM_CAS(spin,0,val,__ret); \ ++ if (__ret) for (;__i < count && (spin)->lock; __i++); \ ++ } \ ++ } while(0) ++ ++#define DRM_SPINUNLOCK(spin,val) \ ++ do { \ ++ DRM_CAS_RESULT(__ret); \ ++ if ((*spin).lock == val) { /* else server stole lock */ \ ++ do { \ ++ DRM_CAS(spin,val,0,__ret); \ ++ } while (__ret); \ ++ } \ ++ } while(0) ++ ++ ++ ++/* General user-level programmer's API: unprivileged */ ++extern int drmAvailable(void); ++extern int drmOpen(const char *name, const char *busid); ++ ++#define DRM_NODE_PRIMARY 0 ++#define DRM_NODE_CONTROL 1 ++#define DRM_NODE_RENDER 2 ++#define DRM_NODE_MAX 3 ++ ++extern int drmOpenWithType(const char *name, const char *busid, ++ int type); ++ ++extern int drmOpenControl(int minor); ++extern int drmOpenRender(int minor); ++extern int drmClose(int fd); ++extern drmVersionPtr drmGetVersion(int fd); ++extern drmVersionPtr drmGetLibVersion(int fd); ++extern int drmGetCap(int fd, uint64_t capability, uint64_t *value); ++extern void drmFreeVersion(drmVersionPtr); ++extern int drmGetMagic(int fd, drm_magic_t * magic); ++extern char *drmGetBusid(int fd); ++extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, ++ int funcnum); ++extern int drmGetMap(int fd, int idx, drm_handle_t *offset, ++ drmSize *size, drmMapType *type, ++ drmMapFlags *flags, drm_handle_t *handle, ++ int *mtrr); ++extern int drmGetClient(int fd, int idx, int *auth, int *pid, ++ int *uid, unsigned long *magic, ++ unsigned long *iocs); ++extern int drmGetStats(int fd, drmStatsT *stats); ++extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); ++extern int drmCommandNone(int fd, unsigned long drmCommandIndex); ++extern int drmCommandRead(int fd, unsigned long drmCommandIndex, ++ void *data, unsigned long size); ++extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, ++ void *data, unsigned long size); ++extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, ++ void *data, unsigned long size); ++ ++/* General user-level programmer's API: X server (root) only */ ++extern void drmFreeBusid(const char *busid); ++extern int drmSetBusid(int fd, const char *busid); ++extern int drmAuthMagic(int fd, drm_magic_t magic); ++extern int drmAddMap(int fd, ++ drm_handle_t offset, ++ drmSize size, ++ drmMapType type, ++ drmMapFlags flags, ++ drm_handle_t * handle); ++extern int drmRmMap(int fd, drm_handle_t handle); ++extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, ++ drm_handle_t handle); ++ ++extern int drmAddBufs(int fd, int count, int size, ++ drmBufDescFlags flags, ++ int agp_offset); ++extern int drmMarkBufs(int fd, double low, double high); ++extern int drmCreateContext(int fd, drm_context_t * handle); ++extern int drmSetContextFlags(int fd, drm_context_t context, ++ drm_context_tFlags flags); ++extern int drmGetContextFlags(int fd, drm_context_t context, ++ drm_context_tFlagsPtr flags); ++extern int drmAddContextTag(int fd, drm_context_t context, void *tag); ++extern int drmDelContextTag(int fd, drm_context_t context); ++extern void *drmGetContextTag(int fd, drm_context_t context); ++extern drm_context_t * drmGetReservedContextList(int fd, int *count); ++extern void drmFreeReservedContextList(drm_context_t *); ++extern int drmSwitchToContext(int fd, drm_context_t context); ++extern int drmDestroyContext(int fd, drm_context_t handle); ++extern int drmCreateDrawable(int fd, drm_drawable_t * handle); ++extern int drmDestroyDrawable(int fd, drm_drawable_t handle); ++extern int drmUpdateDrawableInfo(int fd, drm_drawable_t handle, ++ drm_drawable_info_type_t type, ++ unsigned int num, void *data); ++extern int drmCtlInstHandler(int fd, int irq); ++extern int drmCtlUninstHandler(int fd); ++extern int drmSetClientCap(int fd, uint64_t capability, ++ uint64_t value); ++ ++extern int drmCrtcGetSequence(int fd, uint32_t crtcId, ++ uint64_t *sequence, uint64_t *ns); ++extern int drmCrtcQueueSequence(int fd, uint32_t crtcId, ++ uint32_t flags, uint64_t sequence, ++ uint64_t *sequence_queued, ++ uint64_t user_data); ++/* General user-level programmer's API: authenticated client and/or X */ ++extern int drmMap(int fd, ++ drm_handle_t handle, ++ drmSize size, ++ drmAddressPtr address); ++extern int drmUnmap(drmAddress address, drmSize size); ++extern drmBufInfoPtr drmGetBufInfo(int fd); ++extern drmBufMapPtr drmMapBufs(int fd); ++extern int drmUnmapBufs(drmBufMapPtr bufs); ++extern int drmDMA(int fd, drmDMAReqPtr request); ++extern int drmFreeBufs(int fd, int count, int *list); ++extern int drmGetLock(int fd, ++ drm_context_t context, ++ drmLockFlags flags); ++extern int drmUnlock(int fd, drm_context_t context); ++extern int drmFinish(int fd, int context, drmLockFlags flags); ++extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, ++ drm_handle_t * handle); ++ ++/* AGP/GART support: X server (root) only */ ++extern int drmAgpAcquire(int fd); ++extern int drmAgpRelease(int fd); ++extern int drmAgpEnable(int fd, unsigned long mode); ++extern int drmAgpAlloc(int fd, unsigned long size, ++ unsigned long type, unsigned long *address, ++ drm_handle_t *handle); ++extern int drmAgpFree(int fd, drm_handle_t handle); ++extern int drmAgpBind(int fd, drm_handle_t handle, ++ unsigned long offset); ++extern int drmAgpUnbind(int fd, drm_handle_t handle); ++ ++/* AGP/GART info: authenticated client and/or X */ ++extern int drmAgpVersionMajor(int fd); ++extern int drmAgpVersionMinor(int fd); ++extern unsigned long drmAgpGetMode(int fd); ++extern unsigned long drmAgpBase(int fd); /* Physical location */ ++extern unsigned long drmAgpSize(int fd); /* Bytes */ ++extern unsigned long drmAgpMemoryUsed(int fd); ++extern unsigned long drmAgpMemoryAvail(int fd); ++extern unsigned int drmAgpVendorId(int fd); ++extern unsigned int drmAgpDeviceId(int fd); ++ ++/* PCI scatter/gather support: X server (root) only */ ++extern int drmScatterGatherAlloc(int fd, unsigned long size, ++ drm_handle_t *handle); ++extern int drmScatterGatherFree(int fd, drm_handle_t handle); ++ ++extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); ++ ++/* Support routines */ ++extern void drmSetServerInfo(drmServerInfoPtr info); ++extern int drmError(int err, const char *label); ++extern void *drmMalloc(int size); ++extern void drmFree(void *pt); ++ ++/* Hash table routines */ ++extern void *drmHashCreate(void); ++extern int drmHashDestroy(void *t); ++extern int drmHashLookup(void *t, unsigned long key, void **value); ++extern int drmHashInsert(void *t, unsigned long key, void *value); ++extern int drmHashDelete(void *t, unsigned long key); ++extern int drmHashFirst(void *t, unsigned long *key, void **value); ++extern int drmHashNext(void *t, unsigned long *key, void **value); ++ ++/* PRNG routines */ ++extern void *drmRandomCreate(unsigned long seed); ++extern int drmRandomDestroy(void *state); ++extern unsigned long drmRandom(void *state); ++extern double drmRandomDouble(void *state); ++ ++/* Skip list routines */ ++ ++extern void *drmSLCreate(void); ++extern int drmSLDestroy(void *l); ++extern int drmSLLookup(void *l, unsigned long key, void **value); ++extern int drmSLInsert(void *l, unsigned long key, void *value); ++extern int drmSLDelete(void *l, unsigned long key); ++extern int drmSLNext(void *l, unsigned long *key, void **value); ++extern int drmSLFirst(void *l, unsigned long *key, void **value); ++extern void drmSLDump(void *l); ++extern int drmSLLookupNeighbors(void *l, unsigned long key, ++ unsigned long *prev_key, void **prev_value, ++ unsigned long *next_key, void **next_value); ++ ++extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); ++extern int drmOpenOnceWithType(const char *BusID, int *newlyopened, int type); ++extern void drmCloseOnce(int fd); ++extern void drmMsg(const char *format, ...) DRM_PRINTFLIKE(1, 2); ++ ++extern int drmSetMaster(int fd); ++extern int drmDropMaster(int fd); ++extern int drmIsMaster(int fd); ++ ++#define DRM_EVENT_CONTEXT_VERSION 4 ++ ++typedef struct _drmEventContext { ++ ++ /* This struct is versioned so we can add more pointers if we ++ * add more events. */ ++ int version; ++ ++ void (*vblank_handler)(int fd, ++ unsigned int sequence, ++ unsigned int tv_sec, ++ unsigned int tv_usec, ++ void *user_data); ++ ++ void (*page_flip_handler)(int fd, ++ unsigned int sequence, ++ unsigned int tv_sec, ++ unsigned int tv_usec, ++ void *user_data); ++ ++ void (*page_flip_handler2)(int fd, ++ unsigned int sequence, ++ unsigned int tv_sec, ++ unsigned int tv_usec, ++ unsigned int crtc_id, ++ void *user_data); ++ ++ void (*sequence_handler)(int fd, ++ uint64_t sequence, ++ uint64_t ns, ++ uint64_t user_data); ++} drmEventContext, *drmEventContextPtr; ++ ++extern int drmHandleEvent(int fd, drmEventContextPtr evctx); ++ ++extern char *drmGetDeviceNameFromFd(int fd); ++ ++/* Improved version of drmGetDeviceNameFromFd which attributes for any type of ++ * device/node - card, control or renderD. ++ */ ++extern char *drmGetDeviceNameFromFd2(int fd); ++extern int drmGetNodeTypeFromFd(int fd); ++ ++/* Convert between GEM handles and DMA-BUF file descriptors. ++ * ++ * Warning: since GEM handles are not reference-counted and are unique per ++ * DRM file description, the caller is expected to perform its own reference ++ * counting. drmPrimeFDToHandle is guaranteed to return the same handle for ++ * different FDs if they reference the same underlying buffer object. This ++ * could even be a buffer object originally created on the same DRM FD. ++ * ++ * When sharing a DRM FD with an API such as EGL or GBM, the caller must not ++ * use drmPrimeHandleToFD nor drmPrimeFDToHandle. A single user-space ++ * reference-counting implementation is necessary to avoid double-closing GEM ++ * handles. ++ * ++ * Two processes can't share the same DRM FD and both use it to create or ++ * import GEM handles, even when using a single user-space reference-counting ++ * implementation like GBM, because GBM doesn't share its state between ++ * processes. ++ */ ++extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd); ++extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle); ++ ++extern int drmCloseBufferHandle(int fd, uint32_t handle); ++ ++extern char *drmGetPrimaryDeviceNameFromFd(int fd); ++extern char *drmGetRenderDeviceNameFromFd(int fd); ++ ++#define DRM_BUS_PCI 0 ++#define DRM_BUS_USB 1 ++#define DRM_BUS_PLATFORM 2 ++#define DRM_BUS_HOST1X 3 ++ ++typedef struct _drmPciBusInfo { ++ uint16_t domain; ++ uint8_t bus; ++ uint8_t dev; ++ uint8_t func; ++} drmPciBusInfo, *drmPciBusInfoPtr; ++ ++typedef struct _drmPciDeviceInfo { ++ uint16_t vendor_id; ++ uint16_t device_id; ++ uint16_t subvendor_id; ++ uint16_t subdevice_id; ++ uint8_t revision_id; ++} drmPciDeviceInfo, *drmPciDeviceInfoPtr; ++ ++typedef struct _drmUsbBusInfo { ++ uint8_t bus; ++ uint8_t dev; ++} drmUsbBusInfo, *drmUsbBusInfoPtr; ++ ++typedef struct _drmUsbDeviceInfo { ++ uint16_t vendor; ++ uint16_t product; ++} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr; ++ ++#define DRM_PLATFORM_DEVICE_NAME_LEN 512 ++ ++typedef struct _drmPlatformBusInfo { ++ char fullname[DRM_PLATFORM_DEVICE_NAME_LEN]; ++} drmPlatformBusInfo, *drmPlatformBusInfoPtr; ++ ++typedef struct _drmPlatformDeviceInfo { ++ char **compatible; /* NULL terminated list of compatible strings */ ++} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr; ++ ++#define DRM_HOST1X_DEVICE_NAME_LEN 512 ++ ++typedef struct _drmHost1xBusInfo { ++ char fullname[DRM_HOST1X_DEVICE_NAME_LEN]; ++} drmHost1xBusInfo, *drmHost1xBusInfoPtr; ++ ++typedef struct _drmHost1xDeviceInfo { ++ char **compatible; /* NULL terminated list of compatible strings */ ++} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; ++ ++typedef struct _drmDevice { ++ char **nodes; /* DRM_NODE_MAX sized array */ ++ int available_nodes; /* DRM_NODE_* bitmask */ ++ int bustype; ++ union { ++ drmPciBusInfoPtr pci; ++ drmUsbBusInfoPtr usb; ++ drmPlatformBusInfoPtr platform; ++ drmHost1xBusInfoPtr host1x; ++ } businfo; ++ union { ++ drmPciDeviceInfoPtr pci; ++ drmUsbDeviceInfoPtr usb; ++ drmPlatformDeviceInfoPtr platform; ++ drmHost1xDeviceInfoPtr host1x; ++ } deviceinfo; ++} drmDevice, *drmDevicePtr; ++ ++extern int drmGetDevice(int fd, drmDevicePtr *device); ++extern void drmFreeDevice(drmDevicePtr *device); ++ ++extern int drmGetDevices(drmDevicePtr devices[], int max_devices); ++extern void drmFreeDevices(drmDevicePtr devices[], int count); ++ ++#define DRM_DEVICE_GET_PCI_REVISION (1 << 0) ++extern int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device); ++extern int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); ++ ++extern int drmGetDeviceFromDevId(dev_t dev_id, uint32_t flags, drmDevicePtr *device); ++ ++extern int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b); ++ ++extern int drmSyncobjCreate(int fd, uint32_t flags, uint32_t *handle); ++extern int drmSyncobjDestroy(int fd, uint32_t handle); ++extern int drmSyncobjHandleToFD(int fd, uint32_t handle, int *obj_fd); ++extern int drmSyncobjFDToHandle(int fd, int obj_fd, uint32_t *handle); ++ ++extern int drmSyncobjImportSyncFile(int fd, uint32_t handle, int sync_file_fd); ++extern int drmSyncobjExportSyncFile(int fd, uint32_t handle, int *sync_file_fd); ++extern int drmSyncobjWait(int fd, uint32_t *handles, unsigned num_handles, ++ int64_t timeout_nsec, unsigned flags, ++ uint32_t *first_signaled); ++extern int drmSyncobjReset(int fd, const uint32_t *handles, uint32_t handle_count); ++extern int drmSyncobjSignal(int fd, const uint32_t *handles, uint32_t handle_count); ++extern int drmSyncobjTimelineSignal(int fd, const uint32_t *handles, ++ uint64_t *points, uint32_t handle_count); ++extern int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points, ++ unsigned num_handles, ++ int64_t timeout_nsec, unsigned flags, ++ uint32_t *first_signaled); ++extern int drmSyncobjQuery(int fd, uint32_t *handles, uint64_t *points, ++ uint32_t handle_count); ++extern int drmSyncobjQuery2(int fd, uint32_t *handles, uint64_t *points, ++ uint32_t handle_count, uint32_t flags); ++extern int drmSyncobjTransfer(int fd, ++ uint32_t dst_handle, uint64_t dst_point, ++ uint32_t src_handle, uint64_t src_point, ++ uint32_t flags); ++ ++extern char * ++drmGetFormatModifierVendor(uint64_t modifier); ++ ++extern char * ++drmGetFormatModifierName(uint64_t modifier); ++ ++#ifndef fourcc_mod_get_vendor ++#define fourcc_mod_get_vendor(modifier) \ ++ (((modifier) >> 56) & 0xff) ++#endif ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif +diff -up firefox-103.0/third_party/drm/libdrm/moz.build.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/libdrm/moz.build +--- firefox-103.0/third_party/drm/libdrm/moz.build.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/drm/libdrm/moz.build 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,16 @@ ++# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- ++# vim: set filetype=python: ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++SOURCES += [ ++ 'mozdrm.cpp', ++] ++ ++if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": ++ CXXFLAGS += CONFIG['MOZ_GTK3_CFLAGS'] ++ ++LOCAL_INCLUDES += ['/third_party/drm'] ++ ++FINAL_LIBRARY = 'xul' +diff -up firefox-103.0/third_party/drm/libdrm/mozdrm.cpp.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/libdrm/mozdrm.cpp +--- firefox-103.0/third_party/drm/libdrm/mozdrm.cpp.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/drm/libdrm/mozdrm.cpp 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,66 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "mozilla/Types.h" ++#include "prlink.h" ++ ++#include ++ ++#define GET_FUNC(func, lib) \ ++ func##_fn = \ ++ (decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \ ++ ++#define IS_FUNC_LOADED(func) \ ++ (func != nullptr) \ ++ ++static int (*drmGetDevices2_fn)(uint32_t flags, drmDevicePtr devices[], int max_devices); ++static void (*drmFreeDevices_fn)(drmDevicePtr devices[], int count); ++ ++bool IsDRMLibraryLoaded() { ++ static bool isLoaded = ++ (IS_FUNC_LOADED(drmGetDevices2_fn) && ++ IS_FUNC_LOADED(drmFreeDevices_fn)); ++ ++ return isLoaded; ++} ++ ++bool LoadDRMLibrary() { ++ static PRLibrary* drmLib = nullptr; ++ static bool drmInitialized = false; ++ ++ //TODO Thread safe ++ if (!drmInitialized) { ++ drmInitialized = true; ++ drmLib = PR_LoadLibrary("libdrm.so.2"); ++ if (!drmLib) { ++ return false; ++ } ++ ++ GET_FUNC(drmGetDevices2, drmLib); ++ GET_FUNC(drmFreeDevices, drmLib); ++ } ++ ++ return IsDRMLibraryLoaded(); ++} ++ ++int ++drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices) ++{ ++ if (!LoadDRMLibrary()) { ++ return 0; ++ } ++ return drmGetDevices2_fn(flags, devices, max_devices); ++} ++ ++void ++drmFreeDevices(drmDevicePtr devices[], int count) ++{ ++ if (!LoadDRMLibrary()) { ++ return; ++ } ++ return drmFreeDevices_fn(devices, count); ++} +diff -up firefox-103.0/third_party/drm/README.libwebrtc-screen-cast-sync firefox-103.0/third_party/drm/README +--- firefox-103.0/third_party/drm/README.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/drm/README 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,4 @@ ++Libdrm is a drm library wrapper needed to build and run Firefox with ++Pipewire support on Linux (https://gitlab.freedesktop.org/mesa/drm). ++ ++libdrm directory stores headers of libdrm needed for build only. +diff -up firefox-103.0/third_party/gbm/gbm/gbm.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/gbm/gbm/gbm.h +--- firefox-103.0/third_party/gbm/gbm/gbm.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/gbm/gbm/gbm.h 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,452 @@ ++/* ++ * Copyright © 2011 Intel Corporation ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: ++ * Benjamin Franzke ++ */ ++ ++#ifndef _GBM_H_ ++#define _GBM_H_ ++ ++#define __GBM__ 1 ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++/** ++ * \file gbm.h ++ * \brief Generic Buffer Manager ++ */ ++ ++struct gbm_device; ++struct gbm_bo; ++struct gbm_surface; ++ ++/** ++ * \mainpage The Generic Buffer Manager ++ * ++ * This module provides an abstraction that the caller can use to request a ++ * buffer from the underlying memory management system for the platform. ++ * ++ * This allows the creation of portable code whilst still allowing access to ++ * the underlying memory manager. ++ */ ++ ++/** ++ * Abstraction representing the handle to a buffer allocated by the ++ * manager ++ */ ++union gbm_bo_handle { ++ void *ptr; ++ int32_t s32; ++ uint32_t u32; ++ int64_t s64; ++ uint64_t u64; ++}; ++ ++/** Format of the allocated buffer */ ++enum gbm_bo_format { ++ /** RGB with 8 bits per channel in a 32 bit value */ ++ GBM_BO_FORMAT_XRGB8888, ++ /** ARGB with 8 bits per channel in a 32 bit value */ ++ GBM_BO_FORMAT_ARGB8888 ++}; ++ ++ ++/** ++ * The FourCC format codes are taken from the drm_fourcc.h definition, and ++ * re-namespaced. New GBM formats must not be added, unless they are ++ * identical ports from drm_fourcc. ++ */ ++#define __gbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ ++ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) ++ ++#define GBM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */ ++ ++/* color index */ ++#define GBM_FORMAT_C8 __gbm_fourcc_code('C', '8', ' ', ' ') /* [7:0] C */ ++ ++/* 8 bpp Red */ ++#define GBM_FORMAT_R8 __gbm_fourcc_code('R', '8', ' ', ' ') /* [7:0] R */ ++ ++/* 16 bpp Red */ ++#define GBM_FORMAT_R16 __gbm_fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */ ++ ++/* 16 bpp RG */ ++#define GBM_FORMAT_GR88 __gbm_fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */ ++ ++/* 8 bpp RGB */ ++#define GBM_FORMAT_RGB332 __gbm_fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ ++#define GBM_FORMAT_BGR233 __gbm_fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ ++ ++/* 16 bpp RGB */ ++#define GBM_FORMAT_XRGB4444 __gbm_fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */ ++#define GBM_FORMAT_XBGR4444 __gbm_fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */ ++#define GBM_FORMAT_RGBX4444 __gbm_fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */ ++#define GBM_FORMAT_BGRX4444 __gbm_fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */ ++ ++#define GBM_FORMAT_ARGB4444 __gbm_fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */ ++#define GBM_FORMAT_ABGR4444 __gbm_fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */ ++#define GBM_FORMAT_RGBA4444 __gbm_fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */ ++#define GBM_FORMAT_BGRA4444 __gbm_fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */ ++ ++#define GBM_FORMAT_XRGB1555 __gbm_fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */ ++#define GBM_FORMAT_XBGR1555 __gbm_fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */ ++#define GBM_FORMAT_RGBX5551 __gbm_fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */ ++#define GBM_FORMAT_BGRX5551 __gbm_fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */ ++ ++#define GBM_FORMAT_ARGB1555 __gbm_fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */ ++#define GBM_FORMAT_ABGR1555 __gbm_fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */ ++#define GBM_FORMAT_RGBA5551 __gbm_fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */ ++#define GBM_FORMAT_BGRA5551 __gbm_fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */ ++ ++#define GBM_FORMAT_RGB565 __gbm_fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ ++#define GBM_FORMAT_BGR565 __gbm_fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */ ++ ++/* 24 bpp RGB */ ++#define GBM_FORMAT_RGB888 __gbm_fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */ ++#define GBM_FORMAT_BGR888 __gbm_fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */ ++ ++/* 32 bpp RGB */ ++#define GBM_FORMAT_XRGB8888 __gbm_fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ ++#define GBM_FORMAT_XBGR8888 __gbm_fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */ ++#define GBM_FORMAT_RGBX8888 __gbm_fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */ ++#define GBM_FORMAT_BGRX8888 __gbm_fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */ ++ ++#define GBM_FORMAT_ARGB8888 __gbm_fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */ ++#define GBM_FORMAT_ABGR8888 __gbm_fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */ ++#define GBM_FORMAT_RGBA8888 __gbm_fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */ ++#define GBM_FORMAT_BGRA8888 __gbm_fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */ ++ ++#define GBM_FORMAT_XRGB2101010 __gbm_fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */ ++#define GBM_FORMAT_XBGR2101010 __gbm_fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */ ++#define GBM_FORMAT_RGBX1010102 __gbm_fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */ ++#define GBM_FORMAT_BGRX1010102 __gbm_fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */ ++ ++#define GBM_FORMAT_ARGB2101010 __gbm_fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */ ++#define GBM_FORMAT_ABGR2101010 __gbm_fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */ ++#define GBM_FORMAT_RGBA1010102 __gbm_fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */ ++#define GBM_FORMAT_BGRA1010102 __gbm_fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ ++ ++/* ++ * Floating point 64bpp RGB ++ * IEEE 754-2008 binary16 half-precision float ++ * [15:0] sign:exponent:mantissa 1:5:10 ++ */ ++#define GBM_FORMAT_XBGR16161616F __gbm_fourcc_code('X', 'B', '4', 'H') /* [63:0] x:B:G:R 16:16:16:16 little endian */ ++ ++#define GBM_FORMAT_ABGR16161616F __gbm_fourcc_code('A', 'B', '4', 'H') /* [63:0] A:B:G:R 16:16:16:16 little endian */ ++ ++/* packed YCbCr */ ++#define GBM_FORMAT_YUYV __gbm_fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ ++#define GBM_FORMAT_YVYU __gbm_fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */ ++#define GBM_FORMAT_UYVY __gbm_fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ ++#define GBM_FORMAT_VYUY __gbm_fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */ ++ ++#define GBM_FORMAT_AYUV __gbm_fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */ ++ ++/* ++ * 2 plane YCbCr ++ * index 0 = Y plane, [7:0] Y ++ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian ++ * or ++ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian ++ */ ++#define GBM_FORMAT_NV12 __gbm_fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */ ++#define GBM_FORMAT_NV21 __gbm_fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */ ++#define GBM_FORMAT_NV16 __gbm_fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */ ++#define GBM_FORMAT_NV61 __gbm_fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */ ++ ++/* ++ * 3 plane YCbCr ++ * index 0: Y plane, [7:0] Y ++ * index 1: Cb plane, [7:0] Cb ++ * index 2: Cr plane, [7:0] Cr ++ * or ++ * index 1: Cr plane, [7:0] Cr ++ * index 2: Cb plane, [7:0] Cb ++ */ ++#define GBM_FORMAT_YUV410 __gbm_fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */ ++#define GBM_FORMAT_YVU410 __gbm_fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */ ++#define GBM_FORMAT_YUV411 __gbm_fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */ ++#define GBM_FORMAT_YVU411 __gbm_fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */ ++#define GBM_FORMAT_YUV420 __gbm_fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */ ++#define GBM_FORMAT_YVU420 __gbm_fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */ ++#define GBM_FORMAT_YUV422 __gbm_fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */ ++#define GBM_FORMAT_YVU422 __gbm_fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */ ++#define GBM_FORMAT_YUV444 __gbm_fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */ ++#define GBM_FORMAT_YVU444 __gbm_fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */ ++ ++struct gbm_format_name_desc { ++ char name[5]; ++}; ++ ++/** ++ * Flags to indicate the intended use for the buffer - these are passed into ++ * gbm_bo_create(). The caller must set the union of all the flags that are ++ * appropriate ++ * ++ * \sa Use gbm_device_is_format_supported() to check if the combination of format ++ * and use flags are supported ++ */ ++enum gbm_bo_flags { ++ /** ++ * Buffer is going to be presented to the screen using an API such as KMS ++ */ ++ GBM_BO_USE_SCANOUT = (1 << 0), ++ /** ++ * Buffer is going to be used as cursor ++ */ ++ GBM_BO_USE_CURSOR = (1 << 1), ++ /** ++ * Deprecated ++ */ ++ GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR, ++ /** ++ * Buffer is to be used for rendering - for example it is going to be used ++ * as the storage for a color buffer ++ */ ++ GBM_BO_USE_RENDERING = (1 << 2), ++ /** ++ * Buffer can be used for gbm_bo_write. This is guaranteed to work ++ * with GBM_BO_USE_CURSOR, but may not work for other combinations. ++ */ ++ GBM_BO_USE_WRITE = (1 << 3), ++ /** ++ * Buffer is linear, i.e. not tiled. ++ */ ++ GBM_BO_USE_LINEAR = (1 << 4), ++ /** ++ * Buffer is protected, i.e. encrypted and not readable by CPU or any ++ * other non-secure / non-trusted components nor by non-trusted OpenGL, ++ * OpenCL, and Vulkan applications. ++ */ ++ GBM_BO_USE_PROTECTED = (1 << 5), ++}; ++ ++int ++gbm_device_get_fd(struct gbm_device *gbm); ++ ++const char * ++gbm_device_get_backend_name(struct gbm_device *gbm); ++ ++int ++gbm_device_is_format_supported(struct gbm_device *gbm, ++ uint32_t format, uint32_t flags); ++ ++int ++gbm_device_get_format_modifier_plane_count(struct gbm_device *gbm, ++ uint32_t format, ++ uint64_t modifier); ++ ++void ++gbm_device_destroy(struct gbm_device *gbm); ++ ++struct gbm_device * ++gbm_create_device(int fd); ++ ++struct gbm_bo * ++gbm_bo_create(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, uint32_t flags); ++ ++struct gbm_bo * ++gbm_bo_create_with_modifiers(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, ++ const uint64_t *modifiers, ++ const unsigned int count); ++ ++struct gbm_bo * ++gbm_bo_create_with_modifiers2(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, ++ const uint64_t *modifiers, ++ const unsigned int count, ++ uint32_t flags); ++ ++#define GBM_BO_IMPORT_WL_BUFFER 0x5501 ++#define GBM_BO_IMPORT_EGL_IMAGE 0x5502 ++#define GBM_BO_IMPORT_FD 0x5503 ++#define GBM_BO_IMPORT_FD_MODIFIER 0x5504 ++ ++struct gbm_import_fd_data { ++ int fd; ++ uint32_t width; ++ uint32_t height; ++ uint32_t stride; ++ uint32_t format; ++}; ++ ++#define GBM_MAX_PLANES 4 ++ ++struct gbm_import_fd_modifier_data { ++ uint32_t width; ++ uint32_t height; ++ uint32_t format; ++ uint32_t num_fds; ++ int fds[GBM_MAX_PLANES]; ++ int strides[GBM_MAX_PLANES]; ++ int offsets[GBM_MAX_PLANES]; ++ uint64_t modifier; ++}; ++ ++struct gbm_bo * ++gbm_bo_import(struct gbm_device *gbm, uint32_t type, ++ void *buffer, uint32_t flags); ++ ++/** ++ * Flags to indicate the type of mapping for the buffer - these are ++ * passed into gbm_bo_map(). The caller must set the union of all the ++ * flags that are appropriate. ++ * ++ * These flags are independent of the GBM_BO_USE_* creation flags. However, ++ * mapping the buffer may require copying to/from a staging buffer. ++ * ++ * See also: pipe_map_flags ++ */ ++enum gbm_bo_transfer_flags { ++ /** ++ * Buffer contents read back (or accessed directly) at transfer ++ * create time. ++ */ ++ GBM_BO_TRANSFER_READ = (1 << 0), ++ /** ++ * Buffer contents will be written back at unmap time ++ * (or modified as a result of being accessed directly). ++ */ ++ GBM_BO_TRANSFER_WRITE = (1 << 1), ++ /** ++ * Read/modify/write ++ */ ++ GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE), ++}; ++ ++void * ++gbm_bo_map(struct gbm_bo *bo, ++ uint32_t x, uint32_t y, uint32_t width, uint32_t height, ++ uint32_t flags, uint32_t *stride, void **map_data); ++ ++void ++gbm_bo_unmap(struct gbm_bo *bo, void *map_data); ++ ++uint32_t ++gbm_bo_get_width(struct gbm_bo *bo); ++ ++uint32_t ++gbm_bo_get_height(struct gbm_bo *bo); ++ ++uint32_t ++gbm_bo_get_stride(struct gbm_bo *bo); ++ ++uint32_t ++gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane); ++ ++uint32_t ++gbm_bo_get_format(struct gbm_bo *bo); ++ ++uint32_t ++gbm_bo_get_bpp(struct gbm_bo *bo); ++ ++uint32_t ++gbm_bo_get_offset(struct gbm_bo *bo, int plane); ++ ++struct gbm_device * ++gbm_bo_get_device(struct gbm_bo *bo); ++ ++union gbm_bo_handle ++gbm_bo_get_handle(struct gbm_bo *bo); ++ ++int ++gbm_bo_get_fd(struct gbm_bo *bo); ++ ++uint64_t ++gbm_bo_get_modifier(struct gbm_bo *bo); ++ ++int ++gbm_bo_get_plane_count(struct gbm_bo *bo); ++ ++union gbm_bo_handle ++gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane); ++ ++int ++gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane); ++ ++int ++gbm_bo_write(struct gbm_bo *bo, const void *buf, size_t count); ++ ++void ++gbm_bo_set_user_data(struct gbm_bo *bo, void *data, ++ void (*destroy_user_data)(struct gbm_bo *, void *)); ++ ++void * ++gbm_bo_get_user_data(struct gbm_bo *bo); ++ ++void ++gbm_bo_destroy(struct gbm_bo *bo); ++ ++struct gbm_surface * ++gbm_surface_create(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, uint32_t flags); ++ ++struct gbm_surface * ++gbm_surface_create_with_modifiers(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, ++ const uint64_t *modifiers, ++ const unsigned int count); ++ ++struct gbm_surface * ++gbm_surface_create_with_modifiers2(struct gbm_device *gbm, ++ uint32_t width, uint32_t height, ++ uint32_t format, ++ const uint64_t *modifiers, ++ const unsigned int count, ++ uint32_t flags); ++ ++struct gbm_bo * ++gbm_surface_lock_front_buffer(struct gbm_surface *surface); ++ ++void ++gbm_surface_release_buffer(struct gbm_surface *surface, struct gbm_bo *bo); ++ ++int ++gbm_surface_has_free_buffers(struct gbm_surface *surface); ++ ++void ++gbm_surface_destroy(struct gbm_surface *surface); ++ ++char * ++gbm_format_get_name(uint32_t gbm_format, struct gbm_format_name_desc *desc); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff -up firefox-103.0/third_party/gbm/libgbm/moz.build.libwebrtc-screen-cast-sync firefox-103.0/third_party/gbm/libgbm/moz.build +--- firefox-103.0/third_party/gbm/libgbm/moz.build.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/gbm/libgbm/moz.build 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,16 @@ ++# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- ++# vim: set filetype=python: ++# This Source Code Form is subject to the terms of the Mozilla Public ++# License, v. 2.0. If a copy of the MPL was not distributed with this ++# file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++SOURCES += [ ++ 'mozgbm.cpp', ++] ++ ++if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": ++ CXXFLAGS += CONFIG['MOZ_GTK3_CFLAGS'] ++ ++LOCAL_INCLUDES += ['/third_party/gbm'] ++ ++FINAL_LIBRARY = 'xul' +diff -up firefox-103.0/third_party/gbm/libgbm/mozgbm.cpp.libwebrtc-screen-cast-sync firefox-103.0/third_party/gbm/libgbm/mozgbm.cpp +--- firefox-103.0/third_party/gbm/libgbm/mozgbm.cpp.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/gbm/libgbm/mozgbm.cpp 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,66 @@ ++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "mozilla/Types.h" ++#include "prlink.h" ++ ++#include ++ ++#define GET_FUNC(func, lib) \ ++ func##_fn = \ ++ (decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \ ++ ++#define IS_FUNC_LOADED(func) \ ++ (func != nullptr) \ ++ ++static struct gbm_device * (*gbm_create_device_fn)(int fd); ++static void (*gbm_device_destroy_fn)(struct gbm_device* gbm); ++ ++bool IsGBMLibraryLoaded() { ++ static bool isLoaded = ++ (IS_FUNC_LOADED(gbm_create_device_fn) && ++ IS_FUNC_LOADED(gbm_device_destroy_fn)); ++ ++ return isLoaded; ++} ++ ++bool LoadGBMLibrary() { ++ static PRLibrary* gbmLib = nullptr; ++ static bool gbmInitialized = false; ++ ++ //TODO Thread safe ++ if (!gbmInitialized) { ++ gbmInitialized = true; ++ gbmLib = PR_LoadLibrary("libgbm.so.1"); ++ if (!gbmLib) { ++ return false; ++ } ++ ++ GET_FUNC(gbm_create_device, gbmLib); ++ GET_FUNC(gbm_device_destroy, gbmLib); ++ } ++ ++ return IsGBMLibraryLoaded(); ++} ++ ++struct gbm_device * ++gbm_create_device(int fd) ++{ ++ if (!LoadGBMLibrary()) { ++ return nullptr; ++ } ++ return gbm_create_device_fn(fd); ++} ++ ++void ++gbm_device_destroy(struct gbm_device* gbm) ++{ ++ if (!LoadGBMLibrary()) { ++ return; ++ } ++ return gbm_device_destroy_fn(gbm); ++} +diff -up firefox-103.0/third_party/gbm/README.libwebrtc-screen-cast-sync firefox-103.0/third_party/gbm/README +--- firefox-103.0/third_party/gbm/README.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.318409017 +0200 ++++ firefox-103.0/third_party/gbm/README 2022-07-28 11:45:30.318409017 +0200 +@@ -0,0 +1,4 @@ ++Libgbm is a gbm library wrapper needed to build and run Firefox with ++Pipewire support on Linux (https://gitlab.freedesktop.org/mesa/gbm). ++ ++libgbm directory stores headers of libgbm needed for build only. +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build 2022-07-29 11:28:39.473827919 +0200 +@@ -26,6 +26,8 @@ LOCAL_INCLUDES += [ + "/ipc/chromium/src", + "/media/libyuv/", + "/media/libyuv/libyuv/include/", ++ "/third_party/drm/", ++ "/third_party/gbm/", + "/third_party/libwebrtc/", + "/third_party/libwebrtc/third_party/abseil-cpp/", + "/third_party/pipewire/", +@@ -133,15 +135,18 @@ if CONFIG["OS_TARGET"] == "OpenBSD": + ] + + SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc" ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + + UNIFIED_SOURCES += [ + "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_x11.cc", +- "/third_party/libwebrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", + "/third_party/libwebrtc/modules/desktop_capture/linux/screen_capturer_x11.cc", + "/third_party/libwebrtc/modules/desktop_capture/linux/shared_x_display.cc", +- "/third_party/libwebrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc", + "/third_party/libwebrtc/modules/desktop_capture/linux/window_capturer_x11.cc", + "/third_party/libwebrtc/modules/desktop_capture/linux/window_finder_x11.cc", + "/third_party/libwebrtc/modules/desktop_capture/linux/window_list_utils.cc", +@@ -241,7 +246,12 @@ if CONFIG["CPU_ARCH"] == "arm": + DEFINES["_GNU_SOURCE"] = True + + SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc" ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + + UNIFIED_SOURCES += [ +@@ -300,12 +310,12 @@ if CONFIG["CPU_ARCH"] == "aarch64" and C + DEFINES["_GNU_SOURCE"] = True + + SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc" +- ] +- +- UNIFIED_SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", +- "/third_party/libwebrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + + if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux": +@@ -318,12 +328,12 @@ if CONFIG["CPU_ARCH"] == "x86" and CONFI + DEFINES["_GNU_SOURCE"] = True + + SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc" +- ] +- +- UNIFIED_SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", +- "/third_party/libwebrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + + if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux": +@@ -332,12 +342,26 @@ if CONFIG["CPU_ARCH"] == "x86_64" and CO + DEFINES["_GNU_SOURCE"] = True + + SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc" ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + +- UNIFIED_SOURCES += [ +- "/third_party/libwebrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", +- "/third_party/libwebrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" ++if CONFIG["CPU_ARCH"] == "ppc64le" and CONFIG["OS_TARGET"] == "Linux": ++ ++ DEFINES["WEBRTC_USE_PIPEWIRE"] = True ++ DEFINES["_GNU_SOURCE"] = True ++ ++ SOURCES += [ ++ "/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc", ++ "/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc" + ] + + if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux": +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.cc.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.cc 2022-07-28 11:45:30.318409017 +0200 +@@ -14,6 +14,9 @@ + #elif defined(WEBRTC_WIN) + #include "modules/desktop_capture/win/full_screen_win_application_handler.h" + #endif ++#if defined(WEBRTC_USE_PIPEWIRE) ++#include "modules/desktop_capture/linux/shared_screencast_stream.h" ++#endif + + namespace webrtc { + +@@ -35,6 +38,9 @@ DesktopCaptureOptions DesktopCaptureOpti + #if defined(WEBRTC_USE_X11) + result.set_x_display(SharedXDisplay::CreateDefault()); + #endif ++#if defined(WEBRTC_USE_PIPEWIRE) ++ result.set_screencast_stream(SharedScreenCastStream::CreateDefault()); ++#endif + #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) + result.set_configuration_monitor(new DesktopConfigurationMonitor()); + result.set_full_screen_window_detector( +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.h.libwebrtc-screen-cast-sync 2022-07-18 20:44:32.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/desktop_capture_options.h 2022-07-28 11:45:30.319409011 +0200 +@@ -17,6 +17,10 @@ + #include "modules/desktop_capture/linux/shared_x_display.h" + #endif + ++#if defined(WEBRTC_USE_PIPEWIRE) ++#include "modules/desktop_capture/linux/shared_screencast_stream.h" ++#endif ++ + #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) + #include "modules/desktop_capture/mac/desktop_configuration_monitor.h" + #endif +@@ -149,13 +153,26 @@ class RTC_EXPORT DesktopCaptureOptions { + #if defined(WEBRTC_USE_PIPEWIRE) + bool allow_pipewire() const { return allow_pipewire_; } + void set_allow_pipewire(bool allow) { allow_pipewire_ = allow; } ++ ++ const rtc::scoped_refptr& screencast_stream() const { ++ return screencast_stream_; ++ } ++ void set_screencast_stream( ++ rtc::scoped_refptr stream) { ++ screencast_stream_ = stream; ++ } + #endif + + private: + #if defined(WEBRTC_USE_X11) + rtc::scoped_refptr x_display_; + #endif +- ++#if defined(WEBRTC_USE_PIPEWIRE) ++ // An instance of shared PipeWire ScreenCast stream we share between ++ // BaseCapturerPipeWire and MouseCursorMonitorPipeWire as cursor information ++ // is sent together with screen content. ++ rtc::scoped_refptr screencast_stream_; ++#endif + #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) + rtc::scoped_refptr configuration_monitor_; + bool allow_iosurface_ = false; +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc.libwebrtc-screen-cast-sync 2022-07-18 20:44:26.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc 2022-07-28 11:45:30.319409011 +0200 +@@ -10,937 +10,67 @@ + + #include "modules/desktop_capture/linux/base_capturer_pipewire.h" + +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "absl/memory/memory.h" + #include "modules/desktop_capture/desktop_capture_options.h" + #include "modules/desktop_capture/desktop_capturer.h" + #include "rtc_base/checks.h" + #include "rtc_base/logging.h" + +-#if defined(WEBRTC_DLOPEN_PIPEWIRE) +-#include "modules/desktop_capture/linux/pipewire_stubs.h" +- +-using modules_desktop_capture_linux::InitializeStubs; +-using modules_desktop_capture_linux::kModulePipewire; +-using modules_desktop_capture_linux::StubPathMap; +-#endif // defined(WEBRTC_DLOPEN_PIPEWIRE) +- + namespace webrtc { + +-const char kDesktopBusName[] = "org.freedesktop.portal.Desktop"; +-const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; +-const char kDesktopRequestObjectPath[] = +- "/org/freedesktop/portal/desktop/request"; +-const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; +-const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; +-const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; +- +-const int kBytesPerPixel = 4; +- +-#if defined(WEBRTC_DLOPEN_PIPEWIRE) +-const char kPipeWireLib[] = "libpipewire-0.2.so.1"; +-#endif +- +-// static +-struct dma_buf_sync { +- uint64_t flags; +-}; +-#define DMA_BUF_SYNC_READ (1 << 0) +-#define DMA_BUF_SYNC_START (0 << 2) +-#define DMA_BUF_SYNC_END (1 << 2) +-#define DMA_BUF_BASE 'b' +-#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) +- +-static void SyncDmaBuf(int fd, uint64_t start_or_end) { +- struct dma_buf_sync sync = { 0 }; +- +- sync.flags = start_or_end | DMA_BUF_SYNC_READ; +- +- while(true) { +- int ret; +- ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync); +- if (ret == -1 && errno == EINTR) { +- continue; +- } else if (ret == -1) { +- RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno); +- break; +- } else { +- break; +- } +- } +-} +- +-// static +-void BaseCapturerPipeWire::OnCoreError(void *data, +- uint32_t id, +- int seq, +- int res, +- const char *message) { +- RTC_LOG(LS_ERROR) << "core error: " << message; +-} +- +-// static +-void BaseCapturerPipeWire::OnStreamStateChanged(void* data, +- pw_stream_state old_state, +- pw_stream_state state, +- const char* error_message) { +- BaseCapturerPipeWire* that = static_cast(data); +- RTC_DCHECK(that); +- +- switch (state) { +- case PW_STREAM_STATE_ERROR: +- RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; +- break; +- case PW_STREAM_STATE_PAUSED: +- case PW_STREAM_STATE_STREAMING: +- case PW_STREAM_STATE_UNCONNECTED: +- case PW_STREAM_STATE_CONNECTING: +- break; +- } +-} +- +-// static +-void BaseCapturerPipeWire::OnStreamParamChanged(void *data, uint32_t id, +- const struct spa_pod *format) { +- BaseCapturerPipeWire* that = static_cast(data); +- RTC_DCHECK(that); +- +- RTC_LOG(LS_INFO) << "PipeWire stream param changed."; +- +- if (!format || id != SPA_PARAM_Format) { +- return; +- } +- +- spa_format_video_raw_parse(format, &that->spa_video_format_); +- +- auto width = that->spa_video_format_.size.width; +- auto height = that->spa_video_format_.size.height; +- // In order to be able to build in the non unified environment kBytesPerPixel +- // must be fully qualified, see Bug 1725145 +- auto stride = SPA_ROUND_UP_N(width * BasicDesktopFrame::kBytesPerPixel, 4); +- auto size = height * stride; +- +- that->desktop_size_ = DesktopSize(width, height); +- +- uint8_t buffer[1024] = {}; +- auto builder = spa_pod_builder{buffer, sizeof(buffer)}; +- +- // Setup buffers and meta header for new format. +- const struct spa_pod* params[3]; +- params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, +- SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, +- SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int((1<(spa_pod_builder_add_object(&builder, +- SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, +- SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), +- SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))); +- params[2] = reinterpret_cast(spa_pod_builder_add_object(&builder, +- SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, +- SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop), +- SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region)))); +- pw_stream_update_params(that->pw_stream_, params, 3); +-} +- +-// static +-void BaseCapturerPipeWire::OnStreamProcess(void* data) { +- BaseCapturerPipeWire* that = static_cast(data); +- RTC_DCHECK(that); +- +- struct pw_buffer *next_buffer; +- struct pw_buffer *buffer = nullptr; +- +- next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); +- while (next_buffer) { +- buffer = next_buffer; +- next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); +- +- if (next_buffer) { +- pw_stream_queue_buffer (that->pw_stream_, buffer); +- } +- } +- +- if (!buffer) { +- return; +- } +- +- that->HandleBuffer(buffer); +- +- pw_stream_queue_buffer(that->pw_stream_, buffer); +-} +- +-BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) +- : capture_source_type_(source_type) {} +- +-BaseCapturerPipeWire::~BaseCapturerPipeWire() { +- if (pw_main_loop_) { +- pw_thread_loop_stop(pw_main_loop_); +- } +- +- if (pw_stream_) { +- pw_stream_destroy(pw_stream_); +- } +- +- if (pw_core_) { +- pw_core_disconnect(pw_core_); +- } +- +- if (pw_context_) { +- pw_context_destroy(pw_context_); +- } +- +- if (pw_main_loop_) { +- pw_thread_loop_destroy(pw_main_loop_); +- } +- +- if (start_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); +- } +- if (sources_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(connection_, +- sources_request_signal_id_); +- } +- if (session_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(connection_, +- session_request_signal_id_); +- } +- +- if (session_handle_) { +- GDBusMessage* message = g_dbus_message_new_method_call( +- kDesktopBusName, session_handle_, kSessionInterfaceName, "Close"); +- if (message) { +- GError* error = nullptr; +- g_dbus_connection_send_message(connection_, message, +- G_DBUS_SEND_MESSAGE_FLAGS_NONE, +- /*out_serial=*/nullptr, &error); +- if (error) { +- RTC_LOG(LS_ERROR) << "Failed to close the session: " << error->message; +- g_error_free(error); +- } +- g_object_unref(message); +- } +- } +- +- g_free(start_handle_); +- g_free(sources_handle_); +- g_free(session_handle_); +- g_free(portal_handle_); +- +- if (cancellable_) { +- g_cancellable_cancel(cancellable_); +- g_object_unref(cancellable_); +- cancellable_ = nullptr; +- } +- +- if (proxy_) { +- g_object_unref(proxy_); +- proxy_ = nullptr; ++BaseCapturerPipeWire::BaseCapturerPipeWire(const DesktopCaptureOptions& options) ++ : options_(options) { ++ screencast_portal_ = std::make_unique( ++ ScreenCastPortal::CaptureSourceType::kAnyScreenContent, this); ++} ++ ++BaseCapturerPipeWire::~BaseCapturerPipeWire() {} ++ ++void BaseCapturerPipeWire::OnScreenCastRequestResult( ++ ScreenCastPortal::RequestResponse result, ++ uint32_t stream_node_id, ++ int fd) { ++ if (result != ScreenCastPortal::RequestResponse::kSuccess || ++ !options_.screencast_stream()->StartScreenCastStream(stream_node_id, ++ fd)) { ++ capturer_failed_ = true; ++ RTC_LOG(LS_ERROR) << "ScreenCastPortal failed: " ++ << static_cast(result); + } +- +- if (pw_fd_ != -1) { +- close(pw_fd_); +- } +-} +- +-void BaseCapturerPipeWire::InitPortal() { +- cancellable_ = g_cancellable_new(); +- g_dbus_proxy_new_for_bus( +- G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, /*info=*/nullptr, +- kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, +- cancellable_, +- reinterpret_cast(OnProxyRequested), this); +-} +- +-void BaseCapturerPipeWire::InitPipeWire() { +-#if defined(WEBRTC_DLOPEN_PIPEWIRE) +- StubPathMap paths; +- +- // Check if the PipeWire library is available. +- paths[kModulePipewire].push_back(kPipeWireLib); +- if (!InitializeStubs(paths)) { +- RTC_LOG(LS_ERROR) << "Failed to load the PipeWire library and symbols."; +- portal_init_failed_ = true; +- return; +- } +-#endif // defined(WEBRTC_DLOPEN_PIPEWIRE) +- +- pw_init(/*argc=*/nullptr, /*argc=*/nullptr); +- +- pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); +- pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); +- if (!pw_context_) { +- RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; +- return; +- } +- +- pw_core_ = pw_context_connect_fd(pw_context_, pw_fd_, nullptr, 0); +- if (!pw_core_) { +- RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; +- return; +- } +- +- // Initialize event handlers, remote end and stream-related. +- pw_core_events_.version = PW_VERSION_CORE_EVENTS; +- pw_core_events_.error = &OnCoreError; +- +- pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; +- pw_stream_events_.state_changed = &OnStreamStateChanged; +- pw_stream_events_.param_changed = &OnStreamParamChanged; +- pw_stream_events_.process = &OnStreamProcess; +- +- pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this); +- +- pw_stream_ = CreateReceivingStream(); +- if (!pw_stream_) { +- RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; +- return; +- } +- +- if (pw_thread_loop_start(pw_main_loop_) < 0) { +- RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; +- portal_init_failed_ = true; +- } +- +- RTC_LOG(LS_INFO) << "PipeWire remote opened."; +-} +- +-pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { +- spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; +- spa_rectangle pwMaxScreenBounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; +- +- auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr); +- +- if (!stream) { +- RTC_LOG(LS_ERROR) << "Could not create receiving stream."; +- return nullptr; +- } +- +- uint8_t buffer[1024] = {}; +- const spa_pod* params[2]; +- spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer)); +- +- params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, +- SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, +- SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), +- SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), +- SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA, +- SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGRA), +- SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds, +- &pwMinScreenBounds, +- &pwMaxScreenBounds), +- 0)); +- pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, this); +- +- if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, +- PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) { +- RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; +- portal_init_failed_ = true; +- } +- +- return stream; + } + +-static void SpaBufferUnmap(unsigned char *map, int map_size, bool IsDMABuf, int fd) { +- if (map) { +- if (IsDMABuf) { +- SyncDmaBuf(fd, DMA_BUF_SYNC_END); +- } +- munmap(map, map_size); ++void BaseCapturerPipeWire::OnScreenCastSessionClosed() { ++ if (!capturer_failed_) { ++ options_.screencast_stream()->StopScreenCastStream(); + } + } + +-void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { +- spa_buffer* spaBuffer = buffer->buffer; +- uint8_t *map = nullptr; +- uint8_t* src = nullptr; +- +- if (spaBuffer->datas[0].chunk->size == 0) { +- RTC_LOG(LS_ERROR) << "Failed to get video stream: Zero size."; +- return; +- } +- +- switch (spaBuffer->datas[0].type) { +- case SPA_DATA_MemFd: +- case SPA_DATA_DmaBuf: +- map = static_cast(mmap( +- nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, +- PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)); +- if (map == MAP_FAILED) { +- RTC_LOG(LS_ERROR) << "Failed to mmap memory: " << std::strerror(errno); +- return; +- } +- if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { +- SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_START); +- } +- src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t); +- break; +- case SPA_DATA_MemPtr: +- map = nullptr; +- src = static_cast(spaBuffer->datas[0].data); +- break; +- default: +- return; +- } +- +- if (!src) { +- RTC_LOG(LS_ERROR) << "Failed to get video stream: Wrong data after mmap()"; +- SpaBufferUnmap(map, +- spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, +- spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); +- return; +- } +- +- struct spa_meta_region* video_metadata = +- static_cast( +- spa_buffer_find_meta_data(spaBuffer, SPA_META_VideoCrop, sizeof(*video_metadata))); +- +- // Video size from metada is bigger than an actual video stream size. +- // The metadata are wrong or we should up-scale te video...in both cases +- // just quit now. +- if (video_metadata && +- (video_metadata->region.size.width > (uint32_t)desktop_size_.width() || +- video_metadata->region.size.height > (uint32_t)desktop_size_.height())) { +- RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; +- SpaBufferUnmap(map, +- spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, +- spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); +- return; +- } +- +- // Use video metada when video size from metadata is set and smaller than +- // video stream size, so we need to adjust it. +- video_metadata_use_ = (video_metadata && +- video_metadata->region.size.width != 0 && +- video_metadata->region.size.height != 0 && +- (video_metadata->region.size.width < (uint32_t)desktop_size_.width() || +- video_metadata->region.size.height < (uint32_t)desktop_size_.height())); +- +- DesktopSize video_size_prev = video_size_; +- if (video_metadata_use_) { +- video_size_ = DesktopSize(video_metadata->region.size.width, +- video_metadata->region.size.height); +- } else { +- video_size_ = desktop_size_; +- } +- +- webrtc::MutexLock lock(¤t_frame_lock_); +- if (!current_frame_ || !video_size_.equals(video_size_prev)) { +- current_frame_ = +- std::make_unique +- (video_size_.width() * video_size_.height() * BasicDesktopFrame::kBytesPerPixel); +- } +- +- const int32_t dstStride = video_size_.width() * BasicDesktopFrame::kBytesPerPixel; +- const int32_t srcStride = spaBuffer->datas[0].chunk->stride; +- +- // Adjust source content based on metadata video position +- if (video_metadata_use_ && +- (video_metadata->region.position.y + video_size_.height() <= desktop_size_.height())) { +- src += srcStride * video_metadata->region.position.y; +- } +- const int xOffset = +- video_metadata_use_ && +- (video_metadata->region.position.x + video_size_.width() <= desktop_size_.width()) +- ? video_metadata->region.position.x * BasicDesktopFrame::kBytesPerPixel +- : 0; +- +- uint8_t* dst = current_frame_.get(); +- for (int i = 0; i < video_size_.height(); ++i) { +- // Adjust source content based on crop video position if needed +- src += xOffset; +- std::memcpy(dst, src, dstStride); +- // If both sides decided to go with the RGBx format we need to convert it to +- // BGRx to match color format expected by WebRTC. +- if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || +- spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { +- ConvertRGBxToBGRx(dst, dstStride); +- } +- src += srcStride - xOffset; +- dst += dstStride; +- } +- +- SpaBufferUnmap(map, +- spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, +- spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); +-} +- +-void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) { +- // Change color format for KDE KWin which uses RGBx and not BGRx +- for (uint32_t i = 0; i < size; i += 4) { +- uint8_t tempR = frame[i]; +- uint8_t tempB = frame[i + 2]; +- frame[i] = tempB; +- frame[i + 2] = tempR; +- } +-} +- +-guint BaseCapturerPipeWire::SetupRequestResponseSignal( +- const gchar* object_path, +- GDBusSignalCallback callback) { +- return g_dbus_connection_signal_subscribe( +- connection_, kDesktopBusName, kRequestInterfaceName, "Response", +- object_path, /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, +- callback, this, /*user_data_free_func=*/nullptr); +-} +- +-// static +-void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/, +- GAsyncResult* result, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- GError* error = nullptr; +- GDBusProxy *proxy = g_dbus_proxy_new_finish(result, &error); +- if (!proxy) { +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- RTC_LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: " +- << error->message; +- g_error_free(error); +- that->portal_init_failed_ = true; +- return; +- } +- that->proxy_ = proxy; +- that->connection_ = g_dbus_proxy_get_connection(that->proxy_); +- +- RTC_LOG(LS_INFO) << "Created proxy for the screen cast portal."; +- that->SessionRequest(); +-} +- +-// static +-gchar* BaseCapturerPipeWire::PrepareSignalHandle(GDBusConnection* connection, +- const gchar* token) { +- gchar* sender = g_strdup(g_dbus_connection_get_unique_name(connection) + 1); +- for (int i = 0; sender[i]; i++) { +- if (sender[i] == '.') { +- sender[i] = '_'; +- } +- } +- +- gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender, "/", +- token, /*end of varargs*/ nullptr); +- g_free(sender); +- +- return handle; +-} +- +-void BaseCapturerPipeWire::SessionRequest() { +- GVariantBuilder builder; +- gchar* variant_string; +- +- g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); +- variant_string = +- g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT)); +- g_variant_builder_add(&builder, "{sv}", "session_handle_token", +- g_variant_new_string(variant_string)); +- g_free(variant_string); +- variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); +- g_variant_builder_add(&builder, "{sv}", "handle_token", +- g_variant_new_string(variant_string)); +- +- portal_handle_ = PrepareSignalHandle(connection_, variant_string); +- session_request_signal_id_ = SetupRequestResponseSignal( +- portal_handle_, OnSessionRequestResponseSignal); +- g_free(variant_string); +- +- RTC_LOG(LS_INFO) << "Screen cast session requested."; +- g_dbus_proxy_call( +- proxy_, "CreateSession", g_variant_new("(a{sv})", &builder), +- G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, +- reinterpret_cast(OnSessionRequested), this); +-} +- +-// static +-void BaseCapturerPipeWire::OnSessionRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- GError* error = nullptr; +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); +- if (!variant) { +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- RTC_LOG(LS_ERROR) << "Failed to create a screen cast session: " +- << error->message; +- g_error_free(error); +- that->portal_init_failed_ = true; +- return; +- } +- RTC_LOG(LS_INFO) << "Initializing the screen cast session."; +- +- gchar* handle = nullptr; +- g_variant_get_child(variant, 0, "o", &handle); +- g_variant_unref(variant); +- if (!handle) { +- RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; +- if (that->session_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(that->connection_, +- that->session_request_signal_id_); +- that->session_request_signal_id_ = 0; +- } +- that->portal_init_failed_ = true; +- return; +- } +- +- g_free(handle); +- +- RTC_LOG(LS_INFO) << "Subscribing to the screen cast session."; +-} +- +-// static +-void BaseCapturerPipeWire::OnSessionRequestResponseSignal( +- GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- RTC_LOG(LS_INFO) +- << "Received response for the screen cast session subscription."; +- +- guint32 portal_response; +- GVariant* response_data; +- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); +- +- GVariant* session_handle = +- g_variant_lookup_value(response_data, "session_handle", NULL); +- that->session_handle_ = g_variant_dup_string(session_handle, NULL); +- +- g_variant_unref(session_handle); +- g_variant_unref(response_data); +- +- if (!that->session_handle_ || portal_response) { +- RTC_LOG(LS_ERROR) +- << "Failed to request the screen cast session subscription."; +- that->portal_init_failed_ = true; +- return; +- } +- +- that->SourcesRequest(); +-} +- +-void BaseCapturerPipeWire::SourcesRequest() { +- GVariantBuilder builder; +- gchar* variant_string; +- +- g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); +- // We want to record monitor content. +- g_variant_builder_add(&builder, "{sv}", "types", +- g_variant_new_uint32(capture_source_type_)); +- // We don't want to allow selection of multiple sources. +- g_variant_builder_add(&builder, "{sv}", "multiple", +- g_variant_new_boolean(false)); +- variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); +- g_variant_builder_add(&builder, "{sv}", "handle_token", +- g_variant_new_string(variant_string)); +- +- sources_handle_ = PrepareSignalHandle(connection_, variant_string); +- sources_request_signal_id_ = SetupRequestResponseSignal( +- sources_handle_, OnSourcesRequestResponseSignal); +- g_free(variant_string); +- +- RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; +- g_dbus_proxy_call( +- proxy_, "SelectSources", +- g_variant_new("(oa{sv})", session_handle_, &builder), +- G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, +- reinterpret_cast(OnSourcesRequested), this); +-} +- +-// static +-void BaseCapturerPipeWire::OnSourcesRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- GError* error = nullptr; +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); +- if (!variant) { +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- RTC_LOG(LS_ERROR) << "Failed to request the sources: " << error->message; +- g_error_free(error); +- that->portal_init_failed_ = true; +- return; +- } +- +- RTC_LOG(LS_INFO) << "Sources requested from the screen cast session."; +- +- gchar* handle = nullptr; +- g_variant_get_child(variant, 0, "o", &handle); +- g_variant_unref(variant); +- if (!handle) { +- RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; +- if (that->sources_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(that->connection_, +- that->sources_request_signal_id_); +- that->sources_request_signal_id_ = 0; +- } +- that->portal_init_failed_ = true; +- return; +- } +- +- g_free(handle); +- +- RTC_LOG(LS_INFO) << "Subscribed to sources signal."; +-} +- +-// static +-void BaseCapturerPipeWire::OnSourcesRequestResponseSignal( +- GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- RTC_LOG(LS_INFO) << "Received sources signal from session."; +- +- guint32 portal_response; +- g_variant_get(parameters, "(u@a{sv})", &portal_response, nullptr); +- if (portal_response) { +- RTC_LOG(LS_ERROR) +- << "Failed to select sources for the screen cast session."; +- that->portal_init_failed_ = true; +- return; +- } +- +- that->StartRequest(); +-} +- +-void BaseCapturerPipeWire::StartRequest() { +- GVariantBuilder builder; +- gchar* variant_string; +- +- g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); +- variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); +- g_variant_builder_add(&builder, "{sv}", "handle_token", +- g_variant_new_string(variant_string)); +- +- start_handle_ = PrepareSignalHandle(connection_, variant_string); +- start_request_signal_id_ = +- SetupRequestResponseSignal(start_handle_, OnStartRequestResponseSignal); +- g_free(variant_string); +- +- // "Identifier for the application window", this is Wayland, so not "x11:...". +- const gchar parent_window[] = ""; +- +- RTC_LOG(LS_INFO) << "Starting the screen cast session."; +- g_dbus_proxy_call( +- proxy_, "Start", +- g_variant_new("(osa{sv})", session_handle_, parent_window, &builder), +- G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, +- reinterpret_cast(OnStartRequested), this); +-} +- +-// static +-void BaseCapturerPipeWire::OnStartRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- GError* error = nullptr; +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); +- if (!variant) { +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- RTC_LOG(LS_ERROR) << "Failed to start the screen cast session: " +- << error->message; +- g_error_free(error); +- that->portal_init_failed_ = true; +- return; +- } +- +- RTC_LOG(LS_INFO) << "Initializing the start of the screen cast session."; +- +- gchar* handle = nullptr; +- g_variant_get_child(variant, 0, "o", &handle); +- g_variant_unref(variant); +- if (!handle) { +- RTC_LOG(LS_ERROR) +- << "Failed to initialize the start of the screen cast session."; +- if (that->start_request_signal_id_) { +- g_dbus_connection_signal_unsubscribe(that->connection_, +- that->start_request_signal_id_); +- that->start_request_signal_id_ = 0; +- } +- that->portal_init_failed_ = true; +- return; +- } +- +- g_free(handle); +- +- RTC_LOG(LS_INFO) << "Subscribed to the start signal."; +-} +- +-// static +-void BaseCapturerPipeWire::OnStartRequestResponseSignal( +- GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- RTC_LOG(LS_INFO) << "Start signal received."; +- guint32 portal_response; +- GVariant* response_data; +- GVariantIter* iter = nullptr; +- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); +- if (portal_response || !response_data) { +- RTC_LOG(LS_ERROR) << "Failed to start the screen cast session."; +- that->portal_init_failed_ = true; +- return; +- } +- +- // Array of PipeWire streams. See +- // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml +- // documentation for . +- if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { +- GVariant* variant; +- +- while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { +- guint32 stream_id; +- GVariant* options; +- +- g_variant_get(variant, "(u@a{sv})", &stream_id, &options); +- RTC_DCHECK(options != nullptr); +- +- that->pw_stream_node_id_ = stream_id; +- g_variant_unref(options); +- g_variant_unref(variant); +- } +- } +- g_variant_iter_free(iter); +- g_variant_unref(response_data); +- +- that->OpenPipeWireRemote(); +-} +- +-void BaseCapturerPipeWire::OpenPipeWireRemote() { +- GVariantBuilder builder; +- g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); +- +- RTC_LOG(LS_INFO) << "Opening the PipeWire remote."; +- +- g_dbus_proxy_call_with_unix_fd_list( +- proxy_, "OpenPipeWireRemote", +- g_variant_new("(oa{sv})", session_handle_, &builder), +- G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*fd_list=*/nullptr, +- cancellable_, +- reinterpret_cast(OnOpenPipeWireRemoteRequested), +- this); +-} +- +-// static +-void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested( +- GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data) { +- BaseCapturerPipeWire* that = static_cast(user_data); +- RTC_DCHECK(that); +- +- GError* error = nullptr; +- GUnixFDList* outlist = nullptr; +- GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish( +- proxy, &outlist, result, &error); +- if (!variant) { +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- RTC_LOG(LS_ERROR) << "Failed to open the PipeWire remote: " +- << error->message; +- g_error_free(error); +- that->portal_init_failed_ = true; +- return; +- } +- +- gint32 index; +- g_variant_get(variant, "(h)", &index); +- +- if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) { +- RTC_LOG(LS_ERROR) << "Failed to get file descriptor from the list: " +- << error->message; +- g_error_free(error); +- g_variant_unref(variant); +- that->portal_init_failed_ = true; +- return; +- } +- +- g_variant_unref(variant); +- g_object_unref(outlist); +- +- that->InitPipeWire(); +-} +- + void BaseCapturerPipeWire::Start(Callback* callback) { + RTC_DCHECK(!callback_); + RTC_DCHECK(callback); + +- InitPortal(); +- + callback_ = callback; ++ ++ screencast_portal_->Start(); + } + + void BaseCapturerPipeWire::CaptureFrame() { +- if (portal_init_failed_) { ++ if (capturer_failed_) { + callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); + return; + } + +- webrtc::MutexLock lock(¤t_frame_lock_); +- if (!current_frame_) { +- callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); +- return; +- } +- +- DesktopSize frame_size = desktop_size_; +- if (video_metadata_use_) { +- frame_size = video_size_; +- } ++ std::unique_ptr frame = ++ options_.screencast_stream()->CaptureFrame(); + +- std::unique_ptr result(new BasicDesktopFrame(frame_size)); +- result->CopyPixelsFrom( +- current_frame_.get(), (frame_size.width() * BasicDesktopFrame::kBytesPerPixel), +- DesktopRect::MakeWH(frame_size.width(), frame_size.height())); +- if (!result) { ++ if (!frame || !frame->data()) { + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); + return; + } + +- // TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on the +- // frame, see ScreenCapturerX11::CaptureFrame. ++ // TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on ++ // the frame, see ScreenCapturerX11::CaptureFrame. + +- callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); ++ callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); + } + + // Keep in sync with defines at browser/actors/WebRTCParent.jsm +@@ -953,31 +83,13 @@ void BaseCapturerPipeWire::CaptureFrame( + #define PIPEWIRE_NAME "####_PIPEWIRE_PORTAL_####" + + bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { ++ RTC_DCHECK(sources->size() == 0); + sources->push_back({PIPEWIRE_ID, 0, PIPEWIRE_NAME}); + return true; + } + + bool BaseCapturerPipeWire::SelectSource(SourceId id) { +- // Screen selection is handled by the xdg-desktop-portal. + return id == PIPEWIRE_ID; + } + +-// static +-std::unique_ptr +-BaseCapturerPipeWire::CreateRawScreenCapturer( +- const DesktopCaptureOptions& options) { +- std::unique_ptr capturer = +- std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); +- return std::move(capturer);} +- +-// static +-std::unique_ptr +-BaseCapturerPipeWire::CreateRawWindowCapturer( +- const DesktopCaptureOptions& options) { +- +- std::unique_ptr capturer = +- std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); +- return std::move(capturer); +-} +- + } // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.h.libwebrtc-screen-cast-sync 2022-07-18 20:44:26.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/base_capturer_pipewire.h 2022-07-28 11:45:30.319409011 +0200 +@@ -11,160 +11,39 @@ + #ifndef MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ + #define MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ + +-#include +-#define typeof __typeof__ +-#include +-#include +- + #include "modules/desktop_capture/desktop_capture_options.h" + #include "modules/desktop_capture/desktop_capturer.h" +-#include "rtc_base/synchronization/mutex.h" ++#include "modules/desktop_capture/linux/screencast_portal.h" ++#include "modules/desktop_capture/linux/shared_screencast_stream.h" + + namespace webrtc { + +-class BaseCapturerPipeWire : public DesktopCapturer { ++class BaseCapturerPipeWire : public DesktopCapturer, ++ public ScreenCastPortal::PortalNotifier { + public: +- enum CaptureSourceType : uint32_t { +- kScreen = 0b01, +- kWindow = 0b10, +- kAny = 0b11 +- }; +- +- explicit BaseCapturerPipeWire(CaptureSourceType source_type); ++ BaseCapturerPipeWire(const DesktopCaptureOptions& options); + ~BaseCapturerPipeWire() override; + ++ BaseCapturerPipeWire(const BaseCapturerPipeWire&) = delete; ++ BaseCapturerPipeWire& operator=(const BaseCapturerPipeWire&) = delete; ++ + // DesktopCapturer interface. + void Start(Callback* delegate) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + +- static std::unique_ptr CreateRawScreenCapturer( +- const DesktopCaptureOptions& options); +- +- static std::unique_ptr CreateRawWindowCapturer( +- const DesktopCaptureOptions& options); ++ // ScreenCastPortal::PortalNotifier interface. ++ void OnScreenCastRequestResult(ScreenCastPortal::RequestResponse result, ++ uint32_t stream_node_id, ++ int fd) override; ++ void OnScreenCastSessionClosed() override; + + private: +- // PipeWire types --> +- pw_context* pw_context_ = nullptr; +- pw_core* pw_core_ = nullptr; +- pw_stream* pw_stream_ = nullptr; +- pw_thread_loop* pw_main_loop_ = nullptr; +- +- spa_hook spa_core_listener_ = {}; +- spa_hook spa_stream_listener_ = {}; +- +- pw_core_events pw_core_events_ = {}; +- pw_stream_events pw_stream_events_ = {}; +- +- struct spa_video_info_raw spa_video_format_; +- +- guint32 pw_stream_node_id_ = 0; +- gint32 pw_fd_ = -1; +- +- CaptureSourceType capture_source_type_ = +- BaseCapturerPipeWire::CaptureSourceType::kAny; +- +- // <-- end of PipeWire types +- +- GDBusConnection* connection_ = nullptr; +- GDBusProxy* proxy_ = nullptr; +- GCancellable *cancellable_ = nullptr; +- gchar* portal_handle_ = nullptr; +- gchar* session_handle_ = nullptr; +- gchar* sources_handle_ = nullptr; +- gchar* start_handle_ = nullptr; +- guint session_request_signal_id_ = 0; +- guint sources_request_signal_id_ = 0; +- guint start_request_signal_id_ = 0; +- +- bool video_metadata_use_ = false; +- DesktopSize video_size_; +- DesktopSize desktop_size_ = {}; + DesktopCaptureOptions options_ = {}; +- +- webrtc::Mutex current_frame_lock_; +- std::unique_ptr current_frame_; + Callback* callback_ = nullptr; +- +- bool portal_init_failed_ = false; +- +- void InitPortal(); +- void InitPipeWire(); +- +- pw_stream* CreateReceivingStream(); +- void HandleBuffer(pw_buffer* buffer); +- +- void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); +- +- static void OnCoreError(void *data, +- uint32_t id, +- int seq, +- int res, +- const char *message); +- static void OnStreamParamChanged(void *data, +- uint32_t id, +- const struct spa_pod *format); +- static void OnStreamStateChanged(void* data, +- pw_stream_state old_state, +- pw_stream_state state, +- const char* error_message); +- static void OnStreamProcess(void* data); +- static void OnNewBuffer(void* data, uint32_t id); +- +- guint SetupRequestResponseSignal(const gchar* object_path, +- GDBusSignalCallback callback); +- +- static void OnProxyRequested(GObject* object, +- GAsyncResult* result, +- gpointer user_data); +- +- static gchar* PrepareSignalHandle(GDBusConnection* connection, +- const gchar* token); +- +- void SessionRequest(); +- static void OnSessionRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data); +- static void OnSessionRequestResponseSignal(GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data); +- +- void SourcesRequest(); +- static void OnSourcesRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data); +- static void OnSourcesRequestResponseSignal(GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data); +- +- void StartRequest(); +- static void OnStartRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data); +- static void OnStartRequestResponseSignal(GDBusConnection* connection, +- const gchar* sender_name, +- const gchar* object_path, +- const gchar* interface_name, +- const gchar* signal_name, +- GVariant* parameters, +- gpointer user_data); +- +- void OpenPipeWireRemote(); +- static void OnOpenPipeWireRemoteRequested(GDBusProxy *proxy, +- GAsyncResult* result, +- gpointer user_data); +- +- RTC_DISALLOW_COPY_AND_ASSIGN(BaseCapturerPipeWire); ++ bool capturer_failed_ = false; ++ std::unique_ptr screencast_portal_; + }; + + } // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/drm.sigs.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/drm.sigs +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/drm.sigs.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.319409011 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/drm.sigs 2022-07-28 11:45:30.319409011 +0200 +@@ -0,0 +1,11 @@ ++// Copyright 2021 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. ++ ++//------------------------------------------------ ++// Functions from DRM used in capturer code. ++//-------- ++ ++// xf86drm.h ++int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices); ++void drmFreeDevices(drmDevicePtr devices[], int count); +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.319409011 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.cc 2022-07-28 11:45:30.319409011 +0200 +@@ -0,0 +1,695 @@ ++/* ++ * Copyright 2021 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. ++ */ ++ ++#include "modules/desktop_capture/linux/egl_dmabuf.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "absl/memory/memory.h" ++#include "absl/types/optional.h" ++#include "rtc_base/checks.h" ++#include "rtc_base/logging.h" ++#include "rtc_base/sanitizer.h" ++#include "rtc_base/string_encode.h" ++ ++namespace webrtc { ++ ++// EGL ++typedef EGLBoolean (*eglBindAPI_func)(EGLenum api); ++typedef EGLContext (*eglCreateContext_func)(EGLDisplay dpy, ++ EGLConfig config, ++ EGLContext share_context, ++ const EGLint* attrib_list); ++typedef EGLBoolean (*eglDestroyContext_func)(EGLDisplay display, ++ EGLContext context); ++typedef EGLBoolean (*eglTerminate_func)(EGLDisplay display); ++typedef EGLImageKHR (*eglCreateImageKHR_func)(EGLDisplay dpy, ++ EGLContext ctx, ++ EGLenum target, ++ EGLClientBuffer buffer, ++ const EGLint* attrib_list); ++typedef EGLBoolean (*eglDestroyImageKHR_func)(EGLDisplay dpy, ++ EGLImageKHR image); ++typedef EGLint (*eglGetError_func)(void); ++typedef void* (*eglGetProcAddress_func)(const char*); ++typedef EGLDisplay (*eglGetPlatformDisplayEXT_func)(EGLenum platform, ++ void* native_display, ++ const EGLint* attrib_list); ++typedef EGLDisplay (*eglGetPlatformDisplay_func)(EGLenum platform, ++ void* native_display, ++ const EGLAttrib* attrib_list); ++ ++typedef EGLBoolean (*eglInitialize_func)(EGLDisplay dpy, ++ EGLint* major, ++ EGLint* minor); ++typedef EGLBoolean (*eglMakeCurrent_func)(EGLDisplay dpy, ++ EGLSurface draw, ++ EGLSurface read, ++ EGLContext ctx); ++typedef EGLBoolean (*eglQueryDmaBufFormatsEXT_func)(EGLDisplay dpy, ++ EGLint max_formats, ++ EGLint* formats, ++ EGLint* num_formats); ++typedef EGLBoolean (*eglQueryDmaBufModifiersEXT_func)(EGLDisplay dpy, ++ EGLint format, ++ EGLint max_modifiers, ++ EGLuint64KHR* modifiers, ++ EGLBoolean* external_only, ++ EGLint* num_modifiers); ++typedef const char* (*eglQueryString_func)(EGLDisplay dpy, EGLint name); ++typedef void (*glEGLImageTargetTexture2DOES_func)(GLenum target, ++ GLeglImageOES image); ++ ++// This doesn't follow naming conventions in WebRTC, where the naming ++// should look like e.g. egl_bind_api instead of EglBindAPI, however ++// we named them according to the exported functions they map to for ++// consistency. ++eglBindAPI_func EglBindAPI = nullptr; ++eglCreateContext_func EglCreateContext = nullptr; ++eglDestroyContext_func EglDestroyContext = nullptr; ++eglTerminate_func EglTerminate = nullptr; ++eglCreateImageKHR_func EglCreateImageKHR = nullptr; ++eglDestroyImageKHR_func EglDestroyImageKHR = nullptr; ++eglGetError_func EglGetError = nullptr; ++eglGetProcAddress_func EglGetProcAddress = nullptr; ++eglGetPlatformDisplayEXT_func EglGetPlatformDisplayEXT = nullptr; ++eglGetPlatformDisplay_func EglGetPlatformDisplay = nullptr; ++eglInitialize_func EglInitialize = nullptr; ++eglMakeCurrent_func EglMakeCurrent = nullptr; ++eglQueryDmaBufFormatsEXT_func EglQueryDmaBufFormatsEXT = nullptr; ++eglQueryDmaBufModifiersEXT_func EglQueryDmaBufModifiersEXT = nullptr; ++eglQueryString_func EglQueryString = nullptr; ++glEGLImageTargetTexture2DOES_func GlEGLImageTargetTexture2DOES = nullptr; ++ ++// GL ++typedef void (*glBindTexture_func)(GLenum target, GLuint texture); ++typedef void (*glDeleteTextures_func)(GLsizei n, const GLuint* textures); ++typedef void (*glGenTextures_func)(GLsizei n, GLuint* textures); ++typedef GLenum (*glGetError_func)(void); ++typedef const GLubyte* (*glGetString_func)(GLenum name); ++typedef void (*glGetTexImage_func)(GLenum target, ++ GLint level, ++ GLenum format, ++ GLenum type, ++ void* pixels); ++typedef void (*glTexParameteri_func)(GLenum target, GLenum pname, GLint param); ++typedef void* (*glXGetProcAddressARB_func)(const char*); ++ ++// This doesn't follow naming conventions in WebRTC, where the naming ++// should look like e.g. egl_bind_api instead of EglBindAPI, however ++// we named them according to the exported functions they map to for ++// consistency. ++glBindTexture_func GlBindTexture = nullptr; ++glDeleteTextures_func GlDeleteTextures = nullptr; ++glGenTextures_func GlGenTextures = nullptr; ++glGetError_func GlGetError = nullptr; ++glGetString_func GlGetString = nullptr; ++glGetTexImage_func GlGetTexImage = nullptr; ++glTexParameteri_func GlTexParameteri = nullptr; ++glXGetProcAddressARB_func GlXGetProcAddressARB = nullptr; ++ ++static const std::string FormatGLError(GLenum err) { ++ switch (err) { ++ case GL_NO_ERROR: ++ return "GL_NO_ERROR"; ++ case GL_INVALID_ENUM: ++ return "GL_INVALID_ENUM"; ++ case GL_INVALID_VALUE: ++ return "GL_INVALID_VALUE"; ++ case GL_INVALID_OPERATION: ++ return "GL_INVALID_OPERATION"; ++ case GL_STACK_OVERFLOW: ++ return "GL_STACK_OVERFLOW"; ++ case GL_STACK_UNDERFLOW: ++ return "GL_STACK_UNDERFLOW"; ++ case GL_OUT_OF_MEMORY: ++ return "GL_OUT_OF_MEMORY"; ++ default: ++ return "GL error code: " + std::to_string(err); ++ } ++} ++ ++static const std::string FormatEGLError(EGLint err) { ++ switch (err) { ++ case EGL_NOT_INITIALIZED: ++ return "EGL_NOT_INITIALIZED"; ++ case EGL_BAD_ACCESS: ++ return "EGL_BAD_ACCESS"; ++ case EGL_BAD_ALLOC: ++ return "EGL_BAD_ALLOC"; ++ case EGL_BAD_ATTRIBUTE: ++ return "EGL_BAD_ATTRIBUTE"; ++ case EGL_BAD_CONTEXT: ++ return "EGL_BAD_CONTEXT"; ++ case EGL_BAD_CONFIG: ++ return "EGL_BAD_CONFIG"; ++ case EGL_BAD_CURRENT_SURFACE: ++ return "EGL_BAD_CURRENT_SURFACE"; ++ case EGL_BAD_DISPLAY: ++ return "EGL_BAD_DISPLAY"; ++ case EGL_BAD_SURFACE: ++ return "EGL_BAD_SURFACE"; ++ case EGL_BAD_MATCH: ++ return "EGL_BAD_MATCH"; ++ case EGL_BAD_PARAMETER: ++ return "EGL_BAD_PARAMETER"; ++ case EGL_BAD_NATIVE_PIXMAP: ++ return "EGL_BAD_NATIVE_PIXMAP"; ++ case EGL_BAD_NATIVE_WINDOW: ++ return "EGL_BAD_NATIVE_WINDOW"; ++ case EGL_CONTEXT_LOST: ++ return "EGL_CONTEXT_LOST"; ++ default: ++ return "EGL error code: " + std::to_string(err); ++ } ++} ++ ++static uint32_t SpaPixelFormatToDrmFormat(uint32_t spa_format) { ++ switch (spa_format) { ++ case SPA_VIDEO_FORMAT_RGBA: ++ return DRM_FORMAT_ABGR8888; ++ case SPA_VIDEO_FORMAT_RGBx: ++ return DRM_FORMAT_XBGR8888; ++ case SPA_VIDEO_FORMAT_BGRA: ++ return DRM_FORMAT_ARGB8888; ++ case SPA_VIDEO_FORMAT_BGRx: ++ return DRM_FORMAT_XRGB8888; ++ default: ++ return DRM_FORMAT_INVALID; ++ } ++} ++ ++static void CloseLibrary(void* library) { ++ if (library) { ++ dlclose(library); ++ library = nullptr; ++ } ++} ++ ++static void* g_lib_egl = nullptr; ++ ++static bool OpenEGL() { ++ g_lib_egl = dlopen("libEGL.so.1", RTLD_NOW | RTLD_GLOBAL); ++ if (g_lib_egl) { ++ EglGetProcAddress = ++ (eglGetProcAddress_func)dlsym(g_lib_egl, "eglGetProcAddress"); ++ return EglGetProcAddress; ++ } ++ ++ return false; ++} ++ ++static bool LoadEGL() { ++ if (OpenEGL()) { ++ EglBindAPI = (eglBindAPI_func)EglGetProcAddress("eglBindAPI"); ++ EglCreateContext = ++ (eglCreateContext_func)EglGetProcAddress("eglCreateContext"); ++ EglDestroyContext = ++ (eglDestroyContext_func)EglGetProcAddress("eglDestroyContext"); ++ EglTerminate = (eglTerminate_func)EglGetProcAddress("eglTerminate"); ++ EglCreateImageKHR = ++ (eglCreateImageKHR_func)EglGetProcAddress("eglCreateImageKHR"); ++ EglDestroyImageKHR = ++ (eglDestroyImageKHR_func)EglGetProcAddress("eglDestroyImageKHR"); ++ EglGetError = (eglGetError_func)EglGetProcAddress("eglGetError"); ++ EglGetPlatformDisplayEXT = (eglGetPlatformDisplayEXT_func)EglGetProcAddress( ++ "eglGetPlatformDisplayEXT"); ++ EglGetPlatformDisplay = ++ (eglGetPlatformDisplay_func)EglGetProcAddress("eglGetPlatformDisplay"); ++ EglInitialize = (eglInitialize_func)EglGetProcAddress("eglInitialize"); ++ EglMakeCurrent = (eglMakeCurrent_func)EglGetProcAddress("eglMakeCurrent"); ++ EglQueryString = (eglQueryString_func)EglGetProcAddress("eglQueryString"); ++ GlEGLImageTargetTexture2DOES = ++ (glEGLImageTargetTexture2DOES_func)EglGetProcAddress( ++ "glEGLImageTargetTexture2DOES"); ++ ++ return EglBindAPI && EglCreateContext && EglCreateImageKHR && ++ EglTerminate && EglDestroyContext && EglDestroyImageKHR && ++ EglGetError && EglGetPlatformDisplayEXT && EglGetPlatformDisplay && ++ EglInitialize && EglMakeCurrent && EglQueryString && ++ GlEGLImageTargetTexture2DOES; ++ } ++ ++ return false; ++} ++ ++static void* g_lib_gl = nullptr; ++ ++static bool OpenGL() { ++ std::vector names = {"libGL.so.1", "libGL.so"}; ++ for (const std::string& name : names) { ++ g_lib_gl = dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL); ++ if (g_lib_gl) { ++ GlXGetProcAddressARB = ++ (glXGetProcAddressARB_func)dlsym(g_lib_gl, "glXGetProcAddressARB"); ++ return GlXGetProcAddressARB; ++ } ++ } ++ ++ return false; ++} ++ ++static bool LoadGL() { ++ if (OpenGL()) { ++ GlGetString = (glGetString_func)GlXGetProcAddressARB("glGetString"); ++ if (!GlGetString) { ++ return false; ++ } ++ ++ GlBindTexture = (glBindTexture_func)GlXGetProcAddressARB("glBindTexture"); ++ GlDeleteTextures = ++ (glDeleteTextures_func)GlXGetProcAddressARB("glDeleteTextures"); ++ GlGenTextures = (glGenTextures_func)GlXGetProcAddressARB("glGenTextures"); ++ GlGetError = (glGetError_func)GlXGetProcAddressARB("glGetError"); ++ GlGetTexImage = (glGetTexImage_func)GlXGetProcAddressARB("glGetTexImage"); ++ GlTexParameteri = ++ (glTexParameteri_func)GlXGetProcAddressARB("glTexParameteri"); ++ ++ return GlBindTexture && GlDeleteTextures && GlGenTextures && GlGetError && ++ GlGetTexImage && GlTexParameteri; ++ } ++ ++ return false; ++} ++ ++EglDmaBuf::EglDmaBuf() { ++ if (!LoadEGL()) { ++ RTC_LOG(LS_ERROR) << "Unable to load EGL entry functions."; ++ CloseLibrary(g_lib_egl); ++ return; ++ } ++ ++ if (!LoadGL()) { ++ RTC_LOG(LS_ERROR) << "Failed to load OpenGL entry functions."; ++ CloseLibrary(g_lib_gl); ++ return; ++ } ++ ++ if (!GetClientExtensions(EGL_NO_DISPLAY, EGL_EXTENSIONS)) { ++ return; ++ } ++ ++ bool has_platform_base_ext = false; ++ bool has_platform_gbm_ext = false; ++ bool has_khr_platform_gbm_ext = false; ++ ++ for (const auto& extension : egl_.extensions) { ++ if (extension == "EGL_EXT_platform_base") { ++ has_platform_base_ext = true; ++ continue; ++ } else if (extension == "EGL_MESA_platform_gbm") { ++ has_platform_gbm_ext = true; ++ continue; ++ } else if (extension == "EGL_KHR_platform_gbm") { ++ has_khr_platform_gbm_ext = true; ++ continue; ++ } ++ } ++ ++ if (!has_platform_base_ext || !has_platform_gbm_ext || ++ !has_khr_platform_gbm_ext) { ++ RTC_LOG(LS_ERROR) << "One of required EGL extensions is missing"; ++ return; ++ } ++ ++ egl_.display = EglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, ++ (void*)EGL_DEFAULT_DISPLAY, nullptr); ++ ++ if (egl_.display == EGL_NO_DISPLAY) { ++ RTC_LOG(LS_ERROR) << "Failed to obtain default EGL display: " ++ << FormatEGLError(EglGetError()) << "\n" ++ << "Defaulting to using first available render node"; ++ absl::optional render_node = GetRenderNode(); ++ if (!render_node) { ++ return; ++ } ++ ++ drm_fd_ = open(render_node->c_str(), O_RDWR); ++ ++ if (drm_fd_ < 0) { ++ RTC_LOG(LS_ERROR) << "Failed to open drm render node: " ++ << strerror(errno); ++ return; ++ } ++ ++ gbm_device_ = gbm_create_device(drm_fd_); ++ ++ if (!gbm_device_) { ++ RTC_LOG(LS_ERROR) << "Cannot create GBM device: " << strerror(errno); ++ close(drm_fd_); ++ return; ++ } ++ ++ // Use eglGetPlatformDisplayEXT() to get the display pointer ++ // if the implementation supports it. ++ egl_.display = ++ EglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, gbm_device_, nullptr); ++ } ++ ++ if (egl_.display == EGL_NO_DISPLAY) { ++ RTC_LOG(LS_ERROR) << "Error during obtaining EGL display: " ++ << FormatEGLError(EglGetError()); ++ return; ++ } ++ ++ EGLint major, minor; ++ if (EglInitialize(egl_.display, &major, &minor) == EGL_FALSE) { ++ RTC_LOG(LS_ERROR) << "Error during eglInitialize: " ++ << FormatEGLError(EglGetError()); ++ return; ++ } ++ ++ if (EglBindAPI(EGL_OPENGL_API) == EGL_FALSE) { ++ RTC_LOG(LS_ERROR) << "bind OpenGL API failed"; ++ return; ++ } ++ ++ egl_.context = ++ EglCreateContext(egl_.display, nullptr, EGL_NO_CONTEXT, nullptr); ++ ++ if (egl_.context == EGL_NO_CONTEXT) { ++ RTC_LOG(LS_ERROR) << "Couldn't create EGL context: " ++ << FormatGLError(EglGetError()); ++ return; ++ } ++ ++ if (!GetClientExtensions(egl_.display, EGL_EXTENSIONS)) { ++ return; ++ } ++ ++ bool has_image_dma_buf_import_modifiers_ext = false; ++ ++ for (const auto& extension : egl_.extensions) { ++ if (extension == "EGL_EXT_image_dma_buf_import") { ++ has_image_dma_buf_import_ext_ = true; ++ continue; ++ } else if (extension == "EGL_EXT_image_dma_buf_import_modifiers") { ++ has_image_dma_buf_import_modifiers_ext = true; ++ continue; ++ } ++ } ++ ++ if (has_image_dma_buf_import_ext_ && has_image_dma_buf_import_modifiers_ext) { ++ EglQueryDmaBufFormatsEXT = (eglQueryDmaBufFormatsEXT_func)EglGetProcAddress( ++ "eglQueryDmaBufFormatsEXT"); ++ EglQueryDmaBufModifiersEXT = ++ (eglQueryDmaBufModifiersEXT_func)EglGetProcAddress( ++ "eglQueryDmaBufModifiersEXT"); ++ } ++ ++ RTC_LOG(LS_INFO) << "Egl initialization succeeded"; ++ egl_initialized_ = true; ++} ++ ++EglDmaBuf::~EglDmaBuf() { ++ if (gbm_device_) { ++ gbm_device_destroy(gbm_device_); ++ close(drm_fd_); ++ } ++ ++ if (egl_.context != EGL_NO_CONTEXT) { ++ EglDestroyContext(egl_.display, egl_.context); ++ } ++ ++ if (egl_.display != EGL_NO_DISPLAY) { ++ EglTerminate(egl_.display); ++ } ++ ++ // BUG: crbug.com/1290566 ++ // Closing libEGL.so.1 when using NVidia drivers causes a crash ++ // when EglGetPlatformDisplayEXT() is used, at least this one is enough ++ // to be called to make it crash. ++ // It also looks that libepoxy and glad don't dlclose it either ++ // CloseLibrary(g_lib_egl); ++ // CloseLibrary(g_lib_gl); ++} ++ ++bool EglDmaBuf::GetClientExtensions(EGLDisplay dpy, EGLint name) { ++ // Get the list of client extensions ++ const char* client_extensions_cstring = EglQueryString(dpy, name); ++ if (!client_extensions_cstring) { ++ // If eglQueryString() returned NULL, the implementation doesn't support ++ // EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error. ++ RTC_LOG(LS_ERROR) << "No client extensions defined! " ++ << FormatEGLError(EglGetError()); ++ return false; ++ } ++ ++ std::vector client_extensions; ++ rtc::split(client_extensions_cstring, ' ', ++ &client_extensions); ++ for (const auto& extension : client_extensions) { ++ egl_.extensions.push_back(extension); ++ } ++ ++ return true; ++} ++ ++std::unique_ptr EglDmaBuf::ImageFromDmaBuf( ++ const DesktopSize& size, ++ uint32_t format, ++ const std::vector& plane_datas, ++ uint64_t modifier) { ++ std::unique_ptr src; ++ ++ if (!egl_initialized_) { ++ return src; ++ } ++ ++ if (plane_datas.size() <= 0) { ++ RTC_LOG(LS_ERROR) << "Failed to process buffer: invalid number of planes"; ++ return src; ++ } ++ ++ EGLint attribs[47]; ++ int atti = 0; ++ ++ attribs[atti++] = EGL_WIDTH; ++ attribs[atti++] = static_cast(size.width()); ++ attribs[atti++] = EGL_HEIGHT; ++ attribs[atti++] = static_cast(size.height()); ++ attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; ++ attribs[atti++] = SpaPixelFormatToDrmFormat(format); ++ ++ if (plane_datas.size() > 0) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; ++ attribs[atti++] = plane_datas[0].fd; ++ attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; ++ attribs[atti++] = plane_datas[0].offset; ++ attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; ++ attribs[atti++] = plane_datas[0].stride; ++ ++ if (modifier != DRM_FORMAT_MOD_INVALID) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; ++ attribs[atti++] = modifier & 0xFFFFFFFF; ++ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; ++ attribs[atti++] = modifier >> 32; ++ } ++ } ++ ++ if (plane_datas.size() > 1) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; ++ attribs[atti++] = plane_datas[1].fd; ++ attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; ++ attribs[atti++] = plane_datas[1].offset; ++ attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; ++ attribs[atti++] = plane_datas[1].stride; ++ ++ if (modifier != DRM_FORMAT_MOD_INVALID) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; ++ attribs[atti++] = modifier & 0xFFFFFFFF; ++ attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; ++ attribs[atti++] = modifier >> 32; ++ } ++ } ++ ++ if (plane_datas.size() > 2) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT; ++ attribs[atti++] = plane_datas[2].fd; ++ attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT; ++ attribs[atti++] = plane_datas[2].offset; ++ attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; ++ attribs[atti++] = plane_datas[2].stride; ++ ++ if (modifier != DRM_FORMAT_MOD_INVALID) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; ++ attribs[atti++] = modifier & 0xFFFFFFFF; ++ attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; ++ attribs[atti++] = modifier >> 32; ++ } ++ } ++ ++ if (plane_datas.size() > 3) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE3_FD_EXT; ++ attribs[atti++] = plane_datas[3].fd; ++ attribs[atti++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT; ++ attribs[atti++] = plane_datas[3].offset; ++ attribs[atti++] = EGL_DMA_BUF_PLANE3_PITCH_EXT; ++ attribs[atti++] = plane_datas[3].stride; ++ ++ if (modifier != DRM_FORMAT_MOD_INVALID) { ++ attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT; ++ attribs[atti++] = modifier & 0xFFFFFFFF; ++ attribs[atti++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT; ++ attribs[atti++] = modifier >> 32; ++ } ++ } ++ ++ attribs[atti++] = EGL_NONE; ++ ++ // bind context to render thread ++ EglMakeCurrent(egl_.display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_.context); ++ ++ // create EGL image from attribute list ++ EGLImageKHR image = EglCreateImageKHR( ++ egl_.display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs); ++ ++ if (image == EGL_NO_IMAGE) { ++ RTC_LOG(LS_ERROR) << "Failed to record frame: Error creating EGLImage - " ++ << FormatEGLError(EglGetError()); ++ return src; ++ } ++ ++ // create GL 2D texture for framebuffer ++ GLuint texture; ++ GlGenTextures(1, &texture); ++ GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); ++ GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ++ GlBindTexture(GL_TEXTURE_2D, texture); ++ GlEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); ++ ++ src = std::make_unique(plane_datas[0].stride * size.height()); ++ ++ GLenum gl_format = GL_BGRA; ++ switch (format) { ++ case SPA_VIDEO_FORMAT_RGBx: ++ gl_format = GL_RGBA; ++ break; ++ case SPA_VIDEO_FORMAT_RGBA: ++ gl_format = GL_RGBA; ++ break; ++ case SPA_VIDEO_FORMAT_BGRx: ++ gl_format = GL_BGRA; ++ break; ++ default: ++ gl_format = GL_BGRA; ++ break; ++ } ++ GlGetTexImage(GL_TEXTURE_2D, 0, gl_format, GL_UNSIGNED_BYTE, src.get()); ++ ++ if (GlGetError()) { ++ RTC_LOG(LS_ERROR) << "Failed to get image from DMA buffer."; ++ return src; ++ } ++ ++ GlDeleteTextures(1, &texture); ++ EglDestroyImageKHR(egl_.display, image); ++ ++ return src; ++} ++ ++std::vector EglDmaBuf::QueryDmaBufModifiers(uint32_t format) { ++ if (!egl_initialized_) { ++ return {}; ++ } ++ ++ // Explicit modifiers not supported, return just DRM_FORMAT_MOD_INVALID as we ++ // can still use modifier-less DMA-BUFs if we have required extension ++ if (EglQueryDmaBufFormatsEXT == nullptr || ++ EglQueryDmaBufModifiersEXT == nullptr) { ++ return has_image_dma_buf_import_ext_ ++ ? std::vector{DRM_FORMAT_MOD_INVALID} ++ : std::vector{}; ++ } ++ ++ uint32_t drm_format = SpaPixelFormatToDrmFormat(format); ++ // Should never happen as it's us who controls the list of supported formats ++ RTC_DCHECK(drm_format != DRM_FORMAT_INVALID); ++ ++ EGLint count = 0; ++ EGLBoolean success = ++ EglQueryDmaBufFormatsEXT(egl_.display, 0, nullptr, &count); ++ ++ if (!success || !count) { ++ RTC_LOG(LS_ERROR) << "Failed to query DMA-BUF formats."; ++ return {DRM_FORMAT_MOD_INVALID}; ++ } ++ ++ std::vector formats(count); ++ if (!EglQueryDmaBufFormatsEXT(egl_.display, count, ++ reinterpret_cast(formats.data()), ++ &count)) { ++ RTC_LOG(LS_ERROR) << "Failed to query DMA-BUF formats."; ++ return {DRM_FORMAT_MOD_INVALID}; ++ } ++ ++ if (std::find(formats.begin(), formats.end(), drm_format) == formats.end()) { ++ RTC_LOG(LS_ERROR) << "Format " << drm_format ++ << " not supported for modifiers."; ++ return {DRM_FORMAT_MOD_INVALID}; ++ } ++ ++ success = EglQueryDmaBufModifiersEXT(egl_.display, drm_format, 0, nullptr, ++ nullptr, &count); ++ ++ if (!success || !count) { ++ RTC_LOG(LS_ERROR) << "Failed to query DMA-BUF modifiers."; ++ return {DRM_FORMAT_MOD_INVALID}; ++ } ++ ++ std::vector modifiers(count); ++ if (!EglQueryDmaBufModifiersEXT(egl_.display, drm_format, count, ++ modifiers.data(), nullptr, &count)) { ++ RTC_LOG(LS_ERROR) << "Failed to query DMA-BUF modifiers."; ++ } ++ ++ // Support modifier-less buffers ++ modifiers.push_back(DRM_FORMAT_MOD_INVALID); ++ return modifiers; ++} ++ ++absl::optional EglDmaBuf::GetRenderNode() { ++ int max_devices = drmGetDevices2(0, nullptr, 0); ++ if (max_devices <= 0) { ++ RTC_LOG(LS_ERROR) << "drmGetDevices2() has not found any devices (errno=" ++ << -max_devices << ")"; ++ return absl::nullopt; ++ } ++ ++ std::vector devices(max_devices); ++ int ret = drmGetDevices2(0, devices.data(), max_devices); ++ if (ret < 0) { ++ RTC_LOG(LS_ERROR) << "drmGetDevices2() returned an error " << ret; ++ return absl::nullopt; ++ } ++ ++ std::string render_node; ++ ++ for (const drmDevicePtr& device : devices) { ++ if (device->available_nodes & (1 << DRM_NODE_RENDER)) { ++ render_node = device->nodes[DRM_NODE_RENDER]; ++ break; ++ } ++ } ++ ++ drmFreeDevices(devices.data(), ret); ++ return render_node; ++} ++ ++} // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.319409011 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/egl_dmabuf.h 2022-07-28 11:45:30.319409011 +0200 +@@ -0,0 +1,68 @@ ++/* ++ * Copyright 2021 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. ++ */ ++ ++#ifndef MODULES_DESKTOP_CAPTURE_LINUX_EGL_DMABUF_H_ ++#define MODULES_DESKTOP_CAPTURE_LINUX_EGL_DMABUF_H_ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "absl/types/optional.h" ++#include "modules/desktop_capture/desktop_geometry.h" ++ ++namespace webrtc { ++ ++class EglDmaBuf { ++ public: ++ struct EGLStruct { ++ std::vector extensions; ++ EGLDisplay display = EGL_NO_DISPLAY; ++ EGLContext context = EGL_NO_CONTEXT; ++ }; ++ ++ struct PlaneData { ++ int32_t fd; ++ uint32_t stride; ++ uint32_t offset; ++ }; ++ ++ EglDmaBuf(); ++ ~EglDmaBuf(); ++ ++ std::unique_ptr ImageFromDmaBuf( ++ const DesktopSize& size, ++ uint32_t format, ++ const std::vector& plane_datas, ++ uint64_t modifiers); ++ std::vector QueryDmaBufModifiers(uint32_t format); ++ ++ bool IsEglInitialized() const { return egl_initialized_; } ++ ++ private: ++ bool GetClientExtensions(EGLDisplay dpy, EGLint name); ++ ++ bool egl_initialized_ = false; ++ bool has_image_dma_buf_import_ext_ = false; ++ int32_t drm_fd_ = -1; // for GBM buffer mmap ++ gbm_device* gbm_device_ = nullptr; // for passed GBM buffer retrieval ++ ++ EGLStruct egl_; ++ ++ absl::optional GetRenderNode(); ++}; ++ ++} // namespace webrtc ++ ++#endif // MODULES_DESKTOP_CAPTURE_LINUX_EGL_DMABUF_H_ +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.319409011 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.cc 2022-07-28 11:45:30.319409011 +0200 +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2022 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. ++ */ ++ ++#include "modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h" ++ ++#include ++ ++#include "modules/desktop_capture/desktop_capture_options.h" ++#include "modules/desktop_capture/desktop_capturer.h" ++#include "rtc_base/checks.h" ++#include "rtc_base/logging.h" ++ ++namespace webrtc { ++ ++MouseCursorMonitorPipeWire::MouseCursorMonitorPipeWire( ++ const DesktopCaptureOptions& options) ++ : options_(options) { ++} ++ ++MouseCursorMonitorPipeWire::~MouseCursorMonitorPipeWire() {} ++ ++void MouseCursorMonitorPipeWire::Init(Callback* callback, Mode mode) { ++ RTC_DCHECK(!callback_); ++ RTC_DCHECK(callback); ++ ++ callback_ = callback; ++ mode_ = mode; ++} ++ ++void MouseCursorMonitorPipeWire::Capture() { ++ RTC_DCHECK(callback_); ++ ++ std::unique_ptr mouse_cursor = ++ options_.screencast_stream()->CaptureCursor(); ++ ++ if (mouse_cursor && mouse_cursor->image()->data()) { ++ callback_->OnMouseCursor(mouse_cursor.release()); ++ } ++ ++ if (mode_ == SHAPE_AND_POSITION) { ++ absl::optional mouse_cursor_position = ++ options_.screencast_stream()->CaptureCursorPosition(); ++ if (mouse_cursor_position) { ++ callback_->OnMouseCursorPosition(mouse_cursor_position.value()); ++ } ++ } ++} ++ ++} // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.319409011 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h 2022-07-28 11:45:30.319409011 +0200 +@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#ifndef MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_PIPEWIRE_H_ ++#define MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_PIPEWIRE_H_ ++ ++#include ++ ++#include "api/scoped_refptr.h" ++#include "modules/desktop_capture/desktop_capture_options.h" ++#include "modules/desktop_capture/desktop_capture_types.h" ++#include "modules/desktop_capture/linux/shared_screencast_stream.h" ++#include "modules/desktop_capture/mouse_cursor.h" ++#include "modules/desktop_capture/mouse_cursor_monitor.h" ++ ++namespace webrtc { ++ ++class MouseCursorMonitorPipeWire : public MouseCursorMonitor { ++ public: ++ explicit MouseCursorMonitorPipeWire(const DesktopCaptureOptions& options); ++ ~MouseCursorMonitorPipeWire() override; ++ ++ // MouseCursorMonitor: ++ void Init(Callback* callback, Mode mode) override; ++ void Capture() override; ++ ++ DesktopCaptureOptions options_; ++ Callback* callback_ = nullptr; ++ Mode mode_ = SHAPE_AND_POSITION; ++}; ++ ++} // namespace webrtc ++ ++#endif // MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_PIPEWIRE_H_ +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire.sigs.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire.sigs +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire.sigs.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire.sigs 2022-07-28 11:45:30.319409011 +0200 +@@ -7,38 +7,44 @@ + //------------------------------------------------ + + // core.h +-void pw_core_destroy(pw_core *core); +-pw_type *pw_core_get_type(pw_core *core); +-pw_core * pw_core_new(pw_loop *main_loop, pw_properties *props); ++int pw_core_disconnect(pw_core *core); + + // loop.h + void pw_loop_destroy(pw_loop *loop); +-pw_loop * pw_loop_new(pw_properties *properties); ++pw_loop * pw_loop_new(const spa_dict *props); ++ + + // pipewire.h + void pw_init(int *argc, char **argv[]); ++const char* pw_get_library_version(); + + // properties.h + pw_properties * pw_properties_new_string(const char *args); + +-// remote.h +-void pw_remote_add_listener(pw_remote *remote, spa_hook *listener, const pw_remote_events *events, void *data); +-int pw_remote_connect_fd(pw_remote *remote, int fd); +-void pw_remote_destroy(pw_remote *remote); +-pw_remote * pw_remote_new(pw_core *core, pw_properties *properties, size_t user_data_size); +- + // stream.h + void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const pw_stream_events *events, void *data); +-int pw_stream_connect(pw_stream *stream, enum pw_direction direction, const char *port_path, enum pw_stream_flags flags, const spa_pod **params, uint32_t n_params); ++int pw_stream_connect(pw_stream *stream, enum pw_direction direction, uint32_t target_id, enum pw_stream_flags flags, const spa_pod **params, uint32_t n_params); ++int pw_stream_disconnect(pw_stream *stream); + pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); + void pw_stream_destroy(pw_stream *stream); +-void pw_stream_finish_format(pw_stream *stream, int res, const spa_pod **params, uint32_t n_params); +-pw_stream * pw_stream_new(pw_remote *remote, const char *name, pw_properties *props); ++pw_stream * pw_stream_new(pw_core *core, const char *name, pw_properties *props); + int pw_stream_queue_buffer(pw_stream *stream, pw_buffer *buffer); + int pw_stream_set_active(pw_stream *stream, bool active); ++int pw_stream_update_params(pw_stream *stream, const spa_pod **params, uint32_t n_params); + + // thread-loop.h + void pw_thread_loop_destroy(pw_thread_loop *loop); +-pw_thread_loop * pw_thread_loop_new(pw_loop *loop, const char *name); ++pw_thread_loop * pw_thread_loop_new(const char *name, const spa_dict *props); + int pw_thread_loop_start(pw_thread_loop *loop); + void pw_thread_loop_stop(pw_thread_loop *loop); ++void pw_thread_loop_lock(pw_thread_loop *loop); ++void pw_thread_loop_unlock(pw_thread_loop *loop); ++pw_loop * pw_thread_loop_get_loop(pw_thread_loop *loop); ++void pw_thread_loop_signal(pw_thread_loop *loop, bool wait_for_accept); ++void pw_thread_loop_wait(pw_thread_loop *loop); ++ ++// context.h ++void pw_context_destroy(pw_context *context); ++pw_context *pw_context_new(pw_loop *main_loop, pw_properties *props, size_t user_data_size); ++pw_core * pw_context_connect(pw_context *context, pw_properties *properties, size_t user_data_size); ++pw_core * pw_context_connect_fd(pw_context *context, int fd, pw_properties *properties, size_t user_data_size); +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire_stub_header.fragment.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire_stub_header.fragment +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire_stub_header.fragment.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/pipewire_stub_header.fragment 2022-07-28 11:45:30.320409004 +0200 +@@ -5,4 +5,5 @@ extern "C" { + + #include + ++#include + } +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#include "modules/desktop_capture/linux/scoped_glib.h" ++ ++namespace webrtc { ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_error_free(ptr_); ++ } ++} ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_free(ptr_); ++ } ++} ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_variant_unref(ptr_); ++ } ++} ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_variant_iter_free(ptr_); ++ } ++} ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_object_unref(ptr_); ++ } ++} ++ ++template <> ++Scoped::~Scoped() { ++ if (ptr_) { ++ g_object_unref(ptr_); ++ } ++} ++ ++} // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/scoped_glib.h 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCOPED_GLIB_H_ ++#define MODULES_DESKTOP_CAPTURE_LINUX_SCOPED_GLIB_H_ ++ ++#include ++ ++#include "rtc_base/checks.h" ++ ++namespace webrtc { ++ ++template ++class Scoped { ++ public: ++ Scoped() {} ++ explicit Scoped(T* val) { ptr_ = val; } ++ ~Scoped() { RTC_NOTREACHED(); } ++ ++ T* operator->() const { return ptr_; } ++ ++ explicit operator bool() const { return ptr_ != nullptr; } ++ ++ bool operator!() const { return ptr_ == nullptr; } ++ ++ T* get() const { return ptr_; } ++ ++ T** receive() { ++ RTC_CHECK(!ptr_); ++ return &ptr_; ++ } ++ ++ Scoped& operator=(T* val) { ++ RTC_DCHECK(val); ++ ptr_ = val; ++ return *this; ++ } ++ ++ protected: ++ T* ptr_ = nullptr; ++}; ++ ++template <> ++Scoped::~Scoped(); ++template <> ++Scoped::~Scoped(); ++template <> ++Scoped::~Scoped(); ++template <> ++Scoped::~Scoped(); ++template <> ++Scoped::~Scoped(); ++template <> ++Scoped::~Scoped(); ++ ++} // namespace webrtc ++ ++#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCOPED_GLIB_H_ +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,532 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#include "modules/desktop_capture/linux/screencast_portal.h" ++ ++#include ++#include ++ ++#include "modules/desktop_capture/linux/scoped_glib.h" ++#include "rtc_base/checks.h" ++#include "rtc_base/logging.h" ++ ++namespace webrtc { ++ ++const char kDesktopBusName[] = "org.freedesktop.portal.Desktop"; ++const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; ++const char kDesktopRequestObjectPath[] = ++ "/org/freedesktop/portal/desktop/request"; ++const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; ++const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; ++const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; ++ ++ScreenCastPortal::ScreenCastPortal(CaptureSourceType source_type, ++ PortalNotifier* notifier) ++ : notifier_(notifier), capture_source_type_(source_type) {} ++ ++ScreenCastPortal::~ScreenCastPortal() { ++ if (start_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); ++ } ++ if (sources_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(connection_, ++ sources_request_signal_id_); ++ } ++ if (session_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(connection_, ++ session_request_signal_id_); ++ } ++ ++ if (!session_handle_.empty()) { ++ Scoped message( ++ g_dbus_message_new_method_call(kDesktopBusName, session_handle_.c_str(), ++ kSessionInterfaceName, "Close")); ++ if (message.get()) { ++ Scoped error; ++ g_dbus_connection_send_message(connection_, message.get(), ++ G_DBUS_SEND_MESSAGE_FLAGS_NONE, ++ /*out_serial=*/nullptr, error.receive()); ++ if (error.get()) { ++ RTC_LOG(LS_ERROR) << "Failed to close the session: " << error->message; ++ } ++ } ++ } ++ ++ if (cancellable_) { ++ g_cancellable_cancel(cancellable_); ++ g_object_unref(cancellable_); ++ cancellable_ = nullptr; ++ } ++ ++ if (proxy_) { ++ g_object_unref(proxy_); ++ proxy_ = nullptr; ++ } ++ ++ if (pw_fd_ != -1) { ++ close(pw_fd_); ++ } ++} ++ ++void ScreenCastPortal::Start() { ++ cancellable_ = g_cancellable_new(); ++ g_dbus_proxy_new_for_bus( ++ G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, /*info=*/nullptr, ++ kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, ++ cancellable_, reinterpret_cast(OnProxyRequested), ++ this); ++} ++ ++void ScreenCastPortal::PortalFailed(RequestResponse result) { ++ notifier_->OnScreenCastRequestResult(result, pw_stream_node_id_, pw_fd_); ++} ++ ++uint32_t ScreenCastPortal::SetupRequestResponseSignal( ++ const char* object_path, ++ GDBusSignalCallback callback) { ++ return g_dbus_connection_signal_subscribe( ++ connection_, kDesktopBusName, kRequestInterfaceName, "Response", ++ object_path, /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, ++ callback, this, /*user_data_free_func=*/nullptr); ++} ++ ++// static ++void ScreenCastPortal::OnProxyRequested(GObject* /*object*/, ++ GAsyncResult* result, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ Scoped error; ++ GDBusProxy* proxy = g_dbus_proxy_new_finish(result, error.receive()); ++ if (!proxy) { ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ RTC_LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: " ++ << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ that->proxy_ = proxy; ++ that->connection_ = g_dbus_proxy_get_connection(that->proxy_); ++ ++ RTC_LOG(LS_INFO) << "Created proxy for the screen cast portal."; ++ ++ that->SessionRequest(); ++} ++ ++// static ++std::string ScreenCastPortal::PrepareSignalHandle(GDBusConnection* connection, ++ const char* token) { ++ Scoped sender( ++ g_strdup(g_dbus_connection_get_unique_name(connection) + 1)); ++ for (int i = 0; sender.get()[i]; ++i) { ++ if (sender.get()[i] == '.') { ++ sender.get()[i] = '_'; ++ } ++ } ++ ++ const char* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender.get(), ++ "/", token, /*end of varargs*/ nullptr); ++ ++ return handle; ++} ++ ++void ScreenCastPortal::SessionRequest() { ++ GVariantBuilder builder; ++ Scoped variant_string; ++ ++ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); ++ variant_string = ++ g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT)); ++ g_variant_builder_add(&builder, "{sv}", "session_handle_token", ++ g_variant_new_string(variant_string.get())); ++ variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); ++ g_variant_builder_add(&builder, "{sv}", "handle_token", ++ g_variant_new_string(variant_string.get())); ++ ++ portal_handle_ = PrepareSignalHandle(connection_, variant_string.get()); ++ session_request_signal_id_ = SetupRequestResponseSignal( ++ portal_handle_.c_str(), OnSessionRequestResponseSignal); ++ ++ RTC_LOG(LS_INFO) << "Screen cast session requested."; ++ g_dbus_proxy_call(proxy_, "CreateSession", g_variant_new("(a{sv})", &builder), ++ G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, ++ reinterpret_cast(OnSessionRequested), ++ this); ++} ++ ++// static ++void ScreenCastPortal::OnSessionRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ Scoped error; ++ Scoped variant( ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); ++ if (!variant) { ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ RTC_LOG(LS_ERROR) << "Failed to create a screen cast session: " ++ << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ RTC_LOG(LS_INFO) << "Initializing the screen cast session."; ++ ++ Scoped handle; ++ g_variant_get_child(variant.get(), 0, "o", &handle); ++ if (!handle) { ++ RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; ++ if (that->session_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(that->connection_, ++ that->session_request_signal_id_); ++ that->session_request_signal_id_ = 0; ++ } ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ RTC_LOG(LS_INFO) << "Subscribing to the screen cast session."; ++} ++ ++// static ++void ScreenCastPortal::OnSessionRequestResponseSignal( ++ GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_INFO) ++ << "Received response for the screen cast session subscription."; ++ ++ uint32_t portal_response; ++ Scoped response_data; ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, ++ response_data.receive()); ++ Scoped session_handle( ++ g_variant_lookup_value(response_data.get(), "session_handle", nullptr)); ++ that->session_handle_ = g_variant_dup_string(session_handle.get(), nullptr); ++ ++ if (that->session_handle_.empty() || portal_response) { ++ RTC_LOG(LS_ERROR) ++ << "Failed to request the screen cast session subscription."; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ that->session_closed_signal_id_ = g_dbus_connection_signal_subscribe( ++ that->connection_, kDesktopBusName, kSessionInterfaceName, "Closed", ++ that->session_handle_.c_str(), /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NONE, ++ OnSessionClosedSignal, that, /*user_data_free_func=*/nullptr); ++ ++ that->SourcesRequest(); ++} ++ ++// static ++void ScreenCastPortal::OnSessionClosedSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_INFO) << "Received closed signal from session."; ++ ++ that->notifier_->OnScreenCastSessionClosed(); ++ ++ // Unsubscribe from the signal and free the session handle to avoid calling ++ // Session::Close from the destructor since it's already closed ++ g_dbus_connection_signal_unsubscribe(that->connection_, ++ that->session_closed_signal_id_); ++} ++ ++void ScreenCastPortal::SourcesRequest() { ++ GVariantBuilder builder; ++ Scoped variant_string; ++ ++ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); ++ // We want to record monitor content. ++ g_variant_builder_add( ++ &builder, "{sv}", "types", ++ g_variant_new_uint32(static_cast(capture_source_type_))); ++ // We don't want to allow selection of multiple sources. ++ g_variant_builder_add(&builder, "{sv}", "multiple", ++ g_variant_new_boolean(false)); ++ ++ Scoped variant( ++ g_dbus_proxy_get_cached_property(proxy_, "AvailableCursorModes")); ++ if (variant.get()) { ++ uint32_t modes = 0; ++ g_variant_get(variant.get(), "u", &modes); ++ // Make request only if this mode is advertised by the portal ++ // implementation. ++ if (modes & static_cast(cursor_mode_)) { ++ g_variant_builder_add( ++ &builder, "{sv}", "cursor_mode", ++ g_variant_new_uint32(static_cast(cursor_mode_))); ++ } ++ } ++ ++ variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); ++ g_variant_builder_add(&builder, "{sv}", "handle_token", ++ g_variant_new_string(variant_string.get())); ++ ++ sources_handle_ = PrepareSignalHandle(connection_, variant_string.get()); ++ sources_request_signal_id_ = SetupRequestResponseSignal( ++ sources_handle_.c_str(), OnSourcesRequestResponseSignal); ++ ++ RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; ++ g_dbus_proxy_call( ++ proxy_, "SelectSources", ++ g_variant_new("(oa{sv})", session_handle_.c_str(), &builder), ++ G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, ++ reinterpret_cast(OnSourcesRequested), this); ++} ++ ++// static ++void ScreenCastPortal::OnSourcesRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ Scoped error; ++ Scoped variant( ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); ++ if (!variant) { ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ RTC_LOG(LS_ERROR) << "Failed to request the sources: " << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ RTC_LOG(LS_INFO) << "Sources requested from the screen cast session."; ++ ++ Scoped handle; ++ g_variant_get_child(variant.get(), 0, "o", handle.receive()); ++ if (!handle) { ++ RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; ++ if (that->sources_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(that->connection_, ++ that->sources_request_signal_id_); ++ that->sources_request_signal_id_ = 0; ++ } ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ RTC_LOG(LS_INFO) << "Subscribed to sources signal."; ++} ++ ++// static ++void ScreenCastPortal::OnSourcesRequestResponseSignal( ++ GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_INFO) << "Received sources signal from session."; ++ ++ uint32_t portal_response; ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, nullptr); ++ if (portal_response) { ++ RTC_LOG(LS_ERROR) ++ << "Failed to select sources for the screen cast session."; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ that->StartRequest(); ++} ++ ++void ScreenCastPortal::StartRequest() { ++ GVariantBuilder builder; ++ Scoped variant_string; ++ ++ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); ++ variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); ++ g_variant_builder_add(&builder, "{sv}", "handle_token", ++ g_variant_new_string(variant_string.get())); ++ ++ start_handle_ = PrepareSignalHandle(connection_, variant_string.get()); ++ start_request_signal_id_ = SetupRequestResponseSignal( ++ start_handle_.c_str(), OnStartRequestResponseSignal); ++ ++ // "Identifier for the application window", this is Wayland, so not "x11:...". ++ const char parent_window[] = ""; ++ ++ RTC_LOG(LS_INFO) << "Starting the screen cast session."; ++ g_dbus_proxy_call(proxy_, "Start", ++ g_variant_new("(osa{sv})", session_handle_.c_str(), ++ parent_window, &builder), ++ G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, cancellable_, ++ reinterpret_cast(OnStartRequested), ++ this); ++} ++ ++// static ++void ScreenCastPortal::OnStartRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ Scoped error; ++ Scoped variant( ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); ++ if (!variant) { ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ RTC_LOG(LS_ERROR) << "Failed to start the screen cast session: " ++ << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ RTC_LOG(LS_INFO) << "Initializing the start of the screen cast session."; ++ ++ Scoped handle; ++ g_variant_get_child(variant.get(), 0, "o", handle.receive()); ++ if (!handle) { ++ RTC_LOG(LS_ERROR) ++ << "Failed to initialize the start of the screen cast session."; ++ if (that->start_request_signal_id_) { ++ g_dbus_connection_signal_unsubscribe(that->connection_, ++ that->start_request_signal_id_); ++ that->start_request_signal_id_ = 0; ++ } ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ RTC_LOG(LS_INFO) << "Subscribed to the start signal."; ++} ++ ++// static ++void ScreenCastPortal::OnStartRequestResponseSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_INFO) << "Start signal received."; ++ uint32_t portal_response; ++ Scoped response_data; ++ Scoped iter; ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, ++ response_data.receive()); ++ if (portal_response || !response_data) { ++ RTC_LOG(LS_ERROR) << "Failed to start the screen cast session."; ++ that->PortalFailed(static_cast(portal_response)); ++ return; ++ } ++ ++ // Array of PipeWire streams. See ++ // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml ++ // documentation for . ++ if (g_variant_lookup(response_data.get(), "streams", "a(ua{sv})", ++ iter.receive())) { ++ Scoped variant; ++ ++ while (g_variant_iter_next(iter.get(), "@(ua{sv})", variant.receive())) { ++ uint32_t stream_id; ++ uint32_t type; ++ Scoped options; ++ ++ g_variant_get(variant.get(), "(u@a{sv})", &stream_id, options.receive()); ++ RTC_DCHECK(options.get()); ++ ++ if (g_variant_lookup(options.get(), "source_type", "u", &type)) { ++ that->capture_source_type_ = ++ static_cast(type); ++ } ++ ++ that->pw_stream_node_id_ = stream_id; ++ ++ break; ++ } ++ } ++ ++ that->OpenPipeWireRemote(); ++} ++ ++void ScreenCastPortal::OpenPipeWireRemote() { ++ GVariantBuilder builder; ++ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); ++ ++ RTC_LOG(LS_INFO) << "Opening the PipeWire remote."; ++ ++ g_dbus_proxy_call_with_unix_fd_list( ++ proxy_, "OpenPipeWireRemote", ++ g_variant_new("(oa{sv})", session_handle_.c_str(), &builder), ++ G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*fd_list=*/nullptr, cancellable_, ++ reinterpret_cast(OnOpenPipeWireRemoteRequested), ++ this); ++} ++ ++// static ++void ScreenCastPortal::OnOpenPipeWireRemoteRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data) { ++ ScreenCastPortal* that = static_cast(user_data); ++ RTC_DCHECK(that); ++ ++ Scoped error; ++ Scoped outlist; ++ Scoped variant(g_dbus_proxy_call_with_unix_fd_list_finish( ++ proxy, outlist.receive(), result, error.receive())); ++ if (!variant) { ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ RTC_LOG(LS_ERROR) << "Failed to open the PipeWire remote: " ++ << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ int32_t index; ++ g_variant_get(variant.get(), "(h)", &index); ++ ++ that->pw_fd_ = g_unix_fd_list_get(outlist.get(), index, error.receive()); ++ ++ if (that->pw_fd_ == -1) { ++ RTC_LOG(LS_ERROR) << "Failed to get file descriptor from the list: " ++ << error->message; ++ that->PortalFailed(RequestResponse::kError); ++ return; ++ } ++ ++ that->notifier_->OnScreenCastRequestResult( ++ ScreenCastPortal::RequestResponse::kSuccess, that->pw_stream_node_id_, ++ that->pw_fd_); ++} ++ ++} // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/screencast_portal.h 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,169 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCREENCAST_PORTAL_H_ ++#define MODULES_DESKTOP_CAPTURE_LINUX_SCREENCAST_PORTAL_H_ ++ ++#include ++ ++#include ++ ++#include "absl/types/optional.h" ++ ++namespace webrtc { ++ ++class ScreenCastPortal { ++ public: ++ // Values are set based on source type property in ++ // xdg-desktop-portal/screencast ++ // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml ++ enum class CaptureSourceType : uint32_t { ++ kScreen = 0b01, ++ kWindow = 0b10, ++ kAnyScreenContent = kScreen | kWindow ++ }; ++ ++ // Values are set based on cursor mode property in ++ // xdg-desktop-portal/screencast ++ // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml ++ enum class CursorMode : uint32_t { ++ // Mouse cursor will not be included in any form ++ kHidden = 0b01, ++ // Mouse cursor will be part of the screen content ++ kEmbedded = 0b10, ++ // Mouse cursor information will be send separately in form of metadata ++ kMetadata = 0b100 ++ }; ++ ++ // Interface that must be implemented by the ScreenCastPortal consumers. ++ enum class RequestResponse { ++ // Success, the request is carried out. ++ kSuccess, ++ // The user cancelled the interaction. ++ kUserCancelled, ++ // The user interaction was ended in some other way. ++ kError, ++ ++ kMaxValue = kError ++ }; ++ ++ class PortalNotifier { ++ public: ++ virtual void OnScreenCastRequestResult(RequestResponse result, ++ uint32_t stream_node_id, ++ int fd) = 0; ++ virtual void OnScreenCastSessionClosed() = 0; ++ ++ protected: ++ PortalNotifier() = default; ++ virtual ~PortalNotifier() = default; ++ }; ++ ++ explicit ScreenCastPortal(CaptureSourceType source_type, ++ PortalNotifier* notifier); ++ ~ScreenCastPortal(); ++ ++ // Initialize ScreenCastPortal with series of DBus calls where we try to ++ // obtain all the required information, like PipeWire file descriptor and ++ // PipeWire stream node ID. ++ // ++ // The observer will return whether the communication with xdg-desktop-portal ++ // was successful and only then you will be able to get all the required ++ // information in order to continue working with PipeWire. ++ void Start(); ++ ++ private: ++ PortalNotifier* notifier_; ++ ++ // A PipeWire stream ID of stream we will be connecting to ++ uint32_t pw_stream_node_id_ = 0; ++ // A file descriptor of PipeWire socket ++ int pw_fd_ = -1; ++ ++ CaptureSourceType capture_source_type_ = ++ ScreenCastPortal::CaptureSourceType::kScreen; ++ ++ CursorMode cursor_mode_ = ScreenCastPortal::CursorMode::kMetadata; ++ ++ GDBusConnection* connection_ = nullptr; ++ GDBusProxy* proxy_ = nullptr; ++ GCancellable* cancellable_ = nullptr; ++ std::string portal_handle_; ++ std::string session_handle_; ++ std::string sources_handle_; ++ std::string start_handle_; ++ guint session_request_signal_id_ = 0; ++ guint sources_request_signal_id_ = 0; ++ guint start_request_signal_id_ = 0; ++ guint session_closed_signal_id_ = 0; ++ ++ void PortalFailed(RequestResponse result); ++ ++ uint32_t SetupRequestResponseSignal(const char* object_path, ++ GDBusSignalCallback callback); ++ ++ static void OnProxyRequested(GObject* object, ++ GAsyncResult* result, ++ gpointer user_data); ++ ++ static std::string PrepareSignalHandle(GDBusConnection* connection, ++ const char* token); ++ ++ void SessionRequest(); ++ static void OnSessionRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data); ++ static void OnSessionRequestResponseSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data); ++ static void OnSessionClosedSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data); ++ void SourcesRequest(); ++ static void OnSourcesRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data); ++ static void OnSourcesRequestResponseSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data); ++ ++ void StartRequest(); ++ static void OnStartRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data); ++ static void OnStartRequestResponseSignal(GDBusConnection* connection, ++ const char* sender_name, ++ const char* object_path, ++ const char* interface_name, ++ const char* signal_name, ++ GVariant* parameters, ++ gpointer user_data); ++ ++ void OpenPipeWireRemote(); ++ static void OnOpenPipeWireRemoteRequested(GDBusProxy* proxy, ++ GAsyncResult* result, ++ gpointer user_data); ++}; ++ ++} // namespace webrtc ++ ++#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCREENCAST_PORTAL_H_ +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,892 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#include "modules/desktop_capture/linux/shared_screencast_stream.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "absl/memory/memory.h" ++#include "modules/desktop_capture/linux/egl_dmabuf.h" ++#include "modules/desktop_capture/screen_capture_frame_queue.h" ++#include "rtc_base/checks.h" ++#include "rtc_base/logging.h" ++#include "rtc_base/sanitizer.h" ++#include "rtc_base/string_encode.h" ++#include "rtc_base/string_to_number.h" ++#include "rtc_base/synchronization/mutex.h" ++ ++#if defined(WEBRTC_DLOPEN_PIPEWIRE) ++#include "modules/desktop_capture/linux/pipewire_stubs.h" ++using modules_desktop_capture_linux_wayland::InitializeStubs; ++using modules_desktop_capture_linux_wayland::kModuleDrm; ++using modules_desktop_capture_linux_wayland::kModulePipewire; ++using modules_desktop_capture_linux_wayland::StubPathMap; ++#endif // defined(WEBRTC_DLOPEN_PIPEWIRE) ++ ++namespace webrtc { ++ ++const int kBytesPerPixel = 4; ++ ++#if defined(WEBRTC_DLOPEN_PIPEWIRE) ++const char kPipeWireLib[] = "libpipewire-0.3.so.0"; ++const char kDrmLib[] = "libdrm.so.2"; ++#endif ++ ++#if !PW_CHECK_VERSION(0, 3, 29) ++#define SPA_POD_PROP_FLAG_MANDATORY (1u << 3) ++#endif ++#if !PW_CHECK_VERSION(0, 3, 33) ++#define SPA_POD_PROP_FLAG_DONT_FIXATE (1u << 4) ++#endif ++ ++constexpr int kCursorBpp = 4; ++constexpr int CursorMetaSize(int w, int h) { ++ return (sizeof(struct spa_meta_cursor) + sizeof(struct spa_meta_bitmap) + ++ w * h * kCursorBpp); ++} ++ ++struct PipeWireVersion { ++ int major = 0; ++ int minor = 0; ++ int micro = 0; ++}; ++ ++constexpr PipeWireVersion kDmaBufMinVersion = {0, 3, 24}; ++constexpr PipeWireVersion kDmaBufModifierMinVersion = {0, 3, 33}; ++constexpr PipeWireVersion kDropSingleModifierMinVersion = {0, 3, 40}; ++ ++PipeWireVersion ParsePipeWireVersion(const char* version) { ++ std::vector parsed_version; ++ rtc::split(version, '.', &parsed_version); ++ ++ if (parsed_version.size() != 3) { ++ return {}; ++ } ++ ++ absl::optional major = rtc::StringToNumber(parsed_version.at(0)); ++ absl::optional minor = rtc::StringToNumber(parsed_version.at(1)); ++ absl::optional micro = rtc::StringToNumber(parsed_version.at(2)); ++ ++ // Return invalid version if we failed to parse it ++ if (!major || !minor || !micro) { ++ return {0, 0, 0}; ++ } ++ ++ return {major.value(), micro.value(), micro.value()}; ++} ++ ++spa_pod* BuildFormat(spa_pod_builder* builder, ++ uint32_t format, ++ const std::vector& modifiers) { ++ bool first = true; ++ spa_pod_frame frames[2]; ++ spa_rectangle pw_min_screen_bounds = spa_rectangle{1, 1}; ++ spa_rectangle pw_max_screen_bounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; ++ ++ spa_pod_builder_push_object(builder, &frames[0], SPA_TYPE_OBJECT_Format, ++ SPA_PARAM_EnumFormat); ++ spa_pod_builder_add(builder, SPA_FORMAT_mediaType, ++ SPA_POD_Id(SPA_MEDIA_TYPE_video), 0); ++ spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype, ++ SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 0); ++ spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(format), 0); ++ ++ if (modifiers.size()) { ++ if (modifiers.size() == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { ++ spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier, ++ SPA_POD_PROP_FLAG_MANDATORY); ++ spa_pod_builder_long(builder, modifiers[0]); ++ } else { ++ spa_pod_builder_prop( ++ builder, SPA_FORMAT_VIDEO_modifier, ++ SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE); ++ spa_pod_builder_push_choice(builder, &frames[1], SPA_CHOICE_Enum, 0); ++ ++ // modifiers from the array ++ for (int64_t val : modifiers) { ++ spa_pod_builder_long(builder, val); ++ // Add the first modifier twice as the very first value is the default ++ // option ++ if (first) { ++ spa_pod_builder_long(builder, val); ++ first = false; ++ } ++ } ++ spa_pod_builder_pop(builder, &frames[1]); ++ } ++ } ++ ++ spa_pod_builder_add( ++ builder, SPA_FORMAT_VIDEO_size, ++ SPA_POD_CHOICE_RANGE_Rectangle( ++ &pw_min_screen_bounds, &pw_min_screen_bounds, &pw_max_screen_bounds), ++ 0); ++ ++ return static_cast(spa_pod_builder_pop(builder, &frames[0])); ++} ++ ++class PipeWireThreadLoopLock { ++ public: ++ explicit PipeWireThreadLoopLock(pw_thread_loop* loop) : loop_(loop) { ++ pw_thread_loop_lock(loop_); ++ } ++ ~PipeWireThreadLoopLock() { pw_thread_loop_unlock(loop_); } ++ ++ private: ++ pw_thread_loop* const loop_; ++}; ++ ++class ScopedBuf { ++ public: ++ ScopedBuf() {} ++ ScopedBuf(uint8_t* map, int map_size, int fd) ++ : map_(map), map_size_(map_size), fd_(fd) {} ++ ~ScopedBuf() { ++ if (map_ != MAP_FAILED) { ++ munmap(map_, map_size_); ++ } ++ } ++ ++ explicit operator bool() { return map_ != MAP_FAILED; } ++ ++ void initialize(uint8_t* map, int map_size, int fd) { ++ map_ = map; ++ map_size_ = map_size; ++ fd_ = fd; ++ } ++ ++ uint8_t* get() { return map_; } ++ ++ protected: ++ uint8_t* map_ = static_cast(MAP_FAILED); ++ int map_size_; ++ int fd_; ++}; ++ ++class SharedScreenCastStreamPrivate { ++ public: ++ SharedScreenCastStreamPrivate(); ++ ~SharedScreenCastStreamPrivate(); ++ ++ bool StartScreenCastStream(uint32_t stream_node_id, int fd); ++ void StopScreenCastStream(); ++ std::unique_ptr CaptureFrame(); ++ std::unique_ptr CaptureCursor(); ++ DesktopVector CaptureCursorPosition(); ++ ++ private: ++ uint32_t pw_stream_node_id_ = 0; ++ int pw_fd_ = -1; ++ ++ DesktopSize desktop_size_ = {}; ++ DesktopSize video_size_; ++ ++ webrtc::Mutex queue_lock_; ++ ScreenCaptureFrameQueue queue_ ++ RTC_GUARDED_BY(&queue_lock_); ++ std::unique_ptr mouse_cursor_; ++ DesktopVector mouse_cursor_position_ = DesktopVector(-1, -1); ++ ++ int64_t modifier_; ++ std::unique_ptr egl_dmabuf_; ++ // List of modifiers we query as supported by the graphics card/driver ++ std::vector modifiers_; ++ ++ // PipeWire types ++ struct pw_context* pw_context_ = nullptr; ++ struct pw_core* pw_core_ = nullptr; ++ struct pw_stream* pw_stream_ = nullptr; ++ struct pw_thread_loop* pw_main_loop_ = nullptr; ++ struct spa_source* renegotiate_ = nullptr; ++ ++ spa_hook spa_core_listener_; ++ spa_hook spa_stream_listener_; ++ ++ // A number used to verify all previous methods and the resulting ++ // events have been handled. ++ int server_version_sync_ = 0; ++ // Version of the running PipeWire server we communicate with ++ PipeWireVersion pw_server_version_; ++ // Version of the library used to run our code ++ PipeWireVersion pw_client_version_; ++ ++ // event handlers ++ pw_core_events pw_core_events_ = {}; ++ pw_stream_events pw_stream_events_ = {}; ++ ++ struct spa_video_info_raw spa_video_format_; ++ ++ void ProcessBuffer(pw_buffer* buffer); ++ void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); ++ ++ // PipeWire callbacks ++ static void OnCoreError(void* data, ++ uint32_t id, ++ int seq, ++ int res, ++ const char* message); ++ static void OnCoreDone(void* user_data, uint32_t id, int seq); ++ static void OnCoreInfo(void* user_data, const pw_core_info* info); ++ static void OnStreamParamChanged(void* data, ++ uint32_t id, ++ const struct spa_pod* format); ++ static void OnStreamStateChanged(void* data, ++ pw_stream_state old_state, ++ pw_stream_state state, ++ const char* error_message); ++ static void OnStreamProcess(void* data); ++ // This will be invoked in case we fail to process DMA-BUF PW buffer using ++ // negotiated stream parameters (modifier). We will drop the modifier we ++ // failed to use and try to use a different one or fallback to shared memory ++ // buffers. ++ static void OnRenegotiateFormat(void* data, uint64_t); ++}; ++ ++bool operator>=(const PipeWireVersion& current_pw_version, ++ const PipeWireVersion& required_pw_version) { ++ if (!current_pw_version.major && !current_pw_version.minor && ++ !current_pw_version.micro) { ++ return false; ++ } ++ ++ return std::tie(current_pw_version.major, current_pw_version.minor, ++ current_pw_version.micro) >= ++ std::tie(required_pw_version.major, required_pw_version.minor, ++ required_pw_version.micro); ++} ++ ++bool operator<=(const PipeWireVersion& current_pw_version, ++ const PipeWireVersion& required_pw_version) { ++ if (!current_pw_version.major && !current_pw_version.minor && ++ !current_pw_version.micro) { ++ return false; ++ } ++ ++ return std::tie(current_pw_version.major, current_pw_version.minor, ++ current_pw_version.micro) <= ++ std::tie(required_pw_version.major, required_pw_version.minor, ++ required_pw_version.micro); ++} ++ ++void SharedScreenCastStreamPrivate::OnCoreError(void* data, ++ uint32_t id, ++ int seq, ++ int res, ++ const char* message) { ++ SharedScreenCastStreamPrivate* that = ++ static_cast(data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_ERROR) << "PipeWire remote error: " << message; ++} ++ ++void SharedScreenCastStreamPrivate::OnCoreInfo(void* data, ++ const pw_core_info* info) { ++ SharedScreenCastStreamPrivate* stream = ++ static_cast(data); ++ RTC_DCHECK(stream); ++ ++ stream->pw_server_version_ = ParsePipeWireVersion(info->version); ++} ++ ++void SharedScreenCastStreamPrivate::OnCoreDone(void* data, ++ uint32_t id, ++ int seq) { ++ const SharedScreenCastStreamPrivate* stream = ++ static_cast(data); ++ RTC_DCHECK(stream); ++ ++ if (id == PW_ID_CORE && stream->server_version_sync_ == seq) { ++ pw_thread_loop_signal(stream->pw_main_loop_, false); ++ } ++} ++ ++// static ++void SharedScreenCastStreamPrivate::OnStreamStateChanged( ++ void* data, ++ pw_stream_state old_state, ++ pw_stream_state state, ++ const char* error_message) { ++ SharedScreenCastStreamPrivate* that = ++ static_cast(data); ++ RTC_DCHECK(that); ++ ++ switch (state) { ++ case PW_STREAM_STATE_ERROR: ++ RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; ++ break; ++ case PW_STREAM_STATE_PAUSED: ++ case PW_STREAM_STATE_STREAMING: ++ case PW_STREAM_STATE_UNCONNECTED: ++ case PW_STREAM_STATE_CONNECTING: ++ break; ++ } ++} ++ ++// static ++void SharedScreenCastStreamPrivate::OnStreamParamChanged( ++ void* data, ++ uint32_t id, ++ const struct spa_pod* format) { ++ SharedScreenCastStreamPrivate* that = ++ static_cast(data); ++ RTC_DCHECK(that); ++ ++ RTC_LOG(LS_INFO) << "PipeWire stream format changed."; ++ if (!format || id != SPA_PARAM_Format) { ++ return; ++ } ++ ++ spa_format_video_raw_parse(format, &that->spa_video_format_); ++ ++ auto width = that->spa_video_format_.size.width; ++ auto height = that->spa_video_format_.size.height; ++ auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); ++ auto size = height * stride; ++ ++ that->desktop_size_ = DesktopSize(width, height); ++ ++ uint8_t buffer[1024] = {}; ++ auto builder = spa_pod_builder{buffer, sizeof(buffer)}; ++ ++ // Setup buffers and meta header for new format. ++ ++ // When SPA_FORMAT_VIDEO_modifier is present we can use DMA-BUFs as ++ // the server announces support for it. ++ // See https://github.com/PipeWire/pipewire/blob/master/doc/dma-buf.dox ++ const bool has_modifier = ++ spa_pod_find_prop(format, nullptr, SPA_FORMAT_VIDEO_modifier); ++ that->modifier_ = ++ has_modifier ? that->spa_video_format_.modifier : DRM_FORMAT_MOD_INVALID; ++ std::vector params; ++ const int buffer_types = ++ has_modifier || (that->pw_server_version_ >= kDmaBufMinVersion) ++ ? (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | ++ (1 << SPA_DATA_MemPtr) ++ : (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr); ++ ++ params.push_back(reinterpret_cast(spa_pod_builder_add_object( ++ &builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, ++ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), SPA_PARAM_BUFFERS_stride, ++ SPA_POD_Int(stride), SPA_PARAM_BUFFERS_buffers, ++ SPA_POD_CHOICE_RANGE_Int(8, 1, 32), SPA_PARAM_BUFFERS_dataType, ++ SPA_POD_CHOICE_FLAGS_Int(buffer_types)))); ++ params.push_back(reinterpret_cast(spa_pod_builder_add_object( ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, ++ SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, ++ SPA_POD_Int(sizeof(struct spa_meta_header))))); ++ params.push_back(reinterpret_cast(spa_pod_builder_add_object( ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, ++ SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size, ++ SPA_POD_Int(sizeof(struct spa_meta_region))))); ++ params.push_back(reinterpret_cast(spa_pod_builder_add_object( ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, ++ SPA_POD_Id(SPA_META_Cursor), SPA_PARAM_META_size, ++ SPA_POD_CHOICE_RANGE_Int(CursorMetaSize(64, 64), CursorMetaSize(1, 1), ++ CursorMetaSize(384, 384))))); ++ params.push_back(reinterpret_cast(spa_pod_builder_add_object( ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, ++ SPA_POD_Id(SPA_META_VideoDamage), SPA_PARAM_META_size, ++ SPA_POD_CHOICE_RANGE_Int(sizeof(struct spa_meta_region) * 16, ++ sizeof(struct spa_meta_region) * 1, ++ sizeof(struct spa_meta_region) * 16)))); ++ ++ pw_stream_update_params(that->pw_stream_, params.data(), params.size()); ++} ++ ++// static ++void SharedScreenCastStreamPrivate::OnStreamProcess(void* data) { ++ SharedScreenCastStreamPrivate* that = ++ static_cast(data); ++ RTC_DCHECK(that); ++ ++ struct pw_buffer* next_buffer; ++ struct pw_buffer* buffer = nullptr; ++ ++ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); ++ while (next_buffer) { ++ buffer = next_buffer; ++ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); ++ ++ if (next_buffer) { ++ pw_stream_queue_buffer(that->pw_stream_, buffer); ++ } ++ } ++ ++ if (!buffer) { ++ return; ++ } ++ ++ that->ProcessBuffer(buffer); ++ ++ pw_stream_queue_buffer(that->pw_stream_, buffer); ++} ++ ++void SharedScreenCastStreamPrivate::OnRenegotiateFormat(void* data, uint64_t) { ++ SharedScreenCastStreamPrivate* that = ++ static_cast(data); ++ RTC_DCHECK(that); ++ ++ { ++ PipeWireThreadLoopLock thread_loop_lock(that->pw_main_loop_); ++ ++ uint8_t buffer[2048] = {}; ++ ++ spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; ++ ++ std::vector params; ++ ++ for (uint32_t format : {SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA, ++ SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) { ++ if (!that->modifiers_.empty()) { ++ params.push_back(BuildFormat(&builder, format, that->modifiers_)); ++ } ++ params.push_back(BuildFormat(&builder, format, /*modifiers=*/{})); ++ } ++ ++ pw_stream_update_params(that->pw_stream_, params.data(), params.size()); ++ } ++} ++ ++SharedScreenCastStreamPrivate::SharedScreenCastStreamPrivate() {} ++ ++SharedScreenCastStreamPrivate::~SharedScreenCastStreamPrivate() { ++ if (pw_main_loop_) { ++ pw_thread_loop_stop(pw_main_loop_); ++ } ++ ++ if (pw_stream_) { ++ pw_stream_destroy(pw_stream_); ++ } ++ ++ if (pw_core_) { ++ pw_core_disconnect(pw_core_); ++ } ++ ++ if (pw_context_) { ++ pw_context_destroy(pw_context_); ++ } ++ ++ if (pw_main_loop_) { ++ pw_thread_loop_destroy(pw_main_loop_); ++ } ++} ++ ++bool SharedScreenCastStreamPrivate::StartScreenCastStream( ++ uint32_t stream_node_id, ++ int fd) { ++#if defined(WEBRTC_DLOPEN_PIPEWIRE) ++ StubPathMap paths; ++ ++ // Check if the PipeWire and DRM libraries are available. ++ paths[kModulePipewire].push_back(kPipeWireLib); ++ paths[kModuleDrm].push_back(kDrmLib); ++ ++ if (!InitializeStubs(paths)) { ++ RTC_LOG(LS_ERROR) ++ << "One of following libraries is missing on your system:\n" ++ << " - PipeWire (" << kPipeWireLib << ")\n" ++ << " - drm (" << kDrmLib << ")"; ++ return false; ++ } ++#endif // defined(WEBRTC_DLOPEN_PIPEWIRE) ++ egl_dmabuf_ = std::make_unique(); ++ ++ pw_stream_node_id_ = stream_node_id; ++ pw_fd_ = fd; ++ ++ pw_init(/*argc=*/nullptr, /*argc=*/nullptr); ++ ++ pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); ++ ++ pw_context_ = ++ pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); ++ if (!pw_context_) { ++ RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; ++ return false; ++ } ++ ++ if (pw_thread_loop_start(pw_main_loop_) < 0) { ++ RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; ++ return false; ++ } ++ ++ pw_client_version_ = ParsePipeWireVersion(pw_get_library_version()); ++ ++ // Initialize event handlers, remote end and stream-related. ++ pw_core_events_.version = PW_VERSION_CORE_EVENTS; ++ pw_core_events_.info = &OnCoreInfo; ++ pw_core_events_.done = &OnCoreDone; ++ pw_core_events_.error = &OnCoreError; ++ ++ pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; ++ pw_stream_events_.state_changed = &OnStreamStateChanged; ++ pw_stream_events_.param_changed = &OnStreamParamChanged; ++ pw_stream_events_.process = &OnStreamProcess; ++ ++ { ++ PipeWireThreadLoopLock thread_loop_lock(pw_main_loop_); ++ ++ pw_core_ = pw_context_connect_fd(pw_context_, pw_fd_, nullptr, 0); ++ if (!pw_core_) { ++ RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; ++ return false; ++ } ++ ++ pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this); ++ ++ // Add an event that can be later invoked by pw_loop_signal_event() ++ renegotiate_ = pw_loop_add_event(pw_thread_loop_get_loop(pw_main_loop_), ++ OnRenegotiateFormat, this); ++ ++ server_version_sync_ = ++ pw_core_sync(pw_core_, PW_ID_CORE, server_version_sync_); ++ ++ pw_thread_loop_wait(pw_main_loop_); ++ ++ pw_properties* reuseProps = ++ pw_properties_new_string("pipewire.client.reuse=1"); ++ pw_stream_ = pw_stream_new(pw_core_, "webrtc-consume-stream", reuseProps); ++ ++ if (!pw_stream_) { ++ RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; ++ return false; ++ } ++ ++ pw_stream_add_listener(pw_stream_, &spa_stream_listener_, ++ &pw_stream_events_, this); ++ uint8_t buffer[2048] = {}; ++ ++ spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; ++ ++ std::vector params; ++ const bool has_required_pw_client_version = ++ pw_client_version_ >= kDmaBufModifierMinVersion; ++ const bool has_required_pw_server_version = ++ pw_server_version_ >= kDmaBufModifierMinVersion; ++ for (uint32_t format : {SPA_VIDEO_FORMAT_BGRA, SPA_VIDEO_FORMAT_RGBA, ++ SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx}) { ++ // Modifiers can be used with PipeWire >= 0.3.33 ++ if (has_required_pw_client_version && has_required_pw_server_version) { ++ modifiers_ = egl_dmabuf_->QueryDmaBufModifiers(format); ++ ++ if (!modifiers_.empty()) { ++ params.push_back(BuildFormat(&builder, format, modifiers_)); ++ } ++ } ++ ++ params.push_back(BuildFormat(&builder, format, /*modifiers=*/{})); ++ } ++ ++ if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, pw_stream_node_id_, ++ PW_STREAM_FLAG_AUTOCONNECT, params.data(), ++ params.size()) != 0) { ++ RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; ++ return false; ++ } ++ ++ RTC_LOG(LS_INFO) << "PipeWire remote opened."; ++ } ++ return true; ++} ++ ++void SharedScreenCastStreamPrivate::StopScreenCastStream() { ++ if (pw_stream_) { ++ pw_stream_disconnect(pw_stream_); ++ } ++} ++ ++std::unique_ptr SharedScreenCastStreamPrivate::CaptureFrame() { ++ webrtc::MutexLock lock(&queue_lock_); ++ ++ if (!queue_.current_frame()) { ++ return std::unique_ptr{}; ++ } ++ ++ std::unique_ptr frame = queue_.current_frame()->Share(); ++ return std::move(frame); ++} ++ ++std::unique_ptr SharedScreenCastStreamPrivate::CaptureCursor() { ++ if (!mouse_cursor_) { ++ return nullptr; ++ } ++ ++ return std::move(mouse_cursor_); ++} ++ ++DesktopVector SharedScreenCastStreamPrivate::CaptureCursorPosition() { ++ return mouse_cursor_position_; ++} ++ ++void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { ++ spa_buffer* spa_buffer = buffer->buffer; ++ ScopedBuf map; ++ std::unique_ptr src_unique_ptr; ++ uint8_t* src = nullptr; ++ ++ // Try to update the mouse cursor first, because it can be the only ++ // information carried by the buffer ++ { ++ const struct spa_meta_cursor* cursor = ++ static_cast(spa_buffer_find_meta_data( ++ spa_buffer, SPA_META_Cursor, sizeof(*cursor))); ++ if (cursor && spa_meta_cursor_is_valid(cursor)) { ++ struct spa_meta_bitmap* bitmap = nullptr; ++ ++ if (cursor->bitmap_offset) ++ bitmap = ++ SPA_MEMBER(cursor, cursor->bitmap_offset, struct spa_meta_bitmap); ++ ++ if (bitmap && bitmap->size.width > 0 && bitmap->size.height > 0) { ++ const uint8_t* bitmap_data = ++ SPA_MEMBER(bitmap, bitmap->offset, uint8_t); ++ BasicDesktopFrame* mouse_frame = new BasicDesktopFrame( ++ DesktopSize(bitmap->size.width, bitmap->size.height)); ++ mouse_frame->CopyPixelsFrom( ++ bitmap_data, bitmap->stride, ++ DesktopRect::MakeWH(bitmap->size.width, bitmap->size.height)); ++ mouse_cursor_ = std::make_unique( ++ mouse_frame, DesktopVector(cursor->hotspot.x, cursor->hotspot.y)); ++ } ++ mouse_cursor_position_.set(cursor->position.x, cursor->position.y); ++ } ++ } ++ ++ if (spa_buffer->datas[0].chunk->size == 0) { ++ return; ++ } ++ ++ if (spa_buffer->datas[0].type == SPA_DATA_MemFd) { ++ map.initialize( ++ static_cast( ++ mmap(nullptr, ++ spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset, ++ PROT_READ, MAP_PRIVATE, spa_buffer->datas[0].fd, 0)), ++ spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset, ++ spa_buffer->datas[0].fd); ++ ++ if (!map) { ++ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " ++ << std::strerror(errno); ++ return; ++ } ++ ++ src = SPA_MEMBER(map.get(), spa_buffer->datas[0].mapoffset, uint8_t); ++ } else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf) { ++ const uint n_planes = spa_buffer->n_datas; ++ ++ if (!n_planes) { ++ return; ++ } ++ ++ std::vector plane_datas; ++ for (uint32_t i = 0; i < n_planes; ++i) { ++ EglDmaBuf::PlaneData data = { ++ static_cast(spa_buffer->datas[i].fd), ++ static_cast(spa_buffer->datas[i].chunk->stride), ++ static_cast(spa_buffer->datas[i].chunk->offset)}; ++ plane_datas.push_back(data); ++ } ++ ++ // When importing DMA-BUFs, we use the stride (number of bytes from one row ++ // of pixels in the buffer) provided by PipeWire. The stride from PipeWire ++ // is given by the graphics driver and some drivers might add some ++ // additional padding for memory layout optimizations so not everytime the ++ // stride is equal to BYTES_PER_PIXEL x WIDTH. This is fine, because during ++ // the import we will use OpenGL and same graphics driver so it will be able ++ // to work with the stride it provided, but later on when we work with ++ // images we get from DMA-BUFs we will need to update the stride to be equal ++ // to BYTES_PER_PIXEL x WIDTH as that's the size of the DesktopFrame we ++ // allocate for each captured frame. ++ src_unique_ptr = egl_dmabuf_->ImageFromDmaBuf( ++ desktop_size_, spa_video_format_.format, plane_datas, modifier_); ++ if (src_unique_ptr) { ++ src = src_unique_ptr.get(); ++ } else { ++ RTC_LOG(LS_ERROR) << "Dropping DMA-BUF modifier: " << modifier_ ++ << " and trying to renegotiate stream parameters"; ++ ++ if (pw_server_version_ >= kDropSingleModifierMinVersion) { ++ modifiers_.erase( ++ std::remove(modifiers_.begin(), modifiers_.end(), modifier_), ++ modifiers_.end()); ++ } else { ++ modifiers_.clear(); ++ } ++ ++ pw_loop_signal_event(pw_thread_loop_get_loop(pw_main_loop_), ++ renegotiate_); ++ return; ++ } ++ } else if (spa_buffer->datas[0].type == SPA_DATA_MemPtr) { ++ src = static_cast(spa_buffer->datas[0].data); ++ } ++ ++ if (!src) { ++ return; ++ } ++ struct spa_meta_region* video_metadata = ++ static_cast(spa_buffer_find_meta_data( ++ spa_buffer, SPA_META_VideoCrop, sizeof(*video_metadata))); ++ ++ // Video size from metadata is bigger than an actual video stream size. ++ // The metadata are wrong or we should up-scale the video...in both cases ++ // just quit now. ++ if (video_metadata && (video_metadata->region.size.width > ++ static_cast(desktop_size_.width()) || ++ video_metadata->region.size.height > ++ static_cast(desktop_size_.height()))) { ++ RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; ++ return; ++ } ++ ++ // Use video metadata when video size from metadata is set and smaller than ++ // video stream size, so we need to adjust it. ++ bool video_metadata_use = false; ++ const struct spa_rectangle* video_metadata_size = ++ video_metadata ? &video_metadata->region.size : nullptr; ++ ++ if (video_metadata_size && video_metadata_size->width != 0 && ++ video_metadata_size->height != 0 && ++ (static_cast(video_metadata_size->width) < desktop_size_.width() || ++ static_cast(video_metadata_size->height) < ++ desktop_size_.height())) { ++ video_metadata_use = true; ++ } ++ ++ if (video_metadata_use) { ++ video_size_ = ++ DesktopSize(video_metadata_size->width, video_metadata_size->height); ++ } else { ++ video_size_ = desktop_size_; ++ } ++ ++ uint32_t y_offset = video_metadata_use && (video_metadata->region.position.y + ++ video_size_.height() <= ++ desktop_size_.height()) ++ ? video_metadata->region.position.y ++ : 0; ++ uint32_t x_offset = video_metadata_use && (video_metadata->region.position.x + ++ video_size_.width() <= ++ desktop_size_.width()) ++ ? video_metadata->region.position.x ++ : 0; ++ ++ const uint32_t frame_stride = kBytesPerPixel * desktop_size_.width(); ++ uint32_t stride = spa_buffer->datas[0].chunk->stride; ++ ++ if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf && stride > frame_stride) { ++ // When DMA-BUFs are used, sometimes spa_buffer->stride we get might ++ // contain additional padding, but after we import the buffer, the stride ++ // we used is no longer relevant and we should just calculate it based on ++ // width. For more context see https://crbug.com/1333304. ++ stride = frame_stride; ++ } ++ ++ uint8_t* updated_src = ++ src + (stride * y_offset) + (kBytesPerPixel * x_offset); ++ ++ webrtc::MutexLock lock(&queue_lock_); ++ ++ // Move to the next frame if the current one is being used and shared ++ if (queue_.current_frame() && queue_.current_frame()->IsShared()) { ++ queue_.MoveToNextFrame(); ++ if (queue_.current_frame() && queue_.current_frame()->IsShared()) { ++ RTC_LOG(LS_WARNING) ++ << "Failed to process PipeWire buffer: no available frame"; ++ return; ++ } ++ } ++ ++ if (!queue_.current_frame() || ++ !queue_.current_frame()->size().equals(video_size_)) { ++ std::unique_ptr frame(new BasicDesktopFrame( ++ DesktopSize(video_size_.width(), video_size_.height()))); ++ queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame))); ++ } ++ ++ queue_.current_frame()->CopyPixelsFrom( ++ updated_src, (stride - (kBytesPerPixel * x_offset)), ++ DesktopRect::MakeWH(video_size_.width(), video_size_.height())); ++ ++ if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || ++ spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { ++ uint8_t* tmp_src = queue_.current_frame()->data(); ++ for (int i = 0; i < video_size_.height(); ++i) { ++ // If both sides decided to go with the RGBx format we need to convert ++ // it to BGRx to match color format expected by WebRTC. ++ ConvertRGBxToBGRx(tmp_src, queue_.current_frame()->stride()); ++ tmp_src += queue_.current_frame()->stride(); ++ } ++ } ++} ++ ++void SharedScreenCastStreamPrivate::ConvertRGBxToBGRx(uint8_t* frame, ++ uint32_t size) { ++ for (uint32_t i = 0; i < size; i += 4) { ++ uint8_t tempR = frame[i]; ++ uint8_t tempB = frame[i + 2]; ++ frame[i] = tempB; ++ frame[i + 2] = tempR; ++ } ++} ++ ++SharedScreenCastStream::SharedScreenCastStream() ++ : private_(std::make_unique()) {} ++ ++SharedScreenCastStream::~SharedScreenCastStream() {} ++ ++rtc::scoped_refptr ++SharedScreenCastStream::CreateDefault() { ++ // Explicit new, to access non-public constructor. ++ return rtc::scoped_refptr(new SharedScreenCastStream()); ++} ++ ++bool SharedScreenCastStream::StartScreenCastStream(uint32_t stream_node_id, ++ int fd) { ++ return private_->StartScreenCastStream(stream_node_id, fd); ++} ++ ++void SharedScreenCastStream::StopScreenCastStream() { ++ private_->StopScreenCastStream(); ++} ++ ++std::unique_ptr SharedScreenCastStream::CaptureFrame() { ++ return private_->CaptureFrame(); ++} ++ ++std::unique_ptr SharedScreenCastStream::CaptureCursor() { ++ return private_->CaptureCursor(); ++} ++ ++absl::optional SharedScreenCastStream::CaptureCursorPosition() { ++ DesktopVector position = private_->CaptureCursorPosition(); ++ ++ // Consider only (x >= 0 and y >= 0) a valid position ++ if (position.x() < 0 || position.y() < 0) { ++ return absl::nullopt; ++ } ++ ++ return position; ++} ++ ++} // namespace webrtc +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.h.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.h +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.h.libwebrtc-screen-cast-sync 2022-07-28 11:45:30.320409004 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/linux/shared_screencast_stream.h 2022-07-28 11:45:30.320409004 +0200 +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2022 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. ++ */ ++ ++#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SHARED_SCREENCAST_STREAM_H_ ++#define MODULES_DESKTOP_CAPTURE_LINUX_SHARED_SCREENCAST_STREAM_H_ ++ ++#include ++ ++#include "absl/types/optional.h" ++#include "api/ref_counted_base.h" ++#include "api/scoped_refptr.h" ++#include "modules/desktop_capture/desktop_frame.h" ++#include "modules/desktop_capture/mouse_cursor.h" ++#include "rtc_base/system/rtc_export.h" ++ ++namespace webrtc { ++ ++class SharedScreenCastStreamPrivate; ++ ++class RTC_EXPORT SharedScreenCastStream ++ : public rtc::RefCountedBase { ++ public: ++ static rtc::scoped_refptr CreateDefault(); ++ ++ bool StartScreenCastStream(uint32_t stream_node_id, int fd); ++ void StopScreenCastStream(); ++ ++ // Below functions return the most recent information we get from a ++ // PipeWire buffer on each Process() callback. This assumes that we ++ // managed to successfuly connect to a PipeWire stream provided by the ++ // compositor (based on stream parameters). The cursor data are obtained ++ // from spa_meta_cursor stream metadata and therefore the cursor is not ++ // part of actual screen/window frame. ++ ++ // Returns the most recent screen/window frame we obtained from PipeWire ++ // buffer. Will return an empty frame in case we didn't manage to get a frame ++ // from PipeWire buffer. ++ std::unique_ptr CaptureFrame(); ++ ++ // Returns the most recent mouse cursor image. Will return an nullptr cursor ++ // in case we didn't manage to get a cursor from PipeWire buffer. NOTE: the ++ // cursor image might not be updated on every cursor location change, but ++ // actually only when its shape changes. ++ std::unique_ptr CaptureCursor(); ++ ++ // Returns the most recent mouse cursor position. Will not return a value in ++ // case we didn't manage to get it from PipeWire buffer. ++ absl::optional CaptureCursorPosition(); ++ ++ ~SharedScreenCastStream(); ++ ++ protected: ++ SharedScreenCastStream(); ++ ++ private: ++ SharedScreenCastStream(const SharedScreenCastStream&) = delete; ++ SharedScreenCastStream& operator=(const SharedScreenCastStream&) = delete; ++ ++ std::unique_ptr private_; ++}; ++ ++} // namespace webrtc ++ ++#endif // MODULES_DESKTOP_CAPTURE_LINUX_SHARED_SCREENCAST_STREAM_H_ +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc.libwebrtc-screen-cast-sync 2022-07-18 20:44:26.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -17,6 +17,10 @@ + #include "modules/desktop_capture/linux/mouse_cursor_monitor_x11.h" + #endif // defined(WEBRTC_USE_X11) + ++#if defined(WEBRTC_USE_PIPEWIRE) ++#include "modules/desktop_capture/linux/mouse_cursor_monitor_pipewire.h" ++#endif // defined(WEBRTC_USE_PIPEWIRE) ++ + namespace webrtc { + + // static +@@ -44,6 +48,13 @@ MouseCursorMonitor* MouseCursorMonitor:: + // static + std::unique_ptr MouseCursorMonitor::Create( + const DesktopCaptureOptions& options) { ++#if defined(WEBRTC_USE_PIPEWIRE) ++ if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland() && ++ options.screencast_stream()) { ++ return std::make_unique(options); ++ } ++#endif // defined(WEBRTC_USE_PIPEWIRE) ++ + #if defined(WEBRTC_USE_X11) + return MouseCursorMonitorX11::Create(options); + #else +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/screen_capturer_linux.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/screen_capturer_linux.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/screen_capturer_linux.cc.libwebrtc-screen-cast-sync 2022-07-18 20:44:33.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/screen_capturer_linux.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -14,7 +14,7 @@ + #include "modules/desktop_capture/desktop_capturer.h" + + #if defined(WEBRTC_USE_PIPEWIRE) +-#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" ++#include "modules/desktop_capture/linux/base_capturer_pipewire.h" + #endif // defined(WEBRTC_USE_PIPEWIRE) + + #if defined(WEBRTC_USE_X11) +@@ -28,7 +28,7 @@ std::unique_ptr Desktop + const DesktopCaptureOptions& options) { + #if defined(WEBRTC_USE_PIPEWIRE) + if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { +- return BaseCapturerPipeWire::CreateRawScreenCapturer(options); ++ return std::make_unique(options); + } + #endif // defined(WEBRTC_USE_PIPEWIRE) + +diff -up firefox-103.0/third_party/libwebrtc/modules/desktop_capture/window_capturer_linux.cc.libwebrtc-screen-cast-sync firefox-103.0/third_party/libwebrtc/modules/desktop_capture/window_capturer_linux.cc +--- firefox-103.0/third_party/libwebrtc/modules/desktop_capture/window_capturer_linux.cc.libwebrtc-screen-cast-sync 2022-07-18 20:44:26.000000000 +0200 ++++ firefox-103.0/third_party/libwebrtc/modules/desktop_capture/window_capturer_linux.cc 2022-07-28 11:45:30.320409004 +0200 +@@ -14,7 +14,7 @@ + #include "modules/desktop_capture/desktop_capturer.h" + + #if defined(WEBRTC_USE_PIPEWIRE) +-#include "modules/desktop_capture/linux/window_capturer_pipewire.h" ++#include "modules/desktop_capture/linux/base_capturer_pipewire.h" + #endif // defined(WEBRTC_USE_PIPEWIRE) + + #if defined(WEBRTC_USE_X11) +@@ -28,7 +28,7 @@ std::unique_ptr Desktop + const DesktopCaptureOptions& options) { + #if defined(WEBRTC_USE_PIPEWIRE) + if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { +- return BaseCapturerPipeWire::CreateRawWindowCapturer(options); ++ return std::make_unique(options); + } + #endif // defined(WEBRTC_USE_PIPEWIRE) + +diff -up firefox-103.0/third_party/moz.build.libwebrtc-screen-cast-sync firefox-103.0/third_party/moz.build +--- firefox-103.0/third_party/moz.build.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/moz.build 2022-07-28 11:45:30.321408998 +0200 +@@ -61,6 +61,12 @@ with Files("libwebrtc/**"): + with Files("pipewire/**"): + BUG_COMPONENT = ("Core", "WebRTC") + ++with Files("drm/**"): ++ BUG_COMPONENT = ("Core", "WebRTC") ++ ++with Files("gbm/**"): ++ BUG_COMPONENT = ("Core", "WebRTC") ++ + with Files('rlbox_wasm2c_sandbox/**'): + BUG_COMPONENT = ('Firefox Build System', 'General') + +diff -up firefox-103.0/third_party/pipewire/libpipewire/mozpipewire.cpp.libwebrtc-screen-cast-sync firefox-103.0/third_party/pipewire/libpipewire/mozpipewire.cpp +--- firefox-103.0/third_party/pipewire/libpipewire/mozpipewire.cpp.libwebrtc-screen-cast-sync 2022-07-18 20:44:36.000000000 +0200 ++++ firefox-103.0/third_party/pipewire/libpipewire/mozpipewire.cpp 2022-07-28 11:45:30.321408998 +0200 +@@ -69,11 +69,13 @@ static int (*pw_stream_connect_fn)(struc + enum pw_stream_flags flags, + const struct spa_pod **params, + uint32_t n_params); ++static int (*pw_stream_disconnect_fn)(struct pw_stream *stream); + static struct pw_buffer* (*pw_stream_dequeue_buffer_fn)(struct pw_stream *stream); + static void (*pw_stream_destroy_fn)(struct pw_stream *stream); + static struct pw_stream* (*pw_stream_new_fn)(struct pw_core *core, + const char *name, + struct pw_properties *props); ++ + static int (*pw_stream_queue_buffer_fn)(struct pw_stream *stream, + struct pw_buffer *buffer); + static int (*pw_stream_update_params_fn)(struct pw_stream *stream, +@@ -87,7 +89,10 @@ static int (*pw_thread_loop_start_fn)(st + static void (*pw_thread_loop_stop_fn)(struct pw_thread_loop *loop); + static void (*pw_thread_loop_lock_fn)(struct pw_thread_loop *loop); + static void (*pw_thread_loop_unlock_fn)(struct pw_thread_loop *loop); ++static void (*pw_thread_loop_wait_fn)(struct pw_thread_loop *loop); ++static void (*pw_thread_loop_signal_fn)(struct pw_thread_loop *loop, bool wait_for_accept); + static struct pw_properties* (*pw_properties_new_string_fn)(const char *str); ++static const char* (*pw_get_library_version_fn)(); + + bool IsPwLibraryLoaded() { + static bool isLoaded = +@@ -99,6 +104,7 @@ bool IsPwLibraryLoaded() { + IS_FUNC_LOADED(pw_init_fn) && + IS_FUNC_LOADED(pw_stream_add_listener_fn) && + IS_FUNC_LOADED(pw_stream_connect_fn) && ++ IS_FUNC_LOADED(pw_stream_disconnect_fn) && + IS_FUNC_LOADED(pw_stream_dequeue_buffer_fn) && + IS_FUNC_LOADED(pw_stream_destroy_fn) && + IS_FUNC_LOADED(pw_stream_new_fn) && +@@ -111,7 +117,10 @@ bool IsPwLibraryLoaded() { + IS_FUNC_LOADED(pw_thread_loop_stop_fn) && + IS_FUNC_LOADED(pw_thread_loop_lock_fn) && + IS_FUNC_LOADED(pw_thread_loop_unlock_fn) && +- IS_FUNC_LOADED(pw_properties_new_string_fn)); ++ IS_FUNC_LOADED(pw_thread_loop_signal_fn) && ++ IS_FUNC_LOADED(pw_thread_loop_wait_fn) && ++ IS_FUNC_LOADED(pw_properties_new_string_fn) && ++ IS_FUNC_LOADED(pw_get_library_version_fn)); + + return isLoaded; + } +@@ -136,6 +145,7 @@ bool LoadPWLibrary() { + GET_FUNC(pw_init, pwLib); + GET_FUNC(pw_stream_add_listener, pwLib); + GET_FUNC(pw_stream_connect, pwLib); ++ GET_FUNC(pw_stream_disconnect, pwLib); + GET_FUNC(pw_stream_dequeue_buffer, pwLib); + GET_FUNC(pw_stream_destroy, pwLib); + GET_FUNC(pw_stream_new, pwLib); +@@ -148,7 +158,10 @@ bool LoadPWLibrary() { + GET_FUNC(pw_thread_loop_stop, pwLib); + GET_FUNC(pw_thread_loop_lock, pwLib); + GET_FUNC(pw_thread_loop_unlock, pwLib); ++ GET_FUNC(pw_thread_loop_signal, pwLib); ++ GET_FUNC(pw_thread_loop_wait, pwLib); + GET_FUNC(pw_properties_new_string, pwLib); ++ GET_FUNC(pw_get_library_version, pwLib); + } + + return IsPwLibraryLoaded(); +@@ -242,6 +255,15 @@ pw_stream_connect(struct pw_stream *stre + params, n_params); + } + ++int ++pw_stream_disconnect(struct pw_stream *stream) ++{ ++ if (!LoadPWLibrary()) { ++ return 0; ++ } ++ return pw_stream_disconnect_fn(stream); ++} ++ + struct pw_buffer * + pw_stream_dequeue_buffer(struct pw_stream *stream) + { +@@ -356,6 +378,23 @@ pw_thread_loop_unlock(struct pw_thread_l + return pw_thread_loop_unlock_fn(loop); + } + ++void ++pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept) ++{ ++ if (!LoadPWLibrary()) { ++ return; ++ } ++ return pw_thread_loop_signal_fn(loop, wait_for_accept); ++} ++ ++void ++pw_thread_loop_wait(struct pw_thread_loop *loop) ++{ ++ if (!LoadPWLibrary()) { ++ return; ++ } ++ return pw_thread_loop_wait_fn(loop); ++} + + struct pw_properties * + pw_properties_new_string(const char *str) +@@ -366,3 +405,12 @@ pw_properties_new_string(const char *str + return pw_properties_new_string_fn(str); + } + ++const char* ++pw_get_library_version() ++{ ++ if (!LoadPWLibrary()) { ++ return nullptr; ++ } ++ return pw_get_library_version_fn(); ++} ++ diff --git a/firefox/no-ccache-stats.patch b/firefox/no-ccache-stats.patch new file mode 100644 index 000000000..8ef804919 --- /dev/null +++ b/firefox/no-ccache-stats.patch @@ -0,0 +1,11 @@ +prevents a call to ccache +--- a/python/mozbuild/mozbuild/controller/building.py ++++ b/python/mozbuild/mozbuild/controller/building.py +@@ -586,6 +586,7 @@ + ) + + def ccache_stats(self): ++ return None + ccache_stats = None + + ccache = mozfile.which("ccache") diff --git a/firefox/node-stdout-nonblocking-wrapper b/firefox/node-stdout-nonblocking-wrapper new file mode 100755 index 000000000..b2814b8d4 --- /dev/null +++ b/firefox/node-stdout-nonblocking-wrapper @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/bin/node "$@" 2>&1 | cat -