pax_global_header 0000666 0000000 0000000 00000000064 15070717111 0014512 g ustar 00root root 0000000 0000000 52 comment=f1a5acbae0728eac3d63614b4b9232ca3b65d575
waypipe-v0.10.5/ 0000775 0000000 0000000 00000000000 15070717111 0013441 5 ustar 00root root 0000000 0000000 waypipe-v0.10.5/.clang-format 0000664 0000000 0000000 00000005360 15070717111 0016020 0 ustar 00root root 0000000 0000000 # Only including options for C only
Language: Cpp
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Linux
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 16
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: ForContinuationAndIndentation
waypipe-v0.10.5/.gitignore 0000664 0000000 0000000 00000000264 15070717111 0015433 0 ustar 00root root 0000000 0000000 /waypipe
/build/
/Doxyfile
/html
/latex
/doc
/waypipe-c/test/matrix
/target
/build-minimal/
/wrap-ffmpeg/target
/wrap-lz4/target
/wrap-zstd/target
/wrap-gbm/target
/shaders/target
waypipe-v0.10.5/CONTRIBUTING.md 0000664 0000000 0000000 00000004307 15070717111 0015676 0 ustar 00root root 0000000 0000000 Contributing guidelines
===============================================================================
## Formatting
To avoid needless time spent formatting things, this project has autoformatting
set up. Yes, it's often ugly, but after using it long enough you'll forget that
code can look nice. Python scripts are formatted with ruff[0], C code with
clang-format[1], and Rust code with `cargo fmt`. The script `autoformat.sh`
at the root of the directory should format all source code files in the project.
[0] https://docs.astral.sh/ruff/
[1] https://clang.llvm.org/docs/ClangFormat.html
## Comments
Explain precisely that which is not obvious. `/* ... */` is preferred to
`// ...` for longer comments; the leading `/*` and trailing
`*/ do not need lines of their own. Use Doxygen style (`/\*\*\`) for functions
and structs that need commenting, but not to the point where it hinders source
code readability. Waypipe is not a library.
## Memory and errors
Some errors are unrecoverable, and for those cases Waypipe should shut down
cleanly. For instance, if Waypipe cannot replicate a file descriptor, then an
application connected through it will almost certainly crash, and it's better to
have Waypipe exit instead. Other errors can safely ignored -- if fine grained
damage tracking fails, a sane fallback would be to assume that an entire surface
is damaged.
All error conditions should be handled, including the errors produced by
allocation failures. (It is relatively easy to test for allocation failure by
`LD_PRELOAD`ing a library that redefines malloc et al.; see for instance
"mallocfail" and "failmalloc". `ulimit -v` may be less effective.)
## Types
- Typedefs should be used only for function signatures, and never applied to
structs.
- `short`, `long`, and `long long` should not be used, in favor of `int16_t` and
`int64_t`.
- All wire-format structures should use fixed size types. It's safe to assume
that buffers will never be larger than about 1 GB, so buffer sizes and indices
do not require 64 bit types when used in protocol message headers.
- `printf` should be called with the correct format codes. For example, `%zd`
for `ssize_t`, and the `PRIu32` macro for `uint32_t`.
- Avoid unnecessary casts.
waypipe-v0.10.5/Cargo.lock 0000664 0000000 0000000 00000020546 15070717111 0015355 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "ash"
version = "0.38.0+1.3.281"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
dependencies = [
"libloading",
]
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "clap"
version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_lex"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "libc"
version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]]
name = "nix"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
"memoffset",
]
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "waypipe"
version = "0.10.5"
dependencies = [
"ash",
"clap",
"getrandom",
"log",
"nix",
"waypipe-ffmpeg-wrapper",
"waypipe-gbm-wrapper",
"waypipe-lz4-wrapper",
"waypipe-shaders",
"waypipe-zstd-wrapper",
]
[[package]]
name = "waypipe-ffmpeg-wrapper"
version = "0.1.0"
dependencies = [
"libloading",
"pkg-config",
]
[[package]]
name = "waypipe-gbm-wrapper"
version = "0.1.0"
dependencies = [
"libloading",
"pkg-config",
]
[[package]]
name = "waypipe-lz4-wrapper"
version = "0.1.0"
dependencies = [
"pkg-config",
]
[[package]]
name = "waypipe-shaders"
version = "0.1.0"
[[package]]
name = "waypipe-zstd-wrapper"
version = "0.1.0"
dependencies = [
"pkg-config",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
waypipe-v0.10.5/Cargo.toml 0000664 0000000 0000000 00000004772 15070717111 0015403 0 ustar 00root root 0000000 0000000 [package]
name = "waypipe"
version = "0.10.5"
# To ensure Waypipe can still be built on older/unupdated systems, do
# not update the edition or version unless necessary.
edition = "2021"
rust-version = "1.77.0"
default-run = "waypipe"
[[bin]]
name = "waypipe"
path = "src/main.rs"
[[bin]]
name = "test_proto"
path = "src/test_proto.rs"
required-features = ["test_proto"]
[features]
default = ["video", "dmabuf", "lz4", "zstd", "gbmfallback", "test_proto"]
video = ["dep:waypipe-ffmpeg-wrapper", "dep:waypipe-shaders", "dmabuf"]
dmabuf = ["dep:ash"]
lz4 = ["dep:waypipe-lz4-wrapper"]
zstd = ["dep:waypipe-zstd-wrapper"]
gbmfallback = ["dep:waypipe-gbm-wrapper"]
test_proto = []
[dependencies]
getrandom = "0.2.15"
clap = { version = "4.5.21", features = [] }
log = { version = "0.4.22", features = ["std"] }
nix = { version = "0.29.0", features = ["fs", "poll", "uio", "socket", "process", "signal", "ioctl"] }
ash = { version = "0.38.0", optional = true }
waypipe-ffmpeg-wrapper = { path = "wrap-ffmpeg", optional = true}
waypipe-lz4-wrapper = { path = "wrap-lz4", optional = true}
waypipe-zstd-wrapper = { path = "wrap-zstd", optional = true}
waypipe-gbm-wrapper = { path = "wrap-gbm", optional = true}
waypipe-shaders= { path = "shaders", optional = true}
# Build profiles. The default 'release' and 'dev' are for use when building
# waypipe directly with cargo; debug info is _on_ for both. There are also
# variants used by meson corresponding to each optimization level and debug amount.
# Note: tt is recommended to split debuginfo _after_ building, as Rust's
# split-debuginfo still keeps a lot of debug info in the executable.
[profile.release]
opt-level = 3
debug = "full"
panic = "abort"
lto = "thin"
[profile.dev]
panic = "abort"
[profile.meson-0]
inherits = "dev"
opt-level = 0
[profile.meson-1]
inherits = "release"
opt-level = 1
lto = false
[profile.meson-2]
inherits = "release"
lto = "thin"
opt-level = 2
[profile.meson-3]
inherits = "release"
opt-level = 3
lto = true
codegen-units = 1
[profile.meson-s]
inherits = "release"
lto = true
opt-level = "s"
codegen-units = 1
# to shave off ~100kB: -Z build-std="std,panic_abort"
[profile.meson-0-strip]
inherits = "meson-0"
debug = false
strip = "debuginfo"
[profile.meson-1-strip]
inherits = "meson-1"
debug = false
strip = "debuginfo"
[profile.meson-2-strip]
inherits = "meson-2"
debug = false
strip = "debuginfo"
[profile.meson-3-strip]
inherits = "meson-3"
debug = false
strip = "debuginfo"
[profile.meson-s-strip]
inherits = "meson-s"
debug = false
strip = "debuginfo"
waypipe-v0.10.5/Cross.toml 0000664 0000000 0000000 00000000453 15070717111 0015431 0 ustar 00root root 0000000 0000000 [build]
pre-build = [
"dpkg --add-architecture $CROSS_DEB_ARCH",
"apt-get update && apt-get --assume-yes install libvulkan-dev:$CROSS_DEB_ARCH"
]
[target.i686-unknown-freebsd]
pre-build = []
[target.x86_64-unknown-freebsd]
pre-build = []
[target.powerpc64-unknown-linux-gnu]
pre-build = []
waypipe-v0.10.5/LICENSE.GPLv3 0000664 0000000 0000000 00000104515 15070717111 0015346 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
waypipe-v0.10.5/LICENSE.MIT 0000664 0000000 0000000 00000002305 15070717111 0015076 0 ustar 00root root 0000000 0000000 Copyright © 2019 Manuel Stoeckl
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.
---
The above is the version of the MIT "Expat" License used by X.org:
http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
waypipe-v0.10.5/README.md 0000664 0000000 0000000 00000024130 15070717111 0014720 0 ustar 00root root 0000000 0000000 Waypipe
================================================================================
`waypipe` is a proxy for [Wayland][l0] clients. It forwards Wayland messages and
serializes changes to shared memory buffers over a single socket. This makes
application forwarding similar to [`ssh -X`][l1] feasible.
[l0]: https://wayland.freedesktop.org/
[l1]: https://wiki.archlinux.org/title/OpenSSH#X11_forwarding
## Usage
`waypipe` should be installed on both the local and remote computers. There is a
user-friendly command line pattern which prefixes a call to `ssh` and
automatically sets up a reverse tunnel for protocol data. For example,
```
waypipe ssh user@theserver weston-terminal
```
will run `ssh`, connect to `theserver`, and remotely run `weston-terminal`,
using local and remote `waypipe` processes to synchronize the shared memory
buffers used by Wayland clients between both computers. Command line arguments
before `ssh` apply only to `waypipe`; those after `ssh` belong to `ssh`.
Alternatively, one can launch the local and remote processes by hand, with the
following set of shell commands:
```
/usr/bin/waypipe -s /tmp/socket-local client &
ssh -R /tmp/socket-remote:/tmp/socket-local -t user@theserver \
/usr/bin/waypipe -s /tmp/socket-remote server -- \
/usr/bin/weston-terminal
kill %1
```
It's possible to set up the local and remote processes so that, when the
connection between the sockets used by each end breaks, one can create a new
forwarded socket on the remote side and reconnect the two processes. For a more
detailed example, see the man page.
## Installing
Waypipe's build uses a mixture of [meson][i0] and [cargo][i1]. For example:
```
cd /path/to/waypipe/
cargo fetch --locked
cd ..
mkdir build-waypipe
meson --buildtype debugoptimized waypipe build-waypipe
ninja -C build-waypipe install
```
Core build requirements:
- [meson][i0] (build, ≥ 0.57. with dependencies `ninja`, `pkg-config`, `python3`)
- [cargo][i1] (build)
- rust (build, edition 2021, version ≥ 1.77)
- [scdoc][i2] (optional, to generate a man page, )
- ssh (runtime, OpenSSH ≥ 6.7, for Unix domain socket forwarding)
Rust library dependencies (can be acquired through `cargo fetch --locked`):
- clap: command line parsing
- getrandom: picking random socket names
- log: logging
- nix: safer libc wrapper
- ash: (optional, provides vulkan bindings for dmabuf support)
- libloading: (optional, used by ffmpeg bindings)
- pkg-config: (optional, used to find libraries to link to)
Optional linked dependencies, broken out by feature:
- lz4 compression:
- liblz4 (≥ 1.7.0)
- bindgen (build, ≥ 0.70.0)
- zstd compression:
- libzstd (≥ 0.4.6)
- bindgen (build, ≥ 0.70.0)
- dmabuf support:
- vulkan (to support programs using GPU rendering and DMABUFs)
- vulkan validation layers (runtime, optional, used for tests and with --debug flag)
- dmabuf support fallback with gbm:
- libgbm (mesa, ≥ 11.0.0)
- bindgen (build, ≥ 0.70.0)
- video encoding/decoding support:
- dmabuf support
- ffmpeg (≥ 7.1, needs avcodec/avutil for lossy video encoding)
- bindgen (build, ≥ 0.70.0)
- glslc (build, to compile shaders for image format conversion)
Note: in practice, bindgen requires certain C library headers from clang, but some
distributions have not made them a dependency of bindgen. If the build fails
because `limits.h` or `stddef.h` is missing, try installing `clang`.
[i0]: https://mesonbuild.com/
[i1]: https://doc.rust-lang.org/cargo/
[i2]: https://git.sr.ht/~sircmpwn/scdoc
### `waypipe-c`
Originally, Waypipe was developed in C; it was later ported to use Rust. The
C implementation, now producing an executable called `waypipe-c`, has been kept
in the repository for use on older systems which do not have the Rust version's
dependencies installed. `waypipe-c` also includes some features (like reconnection
support) dropped in later versions. There are two ways to build it: with `meson`,
```
cd /path/to/waypipe/ && cd ..
mkdir build-waypipe
meson --buildtype debugoptimized waypipe build-waypipe -Dbuild_c=true -Dbuild_rs=false
ninja -C build-waypipe install
```
or by running the `./minimal_build.sh` script. In addition to `meson`, `python`,
`liblz4`, `libzstd`, `ssh`, `waypipe-c` requires:
- ffmpeg (≥ 3.1, needs avcodec/avutil/swscale for lossy video encoding)
- libva (for hardware video encoding and decoding)
- libgbm (to support programs using OpenGL via DMABUFs)
- libdrm (same as for libgbm)
- sys/sdt.h (to provide static tracepoints for profiling)
- libwayland-client (for security context support)
## License
`waypipe` is licensed GPLv3-or-later; `waypipe-c` is MIT. In both cases, the
compiled executable is derived from the Wayland protocol files in `./protocols`,
which have their own (permissive) licenses. `waypipe`'s Rust dependency tree
can be shown with `cargo tree`. See git history for a list of authors.
## Reporting issues
Waypipe is developed at [gitlab.freedesktop.org/mstoeckl/waypipe][r0];
file bug reports or submit patches here.
In general, if a program does not work properly under Waypipe, it is a bug worth
reporting. If possible, before doing so ensure both computers are using the most
recently released version of Waypipe (or are built from git master).
A workaround that may help for some programs using OpenGL or Vulkan is to run
Waypipe with the `--no-gpu` flag, which may force them to use software rendering
and shared memory buffers. (Please still file a bug.)
Some programs may require specific environment variable settings or command line
flags to run remotely; a few examples are given in the [man page][r1].
Useful information for bug reports includes:
- If a Waypipe process has crashed on either end of the connection, a full stack
trace, with debug symbols. (In gdb, `bt full`).
- If the program uses OpenGL or Vulkan, the graphics cards and drivers on both
computers.
- The output of `waypipe --version` on both ends of the connection
- Logs when Waypipe is run with the `--debug` flag, or when the program is run
with the environment variable setting `WAYLAND_DEBUG=1`.
- Screenshots of any visual glitches.
[r0]: https://gitlab.freedesktop.org/mstoeckl/waypipe/
[r1]: https://gitlab.freedesktop.org/mstoeckl/waypipe/-/blob/master/waypipe.scd
## Technical Limitations
### Security
Waypipe sends Wayland messages and updates to file descriptors (like window surface
content or copy-paste data transfers) over a socket. When these messages are
sent over a network, even if encrypted and with ssh's (lightweight) timing mitigations,
an observer may be able to guess what is being done (typing, mouse motion, scrolling
a page, and more...) from the sizes and timing of messages alone, even without
knowing the precise contents.
Against broken or malicious compositors or applications: Waypipe does not impose
resource limits, and the applications or compositors it forwards may instruct it
to allocate large amounts of memory or do CPU or GPU-intensive work. Waypipe exposes
compression and video encoding libraries which parse complicated formats and may
have potential vulnerabilities; of these the compression libraries are simpler
and better tested.
See the man page for more details.
### Partial protocol processing
Waypipe does not have a full view of the Wayland protocol. It includes a
compiled form of the base protocol and several extension protocols, but is not
able to parse all messages that the programs it connects send. Fortunately, the
Wayland wire protocol is partially self-describing, so Waypipe can parse the
messages it needs (those related to resources shared with file descriptors)
while ignoring the rest. This makes Waypipe partially forward-compatible: if a
future protocol comes out about details (for example, about window positioning)
which do not require that file descriptors be sent, then applications will be
able to use that protocol even with older versions of Waypipe. The tradeoff to
allowing messages that Waypipe can not parse is that Waypipe can only make minor
modifications to the wire protocol. In particular, adding or removing any
Wayland protocol objects would require changing all messages that refer to them,
including those messages that Waypipe does not parse. This precludes, for
example, global object deduplication tricks that could reduce startup time for
complicated applications.
### Latency
Shared memory buffer updates, including those for the contents of windows, are
tracked by keeping a "mirror" copy of the buffer the represents the view which
the opposing instance of Waypipe has. This way, Waypipe can send only the
regions of the buffer that have changed relative to the remote copy. This is
more efficient than resending the entire buffer on every update, which is good
for applications with reasonably static user interfaces (like a text editor or
email client). However, with programs with animations where the interaction
latency matters (like games or certain audio tools), major window updates will
unavoidably produce a lag spike. The additional memory cost of keeping mirrors
is moderate.
The ssh ObscureKeystrokeTiming feature may introduce delays to obscure when
input events and responses occur; reducing the delay interval should reduce
latency/improve frame rates at the cost of sending more packets.
### Other
The video encoding option for DMABUFs currently maintains a video stream for
each buffer that is used by a window surface. Since surfaces typically rotate
between a small number of buffers, a video encoded window will appear to flicker
as it switches rapidly between the underlying buffers, each of whose video
streams has different encoding artifacts.
As of writing, hardware video support with Vulkan is somewhat experimental and may
require that driver-specific environment variables be set.
Since little-endian computers are vastly more common than big-endian, Waypipe
only receives and produces little-endian Wayland protocol messages. For
big-endian machines, run applications under a tool like `wswapendian` to adjust
the protocol endianness. (Having Waypipe do this itself would require that it
embed or load many more Wayland protocol descriptions and restrict clients to
use them; at the moment it is more practical to do the endianness conversion
in a separate program.)
waypipe-v0.10.5/autoformat.sh 0000775 0000000 0000000 00000000600 15070717111 0016155 0 ustar 00root root 0000000 0000000 #!/bin/sh
set -e
cargo fmt --all
ruff format -q -n protogen.py waypipe-c/test/*.py waypipe-c/protocols/*.py
clang-format -style=file --assume-filename=C -i waypipe-c/*.h waypipe-c/*.c waypipe-c/test/*.c waypipe-c/test/*.h
clang-format -style=llvm -i shaders/*.glsl
meson fmt -i meson.build waypipe-c/meson.build waypipe-c/protocols/meson.build waypipe-c/test/meson.build
cd wrap-zstd
waypipe-v0.10.5/compile_wrapper.sh 0000664 0000000 0000000 00000001273 15070717111 0017170 0 ustar 00root root 0000000 0000000 #!/bin/sh
# This script is run by meson to make cargo build in a specific folder and produce a specific output file,
# because --artifact-dir is still nightly-only
set -e
if [ $# -ne 10 ] ; then
echo "Incorrect number of arguments: $#"
exit 1
fi
# This is a workaround for Rust having no simple and stable compile
# time conditional string concatenation; and meson not properly
# handling newlines or backslashes in custom targets
version="$6
features:
lz4: $7
zstd: $8
dmabuf: $9
video: ${10}"
env WAYPIPE_VERSION="$version" cargo build --frozen -v --bin waypipe --profile "$1" --manifest-path "$2" --no-default-features --target-dir "$3" --features "$4"
cp "$3/$1/waypipe" "$5"
waypipe-v0.10.5/cross_testing.sh 0000775 0000000 0000000 00000002610 15070717111 0016665 0 ustar 00root root 0000000 0000000 #!/bin/sh
# WARNING: cross may download target-specific images from the internet
# WARNING: cargo msrv may install toolchains via rustup
set -ex
cargo fmt --check
cargo test
cargo test --no-default-features
cargo test --no-default-features --features lz4,dmabuf,test_proto
cargo test --no-default-features --features zstd,video,test_proto
cargo test --no-default-features --features gbmfallback,test_proto
# Tier 1
cross test --target x86_64-unknown-linux-gnu --no-default-features --features dmabuf,test_proto
cross test --target aarch64-unknown-linux-gnu --no-default-features --features dmabuf,test_proto
# Linux support, 32 bit
cross test --target i686-unknown-linux-gnu --no-default-features --features dmabuf,test_proto
cross test --target armv7-unknown-linux-gnueabihf --no-default-features --features dmabuf,test_proto
# Big-endian representative
cross test --target powerpc64-unknown-linux-gnu --no-default-features --features test_proto
# FreeBSD support (testing not available, needs full emulation?)
cross build --target x86_64-unknown-freebsd --no-default-features --features test_proto
cross build --target i686-unknown-freebsd --no-default-features --features test_proto
# Check that the build still works with older Rust versions
cargo msrv verify
# on 64 bit systems with the necessary libraries, cross build to 32 bit
# PKG_CONFIG_ALLOW_CROSS=1 cargo build --target=i686-unknown-linux-gnu
waypipe-v0.10.5/meson.build 0000664 0000000 0000000 00000014627 15070717111 0015615 0 ustar 00root root 0000000 0000000 project(
'waypipe',
'c',
license: ['GPL3+', 'MIT/Expat'],
meson_version: '>=0.56.0',
default_options: ['c_std=c11', 'warning_level=3', 'werror=true'],
version: '0.10.5',
)
# mention version
raw_version = '@0@'.format(meson.project_version())
git = find_program('git', native: true, required: false)
if git.found()
dir_arg = '--git-dir=@0@/.git'.format(meson.project_source_root())
commit = run_command(
[git, dir_arg, 'rev-parse', '--verify', '-q', 'HEAD'],
check: false,
)
if commit.returncode() == 0
raw_version = '@0@ (commit @1@)'.format(
meson.project_version(),
commit.stdout().strip(),
)
endif
endif
version = '"@0@"'.format(raw_version)
if get_option('build_rs')
cargo = find_program('cargo', native: true)
sh = find_program('sh', native: true)
objcopy = find_program('objcopy', native: true)
# Because meson and cargo interact badly, option implementation and dependency resolution are deferred to cargo
# However, to 'autodetect' what features are available, we duplicate some of the build logic
features = []
has_lz4 = false
has_zstd = false
has_gbm = false
has_dmabuf = false
has_video = false
# compute maximum of with_lz4/with_zstd/with_gbm/with_video features
max_feature = get_option('with_lz4')
if (max_feature.auto() and get_option('with_zstd').enabled()) or (not max_feature.enabled() and get_option(
'with_zstd',
).auto())
max_feature = get_option('with_zstd')
endif
if (max_feature.auto() and get_option('with_gbm').enabled()) or (not max_feature.enabled() and get_option(
'with_gbm',
).auto())
max_feature = get_option('with_gbm')
endif
if (max_feature.auto() and get_option('with_video').enabled()) or (not max_feature.enabled() and get_option(
'with_video',
).auto())
max_feature = get_option('with_video')
endif
bindgen = find_program(
'bindgen',
version: '>= 0.66.0',
native: true,
required: max_feature,
)
liblz4 = dependency(
'liblz4',
version: '>=1.7.0',
required: get_option('with_lz4'),
)
if bindgen.found() and liblz4.found()
has_lz4 = true
features += ['lz4']
endif
libzstd = dependency(
'libzstd',
version: '>=0.4.6',
required: get_option('with_zstd'),
)
if bindgen.found() and libzstd.found()
has_zstd = true
features += ['zstd']
endif
libvulkan = dependency('vulkan', required: get_option('with_dmabuf'))
if libvulkan.found()
# Note: 'ash' is the vulkan wrapper used, and may require other libraries/programs to be present
has_dmabuf = true
features += ['dmabuf']
endif
libgbm = dependency(
'gbm',
version: '>=11.0.0', # gbm is part of Mesa and has a matching version
required: get_option('with_gbm'),
)
if bindgen.found() and libzstd.found()
has_zstd = true
features += ['gbmfallback']
endif
glslc = find_program(
'glslc',
native: true,
required: get_option('with_video'),
)
libavutil = dependency(
'libavutil',
version: '>=58.11.100',
required: get_option('with_video'),
)
libavcodec = dependency(
'libavcodec',
version: '>=59.0.100',
required: get_option('with_video'),
)
if bindgen.found() and libavcodec.found() and libavutil.found() and glslc.found()
has_video = true
features += ['video']
endif
target_dir = meson.project_build_root() / 'target'
output = target_dir / 'release/waypipe'
manifest = meson.project_source_root() / 'Cargo.toml'
# Cargo has no direct analogue for 'g' or 'plain' optimization levels,
# so the choices for them are somewhat arbitrary
if get_option('optimization') == '0' or get_option('optimization') == 'g'
profile = 'meson-0'
elif get_option('optimization') == '1' or get_option('optimization') == 'plain'
profile = 'meson-1'
elif get_option('optimization') == '3'
profile = 'meson-3'
elif get_option('optimization') == 's'
profile = 'meson-s'
else
profile = 'meson-2'
endif
if get_option('debug') == false
profile += '-strip'
endif
message('Cargo will be run with profile: @0@'.format(profile))
binary = custom_target(
'waypipe',
build_always_stale: true,
output: 'waypipe',
command: [
sh,
'@SOURCE_ROOT@' / 'compile_wrapper.sh',
profile,
manifest,
target_dir,
','.join(features),
'@OUTPUT@',
raw_version,
has_lz4.to_string('true', 'false'),
has_zstd.to_string('true', 'false'),
has_dmabuf.to_string('true', 'false'),
has_video.to_string('true', 'false'),
],
install: true,
install_dir: get_option('bindir'),
)
test(
'running cargo test',
cargo,
args: [
'test',
'--frozen',
'--bin',
'waypipe',
'--test',
'proto',
'-v',
'--manifest-path',
manifest,
'--no-default-features',
'--target-dir',
target_dir,
'--features',
','.join(features + ['test_proto']),
],
timeout: 200,
priority: 100,
)
test(
'running (shortened) waypipe bench',
sh,
args: [
'-c',
' '.join([binary.full_path(), '--test-fast-bench', 'bench']),
],
depends: binary,
)
endif
if get_option('build_c')
subdir('waypipe-c')
endif
scdoc = dependency(
'scdoc',
version: '>=1.9.4',
native: true,
required: get_option('man-pages'),
)
if scdoc.found()
scdoc_prog = find_program(
scdoc.get_variable(pkgconfig: 'scdoc'),
native: true,
)
sh = find_program('sh', native: true)
mandir = get_option('mandir')
custom_target(
'waypipe.1',
input: 'waypipe.scd',
output: 'waypipe.1',
command: [
sh,
'-c',
'@0@ < @INPUT@ > @1@'.format(scdoc_prog.full_path(), 'waypipe.1'),
],
install: true,
install_dir: '@0@/man1'.format(mandir),
)
endif
waypipe-v0.10.5/meson_options.txt 0000664 0000000 0000000 00000004350 15070717111 0017100 0 ustar 00root root 0000000 0000000 # Control what to build
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
option('build_c', description: 'Build old version of waypipe (waypipe-c)', type: 'boolean', value: false)
option('build_rs', description: 'Build current version of waypipe', type: 'boolean', value: true)
option('tests', description: 'Compile Waypipe tests', type: 'boolean', value: true)
# Options that apply to waypipe and waypipe-c
option('with_video', type : 'feature', value : 'auto', description : 'Link with ffmpeg libraries and provide a command line option to display all buffers using a video stream')
option('with_dmabuf', type : 'feature', value : 'auto', description : 'Support DMABUFs, the file descriptors used to exchange data for e.g. OpenGL applications')
option('with_lz4', type : 'feature', value : 'auto', description : 'Support LZ4 as a compression mechanism')
option('with_zstd', type : 'feature', value : 'auto', description : 'Support ZStandard as a compression mechanism')
# Options for: waypipe
option('with_gbm', type : 'feature', value : 'auto', description : 'Use libgbm as a limited fallback path to support DMABUFs')
# Options for: waypipe-c
option('with_vaapi', type : 'feature', value : 'auto', description : 'C only: Link with libva and use VAAPI to perform hardware video output color space conversions on GPU')
option('with_systemtap', type: 'boolean', value: true, description: 'C only: Enable tracing using sdt and provide static tracepoints for profiling')
option('with_secctx', type: 'feature', value: 'auto', description: 'C only: Enable support for the Wayland security context protocol')
## It is recommended to keep these on; Waypipe will automatically select the highest available instruction set at runtime
option('with_avx512f', type: 'boolean', value: true, description: 'C only: Compile with support for AVX512f SIMD instructions')
option('with_avx2', type: 'boolean', value: true, description: 'C only: Compile with support for AVX2 SIMD instructions')
option('with_sse3', type: 'boolean', value: true, description: 'C only: Compile with support for SSE3 SIMD instructions')
option('with_neon_opts', type: 'boolean', value: true, description: 'C only: Compile with support for ARM64 neon instructions')
waypipe-v0.10.5/minimal_build.sh 0000775 0000000 0000000 00000002031 15070717111 0016601 0 ustar 00root root 0000000 0000000 #!/bin/sh
set -e
echo "This script is a backup build system in case meson/ninja are unavailable."
echo "No optional features or optimizations are included. Waypipe will be slow."
echo "Requirements: python3, gcc, libc+pthreads"
echo "Enter to continue, interrupt to exit."
read unused
mkdir -p build-minimal
cd build-minimal
root=../waypipe-c
echo "Generating code..."
python3 $root/protocols/symgen.py data $root/protocols/function_list.txt protocols.c \
../protocols/*.xml
python3 $root/protocols/symgen.py header $root/protocols/function_list.txt protocols.h \
../protocols/*.xml
echo '#define WAYPIPE_VERSION "minimal"' > config-waypipe.h
echo "Compiling..."
gcc -D_DEFAULT_SOURCE -Os -I. -I$root/protocols/ -lpthread -o waypipe-c protocols.c \
$root/bench.c $root/client.c $root/dmabuf.c $root/handlers.c \
$root/interval.c $root/kernel.c $root/mainloop.c $root/parsing.c \
$root/platform.c $root/server.c $root/shadow.c $root/util.c \
$root/video.c $root/waypipe.c
cd ..
echo "Done. See ./build-minimal/waypipe-c"
waypipe-v0.10.5/protocols/ 0000775 0000000 0000000 00000000000 15070717111 0015465 5 ustar 00root root 0000000 0000000 waypipe-v0.10.5/protocols/color-management-v1.xml 0000664 0000000 0000000 00000222127 15070717111 0021771 0 ustar 00root root 0000000 0000000
Copyright 2019 Sebastian Wick
Copyright 2019 Erwin Burema
Copyright 2020 AMD
Copyright 2020-2024 Collabora, Ltd.
Copyright 2024 Xaver Hugl
Copyright 2022-2025 Red Hat, Inc.
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.
The aim of the color management extension is to allow clients to know
the color properties of outputs, and to tell the compositor about the color
properties of their content on surfaces. Doing this enables a compositor
to perform automatic color management of content for different outputs
according to how content is intended to look like.
The color properties are represented as an image description object which
is immutable after it has been created. A wl_output always has an
associated image description that clients can observe. A wl_surface
always has an associated preferred image description as a hint chosen by
the compositor that clients can also observe. Clients can set an image
description on a wl_surface to denote the color characteristics of the
surface contents.
An image description includes SDR and HDR colorimetry and encoding, HDR
metadata, and viewing environment parameters. An image description does
not include the properties set through color-representation extension.
It is expected that the color-representation extension is used in
conjunction with the color management extension when necessary,
particularly with the YUV family of pixel formats.
Recommendation ITU-T H.273
"Coding-independent code points for video signal type identification"
shall be referred to as simply H.273 here.
The color-and-hdr repository
(https://gitlab.freedesktop.org/pq/color-and-hdr) contains
background information on the protocol design and legacy color management.
It also contains a glossary, learning resources for digital color, tools,
samples and more.
The terminology used in this protocol is based on common color science and
color encoding terminology where possible. The glossary in the color-and-hdr
repository shall be the authority on the definition of terms in this
protocol.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
A singleton global interface used for getting color management extensions
for wl_surface and wl_output objects, and for creating client defined
image description objects. The extension interfaces allow
getting the image description of outputs and setting the image
description of surfaces.
Compositors should never remove this global.
Destroy the wp_color_manager_v1 object. This does not affect any other
objects in any way.
See the ICC.1:2022 specification from the International Color Consortium
for more details about rendering intents.
The principles of ICC defined rendering intents apply with all types of
image descriptions, not only those with ICC file profiles.
Compositors must support the perceptual rendering intent. Other
rendering intents are optional.
The compositor supports set_mastering_display_primaries request with a
target color volume fully contained inside the primary color volume.
The compositor additionally supports target color volumes that
extend outside of the primary color volume.
This can only be advertised if feature set_mastering_display_primaries
is supported as well.
Named color primaries used to encode well-known sets of primaries. H.273
is the authority, when it comes to the exact values of primaries and
authoritative specifications, where an equivalent code point exists.
A value of 0 is invalid and will never be present in the list of enums.
Descriptions do list the specifications for convenience.
Color primaries as defined by
- Rec. ITU-R BT.709-6
- Rec. ITU-R BT.1361-0 conventional colour gamut system and extended
colour gamut system (historical)
- IEC 61966-2-1 sRGB or sYCC
- IEC 61966-2-4
- Society of Motion Picture and Television Engineers (SMPTE) RP 177
(1993) Annex B
Equivalent to H.273 ColourPrimaries code point 1.
Color primaries as defined by
- Rec. ITU-R BT.470-6 System M (historical)
- United States National Television System Committee 1953
Recommendation for transmission standards for color television
- United States Federal Communications Commission (2003) Title 47 Code
of Federal Regulations 73.682 (a)(20)
Equivalent to H.273 ColourPrimaries code point 4.
Color primaries as defined by
- Rec. ITU-R BT.470-6 System B, G (historical)
- Rec. ITU-R BT.601-7 625
- Rec. ITU-R BT.1358-0 625 (historical)
- Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
Equivalent to H.273 ColourPrimaries code point 5.
Color primaries as defined by
- Rec. ITU-R BT.601-7 525
- Rec. ITU-R BT.1358-1 525 or 625 (historical)
- Rec. ITU-R BT.1700-0 NTSC
- SMPTE 170M (2004)
- SMPTE 240M (1999) (historical)
Equivalent to H.273 ColourPrimaries code point 6 and 7.
Color primaries as defined by H.273 for generic film.
Equivalent to H.273 ColourPrimaries code point 8.
Color primaries as defined by
- Rec. ITU-R BT.2020-2
- Rec. ITU-R BT.2100-0
Equivalent to H.273 ColourPrimaries code point 9.
Color primaries as defined as the maximum of the CIE 1931 XYZ color
space by
- SMPTE ST 428-1
- (CIE 1931 XYZ as in ISO 11664-1)
Equivalent to H.273 ColourPrimaries code point 10.
Color primaries as defined by Digital Cinema System and published in
SMPTE RP 431-2 (2011). Equivalent to H.273 ColourPrimaries code point
11.
Color primaries as defined by Digital Cinema System and published in
SMPTE EG 432-1 (2010).
Equivalent to H.273 ColourPrimaries code point 12.
Color primaries as defined by Adobe as "Adobe RGB" and later published
by ISO 12640-4 (2011).
Named transfer functions used to represent well-known transfer
characteristics. H.273 is the authority, when it comes to the exact
formulas and authoritative specifications, where an equivalent code
point exists.
A value of 0 is invalid and will never be present in the list of enums.
Descriptions do list the specifications for convenience.
Rec. ITU-R BT.1886 is the display transfer characteristic assumed by
- Rec. ITU-R BT.601-7 525 and 625
- Rec. ITU-R BT.709-6
- Rec. ITU-R BT.2020-2
These recommendations are referred to by H.273 TransferCharacteristics
code points 1, 6, 14, and 15, which are all equivalent.
This TF implies these default luminances from Rec. ITU-R BT.2035:
- primary color volume minimum: 0.01 cd/m²
- primary color volume maximum: 100 cd/m²
- reference white: 100 cd/m²
Transfer characteristics as defined by
- Rec. ITU-R BT.470-6 System M (historical)
- United States National Television System Committee 1953
Recommendation for transmission standards for color television
- United States Federal Communications Commission (2003) Title 47 Code
of Federal Regulations 73.682 (a) (20)
- Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
Equivalent to H.273 TransferCharacteristics code point 4.
Transfer characteristics as defined by
- Rec. ITU-R BT.470-6 System B, G (historical)
Equivalent to H.273 TransferCharacteristics code point 5.
Transfer characteristics as defined by
- SMPTE ST 240 (1999)
Equivalent to H.273 TransferCharacteristics code point 7.
Linear transfer function defined over all real numbers.
Normalised electrical values are equal the normalised optical values.
The differences to H.273 TransferCharacteristics code point 8 are
the definition over all real numbers.
Logarithmic transfer characteristic (100:1 range).
Equivalent to H.273 TransferCharacteristics code point 9.
Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range).
Equivalent to H.273 TransferCharacteristics code point 10.
Transfer characteristics as defined by
- IEC 61966-2-4
Equivalent to H.273 TransferCharacteristics code point 11.
Transfer characteristics as defined by
- IEC 61966-2-1 sRGB
Equivalent to H.273 TransferCharacteristics code point 13 with
MatrixCoefficients set to 0.
Transfer characteristics as defined by
- IEC 61966-2-1 sYCC
Equivalent to H.273 TransferCharacteristics code point 13 with
MatrixCoefficients set to anything but 0.
Transfer characteristics as defined by
- SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems
- Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
Equivalent to H.273 TransferCharacteristics code point 16.
This TF implies these default luminances
- primary color volume minimum: 0.005 cd/m²
- primary color volume maximum: 10000 cd/m²
- reference white: 203 cd/m²
The difference between the primary color volume minimum and maximum
must be approximately 10000 cd/m² as that is the swing of the EOTF
defined by ST 2084 and BT.2100. The default value for the
reference white is a protocol addition: it is suggested by
Report ITU-R BT.2408-7 and is not part of ST 2084 or BT.2100.
Transfer characteristics as defined by
- SMPTE ST 428-1 (2019)
Equivalent to H.273 TransferCharacteristics code point 17.
Transfer characteristics as defined by
- ARIB STD-B67 (2015)
- Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system
Equivalent to H.273 TransferCharacteristics code point 18.
This TF implies these default luminances
- primary color volume minimum: 0.005 cd/m²
- primary color volume maximum: 1000 cd/m²
- reference white: 203 cd/m²
HLG is a relative display-referred signal with a specified
non-linear mapping to the display peak luminance (the HLG OOTF).
All absolute luminance values used here for HLG assume a 1000 cd/m²
peak display.
The default value for the reference white is a protocol addition:
it is suggested by Report ITU-R BT.2408-7 and is not part of
ARIB STD-B67 or BT.2100.
This creates a new wp_color_management_output_v1 object for the
given wl_output.
See the wp_color_management_output_v1 interface for more details.
If a wp_color_management_surface_v1 object already exists for the given
wl_surface, the protocol error surface_exists is raised.
This creates a new color wp_color_management_surface_v1 object for the
given wl_surface.
See the wp_color_management_surface_v1 interface for more details.
This creates a new color wp_color_management_surface_feedback_v1 object
for the given wl_surface.
See the wp_color_management_surface_feedback_v1 interface for more
details.
Makes a new ICC-based image description creator object with all
properties initially unset. The client can then use the object's
interface to define all the required properties for an image description
and finally create a wp_image_description_v1 object.
This request can be used when the compositor advertises
wp_color_manager_v1.feature.icc_v2_v4.
Otherwise this request raises the protocol error unsupported_feature.
Makes a new parametric image description creator object with all
properties initially unset. The client can then use the object's
interface to define all the required properties for an image description
and finally create a wp_image_description_v1 object.
This request can be used when the compositor advertises
wp_color_manager_v1.feature.parametric.
Otherwise this request raises the protocol error unsupported_feature.
This creates a pre-defined image description for the so-called
Windows-scRGB stimulus encoding. This comes from the Windows 10 handling
of its own definition of an scRGB color space for an HDR screen
driven in BT.2100/PQ signalling mode.
Windows-scRGB uses sRGB (BT.709) color primaries and white point.
The transfer characteristic is extended linear.
The nominal color channel value range is extended, meaning it includes
negative and greater than 1.0 values. Negative values are used to
escape the sRGB color gamut boundaries. To make use of the extended
range, the client needs to use a pixel format that can represent those
values, e.g. floating-point 16 bits per channel.
Nominal color value R=G=B=0.0 corresponds to BT.2100/PQ system
0 cd/m², and R=G=B=1.0 corresponds to BT.2100/PQ system 80 cd/m².
The maximum is R=G=B=125.0 corresponding to 10k cd/m².
Windows-scRGB is displayed by Windows 10 by converting it to
BT.2100/PQ, maintaining the CIE 1931 chromaticity and mapping the
luminance as above. No adjustment is made to the signal to account
for the viewing conditions.
The reference white level of Windows-scRGB is unknown. If a
reference white level must be assumed for compositor processing, it
should be R=G=B=2.5375 corresponding to 203 cd/m² of Report ITU-R
BT.2408-7.
The target color volume of Windows-scRGB is unknown. The color gamut
may be anything between sRGB and BT.2100.
Note: EGL_EXT_gl_colorspace_scrgb_linear definition differs from
Windows-scRGB by using R=G=B=1.0 as the reference white level, while
Windows-scRGB reference white level is unknown or varies. However,
it seems probable that Windows implements both
EGL_EXT_gl_colorspace_scrgb_linear and Vulkan
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT as Windows-scRGB.
This request can be used when the compositor advertises
wp_color_manager_v1.feature.windows_scrgb.
Otherwise this request raises the protocol error unsupported_feature.
The resulting image description object does not allow get_information
request. The wp_image_description_v1.ready event shall be sent.
When this object is created, it shall immediately send this event once
for each rendering intent the compositor supports.
When this object is created, it shall immediately send this event once
for each compositor supported feature listed in the enumeration.
When this object is created, it shall immediately send this event once
for each named transfer function the compositor supports with the
parametric image description creator.
When this object is created, it shall immediately send this event once
for each named set of primaries the compositor supports with the
parametric image description creator.
This event is sent when all supported rendering intents, features,
transfer functions and named primaries have been sent.
A wp_color_management_output_v1 describes the color properties of an
output.
The wp_color_management_output_v1 is associated with the wl_output global
underlying the wl_output object. Therefore the client destroying the
wl_output object has no impact, but the compositor removing the output
global makes the wp_color_management_output_v1 object inert.
Destroy the color wp_color_management_output_v1 object. This does not
affect any remaining protocol objects.
This event is sent whenever the image description of the output changed,
followed by one wl_output.done event common to output events across all
extensions.
If the client wants to use the updated image description, it needs to do
get_image_description again, because image description objects are
immutable.
This creates a new wp_image_description_v1 object for the current image
description of the output. There always is exactly one image description
active for an output so the client should destroy the image description
created by earlier invocations of this request. This request is usually
sent as a reaction to the image_description_changed event or when
creating a wp_color_management_output_v1 object.
The image description of an output represents the color encoding the
output expects. There might be performance and power advantages, as well
as improved color reproduction, if a content update matches the image
description of the output it is being shown on. If a content update is
shown on any other output than the one it matches the image description
of, then the color reproduction on those outputs might be considerably
worse.
The created wp_image_description_v1 object preserves the image
description of the output from the time the object was created.
The resulting image description object allows get_information request.
If this protocol object is inert, the resulting image description object
shall immediately deliver the wp_image_description_v1.failed event with
the no_output cause.
If the interface version is inadequate for the output's image
description, meaning that the client does not support all the events
needed to deliver the crucial information, the resulting image
description object shall immediately deliver the
wp_image_description_v1.failed event with the low_version cause.
Otherwise the object shall immediately deliver the ready event.
A wp_color_management_surface_v1 allows the client to set the color
space and HDR properties of a surface.
If the wl_surface associated with the wp_color_management_surface_v1 is
destroyed, the wp_color_management_surface_v1 object becomes inert.
Destroy the wp_color_management_surface_v1 object and do the same as
unset_image_description.
If this protocol object is inert, the protocol error inert is raised.
Set the image description of the underlying surface. The image
description and rendering intent are double-buffered state, see
wl_surface.commit.
It is the client's responsibility to understand the image description
it sets on a surface, and to provide content that matches that image
description. Compositors might convert images to match their own or any
other image descriptions.
Image descriptions which are not ready (see wp_image_description_v1)
are forbidden in this request, and in such case the protocol error
image_description is raised.
All image descriptions which are ready (see wp_image_description_v1)
are allowed and must always be accepted by the compositor.
A rendering intent provides the client's preference on how content
colors should be mapped to each output. The render_intent value must
be one advertised by the compositor with
wp_color_manager_v1.render_intent event, otherwise the protocol error
render_intent is raised.
When an image description is set on a surface, the Transfer
Characteristics of the image description defines the valid range of
the nominal (real-valued) color channel values. The processing of
out-of-range color channel values is undefined, but compositors are
recommended to clamp the values to the valid range when possible.
By default, a surface does not have an associated image description
nor a rendering intent. The handling of color on such surfaces is
compositor implementation defined. Compositors should handle such
surfaces as sRGB, but may handle them differently if they have specific
requirements.
Setting the image description has copy semantics; after this request,
the image description can be immediately destroyed without affecting
the pending state of the surface.
If this protocol object is inert, the protocol error inert is raised.
This request removes any image description from the surface. See
set_image_description for how a compositor handles a surface without
an image description. This is double-buffered state, see
wl_surface.commit.
A wp_color_management_surface_feedback_v1 allows the client to get the
preferred image description of a surface.
If the wl_surface associated with this object is destroyed, the
wp_color_management_surface_feedback_v1 object becomes inert.
Destroy the wp_color_management_surface_feedback_v1 object.
The preferred image description is the one which likely has the most
performance and/or quality benefits for the compositor if used by the
client for its wl_surface contents. This event is sent whenever the
compositor changes the wl_surface's preferred image description.
This event sends the identity of the new preferred state as the argument,
so clients who are aware of the image description already can reuse it.
Otherwise, if the client client wants to know what the preferred image
description is, it shall use the get_preferred request.
The preferred image description is not automatically used for anything.
It is only a hint, and clients may set any valid image description with
set_image_description, but there might be performance and color accuracy
improvements by providing the wl_surface contents in the preferred
image description. Therefore clients that can, should render according
to the preferred image description
If this protocol object is inert, the protocol error inert is raised.
The preferred image description represents the compositor's preferred
color encoding for this wl_surface at the current time. There might be
performance and power advantages, as well as improved color
reproduction, if the image description of a content update matches the
preferred image description.
This creates a new wp_image_description_v1 object for the currently
preferred image description for the wl_surface. The client should
stop using and destroy the image descriptions created by earlier
invocations of this request for the associated wl_surface.
This request is usually sent as a reaction to the preferred_changed
event or when creating a wp_color_management_surface_feedback_v1 object
if the client is capable of adapting to image descriptions.
The created wp_image_description_v1 object preserves the preferred image
description of the wl_surface from the time the object was created.
The resulting image description object allows get_information request.
If the image description is parametric, the client should set it on its
wl_surface only if the image description is an exact match with the
client content. Particularly if everything else matches, but the target
color volume is greater than what the client needs, the client should
create its own parameric image description with its exact parameters.
If the interface version is inadequate for the preferred image
description, meaning that the client does not support all the
events needed to deliver the crucial information, the resulting image
description object shall immediately deliver the
wp_image_description_v1.failed event with the low_version cause,
otherwise the object shall immediately deliver the ready event.
The same description as for get_preferred applies, except the returned
image description is guaranteed to be parametric. This is meant for
clients that can only deal with parametric image descriptions.
If the compositor doesn't support parametric image descriptions, the
unsupported_feature error is emitted.
This type of object is used for collecting all the information required
to create a wp_image_description_v1 object from an ICC file. A complete
set of required parameters consists of these properties:
- ICC file
Each required property must be set exactly once if the client is to create
an image description. The set requests verify that a property was not
already set. The create request verifies that all required properties are
set. There may be several alternative requests for setting each property,
and in that case the client must choose one of them.
Once all properties have been set, the create request must be used to
create the image description object, destroying the creator in the
process.
Create an image description object based on the ICC information
previously set on this object. A compositor must parse the ICC data in
some undefined but finite amount of time.
The completeness of the parameter set is verified. If the set is not
complete, the protocol error incomplete_set is raised. For the
definition of a complete set, see the description of this interface.
If the particular combination of the information is not supported
by the compositor, the resulting image description object shall
immediately deliver the wp_image_description_v1.failed event with the
'unsupported' cause. If a valid image description was created from the
information, the wp_image_description_v1.ready event will eventually
be sent instead.
This request destroys the wp_image_description_creator_icc_v1 object.
The resulting image description object does not allow get_information
request.
Sets the ICC profile file to be used as the basis of the image
description.
The data shall be found through the given fd at the given offset, having
the given length. The fd must be seekable and readable. Violating these
requirements raises the bad_fd protocol error.
If reading the data fails due to an error independent of the client, the
compositor shall send the wp_image_description_v1.failed event on the
created wp_image_description_v1 with the 'operating_system' cause.
The maximum size of the ICC profile is 32 MB. If length is greater than
that or zero, the protocol error bad_size is raised. If offset + length
exceeds the file size, the protocol error out_of_file is raised.
A compositor may read the file at any time starting from this request
and only until whichever happens first:
- If create request was issued, the wp_image_description_v1 object
delivers either failed or ready event; or
- if create request was not issued, this
wp_image_description_creator_icc_v1 object is destroyed.
A compositor shall not modify the contents of the file, and the fd may
be sealed for writes and size changes. The client must ensure to its
best ability that the data does not change while the compositor is
reading it.
The data must represent a valid ICC profile. The ICC profile version
must be 2 or 4, it must be a 3 channel profile and the class must be
Display or ColorSpace. Violating these requirements will not result in a
protocol error, but will eventually send the
wp_image_description_v1.failed event on the created
wp_image_description_v1 with the 'unsupported' cause.
See the International Color Consortium specification ICC.1:2022 for more
details about ICC profiles.
If ICC file has already been set on this object, the protocol error
already_set is raised.
This type of object is used for collecting all the parameters required
to create a wp_image_description_v1 object. A complete set of required
parameters consists of these properties:
- transfer characteristic function (tf)
- chromaticities of primaries and white point (primary color volume)
The following properties are optional and have a well-defined default
if not explicitly set:
- primary color volume luminance range
- reference white luminance level
- mastering display primaries and white point (target color volume)
- mastering luminance range
The following properties are optional and will be ignored
if not explicitly set:
- maximum content light level
- maximum frame-average light level
Each required property must be set exactly once if the client is to create
an image description. The set requests verify that a property was not
already set. The create request verifies that all required properties are
set. There may be several alternative requests for setting each property,
and in that case the client must choose one of them.
Once all properties have been set, the create request must be used to
create the image description object, destroying the creator in the
process.
Create an image description object based on the parameters previously
set on this object.
The completeness of the parameter set is verified. If the set is not
complete, the protocol error incomplete_set is raised. For the
definition of a complete set, see the description of this interface.
The protocol error invalid_luminance is raised if any of the following
requirements is not met:
- When max_cll is set, it must be greater than min L and less or equal
to max L of the mastering luminance range.
- When max_fall is set, it must be greater than min L and less or equal
to max L of the mastering luminance range.
- When both max_cll and max_fall are set, max_fall must be less or equal
to max_cll.
If the particular combination of the parameter set is not supported
by the compositor, the resulting image description object shall
immediately deliver the wp_image_description_v1.failed event with the
'unsupported' cause. If a valid image description was created from the
parameter set, the wp_image_description_v1.ready event will eventually
be sent instead.
This request destroys the wp_image_description_creator_params_v1
object.
The resulting image description object does not allow get_information
request.
Sets the transfer characteristic using explicitly enumerated named
functions.
When the resulting image description is attached to an image, the
content should be encoded and decoded according to the industry standard
practices for the transfer characteristic.
Only names advertised with wp_color_manager_v1 event supported_tf_named
are allowed. Other values shall raise the protocol error invalid_tf.
If transfer characteristic has already been set on this object, the
protocol error already_set is raised.
Sets the color component transfer characteristic to a power curve with
the given exponent. Negative values are handled by mirroring the
positive half of the curve through the origin. The valid domain and
range of the curve are all finite real numbers. This curve represents
the conversion from electrical to optical color channel values.
When the resulting image description is attached to an image, the
content should be encoded with the inverse of the power curve.
The curve exponent shall be multiplied by 10000 to get the argument eexp
value to carry the precision of 4 decimals.
The curve exponent must be at least 1.0 and at most 10.0. Otherwise the
protocol error invalid_tf is raised.
If transfer characteristic has already been set on this object, the
protocol error already_set is raised.
This request can be used when the compositor advertises
wp_color_manager_v1.feature.set_tf_power. Otherwise this request raises
the protocol error unsupported_feature.
Sets the color primaries and white point using explicitly named sets.
This describes the primary color volume which is the basis for color
value encoding.
Only names advertised with wp_color_manager_v1 event
supported_primaries_named are allowed. Other values shall raise the
protocol error invalid_primaries_named.
If primaries have already been set on this object, the protocol error
already_set is raised.
Sets the color primaries and white point using CIE 1931 xy chromaticity
coordinates. This describes the primary color volume which is the basis
for color value encoding.
Each coordinate value is multiplied by 1 million to get the argument
value to carry precision of 6 decimals.
If primaries have already been set on this object, the protocol error
already_set is raised.
This request can be used if the compositor advertises
wp_color_manager_v1.feature.set_primaries. Otherwise this request raises
the protocol error unsupported_feature.
Sets the primary color volume luminance range and the reference white
luminance level. These values include the minimum display emission
and ambient flare luminances, assumed to be optically additive and have
the chromaticity of the primary color volume white point.
The default luminances from
https://www.color.org/chardata/rgb/srgb.xalter are
- primary color volume minimum: 0.2 cd/m²
- primary color volume maximum: 80 cd/m²
- reference white: 80 cd/m²
Setting a named transfer characteristic can imply other default
luminances.
The default luminances get overwritten when this request is used.
With transfer_function.st2084_pq the given 'max_lum' value is ignored,
and 'max_lum' is taken as 'min_lum' + 10000 cd/m².
'min_lum' and 'max_lum' specify the minimum and maximum luminances of
the primary color volume as reproduced by the targeted display.
'reference_lum' specifies the luminance of the reference white as
reproduced by the targeted display, and reflects the targeted viewing
environment.
Compositors should make sure that all content is anchored, meaning that
an input signal level of 'reference_lum' on one image description and
another input signal level of 'reference_lum' on another image
description should produce the same output level, even though the
'reference_lum' on both image representations can be different.
'reference_lum' may be higher than 'max_lum'. In that case reaching
the reference white output level in image content requires the
'extended_target_volume' feature support.
If 'max_lum' or 'reference_lum' are less than or equal to 'min_lum',
the protocol error invalid_luminance is raised.
The minimum luminance is multiplied by 10000 to get the argument
'min_lum' value and carries precision of 4 decimals. The maximum
luminance and reference white luminance values are unscaled.
If the primary color volume luminance range and the reference white
luminance level have already been set on this object, the protocol error
already_set is raised.
This request can be used if the compositor advertises
wp_color_manager_v1.feature.set_luminances. Otherwise this request
raises the protocol error unsupported_feature.
Provides the color primaries and white point of the mastering display
using CIE 1931 xy chromaticity coordinates. This is compatible with the
SMPTE ST 2086 definition of HDR static metadata.
The mastering display primaries and mastering display luminances define
the target color volume.
If mastering display primaries are not explicitly set, the target color
volume is assumed to have the same primaries as the primary color volume.
The target color volume is defined by all tristimulus values between 0.0
and 1.0 (inclusive) of the color space defined by the given mastering
display primaries and white point. The colorimetry is identical between
the container color space and the mastering display color space,
including that no chromatic adaptation is applied even if the white
points differ.
The target color volume can exceed the primary color volume to allow for
a greater color volume with an existing color space definition (for
example scRGB). It can be smaller than the primary color volume to
minimize gamut and tone mapping distances for big color spaces (HDR
metadata).
To make use of the entire target color volume a suitable pixel format
has to be chosen (e.g. floating point to exceed the primary color
volume, or abusing limited quantization range as with xvYCC).
Each coordinate value is multiplied by 1 million to get the argument
value to carry precision of 6 decimals.
If mastering display primaries have already been set on this object, the
protocol error already_set is raised.
This request can be used if the compositor advertises
wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise
this request raises the protocol error unsupported_feature. The
advertisement implies support only for target color volumes fully
contained within the primary color volume.
If a compositor additionally supports target color volume exceeding the
primary color volume, it must advertise
wp_color_manager_v1.feature.extended_target_volume. If a client uses
target color volume exceeding the primary color volume and the
compositor does not support it, the result is implementation defined.
Compositors are recommended to detect this case and fail the image
description gracefully, but it may as well result in color artifacts.
Sets the luminance range that was used during the content mastering
process as the minimum and maximum absolute luminance L. These values
include the minimum display emission and ambient flare luminances,
assumed to be optically additive and have the chromaticity of the
primary color volume white point. This should be
compatible with the SMPTE ST 2086 definition of HDR static metadata.
The mastering display primaries and mastering display luminances define
the target color volume.
If mastering luminances are not explicitly set, the target color volume
is assumed to have the same min and max luminances as the primary color
volume.
If max L is less than or equal to min L, the protocol error
invalid_luminance is raised.
Min L value is multiplied by 10000 to get the argument min_lum value
and carry precision of 4 decimals. Max L value is unscaled for max_lum.
This request can be used if the compositor advertises
wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise
this request raises the protocol error unsupported_feature. The
advertisement implies support only for target color volumes fully
contained within the primary color volume.
If a compositor additionally supports target color volume exceeding the
primary color volume, it must advertise
wp_color_manager_v1.feature.extended_target_volume. If a client uses
target color volume exceeding the primary color volume and the
compositor does not support it, the result is implementation defined.
Compositors are recommended to detect this case and fail the image
description gracefully, but it may as well result in color artifacts.
Sets the maximum content light level (max_cll) as defined by CTA-861-H.
max_cll is undefined by default.
Sets the maximum frame-average light level (max_fall) as defined by
CTA-861-H.
max_fall is undefined by default.
An image description carries information about the color encoding used on
a surface when attached to a wl_surface via
wp_color_management_surface_v1.set_image_description. A compositor can use
this information to decode pixel values into colorimetrically meaningful
quantities.
Note, that the wp_image_description_v1 object is not ready to be used
immediately after creation. The object eventually delivers either the
'ready' or the 'failed' event, specified in all requests creating it. The
object is deemed "ready" after receiving the 'ready' event.
An object which is not ready is illegal to use, it can only be destroyed.
Any other request in this interface shall result in the 'not_ready'
protocol error. Attempts to use an object which is not ready through other
interfaces shall raise protocol errors defined there.
Once created and regardless of how it was created, a
wp_image_description_v1 object always refers to one fixed image
description. It cannot change after creation.
Destroy this object. It is safe to destroy an object which is not ready.
Destroying a wp_image_description_v1 object has no side-effects, not
even if a wp_color_management_surface_v1.set_image_description has not
yet been followed by a wl_surface.commit.
If creating a wp_image_description_v1 object fails for a reason that is
not defined as a protocol error, this event is sent.
The requests that create image description objects define whether and
when this can occur. Only such creation requests can trigger this event.
This event cannot be triggered after the image description was
successfully formed.
Once this event has been sent, the wp_image_description_v1 object will
never become ready and it can only be destroyed.
Once this event has been sent, the wp_image_description_v1 object is
deemed "ready". Ready objects can be used to send requests and can be
used through other interfaces.
Every ready wp_image_description_v1 protocol object refers to an
underlying image description record in the compositor. Multiple protocol
objects may end up referring to the same record. Clients may identify
these "copies" by comparing their id numbers: if the numbers from two
protocol objects are identical, the protocol objects refer to the same
image description record. Two different image description records
cannot have the same id number simultaneously. The id number does not
change during the lifetime of the image description record.
The id number is valid only as long as the protocol object is alive. If
all protocol objects referring to the same image description record are
destroyed, the id number may be recycled for a different image
description record.
Image description id number is not a protocol object id. Zero is
reserved as an invalid id number. It shall not be possible for a client
to refer to an image description by its id number in protocol. The id
numbers might not be portable between Wayland connections. A compositor
shall not send an invalid id number.
This identity allows clients to de-duplicate image description records
and avoid get_information request if they already have the image
description information.
Creates a wp_image_description_info_v1 object which delivers the
information that makes up the image description.
Not all image description protocol objects allow get_information
request. Whether it is allowed or not is defined by the request that
created the object. If get_information is not allowed, the protocol
error no_information is raised.
Sends all matching events describing an image description object exactly
once and finally sends the 'done' event.
This means
- if the image description is parametric, it must send
- primaries
- named_primaries, if applicable
- at least one of tf_power and tf_named, as applicable
- luminances
- target_primaries
- target_luminance
- if the image description is parametric, it may send, if applicable,
- target_max_cll
- target_max_fall
- if the image description contains an ICC profile, it must send the
icc_file event
Once a wp_image_description_info_v1 object has delivered a 'done' event it
is automatically destroyed.
Every wp_image_description_info_v1 created from the same
wp_image_description_v1 shall always return the exact same data.
Signals the end of information events and destroys the object.
The icc argument provides a file descriptor to the client which may be
memory-mapped to provide the ICC profile matching the image description.
The fd is read-only, and if mapped then it must be mapped with
MAP_PRIVATE by the client.
The ICC profile version and other details are determined by the
compositor. There is no provision for a client to ask for a specific
kind of a profile.
Delivers the primary color volume primaries and white point using CIE
1931 xy chromaticity coordinates.
Each coordinate value is multiplied by 1 million to get the argument
value to carry precision of 6 decimals.
Delivers the primary color volume primaries and white point using an
explicitly enumerated named set.
The color component transfer characteristic of this image description is
a pure power curve. This event provides the exponent of the power
function. This curve represents the conversion from electrical to
optical pixel or color values.
The curve exponent has been multiplied by 10000 to get the argument eexp
value to carry the precision of 4 decimals.
Delivers the transfer characteristic using an explicitly enumerated
named function.
Delivers the primary color volume luminance range and the reference
white luminance level. These values include the minimum display emission
and ambient flare luminances, assumed to be optically additive and have
the chromaticity of the primary color volume white point.
The minimum luminance is multiplied by 10000 to get the argument
'min_lum' value and carries precision of 4 decimals. The maximum
luminance and reference white luminance values are unscaled.
Provides the color primaries and white point of the target color volume
using CIE 1931 xy chromaticity coordinates. This is compatible with the
SMPTE ST 2086 definition of HDR static metadata for mastering displays.
While primary color volume is about how color is encoded, the target
color volume is the actually displayable color volume. If target color
volume is equal to the primary color volume, then this event is not
sent.
Each coordinate value is multiplied by 1 million to get the argument
value to carry precision of 6 decimals.
Provides the luminance range that the image description is targeting as
the minimum and maximum absolute luminance L. These values include the
minimum display emission and ambient flare luminances, assumed to be
optically additive and have the chromaticity of the primary color
volume white point. This should be compatible with the SMPTE ST 2086
definition of HDR static metadata.
This luminance range is only theoretical and may not correspond to the
luminance of light emitted on an actual display.
Min L value is multiplied by 10000 to get the argument min_lum value and
carry precision of 4 decimals. Max L value is unscaled for max_lum.
Provides the targeted max_cll of the image description. max_cll is
defined by CTA-861-H.
This luminance is only theoretical and may not correspond to the
luminance of light emitted on an actual display.
Provides the targeted max_fall of the image description. max_fall is
defined by CTA-861-H.
This luminance is only theoretical and may not correspond to the
luminance of light emitted on an actual display.
waypipe-v0.10.5/protocols/commit-timing-v1.xml 0000664 0000000 0000000 00000012630 15070717111 0021312 0 ustar 00root root 0000000 0000000
Copyright © 2023 Valve 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.
When a compositor latches on to new content updates it will check for
any number of requirements of the available content updates (such as
fences of all buffers being signalled) to consider the update ready.
This protocol provides a method for adding a time constraint to surface
content. This constraint indicates to the compositor that a content
update should be presented as closely as possible to, but not before,
a specified time.
This protocol does not change the Wayland property that content
updates are applied in the order they are received, even when some
content updates contain timestamps and others do not.
To provide timestamps, this global factory interface must be used to
acquire a wp_commit_timing_v1 object for a surface, which may then be
used to provide timestamp information for commits.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
Informs the server that the client will no longer be using
this protocol object. Existing objects created by this object
are not affected.
Establish a timing controller for a surface.
Only one commit timer can be created for a surface, or a
commit_timer_exists protocol error will be generated.
An object to set a time constraint for a content update on a surface.
Provide a timing constraint for a surface content update.
A set_timestamp request may be made before a wl_surface.commit to
tell the compositor that the content is intended to be presented
as closely as possible to, but not before, the specified time.
The time is in the domain of the compositor's presentation clock.
An invalid_timestamp error will be generated for invalid tv_nsec.
If a timestamp already exists on the surface, a timestamp_exists
error is generated.
Requesting set_timestamp after the commit_timer object's surface is
destroyed will generate a "surface_destroyed" error.
Informs the server that the client will no longer be using
this protocol object.
Existing timing constraints are not affected by the destruction.
waypipe-v0.10.5/protocols/ext-data-control-v1.xml 0000664 0000000 0000000 00000027375 15070717111 0021736 0 ustar 00root root 0000000 0000000
Copyright © 2018 Simon Ser
Copyright © 2019 Ivan Molodetskikh
Copyright © 2024 Neal Gompa
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
This protocol allows a privileged client to control data devices. In
particular, the client will be able to manage the current selection and take
the role of a clipboard manager.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
This interface is a manager that allows creating per-seat data device
controls.
Create a new data source.
Create a data device that can be used to manage a seat's selection.
All objects created by the manager will still remain valid, until their
appropriate destroy request has been called.
This interface allows a client to manage a seat's selection.
When the seat is destroyed, this object becomes inert.
This request asks the compositor to set the selection to the data from
the source on behalf of the client.
The given source may not be used in any further set_selection or
set_primary_selection requests. Attempting to use a previously used
source triggers the used_source protocol error.
To unset the selection, set the source to NULL.
Destroys the data device object.
The data_offer event introduces a new ext_data_control_offer object,
which will subsequently be used in either the
ext_data_control_device.selection event (for the regular clipboard
selections) or the ext_data_control_device.primary_selection event (for
the primary clipboard selections). Immediately following the
ext_data_control_device.data_offer event, the new data_offer object
will send out ext_data_control_offer.offer events to describe the MIME
types it offers.
The selection event is sent out to notify the client of a new
ext_data_control_offer for the selection for this device. The
ext_data_control_device.data_offer and the ext_data_control_offer.offer
events are sent out immediately before this event to introduce the data
offer object. The selection event is sent to a client when a new
selection is set. The ext_data_control_offer is valid until a new
ext_data_control_offer or NULL is received. The client must destroy the
previous selection ext_data_control_offer, if any, upon receiving this
event. Regardless, the previous selection will be ignored once a new
selection ext_data_control_offer is received.
The first selection event is sent upon binding the
ext_data_control_device object.
This data control object is no longer valid and should be destroyed by
the client.
The primary_selection event is sent out to notify the client of a new
ext_data_control_offer for the primary selection for this device. The
ext_data_control_device.data_offer and the ext_data_control_offer.offer
events are sent out immediately before this event to introduce the data
offer object. The primary_selection event is sent to a client when a
new primary selection is set. The ext_data_control_offer is valid until
a new ext_data_control_offer or NULL is received. The client must
destroy the previous primary selection ext_data_control_offer, if any,
upon receiving this event. Regardless, the previous primary selection
will be ignored once a new primary selection ext_data_control_offer is
received.
If the compositor supports primary selection, the first
primary_selection event is sent upon binding the
ext_data_control_device object.
This request asks the compositor to set the primary selection to the
data from the source on behalf of the client.
The given source may not be used in any further set_selection or
set_primary_selection requests. Attempting to use a previously used
source triggers the used_source protocol error.
To unset the primary selection, set the source to NULL.
The compositor will ignore this request if it does not support primary
selection.
The ext_data_control_source object is the source side of a
ext_data_control_offer. It is created by the source client in a data
transfer and provides a way to describe the offered data and a way to
respond to requests to transfer the data.
This request adds a MIME type to the set of MIME types advertised to
targets. Can be called several times to offer multiple types.
Calling this after ext_data_control_device.set_selection is a protocol
error.
Destroys the data source object.
Request for data from the client. Send the data as the specified MIME
type over the passed file descriptor, then close it.
This data source is no longer valid. The data source has been replaced
by another data source.
The client should clean up and destroy this data source.
A ext_data_control_offer represents a piece of data offered for transfer
by another client (the source client). The offer describes the different
MIME types that the data can be converted to and provides the mechanism
for transferring the data directly from the source client.
To transfer the offered data, the client issues this request and
indicates the MIME type it wants to receive. The transfer happens
through the passed file descriptor (typically created with the pipe
system call). The source client writes the data in the MIME type
representation requested and then closes the file descriptor.
The receiving client reads from the read end of the pipe until EOF and
then closes its end, at which point the transfer is complete.
This request may happen multiple times for different MIME types.
Destroys the data offer object.
Sent immediately after creating the ext_data_control_offer object.
One event per offered MIME type.
waypipe-v0.10.5/protocols/ext-foreign-toplevel-list-v1.xml 0000664 0000000 0000000 00000023446 15070717111 0023574 0 ustar 00root root 0000000 0000000
Copyright © 2018 Ilia Bozhinov
Copyright © 2020 Isaac Freund
Copyright © 2022 wb9688
Copyright © 2023 i509VCB
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
The purpose of this protocol is to provide protocol object handles for
toplevels, possibly originating from another client.
This protocol is intentionally minimalistic and expects additional
functionality (e.g. creating a screencopy source from a toplevel handle,
getting information about the state of the toplevel) to be implemented
in extension protocols.
The compositor may choose to restrict this protocol to a special client
launched by the compositor itself or expose it to all clients,
this is compositor policy.
The key words "must", "must not", "required", "shall", "shall not",
"should", "should not", "recommended", "may", and "optional" in this
document are to be interpreted as described in IETF RFC 2119.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
A toplevel is defined as a surface with a role similar to xdg_toplevel.
XWayland surfaces may be treated like toplevels in this protocol.
After a client binds the ext_foreign_toplevel_list_v1, each mapped
toplevel window will be sent using the ext_foreign_toplevel_list_v1.toplevel
event.
Clients which only care about the current state can perform a roundtrip after
binding this global.
For each instance of ext_foreign_toplevel_list_v1, the compositor must
create a new ext_foreign_toplevel_handle_v1 object for each mapped toplevel.
If a compositor implementation sends the ext_foreign_toplevel_list_v1.finished
event after the global is bound, the compositor must not send any
ext_foreign_toplevel_list_v1.toplevel events.
This event is emitted whenever a new toplevel window is created. It is
emitted for all toplevels, regardless of the app that has created them.
All initial properties of the toplevel (identifier, title, app_id) will be sent
immediately after this event using the corresponding events for
ext_foreign_toplevel_handle_v1. The compositor will use the
ext_foreign_toplevel_handle_v1.done event to indicate when all data has
been sent.
This event indicates that the compositor is done sending events
to this object. The client should destroy the object.
See ext_foreign_toplevel_list_v1.destroy for more information.
The compositor must not send any more toplevel events after this event.
This request indicates that the client no longer wishes to receive
events for new toplevels.
The Wayland protocol is asynchronous, meaning the compositor may send
further toplevel events until the stop request is processed.
The client should wait for a ext_foreign_toplevel_list_v1.finished
event before destroying this object.
This request should be called either when the client will no longer
use the ext_foreign_toplevel_list_v1 or after the finished event
has been received to allow destruction of the object.
If a client wishes to destroy this object it should send a
ext_foreign_toplevel_list_v1.stop request and wait for a ext_foreign_toplevel_list_v1.finished
event, then destroy the handles and then this object.
A ext_foreign_toplevel_handle_v1 object represents a mapped toplevel
window. A single app may have multiple mapped toplevels.
This request should be used when the client will no longer use the handle
or after the closed event has been received to allow destruction of the
object.
When a handle is destroyed, a new handle may not be created by the server
until the toplevel is unmapped and then remapped. Destroying a toplevel handle
is not recommended unless the client is cleaning up child objects
before destroying the ext_foreign_toplevel_list_v1 object, the toplevel
was closed or the toplevel handle will not be used in the future.
Other protocols which extend the ext_foreign_toplevel_handle_v1
interface should require destructors for extension interfaces be
called before allowing the toplevel handle to be destroyed.
The server will emit no further events on the ext_foreign_toplevel_handle_v1
after this event. Any requests received aside from the destroy request must
be ignored. Upon receiving this event, the client should destroy the handle.
Other protocols which extend the ext_foreign_toplevel_handle_v1
interface must also ignore requests other than destructors.
This event is sent after all changes in the toplevel state have
been sent.
This allows changes to the ext_foreign_toplevel_handle_v1 properties
to be atomically applied. Other protocols which extend the
ext_foreign_toplevel_handle_v1 interface may use this event to also
atomically apply any pending state.
This event must not be sent after the ext_foreign_toplevel_handle_v1.closed
event.
The title of the toplevel has changed.
The configured state must not be applied immediately. See
ext_foreign_toplevel_handle_v1.done for details.
The app id of the toplevel has changed.
The configured state must not be applied immediately. See
ext_foreign_toplevel_handle_v1.done for details.
This identifier is used to check if two or more toplevel handles belong
to the same toplevel.
The identifier is useful for command line tools or privileged clients
which may need to reference an exact toplevel across processes or
instances of the ext_foreign_toplevel_list_v1 global.
The compositor must only send this event when the handle is created.
The identifier must be unique per toplevel and it's handles. Two different
toplevels must not have the same identifier. The identifier is only valid
as long as the toplevel is mapped. If the toplevel is unmapped the identifier
must not be reused. An identifier must not be reused by the compositor to
ensure there are no races when sharing identifiers between processes.
An identifier is a string that contains up to 32 printable ASCII bytes.
An identifier must not be an empty string. It is recommended that a
compositor includes an opaque generation value in identifiers. How the
generation value is used when generating the identifier is implementation
dependent.
waypipe-v0.10.5/protocols/ext-image-capture-source-v1.xml 0000664 0000000 0000000 00000011635 15070717111 0023360 0 ustar 00root root 0000000 0000000
Copyright © 2022 Andri Yngvason
Copyright © 2024 Simon Ser
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.
This protocol serves as an intermediary between capturing protocols and
potential image capture sources such as outputs and toplevels.
This protocol may be extended to support more image capture sources in the
future, thereby adding those image capture sources to other protocols that
use the image capture source object without having to modify those
protocols.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
The image capture source object is an opaque descriptor for a capturable
resource. This resource may be any sort of entity from which an image
may be derived.
Note, because ext_image_capture_source_v1 objects are created from multiple
independent factory interfaces, the ext_image_capture_source_v1 interface is
frozen at version 1.
Destroys the image capture source. This request may be sent at any time
by the client.
A manager for creating image capture source objects for wl_output objects.
Creates a source object for an output. Images captured from this source
will show the same content as the output. Some elements may be omitted,
such as cursors and overlays that have been marked as transparent to
capturing.
Destroys the manager. This request may be sent at any time by the client
and objects created by the manager will remain valid after its
destruction.
A manager for creating image capture source objects for
ext_foreign_toplevel_handle_v1 objects.
Creates a source object for a foreign toplevel handle. Images captured
from this source will show the same content as the toplevel.
Destroys the manager. This request may be sent at any time by the client
and objects created by the manager will remain valid after its
destruction.
waypipe-v0.10.5/protocols/ext-image-copy-capture-v1.xml 0000664 0000000 0000000 00000045076 15070717111 0023040 0 ustar 00root root 0000000 0000000
Copyright © 2021-2023 Andri Yngvason
Copyright © 2024 Simon Ser
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.
This protocol allows clients to ask the compositor to capture image sources
such as outputs and toplevels into user submitted buffers.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
This object is a manager which offers requests to start capturing from a
source.
Create a capturing session for an image capture source.
If the paint_cursors option is set, cursors shall be composited onto
the captured frame. The cursor must not be composited onto the frame
if this flag is not set.
If the options bitfield is invalid, the invalid_option protocol error
is sent.
Create a cursor capturing session for the pointer of an image capture
source.
Destroy the manager object.
Other objects created via this interface are unaffected.
This object represents an active image copy capture session.
After a capture session is created, buffer constraint events will be
emitted from the compositor to tell the client which buffer types and
formats are supported for reading from the session. The compositor may
re-send buffer constraint events whenever they change.
To advertise buffer constraints, the compositor must send in no
particular order: zero or more shm_format and dmabuf_format events, zero
or one dmabuf_device event, and exactly one buffer_size event. Then the
compositor must send a done event.
When the client has received all the buffer constraints, it can create a
buffer accordingly, attach it to the capture session using the
attach_buffer request, set the buffer damage using the damage_buffer
request and then send the capture request.
Provides the dimensions of the source image in buffer pixel coordinates.
The client must attach buffers that match this size.
Provides the format that must be used for shared-memory buffers.
This event may be emitted multiple times, in which case the client may
choose any given format.
This event advertises the device buffers must be allocated on for
dma-buf buffers.
In general the device is a DRM node. The DRM node type (primary vs.
render) is unspecified. Clients must not rely on the compositor sending
a particular node type. Clients cannot check two devices for equality
by comparing the dev_t value.
Provides the format that must be used for dma-buf buffers.
The client may choose any of the modifiers advertised in the array of
64-bit unsigned integers.
This event may be emitted multiple times, in which case the client may
choose any given format.
This event is sent once when all buffer constraint events have been
sent.
The compositor must always end a batch of buffer constraint events with
this event, regardless of whether it sends the initial constraints or
an update.
This event indicates that the capture session has stopped and is no
longer available. This can happen in a number of cases, e.g. when the
underlying source is destroyed, if the user decides to end the image
capture, or if an unrecoverable runtime error has occurred.
The client should destroy the session after receiving this event.
Create a capture frame for this session.
At most one frame object can exist for a given session at any time. If
a client sends a create_frame request before a previous frame object
has been destroyed, the duplicate_frame protocol error is raised.
Destroys the session. This request can be sent at any time by the
client.
This request doesn't affect ext_image_copy_capture_frame_v1 objects created by
this object.
This object represents an image capture frame.
The client should attach a buffer, damage the buffer, and then send a
capture request.
If the capture is successful, the compositor must send the frame metadata
(transform, damage, presentation_time in any order) followed by the ready
event.
If the capture fails, the compositor must send the failed event.
Destroys the frame. This request can be sent at any time by the
client.
Attach a buffer to the session.
The wl_buffer.release request is unused.
The new buffer replaces any previously attached buffer.
This request must not be sent after capture, or else the
already_captured protocol error is raised.
Apply damage to the buffer which is to be captured next. This request
may be sent multiple times to describe a region.
The client indicates the accumulated damage since this wl_buffer was
last captured. During capture, the compositor will update the buffer
with at least the union of the region passed by the client and the
region advertised by ext_image_copy_capture_frame_v1.damage.
When a wl_buffer is captured for the first time, or when the client
doesn't track damage, the client must damage the whole buffer.
This is for optimisation purposes. The compositor may use this
information to reduce copying.
These coordinates originate from the upper left corner of the buffer.
If x or y are strictly negative, or if width or height are negative or
zero, the invalid_buffer_damage protocol error is raised.
This request must not be sent after capture, or else the
already_captured protocol error is raised.
Capture a frame.
Unless this is the first successful captured frame performed in this
session, the compositor may wait an indefinite amount of time for the
source content to change before performing the copy.
This request may only be sent once, or else the already_captured
protocol error is raised. A buffer must be attached before this request
is sent, or else the no_buffer protocol error is raised.
This event is sent before the ready event and holds the transform that
the compositor has applied to the buffer contents.
This event is sent before the ready event. It may be generated multiple
times to describe a region.
The first captured frame in a session will always carry full damage.
Subsequent frames' damaged regions describe which parts of the buffer
have changed since the last ready event.
These coordinates originate in the upper left corner of the buffer.
This event indicates the time at which the frame is presented to the
output in system monotonic time. This event is sent before the ready
event.
The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
each component being an unsigned 32-bit value. Whole seconds are in
tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
and the additional fractional part in tv_nsec as nanoseconds. Hence,
for valid timestamps tv_nsec must be in [0, 999999999].
Called as soon as the frame is copied, indicating it is available
for reading.
The buffer may be re-used by the client after this event.
After receiving this event, the client must destroy the object.
An unspecified runtime error has occurred. The client may retry.
The buffer submitted by the client doesn't match the latest session
constraints. The client should re-allocate its buffers and retry.
The session has stopped. See ext_image_copy_capture_session_v1.stopped.
This event indicates that the attempted frame copy has failed.
After receiving this event, the client must destroy the object.
This object represents a cursor capture session. It extends the base
capture session with cursor-specific metadata.
Destroys the session. This request can be sent at any time by the
client.
This request doesn't affect ext_image_copy_capture_frame_v1 objects created by
this object.
Gets the image copy capture session for this cursor session.
The session will produce frames of the cursor image. The compositor may
pause the session when the cursor leaves the captured area.
This request must not be sent more than once, or else the
duplicate_session protocol error is raised.
Sent when a cursor enters the captured area. It shall be generated
before the "position" and "hotspot" events when and only when a cursor
enters the area.
The cursor enters the captured area when the cursor image intersects
with the captured area. Note, this is different from e.g.
wl_pointer.enter.
Sent when a cursor leaves the captured area. No "position" or "hotspot"
event is generated for the cursor until the cursor enters the captured
area again.
Cursors outside the image capture source do not get captured and no
event will be generated for them.
The given position is the position of the cursor's hotspot and it is
relative to the main buffer's top left corner in transformed buffer
pixel coordinates. The coordinates may be negative or greater than the
main buffer size.
The hotspot describes the offset between the cursor image and the
position of the input device.
The given coordinates are the hotspot's offset from the origin in
buffer coordinates.
Clients should not apply the hotspot immediately: the hotspot becomes
effective when the next ext_image_copy_capture_frame_v1.ready event is received.
Compositors may delay this event until the client captures a new frame.
waypipe-v0.10.5/protocols/gtk-primary-selection.xml 0000664 0000000 0000000 00000023711 15070717111 0022444 0 ustar 00root root 0000000 0000000
Copyright © 2015, 2016 Red Hat
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.
This protocol provides the ability to have a primary selection device to
match that of the X server. This primary selection is a shortcut to the
common clipboard selection, where text just needs to be selected in order
to allow copying it elsewhere. The de facto way to perform this action
is the middle mouse button, although it is not limited to this one.
Clients wishing to honor primary selection should create a primary
selection source and set it as the selection through
wp_primary_selection_device.set_selection whenever the text selection
changes. In order to minimize calls in pointer-driven text selection,
it should happen only once after the operation finished. Similarly,
a NULL source should be set when text is unselected.
wp_primary_selection_offer objects are first announced through the
wp_primary_selection_device.data_offer event. Immediately after this event,
the primary data offer will emit wp_primary_selection_offer.offer events
to let know of the mime types being offered.
When the primary selection changes, the client with the keyboard focus
will receive wp_primary_selection_device.selection events. Only the client
with the keyboard focus will receive such events with a non-NULL
wp_primary_selection_offer. Across keyboard focus changes, previously
focused clients will receive wp_primary_selection_device.events with a
NULL wp_primary_selection_offer.
In order to request the primary selection data, the client must pass
a recent serial pertaining to the press event that is triggering the
operation, if the compositor deems the serial valid and recent, the
wp_primary_selection_source.send event will happen in the other end
to let the transfer begin. The client owning the primary selection
should write the requested data, and close the file descriptor
immediately.
If the primary selection owner client disappeared during the transfer,
the client reading the data will receive a
wp_primary_selection_device.selection event with a NULL
wp_primary_selection_offer, the client should take this as a hint
to finish the reads related to the no longer existing offer.
The primary selection owner should be checking for errors during
writes, merely cancelling the ongoing transfer if any happened.
The primary selection device manager is a singleton global object that
provides access to the primary selection. It allows to create
wp_primary_selection_source objects, as well as retrieving the per-seat
wp_primary_selection_device objects.
Create a new primary selection source.
Create a new data device for a given seat.
Destroy the primary selection device manager.
Replaces the current selection. The previous owner of the primary selection
will receive a wp_primary_selection_source.cancelled event.
To unset the selection, set the source to NULL.
Introduces a new wp_primary_selection_offer object that may be used
to receive the current primary selection. Immediately following this
event, the new wp_primary_selection_offer object will send
wp_primary_selection_offer.offer events to describe the offered mime
types.
The wp_primary_selection_device.selection event is sent to notify the
client of a new primary selection. This event is sent after the
wp_primary_selection.data_offer event introducing this object, and after
the offer has announced its mimetypes through
wp_primary_selection_offer.offer.
The data_offer is valid until a new offer or NULL is received
or until the client loses keyboard focus. The client must destroy the
previous selection data_offer, if any, upon receiving this event.
Destroy the primary selection device.
A wp_primary_selection_offer represents an offer to transfer the contents
of the primary selection clipboard to the client. Similar to
wl_data_offer, the offer also describes the mime types that the source
will transferthat the
data can be converted to and provides the mechanisms for transferring the
data directly to the client.
To transfer the contents of the primary selection clipboard, the client
issues this request and indicates the mime type that it wants to
receive. The transfer happens through the passed file descriptor
(typically created with the pipe system call). The source client writes
the data in the mime type representation requested and then closes the
file descriptor.
The receiving client reads from the read end of the pipe until EOF and
closes its end, at which point the transfer is complete.
Destroy the primary selection offer.
Sent immediately after creating announcing the wp_primary_selection_offer
through wp_primary_selection_device.data_offer. One event is sent per
offered mime type.
The source side of a wp_primary_selection_offer, it provides a way to
describe the offered data and respond to requests to transfer the
requested contents of the primary selection clipboard.
This request adds a mime type to the set of mime types advertised to
targets. Can be called several times to offer multiple types.
Destroy the primary selection source.
Request for the current primary selection contents from the client.
Send the specified mime type over the passed file descriptor, then
close it.
This primary selection source is no longer valid. The client should
clean up and destroy this primary selection source.
waypipe-v0.10.5/protocols/input-method-unstable-v2.xml 0000664 0000000 0000000 00000051552 15070717111 0022774 0 ustar 00root root 0000000 0000000
Copyright © 2008-2011 Kristian Høgsberg
Copyright © 2010-2011 Intel Corporation
Copyright © 2012-2013 Collabora, Ltd.
Copyright © 2012, 2013 Intel Corporation
Copyright © 2015, 2016 Jan Arne Petersen
Copyright © 2017, 2018 Red Hat, Inc.
Copyright © 2018 Purism SPC
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.
This protocol allows applications to act as input methods for compositors.
An input method context is used to manage the state of the input method.
Text strings are UTF-8 encoded, their indices and lengths are in bytes.
This document adheres to the RFC 2119 when using words like "must",
"should", "may", etc.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
An input method object allows for clients to compose text.
The objects connects the client to a text input in an application, and
lets the client to serve as an input method for a seat.
The zwp_input_method_v2 object can occupy two distinct states: active and
inactive. In the active state, the object is associated to and
communicates with a text input. In the inactive state, there is no
associated text input, and the only communication is with the compositor.
Initially, the input method is in the inactive state.
Requests issued in the inactive state must be accepted by the compositor.
Because of the serial mechanism, and the state reset on activate event,
they will not have any effect on the state of the next text input.
There must be no more than one input method object per seat.
Notification that a text input focused on this seat requested the input
method to be activated.
This event serves the purpose of providing the compositor with an
active input method.
This event resets all state associated with previous enable, disable,
surrounding_text, text_change_cause, and content_type events, as well
as the state associated with set_preedit_string, commit_string, and
delete_surrounding_text requests. In addition, it marks the
zwp_input_method_v2 object as active, and makes any existing
zwp_input_popup_surface_v2 objects visible.
The surrounding_text, and content_type events must follow before the
next done event if the text input supports the respective
functionality.
State set with this event is double-buffered. It will get applied on
the next zwp_input_method_v2.done event, and stay valid until changed.
Notification that no focused text input currently needs an active
input method on this seat.
This event marks the zwp_input_method_v2 object as inactive. The
compositor must make all existing zwp_input_popup_surface_v2 objects
invisible until the next activate event.
State set with this event is double-buffered. It will get applied on
the next zwp_input_method_v2.done event, and stay valid until changed.
Updates the surrounding plain text around the cursor, excluding the
preedit text.
If any preedit text is present, it is replaced with the cursor for the
purpose of this event.
The argument text is a buffer containing the preedit string, and must
include the cursor position, and the complete selection. It should
contain additional characters before and after these. There is a
maximum length of wayland messages, so text can not be longer than 4000
bytes.
cursor is the byte offset of the cursor within the text buffer.
anchor is the byte offset of the selection anchor within the text
buffer. If there is no selected text, anchor must be the same as
cursor.
If this event does not arrive before the first done event, the input
method may assume that the text input does not support this
functionality and ignore following surrounding_text events.
Values set with this event are double-buffered. They will get applied
and set to initial values on the next zwp_input_method_v2.done
event.
The initial state for affected fields is empty, meaning that the text
input does not support sending surrounding text. If the empty values
get applied, subsequent attempts to change them may have no effect.
Tells the input method why the text surrounding the cursor changed.
Whenever the client detects an external change in text, cursor, or
anchor position, it must issue this request to the compositor. This
request is intended to give the input method a chance to update the
preedit text in an appropriate way, e.g. by removing it when the user
starts typing with a keyboard.
cause describes the source of the change.
The value set with this event is double-buffered. It will get applied
and set to its initial value on the next zwp_input_method_v2.done
event.
The initial value of cause is input_method.
Indicates the content type and hint for the current
zwp_input_method_v2 instance.
Values set with this event are double-buffered. They will get applied
on the next zwp_input_method_v2.done event.
The initial value for hint is none, and the initial value for purpose
is normal.
Atomically applies state changes recently sent to the client.
The done event establishes and updates the state of the client, and
must be issued after any changes to apply them.
Text input state (content purpose, content hint, surrounding text, and
change cause) is conceptually double-buffered within an input method
context.
Events modify the pending state, as opposed to the current state in use
by the input method. A done event atomically applies all pending state,
replacing the current state. After done, the new pending state is as
documented for each related request.
Events must be applied in the order of arrival.
Neither current nor pending state are modified unless noted otherwise.
Send the commit string text for insertion to the application.
Inserts a string at current cursor position (see commit event
sequence). The string to commit could be either just a single character
after a key press or the result of some composing.
The argument text is a buffer containing the string to insert. There is
a maximum length of wayland messages, so text can not be longer than
4000 bytes.
Values set with this event are double-buffered. They must be applied
and reset to initial on the next zwp_text_input_v3.commit request.
The initial value of text is an empty string.
Send the pre-edit string text to the application text input.
Place a new composing text (pre-edit) at the current cursor position.
Any previously set composing text must be removed. Any previously
existing selected text must be removed. The cursor is moved to a new
position within the preedit string.
The argument text is a buffer containing the preedit string. There is
a maximum length of wayland messages, so text can not be longer than
4000 bytes.
The arguments cursor_begin and cursor_end are counted in bytes relative
to the beginning of the submitted string buffer. Cursor should be
hidden by the text input when both are equal to -1.
cursor_begin indicates the beginning of the cursor. cursor_end
indicates the end of the cursor. It may be equal or different than
cursor_begin.
Values set with this event are double-buffered. They must be applied on
the next zwp_input_method_v2.commit event.
The initial value of text is an empty string. The initial value of
cursor_begin, and cursor_end are both 0.
Remove the surrounding text.
before_length and after_length are the number of bytes before and after
the current cursor index (excluding the preedit text) to delete.
If any preedit text is present, it is replaced with the cursor for the
purpose of this event. In effect before_length is counted from the
beginning of preedit text, and after_length from its end (see commit
event sequence).
Values set with this event are double-buffered. They must be applied
and reset to initial on the next zwp_input_method_v2.commit request.
The initial values of both before_length and after_length are 0.
Apply state changes from commit_string, set_preedit_string and
delete_surrounding_text requests.
The state relating to these events is double-buffered, and each one
modifies the pending state. This request replaces the current state
with the pending state.
The connected text input is expected to proceed by evaluating the
changes in the following order:
1. Replace existing preedit string with the cursor.
2. Delete requested surrounding text.
3. Insert commit string with the cursor at its end.
4. Calculate surrounding text to send.
5. Insert new preedit text in cursor position.
6. Place cursor inside preedit text.
The serial number reflects the last state of the zwp_input_method_v2
object known to the client. The value of the serial argument must be
equal to the number of done events already issued by that object. When
the compositor receives a commit request with a serial different than
the number of past done events, it must proceed as normal, except it
should not change the current state of the zwp_input_method_v2 object.
Creates a new zwp_input_popup_surface_v2 object wrapping a given
surface.
The surface gets assigned the "input_popup" role. If the surface
already has an assigned role, the compositor must issue a protocol
error.
Allow an input method to receive hardware keyboard input and process
key events to generate text events (with pre-edit) over the wire. This
allows input methods which compose multiple key events for inputting
text like it is done for CJK languages.
The compositor should send all keyboard events on the seat to the grab
holder via the returned wl_keyboard object. Nevertheless, the
compositor may decide not to forward any particular event. The
compositor must not further process any event after it has been
forwarded to the grab holder.
Releasing the resulting wl_keyboard object releases the grab.
The input method ceased to be available.
The compositor must issue this event as the only event on the object if
there was another input_method object associated with the same seat at
the time of its creation.
The compositor must issue this request when the object is no longer
usable, e.g. due to seat removal.
The input method context becomes inert and should be destroyed after
deactivation is handled. Any further requests and events except for the
destroy request must be ignored.
Destroys the zwp_text_input_v2 object and any associated child
objects, i.e. zwp_input_popup_surface_v2 and
zwp_input_method_keyboard_grab_v2.
This interface marks a surface as a popup for interacting with an input
method.
The compositor should place it near the active text input area. It must
be visible if and only if the input method is in the active state.
The client must not destroy the underlying wl_surface while the
zwp_input_popup_surface_v2 object exists.
Notify about the position of the area of the text input expressed as a
rectangle in surface local coordinates.
This is a hint to the input method telling it the relative position of
the text being entered.
The zwp_input_method_keyboard_grab_v2 interface represents an exclusive
grab of the wl_keyboard interface associated with the seat.
This event provides a file descriptor to the client which can be
memory-mapped to provide a keyboard mapping description.
A key was pressed or released.
The time argument is a timestamp with millisecond granularity, with an
undefined base.
Notifies clients that the modifier and/or group state has changed, and
it should update its local state.
Informs the client about the keyboard's repeat rate and delay.
This event is sent as soon as the zwp_input_method_keyboard_grab_v2
object has been created, and is guaranteed to be received by the
client before any key press event.
Negative values for either rate or delay are illegal. A rate of zero
will disable any repeating (regardless of the value of delay).
This event can be sent later on as well with a new value if necessary,
so clients should continue listening for the event past the creation
of zwp_input_method_keyboard_grab_v2.
The input method manager allows the client to become the input method on
a chosen seat.
No more than one input method must be associated with any seat at any
given time.
Request a new input zwp_input_method_v2 object associated with a given
seat.
Destroys the zwp_input_method_manager_v2 object.
The zwp_input_method_v2 objects originating from it remain valid.
waypipe-v0.10.5/protocols/linux-dmabuf-v1.xml 0000664 0000000 0000000 00000067652 15070717111 0021146 0 ustar 00root root 0000000 0000000
Copyright © 2014, 2015 Collabora, Ltd.
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.
Following the interfaces from:
https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt
https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt
and the Linux DRM sub-system's AddFb2 ioctl.
This interface offers ways to create generic dmabuf-based wl_buffers.
Clients can use the get_surface_feedback request to get dmabuf feedback
for a particular surface. If the client wants to retrieve feedback not
tied to a surface, they can use the get_default_feedback request.
The following are required from clients:
- Clients must ensure that either all data in the dma-buf is
coherent for all subsequent read access or that coherency is
correctly handled by the underlying kernel-side dma-buf
implementation.
- Don't make any more attachments after sending the buffer to the
compositor. Making more attachments later increases the risk of
the compositor not being able to use (re-import) an existing
dmabuf-based wl_buffer.
The underlying graphics stack must ensure the following:
- The dmabuf file descriptors relayed to the server will stay valid
for the whole lifetime of the wl_buffer. This means the server may
at any time use those fds to import the dmabuf into any kernel
sub-system that might accept it.
However, when the underlying graphics stack fails to deliver the
promise, because of e.g. a device hot-unplug which raises internal
errors, after the wl_buffer has been successfully created the
compositor must not raise protocol errors to the client when dmabuf
import later fails.
To create a wl_buffer from one or more dmabufs, a client creates a
zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params
request. All planes required by the intended format are added with
the 'add' request. Finally, a 'create' or 'create_immed' request is
issued, which has the following outcome depending on the import success.
The 'create' request,
- on success, triggers a 'created' event which provides the final
wl_buffer to the client.
- on failure, triggers a 'failed' event to convey that the server
cannot use the dmabufs received from the client.
For the 'create_immed' request,
- on success, the server immediately imports the added dmabufs to
create a wl_buffer. No event is sent from the server in this case.
- on failure, the server can choose to either:
- terminate the client by raising a fatal error.
- mark the wl_buffer as failed, and send a 'failed' event to the
client. If the client uses a failed wl_buffer as an argument to any
request, the behaviour is compositor implementation-defined.
For all DRM formats and unless specified in another protocol extension,
pre-multiplied alpha is used for pixel values.
Unless specified otherwise in another protocol extension, implicit
synchronization is used. In other words, compositors and clients must
wait and signal fences implicitly passed via the DMA-BUF's reservation
mechanism.
Objects created through this interface, especially wl_buffers, will
remain valid.
This temporary object is used to collect multiple dmabuf handles into
a single batch to create a wl_buffer. It can only be used once and
should be destroyed after a 'created' or 'failed' event has been
received.
This event advertises one buffer format that the server supports.
All the supported formats are advertised once when the client
binds to this interface. A roundtrip after binding guarantees
that the client has received all supported formats.
For the definition of the format codes, see the
zwp_linux_buffer_params_v1::create request.
Starting version 4, the format event is deprecated and must not be
sent by compositors. Instead, use get_default_feedback or
get_surface_feedback.
This event advertises the formats that the server supports, along with
the modifiers supported for each format. All the supported modifiers
for all the supported formats are advertised once when the client
binds to this interface. A roundtrip after binding guarantees that
the client has received all supported format-modifier pairs.
For legacy support, DRM_FORMAT_MOD_INVALID (that is, modifier_hi ==
0x00ffffff and modifier_lo == 0xffffffff) is allowed in this event.
It indicates that the server can support the format with an implicit
modifier. When a plane has DRM_FORMAT_MOD_INVALID as its modifier, it
is as if no explicit modifier is specified. The effective modifier
will be derived from the dmabuf.
A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
a given format supports both explicit modifiers and implicit modifiers.
For the definition of the format and modifier codes, see the
zwp_linux_buffer_params_v1::create and zwp_linux_buffer_params_v1::add
requests.
Starting version 4, the modifier event is deprecated and must not be
sent by compositors. Instead, use get_default_feedback or
get_surface_feedback.
This request creates a new wp_linux_dmabuf_feedback object not bound
to a particular surface. This object will deliver feedback about dmabuf
parameters to use if the client doesn't support per-surface feedback
(see get_surface_feedback).
This request creates a new wp_linux_dmabuf_feedback object for the
specified wl_surface. This object will deliver feedback about dmabuf
parameters to use for buffers attached to this surface.
If the surface is destroyed before the wp_linux_dmabuf_feedback object,
the feedback object becomes inert.
This temporary object is a collection of dmabufs and other
parameters that together form a single logical buffer. The temporary
object may eventually create one wl_buffer unless cancelled by
destroying it before requesting 'create'.
Single-planar formats only require one dmabuf, however
multi-planar formats may require more than one dmabuf. For all
formats, an 'add' request must be called once per plane (even if the
underlying dmabuf fd is identical).
You must use consecutive plane indices ('plane_idx' argument for 'add')
from zero to the number of planes used by the drm_fourcc format code.
All planes required by the format must be given exactly once, but can
be given in any order. Each plane index can be set only once.
Cleans up the temporary data sent to the server for dmabuf-based
wl_buffer creation.
This request adds one dmabuf to the set in this
zwp_linux_buffer_params_v1.
The 64-bit unsigned value combined from modifier_hi and modifier_lo
is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the
fb modifier, which is defined in drm_mode.h of Linux UAPI.
This is an opaque token. Drivers use this token to express tiling,
compression, etc. driver-specific modifications to the base format
defined by the DRM fourcc code.
Starting from version 4, the invalid_format protocol error is sent if
the format + modifier pair was not advertised as supported.
Starting from version 5, the invalid_format protocol error is sent if
all planes don't use the same modifier.
This request raises the PLANE_IDX error if plane_idx is too large.
The error PLANE_SET is raised if attempting to set a plane that
was already set.
This asks for creation of a wl_buffer from the added dmabuf
buffers. The wl_buffer is not created immediately but returned via
the 'created' event if the dmabuf sharing succeeds. The sharing
may fail at runtime for reasons a client cannot predict, in
which case the 'failed' event is triggered.
The 'format' argument is a DRM_FORMAT code, as defined by the
libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the
authoritative source on how the format codes should work.
The 'flags' is a bitfield of the flags defined in enum "flags".
'y_invert' means the that the image needs to be y-flipped.
Flag 'interlaced' means that the frame in the buffer is not
progressive as usual, but interlaced. An interlaced buffer as
supported here must always contain both top and bottom fields.
The top field always begins on the first pixel row. The temporal
ordering between the two fields is top field first, unless
'bottom_first' is specified. It is undefined whether 'bottom_first'
is ignored if 'interlaced' is not set.
This protocol does not convey any information about field rate,
duration, or timing, other than the relative ordering between the
two fields in one buffer. A compositor may have to estimate the
intended field rate from the incoming buffer rate. It is undefined
whether the time of receiving wl_surface.commit with a new buffer
attached, applying the wl_surface state, wl_surface.frame callback
trigger, presentation, or any other point in the compositor cycle
is used to measure the frame or field times. There is no support
for detecting missed or late frames/fields/buffers either, and
there is no support whatsoever for cooperating with interlaced
compositor output.
The composited image quality resulting from the use of interlaced
buffers is explicitly undefined. A compositor may use elaborate
hardware features or software to deinterlace and create progressive
output frames from a sequence of interlaced input buffers, or it
may produce substandard image quality. However, compositors that
cannot guarantee reasonable image quality in all cases are recommended
to just reject all interlaced buffers.
Any argument errors, including non-positive width or height,
mismatch between the number of planes and the format, bad
format, bad offset or stride, may be indicated by fatal protocol
errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS,
OUT_OF_BOUNDS.
Dmabuf import errors in the server that are not obvious client
bugs are returned via the 'failed' event as non-fatal. This
allows attempting dmabuf sharing and falling back in the client
if it fails.
This request can be sent only once in the object's lifetime, after
which the only legal request is destroy. This object should be
destroyed after issuing a 'create' request. Attempting to use this
object after issuing 'create' raises ALREADY_USED protocol error.
It is not mandatory to issue 'create'. If a client wants to
cancel the buffer creation, it can just destroy this object.
This event indicates that the attempted buffer creation was
successful. It provides the new wl_buffer referencing the dmabuf(s).
Upon receiving this event, the client should destroy the
zwp_linux_buffer_params_v1 object.
This event indicates that the attempted buffer creation has
failed. It usually means that one of the dmabuf constraints
has not been fulfilled.
Upon receiving this event, the client should destroy the
zwp_linux_buffer_params_v1 object.
This asks for immediate creation of a wl_buffer by importing the
added dmabufs.
In case of import success, no event is sent from the server, and the
wl_buffer is ready to be used by the client.
Upon import failure, either of the following may happen, as seen fit
by the implementation:
- the client is terminated with one of the following fatal protocol
errors:
- INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS,
in case of argument errors such as mismatch between the number
of planes and the format, bad format, non-positive width or
height, or bad offset or stride.
- INVALID_WL_BUFFER, in case the cause for failure is unknown or
platform specific.
- the server creates an invalid wl_buffer, marks it as failed and
sends a 'failed' event to the client. The result of using this
invalid wl_buffer as an argument in any request by the client is
defined by the compositor implementation.
This takes the same arguments as a 'create' request, and obeys the
same restrictions.
This object advertises dmabuf parameters feedback. This includes the
preferred devices and the supported formats/modifiers.
The parameters are sent once when this object is created and whenever they
change. The done event is always sent once after all parameters have been
sent. When a single parameter changes, all parameters are re-sent by the
compositor.
Compositors can re-send the parameters when the current client buffer
allocations are sub-optimal. Compositors should not re-send the
parameters if re-allocating the buffers would not result in a more optimal
configuration. In particular, compositors should avoid sending the exact
same parameters multiple times in a row.
The tranche_target_device and tranche_formats events are grouped by
tranches of preference. For each tranche, a tranche_target_device, one
tranche_flags and one or more tranche_formats events are sent, followed
by a tranche_done event finishing the list. The tranches are sent in
descending order of preference. All formats and modifiers in the same
tranche have the same preference.
To send parameters, the compositor sends one main_device event, tranches
(each consisting of one tranche_target_device event, one tranche_flags
event, tranche_formats events and then a tranche_done event), then one
done event.
Using this request a client can tell the server that it is not going to
use the wp_linux_dmabuf_feedback object anymore.
This event is sent after all parameters of a wp_linux_dmabuf_feedback
object have been sent.
This allows changes to the wp_linux_dmabuf_feedback parameters to be
seen as atomic, even if they happen via multiple events.
This event provides a file descriptor which can be memory-mapped to
access the format and modifier table.
The table contains a tightly packed array of consecutive format +
modifier pairs. Each pair is 16 bytes wide. It contains a format as a
32-bit unsigned integer, followed by 4 bytes of unused padding, and a
modifier as a 64-bit unsigned integer. The native endianness is used.
The client must map the file descriptor in read-only private mode.
Compositors are not allowed to mutate the table file contents once this
event has been sent. Instead, compositors must create a new, separate
table file and re-send feedback parameters. Compositors are allowed to
store duplicate format + modifier pairs in the table.
This event advertises the main device that the server prefers to use
when direct scan-out to the target device isn't possible. The
advertised main device may be different for each
wp_linux_dmabuf_feedback object, and may change over time.
There is exactly one main device. The compositor must send at least
one preference tranche with tranche_target_device equal to main_device.
Clients need to create buffers that the main device can import and
read from, otherwise creating the dmabuf wl_buffer will fail (see the
wp_linux_buffer_params.create and create_immed requests for details).
The main device will also likely be kept active by the compositor,
so clients can use it instead of waking up another device for power
savings.
In general the device is a DRM node. The DRM node type (primary vs.
render) is unspecified. Clients must not rely on the compositor sending
a particular node type. Clients cannot check two devices for equality
by comparing the dev_t value.
If explicit modifiers are not supported and the client performs buffer
allocations on a different device than the main device, then the client
must force the buffer to have a linear layout.
This event splits tranche_target_device and tranche_formats events in
preference tranches. It is sent after a set of tranche_target_device
and tranche_formats events; it represents the end of a tranche. The
next tranche will have a lower preference.
This event advertises the target device that the server prefers to use
for a buffer created given this tranche. The advertised target device
may be different for each preference tranche, and may change over time.
There is exactly one target device per tranche.
The target device may be a scan-out device, for example if the
compositor prefers to directly scan-out a buffer created given this
tranche. The target device may be a rendering device, for example if
the compositor prefers to texture from said buffer.
The client can use this hint to allocate the buffer in a way that makes
it accessible from the target device, ideally directly. The buffer must
still be accessible from the main device, either through direct import
or through a potentially more expensive fallback path. If the buffer
can't be directly imported from the main device then clients must be
prepared for the compositor changing the tranche priority or making
wl_buffer creation fail (see the wp_linux_buffer_params.create and
create_immed requests for details).
If the device is a DRM node, the DRM node type (primary vs. render) is
unspecified. Clients must not rely on the compositor sending a
particular node type. Clients cannot check two devices for equality by
comparing the dev_t value.
This event is tied to a preference tranche, see the tranche_done event.
This event advertises the format + modifier combinations that the
compositor supports.
It carries an array of indices, each referring to a format + modifier
pair in the last received format table (see the format_table event).
Each index is a 16-bit unsigned integer in native endianness.
For legacy support, DRM_FORMAT_MOD_INVALID is an allowed modifier.
It indicates that the server can support the format with an implicit
modifier. When a buffer has DRM_FORMAT_MOD_INVALID as its modifier, it
is as if no explicit modifier is specified. The effective modifier
will be derived from the dmabuf.
A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
a given format supports both explicit modifiers and implicit modifiers.
Compositors must not send duplicate format + modifier pairs within the
same tranche or across two different tranches with the same target
device and flags.
This event is tied to a preference tranche, see the tranche_done event.
For the definition of the format and modifier codes, see the
wp_linux_buffer_params.create request.
This event sets tranche-specific flags.
The scanout flag is a hint that direct scan-out may be attempted by the
compositor on the target device if the client appropriately allocates a
buffer. How to allocate a buffer that can be scanned out on the target
device is implementation-defined.
This event is tied to a preference tranche, see the tranche_done event.
waypipe-v0.10.5/protocols/linux-drm-syncobj-v1.xml 0000664 0000000 0000000 00000030557 15070717111 0022131 0 ustar 00root root 0000000 0000000
Copyright 2016 The Chromium Authors.
Copyright 2017 Intel Corporation
Copyright 2018 Collabora, Ltd
Copyright 2021 Simon Ser
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.
This protocol allows clients to request explicit synchronization for
buffers. It is tied to the Linux DRM synchronization object framework.
Synchronization refers to co-ordination of pipelined operations performed
on buffers. Most GPU clients will schedule an asynchronous operation to
render to the buffer, then immediately send the buffer to the compositor
to be attached to a surface.
With implicit synchronization, ensuring that the rendering operation is
complete before the compositor displays the buffer is an implementation
detail handled by either the kernel or userspace graphics driver.
By contrast, with explicit synchronization, DRM synchronization object
timeline points mark when the asynchronous operations are complete. When
submitting a buffer, the client provides a timeline point which will be
waited on before the compositor accesses the buffer, and another timeline
point that the compositor will signal when it no longer needs to access the
buffer contents for the purposes of the surface commit.
Linux DRM synchronization objects are documented at:
https://dri.freedesktop.org/docs/drm/gpu/drm-mm.html#drm-sync-objects
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
This global is a factory interface, allowing clients to request
explicit synchronization for buffers on a per-surface basis.
See wp_linux_drm_syncobj_surface_v1 for more information.
Destroy this explicit synchronization factory object. Other objects
shall not be affected by this request.
Instantiate an interface extension for the given wl_surface to provide
explicit synchronization.
If the given wl_surface already has an explicit synchronization object
associated, the surface_exists protocol error is raised.
Graphics APIs, like EGL or Vulkan, that manage the buffer queue and
commits of a wl_surface themselves, are likely to be using this
extension internally. If a client is using such an API for a
wl_surface, it should not directly use this extension on that surface,
to avoid raising a surface_exists protocol error.
Import a DRM synchronization object timeline.
If the FD cannot be imported, the invalid_timeline error is raised.
This object represents an explicit synchronization object timeline
imported by the client to the compositor.
Destroy the synchronization object timeline. Other objects are not
affected by this request, in particular timeline points set by
set_acquire_point and set_release_point are not unset.
This object is an add-on interface for wl_surface to enable explicit
synchronization.
Each surface can be associated with only one object of this interface at
any time.
Explicit synchronization is guaranteed to be supported for buffers
created with any version of the linux-dmabuf protocol. Compositors are
free to support explicit synchronization for additional buffer types.
If at surface commit time the attached buffer does not support explicit
synchronization, an unsupported_buffer error is raised.
As long as the wp_linux_drm_syncobj_surface_v1 object is alive, the
compositor may ignore implicit synchronization for buffers attached and
committed to the wl_surface. The delivery of wl_buffer.release events
for buffers attached to the surface becomes undefined.
Clients must set both acquire and release points if and only if a
non-null buffer is attached in the same surface commit. See the
no_buffer, no_acquire_point and no_release_point protocol errors.
If at surface commit time the acquire and release DRM syncobj timelines
are identical, the acquire point value must be strictly less than the
release point value, or else the conflicting_points protocol error is
raised.
Destroy this surface synchronization object.
Any timeline point set by this object with set_acquire_point or
set_release_point since the last commit may be discarded by the
compositor. Any timeline point set by this object before the last
commit will not be affected.
Set the timeline point that must be signalled before the compositor may
sample from the buffer attached with wl_surface.attach.
The 64-bit unsigned value combined from point_hi and point_lo is the
point value.
The acquire point is double-buffered state, and will be applied on the
next wl_surface.commit request for the associated surface. Thus, it
applies only to the buffer that is attached to the surface at commit
time.
If an acquire point has already been attached during the same commit
cycle, the new point replaces the old one.
If the associated wl_surface was destroyed, a no_surface error is
raised.
If at surface commit time there is a pending acquire timeline point set
but no pending buffer attached, a no_buffer error is raised. If at
surface commit time there is a pending buffer attached but no pending
acquire timeline point set, the no_acquire_point protocol error is
raised.
Set the timeline point that must be signalled by the compositor when it
has finished its usage of the buffer attached with wl_surface.attach
for the relevant commit.
Once the timeline point is signaled, and assuming the associated buffer
is not pending release from other wl_surface.commit requests, no
additional explicit or implicit synchronization with the compositor is
required to safely re-use the buffer.
Note that clients cannot rely on the release point being always
signaled after the acquire point: compositors may release buffers
without ever reading from them. In addition, the compositor may use
different presentation paths for different commits, which may have
different release behavior. As a result, the compositor may signal the
release points in a different order than the client committed them.
Because signaling a timeline point also signals every previous point,
it is generally not safe to use the same timeline object for the
release points of multiple buffers. The out-of-order signaling
described above may lead to a release point being signaled before the
compositor has finished reading. To avoid this, it is strongly
recommended that each buffer should use a separate timeline for its
release points.
The 64-bit unsigned value combined from point_hi and point_lo is the
point value.
The release point is double-buffered state, and will be applied on the
next wl_surface.commit request for the associated surface. Thus, it
applies only to the buffer that is attached to the surface at commit
time.
If a release point has already been attached during the same commit
cycle, the new point replaces the old one.
If the associated wl_surface was destroyed, a no_surface error is
raised.
If at surface commit time there is a pending release timeline point set
but no pending buffer attached, a no_buffer error is raised. If at
surface commit time there is a pending buffer attached but no pending
release timeline point set, the no_release_point protocol error is
raised.
waypipe-v0.10.5/protocols/presentation-time.xml 0000664 0000000 0000000 00000031132 15070717111 0021656 0 ustar 00root root 0000000 0000000
Copyright © 2013-2014 Collabora, Ltd.
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.
The main feature of this interface is accurate presentation
timing feedback to ensure smooth video playback while maintaining
audio/video synchronization. Some features use the concept of a
presentation clock, which is defined in the
presentation.clock_id event.
A content update for a wl_surface is submitted by a
wl_surface.commit request. Request 'feedback' associates with
the wl_surface.commit and provides feedback on the content
update, particularly the final realized presentation time.
When the final realized presentation time is available, e.g.
after a framebuffer flip completes, the requested
presentation_feedback.presented events are sent. The final
presentation time can differ from the compositor's predicted
display update time and the update's target time, especially
when the compositor misses its target vertical blanking period.
These fatal protocol errors may be emitted in response to
illegal presentation requests.
Informs the server that the client will no longer be using
this protocol object. Existing objects created by this object
are not affected.
Request presentation feedback for the current content submission
on the given surface. This creates a new presentation_feedback
object, which will deliver the feedback information once. If
multiple presentation_feedback objects are created for the same
submission, they will all deliver the same information.
For details on what information is returned, see the
presentation_feedback interface.
This event tells the client in which clock domain the
compositor interprets the timestamps used by the presentation
extension. This clock is called the presentation clock.
The compositor sends this event when the client binds to the
presentation interface. The presentation clock does not change
during the lifetime of the client connection.
The clock identifier is platform dependent. On POSIX platforms, the
identifier value is one of the clockid_t values accepted by
clock_gettime(). clock_gettime() is defined by POSIX.1-2001.
Timestamps in this clock domain are expressed as tv_sec_hi,
tv_sec_lo, tv_nsec triples, each component being an unsigned
32-bit value. Whole seconds are in tv_sec which is a 64-bit
value combined from tv_sec_hi and tv_sec_lo, and the
additional fractional part in tv_nsec as nanoseconds. Hence,
for valid timestamps tv_nsec must be in [0, 999999999].
Note that clock_id applies only to the presentation clock,
and implies nothing about e.g. the timestamps used in the
Wayland core protocol input events.
Compositors should prefer a clock which does not jump and is
not slewed e.g. by NTP. The absolute value of the clock is
irrelevant. Precision of one millisecond or better is
recommended. Clients must be able to query the current clock
value directly, not by asking the compositor.
A presentation_feedback object returns an indication that a
wl_surface content update has become visible to the user.
One object corresponds to one content update submission
(wl_surface.commit). There are two possible outcomes: the
content update is presented to the user, and a presentation
timestamp delivered; or, the user did not see the content
update because it was superseded or its surface destroyed,
and the content update is discarded.
Once a presentation_feedback object has delivered a 'presented'
or 'discarded' event it is automatically destroyed.
As presentation can be synchronized to only one output at a
time, this event tells which output it was. This event is only
sent prior to the presented event.
As clients may bind to the same global wl_output multiple
times, this event is sent for each bound instance that matches
the synchronized output. If a client has not bound to the
right wl_output global at all, this event is not sent.
These flags provide information about how the presentation of
the related content update was done. The intent is to help
clients assess the reliability of the feedback and the visual
quality with respect to possible tearing and timings.
The presentation was synchronized to the "vertical retrace" by
the display hardware such that tearing does not happen.
Relying on software scheduling is not acceptable for this
flag. If presentation is done by a copy to the active
frontbuffer, then it must guarantee that tearing cannot
happen.
The display hardware provided measurements that the hardware
driver converted into a presentation timestamp. Sampling a
clock in software is not acceptable for this flag.
The display hardware signalled that it started using the new
image content. The opposite of this is e.g. a timer being used
to guess when the display hardware has switched to the new
image content.
The presentation of this update was done zero-copy. This means
the buffer from the client was given to display hardware as
is, without copying it. Compositing with OpenGL counts as
copying, even if textured directly from the client buffer.
Possible zero-copy cases include direct scanout of a
fullscreen surface and a surface on a hardware overlay.
The associated content update was displayed to the user at the
indicated time (tv_sec_hi/lo, tv_nsec). For the interpretation of
the timestamp, see presentation.clock_id event.
The timestamp corresponds to the time when the content update
turned into light the first time on the surface's main output.
Compositors may approximate this from the framebuffer flip
completion events from the system, and the latency of the
physical display path if known.
This event is preceded by all related sync_output events
telling which output's refresh cycle the feedback corresponds
to, i.e. the main output for the surface. Compositors are
recommended to choose the output containing the largest part
of the wl_surface, or keeping the output they previously
chose. Having a stable presentation output association helps
clients predict future output refreshes (vblank).
The 'refresh' argument gives the compositor's prediction of how
many nanoseconds after tv_sec, tv_nsec the very next output
refresh may occur. This is to further aid clients in
predicting future refreshes, i.e., estimating the timestamps
targeting the next few vblanks. If such prediction cannot
usefully be done, the argument is zero.
For version 2 and later, if the output does not have a constant
refresh rate, explicit video mode switches excluded, then the
refresh argument must be either an appropriate rate picked by the
compositor (e.g. fastest rate), or 0 if no such rate exists.
For version 1, if the output does not have a constant refresh rate,
the refresh argument must be zero.
The 64-bit value combined from seq_hi and seq_lo is the value
of the output's vertical retrace counter when the content
update was first scanned out to the display. This value must
be compatible with the definition of MSC in
GLX_OML_sync_control specification. Note, that if the display
path has a non-zero latency, the time instant specified by
this counter may differ from the timestamp's.
If the output does not have a concept of vertical retrace or a
refresh cycle, or the output device is self-refreshing without
a way to query the refresh count, then the arguments seq_hi
and seq_lo must be zero.
The content update was never displayed to the user.
waypipe-v0.10.5/protocols/primary-selection-unstable-v1.xml 0000664 0000000 0000000 00000024345 15070717111 0024024 0 ustar 00root root 0000000 0000000
Copyright © 2015, 2016 Red Hat
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.
This protocol provides the ability to have a primary selection device to
match that of the X server. This primary selection is a shortcut to the
common clipboard selection, where text just needs to be selected in order
to allow copying it elsewhere. The de facto way to perform this action
is the middle mouse button, although it is not limited to this one.
Clients wishing to honor primary selection should create a primary
selection source and set it as the selection through
wp_primary_selection_device.set_selection whenever the text selection
changes. In order to minimize calls in pointer-driven text selection,
it should happen only once after the operation finished. Similarly,
a NULL source should be set when text is unselected.
wp_primary_selection_offer objects are first announced through the
wp_primary_selection_device.data_offer event. Immediately after this event,
the primary data offer will emit wp_primary_selection_offer.offer events
to let know of the mime types being offered.
When the primary selection changes, the client with the keyboard focus
will receive wp_primary_selection_device.selection events. Only the client
with the keyboard focus will receive such events with a non-NULL
wp_primary_selection_offer. Across keyboard focus changes, previously
focused clients will receive wp_primary_selection_device.events with a
NULL wp_primary_selection_offer.
In order to request the primary selection data, the client must pass
a recent serial pertaining to the press event that is triggering the
operation, if the compositor deems the serial valid and recent, the
wp_primary_selection_source.send event will happen in the other end
to let the transfer begin. The client owning the primary selection
should write the requested data, and close the file descriptor
immediately.
If the primary selection owner client disappeared during the transfer,
the client reading the data will receive a
wp_primary_selection_device.selection event with a NULL
wp_primary_selection_offer, the client should take this as a hint
to finish the reads related to the no longer existing offer.
The primary selection owner should be checking for errors during
writes, merely cancelling the ongoing transfer if any happened.
The primary selection device manager is a singleton global object that
provides access to the primary selection. It allows to create
wp_primary_selection_source objects, as well as retrieving the per-seat
wp_primary_selection_device objects.
Create a new primary selection source.
Create a new data device for a given seat.
Destroy the primary selection device manager.
Replaces the current selection. The previous owner of the primary
selection will receive a wp_primary_selection_source.cancelled event.
To unset the selection, set the source to NULL.
Introduces a new wp_primary_selection_offer object that may be used
to receive the current primary selection. Immediately following this
event, the new wp_primary_selection_offer object will send
wp_primary_selection_offer.offer events to describe the offered mime
types.
The wp_primary_selection_device.selection event is sent to notify the
client of a new primary selection. This event is sent after the
wp_primary_selection.data_offer event introducing this object, and after
the offer has announced its mimetypes through
wp_primary_selection_offer.offer.
The data_offer is valid until a new offer or NULL is received
or until the client loses keyboard focus. The client must destroy the
previous selection data_offer, if any, upon receiving this event.
Destroy the primary selection device.
A wp_primary_selection_offer represents an offer to transfer the contents
of the primary selection clipboard to the client. Similar to
wl_data_offer, the offer also describes the mime types that the data can
be converted to and provides the mechanisms for transferring the data
directly to the client.
To transfer the contents of the primary selection clipboard, the client
issues this request and indicates the mime type that it wants to
receive. The transfer happens through the passed file descriptor
(typically created with the pipe system call). The source client writes
the data in the mime type representation requested and then closes the
file descriptor.
The receiving client reads from the read end of the pipe until EOF and
closes its end, at which point the transfer is complete.
Destroy the primary selection offer.
Sent immediately after creating announcing the
wp_primary_selection_offer through
wp_primary_selection_device.data_offer. One event is sent per offered
mime type.
The source side of a wp_primary_selection_offer, it provides a way to
describe the offered data and respond to requests to transfer the
requested contents of the primary selection clipboard.
This request adds a mime type to the set of mime types advertised to
targets. Can be called several times to offer multiple types.
Destroy the primary selection source.
Request for the current primary selection contents from the client.
Send the specified mime type over the passed file descriptor, then
close it.
This primary selection source is no longer valid. The client should
clean up and destroy this primary selection source.
waypipe-v0.10.5/protocols/security-context-v1.xml 0000664 0000000 0000000 00000017635 15070717111 0022100 0 ustar 00root root 0000000 0000000
Copyright © 2021 Simon Ser
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.
This interface allows a client to register a new Wayland connection to
the compositor and attach a security context to it.
This is intended to be used by sandboxes. Sandbox engines attach a
security context to all connections coming from inside the sandbox. The
compositor can then restrict the features that the sandboxed connections
can use.
Compositors should forbid nesting multiple security contexts by not
exposing wp_security_context_manager_v1 global to clients with a security
context attached, or by sending the nested protocol error. Nested
security contexts are dangerous because they can potentially allow
privilege escalation of a sandboxed client.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
Destroy the manager. This doesn't destroy objects created with the
manager.
Creates a new security context with a socket listening FD.
The compositor will accept new client connections on listen_fd.
listen_fd must be ready to accept new connections when this request is
sent by the client. In other words, the client must call bind(2) and
listen(2) before sending the FD.
close_fd is a FD that will signal hangup when the compositor should stop
accepting new connections on listen_fd.
The compositor must continue to accept connections on listen_fd when
the Wayland client which created the security context disconnects.
After sending this request, closing listen_fd and close_fd remains the
only valid operation on them.
The security context allows a client to register a new client and attach
security context metadata to the connections.
When both are set, the combination of the application ID and the sandbox
engine must uniquely identify an application. The same application ID
will be used across instances (e.g. if the application is restarted, or
if the application is started multiple times).
When both are set, the combination of the instance ID and the sandbox
engine must uniquely identify a running instance of an application.
Destroy the security context object.
Attach a unique sandbox engine name to the security context. The name
should follow the reverse-DNS style (e.g. "org.flatpak").
A list of well-known engines is maintained at:
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/security-context/engines.md
It is a protocol error to call this request twice. The already_set
error is sent in this case.
Attach an application ID to the security context.
The application ID is an opaque, sandbox-specific identifier for an
application. See the well-known engines document for more details:
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/security-context/engines.md
The compositor may use the application ID to group clients belonging to
the same security context application.
Whether this request is optional or not depends on the sandbox engine used.
It is a protocol error to call this request twice. The already_set
error is sent in this case.
Attach an instance ID to the security context.
The instance ID is an opaque, sandbox-specific identifier for a running
instance of an application. See the well-known engines document for
more details:
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/security-context/engines.md
Whether this request is optional or not depends on the sandbox engine used.
It is a protocol error to call this request twice. The already_set
error is sent in this case.
Atomically register the new client and attach the security context
metadata.
If the provided metadata is inconsistent or does not match with out of
band metadata (see
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/staging/security-context/engines.md),
the invalid_metadata error may be sent eventually.
It's a protocol error to send any request other than "destroy" after
this request. In this case, the already_used error is sent.
waypipe-v0.10.5/protocols/viewporter.xml 0000664 0000000 0000000 00000017705 15070717111 0020427 0 ustar 00root root 0000000 0000000
Copyright © 2013-2016 Collabora, Ltd.
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.
The global interface exposing surface cropping and scaling
capabilities is used to instantiate an interface extension for a
wl_surface object. This extended interface will then allow
cropping and scaling the surface contents, effectively
disconnecting the direct relationship between the buffer and the
surface size.
Informs the server that the client will not be using this
protocol object anymore. This does not affect any other objects,
wp_viewport objects included.
Instantiate an interface extension for the given wl_surface to
crop and scale its content. If the given wl_surface already has
a wp_viewport object associated, the viewport_exists
protocol error is raised.
An additional interface to a wl_surface object, which allows the
client to specify the cropping and scaling of the surface
contents.
This interface works with two concepts: the source rectangle (src_x,
src_y, src_width, src_height), and the destination size (dst_width,
dst_height). The contents of the source rectangle are scaled to the
destination size, and content outside the source rectangle is ignored.
This state is double-buffered, see wl_surface.commit.
The two parts of crop and scale state are independent: the source
rectangle, and the destination size. Initially both are unset, that
is, no scaling is applied. The whole of the current wl_buffer is
used as the source, and the surface size is as defined in
wl_surface.attach.
If the destination size is set, it causes the surface size to become
dst_width, dst_height. The source (rectangle) is scaled to exactly
this size. This overrides whatever the attached wl_buffer size is,
unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
has no content and therefore no size. Otherwise, the size is always
at least 1x1 in surface local coordinates.
If the source rectangle is set, it defines what area of the wl_buffer is
taken as the source. If the source rectangle is set and the destination
size is not set, then src_width and src_height must be integers, and the
surface size becomes the source rectangle size. This results in cropping
without scaling. If src_width or src_height are not integers and
destination size is not set, the bad_size protocol error is raised when
the surface state is applied.
The coordinate transformations from buffer pixel coordinates up to
the surface-local coordinates happen in the following order:
1. buffer_transform (wl_surface.set_buffer_transform)
2. buffer_scale (wl_surface.set_buffer_scale)
3. crop and scale (wp_viewport.set*)
This means, that the source rectangle coordinates of crop and scale
are given in the coordinates after the buffer transform and scale,
i.e. in the coordinates that would be the surface-local coordinates
if the crop and scale was not applied.
If src_x or src_y are negative, the bad_value protocol error is raised.
Otherwise, if the source rectangle is partially or completely outside of
the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
when the surface state is applied. A NULL wl_buffer does not raise the
out_of_buffer error.
If the wl_surface associated with the wp_viewport is destroyed,
all wp_viewport requests except 'destroy' raise the protocol error
no_surface.
If the wp_viewport object is destroyed, the crop and scale
state is removed from the wl_surface. The change will be applied
on the next wl_surface.commit.
The associated wl_surface's crop and scale state is removed.
The change is applied on the next wl_surface.commit.
Set the source rectangle of the associated wl_surface. See
wp_viewport for the description, and relation to the wl_buffer
size.
If all of x, y, width and height are -1.0, the source rectangle is
unset instead. Any other set of values where width or height are zero
or negative, or x or y are negative, raise the bad_value protocol
error.
The crop and scale state is double-buffered, see wl_surface.commit.
Set the destination size of the associated wl_surface. See
wp_viewport for the description, and relation to the wl_buffer
size.
If width is -1 and height is -1, the destination size is unset
instead. Any other pair of values for width and height that
contains zero or negative values raises the bad_value protocol
error.
The crop and scale state is double-buffered, see wl_surface.commit.
waypipe-v0.10.5/protocols/virtual-keyboard-unstable-v1.xml 0000664 0000000 0000000 00000011426 15070717111 0023636 0 ustar 00root root 0000000 0000000
Copyright © 2008-2011 Kristian Høgsberg
Copyright © 2010-2013 Intel Corporation
Copyright © 2012-2013 Collabora, Ltd.
Copyright © 2018 Purism SPC
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.
The virtual keyboard provides an application with requests which emulate
the behaviour of a physical keyboard.
This interface can be used by clients on its own to provide raw input
events, or it can accompany the input method protocol.
Provide a file descriptor to the compositor which can be
memory-mapped to provide a keyboard mapping description.
Format carries a value from the keymap_format enumeration.
A key was pressed or released.
The time argument is a timestamp with millisecond granularity, with an
undefined base. All requests regarding a single object must share the
same clock.
Keymap must be set before issuing this request.
State carries a value from the key_state enumeration.
Notifies the compositor that the modifier and/or group state has
changed, and it should update state.
The client should use wl_keyboard.modifiers event to synchronize its
internal state with seat state.
Keymap must be set before issuing this request.
A virtual keyboard manager allows an application to provide keyboard
input events as if they came from a physical keyboard.
Creates a new virtual keyboard associated to a seat.
If the compositor enables a keyboard to perform arbitrary actions, it
should present an error when an untrusted client requests a new
keyboard.
waypipe-v0.10.5/protocols/wayland-drm.xml 0000664 0000000 0000000 00000017305 15070717111 0020434 0 ustar 00root root 0000000 0000000
Copyright © 2008-2011 Kristian Høgsberg
Copyright © 2010-2011 Intel Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that\n the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
Bitmask of capabilities.
waypipe-v0.10.5/protocols/wayland.xml 0000664 0000000 0000000 00000446376 15070717111 0017672 0 ustar 00root root 0000000 0000000
Copyright © 2008-2011 Kristian Høgsberg
Copyright © 2010-2011 Intel Corporation
Copyright © 2012-2013 Collabora, Ltd.
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.
The core global object. This is a special singleton object. It
is used for internal Wayland protocol features.
The sync request asks the server to emit the 'done' event
on the returned wl_callback object. Since requests are
handled in-order and events are delivered in-order, this can
be used as a barrier to ensure all previous requests and the
resulting events have been handled.
The object returned by this request will be destroyed by the
compositor after the callback is fired and as such the client must not
attempt to use it after that point.
The callback_data passed in the callback is undefined and should be ignored.
This request creates a registry object that allows the client
to list and bind the global objects available from the
compositor.
It should be noted that the server side resources consumed in
response to a get_registry request can only be released when the
client disconnects, not when the client side proxy is destroyed.
Therefore, clients should invoke get_registry as infrequently as
possible to avoid wasting memory.
The error event is sent out when a fatal (non-recoverable)
error has occurred. The object_id argument is the object
where the error occurred, most often in response to a request
to that object. The code identifies the error and is defined
by the object interface. As such, each interface defines its
own set of error codes. The message is a brief description
of the error, for (debugging) convenience.
These errors are global and can be emitted in response to any
server request.
This event is used internally by the object ID management
logic. When a client deletes an object that it had created,
the server will send this event to acknowledge that it has
seen the delete request. When the client receives this event,
it will know that it can safely reuse the object ID.
The singleton global registry object. The server has a number of
global objects that are available to all clients. These objects
typically represent an actual object in the server (for example,
an input device) or they are singleton objects that provide
extension functionality.
When a client creates a registry object, the registry object
will emit a global event for each global currently in the
registry. Globals come and go as a result of device or
monitor hotplugs, reconfiguration or other events, and the
registry will send out global and global_remove events to
keep the client up to date with the changes. To mark the end
of the initial burst of events, the client can use the
wl_display.sync request immediately after calling
wl_display.get_registry.
A client can bind to a global object by using the bind
request. This creates a client-side handle that lets the object
emit events to the client and lets the client invoke requests on
the object.
Binds a new, client-created object to the server using the
specified name as the identifier.
Notify the client of global objects.
The event notifies the client that a global object with
the given name is now available, and it implements the
given version of the given interface.
Notify the client of removed global objects.
This event notifies the client that the global identified
by name is no longer available. If the client bound to
the global using the bind request, the client should now
destroy that object.
The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between
the global going away and a client sending a request to it.
Clients can handle the 'done' event to get notified when
the related request is done.
Note, because wl_callback objects are created from multiple independent
factory interfaces, the wl_callback interface is frozen at version 1.
Notify the client when the related request is done.
A compositor. This object is a singleton global. The
compositor is in charge of combining the contents of multiple
surfaces into one displayable output.
Ask the compositor to create a new surface.
Ask the compositor to create a new region.
The wl_shm_pool object encapsulates a piece of memory shared
between the compositor and client. Through the wl_shm_pool
object, the client can allocate shared memory wl_buffer objects.
All objects created through the same pool share the same
underlying mapped memory. Reusing the mapped memory avoids the
setup/teardown overhead and is useful when interactively resizing
a surface or for many small buffers.
Create a wl_buffer object from the pool.
The buffer is created offset bytes into the pool and has
width and height as specified. The stride argument specifies
the number of bytes from the beginning of one row to the beginning
of the next. The format is the pixel format of the buffer and
must be one of those advertised through the wl_shm.format event.
A buffer will keep a reference to the pool it was created from
so it is valid to destroy the pool immediately after creating
a buffer from it.
Destroy the shared memory pool.
The mmapped memory will be released when all
buffers that have been created from this pool
are gone.
This request will cause the server to remap the backing memory
for the pool from the file descriptor passed when the pool was
created, but using the new size. This request can only be
used to make the pool bigger.
This request only changes the amount of bytes that are mmapped
by the server and does not touch the file corresponding to the
file descriptor passed at creation time. It is the client's
responsibility to ensure that the file is at least as big as
the new pool size.
A singleton global object that provides support for shared
memory.
Clients can create wl_shm_pool objects using the create_pool
request.
On binding the wl_shm object one or more format events
are emitted to inform clients about the valid pixel formats
that can be used for buffers.
These errors can be emitted in response to wl_shm requests.
This describes the memory layout of an individual pixel.
All renderers should support argb8888 and xrgb8888 but any other
formats are optional and may not be supported by the particular
renderer in use.
The drm format codes match the macros defined in drm_fourcc.h, except
argb8888 and xrgb8888. The formats actually supported by the compositor
will be reported by the format event.
For all wl_shm formats and unless specified in another protocol
extension, pre-multiplied alpha is used for pixel values.
Create a new wl_shm_pool object.
The pool can be used to create shared memory based buffer
objects. The server will mmap size bytes of the passed file
descriptor, to use as backing memory for the pool.
Informs the client about a valid pixel format that
can be used for buffers. Known formats include
argb8888 and xrgb8888.
Using this request a client can tell the server that it is not going to
use the shm object anymore.
Objects created via this interface remain unaffected.
A buffer provides the content for a wl_surface. Buffers are
created through factory interfaces such as wl_shm, wp_linux_buffer_params
(from the linux-dmabuf protocol extension) or similar. It has a width and
a height and can be attached to a wl_surface, but the mechanism by which a
client provides and updates the contents is defined by the buffer factory
interface.
Color channels are assumed to be electrical rather than optical (in other
words, encoded with a transfer function) unless otherwise specified. If
the buffer uses a format that has an alpha channel, the alpha channel is
assumed to be premultiplied into the electrical color channel values
(after transfer function encoding) unless otherwise specified.
Note, because wl_buffer objects are created from multiple independent
factory interfaces, the wl_buffer interface is frozen at version 1.
Destroy a buffer. If and how you need to release the backing
storage is defined by the buffer factory interface.
For possible side-effects to a surface, see wl_surface.attach.
Sent when this wl_buffer is no longer used by the compositor.
The client is now free to reuse or destroy this buffer and its
backing storage.
If a client receives a release event before the frame callback
requested in the same wl_surface.commit that attaches this
wl_buffer to a surface, then the client is immediately free to
reuse the buffer and its backing storage, and does not need a
second buffer for the next surface content update. Typically
this is possible, when the compositor maintains a copy of the
wl_surface contents, e.g. as a GL texture. This is an important
optimization for GL(ES) compositors with wl_shm clients.
A wl_data_offer represents a piece of data offered for transfer
by another client (the source client). It is used by the
copy-and-paste and drag-and-drop mechanisms. The offer
describes the different mime types that the data can be
converted to and provides the mechanism for transferring the
data directly from the source client.
Indicate that the client can accept the given mime type, or
NULL for not accepted.
For objects of version 2 or older, this request is used by the
client to give feedback whether the client can receive the given
mime type, or NULL if none is accepted; the feedback does not
determine whether the drag-and-drop operation succeeds or not.
For objects of version 3 or newer, this request determines the
final result of the drag-and-drop operation. If the end result
is that no mime types were accepted, the drag-and-drop operation
will be cancelled and the corresponding drag source will receive
wl_data_source.cancelled. Clients may still use this event in
conjunction with wl_data_source.action for feedback.
To transfer the offered data, the client issues this request
and indicates the mime type it wants to receive. The transfer
happens through the passed file descriptor (typically created
with the pipe system call). The source client writes the data
in the mime type representation requested and then closes the
file descriptor.
The receiving client reads from the read end of the pipe until
EOF and then closes its end, at which point the transfer is
complete.
This request may happen multiple times for different mime types,
both before and after wl_data_device.drop. Drag-and-drop destination
clients may preemptively fetch data or examine it more closely to
determine acceptance.
Destroy the data offer.
Sent immediately after creating the wl_data_offer object. One
event per offered mime type.
Notifies the compositor that the drag destination successfully
finished the drag-and-drop operation.
Upon receiving this request, the compositor will emit
wl_data_source.dnd_finished on the drag source client.
It is a client error to perform other requests than
wl_data_offer.destroy after this one. It is also an error to perform
this request after a NULL mime type has been set in
wl_data_offer.accept or no action was received through
wl_data_offer.action.
If wl_data_offer.finish request is received for a non drag and drop
operation, the invalid_finish protocol error is raised.
Sets the actions that the destination side client supports for
this operation. This request may trigger the emission of
wl_data_source.action and wl_data_offer.action events if the compositor
needs to change the selected action.
This request can be called multiple times throughout the
drag-and-drop operation, typically in response to wl_data_device.enter
or wl_data_device.motion events.
This request determines the final result of the drag-and-drop
operation. If the end result is that no action is accepted,
the drag source will receive wl_data_source.cancelled.
The dnd_actions argument must contain only values expressed in the
wl_data_device_manager.dnd_actions enum, and the preferred_action
argument must only contain one of those values set, otherwise it
will result in a protocol error.
While managing an "ask" action, the destination drag-and-drop client
may perform further wl_data_offer.receive requests, and is expected
to perform one last wl_data_offer.set_actions request with a preferred
action other than "ask" (and optionally wl_data_offer.accept) before
requesting wl_data_offer.finish, in order to convey the action selected
by the user. If the preferred action is not in the
wl_data_offer.source_actions mask, an error will be raised.
If the "ask" action is dismissed (e.g. user cancellation), the client
is expected to perform wl_data_offer.destroy right away.
This request can only be made on drag-and-drop offers, a protocol error
will be raised otherwise.
This event indicates the actions offered by the data source. It
will be sent immediately after creating the wl_data_offer object,
or anytime the source side changes its offered actions through
wl_data_source.set_actions.
This event indicates the action selected by the compositor after
matching the source/destination side actions. Only one action (or
none) will be offered here.
This event can be emitted multiple times during the drag-and-drop
operation in response to destination side action changes through
wl_data_offer.set_actions.
This event will no longer be emitted after wl_data_device.drop
happened on the drag-and-drop destination, the client must
honor the last action received, or the last preferred one set
through wl_data_offer.set_actions when handling an "ask" action.
Compositors may also change the selected action on the fly, mainly
in response to keyboard modifier changes during the drag-and-drop
operation.
The most recent action received is always the valid one. Prior to
receiving wl_data_device.drop, the chosen action may change (e.g.
due to keyboard modifiers being pressed). At the time of receiving
wl_data_device.drop the drag-and-drop destination must honor the
last action received.
Action changes may still happen after wl_data_device.drop,
especially on "ask" actions, where the drag-and-drop destination
may choose another action afterwards. Action changes happening
at this stage are always the result of inter-client negotiation, the
compositor shall no longer be able to induce a different action.
Upon "ask" actions, it is expected that the drag-and-drop destination
may potentially choose a different action and/or mime type,
based on wl_data_offer.source_actions and finally chosen by the
user (e.g. popping up a menu with the available options). The
final wl_data_offer.set_actions and wl_data_offer.accept requests
must happen before the call to wl_data_offer.finish.
The wl_data_source object is the source side of a wl_data_offer.
It is created by the source client in a data transfer and
provides a way to describe the offered data and a way to respond
to requests to transfer the data.
This request adds a mime type to the set of mime types
advertised to targets. Can be called several times to offer
multiple types.
Destroy the data source.
Sent when a target accepts pointer_focus or motion events. If
a target does not accept any of the offered types, type is NULL.
Used for feedback during drag-and-drop.
Request for data from the client. Send the data as the
specified mime type over the passed file descriptor, then
close it.
This data source is no longer valid. There are several reasons why
this could happen:
- The data source has been replaced by another data source.
- The drag-and-drop operation was performed, but the drop destination
did not accept any of the mime types offered through
wl_data_source.target.
- The drag-and-drop operation was performed, but the drop destination
did not select any of the actions present in the mask offered through
wl_data_source.action.
- The drag-and-drop operation was performed but didn't happen over a
surface.
- The compositor cancelled the drag-and-drop operation (e.g. compositor
dependent timeouts to avoid stale drag-and-drop transfers).
The client should clean up and destroy this data source.
For objects of version 2 or older, wl_data_source.cancelled will
only be emitted if the data source was replaced by another data
source.
Sets the actions that the source side client supports for this
operation. This request may trigger wl_data_source.action and
wl_data_offer.action events if the compositor needs to change the
selected action.
The dnd_actions argument must contain only values expressed in the
wl_data_device_manager.dnd_actions enum, otherwise it will result
in a protocol error.
This request must be made once only, and can only be made on sources
used in drag-and-drop, so it must be performed before
wl_data_device.start_drag. Attempting to use the source other than
for drag-and-drop will raise a protocol error.
The user performed the drop action. This event does not indicate
acceptance, wl_data_source.cancelled may still be emitted afterwards
if the drop destination does not accept any mime type.
However, this event might however not be received if the compositor
cancelled the drag-and-drop operation before this event could happen.
Note that the data_source may still be used in the future and should
not be destroyed here.
The drop destination finished interoperating with this data
source, so the client is now free to destroy this data source and
free all associated data.
If the action used to perform the operation was "move", the
source can now delete the transferred data.
This event indicates the action selected by the compositor after
matching the source/destination side actions. Only one action (or
none) will be offered here.
This event can be emitted multiple times during the drag-and-drop
operation, mainly in response to destination side changes through
wl_data_offer.set_actions, and as the data device enters/leaves
surfaces.
It is only possible to receive this event after
wl_data_source.dnd_drop_performed if the drag-and-drop operation
ended in an "ask" action, in which case the final wl_data_source.action
event will happen immediately before wl_data_source.dnd_finished.
Compositors may also change the selected action on the fly, mainly
in response to keyboard modifier changes during the drag-and-drop
operation.
The most recent action received is always the valid one. The chosen
action may change alongside negotiation (e.g. an "ask" action can turn
into a "move" operation), so the effects of the final action must
always be applied in wl_data_offer.dnd_finished.
Clients can trigger cursor surface changes from this point, so
they reflect the current action.
There is one wl_data_device per seat which can be obtained
from the global wl_data_device_manager singleton.
A wl_data_device provides access to inter-client data transfer
mechanisms such as copy-and-paste and drag-and-drop.
This request asks the compositor to start a drag-and-drop
operation on behalf of the client.
The source argument is the data source that provides the data
for the eventual data transfer. If source is NULL, enter, leave
and motion events are sent only to the client that initiated the
drag and the client is expected to handle the data passing
internally. If source is destroyed, the drag-and-drop session will be
cancelled.
The origin surface is the surface where the drag originates and
the client must have an active implicit grab that matches the
serial.
The icon surface is an optional (can be NULL) surface that
provides an icon to be moved around with the cursor. Initially,
the top-left corner of the icon surface is placed at the cursor
hotspot, but subsequent wl_surface.offset requests can move the
relative position. Attach requests must be confirmed with
wl_surface.commit as usual. The icon surface is given the role of
a drag-and-drop icon. If the icon surface already has another role,
it raises a protocol error.
The input region is ignored for wl_surfaces with the role of a
drag-and-drop icon.
The given source may not be used in any further set_selection or
start_drag requests. Attempting to reuse a previously-used source
may send a used_source error.
This request asks the compositor to set the selection
to the data from the source on behalf of the client.
To unset the selection, set the source to NULL.
The given source may not be used in any further set_selection or
start_drag requests. Attempting to reuse a previously-used source
may send a used_source error.
The data_offer event introduces a new wl_data_offer object,
which will subsequently be used in either the
data_device.enter event (for drag-and-drop) or the
data_device.selection event (for selections). Immediately
following the data_device.data_offer event, the new data_offer
object will send out data_offer.offer events to describe the
mime types it offers.
This event is sent when an active drag-and-drop pointer enters
a surface owned by the client. The position of the pointer at
enter time is provided by the x and y arguments, in surface-local
coordinates.
This event is sent when the drag-and-drop pointer leaves the
surface and the session ends. The client must destroy the
wl_data_offer introduced at enter time at this point.
This event is sent when the drag-and-drop pointer moves within
the currently focused surface. The new position of the pointer
is provided by the x and y arguments, in surface-local
coordinates.
The event is sent when a drag-and-drop operation is ended
because the implicit grab is removed.
The drag-and-drop destination is expected to honor the last action
received through wl_data_offer.action, if the resulting action is
"copy" or "move", the destination can still perform
wl_data_offer.receive requests, and is expected to end all
transfers with a wl_data_offer.finish request.
If the resulting action is "ask", the action will not be considered
final. The drag-and-drop destination is expected to perform one last
wl_data_offer.set_actions request, or wl_data_offer.destroy in order
to cancel the operation.
The selection event is sent out to notify the client of a new
wl_data_offer for the selection for this device. The
data_device.data_offer and the data_offer.offer events are
sent out immediately before this event to introduce the data
offer object. The selection event is sent to a client
immediately before receiving keyboard focus and when a new
selection is set while the client has keyboard focus. The
data_offer is valid until a new data_offer or NULL is received
or until the client loses keyboard focus. Switching surface with
keyboard focus within the same client doesn't mean a new selection
will be sent. The client must destroy the previous selection
data_offer, if any, upon receiving this event.
This request destroys the data device.
The wl_data_device_manager is a singleton global object that
provides access to inter-client data transfer mechanisms such as
copy-and-paste and drag-and-drop. These mechanisms are tied to
a wl_seat and this interface lets a client get a wl_data_device
corresponding to a wl_seat.
Depending on the version bound, the objects created from the bound
wl_data_device_manager object will have different requirements for
functioning properly. See wl_data_source.set_actions,
wl_data_offer.accept and wl_data_offer.finish for details.
Create a new data source.
Create a new data device for a given seat.
This is a bitmask of the available/preferred actions in a
drag-and-drop operation.
In the compositor, the selected action is a result of matching the
actions offered by the source and destination sides. "action" events
with a "none" action will be sent to both source and destination if
there is no match. All further checks will effectively happen on
(source actions ∩ destination actions).
In addition, compositors may also pick different actions in
reaction to key modifiers being pressed. One common design that
is used in major toolkits (and the behavior recommended for
compositors) is:
- If no modifiers are pressed, the first match (in bit order)
will be used.
- Pressing Shift selects "move", if enabled in the mask.
- Pressing Control selects "copy", if enabled in the mask.
Behavior beyond that is considered implementation-dependent.
Compositors may for example bind other modifiers (like Alt/Meta)
or drags initiated with other buttons than BTN_LEFT to specific
actions (e.g. "ask").
This interface is implemented by servers that provide
desktop-style user interfaces.
It allows clients to associate a wl_shell_surface with
a basic surface.
Note! This protocol is deprecated and not intended for production use.
For desktop-style user interfaces, use xdg_shell. Compositors and clients
should not implement this interface.
Create a shell surface for an existing surface. This gives
the wl_surface the role of a shell surface. If the wl_surface
already has another role, it raises a protocol error.
Only one shell surface can be associated with a given surface.
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style user interface.
It provides requests to treat surfaces like toplevel, fullscreen
or popup windows, move, resize or maximize them, associate
metadata like title and class, etc.
On the server side the object is automatically destroyed when
the related wl_surface is destroyed. On the client side,
wl_shell_surface_destroy() must be called before destroying
the wl_surface object.
A client must respond to a ping event with a pong request or
the client may be deemed unresponsive.
Start a pointer-driven move of the surface.
This request must be used in response to a button press event.
The server may ignore move requests depending on the state of
the surface (e.g. fullscreen or maximized).
These values are used to indicate which edge of a surface
is being dragged in a resize operation. The server may
use this information to adapt its behavior, e.g. choose
an appropriate cursor image.
Start a pointer-driven resizing of the surface.
This request must be used in response to a button press event.
The server may ignore resize requests depending on the state of
the surface (e.g. fullscreen or maximized).
Map the surface as a toplevel surface.
A toplevel surface is not fullscreen, maximized or transient.
These flags specify details of the expected behaviour
of transient surfaces. Used in the set_transient request.
Map the surface relative to an existing surface.
The x and y arguments specify the location of the upper left
corner of the surface relative to the upper left corner of the
parent surface, in surface-local coordinates.
The flags argument controls details of the transient behaviour.
Hints to indicate to the compositor how to deal with a conflict
between the dimensions of the surface and the dimensions of the
output. The compositor is free to ignore this parameter.
Map the surface as a fullscreen surface.
If an output parameter is given then the surface will be made
fullscreen on that output. If the client does not specify the
output then the compositor will apply its policy - usually
choosing the output on which the surface has the biggest surface
area.
The client may specify a method to resolve a size conflict
between the output size and the surface size - this is provided
through the method parameter.
The framerate parameter is used only when the method is set
to "driver", to indicate the preferred framerate. A value of 0
indicates that the client does not care about framerate. The
framerate is specified in mHz, that is framerate of 60000 is 60Hz.
A method of "scale" or "driver" implies a scaling operation of
the surface, either via a direct scaling operation or a change of
the output mode. This will override any kind of output scaling, so
that mapping a surface with a buffer size equal to the mode can
fill the screen independent of buffer_scale.
A method of "fill" means we don't scale up the buffer, however
any output scale is applied. This means that you may run into
an edge case where the application maps a buffer with the same
size of the output mode but buffer_scale 1 (thus making a
surface larger than the output). In this case it is allowed to
downscale the results to fit the screen.
The compositor must reply to this request with a configure event
with the dimensions for the output on which the surface will
be made fullscreen.
Map the surface as a popup.
A popup surface is a transient surface with an added pointer
grab.
An existing implicit grab will be changed to owner-events mode,
and the popup grab will continue after the implicit grab ends
(i.e. releasing the mouse button does not cause the popup to
be unmapped).
The popup grab continues until the window is destroyed or a
mouse button is pressed in any other client's window. A click
in any of the client's surfaces is reported as normal, however,
clicks in other clients' surfaces will be discarded and trigger
the callback.
The x and y arguments specify the location of the upper left
corner of the surface relative to the upper left corner of the
parent surface, in surface-local coordinates.
Map the surface as a maximized surface.
If an output parameter is given then the surface will be
maximized on that output. If the client does not specify the
output then the compositor will apply its policy - usually
choosing the output on which the surface has the biggest surface
area.
The compositor will reply with a configure event telling
the expected new surface size. The operation is completed
on the next buffer attach to this surface.
A maximized surface typically fills the entire output it is
bound to, except for desktop elements such as panels. This is
the main difference between a maximized shell surface and a
fullscreen shell surface.
The details depend on the compositor implementation.
Set a short title for the surface.
This string may be used to identify the surface in a task bar,
window list, or other user interface elements provided by the
compositor.
The string must be encoded in UTF-8.
Set a class for the surface.
The surface class identifies the general class of applications
to which the surface belongs. A common convention is to use the
file name (or the full path if it is a non-standard location) of
the application's .desktop file as the class.
Ping a client to check if it is receiving events and sending
requests. A client is expected to reply with a pong request.
The configure event asks the client to resize its surface.
The size is a hint, in the sense that the client is free to
ignore it if it doesn't resize, pick a smaller size (to
satisfy aspect ratio or resize in steps of NxM pixels).
The edges parameter provides a hint about how the surface
was resized. The client may use this information to decide
how to adjust its content to the new size (e.g. a scrolling
area might adjust its content position to leave the viewable
content unmoved).
The client is free to dismiss all but the last configure
event it received.
The width and height arguments specify the size of the window
in surface-local coordinates.
The popup_done event is sent out when a popup grab is broken,
that is, when the user clicks a surface that doesn't belong
to the client owning the popup surface.
A surface is a rectangular area that may be displayed on zero
or more outputs, and shown any number of times at the compositor's
discretion. They can present wl_buffers, receive user input, and
define a local coordinate system.
The size of a surface (and relative positions on it) is described
in surface-local coordinates, which may differ from the buffer
coordinates of the pixel content, in case a buffer_transform
or a buffer_scale is used.
A surface without a "role" is fairly useless: a compositor does
not know where, when or how to present it. The role is the
purpose of a wl_surface. Examples of roles are a cursor for a
pointer (as set by wl_pointer.set_cursor), a drag icon
(wl_data_device.start_drag), a sub-surface
(wl_subcompositor.get_subsurface), and a window as defined by a
shell protocol (e.g. wl_shell.get_shell_surface).
A surface can have only one role at a time. Initially a
wl_surface does not have a role. Once a wl_surface is given a
role, it is set permanently for the whole lifetime of the
wl_surface object. Giving the current role again is allowed,
unless explicitly forbidden by the relevant interface
specification.
Surface roles are given by requests in other interfaces such as
wl_pointer.set_cursor. The request should explicitly mention
that this request gives a role to a wl_surface. Often, this
request also creates a new protocol object that represents the
role and adds additional functionality to wl_surface. When a
client wants to destroy a wl_surface, they must destroy this role
object before the wl_surface, otherwise a defunct_role_object error is
sent.
Destroying the role object does not remove the role from the
wl_surface, but it may stop the wl_surface from "playing the role".
For instance, if a wl_subsurface object is destroyed, the wl_surface
it was created for will be unmapped and forget its position and
z-order. It is allowed to create a wl_subsurface for the same
wl_surface again, but it is not allowed to use the wl_surface as
a cursor (cursor is a different role than sub-surface, and role
switching is not allowed).
These errors can be emitted in response to wl_surface requests.
Deletes the surface and invalidates its object ID.
Set a buffer as the content of this surface.
The new size of the surface is calculated based on the buffer
size transformed by the inverse buffer_transform and the
inverse buffer_scale. This means that at commit time the supplied
buffer size must be an integer multiple of the buffer_scale. If
that's not the case, an invalid_size error is sent.
The x and y arguments specify the location of the new pending
buffer's upper left corner, relative to the current buffer's upper
left corner, in surface-local coordinates. In other words, the
x and y, combined with the new surface size define in which
directions the surface's size changes. Setting anything other than 0
as x and y arguments is discouraged, and should instead be replaced
with using the separate wl_surface.offset request.
When the bound wl_surface version is 5 or higher, passing any
non-zero x or y is a protocol violation, and will result in an
'invalid_offset' error being raised. The x and y arguments are ignored
and do not change the pending state. To achieve equivalent semantics,
use wl_surface.offset.
Surface contents are double-buffered state, see wl_surface.commit.
The initial surface contents are void; there is no content.
wl_surface.attach assigns the given wl_buffer as the pending
wl_buffer. wl_surface.commit makes the pending wl_buffer the new
surface contents, and the size of the surface becomes the size
calculated from the wl_buffer, as described above. After commit,
there is no pending buffer until the next attach.
Committing a pending wl_buffer allows the compositor to read the
pixels in the wl_buffer. The compositor may access the pixels at
any time after the wl_surface.commit request. When the compositor
will not access the pixels anymore, it will send the
wl_buffer.release event. Only after receiving wl_buffer.release,
the client may reuse the wl_buffer. A wl_buffer that has been
attached and then replaced by another attach instead of committed
will not receive a release event, and is not used by the
compositor.
If a pending wl_buffer has been committed to more than one wl_surface,
the delivery of wl_buffer.release events becomes undefined. A well
behaved client should not rely on wl_buffer.release events in this
case. Alternatively, a client could create multiple wl_buffer objects
from the same backing storage or use wp_linux_buffer_release.
Destroying the wl_buffer after wl_buffer.release does not change
the surface contents. Destroying the wl_buffer before wl_buffer.release
is allowed as long as the underlying buffer storage isn't re-used (this
can happen e.g. on client process termination). However, if the client
destroys the wl_buffer before receiving the wl_buffer.release event and
mutates the underlying buffer storage, the surface contents become
undefined immediately.
If wl_surface.attach is sent with a NULL wl_buffer, the
following wl_surface.commit will remove the surface content.
If a pending wl_buffer has been destroyed, the result is not specified.
Many compositors are known to remove the surface content on the following
wl_surface.commit, but this behaviour is not universal. Clients seeking to
maximise compatibility should not destroy pending buffers and should
ensure that they explicitly remove content from surfaces, even after
destroying buffers.
This request is used to describe the regions where the pending
buffer is different from the current surface contents, and where
the surface therefore needs to be repainted. The compositor
ignores the parts of the damage that fall outside of the surface.
Damage is double-buffered state, see wl_surface.commit.
The damage rectangle is specified in surface-local coordinates,
where x and y specify the upper left corner of the damage rectangle.
The initial value for pending damage is empty: no damage.
wl_surface.damage adds pending damage: the new pending damage
is the union of old pending damage and the given rectangle.
wl_surface.commit assigns pending damage as the current damage,
and clears pending damage. The server will clear the current
damage as it repaints the surface.
Note! New clients should not use this request. Instead damage can be
posted with wl_surface.damage_buffer which uses buffer coordinates
instead of surface coordinates.
Request a notification when it is a good time to start drawing a new
frame, by creating a frame callback. This is useful for throttling
redrawing operations, and driving animations.
When a client is animating on a wl_surface, it can use the 'frame'
request to get notified when it is a good time to draw and commit the
next frame of animation. If the client commits an update earlier than
that, it is likely that some updates will not make it to the display,
and the client is wasting resources by drawing too often.
The frame request will take effect on the next wl_surface.commit.
The notification will only be posted for one frame unless
requested again. For a wl_surface, the notifications are posted in
the order the frame requests were committed.
The server must send the notifications so that a client
will not send excessive updates, while still allowing
the highest possible update rate for clients that wait for the reply
before drawing again. The server should give some time for the client
to draw and commit after sending the frame callback events to let it
hit the next output refresh.
A server should avoid signaling the frame callbacks if the
surface is not visible in any way, e.g. the surface is off-screen,
or completely obscured by other opaque surfaces.
The object returned by this request will be destroyed by the
compositor after the callback is fired and as such the client must not
attempt to use it after that point.
The callback_data passed in the callback is the current time, in
milliseconds, with an undefined base.
This request sets the region of the surface that contains
opaque content.
The opaque region is an optimization hint for the compositor
that lets it optimize the redrawing of content behind opaque
regions. Setting an opaque region is not required for correct
behaviour, but marking transparent content as opaque will result
in repaint artifacts.
The opaque region is specified in surface-local coordinates.
The compositor ignores the parts of the opaque region that fall
outside of the surface.
Opaque region is double-buffered state, see wl_surface.commit.
wl_surface.set_opaque_region changes the pending opaque region.
wl_surface.commit copies the pending region to the current region.
Otherwise, the pending and current regions are never changed.
The initial value for an opaque region is empty. Setting the pending
opaque region has copy semantics, and the wl_region object can be
destroyed immediately. A NULL wl_region causes the pending opaque
region to be set to empty.
This request sets the region of the surface that can receive
pointer and touch events.
Input events happening outside of this region will try the next
surface in the server surface stack. The compositor ignores the
parts of the input region that fall outside of the surface.
The input region is specified in surface-local coordinates.
Input region is double-buffered state, see wl_surface.commit.
wl_surface.set_input_region changes the pending input region.
wl_surface.commit copies the pending region to the current region.
Otherwise the pending and current regions are never changed,
except cursor and icon surfaces are special cases, see
wl_pointer.set_cursor and wl_data_device.start_drag.
The initial value for an input region is infinite. That means the
whole surface will accept input. Setting the pending input region
has copy semantics, and the wl_region object can be destroyed
immediately. A NULL wl_region causes the input region to be set
to infinite.
Surface state (input, opaque, and damage regions, attached buffers,
etc.) is double-buffered. Protocol requests modify the pending state,
as opposed to the active state in use by the compositor.
A commit request atomically creates a content update from the pending
state, even if the pending state has not been touched. The content
update is placed in a queue until it becomes active. After commit, the
new pending state is as documented for each related request.
When the content update is applied, the wl_buffer is applied before all
other state. This means that all coordinates in double-buffered state
are relative to the newly attached wl_buffers, except for
wl_surface.attach itself. If there is no newly attached wl_buffer, the
coordinates are relative to the previous content update.
All requests that need a commit to become effective are documented
to affect double-buffered state.
Other interfaces may add further double-buffered surface state.
This is emitted whenever a surface's creation, movement, or resizing
results in some part of it being within the scanout region of an
output.
Note that a surface may be overlapping with zero or more outputs.
This is emitted whenever a surface's creation, movement, or resizing
results in it no longer having any part of it within the scanout region
of an output.
Clients should not use the number of outputs the surface is on for frame
throttling purposes. The surface might be hidden even if no leave event
has been sent, and the compositor might expect new surface content
updates even if no enter event has been sent. The frame event should be
used instead.
This request sets the transformation that the client has already applied
to the content of the buffer. The accepted values for the transform
parameter are the values for wl_output.transform.
The compositor applies the inverse of this transformation whenever it
uses the buffer contents.
Buffer transform is double-buffered state, see wl_surface.commit.
A newly created surface has its buffer transformation set to normal.
wl_surface.set_buffer_transform changes the pending buffer
transformation. wl_surface.commit copies the pending buffer
transformation to the current one. Otherwise, the pending and current
values are never changed.
The purpose of this request is to allow clients to render content
according to the output transform, thus permitting the compositor to
use certain optimizations even if the display is rotated. Using
hardware overlays and scanning out a client buffer for fullscreen
surfaces are examples of such optimizations. Those optimizations are
highly dependent on the compositor implementation, so the use of this
request should be considered on a case-by-case basis.
Note that if the transform value includes 90 or 270 degree rotation,
the width of the buffer will become the surface height and the height
of the buffer will become the surface width.
If transform is not one of the values from the
wl_output.transform enum the invalid_transform protocol error
is raised.
This request sets an optional scaling factor on how the compositor
interprets the contents of the buffer attached to the window.
Buffer scale is double-buffered state, see wl_surface.commit.
A newly created surface has its buffer scale set to 1.
wl_surface.set_buffer_scale changes the pending buffer scale.
wl_surface.commit copies the pending buffer scale to the current one.
Otherwise, the pending and current values are never changed.
The purpose of this request is to allow clients to supply higher
resolution buffer data for use on high resolution outputs. It is
intended that you pick the same buffer scale as the scale of the
output that the surface is displayed on. This means the compositor
can avoid scaling when rendering the surface on that output.
Note that if the scale is larger than 1, then you have to attach
a buffer that is larger (by a factor of scale in each dimension)
than the desired surface size.
If scale is not greater than 0 the invalid_scale protocol error is
raised.
This request is used to describe the regions where the pending
buffer is different from the current surface contents, and where
the surface therefore needs to be repainted. The compositor
ignores the parts of the damage that fall outside of the surface.
Damage is double-buffered state, see wl_surface.commit.
The damage rectangle is specified in buffer coordinates,
where x and y specify the upper left corner of the damage rectangle.
The initial value for pending damage is empty: no damage.
wl_surface.damage_buffer adds pending damage: the new pending
damage is the union of old pending damage and the given rectangle.
wl_surface.commit assigns pending damage as the current damage,
and clears pending damage. The server will clear the current
damage as it repaints the surface.
This request differs from wl_surface.damage in only one way - it
takes damage in buffer coordinates instead of surface-local
coordinates. While this generally is more intuitive than surface
coordinates, it is especially desirable when using wp_viewport
or when a drawing library (like EGL) is unaware of buffer scale
and buffer transform.
Note: Because buffer transformation changes and damage requests may
be interleaved in the protocol stream, it is impossible to determine
the actual mapping between surface and buffer damage until
wl_surface.commit time. Therefore, compositors wishing to take both
kinds of damage into account will have to accumulate damage from the
two requests separately and only transform from one to the other
after receiving the wl_surface.commit.
The x and y arguments specify the location of the new pending
buffer's upper left corner, relative to the current buffer's upper
left corner, in surface-local coordinates. In other words, the
x and y, combined with the new surface size define in which
directions the surface's size changes.
The exact semantics of wl_surface.offset are role-specific. Refer to
the documentation of specific roles for more information.
Surface location offset is double-buffered state, see
wl_surface.commit.
This request is semantically equivalent to and the replaces the x and y
arguments in the wl_surface.attach request in wl_surface versions prior
to 5. See wl_surface.attach for details.
This event indicates the preferred buffer scale for this surface. It is
sent whenever the compositor's preference changes.
Before receiving this event the preferred buffer scale for this surface
is 1.
It is intended that scaling aware clients use this event to scale their
content and use wl_surface.set_buffer_scale to indicate the scale they
have rendered with. This allows clients to supply a higher detail
buffer.
The compositor shall emit a scale value greater than 0.
This event indicates the preferred buffer transform for this surface.
It is sent whenever the compositor's preference changes.
Before receiving this event the preferred buffer transform for this
surface is normal.
Applying this transformation to the surface buffer contents and using
wl_surface.set_buffer_transform might allow the compositor to use the
surface buffer more efficiently.
A seat is a group of keyboards, pointer and touch devices. This
object is published as a global during start up, or when such a
device is hot plugged. A seat typically has a pointer and
maintains a keyboard focus and a pointer focus.
This is a bitmask of capabilities this seat has; if a member is
set, then it is present on the seat.
These errors can be emitted in response to wl_seat requests.
This is emitted whenever a seat gains or loses the pointer,
keyboard or touch capabilities. The argument is a capability
enum containing the complete set of capabilities this seat has.
When the pointer capability is added, a client may create a
wl_pointer object using the wl_seat.get_pointer request. This object
will receive pointer events until the capability is removed in the
future.
When the pointer capability is removed, a client should destroy the
wl_pointer objects associated with the seat where the capability was
removed, using the wl_pointer.release request. No further pointer
events will be received on these objects.
In some compositors, if a seat regains the pointer capability and a
client has a previously obtained wl_pointer object of version 4 or
less, that object may start sending pointer events again. This
behavior is considered a misinterpretation of the intended behavior
and must not be relied upon by the client. wl_pointer objects of
version 5 or later must not send events if created before the most
recent event notifying the client of an added pointer capability.
The above behavior also applies to wl_keyboard and wl_touch with the
keyboard and touch capabilities, respectively.
The ID provided will be initialized to the wl_pointer interface
for this seat.
This request only takes effect if the seat has the pointer
capability, or has had the pointer capability in the past.
It is a protocol violation to issue this request on a seat that has
never had the pointer capability. The missing_capability error will
be sent in this case.
The ID provided will be initialized to the wl_keyboard interface
for this seat.
This request only takes effect if the seat has the keyboard
capability, or has had the keyboard capability in the past.
It is a protocol violation to issue this request on a seat that has
never had the keyboard capability. The missing_capability error will
be sent in this case.
The ID provided will be initialized to the wl_touch interface
for this seat.
This request only takes effect if the seat has the touch
capability, or has had the touch capability in the past.
It is a protocol violation to issue this request on a seat that has
never had the touch capability. The missing_capability error will
be sent in this case.
In a multi-seat configuration the seat name can be used by clients to
help identify which physical devices the seat represents.
The seat name is a UTF-8 string with no convention defined for its
contents. Each name is unique among all wl_seat globals. The name is
only guaranteed to be unique for the current compositor instance.
The same seat names are used for all clients. Thus, the name can be
shared across processes to refer to a specific wl_seat global.
The name event is sent after binding to the seat global. This event is
only sent once per seat object, and the name does not change over the
lifetime of the wl_seat global.
Compositors may re-use the same seat name if the wl_seat global is
destroyed and re-created later.
Using this request a client can tell the server that it is not going to
use the seat object anymore.
The wl_pointer interface represents one or more input devices,
such as mice, which control the pointer location and pointer_focus
of a seat.
The wl_pointer interface generates motion, enter and leave
events for the surfaces that the pointer is located over,
and button and axis events for button presses, button releases
and scrolling.
Set the pointer surface, i.e., the surface that contains the
pointer image (cursor). This request gives the surface the role
of a cursor. If the surface already has another role, it raises
a protocol error.
The cursor actually changes only if the pointer
focus for this device is one of the requesting client's surfaces
or the surface parameter is the current pointer surface. If
there was a previous surface set with this request it is
replaced. If surface is NULL, the pointer image is hidden.
The parameters hotspot_x and hotspot_y define the position of
the pointer surface relative to the pointer location. Its
top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
where (x, y) are the coordinates of the pointer location, in
surface-local coordinates.
On wl_surface.offset requests to the pointer surface, hotspot_x
and hotspot_y are decremented by the x and y parameters
passed to the request. The offset must be applied by
wl_surface.commit as usual.
The hotspot can also be updated by passing the currently set
pointer surface to this request with new values for hotspot_x
and hotspot_y.
The input region is ignored for wl_surfaces with the role of
a cursor. When the use as a cursor ends, the wl_surface is
unmapped.
The serial parameter must match the latest wl_pointer.enter
serial number sent to the client. Otherwise the request will be
ignored.
Notification that this seat's pointer is focused on a certain
surface.
When a seat's focus enters a surface, the pointer image
is undefined and a client should respond to this event by setting
an appropriate pointer image with the set_cursor request.
Notification that this seat's pointer is no longer focused on
a certain surface.
The leave notification is sent before the enter notification
for the new focus.
Notification of pointer location change. The arguments
surface_x and surface_y are the location relative to the
focused surface.
Describes the physical state of a button that produced the button
event.
Mouse button click and release notifications.
The location of the click is given by the last motion or
enter event.
The time argument is a timestamp with millisecond
granularity, with an undefined base.
The button is a button code as defined in the Linux kernel's
linux/input-event-codes.h header file, e.g. BTN_LEFT.
Any 16-bit button code value is reserved for future additions to the
kernel's event code list. All other button codes above 0xFFFF are
currently undefined but may be used in future versions of this
protocol.
Describes the axis types of scroll events.
Scroll and other axis notifications.
For scroll events (vertical and horizontal scroll axes), the
value parameter is the length of a vector along the specified
axis in a coordinate space identical to those of motion events,
representing a relative movement along the specified axis.
For devices that support movements non-parallel to axes multiple
axis events will be emitted.
When applicable, for example for touch pads, the server can
choose to emit scroll events where the motion vector is
equivalent to a motion event vector.
When applicable, a client can transform its content relative to the
scroll distance.
Using this request a client can tell the server that it is not going to
use the pointer object anymore.
This request destroys the pointer proxy object, so clients must not call
wl_pointer_destroy() after using this request.
Indicates the end of a set of events that logically belong together.
A client is expected to accumulate the data in all events within the
frame before proceeding.
All wl_pointer events before a wl_pointer.frame event belong
logically together. For example, in a diagonal scroll motion the
compositor will send an optional wl_pointer.axis_source event, two
wl_pointer.axis events (horizontal and vertical) and finally a
wl_pointer.frame event. The client may use this information to
calculate a diagonal vector for scrolling.
When multiple wl_pointer.axis events occur within the same frame,
the motion vector is the combined motion of all events.
When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
the same frame, this indicates that axis movement in one axis has
stopped but continues in the other axis.
When multiple wl_pointer.axis_stop events occur within the same
frame, this indicates that these axes stopped in the same instance.
A wl_pointer.frame event is sent for every logical event group,
even if the group only contains a single wl_pointer event.
Specifically, a client may get a sequence: motion, frame, button,
frame, axis, frame, axis_stop, frame.
The wl_pointer.enter and wl_pointer.leave events are logical events
generated by the compositor and not the hardware. These events are
also grouped by a wl_pointer.frame. When a pointer moves from one
surface to another, a compositor should group the
wl_pointer.leave event within the same wl_pointer.frame.
However, a client must not rely on wl_pointer.leave and
wl_pointer.enter being in the same wl_pointer.frame.
Compositor-specific policies may require the wl_pointer.leave and
wl_pointer.enter event being split across multiple wl_pointer.frame
groups.
Describes the source types for axis events. This indicates to the
client how an axis event was physically generated; a client may
adjust the user interface accordingly. For example, scroll events
from a "finger" source may be in a smooth coordinate space with
kinetic scrolling whereas a "wheel" source may be in discrete steps
of a number of lines.
The "continuous" axis source is a device generating events in a
continuous coordinate space, but using something other than a
finger. One example for this source is button-based scrolling where
the vertical motion of a device is converted to scroll events while
a button is held down.
The "wheel tilt" axis source indicates that the actual device is a
wheel but the scroll event is not caused by a rotation but a
(usually sideways) tilt of the wheel.
Source information for scroll and other axes.
This event does not occur on its own. It is sent before a
wl_pointer.frame event and carries the source information for
all events within that frame.
The source specifies how this event was generated. If the source is
wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
sent when the user lifts the finger off the device.
If the source is wl_pointer.axis_source.wheel,
wl_pointer.axis_source.wheel_tilt or
wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
or may not be sent. Whether a compositor sends an axis_stop event
for these sources is hardware-specific and implementation-dependent;
clients must not rely on receiving an axis_stop event for these
scroll sources and should treat scroll sequences from these scroll
sources as unterminated by default.
This event is optional. If the source is unknown for a particular
axis event sequence, no event is sent.
Only one wl_pointer.axis_source event is permitted per frame.
The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
not guaranteed.
Stop notification for scroll and other axes.
For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
is sent to notify a client that the axis sequence has terminated.
This enables the client to implement kinetic scrolling.
See the wl_pointer.axis_source documentation for information on when
this event may be generated.
Any wl_pointer.axis events with the same axis_source after this
event should be considered as the start of a new axis motion.
The timestamp is to be interpreted identical to the timestamp in the
wl_pointer.axis event. The timestamp value may be the same as a
preceding wl_pointer.axis event.
Discrete step information for scroll and other axes.
This event carries the axis value of the wl_pointer.axis event in
discrete steps (e.g. mouse wheel clicks).
This event is deprecated with wl_pointer version 8 - this event is not
sent to clients supporting version 8 or later.
This event does not occur on its own, it is coupled with a
wl_pointer.axis event that represents this axis value on a
continuous scale. The protocol guarantees that each axis_discrete
event is always followed by exactly one axis event with the same
axis number within the same wl_pointer.frame. Note that the protocol
allows for other events to occur between the axis_discrete and
its coupled axis event, including other axis_discrete or axis
events. A wl_pointer.frame must not contain more than one axis_discrete
event per axis type.
This event is optional; continuous scrolling devices
like two-finger scrolling on touchpads do not have discrete
steps and do not generate this event.
The discrete value carries the directional information. e.g. a value
of -2 is two steps towards the negative direction of this axis.
The axis number is identical to the axis number in the associated
axis event.
The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
not guaranteed.
Discrete high-resolution scroll information.
This event carries high-resolution wheel scroll information,
with each multiple of 120 representing one logical scroll step
(a wheel detent). For example, an axis_value120 of 30 is one quarter of
a logical scroll step in the positive direction, a value120 of
-240 are two logical scroll steps in the negative direction within the
same hardware event.
Clients that rely on discrete scrolling should accumulate the
value120 to multiples of 120 before processing the event.
The value120 must not be zero.
This event replaces the wl_pointer.axis_discrete event in clients
supporting wl_pointer version 8 or later.
Where a wl_pointer.axis_source event occurs in the same
wl_pointer.frame, the axis source applies to this event.
The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
not guaranteed.
This specifies the direction of the physical motion that caused a
wl_pointer.axis event, relative to the wl_pointer.axis direction.
Relative directional information of the entity causing the axis
motion.
For a wl_pointer.axis event, the wl_pointer.axis_relative_direction
event specifies the movement direction of the entity causing the
wl_pointer.axis event. For example:
- if a user's fingers on a touchpad move down and this
causes a wl_pointer.axis vertical_scroll down event, the physical
direction is 'identical'
- if a user's fingers on a touchpad move down and this causes a
wl_pointer.axis vertical_scroll up scroll up event ('natural
scrolling'), the physical direction is 'inverted'.
A client may use this information to adjust scroll motion of
components. Specifically, enabling natural scrolling causes the
content to change direction compared to traditional scrolling.
Some widgets like volume control sliders should usually match the
physical direction regardless of whether natural scrolling is
active. This event enables clients to match the scroll direction of
a widget to the physical direction.
This event does not occur on its own, it is coupled with a
wl_pointer.axis event that represents this axis value.
The protocol guarantees that each axis_relative_direction event is
always followed by exactly one axis event with the same
axis number within the same wl_pointer.frame. Note that the protocol
allows for other events to occur between the axis_relative_direction
and its coupled axis event.
The axis number is identical to the axis number in the associated
axis event.
The order of wl_pointer.axis_relative_direction,
wl_pointer.axis_discrete and wl_pointer.axis_source is not
guaranteed.
The wl_keyboard interface represents one or more keyboards
associated with a seat.
Each wl_keyboard has the following logical state:
- an active surface (possibly null),
- the keys currently logically down,
- the active modifiers,
- the active group.
By default, the active surface is null, the keys currently logically down
are empty, the active modifiers and the active group are 0.
This specifies the format of the keymap provided to the
client with the wl_keyboard.keymap event.
This event provides a file descriptor to the client which can be
memory-mapped in read-only mode to provide a keyboard mapping
description.
From version 7 onwards, the fd must be mapped with MAP_PRIVATE by
the recipient, as MAP_SHARED may fail.
Notification that this seat's keyboard focus is on a certain
surface.
The compositor must send the wl_keyboard.modifiers event after this
event.
In the wl_keyboard logical state, this event sets the active surface to
the surface argument and the keys currently logically down to the keys
in the keys argument. The compositor must not send this event if the
wl_keyboard already had an active surface immediately before this event.
Clients should not use the list of pressed keys to emulate key-press
events. The order of keys in the list is unspecified.
Notification that this seat's keyboard focus is no longer on
a certain surface.
The leave notification is sent before the enter notification
for the new focus.
In the wl_keyboard logical state, this event resets all values to their
defaults. The compositor must not send this event if the active surface
of the wl_keyboard was not equal to the surface argument immediately
before this event.
Describes the physical state of a key that produced the key event.
Since version 10, the key can be in a "repeated" pseudo-state which
means the same as "pressed", but is used to signal repetition in the
key event.
The key may only enter the repeated state after entering the pressed
state and before entering the released state. This event may be
generated multiple times while the key is down.
A key was pressed or released.
The time argument is a timestamp with millisecond
granularity, with an undefined base.
The key is a platform-specific key code that can be interpreted
by feeding it to the keyboard mapping (see the keymap event).
If this event produces a change in modifiers, then the resulting
wl_keyboard.modifiers event must be sent after this event.
In the wl_keyboard logical state, this event adds the key to the keys
currently logically down (if the state argument is pressed) or removes
the key from the keys currently logically down (if the state argument is
released). The compositor must not send this event if the wl_keyboard
did not have an active surface immediately before this event. The
compositor must not send this event if state is pressed (resp. released)
and the key was already logically down (resp. was not logically down)
immediately before this event.
Since version 10, compositors may send key events with the "repeated"
key state when a wl_keyboard.repeat_info event with a rate argument of
0 has been received. This allows the compositor to take over the
responsibility of key repetition.
Notifies clients that the modifier and/or group state has
changed, and it should update its local state.
The compositor may send this event without a surface of the client
having keyboard focus, for example to tie modifier information to
pointer focus instead. If a modifier event with pressed modifiers is sent
without a prior enter event, the client can assume the modifier state is
valid until it receives the next wl_keyboard.modifiers event. In order to
reset the modifier state again, the compositor can send a
wl_keyboard.modifiers event with no pressed modifiers.
In the wl_keyboard logical state, this event updates the modifiers and
group.
Informs the client about the keyboard's repeat rate and delay.
This event is sent as soon as the wl_keyboard object has been created,
and is guaranteed to be received by the client before any key press
event.
Negative values for either rate or delay are illegal. A rate of zero
will disable any repeating (regardless of the value of delay).
This event can be sent later on as well with a new value if necessary,
so clients should continue listening for the event past the creation
of wl_keyboard.
The wl_touch interface represents a touchscreen
associated with a seat.
Touch interactions can consist of one or more contacts.
For each contact, a series of events is generated, starting
with a down event, followed by zero or more motion events,
and ending with an up event. Events relating to the same
contact point can be identified by the ID of the sequence.
A new touch point has appeared on the surface. This touch point is
assigned a unique ID. Future events from this touch point reference
this ID. The ID ceases to be valid after a touch up event and may be
reused in the future.
The touch point has disappeared. No further events will be sent for
this touch point and the touch point's ID is released and may be
reused in a future touch down event.
A touch point has changed coordinates.
Indicates the end of a set of events that logically belong together.
A client is expected to accumulate the data in all events within the
frame before proceeding.
A wl_touch.frame terminates at least one event but otherwise no
guarantee is provided about the set of events within a frame. A client
must assume that any state not updated in a frame is unchanged from the
previously known state.
Sent if the compositor decides the touch stream is a global
gesture. No further events are sent to the clients from that
particular gesture. Touch cancellation applies to all touch points
currently active on this client's surface. The client is
responsible for finalizing the touch points, future touch points on
this surface may reuse the touch point ID.
No frame event is required after the cancel event.
Sent when a touchpoint has changed its shape.
This event does not occur on its own. It is sent before a
wl_touch.frame event and carries the new shape information for
any previously reported, or new touch points of that frame.
Other events describing the touch point such as wl_touch.down,
wl_touch.motion or wl_touch.orientation may be sent within the
same wl_touch.frame. A client should treat these events as a single
logical touch point update. The order of wl_touch.shape,
wl_touch.orientation and wl_touch.motion is not guaranteed.
A wl_touch.down event is guaranteed to occur before the first
wl_touch.shape event for this touch ID but both events may occur within
the same wl_touch.frame.
A touchpoint shape is approximated by an ellipse through the major and
minor axis length. The major axis length describes the longer diameter
of the ellipse, while the minor axis length describes the shorter
diameter. Major and minor are orthogonal and both are specified in
surface-local coordinates. The center of the ellipse is always at the
touchpoint location as reported by wl_touch.down or wl_touch.move.
This event is only sent by the compositor if the touch device supports
shape reports. The client has to make reasonable assumptions about the
shape if it did not receive this event.
Sent when a touchpoint has changed its orientation.
This event does not occur on its own. It is sent before a
wl_touch.frame event and carries the new shape information for
any previously reported, or new touch points of that frame.
Other events describing the touch point such as wl_touch.down,
wl_touch.motion or wl_touch.shape may be sent within the
same wl_touch.frame. A client should treat these events as a single
logical touch point update. The order of wl_touch.shape,
wl_touch.orientation and wl_touch.motion is not guaranteed.
A wl_touch.down event is guaranteed to occur before the first
wl_touch.orientation event for this touch ID but both events may occur
within the same wl_touch.frame.
The orientation describes the clockwise angle of a touchpoint's major
axis to the positive surface y-axis and is normalized to the -180 to
+180 degree range. The granularity of orientation depends on the touch
device, some devices only support binary rotation values between 0 and
90 degrees.
This event is only sent by the compositor if the touch device supports
orientation reports.
An output describes part of the compositor geometry. The
compositor works in the 'compositor coordinate system' and an
output corresponds to a rectangular area in that space that is
actually visible. This typically corresponds to a monitor that
displays part of the compositor space. This object is published
as global during start up, or when a monitor is hotplugged.
This enumeration describes how the physical
pixels on an output are laid out.
This describes transformations that clients and compositors apply to
buffer contents.
The flipped values correspond to an initial flip around a
vertical axis followed by rotation.
The purpose is mainly to allow clients to render accordingly and
tell the compositor, so that for fullscreen surfaces, the
compositor will still be able to scan out directly from client
surfaces.
The geometry event describes geometric properties of the output.
The event is sent when binding to the output object and whenever
any of the properties change.
The physical size can be set to zero if it doesn't make sense for this
output (e.g. for projectors or virtual outputs).
The geometry event will be followed by a done event (starting from
version 2).
Clients should use wl_surface.preferred_buffer_transform instead of the
transform advertised by this event to find the preferred buffer
transform to use for a surface.
Note: wl_output only advertises partial information about the output
position and identification. Some compositors, for instance those not
implementing a desktop-style output layout or those exposing virtual
outputs, might fake this information. Instead of using x and y, clients
should use xdg_output.logical_position. Instead of using make and model,
clients should use name and description.
These flags describe properties of an output mode.
They are used in the flags bitfield of the mode event.
The mode event describes an available mode for the output.
The event is sent when binding to the output object and there
will always be one mode, the current mode. The event is sent
again if an output changes mode, for the mode that is now
current. In other words, the current mode is always the last
mode that was received with the current flag set.
Non-current modes are deprecated. A compositor can decide to only
advertise the current mode and never send other modes. Clients
should not rely on non-current modes.
The size of a mode is given in physical hardware units of
the output device. This is not necessarily the same as
the output size in the global compositor space. For instance,
the output may be scaled, as described in wl_output.scale,
or transformed, as described in wl_output.transform. Clients
willing to retrieve the output size in the global compositor
space should use xdg_output.logical_size instead.
The vertical refresh rate can be set to zero if it doesn't make
sense for this output (e.g. for virtual outputs).
The mode event will be followed by a done event (starting from
version 2).
Clients should not use the refresh rate to schedule frames. Instead,
they should use the wl_surface.frame event or the presentation-time
protocol.
Note: this information is not always meaningful for all outputs. Some
compositors, such as those exposing virtual outputs, might fake the
refresh rate or the size.
This event is sent after all other properties have been
sent after binding to the output object and after any
other property changes done after that. This allows
changes to the output properties to be seen as
atomic, even if they happen via multiple events.
This event contains scaling geometry information
that is not in the geometry event. It may be sent after
binding the output object or if the output scale changes
later. The compositor will emit a non-zero, positive
value for scale. If it is not sent, the client should
assume a scale of 1.
A scale larger than 1 means that the compositor will
automatically scale surface buffers by this amount
when rendering. This is used for very high resolution
displays where applications rendering at the native
resolution would be too small to be legible.
Clients should use wl_surface.preferred_buffer_scale
instead of this event to find the preferred buffer
scale to use for a surface.
The scale event will be followed by a done event.
Using this request a client can tell the server that it is not going to
use the output object anymore.
Many compositors will assign user-friendly names to their outputs, show
them to the user, allow the user to refer to an output, etc. The client
may wish to know this name as well to offer the user similar behaviors.
The name is a UTF-8 string with no convention defined for its contents.
Each name is unique among all wl_output globals. The name is only
guaranteed to be unique for the compositor instance.
The same output name is used for all clients for a given wl_output
global. Thus, the name can be shared across processes to refer to a
specific wl_output global.
The name is not guaranteed to be persistent across sessions, thus cannot
be used to reliably identify an output in e.g. configuration files.
Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
not assume that the name is a reflection of an underlying DRM connector,
X11 connection, etc.
The name event is sent after binding the output object. This event is
only sent once per output object, and the name does not change over the
lifetime of the wl_output global.
Compositors may re-use the same output name if the wl_output global is
destroyed and re-created later. Compositors should avoid re-using the
same name if possible.
The name event will be followed by a done event.
Many compositors can produce human-readable descriptions of their
outputs. The client may wish to know this description as well, e.g. for
output selection purposes.
The description is a UTF-8 string with no convention defined for its
contents. The description is not guaranteed to be unique among all
wl_output globals. Examples might include 'Foocorp 11" Display' or
'Virtual X11 output via :1'.
The description event is sent after binding the output object and
whenever the description changes. The description is optional, and may
not be sent at all.
The description event will be followed by a done event.
A region object describes an area.
Region objects are used to describe the opaque and input
regions of a surface.
Destroy the region. This will invalidate the object ID.
Add the specified rectangle to the region.
Subtract the specified rectangle from the region.
The global interface exposing sub-surface compositing capabilities.
A wl_surface, that has sub-surfaces associated, is called the
parent surface. Sub-surfaces can be arbitrarily nested and create
a tree of sub-surfaces.
The root surface in a tree of sub-surfaces is the main
surface. The main surface cannot be a sub-surface, because
sub-surfaces must always have a parent.
A main surface with its sub-surfaces forms a (compound) window.
For window management purposes, this set of wl_surface objects is
to be considered as a single window, and it should also behave as
such.
The aim of sub-surfaces is to offload some of the compositing work
within a window from clients to the compositor. A prime example is
a video player with decorations and video in separate wl_surface
objects. This should allow the compositor to pass YUV video buffer
processing to dedicated overlay hardware when possible.
Informs the server that the client will not be using this
protocol object anymore. This does not affect any other
objects, wl_subsurface objects included.
Create a sub-surface interface for the given surface, and
associate it with the given parent surface. This turns a
plain wl_surface into a sub-surface.
The to-be sub-surface must not already have another role, and it
must not have an existing wl_subsurface object. Otherwise the
bad_surface protocol error is raised.
Adding sub-surfaces to a parent is a double-buffered operation on the
parent (see wl_surface.commit). The effect of adding a sub-surface
becomes visible on the next time the state of the parent surface is
applied.
The parent surface must not be one of the child surface's descendants,
and the parent must be different from the child surface, otherwise the
bad_parent protocol error is raised.
This request modifies the behaviour of wl_surface.commit request on
the sub-surface, see the documentation on wl_subsurface interface.
An additional interface to a wl_surface object, which has been
made a sub-surface. A sub-surface has one parent surface. A
sub-surface's size and position are not limited to that of the parent.
Particularly, a sub-surface is not automatically clipped to its
parent's area.
A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
and the parent surface is mapped. The order of which one happens
first is irrelevant. A sub-surface is hidden if the parent becomes
hidden, or if a NULL wl_buffer is applied. These rules apply
recursively through the tree of surfaces.
The behaviour of a wl_surface.commit request on a sub-surface
depends on the sub-surface's mode. The possible modes are
synchronized and desynchronized, see methods
wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
mode caches the wl_surface state to be applied when the parent's
state gets applied, and desynchronized mode applies the pending
wl_surface state directly. A sub-surface is initially in the
synchronized mode.
Sub-surfaces also have another kind of state, which is managed by
wl_subsurface requests, as opposed to wl_surface requests. This
state includes the sub-surface position relative to the parent
surface (wl_subsurface.set_position), and the stacking order of
the parent and its sub-surfaces (wl_subsurface.place_above and
.place_below). This state is applied when the parent surface's
wl_surface state is applied, regardless of the sub-surface's mode.
As the exception, set_sync and set_desync are effective immediately.
The main surface can be thought to be always in desynchronized mode,
since it does not have a parent in the sub-surfaces sense.
Even if a sub-surface is in desynchronized mode, it will behave as
in synchronized mode, if its parent surface behaves as in
synchronized mode. This rule is applied recursively throughout the
tree of surfaces. This means, that one can set a sub-surface into
synchronized mode, and then assume that all its child and grand-child
sub-surfaces are synchronized, too, without explicitly setting them.
Destroying a sub-surface takes effect immediately. If you need to
synchronize the removal of a sub-surface to the parent surface update,
unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
and then destroy the sub-surface.
If the parent wl_surface object is destroyed, the sub-surface is
unmapped.
A sub-surface never has the keyboard focus of any seat.
The wl_surface.offset request is ignored: clients must use set_position
instead to move the sub-surface.
The sub-surface interface is removed from the wl_surface object
that was turned into a sub-surface with a
wl_subcompositor.get_subsurface request. The wl_surface's association
to the parent is deleted. The wl_surface is unmapped immediately.
This schedules a sub-surface position change.
The sub-surface will be moved so that its origin (top left
corner pixel) will be at the location x, y of the parent surface
coordinate system. The coordinates are not restricted to the parent
surface area. Negative values are allowed.
The scheduled coordinates will take effect whenever the state of the
parent surface is applied.
If more than one set_position request is invoked by the client before
the commit of the parent surface, the position of a new request always
replaces the scheduled position from any previous request.
The initial position is 0, 0.
This sub-surface is taken from the stack, and put back just
above the reference surface, changing the z-order of the sub-surfaces.
The reference surface must be one of the sibling surfaces, or the
parent surface. Using any other surface, including this sub-surface,
will cause a protocol error.
The z-order is double-buffered. Requests are handled in order and
applied immediately to a pending state. The final pending state is
copied to the active state the next time the state of the parent
surface is applied.
A new sub-surface is initially added as the top-most in the stack
of its siblings and parent.
The sub-surface is placed just below the reference surface.
See wl_subsurface.place_above.
Change the commit behaviour of the sub-surface to synchronized
mode, also described as the parent dependent mode.
In synchronized mode, wl_surface.commit on a sub-surface will
accumulate the committed state in a cache, but the state will
not be applied and hence will not change the compositor output.
The cached state is applied to the sub-surface immediately after
the parent surface's state is applied. This ensures atomic
updates of the parent and all its synchronized sub-surfaces.
Applying the cached state will invalidate the cache, so further
parent surface commits do not (re-)apply old state.
See wl_subsurface for the recursive effect of this mode.
Change the commit behaviour of the sub-surface to desynchronized
mode, also described as independent or freely running mode.
In desynchronized mode, wl_surface.commit on a sub-surface will
apply the pending state directly, without caching, as happens
normally with a wl_surface. Calling wl_surface.commit on the
parent surface has no effect on the sub-surface's wl_surface
state. This mode allows a sub-surface to be updated on its own.
If cached state exists when wl_surface.commit is called in
desynchronized mode, the pending state is added to the cached
state, and applied as a whole. This invalidates the cache.
Note: even if a sub-surface is set to desynchronized, a parent
sub-surface may override it to behave as synchronized. For details,
see wl_subsurface.
If a surface's parent surface behaves as desynchronized, then
the cached state is applied on set_desync.
waypipe-v0.10.5/protocols/wlr-data-control-unstable-v1.xml 0000664 0000000 0000000 00000027416 15070717111 0023551 0 ustar 00root root 0000000 0000000
Copyright © 2018 Simon Ser
Copyright © 2019 Ivan Molodetskikh
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
This protocol allows a privileged client to control data devices. In
particular, the client will be able to manage the current selection and take
the role of a clipboard manager.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
This interface is a manager that allows creating per-seat data device
controls.
Create a new data source.
Create a data device that can be used to manage a seat's selection.
All objects created by the manager will still remain valid, until their
appropriate destroy request has been called.
This interface allows a client to manage a seat's selection.
When the seat is destroyed, this object becomes inert.
This request asks the compositor to set the selection to the data from
the source on behalf of the client.
The given source may not be used in any further set_selection or
set_primary_selection requests. Attempting to use a previously used
source is a protocol error.
To unset the selection, set the source to NULL.
Destroys the data device object.
The data_offer event introduces a new wlr_data_control_offer object,
which will subsequently be used in either the
wlr_data_control_device.selection event (for the regular clipboard
selections) or the wlr_data_control_device.primary_selection event (for
the primary clipboard selections). Immediately following the
wlr_data_control_device.data_offer event, the new data_offer object
will send out wlr_data_control_offer.offer events to describe the MIME
types it offers.
The selection event is sent out to notify the client of a new
wlr_data_control_offer for the selection for this device. The
wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
events are sent out immediately before this event to introduce the data
offer object. The selection event is sent to a client when a new
selection is set. The wlr_data_control_offer is valid until a new
wlr_data_control_offer or NULL is received. The client must destroy the
previous selection wlr_data_control_offer, if any, upon receiving this
event.
The first selection event is sent upon binding the
wlr_data_control_device object.
This data control object is no longer valid and should be destroyed by
the client.
The primary_selection event is sent out to notify the client of a new
wlr_data_control_offer for the primary selection for this device. The
wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
events are sent out immediately before this event to introduce the data
offer object. The primary_selection event is sent to a client when a
new primary selection is set. The wlr_data_control_offer is valid until
a new wlr_data_control_offer or NULL is received. The client must
destroy the previous primary selection wlr_data_control_offer, if any,
upon receiving this event.
If the compositor supports primary selection, the first
primary_selection event is sent upon binding the
wlr_data_control_device object.
This request asks the compositor to set the primary selection to the
data from the source on behalf of the client.
The given source may not be used in any further set_selection or
set_primary_selection requests. Attempting to use a previously used
source is a protocol error.
To unset the primary selection, set the source to NULL.
The compositor will ignore this request if it does not support primary
selection.
The wlr_data_control_source object is the source side of a
wlr_data_control_offer. It is created by the source client in a data
transfer and provides a way to describe the offered data and a way to
respond to requests to transfer the data.
This request adds a MIME type to the set of MIME types advertised to
targets. Can be called several times to offer multiple types.
Calling this after wlr_data_control_device.set_selection is a protocol
error.
Destroys the data source object.
Request for data from the client. Send the data as the specified MIME
type over the passed file descriptor, then close it.
This data source is no longer valid. The data source has been replaced
by another data source.
The client should clean up and destroy this data source.
A wlr_data_control_offer represents a piece of data offered for transfer
by another client (the source client). The offer describes the different
MIME types that the data can be converted to and provides the mechanism
for transferring the data directly from the source client.
To transfer the offered data, the client issues this request and
indicates the MIME type it wants to receive. The transfer happens
through the passed file descriptor (typically created with the pipe
system call). The source client writes the data in the MIME type
representation requested and then closes the file descriptor.
The receiving client reads from the read end of the pipe until EOF and
then closes its end, at which point the transfer is complete.
This request may happen multiple times for different MIME types.
Destroys the data offer object.
Sent immediately after creating the wlr_data_control_offer object.
One event per offered MIME type.
waypipe-v0.10.5/protocols/wlr-export-dmabuf-unstable-v1.xml 0000664 0000000 0000000 00000021727 15070717111 0023736 0 ustar 00root root 0000000 0000000
Copyright © 2018 Rostislav Pehlivanov
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.
An interface to capture surfaces in an efficient way by exporting DMA-BUFs.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
This object is a manager with which to start capturing from sources.
Capture the next frame of an entire output.
All objects created by the manager will still remain valid, until their
appropriate destroy request has been called.
This object represents a single DMA-BUF frame.
If the capture is successful, the compositor will first send a "frame"
event, followed by one or several "object". When the frame is available
for readout, the "ready" event is sent.
If the capture failed, the "cancel" event is sent. This can happen anytime
before the "ready" event.
Once either a "ready" or a "cancel" event is received, the client should
destroy the frame. Once an "object" event is received, the client is
responsible for closing the associated file descriptor.
All frames are read-only and may not be written into or altered.
Special flags that should be respected by the client.
Main event supplying the client with information about the frame. If the
capture didn't fail, this event is always emitted first before any other
events.
This event is followed by a number of "object" as specified by the
"num_objects" argument.
Event which serves to supply the client with the file descriptors
containing the data for each object.
After receiving this event, the client must always close the file
descriptor as soon as they're done with it and even if the frame fails.
This event is sent as soon as the frame is presented, indicating it is
available for reading. This event includes the time at which
presentation happened at.
The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
each component being an unsigned 32-bit value. Whole seconds are in
tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
and the additional fractional part in tv_nsec as nanoseconds. Hence,
for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part
may have an arbitrary offset at start.
After receiving this event, the client should destroy this object.
Indicates reason for cancelling the frame.
If the capture failed or if the frame is no longer valid after the
"frame" event has been emitted, this event will be used to inform the
client to scrap the frame.
If the failure is temporary, the client may capture again the same
source. If the failure is permanent, any further attempts to capture the
same source will fail again.
After receiving this event, the client should destroy this object.
Unreferences the frame. This request must be called as soon as its no
longer used.
It can be called at any time by the client. The client will still have
to close any FDs it has been given.
waypipe-v0.10.5/protocols/wlr-gamma-control-unstable-v1.xml 0000664 0000000 0000000 00000012603 15070717111 0023712 0 ustar 00root root 0000000 0000000
Copyright © 2015 Giulio camuffo
Copyright © 2018 Simon Ser
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
This protocol allows a privileged client to set the gamma tables for
outputs.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
This interface is a manager that allows creating per-output gamma
controls.
Create a gamma control that can be used to adjust gamma tables for the
provided output.
All objects created by the manager will still remain valid, until their
appropriate destroy request has been called.
This interface allows a client to adjust gamma tables for a particular
output.
The client will receive the gamma size, and will then be able to set gamma
tables. At any time the compositor can send a failed event indicating that
this object is no longer valid.
There can only be at most one gamma control object per output, which
has exclusive access to this particular output. When the gamma control
object is destroyed, the gamma table is restored to its original value.
Advertise the size of each gamma ramp.
This event is sent immediately when the gamma control object is created.
Set the gamma table. The file descriptor can be memory-mapped to provide
the raw gamma table, which contains successive gamma ramps for the red,
green and blue channels. Each gamma ramp is an array of 16-byte unsigned
integers which has the same length as the gamma size.
The file descriptor data must have the same length as three times the
gamma size.
This event indicates that the gamma control is no longer valid. This
can happen for a number of reasons, including:
- The output doesn't support gamma tables
- Setting the gamma tables failed
- Another client already has exclusive gamma control for this output
- The compositor has transferred gamma control to another client
Upon receiving this event, the client should destroy this object.
Destroys the gamma control object. If the object is still valid, this
restores the original gamma tables.
waypipe-v0.10.5/protocols/wlr-screencopy-unstable-v1.xml 0000664 0000000 0000000 00000023666 15070717111 0023337 0 ustar 00root root 0000000 0000000
Copyright © 2018 Simon Ser
Copyright © 2019 Andri Yngvason
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.
This protocol allows clients to ask the compositor to copy part of the
screen content to a client buffer.
Warning! The protocol described in this file is experimental and
backward incompatible changes may be made. Backward compatible changes
may be added together with the corresponding interface version bump.
Backward incompatible changes are done by bumping the version number in
the protocol and interface names and resetting the interface version.
Once the protocol is to be declared stable, the 'z' prefix and the
version number in the protocol and interface names are removed and the
interface version number is reset.
This object is a manager which offers requests to start capturing from a
source.
Capture the next frame of an entire output.
Capture the next frame of an output's region.
The region is given in output logical coordinates, see
xdg_output.logical_size. The region will be clipped to the output's
extents.
All objects created by the manager will still remain valid, until their
appropriate destroy request has been called.
This object represents a single frame.
When created, a series of buffer events will be sent, each representing a
supported buffer type. The "buffer_done" event is sent afterwards to
indicate that all supported buffer types have been enumerated. The client
will then be able to send a "copy" request. If the capture is successful,
the compositor will send a "flags" followed by a "ready" event.
For objects version 2 or lower, wl_shm buffers are always supported, ie.
the "buffer" event is guaranteed to be sent.
If the capture failed, the "failed" event is sent. This can happen anytime
before the "ready" event.
Once either a "ready" or a "failed" event is received, the client should
destroy the frame.
Provides information about wl_shm buffer parameters that need to be
used for this frame. This event is sent once after the frame is created
if wl_shm buffers are supported.
Copy the frame to the supplied buffer. The buffer must have a the
correct size, see zwlr_screencopy_frame_v1.buffer and
zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a
supported format.
If the frame is successfully copied, a "flags" and a "ready" events are
sent. Otherwise, a "failed" event is sent.
Provides flags about the frame. This event is sent once before the
"ready" event.
Called as soon as the frame is copied, indicating it is available
for reading. This event includes the time at which presentation happened
at.
The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
each component being an unsigned 32-bit value. Whole seconds are in
tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
and the additional fractional part in tv_nsec as nanoseconds. Hence,
for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part
may have an arbitrary offset at start.
After receiving this event, the client should destroy the object.
This event indicates that the attempted frame copy has failed.
After receiving this event, the client should destroy the object.
Destroys the frame. This request can be sent at any time by the client.
Same as copy, except it waits until there is damage to copy.
This event is sent right before the ready event when copy_with_damage is
requested. It may be generated multiple times for each copy_with_damage
request.
The arguments describe a box around an area that has changed since the
last copy request that was derived from the current screencopy manager
instance.
The union of all regions received between the call to copy_with_damage
and a ready event is the total damage since the prior ready event.
Provides information about linux-dmabuf buffer parameters that need to
be used for this frame. This event is sent once after the frame is
created if linux-dmabuf buffers are supported.
This event is sent once after all buffer events have been sent.
The client should proceed to create a buffer of one of the supported
types, and send a "copy" request.
waypipe-v0.10.5/protocols/xdg-shell.xml 0000664 0000000 0000000 00000167241 15070717111 0020111 0 ustar 00root root 0000000 0000000
Copyright © 2008-2013 Kristian Høgsberg
Copyright © 2013 Rafael Antognolli
Copyright © 2013 Jasper St. Pierre
Copyright © 2010-2013 Intel Corporation
Copyright © 2015-2017 Samsung Electronics Co., Ltd
Copyright © 2015-2017 Red Hat Inc.
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.
The xdg_wm_base interface is exposed as a global object enabling clients
to turn their wl_surfaces into windows in a desktop environment. It
defines the basic functionality needed for clients and the compositor to
create windows that can be dragged, resized, maximized, etc, as well as
creating transient windows such as popup menus.
Destroy this xdg_wm_base object.
Destroying a bound xdg_wm_base object while there are surfaces
still alive created by this xdg_wm_base object instance is illegal
and will result in a defunct_surfaces error.
Create a positioner object. A positioner object is used to position
surfaces relative to some parent surface. See the interface description
and xdg_surface.get_popup for details.
This creates an xdg_surface for the given surface. While xdg_surface
itself is not a role, the corresponding surface may only be assigned
a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
illegal to create an xdg_surface for a wl_surface which already has an
assigned role and this will result in a role error.
This creates an xdg_surface for the given surface. An xdg_surface is
used as basis to define a role to a given surface, such as xdg_toplevel
or xdg_popup. It also manages functionality shared between xdg_surface
based surface roles.
See the documentation of xdg_surface for more details about what an
xdg_surface is and how it is used.
A client must respond to a ping event with a pong request or
the client may be deemed unresponsive. See xdg_wm_base.ping
and xdg_wm_base.error.unresponsive.
The ping event asks the client if it's still alive. Pass the
serial specified in the event back to the compositor by sending
a "pong" request back with the specified serial. See xdg_wm_base.pong.
Compositors can use this to determine if the client is still
alive. It's unspecified what will happen if the client doesn't
respond to the ping request, or in what timeframe. Clients should
try to respond in a reasonable amount of time. The “unresponsive”
error is provided for compositors that wish to disconnect unresponsive
clients.
A compositor is free to ping in any way it wants, but a client must
always respond to any xdg_wm_base object it created.
The xdg_positioner provides a collection of rules for the placement of a
child surface relative to a parent surface. Rules can be defined to ensure
the child surface remains within the visible area's borders, and to
specify how the child surface changes its position, such as sliding along
an axis, or flipping around a rectangle. These positioner-created rules are
constrained by the requirement that a child surface must intersect with or
be at least partially adjacent to its parent surface.
See the various requests for details about possible rules.
At the time of the request, the compositor makes a copy of the rules
specified by the xdg_positioner. Thus, after the request is complete the
xdg_positioner object can be destroyed or reused; further changes to the
object will have no effect on previous usages.
For an xdg_positioner object to be considered complete, it must have a
non-zero size set by set_size, and a non-zero anchor rectangle set by
set_anchor_rect. Passing an incomplete xdg_positioner object when
positioning a surface raises an invalid_positioner error.
Notify the compositor that the xdg_positioner will no longer be used.
Set the size of the surface that is to be positioned with the positioner
object. The size is in surface-local coordinates and corresponds to the
window geometry. See xdg_surface.set_window_geometry.
If a zero or negative size is set the invalid_input error is raised.
Specify the anchor rectangle within the parent surface that the child
surface will be placed relative to. The rectangle is relative to the
window geometry as defined by xdg_surface.set_window_geometry of the
parent surface.
When the xdg_positioner object is used to position a child surface, the
anchor rectangle may not extend outside the window geometry of the
positioned child's parent surface.
If a negative size is set the invalid_input error is raised.
Defines the anchor point for the anchor rectangle. The specified anchor
is used derive an anchor point that the child surface will be
positioned relative to. If a corner anchor is set (e.g. 'top_left' or
'bottom_right'), the anchor point will be at the specified corner;
otherwise, the derived anchor point will be centered on the specified
edge, or in the center of the anchor rectangle if no edge is specified.
Defines in what direction a surface should be positioned, relative to
the anchor point of the parent surface. If a corner gravity is
specified (e.g. 'bottom_right' or 'top_left'), then the child surface
will be placed towards the specified gravity; otherwise, the child
surface will be centered over the anchor point on any axis that had no
gravity specified. If the gravity is not in the ‘gravity’ enum, an
invalid_input error is raised.
The constraint adjustment value define ways the compositor will adjust
the position of the surface, if the unadjusted position would result
in the surface being partly constrained.
Whether a surface is considered 'constrained' is left to the compositor
to determine. For example, the surface may be partly outside the
compositor's defined 'work area', thus necessitating the child surface's
position be adjusted until it is entirely inside the work area.
The adjustments can be combined, according to a defined precedence: 1)
Flip, 2) Slide, 3) Resize.
Don't alter the surface position even if it is constrained on some
axis, for example partially outside the edge of an output.
Slide the surface along the x axis until it is no longer constrained.
First try to slide towards the direction of the gravity on the x axis
until either the edge in the opposite direction of the gravity is
unconstrained or the edge in the direction of the gravity is
constrained.
Then try to slide towards the opposite direction of the gravity on the
x axis until either the edge in the direction of the gravity is
unconstrained or the edge in the opposite direction of the gravity is
constrained.
Slide the surface along the y axis until it is no longer constrained.
First try to slide towards the direction of the gravity on the y axis
until either the edge in the opposite direction of the gravity is
unconstrained or the edge in the direction of the gravity is
constrained.
Then try to slide towards the opposite direction of the gravity on the
y axis until either the edge in the direction of the gravity is
unconstrained or the edge in the opposite direction of the gravity is
constrained.
Invert the anchor and gravity on the x axis if the surface is
constrained on the x axis. For example, if the left edge of the
surface is constrained, the gravity is 'left' and the anchor is
'left', change the gravity to 'right' and the anchor to 'right'.
If the adjusted position also ends up being constrained, the resulting
position of the flip_x adjustment will be the one before the
adjustment.
Invert the anchor and gravity on the y axis if the surface is
constrained on the y axis. For example, if the bottom edge of the
surface is constrained, the gravity is 'bottom' and the anchor is
'bottom', change the gravity to 'top' and the anchor to 'top'.
The adjusted position is calculated given the original anchor
rectangle and offset, but with the new flipped anchor and gravity
values.
If the adjusted position also ends up being constrained, the resulting
position of the flip_y adjustment will be the one before the
adjustment.
Resize the surface horizontally so that it is completely
unconstrained.
Resize the surface vertically so that it is completely unconstrained.
Specify how the window should be positioned if the originally intended
position caused the surface to be constrained, meaning at least
partially outside positioning boundaries set by the compositor. The
adjustment is set by constructing a bitmask describing the adjustment to
be made when the surface is constrained on that axis.
If no bit for one axis is set, the compositor will assume that the child
surface should not change its position on that axis when constrained.
If more than one bit for one axis is set, the order of how adjustments
are applied is specified in the corresponding adjustment descriptions.
The default adjustment is none.
Specify the surface position offset relative to the position of the
anchor on the anchor rectangle and the anchor on the surface. For
example if the anchor of the anchor rectangle is at (x, y), the surface
has the gravity bottom|right, and the offset is (ox, oy), the calculated
surface position will be (x + ox, y + oy). The offset position of the
surface is the one used for constraint testing. See
set_constraint_adjustment.
An example use case is placing a popup menu on top of a user interface
element, while aligning the user interface element of the parent surface
with some user interface element placed somewhere in the popup surface.
When set reactive, the surface is reconstrained if the conditions used
for constraining changed, e.g. the parent window moved.
If the conditions changed and the popup was reconstrained, an
xdg_popup.configure event is sent with updated geometry, followed by an
xdg_surface.configure event.
Set the parent window geometry the compositor should use when
positioning the popup. The compositor may use this information to
determine the future state the popup should be constrained using. If
this doesn't match the dimension of the parent the popup is eventually
positioned against, the behavior is undefined.
The arguments are given in the surface-local coordinate space.
Set the serial of an xdg_surface.configure event this positioner will be
used in response to. The compositor may use this information together
with set_parent_size to determine what future state the popup should be
constrained using.
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style user interface.
It provides a base set of functionality required to construct user
interface elements requiring management by the compositor, such as
toplevel windows, menus, etc. The types of functionality are split into
xdg_surface roles.
Creating an xdg_surface does not set the role for a wl_surface. In order
to map an xdg_surface, the client must create a role-specific object
using, e.g., get_toplevel, get_popup. The wl_surface for any given
xdg_surface can have at most one role, and may not be assigned any role
not based on xdg_surface.
A role must be assigned before any other requests are made to the
xdg_surface object.
The client must call wl_surface.commit on the corresponding wl_surface
for the xdg_surface state to take effect.
Creating an xdg_surface from a wl_surface which has a buffer attached or
committed is a client error, and any attempts by a client to attach or
manipulate a buffer prior to the first xdg_surface.configure call must
also be treated as errors.
After creating a role-specific object and setting it up (e.g. by sending
the title, app ID, size constraints, parent, etc), the client must
perform an initial commit without any buffer attached. The compositor
will reply with initial wl_surface state such as
wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
event. The client must acknowledge it and is then allowed to attach a
buffer to map the surface.
Mapping an xdg_surface-based role surface is defined as making it
possible for the surface to be shown by the compositor. Note that
a mapped surface is not guaranteed to be visible once it is mapped.
For an xdg_surface to be mapped by the compositor, the following
conditions must be met:
(1) the client has assigned an xdg_surface-based role to the surface
(2) the client has set and committed the xdg_surface state and the
role-dependent state to the surface
(3) the client has committed a buffer to the surface
A newly-unmapped surface is considered to have met condition (1) out
of the 3 required conditions for mapping a surface if its role surface
has not been destroyed, i.e. the client must perform the initial commit
again before attaching a buffer.
Destroy the xdg_surface object. An xdg_surface must only be destroyed
after its role object has been destroyed, otherwise
a defunct_role_object error is raised.
This creates an xdg_toplevel object for the given xdg_surface and gives
the associated wl_surface the xdg_toplevel role.
See the documentation of xdg_toplevel for more details about what an
xdg_toplevel is and how it is used.
This creates an xdg_popup object for the given xdg_surface and gives
the associated wl_surface the xdg_popup role.
If null is passed as a parent, a parent surface must be specified using
some other protocol, before committing the initial state.
See the documentation of xdg_popup for more details about what an
xdg_popup is and how it is used.
The window geometry of a surface is its "visible bounds" from the
user's perspective. Client-side decorations often have invisible
portions like drop-shadows which should be ignored for the
purposes of aligning, placing and constraining windows.
The window geometry is double-buffered state, see wl_surface.commit.
When maintaining a position, the compositor should treat the (x, y)
coordinate of the window geometry as the top left corner of the window.
A client changing the (x, y) window geometry coordinate should in
general not alter the position of the window.
Once the window geometry of the surface is set, it is not possible to
unset it, and it will remain the same until set_window_geometry is
called again, even if a new subsurface or buffer is attached.
If never set, the value is the full bounds of the surface,
including any subsurfaces. This updates dynamically on every
commit. This unset is meant for extremely simple clients.
The arguments are given in the surface-local coordinate space of
the wl_surface associated with this xdg_surface, and may extend outside
of the wl_surface itself to mark parts of the subsurface tree as part of
the window geometry.
When applied, the effective window geometry will be the set window
geometry clamped to the bounding rectangle of the combined
geometry of the surface of the xdg_surface and the associated
subsurfaces.
The effective geometry will not be recalculated unless a new call to
set_window_geometry is done and the new pending surface state is
subsequently applied.
The width and height of the effective window geometry must be
greater than zero. Setting an invalid size will raise an
invalid_size error.
When a configure event is received, if a client commits the
surface in response to the configure event, then the client
must make an ack_configure request sometime before the commit
request, passing along the serial of the configure event.
For instance, for toplevel surfaces the compositor might use this
information to move a surface to the top left only when the client has
drawn itself for the maximized or fullscreen state.
If the client receives multiple configure events before it
can respond to one, it only has to ack the last configure event.
Acking a configure event that was never sent raises an invalid_serial
error.
A client is not required to commit immediately after sending
an ack_configure request - it may even ack_configure several times
before its next surface commit.
A client may send multiple ack_configure requests before committing, but
only the last request sent before a commit indicates which configure
event the client really is responding to.
Sending an ack_configure request consumes the serial number sent with
the request, as well as serial numbers sent by all configure events
sent on this xdg_surface prior to the configure event referenced by
the committed serial.
It is an error to issue multiple ack_configure requests referencing a
serial from the same configure event, or to issue an ack_configure
request referencing a serial from a configure event issued before the
event identified by the last ack_configure request for the same
xdg_surface. Doing so will raise an invalid_serial error.
The configure event marks the end of a configure sequence. A configure
sequence is a set of one or more events configuring the state of the
xdg_surface, including the final xdg_surface.configure event.
Where applicable, xdg_surface surface roles will during a configure
sequence extend this event as a latched state sent as events before the
xdg_surface.configure event. Such events should be considered to make up
a set of atomically applied configuration states, where the
xdg_surface.configure commits the accumulated state.
Clients should arrange their surface for the new states, and then send
an ack_configure request with the serial sent in this configure event at
some point before committing the new surface.
If the client receives multiple configure events before it can respond
to one, it is free to discard all but the last event it received.
This interface defines an xdg_surface role which allows a surface to,
among other things, set window-like properties such as maximize,
fullscreen, and minimize, set application-specific metadata like title and
id, and well as trigger user interactive operations such as interactive
resize and move.
A xdg_toplevel by default is responsible for providing the full intended
visual representation of the toplevel, which depending on the window
state, may mean things like a title bar, window controls and drop shadow.
Unmapping an xdg_toplevel means that the surface cannot be shown
by the compositor until it is explicitly mapped again.
All active operations (e.g., move, resize) are canceled and all
attributes (e.g. title, state, stacking, ...) are discarded for
an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
the state it had right after xdg_surface.get_toplevel. The client
can re-map the toplevel by performing a commit without any buffer
attached, waiting for a configure event and handling it as usual (see
xdg_surface description).
Attaching a null buffer to a toplevel unmaps the surface.
This request destroys the role surface and unmaps the surface;
see "Unmapping" behavior in interface section for details.
Set the "parent" of this surface. This surface should be stacked
above the parent surface and all other ancestor surfaces.
Parent surfaces should be set on dialogs, toolboxes, or other
"auxiliary" surfaces, so that the parent is raised when the dialog
is raised.
Setting a null parent for a child surface unsets its parent. Setting
a null parent for a surface which currently has no parent is a no-op.
Only mapped surfaces can have child surfaces. Setting a parent which
is not mapped is equivalent to setting a null parent. If a surface
becomes unmapped, its children's parent is set to the parent of
the now-unmapped surface. If the now-unmapped surface has no parent,
its children's parent is unset. If the now-unmapped surface becomes
mapped again, its parent-child relationship is not restored.
The parent toplevel must not be one of the child toplevel's
descendants, and the parent must be different from the child toplevel,
otherwise the invalid_parent protocol error is raised.
Set a short title for the surface.
This string may be used to identify the surface in a task bar,
window list, or other user interface elements provided by the
compositor.
The string must be encoded in UTF-8.
Set an application identifier for the surface.
The app ID identifies the general class of applications to which
the surface belongs. The compositor can use this to group multiple
surfaces together, or to determine how to launch a new application.
For D-Bus activatable applications, the app ID is used as the D-Bus
service name.
The compositor shell will try to group application surfaces together
by their app ID. As a best practice, it is suggested to select app
ID's that match the basename of the application's .desktop file.
For example, "org.freedesktop.FooViewer" where the .desktop file is
"org.freedesktop.FooViewer.desktop".
Like other properties, a set_app_id request can be sent after the
xdg_toplevel has been mapped to update the property.
See the desktop-entry specification [0] for more details on
application identifiers and how they relate to well-known D-Bus
names and .desktop files.
[0] https://standards.freedesktop.org/desktop-entry-spec/
Clients implementing client-side decorations might want to show
a context menu when right-clicking on the decorations, giving the
user a menu that they can use to maximize or minimize the window.
This request asks the compositor to pop up such a window menu at
the given position, relative to the local surface coordinates of
the parent surface. There are no guarantees as to what menu items
the window menu contains, or even if a window menu will be drawn
at all.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event.
Start an interactive, user-driven move of the surface.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event. The passed
serial is used to determine the type of interactive move (touch,
pointer, etc).
The server may ignore move requests depending on the state of
the surface (e.g. fullscreen or maximized), or if the passed serial
is no longer valid.
If triggered, the surface will lose the focus of the device
(wl_pointer, wl_touch, etc) used for the move. It is up to the
compositor to visually indicate that the move is taking place, such as
updating a pointer cursor, during the move. There is no guarantee
that the device focus will return when the move is completed.
These values are used to indicate which edge of a surface
is being dragged in a resize operation.
Start a user-driven, interactive resize of the surface.
This request must be used in response to some sort of user action
like a button press, key press, or touch down event. The passed
serial is used to determine the type of interactive resize (touch,
pointer, etc).
The server may ignore resize requests depending on the state of
the surface (e.g. fullscreen or maximized).
If triggered, the client will receive configure events with the
"resize" state enum value and the expected sizes. See the "resize"
enum value for more details about what is required. The client
must also acknowledge configure events using "ack_configure". After
the resize is completed, the client will receive another "configure"
event without the resize state.
If triggered, the surface also will lose the focus of the device
(wl_pointer, wl_touch, etc) used for the resize. It is up to the
compositor to visually indicate that the resize is taking place,
such as updating a pointer cursor, during the resize. There is no
guarantee that the device focus will return when the resize is
completed.
The edges parameter specifies how the surface should be resized, and
is one of the values of the resize_edge enum. Values not matching
a variant of the enum will cause the invalid_resize_edge protocol error.
The compositor may use this information to update the surface position
for example when dragging the top left corner. The compositor may also
use this information to adapt its behavior, e.g. choose an appropriate
cursor image.
The different state values used on the surface. This is designed for
state values like maximized, fullscreen. It is paired with the
configure event to ensure that both the client and the compositor
setting the state can be synchronized.
States set in this way are double-buffered, see wl_surface.commit.
The surface is maximized. The window geometry specified in the configure
event must be obeyed by the client, or the xdg_wm_base.invalid_surface_state
error is raised.
The client should draw without shadow or other
decoration outside of the window geometry.
The surface is fullscreen. The window geometry specified in the
configure event is a maximum; the client cannot resize beyond it. For
a surface to cover the whole fullscreened area, the geometry
dimensions must be obeyed by the client. For more details, see
xdg_toplevel.set_fullscreen.
The surface is being resized. The window geometry specified in the
configure event is a maximum; the client cannot resize beyond it.
Clients that have aspect ratio or cell sizing configuration can use
a smaller size, however.
Client window decorations should be painted as if the window is
active. Do not assume this means that the window actually has
keyboard or pointer focus.
The window is currently in a tiled layout and the left edge is
considered to be adjacent to another part of the tiling grid.
The client should draw without shadow or other decoration outside of
the window geometry on the left edge.
The window is currently in a tiled layout and the right edge is
considered to be adjacent to another part of the tiling grid.
The client should draw without shadow or other decoration outside of
the window geometry on the right edge.
The window is currently in a tiled layout and the top edge is
considered to be adjacent to another part of the tiling grid.
The client should draw without shadow or other decoration outside of
the window geometry on the top edge.
The window is currently in a tiled layout and the bottom edge is
considered to be adjacent to another part of the tiling grid.
The client should draw without shadow or other decoration outside of
the window geometry on the bottom edge.
The surface is currently not ordinarily being repainted; for
example because its content is occluded by another window, or its
outputs are switched off due to screen locking.
Set a maximum size for the window.
The client can specify a maximum size so that the compositor does
not try to configure the window beyond this size.
The width and height arguments are in window geometry coordinates.
See xdg_surface.set_window_geometry.
Values set in this way are double-buffered, see wl_surface.commit.
The compositor can use this information to allow or disallow
different states like maximize or fullscreen and draw accurate
animations.
Similarly, a tiling window manager may use this information to
place and resize client windows in a more effective way.
The client should not rely on the compositor to obey the maximum
size. The compositor may decide to ignore the values set by the
client and request a larger size.
If never set, or a value of zero in the request, means that the
client has no expected maximum size in the given dimension.
As a result, a client wishing to reset the maximum size
to an unspecified state can use zero for width and height in the
request.
Requesting a maximum size to be smaller than the minimum size of
a surface is illegal and will result in an invalid_size error.
The width and height must be greater than or equal to zero. Using
strictly negative values for width or height will result in a
invalid_size error.
Set a minimum size for the window.
The client can specify a minimum size so that the compositor does
not try to configure the window below this size.
The width and height arguments are in window geometry coordinates.
See xdg_surface.set_window_geometry.
Values set in this way are double-buffered, see wl_surface.commit.
The compositor can use this information to allow or disallow
different states like maximize or fullscreen and draw accurate
animations.
Similarly, a tiling window manager may use this information to
place and resize client windows in a more effective way.
The client should not rely on the compositor to obey the minimum
size. The compositor may decide to ignore the values set by the
client and request a smaller size.
If never set, or a value of zero in the request, means that the
client has no expected minimum size in the given dimension.
As a result, a client wishing to reset the minimum size
to an unspecified state can use zero for width and height in the
request.
Requesting a minimum size to be larger than the maximum size of
a surface is illegal and will result in an invalid_size error.
The width and height must be greater than or equal to zero. Using
strictly negative values for width and height will result in a
invalid_size error.
Maximize the surface.
After requesting that the surface should be maximized, the compositor
will respond by emitting a configure event. Whether this configure
actually sets the window maximized is subject to compositor policies.
The client must then update its content, drawing in the configured
state. The client must also acknowledge the configure when committing
the new content (see ack_configure).
It is up to the compositor to decide how and where to maximize the
surface, for example which output and what region of the screen should
be used.
If the surface was already maximized, the compositor will still emit
a configure event with the "maximized" state.
If the surface is in a fullscreen state, this request has no direct
effect. It may alter the state the surface is returned to when
unmaximized unless overridden by the compositor.
Unmaximize the surface.
After requesting that the surface should be unmaximized, the compositor
will respond by emitting a configure event. Whether this actually
un-maximizes the window is subject to compositor policies.
If available and applicable, the compositor will include the window
geometry dimensions the window had prior to being maximized in the
configure event. The client must then update its content, drawing it in
the configured state. The client must also acknowledge the configure
when committing the new content (see ack_configure).
It is up to the compositor to position the surface after it was
unmaximized; usually the position the surface had before maximizing, if
applicable.
If the surface was already not maximized, the compositor will still
emit a configure event without the "maximized" state.
If the surface is in a fullscreen state, this request has no direct
effect. It may alter the state the surface is returned to when
unmaximized unless overridden by the compositor.
Make the surface fullscreen.
After requesting that the surface should be fullscreened, the
compositor will respond by emitting a configure event. Whether the
client is actually put into a fullscreen state is subject to compositor
policies. The client must also acknowledge the configure when
committing the new content (see ack_configure).
The output passed by the request indicates the client's preference as
to which display it should be set fullscreen on. If this value is NULL,
it's up to the compositor to choose which display will be used to map
this surface.
If the surface doesn't cover the whole output, the compositor will
position the surface in the center of the output and compensate with
with border fill covering the rest of the output. The content of the
border fill is undefined, but should be assumed to be in some way that
attempts to blend into the surrounding area (e.g. solid black).
If the fullscreened surface is not opaque, the compositor must make
sure that other screen content not part of the same surface tree (made
up of subsurfaces, popups or similarly coupled surfaces) are not
visible below the fullscreened surface.
Make the surface no longer fullscreen.
After requesting that the surface should be unfullscreened, the
compositor will respond by emitting a configure event.
Whether this actually removes the fullscreen state of the client is
subject to compositor policies.
Making a surface unfullscreen sets states for the surface based on the following:
* the state(s) it may have had before becoming fullscreen
* any state(s) decided by the compositor
* any state(s) requested by the client while the surface was fullscreen
The compositor may include the previous window geometry dimensions in
the configure event, if applicable.
The client must also acknowledge the configure when committing the new
content (see ack_configure).
Request that the compositor minimize your surface. There is no
way to know if the surface is currently minimized, nor is there
any way to unset minimization on this surface.
If you are looking to throttle redrawing when minimized, please
instead use the wl_surface.frame event for this, as this will
also work with live previews on windows in Alt-Tab, Expose or
similar compositor features.
This configure event asks the client to resize its toplevel surface or
to change its state. The configured state should not be applied
immediately. See xdg_surface.configure for details.
The width and height arguments specify a hint to the window
about how its surface should be resized in window geometry
coordinates. See set_window_geometry.
If the width or height arguments are zero, it means the client
should decide its own window dimension. This may happen when the
compositor needs to configure the state of the surface but doesn't
have any information about any previous or expected dimension.
The states listed in the event specify how the width/height
arguments should be interpreted, and possibly how it should be
drawn.
Clients must send an ack_configure in response to this event. See
xdg_surface.configure and xdg_surface.ack_configure for details.
The close event is sent by the compositor when the user
wants the surface to be closed. This should be equivalent to
the user clicking the close button in client-side decorations,
if your application has any.
This is only a request that the user intends to close the
window. The client may choose to ignore this request, or show
a dialog to ask the user to save their data, etc.
The configure_bounds event may be sent prior to a xdg_toplevel.configure
event to communicate the bounds a window geometry size is recommended
to constrain to.
The passed width and height are in surface coordinate space. If width
and height are 0, it means bounds is unknown and equivalent to as if no
configure_bounds event was ever sent for this surface.
The bounds can for example correspond to the size of a monitor excluding
any panels or other shell components, so that a surface isn't created in
a way that it cannot fit.
The bounds may change at any point, and in such a case, a new
xdg_toplevel.configure_bounds will be sent, followed by
xdg_toplevel.configure and xdg_surface.configure.
This event advertises the capabilities supported by the compositor. If
a capability isn't supported, clients should hide or disable the UI
elements that expose this functionality. For instance, if the
compositor doesn't advertise support for minimized toplevels, a button
triggering the set_minimized request should not be displayed.
The compositor will ignore requests it doesn't support. For instance,
a compositor which doesn't advertise support for minimized will ignore
set_minimized requests.
Compositors must send this event once before the first
xdg_surface.configure event. When the capabilities change, compositors
must send this event again and then send an xdg_surface.configure
event.
The configured state should not be applied immediately. See
xdg_surface.configure for details.
The capabilities are sent as an array of 32-bit unsigned integers in
native endianness.
A popup surface is a short-lived, temporary surface. It can be used to
implement for example menus, popovers, tooltips and other similar user
interface concepts.
A popup can be made to take an explicit grab. See xdg_popup.grab for
details.
When the popup is dismissed, a popup_done event will be sent out, and at
the same time the surface will be unmapped. See the xdg_popup.popup_done
event for details.
Explicitly destroying the xdg_popup object will also dismiss the popup and
unmap the surface. Clients that want to dismiss the popup when another
surface of their own is clicked should dismiss the popup using the destroy
request.
A newly created xdg_popup will be stacked on top of all previously created
xdg_popup surfaces associated with the same xdg_toplevel.
The parent of an xdg_popup must be mapped (see the xdg_surface
description) before the xdg_popup itself.
The client must call wl_surface.commit on the corresponding wl_surface
for the xdg_popup state to take effect.
This destroys the popup. Explicitly destroying the xdg_popup
object will also dismiss the popup, and unmap the surface.
If this xdg_popup is not the "topmost" popup, the
xdg_wm_base.not_the_topmost_popup protocol error will be sent.
This request makes the created popup take an explicit grab. An explicit
grab will be dismissed when the user dismisses the popup, or when the
client destroys the xdg_popup. This can be done by the user clicking
outside the surface, using the keyboard, or even locking the screen
through closing the lid or a timeout.
If the compositor denies the grab, the popup will be immediately
dismissed.
This request must be used in response to some sort of user action like a
button press, key press, or touch down event. The serial number of the
event should be passed as 'serial'.
The parent of a grabbing popup must either be an xdg_toplevel surface or
another xdg_popup with an explicit grab. If the parent is another
xdg_popup it means that the popups are nested, with this popup now being
the topmost popup.
Nested popups must be destroyed in the reverse order they were created
in, e.g. the only popup you are allowed to destroy at all times is the
topmost one.
When compositors choose to dismiss a popup, they may dismiss every
nested grabbing popup as well. When a compositor dismisses popups, it
will follow the same dismissing order as required from the client.
If the topmost grabbing popup is destroyed, the grab will be returned to
the parent of the popup, if that parent previously had an explicit grab.
If the parent is a grabbing popup which has already been dismissed, this
popup will be immediately dismissed. If the parent is a popup that did
not take an explicit grab, an error will be raised.
During a popup grab, the client owning the grab will receive pointer
and touch events for all their surfaces as normal (similar to an
"owner-events" grab in X11 parlance), while the top most grabbing popup
will always have keyboard focus.
This event asks the popup surface to configure itself given the
configuration. The configured state should not be applied immediately.
See xdg_surface.configure for details.
The x and y arguments represent the position the popup was placed at
given the xdg_positioner rule, relative to the upper left corner of the
window geometry of the parent surface.
For version 2 or older, the configure event for an xdg_popup is only
ever sent once for the initial configuration. Starting with version 3,
it may be sent again if the popup is setup with an xdg_positioner with
set_reactive requested, or in response to xdg_popup.reposition requests.
The popup_done event is sent out when a popup is dismissed by the
compositor. The client should destroy the xdg_popup object at this
point.
Reposition an already-mapped popup. The popup will be placed given the
details in the passed xdg_positioner object, and a
xdg_popup.repositioned followed by xdg_popup.configure and
xdg_surface.configure will be emitted in response. Any parameters set
by the previous positioner will be discarded.
The passed token will be sent in the corresponding
xdg_popup.repositioned event. The new popup position will not take
effect until the corresponding configure event is acknowledged by the
client. See xdg_popup.repositioned for details. The token itself is
opaque, and has no other special meaning.
If multiple reposition requests are sent, the compositor may skip all
but the last one.
If the popup is repositioned in response to a configure event for its
parent, the client should send an xdg_positioner.set_parent_configure
and possibly an xdg_positioner.set_parent_size request to allow the
compositor to properly constrain the popup.
If the popup is repositioned together with a parent that is being
resized, but not in response to a configure event, the client should
send an xdg_positioner.set_parent_size request.
The repositioned event is sent as part of a popup configuration
sequence, together with xdg_popup.configure and lastly
xdg_surface.configure to notify the completion of a reposition request.
The repositioned event is to notify about the completion of a
xdg_popup.reposition request. The token argument is the token passed
in the xdg_popup.reposition request.
Immediately after this event is emitted, xdg_popup.configure and
xdg_surface.configure will be sent with the updated size and position,
as well as a new configure serial.
The client should optionally update the content of the popup, but must
acknowledge the new popup configuration for the new position to take
effect. See xdg_surface.ack_configure for details.
waypipe-v0.10.5/protocols/xdg-toplevel-icon-v1.xml 0000664 0000000 0000000 00000022537 15070717111 0022104 0 ustar 00root root 0000000 0000000
Copyright © 2023-2024 Matthias Klumpp
Copyright © 2024 David Edmundson
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.
This protocol allows clients to set icons for their toplevel surfaces
either via the XDG icon stock (using an icon name), or from pixel data.
A toplevel icon represents the individual toplevel (unlike the application
or launcher icon, which represents the application as a whole), and may be
shown in window switchers, window overviews and taskbars that list
individual windows.
This document adheres to RFC 2119 when using words like "must",
"should", "may", etc.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
This interface allows clients to create toplevel window icons and set
them on toplevel windows to be displayed to the user.
Destroy the toplevel icon manager.
This does not destroy objects created with the manager.
Creates a new icon object. This icon can then be attached to a
xdg_toplevel via the 'set_icon' request.
This request assigns the icon 'icon' to 'toplevel', or clears the
toplevel icon if 'icon' was null.
This state is double-buffered and is applied on the next
wl_surface.commit of the toplevel.
After making this call, the xdg_toplevel_icon_v1 provided as 'icon'
can be destroyed by the client without 'toplevel' losing its icon.
The xdg_toplevel_icon_v1 is immutable from this point, and any
future attempts to change it must raise the
'xdg_toplevel_icon_v1.immutable' protocol error.
The compositor must set the toplevel icon from either the pixel data
the icon provides, or by loading a stock icon using the icon name.
See the description of 'xdg_toplevel_icon_v1' for details.
If 'icon' is set to null, the icon of the respective toplevel is reset
to its default icon (usually the icon of the application, derived from
its desktop-entry file, or a placeholder icon).
If this request is passed an icon with no pixel buffers or icon name
assigned, the icon must be reset just like if 'icon' was null.
This event indicates an icon size the compositor prefers to be
available if the client has scalable icons and can render to any size.
When the 'xdg_toplevel_icon_manager_v1' object is created, the
compositor may send one or more 'icon_size' events to describe the list
of preferred icon sizes. If the compositor has no size preference, it
may not send any 'icon_size' event, and it is up to the client to
decide a suitable icon size.
A sequence of 'icon_size' events must be finished with a 'done' event.
If the compositor has no size preferences, it must still send the
'done' event, without any preceding 'icon_size' events.
This event is sent after all 'icon_size' events have been sent.
This interface defines a toplevel icon.
An icon can have a name, and multiple buffers.
In order to be applied, the icon must have either a name, or at least
one buffer assigned. Applying an empty icon (with no buffer or name) to
a toplevel should reset its icon to the default icon.
It is up to compositor policy whether to prefer using a buffer or loading
an icon via its name. See 'set_name' and 'add_buffer' for details.
Destroys the 'xdg_toplevel_icon_v1' object.
The icon must still remain set on every toplevel it was assigned to,
until the toplevel icon is reset explicitly.
This request assigns an icon name to this icon.
Any previously set name is overridden.
The compositor must resolve 'icon_name' according to the lookup rules
described in the XDG icon theme specification[1] using the
environment's current icon theme.
If the compositor does not support icon names or cannot resolve
'icon_name' according to the XDG icon theme specification it must
fall back to using pixel buffer data instead.
If this request is made after the icon has been assigned to a toplevel
via 'set_icon', a 'immutable' error must be raised.
[1]: https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
This request adds pixel data supplied as wl_buffer to the icon.
The client should add pixel data for all icon sizes and scales that
it can provide, or which are explicitly requested by the compositor
via 'icon_size' events on xdg_toplevel_icon_manager_v1.
The wl_buffer supplying pixel data as 'buffer' must be backed by wl_shm
and must be a square (width and height being equal).
If any of these buffer requirements are not fulfilled, a 'invalid_buffer'
error must be raised.
If this icon instance already has a buffer of the same size and scale
from a previous 'add_buffer' request, data from the last request
overrides the preexisting pixel data.
The wl_buffer must be kept alive for as long as the xdg_toplevel_icon
it is associated with is not destroyed, otherwise a 'no_buffer' error
is raised. The buffer contents must not be modified after it was
assigned to the icon. As a result, the region of the wl_shm_pool's
backing storage used for the wl_buffer must not be modified after this
request is sent. The wl_buffer.release event is unused.
If this request is made after the icon has been assigned to a toplevel
via 'set_icon', a 'immutable' error must be raised.
waypipe-v0.10.5/protogen.py 0000775 0000000 0000000 00000060221 15070717111 0015654 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""
Read protocol files, and convert to a rust-readable format
"""
import os
import xml.etree.ElementTree
import subprocess
# Table of functions for which to generate helper code
handled_funcs = [
("ext_data_control_device_v1", "data_offer"),
("ext_data_control_device_v1", "selection"),
("ext_data_control_device_v1", "set_selection"),
("ext_data_control_manager_v1", "create_data_source"),
("ext_data_control_manager_v1", "get_data_device"),
("ext_data_control_offer_v1", "offer"),
("ext_data_control_offer_v1", "receive"),
("ext_data_control_source_v1", "offer"),
("ext_data_control_source_v1", "send"),
("ext_image_copy_capture_cursor_session_v1", "get_capture_session"),
("ext_image_copy_capture_frame_v1", "attach_buffer"),
("ext_image_copy_capture_frame_v1", "capture"),
("ext_image_copy_capture_frame_v1", "damage_buffer"),
("ext_image_copy_capture_frame_v1", "destroy"),
("ext_image_copy_capture_frame_v1", "failed"),
("ext_image_copy_capture_frame_v1", "presentation_time"),
("ext_image_copy_capture_frame_v1", "ready"),
("ext_image_copy_capture_manager_v1", "create_session"),
("ext_image_copy_capture_session_v1", "buffer_size"),
("ext_image_copy_capture_session_v1", "create_frame"),
("ext_image_copy_capture_session_v1", "destroy"),
("ext_image_copy_capture_session_v1", "dmabuf_device"),
("ext_image_copy_capture_session_v1", "dmabuf_format"),
("ext_image_copy_capture_session_v1", "done"),
("ext_image_copy_capture_session_v1", "shm_format"),
("ext_output_image_capture_source_manager_v1", "create_source"),
("gtk_primary_selection_device", "data_offer"),
("gtk_primary_selection_device", "selection"),
("gtk_primary_selection_device", "set_selection"),
("gtk_primary_selection_device_manager", "create_source"),
("gtk_primary_selection_device_manager", "get_device"),
("gtk_primary_selection_offer", "offer"),
("gtk_primary_selection_offer", "receive"),
("gtk_primary_selection_source", "offer"),
("gtk_primary_selection_source", "send"),
("wl_buffer", "destroy"),
("wl_buffer", "release"),
("wl_callback", "done"),
("wl_compositor", "create_surface"),
("wl_data_device", "data_offer"),
("wl_data_device", "selection"),
("wl_data_device", "set_selection"),
("wl_data_device_manager", "create_data_source"),
("wl_data_device_manager", "get_data_device"),
("wl_data_offer", "offer"),
("wl_data_offer", "receive"),
("wl_data_source", "offer"),
("wl_data_source", "send"),
("wl_display", "delete_id"),
("wl_display", "error"),
("wl_display", "get_registry"),
("wl_display", "sync"),
("wl_keyboard", "keymap"),
("wl_registry", "bind"),
("wl_registry", "global"),
("wl_registry", "global_remove"),
("wl_seat", "capabilities"),
("wl_seat", "get_keyboard"),
("wl_shm", "create_pool"),
("wl_shm_pool", "create_buffer"),
("wl_shm_pool", "destroy"),
("wl_shm_pool", "resize"),
("wl_surface", "attach"),
("wl_surface", "commit"),
("wl_surface", "damage"),
("wl_surface", "damage_buffer"),
("wl_surface", "destroy"),
("wl_surface", "set_buffer_scale"),
("wl_surface", "set_buffer_transform"),
("wp_color_management_output_v1", "get_image_description"),
("wp_color_manager_v1", "create_icc_creator"),
("wp_color_manager_v1", "get_output"),
("wp_commit_timer_v1", "set_timestamp"),
("wp_commit_timing_manager_v1", "get_timer"),
("wp_image_description_creator_icc_v1", "set_icc_file"),
("wp_image_description_info_v1", "icc_file"),
("wp_image_description_v1", "get_information"),
("wp_linux_drm_syncobj_manager_v1", "get_surface"),
("wp_linux_drm_syncobj_manager_v1", "import_timeline"),
("wp_linux_drm_syncobj_surface_v1", "set_acquire_point"),
("wp_linux_drm_syncobj_surface_v1", "set_release_point"),
("wp_presentation", "clock_id"),
("wp_presentation", "destroy"),
("wp_presentation", "feedback"),
("wp_presentation_feedback", "presented"),
("wp_security_context_manager_v1", "create_listener"),
("wp_security_context_v1", "commit"),
("wp_security_context_v1", "set_app_id"),
("wp_security_context_v1", "set_instance_id"),
("wp_security_context_v1", "set_sandbox_engine"),
("wp_viewport", "destroy"),
("wp_viewport", "set_destination"),
("wp_viewport", "set_source"),
("wp_viewporter", "get_viewport"),
("xdg_surface", "get_toplevel"),
("xdg_toplevel", "set_title"),
("xdg_toplevel_icon_manager_v1", "create_icon"),
("xdg_toplevel_icon_manager_v1", "done"),
("xdg_toplevel_icon_manager_v1", "icon_size"),
("xdg_toplevel_icon_v1", "add_buffer"),
("xdg_wm_base", "get_xdg_surface"),
("zwlr_data_control_device_v1", "data_offer"),
("zwlr_data_control_device_v1", "selection"),
("zwlr_data_control_device_v1", "set_selection"),
("zwlr_data_control_manager_v1", "create_data_source"),
("zwlr_data_control_manager_v1", "get_data_device"),
("zwlr_data_control_offer_v1", "offer"),
("zwlr_data_control_offer_v1", "receive"),
("zwlr_data_control_source_v1", "offer"),
("zwlr_data_control_source_v1", "send"),
("zwlr_gamma_control_manager_v1", "get_gamma_control"),
("zwlr_gamma_control_v1", "gamma_size"),
("zwlr_gamma_control_v1", "set_gamma"),
("zwlr_screencopy_frame_v1", "buffer"),
("zwlr_screencopy_frame_v1", "buffer_done"),
("zwlr_screencopy_frame_v1", "copy"),
("zwlr_screencopy_frame_v1", "copy_with_damage"),
("zwlr_screencopy_frame_v1", "destroy"),
("zwlr_screencopy_frame_v1", "failed"),
("zwlr_screencopy_frame_v1", "linux_dmabuf"),
("zwlr_screencopy_frame_v1", "ready"),
("zwlr_screencopy_manager_v1", "capture_output"),
("zwlr_screencopy_manager_v1", "capture_output_region"),
("zwp_linux_buffer_params_v1", "add"),
("zwp_linux_buffer_params_v1", "create"),
("zwp_linux_buffer_params_v1", "create_immed"),
("zwp_linux_buffer_params_v1", "created"),
("zwp_linux_buffer_params_v1", "destroy"),
("zwp_linux_buffer_params_v1", "failed"),
("zwp_linux_dmabuf_feedback_v1", "done"),
("zwp_linux_dmabuf_feedback_v1", "format_table"),
("zwp_linux_dmabuf_feedback_v1", "main_device"),
("zwp_linux_dmabuf_feedback_v1", "tranche_done"),
("zwp_linux_dmabuf_feedback_v1", "tranche_flags"),
("zwp_linux_dmabuf_feedback_v1", "tranche_formats"),
("zwp_linux_dmabuf_feedback_v1", "tranche_target_device"),
("zwp_linux_dmabuf_v1", "create_params"),
("zwp_linux_dmabuf_v1", "format"),
("zwp_linux_dmabuf_v1", "get_default_feedback"),
("zwp_linux_dmabuf_v1", "get_surface_feedback"),
("zwp_linux_dmabuf_v1", "modifier"),
("zwp_primary_selection_device_manager_v1", "create_source"),
("zwp_primary_selection_device_manager_v1", "get_device"),
("zwp_primary_selection_device_v1", "data_offer"),
("zwp_primary_selection_device_v1", "selection"),
("zwp_primary_selection_device_v1", "set_selection"),
("zwp_primary_selection_offer_v1", "offer"),
("zwp_primary_selection_offer_v1", "receive"),
("zwp_primary_selection_source_v1", "offer"),
("zwp_primary_selection_source_v1", "send"),
]
assert handled_funcs == sorted(handled_funcs), "\n".join(
[str(x) for x in sorted(handled_funcs)]
)
handled_funcs = set(handled_funcs)
handled_enums = set([("wl_output", "transform"), ("wl_shm", "format")])
header = """/*! Wayland protocol interface and method data and functions. Code automatically generated from protocols/ folder. */
#![allow(clippy::all,dead_code)]
use crate::wayland::*;
use crate::wayland::WaylandArgument::*;
use WaylandInterface::*;
"""
def unsnake(s):
return "".join(map(lambda x: x.capitalize(), s.split("_")))
def get_signature(method):
"""
returns a string like "[Int, Uint, NewId(WlOutput)]"
"""
vals = []
for arg in method:
if arg.tag != "arg":
continue
allow_null = "allow-null" in arg.attrib and arg.attrib["allow-null"] == "true"
if arg.attrib["type"] == "object":
if "interface" in arg.attrib:
vals.append("Object(" + unsnake(arg.attrib["interface"]) + ")")
else:
vals.append("GenericObject")
elif arg.attrib["type"] == "new_id":
if "interface" in arg.attrib:
vals.append("NewId(" + unsnake(arg.attrib["interface"]) + ")")
else:
vals.append("GenericNewId")
elif arg.attrib["type"] == "int":
vals.append("Int")
elif arg.attrib["type"] == "uint":
vals.append("Uint")
elif arg.attrib["type"] == "fixed":
vals.append("Fixed")
elif arg.attrib["type"] == "string":
if allow_null:
vals.append("OptionalString")
else:
vals.append("String")
elif arg.attrib["type"] == "array":
vals.append("Array")
elif arg.attrib["type"] == "fd":
vals.append("Fd")
else:
raise NotImplementedError(arg.attrib)
return "&[" + ", ".join(vals) + "]"
def write_method_length(meth_name, method, write):
"""
Create a function to report how long the method would be
"""
lines = []
args = []
base_len = 8
for arg in method:
if arg.tag != "arg":
continue
if arg.attrib["type"] == "new_id":
if "interface" in arg.attrib:
base_len += 4
else:
arg_name = arg.attrib["name"] + "_iface_name_len"
args.append(arg_name + ": usize")
lines.append(" v += length_string({});".format(arg_name))
base_len += 8
elif arg.attrib["type"] in ("int", "uint", "object", "fixed"):
base_len += 4
elif arg.attrib["type"] == "string":
args.append(arg.attrib["name"] + "_len : usize")
lines.append(
" v += length_string({});".format(arg.attrib["name"] + "_len")
)
elif arg.attrib["type"] == "array":
args.append(arg.attrib["name"] + "_len : usize")
lines.append(
" v += length_array({});".format(arg.attrib["name"] + "_len")
)
elif arg.attrib["type"] == "fd":
pass
else:
raise NotImplementedError(arg.attrib)
write("pub fn length_{}({}) -> usize {{".format(meth_name, ", ".join(args)))
if lines:
write(" let mut v = {};".format(base_len))
for l in lines:
write(l)
write(" v")
else:
write(" {}".format(base_len))
write("}")
def write_method_write(meth_name, meth_num, method, write):
"""
Create a function to write the method to a buffer
"""
num_fds = 0
length_args = []
for arg in method:
if arg.tag != "arg":
continue
if arg.attrib["type"] == "new_id":
if "interface" not in arg.attrib:
length_args.append(arg.attrib["name"] + "_iface_name")
elif arg.attrib["type"] == "string":
length_args.append(arg.attrib["name"])
elif arg.attrib["type"] == "array":
length_args.append(arg.attrib["name"])
elif arg.attrib["type"] == "fd":
num_fds += 1
elif arg.attrib["type"] in ("uint", "int", "object", "fixed"):
pass
else:
raise NotImplementedError(arg.attrib)
length_args = [x + ".len()" for x in length_args]
args = ["dst: &mut &mut [u8]", "for_id: ObjId"]
lines = [
" let l = length_{}({});".format(meth_name, ", ".join(length_args)),
]
if num_fds > 0:
args.append("tag_fds: bool")
lines.append(
" write_header(dst, for_id, l, {}, if tag_fds {{ {} }} else {{ 0 }});".format(
meth_num, num_fds
)
)
else:
lines.append(" write_header(dst, for_id, l, {}, 0);".format(meth_num))
base_len = 8
for arg in method:
if arg.tag != "arg":
continue
allow_null = "allow-null" in arg.attrib and arg.attrib["allow-null"] == "true"
if arg.attrib["type"] == "object":
args.append(arg.attrib["name"] + ": ObjId")
lines.append(" write_obj(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "new_id":
assert not allow_null
if "interface" in arg.attrib:
args.append(arg.attrib["name"] + ": ObjId")
lines.append(" write_obj(dst, {});".format(arg.attrib["name"]))
else:
args.append(arg.attrib["name"] + "_iface_name" + ": &[u8]")
args.append(arg.attrib["name"] + "_version" + ": u32")
args.append(arg.attrib["name"] + ": ObjId")
lines.append(
" write_string(dst, Some({}));".format(
arg.attrib["name"] + "_iface_name"
)
)
lines.append(
" write_u32(dst, {});".format(arg.attrib["name"] + "_version")
)
lines.append(" write_obj(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "int":
args.append(arg.attrib["name"] + ": i32")
lines.append(" write_i32(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "uint":
args.append(arg.attrib["name"] + ": u32")
lines.append(" write_u32(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "fixed":
args.append(arg.attrib["name"] + ": i32")
lines.append(" write_i32(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "string":
if allow_null:
args.append(arg.attrib["name"] + ": Option<&[u8]>")
lines.append(" write_string(dst, {});".format(arg.attrib["name"]))
else:
args.append(arg.attrib["name"] + ": &[u8]")
lines.append(
" write_string(dst, Some({}));".format(arg.attrib["name"])
)
elif arg.attrib["type"] == "array":
args.append(arg.attrib["name"] + ": &[u8]")
lines.append(" write_array(dst, {});".format(arg.attrib["name"]))
elif arg.attrib["type"] == "fd":
pass
else:
raise NotImplementedError(arg.attrib)
write("pub fn write_{}({}) {{".format(meth_name, ", ".join(args)))
for l in lines:
write(l)
write("}")
def write_method_parse(meth_name, method, write):
"""
Create a function to parse the method tail
"""
length_args = []
for arg in method:
if arg.tag != "arg":
continue
if arg.attrib["type"] == "new_id":
if "interface" not in arg.attrib:
length_args.append(arg.attrib["name"] + "_iface_name")
elif arg.attrib["type"] == "string":
length_args.append(arg.attrib["name"])
elif arg.attrib["type"] == "array":
length_args.append(arg.attrib["name"])
elif arg.attrib["type"] in ("fd", "uint", "int", "object", "fixed"):
pass
else:
raise NotImplementedError(arg.attrib)
sig = []
lines = []
ret = []
for i, arg in enumerate(method):
if arg.tag != "arg":
continue
allow_null = "allow-null" in arg.attrib and arg.attrib["allow-null"] == "true"
if arg.attrib["type"] == "object":
lines.append(" let arg{} = parse_obj(&mut msg)?;".format(i))
sig.append("ObjId")
ret.append("arg{}".format(i))
elif arg.attrib["type"] == "new_id":
if "interface" in arg.attrib:
lines.append(" let arg{} = parse_obj(&mut msg)?;".format(i))
ret.append("arg{}".format(i))
sig.append("ObjId")
else:
lines.append(
" let arg{}_iface_name = parse_string(&mut msg)?.ok_or(PARSE_ERROR)?;".format(
i
)
)
lines.append(" let arg{}_version = parse_u32(&mut msg)?;".format(i))
lines.append(" let arg{} = parse_obj(&mut msg)?;".format(i))
sig.append("&'a [u8]")
sig.append("u32")
sig.append("ObjId")
ret.append("arg{}_iface_name".format(i))
ret.append("arg{}_version".format(i))
ret.append("arg{}".format(i))
elif arg.attrib["type"] in ("int", "fixed"):
lines.append(" let arg{} = parse_i32(&mut msg)?;".format(i))
sig.append("i32")
ret.append("arg{}".format(i))
elif arg.attrib["type"] == "uint":
lines.append(" let arg{} = parse_u32(&mut msg)?;".format(i))
sig.append("u32")
ret.append("arg{}".format(i))
elif arg.attrib["type"] == "string":
if allow_null:
lines.append(" let arg{} = parse_string(&mut msg)?;".format(i))
sig.append("Option<&'a [u8]>")
else:
lines.append(
" let arg{} = parse_string(&mut msg)?.ok_or(PARSE_ERROR)?;".format(
i
)
)
sig.append("&'a [u8]")
ret.append("arg{}".format(i))
elif arg.attrib["type"] == "array":
lines.append(" let arg{} = parse_array(&mut msg)?;".format(i))
sig.append("&'a [u8]")
ret.append("arg{}".format(i))
elif arg.attrib["type"] == "fd":
pass
else:
raise NotImplementedError(arg.attrib)
tail_prefix = "" if not sig else "mut "
paren = (lambda x: "(" + x + ")") if len(sig) != 1 else (lambda x: x)
write(
"pub fn parse_{}<'a>({}msg: &'a [u8]) -> Result<{}, &'static str> {{".format(
meth_name, tail_prefix, paren(", ".join(sig))
)
)
if sig:
write(" msg = msg.get(8..).ok_or(PARSE_ERROR)?;")
for l in lines:
write(l)
write(" if !msg.is_empty() { return Err(PARSE_ERROR); }")
else:
write(" if msg.len() != 8 { return Err(PARSE_ERROR); }")
write(" Ok(" + paren(", ".join(ret)) + ")")
write("}")
def write_enum(enum_name, enum_entries, enum_values, with_try, write):
write("pub enum " + enum_name + " {")
for i, (name, value) in enumerate(zip(enum_entries, enum_values)):
write(" " + name + " = " + str(value) + ",")
write("}")
if with_try:
write("impl TryFrom for " + enum_name + " {")
write(" type Error = ();")
write(" fn try_from(v: u32) -> Result {")
write(" Ok(match v {")
for i, (name, value) in enumerate(zip(enum_entries, enum_values)):
write(" {} => {}::{},".format(value, enum_name, name))
write(" _ => return Err(()),")
write(" })")
write(" }")
write("}")
def process_interface(interface, uid, write):
iface_name = interface.attrib["name"]
iface_version = interface.attrib["version"]
evts = []
reqs = []
for thing in interface:
if thing.tag == "event" or thing.tag == "request":
signature = get_signature(thing)
destructor = "type" in thing.attrib and thing.attrib["type"] == "destructor"
dst = evts if thing.tag == "event" else reqs
meth_num = len(dst)
name = thing.attrib["name"]
dst.append((name, signature, destructor))
meth_name = (
("evt" if thing.tag == "event" else "req")
+ "_"
+ iface_name
+ "_"
+ name
)
if (iface_name, name) in handled_funcs:
write_method_write(meth_name, meth_num, thing, write)
write_method_length(meth_name, thing, write)
write_method_parse(meth_name, thing, write)
write(
"pub const {} : MethodId = {}({});".format(
"OPCODE_" + iface_name.upper() + "_" + name.upper(),
"MethodId::Event"
if thing.tag == "event"
else "MethodId::Request",
len(dst) - 1,
)
)
handled_funcs.remove((iface_name, name))
elif thing.tag == "enum":
enum_name = iface_name + "_" + thing.attrib["name"]
names = []
values = []
for elt in thing:
if elt.tag == "entry":
name = unsnake(elt.attrib["name"])
if name.isnumeric():
name = "Item" + name
names.append(name)
values.append(elt.attrib["value"])
do_try = (iface_name, thing.attrib["name"]) in handled_enums
if do_try:
handled_enums.remove((iface_name, thing.attrib["name"]))
write("#[derive(Debug,Clone,Copy,PartialEq,Eq)]")
write_enum(unsnake(enum_name), names, values, do_try, write)
write("const " + "DATA_" + iface_name.upper() + ": WaylandData = WaylandData {")
write(' name: "' + iface_name + '",')
if evts:
write(" evts: &[")
for name, sig, destructor in evts:
write(" WaylandMethod {")
write(' name: "' + name + '",')
write(" sig: " + sig + ",")
write(" destructor: " + str(destructor).lower() + ",")
write(" },")
write(" ],")
else:
write(" evts: &[],")
if reqs:
write(" reqs: &[")
for name, sig, destructor in reqs:
write(" WaylandMethod {")
write(' name: "' + name + '",')
write(" sig: " + sig + ",")
write(" destructor: " + str(destructor).lower() + ",")
write(" },")
write(" ],")
else:
write(" reqs: &[],")
write(" version: " + iface_version + ",")
write("};")
write(
"pub const "
+ iface_name.upper()
+ ": &[u8] = DATA_"
+ iface_name.upper()
+ ".name.as_bytes();"
)
if False:
if evts:
write_enum(
unsnake(iface_name) + "EvtIDs",
[unsnake(name) for name, _, _ in evts],
list(range(len(evts))),
False,
write,
)
if reqs:
write_enum(
unsnake(iface_name) + "ReqIDs",
[unsnake(name) for name, _, _ in reqs],
list(range(len(reqs))),
False,
write,
)
return iface_name
if __name__ == "__main__":
protocols = sorted(os.listdir(path="protocols"))
if not all(map(lambda x: x.endswith(".xml"), protocols)):
print("Not all files in protocols/ are XML files:", protocols)
quit()
with open("src/wayland_gen.rs", "w") as output:
def write(*x):
print(*x, file=output)
write(header)
interfaces = []
uid = 0
for protocol_file in protocols:
root = xml.etree.ElementTree.parse("protocols/" + protocol_file).getroot()
for interface in root:
if interface.tag == "interface":
interfaces.append(process_interface(interface, uid, write))
uid += 1
write("#[repr(u8)]")
write("#[derive(Debug,Clone,Copy)]")
write_enum(
"WaylandInterface",
[unsnake(x) for x in sorted(interfaces)],
list(range(len(interfaces))),
True,
write,
)
write("pub const INTERFACE_TABLE : &[WaylandData] = &[")
for i, intf in enumerate(sorted(interfaces)):
write(" {},".format("DATA_" + intf.upper()))
write("];")
if handled_enums or handled_funcs:
raise Exception("Unhandled: {} {}".format(handled_funcs, handled_enums))
subprocess.call(["rustfmt", "src/wayland_gen.rs"])
waypipe-v0.10.5/shaders/ 0000775 0000000 0000000 00000000000 15070717111 0015072 5 ustar 00root root 0000000 0000000 waypipe-v0.10.5/shaders/Cargo.lock 0000664 0000000 0000000 00000000237 15070717111 0017001 0 ustar 00root root 0000000 0000000 # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "waypipe-shaders"
version = "0.1.0"
waypipe-v0.10.5/shaders/Cargo.toml 0000664 0000000 0000000 00000000136 15070717111 0017022 0 ustar 00root root 0000000 0000000 [package]
name = "waypipe-shaders"
version = "0.1.0"
edition = "2021"
rust-version = "1.56.0"
waypipe-v0.10.5/shaders/build.rs 0000664 0000000 0000000 00000003217 15070717111 0016542 0 ustar 00root root 0000000 0000000 use std::env;
use std::ffi::OsStr;
use std::fmt::Write;
use std::fs;
use std::path::Path;
use std::process::Command;
fn main() {
let paths = fs::read_dir("./").unwrap();
let mut shaders = Vec::new();
for p in paths {
let q = p.unwrap();
if q.path().extension() == Some(OsStr::new("glsl")) {
shaders.push(q.path());
}
}
/* No rerun-if directives -- these will track changes to
* existing files, but not register any new shaders. */
let compiler = "glslc";
/* If parallelization is ever needed, use jobserver */
shaders.sort();
let mut contents = String::new();
for shader in shaders {
let args: &[&OsStr] = &[
OsStr::new("-O"),
OsStr::new("-fshader-stage=compute"),
shader.as_os_str(),
OsStr::new("-o"),
OsStr::new("-"),
];
let spirv = Command::new(compiler)
.args(args)
.output()
.expect("Failed to compile file")
.stdout;
let s: &str = shader.file_stem().unwrap().to_str().unwrap();
write!(
&mut contents,
"pub const {}: &[u32] = &[\n",
s.to_uppercase()
)
.unwrap();
assert!(spirv.len() % 4 == 0);
for w in spirv.chunks_exact(4) {
let block = u32::from_ne_bytes(w.try_into().unwrap());
write!(&mut contents, " {:#010x},\n", block).unwrap();
}
write!(&mut contents, "];\n").unwrap();
}
let generated_path = Path::new(&env::var("OUT_DIR").unwrap()).join("shaders.rs");
fs::write(&generated_path, contents).unwrap();
}
waypipe-v0.10.5/shaders/check.sh 0000775 0000000 0000000 00000000506 15070717111 0016507 0 ustar 00root root 0000000 0000000 #!/bin/sh
glslc -Werror -O -fshader-stage=compute nv12_img_to_rgb.glsl -o - >/dev/null
glslc -Werror -O -fshader-stage=compute rgb_to_nv12_img.glsl -o - >/dev/null
glslc -Werror -O -fshader-stage=compute rgb_to_yuv420_buf.glsl -o - >/dev/null
glslc -Werror -O -fshader-stage=compute yuv420_buf_to_rgb.glsl -o - >/dev/null
waypipe-v0.10.5/shaders/nv12_img_to_rgb.glsl 0000664 0000000 0000000 00000001705 15070717111 0020736 0 ustar 00root root 0000000 0000000 #version 450
layout(binding = 0, rgba8) uniform writeonly image2D output_img;
layout(binding = 1) uniform sampler2D input_y;
layout(binding = 2) uniform sampler2D input_vu;
layout(push_constant) uniform constants { mat3x4 ybr_to_rgb; }
push;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
ivec2 brdim = textureSize(input_vu, 0);
ivec2 ydim = textureSize(input_y, 0);
ivec2 outdim = imageSize(output_img);
/* input_vu has exactly half the size of input_y */
/* invocation x/y ranges over all pixels of output */
vec2 pos = min(vec2(gl_GlobalInvocationID.xy) + 0.5, vec2(ydim));
float y = texture(input_y, pos).r;
vec2 br = texture(input_vu, pos / 2.0).gr;
vec4 ybro = vec4(y, br.r, br.g, 1.0);
vec3 rgb = transpose(push.ybr_to_rgb) * ybro;
vec4 val = vec4(rgb, 1);
ivec2 opos = ivec2(gl_GlobalInvocationID.xy);
if (opos.x < outdim.x && opos.y < outdim.y) {
imageStore(output_img, opos, val);
}
}
waypipe-v0.10.5/shaders/rgb_to_nv12_img.glsl 0000664 0000000 0000000 00000002425 15070717111 0020736 0 ustar 00root root 0000000 0000000 #version 450
layout(binding = 0) uniform sampler2D input_rgb;
layout(binding = 1, r8) uniform writeonly image2D output_y;
layout(binding = 2, rg8) uniform writeonly image2D output_vu;
layout(push_constant) uniform constants { mat3x4 rgb_to_yrb; }
push;
/* Each individual task fills 2x2 pixels. */
/* note: AMD subgroupSize is 64, so 8x8 is needed to fully use it */
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
ivec2 brdim = imageSize(output_vu);
ivec2 ydim = imageSize(output_y);
ivec2 rgbdim = textureSize(input_rgb, 0);
vec4 avg = vec4(0.);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
ivec2 pos = ivec2(2 * gl_GlobalInvocationID.x + i,
2 * gl_GlobalInvocationID.y + j);
vec2 sample_pos = vec2(pos) + 0.5;
vec4 rgbo = vec4(texture(input_rgb, sample_pos).rgb, 1.0);
float y = (transpose(push.rgb_to_yrb) * rgbo).r;
imageStore(output_y, pos, vec4(y, 1., 1., 1.));
avg += rgbo;
}
}
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
vec2 sample_pos = vec2(2 * pos + 0.5) + 0.5;
// vec4 rgbo = vec4(texture(input_rgb, sample_pos).rgb, 1.0);
vec4 rgbo = avg / 4;
vec2 vu = (transpose(push.rgb_to_yrb) * rgbo).bg;
imageStore(output_vu, pos, vec4(vu, 1., 1.));
}
waypipe-v0.10.5/shaders/rgb_to_yuv420_buf.glsl 0000664 0000000 0000000 00000003056 15070717111 0021222 0 ustar 00root root 0000000 0000000 #version 450
layout(binding = 0) uniform sampler2D input_rgb;
layout(binding = 1, r8) writeonly uniform imageBuffer output_y;
layout(binding = 2, r8) writeonly uniform imageBuffer output_u;
layout(binding = 3, r8) writeonly uniform imageBuffer output_v;
layout(push_constant) uniform constants {
mat3x4 rgb_to_yrb;
int stride_y;
int stride_u;
int stride_v;
}
push;
/* Each individual task fills 2x2 pixels. */
/* note: AMD subgroupSize is 64, so 8x8 is needed to fully use it */
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
ivec2 rgbdim = textureSize(input_rgb, 0);
vec4 avg = vec4(0.);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
ivec2 pos = ivec2(2 * gl_GlobalInvocationID.x + i,
2 * gl_GlobalInvocationID.y + j);
vec2 sample_pos = vec2(pos) + 0.5;
vec4 rgbo = vec4(texture(input_rgb, sample_pos).rgb, 1.0);
float y = (transpose(push.rgb_to_yrb) * rgbo).r;
int store_pos = pos.y * push.stride_y + pos.x;
imageStore(output_y, store_pos, vec4(y, 1., 1., 1.));
avg += rgbo;
}
}
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
vec2 sample_pos = vec2(2 * pos + 0.5) + 0.5;
// vec4 rgbo = vec4(texture(input_rgb, sample_pos).rgb, 1.0);
vec4 rgbo = avg / 4;
vec2 vu = (transpose(push.rgb_to_yrb) * rgbo).bg;
int store_pos_v = pos.y * push.stride_v + pos.x;
imageStore(output_v, store_pos_v, vec4(vu.g, 1., 1., 1.));
int store_pos_u = pos.y * push.stride_u + pos.x;
imageStore(output_u, store_pos_u, vec4(vu.r, 1., 1., 1.));
}
waypipe-v0.10.5/shaders/src/ 0000775 0000000 0000000 00000000000 15070717111 0015661 5 ustar 00root root 0000000 0000000 waypipe-v0.10.5/shaders/src/lib.rs 0000664 0000000 0000000 00000000063 15070717111 0016774 0 ustar 00root root 0000000 0000000 include!(concat!(env!("OUT_DIR"), "/shaders.rs"));
waypipe-v0.10.5/shaders/yuv420_buf_to_rgb.glsl 0000664 0000000 0000000 00000002230 15070717111 0021213 0 ustar 00root root 0000000 0000000 #version 450
layout(binding = 0, rgba8) uniform writeonly image2D output_img;
layout(binding = 1) uniform textureBuffer input_y;
layout(binding = 2) uniform textureBuffer input_u;
layout(binding = 3) uniform textureBuffer input_v;
layout(push_constant) uniform constants {
mat3x4 ybr_to_rgb;
int stride_y;
int stride_u;
int stride_v;
}
push;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
void main() {
ivec2 outdim = imageSize(output_img);
/* invocation x/y ranges over all pixels of output */
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
// TODO: any better strategy than doubling U/V coordinates?
int y_pos = pos.y * push.stride_y + pos.x;
int u_pos = (pos.y / 2) * push.stride_u + (pos.x / 2);
int v_pos = (pos.y / 2) * push.stride_v + (pos.x / 2);
float y = texelFetch(input_y, y_pos).r;
float b = texelFetch(input_v, v_pos).r;
float r = texelFetch(input_u, u_pos).r;
vec4 ybro = vec4(y, b, r, 1.0);
vec3 rgb = transpose(push.ybr_to_rgb) * ybro;
vec4 val = vec4(rgb, 1);
ivec2 opos = ivec2(gl_GlobalInvocationID.xy);
if (opos.x < outdim.x && opos.y < outdim.y) {
imageStore(output_img, opos, val);
}
}
waypipe-v0.10.5/src/ 0000775 0000000 0000000 00000000000 15070717111 0014230 5 ustar 00root root 0000000 0000000 waypipe-v0.10.5/src/bench.rs 0000664 0000000 0000000 00000050556 15070717111 0015670 0 ustar 00root root 0000000 0000000 /* SPDX-License-Identifier: GPL-3.0-or-later */
/*! `waypipe bench` implementation */
use crate::compress::*;
use crate::kernel::{apply_diff_one, construct_diff_segment_two};
use crate::util::*;
use crate::Compression;
use crate::Options;
use std::time::Instant;
#[derive(Debug, PartialEq, Eq)]
enum DiffPattern {
On,
IdealOn,
Off,
MemcmpOff,
MinimumOff,
Alternating100, // very short cycle, should be papered over
Alternating1K, // 2kb ~~ 512 pixels
Alternating2K, // 4kb cycle ~ 1024 pixels,
}
fn fill_alternating(rng: &mut BadRng, data: &mut [u8], span_min: usize, span_max: usize) {
let mut i = 0;
let mut change = false;
while i < data.len() {
let jump = span_min + rng.next_usize(1 + span_max - span_min);
let j = std::cmp::min(data.len(), i + jump);
data[i..j].fill(change as u8);
i = j;
change = !change;
}
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[target_feature(enable = "avx2")]
unsafe fn read_replace_write_avx2(src: &[u8], rdwrite: &mut [u8], dst: &mut [u8]) -> u32 {
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
assert!(src.as_ptr() as usize % 64 == 0);
assert!(rdwrite.as_ptr() as usize % 64 == 0);
assert!(dst.as_ptr() as usize % 4 == 0);
assert!(src.len() == rdwrite.len());
assert!(dst.len() >= src.len());
if true {
let ones = _mm256_set1_epi64x(u64::MAX as i64);
const UNROLL: usize = 4;
for k in 0..(src.len() / (32 * UNROLL)) {
// Widely unrolled
let mut xs = [_mm256_undefined_si256(); UNROLL];
let mut ys = [_mm256_undefined_si256(); UNROLL];
for j in 0..UNROLL {
let i = UNROLL * k + j;
xs[j] = _mm256_load_si256(src.as_ptr().add(i * 32) as *const _);
ys[j] = _mm256_load_si256(rdwrite.as_ptr().add(i * 32) as *const _);
}
let diff0 = _mm256_cmpeq_epi32(xs[0], ys[0]);
let diff1 = _mm256_cmpeq_epi32(xs[1], ys[1]);
let diff2 = _mm256_cmpeq_epi32(xs[2], ys[2]);
let diff3 = _mm256_cmpeq_epi32(xs[3], ys[3]);
let sum0 = _mm256_add_epi32(diff0, diff1);
let sum2 = _mm256_add_epi32(diff2, diff3);
let sum = _mm256_add_epi32(sum0, sum2);
if _mm256_testc_si256(sum, ones) != 0 {
// Introduce early exit option to consume reads and inhibit memcpy optimization
panic!();
}
for (j, x) in xs.iter().enumerate().take(UNROLL) {
let i = UNROLL * k + j;
_mm256_store_si256(rdwrite.as_mut_ptr().add(i * 32) as *mut _, *x);
}
for (j, x) in xs.iter().enumerate().take(UNROLL) {
let i = UNROLL * k + j;
_mm256_storeu_si256(dst.as_mut_ptr().add(i * 32) as *mut _, *x);
}
}
}
if false {
let ones = _mm256_set1_epi64x(u64::MAX as i64);
for i in 0..(src.len() / 32) {
let x = _mm256_load_si256(src.as_ptr().add(i * 32) as *const _);
let y = _mm256_load_si256(rdwrite.as_ptr().add(i * 32) as *const _);
let s = _mm256_cmpeq_epi32(x, y);
_mm256_store_si256(rdwrite.as_mut_ptr().add(i * 32) as *mut _, x);
_mm256_storeu_si256(dst.as_mut_ptr().add(i * 32) as *mut _, x);
if i % 4 == 0 && _mm256_testc_si256(s, ones) != 0 {
/* Should never happen; this test should prevent memcpy optimization */
panic!();
}
}
}
if false {
for i in 0..(src.len() / 32) {
let x = _mm256_load_si256(src.as_ptr().add(i * 32) as *const _);
let y = _mm256_load_si256(rdwrite.as_ptr().add(i * 32) as *const _);
let s = _mm256_add_epi32(x, y);
/* Store "s" instead of the correct "x", because otherwise the compiler will
* mis-optimize by extracting a memcpy and increase total memory bandwidth used. */
_mm256_store_si256(rdwrite.as_mut_ptr().add(i * 32) as *mut _, s);
_mm256_storeu_si256(dst.as_mut_ptr().add(i * 32) as *mut _, s);
}
}
src.len() as u32
}
/* Test function: count the number of differences between src1 and rdwrite, and then
* copy src1 to rdwrite and dst2. The performance of this, if properly optimized, should be
* a lower bound on diff construction performance in the "everything changed" scenario. */
fn read_replace_write(src: &[u8], rdwrite: &mut [u8], dst: &mut [u8]) -> u32 {
const CHUNK_SIZE: usize = 256;
let mut any_nondiff = false;
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
if is_x86_feature_detected!("avx2") {
return unsafe { read_replace_write_avx2(src, rdwrite, dst) };
}
for (bsrc, (brdwr, bdst)) in std::iter::zip(
src.chunks_exact(CHUNK_SIZE),
std::iter::zip(
rdwrite.chunks_exact_mut(CHUNK_SIZE),
dst.chunks_exact_mut(CHUNK_SIZE),
),
) {
any_nondiff |= bsrc.cmp(brdwr).is_eq();
brdwr.copy_from_slice(bsrc);
bdst.copy_from_slice(bsrc);
}
any_nondiff as u32
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[target_feature(enable = "avx2")]
unsafe fn read_once_avx2(src: &[u8]) -> u32 {
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
assert!(src.as_ptr() as usize % 64 == 0);
let mut xs = [_mm256_set1_epi8(0); 4];
for i in 0..(src.len() / 128) {
for (j, x) in xs.iter_mut().enumerate() {
let k = 4 * i + j;
let y = _mm256_load_si256(src.as_ptr().add(k * 32) as *const _);
*x = _mm256_max_epi32(*x, y); // max epi32 may be faster than epi8
}
}
let mut nonzero = false;
for x in xs {
let ones = _mm256_set1_epi8(0xff_u8 as i8);
if _mm256_testz_si256(x, ones) != 0 {
nonzero = true;
}
}
nonzero as u32
}
/* Test function: how long does it take to just _read_ the source, and compute something trivial
* (like whether it is all-zero); only run on all 0 input */
fn read_once(src: &[u8]) -> u32 {
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
if is_x86_feature_detected!("avx2") {
return unsafe { read_once_avx2(src) };
}
src.contains(&1) as u32
}
fn estimate_diff_speed(pattern: DiffPattern) {
let length: usize = 1 << 20;
let mut reference_arr = AlignedArray::new(length);
let mut source_arr = AlignedArray::new(length);
let mut baseline_arr = AlignedArray::new(length);
let baseline = baseline_arr.get_mut();
let reference = reference_arr.get_mut();
let source = source_arr.get_mut();
baseline.fill(0);
reference.fill(0);
let mut diff = vec![0; length + 8];
let mut rng = BadRng { state: 0x1 };
match pattern {
DiffPattern::IdealOn | DiffPattern::On => {
/* disagree with baseline everwhere */
source.fill(1);
}
DiffPattern::MemcmpOff | DiffPattern::Off | DiffPattern::MinimumOff => {
/* match baseline everwhere */
source.fill(0);
}
DiffPattern::Alternating100 => {
fill_alternating(&mut rng, &mut source[..], 90, 110);
}
DiffPattern::Alternating1K => {
fill_alternating(&mut rng, &mut source[..], 900, 1100);
}
DiffPattern::Alternating2K => {
fill_alternating(&mut rng, &mut source[..], 1800, 2200);
}
}
let ntrials = 1600;
let mut elapsed_times = Vec::::new();
let mut last_diff_len = None;
for i in 0..ntrials {
/* Design: construct diffs, periodically diffing the reference against the source and baseline patterns */
let test_src: &[u8] = std::hint::black_box(if i % 2 == 0 { source } else { baseline });
let start = Instant::now();
let diff_len: u32 = if pattern == DiffPattern::MemcmpOff {
(test_src.cmp(reference) as i32) as u32
} else if pattern == DiffPattern::MinimumOff {
read_once(test_src)
} else if pattern == DiffPattern::IdealOn {
read_replace_write(test_src, &mut reference[..], &mut diff[..])
} else {
construct_diff_segment_two(&mut diff[..], test_src, &mut reference[..], 0, 32)
};
let end = Instant::now();
if let Some(d) = last_diff_len {
/* Light sanity check: diff length should only depend on the pattern of differences, not on the
* specific contents of the data */
assert!(d == diff_len);
}
elapsed_times.push(end.duration_since(start).as_secs_f64());
last_diff_len = Some(diff_len);
}
let diff_len = last_diff_len.unwrap();
/* Skip the first run (may not be in cache) */
let hot_times = &elapsed_times[1..];
// minor issue: not stable to outliers or numerical issues, there are better algorithms
let mean = hot_times.iter().sum::() / hot_times.len() as f64;
let sample_var = hot_times
.iter()
.map(|x| (*x - mean) * (*x - mean))
.sum::()
/ ((hot_times.len() - 1) as f64);
let min_time = hot_times.iter().fold(f64::INFINITY, |x, y| x.min(*y));
let max_time = hot_times.iter().fold(-f64::INFINITY, |x, y| x.max(*y));
let f: f64 = 1e9 / (length as f64);
println!(
"{:>8?} (diff len={:>8}): {:.4} +/- {:.4} ns/byte, range [{:.4},{:.3}] ns/byte",
pattern,
diff_len,
mean * f,
sample_var.sqrt() * f,
min_time * f,
max_time * f
);
}
fn estimate_diff_compress_speed(
length: usize,
comp: Compression,
text_like: bool,
) -> ((f32, f32), (f32, f32), f32) {
assert!(length % 64 == 0);
let nshards = std::cmp::max(3, (length / 64) / (1 << 12));
let mut src_arr = AlignedArray::new(length);
let mut src_mirror_arr = AlignedArray::new(length);
let mut diff_arr = AlignedArray::new(length + 8 * nshards);
let mut dst_arr = AlignedArray::new(length);
let mut dst_mirror_arr = AlignedArray::new(length);
let src = src_arr.get_mut();
let src_mirror = src_mirror_arr.get_mut();
let diff = diff_arr.get_mut();
let dst = dst_arr.get_mut();
let dst_mirror = dst_mirror_arr.get_mut();
let mut rng = BadRng { state: 1 };
if text_like {
let mut i = 0;
let mut change = false;
while i < length {
let jump = 4096 + rng.next_usize(1 + 4096);
let j = std::cmp::min(length, i + jump);
if change {
for s in &mut src[i..j] {
*s = (0x7f * rng.next_usize(3)) as u8;
}
}
i = j;
change = !change;
}
} else {
let mut k: usize = 0;
for i in 0..(length / 4) {
if i % 1024 == 0 {
k = rng.next_usize(1 << 24);
} else {
k += 4;
}
let noise = rng.next_usize(2);
src[4 * i] = (k + noise) as u8;
src[4 * i + 1] = (k >> 8) as u8;
src[4 * i + 2] = (k >> 16) as u8;
src[4 * i + 3] = 0xff;
}
}
/* Operate on the large region chunk-by-chunk -- this provides crude statistics
* to estimate uncertainty for timing and makes it possible to stop early if
* compression is very slow */
let mut diff_start = 0;
let mut data = Vec::new();
let total_start = Instant::now();
for i in 0..nshards {
let istart =
64 * split_interval(0, (length / 64) as u32, nshards as u32, i as u32) as usize;
let iend =
64 * split_interval(0, (length / 64) as u32, nshards as u32, (i + 1) as u32) as usize;
let start = Instant::now();
let diff_len = construct_diff_segment_two(
&mut diff[diff_start..],
&src[istart..iend],
&mut src_mirror[istart..iend],
istart as u32,
32,
);
let shard_diff = &diff[diff_start..diff_start + diff_len as usize];
let (ndiff, mid, comp_len): (Vec, Instant, usize) = match comp {
Compression::None => {
let x = std::hint::black_box(Vec::from(shard_diff));
(x, Instant::now(), diff_len as usize)
}
Compression::Lz4(lvl) => {
let mut ctx = lz4_make_cctx().unwrap();
let comp =
std::hint::black_box(lz4_compress_to_vec(&mut ctx, shard_diff, lvl, 0, 0));
let t = Instant::now();
(
lz4_decompress_to_vec(&comp, diff_len as usize).unwrap(),
t,
comp.len(),
)
}
Compression::Zstd(lvl) => {
let mut cctx = zstd_make_cctx().unwrap();
let mut dctx = zstd_make_dctx().unwrap();
let comp =
std::hint::black_box(zstd_compress_to_vec(&mut cctx, shard_diff, lvl, 0, 0));
let t = Instant::now();
(
zstd_decompress_to_vec(&mut dctx, &comp, diff_len as usize).unwrap(),
t,
comp.len(),
)
}
};
apply_diff_one(&ndiff, 0, 0, dst).unwrap();
apply_diff_one(&ndiff, 0, 0, dst_mirror).unwrap();
diff_start += diff_len as usize;
let end = Instant::now();
let time_diff = mid.duration_since(start).as_secs_f32();
let time_apply = end.duration_since(mid).as_secs_f32();
data.push((time_diff, time_apply, iend - istart, comp_len));
/* If replicating the buffer takes a long time, then stop; cache
* effects will be negligible compared to compression/decompression time */
if end.duration_since(total_start).as_secs_f32() >= 1.0 && data.len() >= 3 {
break;
}
}
let copy_end =
64 * split_interval(0, (length / 64) as u32, nshards as u32, data.len() as u32) as usize;
std::hint::black_box(dst);
assert!(std::hint::black_box(dst_mirror)[..copy_end] == src[..copy_end]);
let mut comp_len = 0;
let mut proc_len = 0;
let mut speeds_diff: Vec = Vec::new();
let mut speeds_apply: Vec = Vec::new();
for (time_diff, time_apply, input_len, output_len) in data.iter() {
proc_len += input_len;
comp_len += output_len;
/* The shards are almost equal in length */
speeds_diff.push((*input_len as f32) / time_diff);
speeds_apply.push((*input_len as f32) / time_apply);
}
let ratio = (comp_len as f32) / (proc_len as f32);
let n = data.len();
let diff_speed: f32 = speeds_diff.iter().sum::() / (n as f32);
let diff_sstdev2: f32 = speeds_diff
.iter()
.map(|x| (x - diff_speed) * (x - diff_speed))
.sum::()
/ ((n - 1) as f32);
let apply_speed: f32 = speeds_apply.iter().sum::() / (n as f32);
let apply_sstdev2: f32 = speeds_apply
.iter()
.map(|x| (x - diff_speed) * (x - diff_speed))
.sum::()
/ ((n - 1) as f32);
(
(diff_speed, diff_sstdev2.sqrt()),
(apply_speed, apply_sstdev2.sqrt()),
ratio,
)
}
fn run_diff_speed_benchmark() {
println!("Diff pattern speed for 2^20 bytes, using sample stdev");
estimate_diff_speed(DiffPattern::On);
/* NOTE: these are _not_ perfect benchmarks, and should not be used for comparisons;
* thermal or other throttling makes results after the first run slower. Thus, run 'On' twice. */
estimate_diff_speed(DiffPattern::On);
estimate_diff_speed(DiffPattern::IdealOn);
estimate_diff_speed(DiffPattern::Off);
estimate_diff_speed(DiffPattern::MemcmpOff);
estimate_diff_speed(DiffPattern::MinimumOff);
estimate_diff_speed(DiffPattern::Alternating100);
estimate_diff_speed(DiffPattern::Alternating1K);
estimate_diff_speed(DiffPattern::Alternating2K);
}
pub fn run_benchmark(opts: &Options, fast_mode: bool) -> Result<(), String> {
if opts.debug {
run_diff_speed_benchmark();
}
let mut cvs = Vec::::new();
cvs.push(Compression::None);
if cfg!(feature = "lz4") {
for i in -10..=12 {
cvs.push(Compression::Lz4(i));
}
} else {
println!("Waypipe was not built with lz4 compression/decompression support, skipping measurements with lz4");
}
if cfg!(feature = "zstd") {
for i in -10..=22 {
cvs.push(Compression::Zstd(i));
}
} else {
println!("Waypipe was not built with zstd compression/decompression support, skipping measurements with zstd");
}
let mut text_results = Vec::new();
let mut img_results = Vec::new();
/* A long test length is useful for realism (to avoid having *all data fit into cache), but makes
* the test slower to run, so no repetitions will be done. */
let test_size = if fast_mode { 1 << 16 } else { 1 << 22 };
println!("Measured (diff+compress,decompress+apply) speeds and compression ratios");
println!("(single-threaded, unpipelined, quite artificial, single measurement)");
for c in cvs.iter() {
let (textspeed_diff, textspeed_apply, textratio) =
estimate_diff_compress_speed(test_size, *c, true);
let (imgspeed_diff, imgspeed_apply, imgratio) =
estimate_diff_compress_speed(test_size, *c, false);
let max_pad = &[' '; 8];
let padding = max_pad[..8 - c.to_string().len()]
.iter()
.collect::();
println!(
"{}:{} text-like ({:.2e}±{:.1}%,{:.2e}±{:.1}%) bytes/sec, ratio {:.3} image-like ({:.2e}±{:.1}%,{:.2e}±{:.1}%) bytes/sec, ratio {:.3}",
c, padding, textspeed_diff.0, textspeed_diff.1 / textspeed_diff.0,
textspeed_apply.0, textspeed_apply.1 / textspeed_apply.0, textratio,
imgspeed_diff.0, imgspeed_diff.1 / imgspeed_diff.0, imgspeed_apply.0,
imgspeed_apply.1 / imgspeed_apply.0, imgratio
);
text_results.push((textspeed_diff.0, textspeed_apply.0, textratio));
img_results.push((imgspeed_diff.0, imgspeed_apply.0, imgratio));
}
let nthreads = if opts.threads == 0 {
std::cmp::max(1, std::thread::available_parallelism().unwrap().get() / 2)
} else {
opts.threads as usize
};
println!(
"With {} threads, estimated time for a 32 MB (4k) image transfer, assuming:",
nthreads
);
println!("- perfect utilization and pipelining; no buffering, transfer latency or jitter");
println!("- equally fast local and remote computers");
let mbps_opts = [
1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0,
20000.0,
];
let test_size = (1 << 25) as f32;
for (typ, results) in &[("text-like", &text_results), ("image-like", &img_results)] {
for m in mbps_opts {
let bandwidth = m * 1e6;
/* optimal choice: */
let mut best = Compression::None;
let mut best_time = f32::INFINITY;
for (c, (speed_diff, speed_apply, ratio)) in cvs.iter().zip(results.iter()) {
let full_speed_diff = speed_diff * (nthreads as f32);
let full_speed_apply = speed_apply * (nthreads as f32);
let transfer_speed = bandwidth / ratio;
let processing_speed = transfer_speed.min(full_speed_apply).min(full_speed_diff);
let test_time = test_size / processing_speed;
let test_time_unpipelined = test_size / full_speed_diff
+ test_size / transfer_speed
+ test_size / full_speed_apply;
if opts.debug {
println!(
"comp={}, bandwidth={:e} bytes/sec: estimated {} msec (unpipelined: {} msec)",
c,
bandwidth,
1e3 * test_time,
1e3 * test_time_unpipelined
);
}
if test_time < best_time {
best_time = test_time;
best = *c;
}
}
println!(
"bandwidth={:e} bytes/sec, {} suggested comp={} with: estimated {} msec",
bandwidth,
typ,
best,
1e3 * best_time
);
}
}
Ok(())
}
waypipe-v0.10.5/src/compress.rs 0000664 0000000 0000000 00000031300 15070717111 0016426 0 ustar 00root root 0000000 0000000 /* SPDX-License-Identifier: GPL-3.0-or-later */
/*! Safe LZ4 and ZSTD compression wrappers */
use core::ffi::{c_char, c_void};
#[cfg(feature = "lz4")]
use waypipe_lz4_wrapper::*;
#[cfg(feature = "zstd")]
use waypipe_zstd_wrapper::*;
pub struct LZ4CCtx {
#[cfg(feature = "lz4")]
state: *mut u8,
}
pub struct ZstdCCtx {
#[cfg(feature = "zstd")]
ctx: *mut ZSTD_CCtx,
}
pub struct ZstdDCtx {
#[cfg(feature = "zstd")]
ctx: *mut ZSTD_DCtx,
}
#[cfg(feature = "zstd")]
pub fn zstd_make_cctx() -> Option {
unsafe {
// SAFETY: ZSTD_createCCtx is thread-safe
let x = ZSTD_createCCtx();
if x.is_null() {
return None;
}
Some(ZstdCCtx { ctx: x })
}
}
#[cfg(not(feature = "zstd"))]
pub fn zstd_make_cctx() -> Option {
unreachable!();
}
#[cfg(feature = "zstd")]
pub fn zstd_make_dctx() -> Option {
unsafe {
// SAFETY: ZSTD_createDCtx is thread-safe
let x = ZSTD_createDCtx();
if x.is_null() {
return None;
}
Some(ZstdDCtx { ctx: x })
}
}
#[cfg(not(feature = "zstd"))]
pub fn zstd_make_dctx() -> Option {
unreachable!();
}
#[cfg(feature = "zstd")]
impl Drop for ZstdCCtx {
fn drop(&mut self) {
unsafe {
// SAFETY: ZSTD_freeCCtx is thread-safe, operates
// on non-null pointer made by ZSTD_createCCtx
ZSTD_freeCCtx(self.ctx);
}
}
}
#[cfg(feature = "zstd")]
impl Drop for ZstdDCtx {
fn drop(&mut self) {
unsafe {
// SAFETY: ZSTD_freeDCtx is thread-safe, operates
// on non-null pointer made by ZSTD_createDCtx
ZSTD_freeDCtx(self.ctx);
}
}
}
#[cfg(feature = "lz4")]
pub fn lz4_make_cctx() -> Option {
unsafe {
let sz = std::cmp::max(LZ4_sizeofState(), LZ4_sizeofStateHC()) as usize;
assert!(sz > 0);
// LZ4_compress_extState and LZ4_compress_HC_extStateHC
// require that layout is 8-aligned
let layout = std::alloc::Layout::from_size_align(sz, 8).unwrap();
// SAFETY: layout size is verified to be > 0
let data = std::alloc::alloc(layout);
if data.is_null() {
return None;
}
Some(LZ4CCtx { state: data })
}
}
#[cfg(not(feature = "lz4"))]
pub fn lz4_make_cctx() -> Option {
unreachable!();
}
#[cfg(feature = "lz4")]
impl Drop for LZ4CCtx {
fn drop(&mut self) {
unsafe {
let sz = std::cmp::max(LZ4_sizeofState(), LZ4_sizeofStateHC()) as usize;
let layout = std::alloc::Layout::from_size_align(sz, 8).unwrap();
// SAFETY: self.state only set in lz4_make_cctx, which uses the same layout
// because LZ4_sizeofState / LZ4_sizeofStateHC always return same result
std::alloc::dealloc(self.state, layout);
}
}
}
/* Create a vector containing the compressed input, preceded by pad_pre zeros, and followed by pad_post zeros */
// typically used with pad_pre = 16, pad_post = 4, with Vec::truncate called after (which does not reallocate)
#[cfg(feature = "zstd")]
pub fn zstd_compress_to_vec(
ctx: &mut ZstdCCtx,
input: &[u8],
level: i8,
pad_pre: usize,
pad_post: usize,
) -> Vec {
let mut v = Vec::new();
unsafe {
let max_space: usize = ZSTD_compressBound(input.len());
// Compute required space used without overflow
let req_space = max_space
.checked_add(pad_pre)
.unwrap()
.checked_add(pad_post)
.unwrap();
assert!(req_space <= isize::MAX as usize);
v.reserve_exact(req_space);
// SAFETY: function checks inputs for validity, ctx.ctx is non-null from ZstdCCtx construction
let ret = ZSTD_CCtx_setParameter(
ctx.ctx,
ZSTD_cParameter_ZSTD_c_compressionLevel,
level as i32,
);
assert!(
ZSTD_isError(ret) == 0,
"Failed to set Zstd CCtx compression level"
);
let dst: *mut u8 = v.as_mut_ptr();
// SAFETY: v has reserved reserve_exact > pad_pre bytes, has aligned plain data contents
std::ptr::write_bytes(dst, 0, pad_pre);
// SAFETY: ctx.ctx is not null; ZSTD_compress2 should never write outside dst[..max_space],
// and pad_pre + max_space is <= req_space so all input regions are allocated
let sz = ZSTD_compress2(
ctx.ctx,
dst.add(pad_pre) as *mut c_void,
max_space,
input.as_ptr() as *const c_void,
input.len(),
);
assert!(ZSTD_isError(sz) == 0, "Failed to compress with Zstd");
assert!(sz <= max_space);
// SAFETY: dst has aligned plain data contents, and written interval is in range
// // (because pad_pre + sz + pad_post <= pad_pre + max_space + pad_post = req_space)
std::ptr::write_bytes(dst.add(pad_pre + sz), 0, pad_post);
// SAFETY: ZSTD_compress2 wrote as many bytes as its return value indicated
v.set_len(sz + pad_pre + pad_post);
}
v
}
#[cfg(not(feature = "zstd"))]
pub fn zstd_compress_to_vec(
ctx: &mut ZstdCCtx,
input: &[u8],
level: i8,
pad_pre: usize,
pad_post: usize,
) -> Vec {
unreachable!();
}
/* Returns None if the input does not decompress to exactly uncomp_len, or if input/output is too large */
#[cfg(feature = "zstd")]
pub fn zstd_decompress_to_vec(
ctx: &mut ZstdDCtx,
input: &[u8],
uncomp_len: usize,
) -> Option> {
let mut v = Vec::new();
unsafe {
// SAFETY: iff ZSTD_decompressDCtx succeeds, all of dst will be overwritten. v.reserve_exact
// ensures `uncomp_len` bytes are available in v, and ZSTD_decompressDCtx should not read or
// write outside these bounds, or read outside the input. There is no alignment requirement
v.reserve_exact(uncomp_len);
let ndecomp = ZSTD_decompressDCtx(
ctx.ctx,
v.as_mut_ptr() as *mut c_void,
uncomp_len,
input.as_ptr() as *const c_void,
input.len(),
);
if ndecomp != uncomp_len {
return None;
}
// SAFETY: all of dst[..uncomp_len] has been written to by ZSTD_decompressDCtx
v.set_len(uncomp_len);
}
Some(v)
}
#[cfg(not(feature = "zstd"))]
pub fn zstd_decompress_to_vec(
ctx: &mut ZstdDCtx,
input: &[u8],
uncomp_len: usize,
) -> Option> {
unreachable!();
}
#[cfg(feature = "zstd")]
pub fn zstd_decompress_to_slice(ctx: &mut ZstdDCtx, input: &[u8], dst: &mut [u8]) -> Option<()> {
unsafe {
// SAFETY: iff ZSTD_decompressDCtx succeeds, all of dst will be overwritten; ZSTD_decompressDCtx
// should never write outside `dst` vector allocated by v, or read outside the input. There is
// no alignment requirement
let ndecomp = ZSTD_decompressDCtx(
ctx.ctx,
dst.as_mut_ptr() as *mut c_void,
dst.len(),
input.as_ptr() as *const c_void,
input.len(),
);
if ndecomp != dst.len() {
return None;
}
}
Some(())
}
#[cfg(not(feature = "zstd"))]
pub fn zstd_decompress_to_slice(ctx: &mut ZstdDCtx, input: &[u8], dst: &mut [u8]) -> Option<()> {
unreachable!();
}
#[cfg(feature = "lz4")]
pub fn lz4_compress_to_vec(
ctx: &mut LZ4CCtx,
input: &[u8],
level: i8,
pad_pre: usize,
pad_post: usize,
) -> Vec {
let mut v = Vec::new();
unsafe {
let max_space: i32 = LZ4_compressBound(input.len().try_into().unwrap());
let req_space = TryInto::::try_into(max_space)
.unwrap()
.checked_add(pad_pre)
.unwrap()
.checked_add(pad_post)
.unwrap();
assert!(req_space < isize::MAX as usize);
v.reserve_exact(req_space as usize);
let dst: *mut u8 = v.as_mut_ptr();
// SAFETY: the req_space >= pad_pre bytes written here been allocated;
// dst is aligned and contents valid as data is u8
std::ptr::write_bytes(dst, 0, pad_pre);
// SAFETY: Same in both cases. ctx.state is not null, is 8-aligned, and was made at
// least as large as required for both LZ4/LZ4HC. The LZ4_compress functions do
// not write outside their provided intervals, and dst[pad_pre..pad_pre+max_space]
// is contained in dst[..req_space] so all output regions are allocated and pointer
// calculations are in bounds
let sz: i32 = if level <= 0 {
// todo: currently input values <= 1 are replaced with 1, so level=0,level=1 are equivalent
// waypipe-c has the same behavior
LZ4_compress_fast_extState(
ctx.state as *mut c_void,
input.as_ptr() as *const c_char,
dst.add(pad_pre) as *mut c_char,
input.len().try_into().unwrap(),
max_space,
-(level as i32),
)
} else {
LZ4_compress_HC_extStateHC(
ctx.state as *mut c_void,
input.as_ptr() as *const c_char,
dst.add(pad_pre) as *mut c_char,
input.len().try_into().unwrap(),
max_space,
level as i32,
)
};
assert!(sz >= 0 && sz <= max_space, "Failed to compress with LZ4");
let usz = sz as usize;
// SAFETY: the region up to pad_pre + usz + pad_post has been allocated
// dst is aligned and contents valid as data is u8
std::ptr::write_bytes(dst.add(pad_pre + usz), 0, pad_post);
// SAFETY: usz + pad_pre + pad_post < req_space, and the write_bytes/LZ4_compress
// functions have written to every byte
v.set_len(usz + pad_pre + pad_post);
}
v
}
#[cfg(not(feature = "lz4"))]
pub fn lz4_compress_to_vec(
ctx: &mut LZ4CCtx,
input: &[u8],
level: i8,
pad_pre: usize,
pad_post: usize,
) -> Vec {
unreachable!();
}
#[cfg(feature = "lz4")]
pub fn lz4_decompress_to_vec(input: &[u8], uncomp_len: usize) -> Option> {
let mut v = Vec::new();
let ilen: i32 = input.len().try_into().ok()?;
let olen: i32 = uncomp_len.try_into().ok()?;
unsafe {
// SAFETY: iff LZ4_decompress_safe succeeds, all of dst will be overwritten; LZ4_decompress_safe
// should never write outside `dst` vector allocated by v, or read outside the input. There is
// no alignment requirement. The reserved space `uncomp_len` equals `olen` as overflow was checked.
v.reserve_exact(uncomp_len);
let ndecomp = LZ4_decompress_safe(
input.as_ptr() as *const c_char,
v.as_mut_ptr() as *mut c_char,
ilen,
olen,
);
if ndecomp != olen {
return None;
}
// SAFETY: all of dst[..uncomp_len] has been written to by LZ4_decompress_safe
v.set_len(uncomp_len);
}
Some(v)
}
#[cfg(not(feature = "lz4"))]
pub fn lz4_decompress_to_vec(input: &[u8], uncomp_len: usize) -> Option> {
unreachable!();
}
#[cfg(feature = "lz4")]
pub fn lz4_decompress_to_slice(input: &[u8], dst: &mut [u8]) -> Option<()> {
let ilen: i32 = input.len().try_into().ok()?;
let olen: i32 = dst.len().try_into().ok()?;
unsafe {
// SAFETY: iff LZ4_decompress_safe succeeds, all of dst will be overwritten; LZ4_decompress_safe
// should never operate outside its input/output regions. There is no alignment requirement.
// The reserved space `uncomp_len` equals `olen` as overflow was checked.
let ndecomp = LZ4_decompress_safe(
input.as_ptr() as *const c_char,
dst.as_mut_ptr() as *mut c_char,
ilen,
olen,
);
if ndecomp != olen {
return None;
}
}
Some(())
}
#[cfg(not(feature = "lz4"))]
pub fn lz4_decompress_to_slice(input: &[u8], dst: &mut [u8]) -> Option<()> {
unreachable!();
}
#[cfg(feature = "zstd")]
#[test]
fn test_zstd_compression() {
let mut x: Vec = vec![0; 1000];
for (i, v) in x.iter_mut().enumerate() {
*v = ((11 * i) % 256) as u8;
}
let mut c = zstd_make_cctx().unwrap();
let w = zstd_compress_to_vec(&mut c, &x[..], 0, 16, 4);
let mut d = zstd_make_dctx().unwrap();
let y = zstd_decompress_to_vec(&mut d, &w[16..w.len() - 4], x.len()).unwrap();
assert_eq!(x, y);
}
#[cfg(feature = "lz4")]
#[test]
fn test_lz4_compression() {
let mut x: Vec = vec![0; 1000];
for (i, v) in x.iter_mut().enumerate() {
*v = ((11 * i) % 256) as u8;
}
let mut c = lz4_make_cctx().unwrap();
let w = lz4_compress_to_vec(&mut c, &x[..], 0, 16, 4);
let y = lz4_decompress_to_vec(&w[16..w.len() - 4], x.len()).unwrap();
assert_eq!(x, y);
}
waypipe-v0.10.5/src/damage.rs 0000664 0000000 0000000 00000036446 15070717111 0016031 0 ustar 00root root 0000000 0000000 /* SPDX-License-Identifier: GPL-3.0-or-later */
/*! Damage merging logic */
use log::debug;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
/* Note: (the use of u32 x1/x2 instead of i32 x+width ensures sign and overflow checks need
* be done only once.) */
#[derive(Debug, Copy, Clone)]
pub struct Rect {
pub x1: u32,
pub x2: u32,
pub y1: u32,
pub y2: u32,
}
/* Note: this _saturates_ on overflow, and assumes a well-formed rectangle with x1 (usize, usize) {
let start = offset
.saturating_add((r.y1 as usize).saturating_mul(stride))
.saturating_add((r.x1 as usize).saturating_mul(bpp));
let end = offset
.saturating_add((r.y2 as usize).saturating_mul(stride))
.saturating_add((r.x2 as usize).saturating_mul(bpp));
(start, end)
}
fn align_down(x: usize, align_bits: u32) -> usize {
(x >> align_bits) << align_bits
}
fn align_up(x: usize, align_bits: u32) -> usize {
x.checked_next_multiple_of(1_usize << align_bits).unwrap()
}
// todo: handling overflow? Cannot align max_int - 1; better to error?
fn aligned_bounding_interval(
r: &Rect,
offset: usize,
stride: usize,
bpp: usize,
align_bits: u32,
) -> (usize, usize) {
let x = bounding_interval(r, offset, stride, bpp);
(align_down(x.0, align_bits), align_up(x.1, align_bits))
}
/* Requires: All rectangles, after projection, will fit inside the interval given by bound */
fn process_group(
rects: &[Rect],
bound: (usize, usize),
output: &mut Vec<(usize, usize)>,
align_bits: u32,
min_gap: usize,
offset: usize,
stride: usize,
bpp: usize,
) {
// TODO: implement a pre-pass that computes a disjoint collection of rectangles (e.g.: using a sweep
// line algorithm plus interval tree); this would be far more efficient than the current solution, which
// tends to compute almost the same union once per horizontal line. The fact that the output space is
// almost a cylinder is not actually important -- it at most introduces one seam per horizontal line,
// which is a minor cost. min_gap can be handled by horizontally expanding the rectangles beforehand;
// it is permissible to erase gaps slightly larger than min_gap.
/* A heap of indices into the rectangle, using lex sorted key to track start position and rect index */
let mut rect_heap: BinaryHeap<(Reverse, usize)> = BinaryHeap::new();
rect_heap.reserve_exact(rects.len());
let mut row_counters: Vec = vec![0; rects.len()];
let mut work_estimate: usize = 0; // if this grows too large relative to bound.1-bound.0, fall back to dumb strategy.
for (i, r) in rects.iter().enumerate() {
if (r.x2 - r.x1) as usize * bpp > stride.saturating_sub(min_gap) {
/* All segments from this rectangle will be merged; this is a common case, so optimize it */
row_counters[i] = usize::MAX;
}
// TODO: special case optimization to merge entire rectangle into contiguous segment if gaps are small;
// not _strictly_ necessary, but good for perf
let start_pos = align_down(
offset + (r.y1 as usize) * stride + (r.x1 as usize) * bpp,
align_bits,
);
rect_heap.push((Reverse(start_pos), i));
}
let mut cur: Option<(usize, usize)> = None;
while let Some((Reverse(start), i)) = rect_heap.pop() {
/* Process next segment */
let rect = &rects[i];
let merge_opt = row_counters[i] == usize::MAX;
let end = if merge_opt {
align_up(
offset + (rect.y2 - 1) as usize * stride + (rect.x2 as usize) * bpp,
align_bits,
)
} else {
align_up(
offset + (rect.y1 as usize + row_counters[i]) * stride + (rect.x2 as usize) * bpp,
align_bits,
)
};
if let Some(cv) = cur {
if start <= cv.1 || (start - cv.1) < min_gap {
/* either approximate containment or overlap */
cur = Some((cv.0, std::cmp::max(cv.1, end)));
} else {
output.push(cv);
cur = Some((start, end));
}
} else {
cur = Some((start, end));
}
if !merge_opt {
/* Update row counter and return rectangle if not done */
row_counters[i] += 1;
if row_counters[i] < (rect.y2 - rect.y1) as usize {
let start_pos = align_down(
offset
+ (rect.y1 as usize + row_counters[i]) * stride
+ (rect.x1 as usize) * bpp,
align_bits,
);
rect_heap.push((Reverse(start_pos), i));
}
}
/* Do not spend much more time computing damage regions than it would
* take to just scan the entire interval for differences. This doesn't
* need to be a _great_ estimate, just within a few orders of magnitude
* to avoid pathological behavior */
work_estimate += std::cmp::max(16, rect_heap.len()).ilog2() as usize;
if work_estimate > (bound.1 - bound.0) / 8 {
debug!(
"Stopped processing block after estimated {} work; length {}",
work_estimate,
(bound.1 - bound.0)
);
output.push((cur.unwrap().0, bound.1));
return;
}
}
if let Some(cv) = cur {
output.push(cv);
}
}
// todo: eventually add support for multiplanar and subsampled formats?
/**
* Note: all rectangles must be clipped to the wl_buffer bounds, otherwise function may produce nonsense or panic
*
* min_gap: minimum allowed gap on output
* align_bits: e.g. value 6 => output segment positions are multiples of 64
*
* The last interval may be rounded up align(buffer end, 1< Vec<(usize, usize)> {
if rects.is_empty() {
return Vec::new();
}
assert!(stride > 0);
assert!(bpp > 0);
let mut output = Vec::new();
for r in rects.iter() {
assert!(r.x1 < r.x2 && r.y1 < r.y2);
}
rects.sort_unstable_by_key(|rect: &Rect| -> usize {
bounding_interval(rect, offset, stride, bpp).0
});
struct Group {
i_start: usize,
i_end: usize,
/* The aligned region covered by the corresponding rectangles */
region: (usize, usize),
}
/* First: group intervals into overlapping clumps separated by >= min_gap, post alignment.
* */
let mut spans: Vec = Vec::new();
let mut rect_iter = rects.iter().enumerate();
let mut current = Group {
i_start: 0,
i_end: 1,
region: aligned_bounding_interval(
rect_iter.next().unwrap().1,
offset,
stride,
bpp,
align_bits,
),
};
for (i, rect) in rect_iter {
let b = aligned_bounding_interval(rect, offset, stride, bpp, align_bits);
if b.0 <= current.region.1 || (b.0 - current.region.1) < min_gap {
current = Group {
i_start: current.i_start,
i_end: i + 1,
region: (current.region.0, std::cmp::max(current.region.1, b.1)),
}
} else {
spans.push(current);
current = Group {
i_start: i,
i_end: i + 1,
region: b,
}
}
}
spans.push(current);
/* Next: process each span (or if it isn't worth the time, complete it) */
for group in spans {
process_group(
&rects[group.i_start..group.i_end],
group.region,
&mut output,
align_bits,
min_gap,
offset,
stride,
bpp,
);
}
output
}
/* Given two sorted lists of disjoint intervals, compute their union, automatically closing any
* gaps of size Vec<(usize, usize)> {
assert!(validate_output(a, 0, min_gap).is_ok());
assert!(validate_output(b, 0, min_gap).is_ok());
let mut output = Vec::new();
let mut iter_a = a.iter().peekable();
let mut iter_b = b.iter().peekable();
let mut last: Option<(usize, usize)> = None;
loop {
// Extract element with next earliest endpoint from either of A or B
let pa = iter_a.peek();
let pb = iter_b.peek();
let nxt = *match (pa, pb) {
(Some(ea), Some(eb)) => {
if ea.0 <= eb.0 {
iter_a.next().unwrap()
} else {
iter_b.next().unwrap()
}
}
(Some(_), None) => iter_a.next().unwrap(),
(None, Some(_)) => iter_b.next().unwrap(),
(None, None) => {
break;
}
};
let Some(mut y) = last else {
last = Some(nxt);
continue;
};
// Merge intervals or push old
if nxt.0 <= y.1 || (nxt.0 - y.1) < min_gap {
y.1 = std::cmp::max(y.1, nxt.1);
last = Some(y);
} else {
output.push(y);
last = Some(nxt);
}
}
if let Some(e) = last {
output.push(e);
}
output
}
fn validate_output(a: &[(usize, usize)], align_bits: u32, min_gap: usize) -> Result<(), String> {
for (x, y) in a {
if x >= y {
return Err(format!("negative or empty interval {} {}", x, y));
}
let mask = (1_usize << align_bits) - 1;
if x & mask != 0 || y & mask != 0 {
return Err(format!("misaligned {} {}", x, y));
}
}
for i in 1..a.len() {
if a[i].0 < a[i - 1].1 {
return Err(format!("overlapping {:?} {:?}", a[i - 1], a[i]));
}
if a[i].0 < a[i - 1].1 + min_gap {
return Err(format!(
"min gap too small {}-{}={} < {}",
a[i].0,
a[i - 1].1,
a[i].0 - a[i - 1].1,
min_gap
));
}
}
Ok(())
}
#[test]
fn test_union_damage() {
let x: &[(usize, usize)] = &[(0, 6)];
let y: &[(usize, usize)] = &[(8, 10), (14, 20)];
let align_bits = 1;
let max_gap = 4;
assert!(validate_output(x, align_bits, max_gap).is_ok());
assert!(validate_output(y, align_bits, max_gap).is_ok());
let bad1: &[(usize, usize)] = &[(8, 10), (15, 20)];
let bad2: &[(usize, usize)] = &[(8, 10), (12, 20)];
let bad3: &[(usize, usize)] = &[(8, 10), (6, 20)];
assert!(validate_output(bad1, align_bits, max_gap).is_err());
assert!(validate_output(bad2, align_bits, max_gap).is_err());
assert!(validate_output(bad3, align_bits, max_gap).is_err());
let output = union_damage(x, y, max_gap);
println!("output: {:?}", output);
assert_eq!(&output, &[(0, 10), (14, 20)]);
// TODO: test overflow conditions
}
#[test]
fn test_damage_computation() {
{
let w = 100;
let h = 50;
let bpp = 1;
let stride = bpp * w;
let example_pattern = [
Rect {
x1: 0,
x2: 10,
y1: 0,
y2: 10,
},
Rect {
x1: 90,
x2: 100,
y1: 40,
y2: 50,
},
];
let align_bits = 0;
let offset = 0;
let mut tmp = example_pattern;
let slices = compute_damaged_segments(&mut tmp, align_bits, 0, offset, stride, bpp);
assert!(slices.len() == 20);
println!("slices: {:?}", slices);
/* Check that, when min_gap is huge, only one big interval is reported. */
let mut tmp = example_pattern;
let min_gap = usize::MAX;
let slices = compute_damaged_segments(&mut tmp, align_bits, min_gap, offset, stride, bpp);
assert_eq!(slices, &[(0, w * h * bpp)]);
}
fn fill_mask(mask: &mut [bool], w: usize, h: usize, stride: usize, bpp: usize, rects: &[Rect]) {
mask.fill(false);
for r in rects {
assert!(r.x1 < r.x2 && r.x2 <= w as u32, "{:?}", r);
assert!(r.y1 < r.y2 && r.y2 <= h as u32, "{:?}", r);
for y in r.y1..r.y2 {
mask[((y as usize) * stride + (r.x1 as usize) * bpp)
..((y as usize) * stride + (r.x2 as usize) * bpp)]
.fill(true);
}
}
}
fn test_segments(mask: &mut [bool], segments: &[(usize, usize)]) {
for (a, b) in segments {
let b = std::cmp::min(*b, mask.len());
mask[*a..b].fill(false);
}
assert!(mask.iter().all(|x| !*x));
}
let w = 100;
let h = 100;
let bpp = 1;
let stride = 200;
assert!(stride >= w * bpp);
let mut mask = vec![false; h * stride];
for i in 0..100_usize {
/* A variety of test patterns */
let mut rects: Vec = Vec::new();
if i == 0 {
for x in 0..((w / 2) as u32) {
for y in 0..((h / 2) as u32) {
rects.push(Rect {
x1: 2 * x,
x2: 2 * x + 1,
y1: 2 * y,
y2: 2 * y + 1,
});
}
}
} else if i % 4 == 0 {
for j in 0..(i as u32) {
rects.push(Rect {
x1: j,
x2: j + 1,
y1: 0,
y2: (h as u32) - j,
});
rects.push(Rect {
x1: 0,
x2: (w as u32) - j,
y1: j,
y2: j + 1,
});
}
} else if i % 2 == 0 {
for j in 0..(i as u32) {
rects.push(Rect {
x1: j,
x2: j + 2,
y1: j,
y2: j + 2,
});
}
} else {
let (dw, dh, di) = ((w / 2) as u32, (h / 2) as u32, (i / 2) as u32);
for j in 1..di {
rects.push(Rect {
x1: dw - j,
x2: dw + j,
y1: dh - (di - j),
y2: dh + (di - j),
});
}
}
let align_bits = 2;
let min_gap = 1;
fill_mask(&mut mask, w, h, stride, bpp, &rects);
let nset = mask.iter().map(|x| *x as usize).sum::();
let mut tmp = rects;
let slices = compute_damaged_segments(&mut tmp, align_bits, min_gap, 0, stride, bpp);
let ncover = slices.iter().map(|(x, y)| y - x).sum::();
println!(
"test {}, {} rects, {} slices, {} filled, {} covered",
i,
tmp.len(),
slices.len(),
nset,
ncover
);
validate_output(&slices, align_bits, min_gap).unwrap();
test_segments(&mut mask, &slices);
}
}
waypipe-v0.10.5/src/dmabuf.rs 0000664 0000000 0000000 00000415271 15070717111 0016046 0 ustar 00root root 0000000 0000000 /* SPDX-License-Identifier: GPL-3.0-or-later */
/*! Support for DMABUFs and timeline semaphores (using Vulkan) */
#![cfg(feature = "dmabuf")]
use crate::platform::*;
use crate::tag;
use crate::util::*;
#[cfg(feature = "video")]
pub use crate::video::*;
use crate::wayland_gen::*;
use ash::*;
use log::{debug, error};
use nix::{errno, libc, request_code_readwrite};
use std::collections::BTreeMap;
use std::ffi::{c_char, c_int, c_uint, c_void, CStr, CString};
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
use std::path::Path;
use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
use std::sync::{Arc, Mutex, MutexGuard};
/** Properties of a specific format+modifier combination */
#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct ModifierData {
pub plane_count: u32,
pub max_size_transfer: (u32, u32),
pub max_size_store_and_sample: Option<(u32, u32)>,
}
/** A list of modifiers and associated metadata. */
#[derive(Debug)]
pub struct FormatData {
/** The message handling logic generally only needs the list which modifiers
* are available, so store these separately to provide &[u64] access. */
pub modifiers: Vec,
/** A list matching 'modifiers'. */
modifier_data: Vec,
}
/** Structure holding a queue and associated mutable metadata */
pub struct VulkanQueue {
/** Queue object, for which access must be externally synchronized */
pub queue: vk::Queue,
/** The last semaphore value planned to be signalled by a submission to the queue */
pub last_semaphore_value: u64,
}
/** MutexGuard for a VulkanQueue.
*
* Unlocks the ffmpeg lock for the queue when dropped. */
pub struct VulkanQueueGuard<'a> {
pub inner: MutexGuard<'a, VulkanQueue>,
vulk: &'a VulkanDevice,
}
/** A Vulkan entrypoint, instance, and associated information. */
pub struct VulkanInstance {
entry: Entry,
instance: Instance,
physdevs: Vec,
}
/** A Vulkan logical device, with its associated state, main queue and timeline semaphore,
* extensions, and cached properties. */
pub struct VulkanDevice {
_instance: Arc,
dev_info: DeviceInfo,
/** Queue family indices. Order: [compute+transfer, graphics+transfer, encode, decode] */
qfis: [u32; 4],
/** Timeline semaphore; when it reaches 'queue.last_semaphore_value', all preceding work using
* the semaphore is done */
pub semaphore: vk::Semaphore,
/** DRM handle and event_fd exported from [VulkanDevice::semaphore], for easy access from main loop */
semaphore_external: Option,
drm_fd: OwnedFd,
#[cfg(feature = "video")]
pub video: Option,
/** The compute+transfer queue to use. Do NOT access via queue.lock() -- use
* vulkan_lock_queue() instead, to also ensure ffmpeg is locked out of using
* the queue. */
queue: Mutex,
pub dev: Device,
get_modifier: ext::image_drm_format_modifier::Device,
get_mem_reqs2: khr::get_memory_requirements2::Device,
bind_mem2: khr::bind_memory2::Device,
ext_mem_fd: khr::external_memory_fd::Device,
pub timeline_semaphore: khr::timeline_semaphore::Device,
ext_semaphore_fd: khr::external_semaphore_fd::Device,
pub formats: BTreeMap, // todo: the set of possible formats is small and known at compile time; use a table and perfect hashing instead?
device_id: u64,
pub queue_family: u32,
memory_properties: vk::PhysicalDeviceMemoryProperties,
}
pub enum VulkanImageParameterMismatch {
Format,
Modifier,
Size((u32, u32)),
}
/** The associated drm handle/eventfd associated with a timeline semaphore, which can be
* used to wait for updates on it.
*
* [Drop] has not been implemented for this type; it must be destroyed by the containing struct.
*/
struct VulkanExternalTimelineSemaphore {
drm_handle: u32,
event_fd: OwnedFd,
}
/** A Vulkan timeline semaphore and the eventfd used to wait for updates on it */
pub struct VulkanTimelineSemaphore {
pub vulk: Arc,
pub semaphore: vk::Semaphore,
external: VulkanExternalTimelineSemaphore,
}
/** A sync file (e.g.: exported from a DMABUF, for implicit sync) */
pub struct VulkanSyncFile {
vulk: Arc,
fd: OwnedFd,
}
/** A binary semaphore (e.g.: resulting from DMABUF's exported implicit sync file) */
pub struct VulkanBinarySemaphore {
vulk: Arc,
pub semaphore: vk::Semaphore,
}
/** A Vulkan command pool */
pub struct VulkanCommandPool {
pub vulk: Arc,
pub pool: Mutex,
}
/** Mutable state for a [VulkanDmabuf] */
pub struct VulkanDmabufInner {
// TODO: need to store metadata about all pending operations to the dmabuf
pub image_layout: vk::ImageLayout,
}
/** Structure for a Vulkan image imported from/exported to a DMABUF */
pub struct VulkanDmabuf {
// No RefCell -- unsafe is used throughout anyway, exclusivity is not needed, and no recursion should be done
pub vulk: Arc,
pub image: vk::Image,
// todo: store memory, to be able to free it properly when the VulkanDmabuf is dropped?
// also: the file descriptors probably have a separate lifespan; check this
pub width: u32,
pub height: u32,
// note: the drm_format should never be needed after casting to nearest Vulkan approximation
pub vk_format: vk::Format,
/* True iff vkImage was created with storage and sample usage */
pub can_store_and_sample: bool,
// todo: use a <=4 vector size optimization without any heap allocation
memory_planes: Vec<(vk::DeviceMemory, u32, u32)>, /* mem / offset / stride */
/** In order to extract sync files for implicit synchronization, and to poll the implicit
* fences if sync file extraction is not supported, store a copy of the DMABUF fd.
* (This may need to be changed to support disjoint multi-planar images.) */
pub main_fd: OwnedFd,
pub inner: Mutex,
}
/** Data for a [VulkanBuffer] which is mutable or requires exclusive access. */
struct VulkanBufferInner {
data: *mut c_void,
reader_count: usize,
has_writer: bool,
}
/** A mapped staging buffer, either for use when reading or writing data */
pub struct VulkanBuffer {
pub vulk: Arc,
// todo: central handling of vk::Buffer objects, to allow bump-allocating
// segments from a larger central buffer.
pub buffer: vk::Buffer,
mem: vk::DeviceMemory,
pub memory_len: u64,
pub buffer_len: u64,
/* Mutex-wrapped to ensure only one referent can read/write from data at a time */
inner: Mutex,
}
unsafe impl Send for VulkanBuffer {}
unsafe impl Sync for VulkanBuffer {}
/** Handle storing (and keeping alive) command buffer for a transfer between a [VulkanBuffer] and a [VulkanDmabuf] */
pub struct VulkanCopyHandle {
vulk: Arc,
/* Copy operation is between these two objects */
_image: Arc,
_buffer: Arc,
pool: Arc,
// note: not safe to reuse unless image is still alive
// TODO: not safe to free a 'pending' command buffer; give Vulkan itself a list of copy-handles?
cb: vk::CommandBuffer,
// on the queue's timeline semaphore
completion_time_point: u64,
}
impl Drop for VulkanInstance {
fn drop(&mut self) {
unsafe {
self.instance.destroy_instance(None);
}
}
}
impl Drop for VulkanDevice {
fn drop(&mut self) {
unsafe {
#[cfg(feature = "video")]
{
if let Some(ref v) = self.video {
destroy_video(&self.dev, v);
}
/* Drop video, if present */
self.video = None;
}
// These are probably only safe if operations using them have completed; need
// a centralized registry
self.dev.destroy_semaphore(self.semaphore, None);
self.dev.destroy_device(None);
}
}
}
impl Drop for VulkanQueue {
fn drop(&mut self) {}
}
impl Drop for VulkanCommandPool {
fn drop(&mut self) {
unsafe {
let p = self.pool.lock().unwrap();
self.vulk.dev.destroy_command_pool(*p, None);
}
}
}
impl Drop for VulkanDmabuf {
fn drop(&mut self) {
unsafe {
self.vulk.dev.destroy_image(self.image, None);
for (mem, _offset, _stride) in &self.memory_planes {
self.vulk.dev.free_memory(*mem, None);
}
}
// The Arc> should keep Vulkan alive until after VulkanDmabuf is dropped
}
}
impl Drop for VulkanTimelineSemaphore {
fn drop(&mut self) {
unsafe {
drm_syncobj_destroy(&self.vulk.drm_fd, self.external.drm_handle).unwrap();
// SAFETY: only if semaphore is not being used
self.vulk.dev.destroy_semaphore(self.semaphore, None);
// event_fd cleanup is automatic
}
}
}
impl Drop for VulkanBinarySemaphore {
fn drop(&mut self) {
unsafe {
// SAFETY: only if semaphore is not being used
self.vulk.dev.destroy_semaphore(self.semaphore, None);
}
}
}
impl Drop for VulkanBuffer {
fn drop(&mut self) {
unsafe {
assert!(self.inner.lock().unwrap().reader_count == 0);
assert!(!self.inner.lock().unwrap().has_writer);
self.vulk.dev.destroy_buffer(self.buffer, None);
self.vulk.dev.unmap_memory(self.mem);
self.vulk.dev.free_memory(self.mem, None);
}
}
}
impl Drop for VulkanCopyHandle {
fn drop(&mut self) {
let cmd_pool = self.pool.pool.lock().unwrap();
unsafe {
/* Verify that the command buffer execution has completed; if not, panic, as it's a program error */
if let Ok(counter) = self
.vulk
.timeline_semaphore
.get_semaphore_counter_value(self.vulk.semaphore)
{
assert!(
counter >= self.completion_time_point,
"copy handle deleted at {} >!= {}; dropped too early?",
counter,
self.completion_time_point
);
}
self.vulk.dev.free_command_buffers(*cmd_pool, &[self.cb]);
}
}
}
impl std::fmt::Display for VulkanImageParameterMismatch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Format => f.write_str("unsupported format"),
Self::Modifier => f.write_str("unsupported modifier"),
Self::Size(max_size) => f.write_fmt(format_args!(
"provided size is ≰ max size=({},{})",
max_size.0, max_size.1
)),
}
}
}
/** Function to use to lock the main queue; will ensure queue is also locked
* for ffmpeg, if video encoding/decoding is enabled. */
pub fn vulkan_lock_queue(vulk: &VulkanDevice) -> VulkanQueueGuard<'_> {
/* Lock order: vulk.queue before video lock */
let inner = vulk.queue.lock().unwrap();
#[cfg(feature = "video")]
if let Some(ref v) = vulk.video {
unsafe {
video_lock_queue(v, vulk.queue_family);
}
}
VulkanQueueGuard { inner, vulk }
}
impl Drop for VulkanQueueGuard<'_> {
fn drop(&mut self) {
#[cfg(feature = "video")]
if let Some(ref v) = self.vulk.video {
unsafe {
video_unlock_queue(v, self.vulk.queue_family);
}
}
}
}
/** Check whether a given extension is available in the list with the given version. */
fn exts_has_prop(exts: &[vk::ExtensionProperties], name: &CStr, version: u32) -> bool {
exts.iter()
.any(|x| x.extension_name_as_c_str().unwrap() == name && x.spec_version >= version)
}
/** Additional information for Vulkan formats */
pub struct FormatLayoutInfo {
pub bpp: u32,
pub planes: usize,
// TODO: while the number of _memory_ planes can be looked up by modifier
// (e.g., to account for CCS planes), need to track number of logical planes
// (e.g.: vk::ImageAspectFlags::PLANE_0 vs vk::ImageAspectFlags::MEMORY_PLANE_0_EXT)
// todo: subsampling in vulkan requires width/height to be multiples of 2 sometimes;
// would need to bump up canonical size to match
}
// TODO: determine if it is worth it to deduplicate shm and dmabuf format information.
// (the code pathways will probably become very different.)
/** List of Vulkan formats which Waypipe supports.
*
* Channel interpretations _usually_ do not affect processing; given a linear
* layout it shouldn't matter which channel is R and which is B as long as the
* transfer operations (vkCmdCopyImageToBuffer, etc.) preserve the order.
*
* However, the DMABUF layout may depend on the precise (format, modifier) pair and
* so buffers should be imported/exported using the closest matching Vulkan format.
* In particular, DRM_FORMAT_ABGR8888 should use R8G8B8A8_UNORM, and
* DRM_FORMAT_ARGB8888 should use B8G8R8A8_UNORM. It is possible that a driver
* implements both ABGR and ARGB buffers using a fixed ABGR memory layout (using
* the format value to determine whether to swap R and B channels when transferring
* the data to a buffer, instead of just copying raw data as would occur with a naive
* linear layout). As a result, it is _not_ safe in general to import or export
* a DRM format using anything but the exact corresponding Vulkan format. */
const SUPPORTED_FORMAT_LIST: &[vk::Format] = &[
vk::Format::R4G4B4A4_UNORM_PACK16,
vk::Format::B4G4R4A4_UNORM_PACK16,
// vk::Format::A4R4G4B4_UNORM_PACK16_EXT, A4B4G4R4_UNORM_PACK16_EXT require VK_EXT_4444_formats or Vulkan 1.3
vk::Format::R5G6B5_UNORM_PACK16,
vk::Format::B5G6R5_UNORM_PACK16,
// vk::Format::A1B5G5R5_UNORM_PACK16_KHR, // requires VK_KHR_maintenance5 or Vulkan 1.4.
vk::Format::A1R5G5B5_UNORM_PACK16,
vk::Format::B5G5R5A1_UNORM_PACK16,
vk::Format::R5G5B5A1_UNORM_PACK16,
vk::Format::R8_UNORM,
vk::Format::R8G8_UNORM,
vk::Format::R8G8B8_UNORM,
vk::Format::B8G8R8_UNORM,
vk::Format::R8G8B8A8_UNORM,
vk::Format::B8G8R8A8_UNORM,
vk::Format::A2R10G10B10_UNORM_PACK32,
vk::Format::A2B10G10R10_UNORM_PACK32,
vk::Format::R16_UNORM,
vk::Format::R16G16_UNORM,
vk::Format::R16G16B16A16_UNORM,
vk::Format::R16G16B16A16_SFLOAT,
vk::Format::G8_B8_R8_3PLANE_444_UNORM,
];
/** Get properties of a [vk::Format] */
pub fn get_vulkan_info(f: vk::Format) -> FormatLayoutInfo {
match f {
vk::Format::R4G4B4A4_UNORM_PACK16
| vk::Format::B4G4R4A4_UNORM_PACK16
| vk::Format::R5G6B5_UNORM_PACK16
| vk::Format::B5G6R5_UNORM_PACK16
| vk::Format::A1R5G5B5_UNORM_PACK16
| vk::Format::B5G5R5A1_UNORM_PACK16
| vk::Format::R5G5B5A1_UNORM_PACK16 => FormatLayoutInfo { bpp: 2, planes: 1 },
vk::Format::R8_UNORM => FormatLayoutInfo { bpp: 1, planes: 1 },
vk::Format::R8G8_UNORM => FormatLayoutInfo { bpp: 2, planes: 1 },
vk::Format::R8G8B8_UNORM | vk::Format::B8G8R8_UNORM => {
FormatLayoutInfo { bpp: 3, planes: 1 }
}
vk::Format::R8G8B8A8_UNORM | vk::Format::B8G8R8A8_UNORM => {
FormatLayoutInfo { bpp: 4, planes: 1 }
}
vk::Format::A2R10G10B10_UNORM_PACK32 | vk::Format::A2B10G10R10_UNORM_PACK32 => {
FormatLayoutInfo { bpp: 4, planes: 1 }
}
vk::Format::R16_UNORM => FormatLayoutInfo { bpp: 2, planes: 1 },
vk::Format::R16G16_UNORM => FormatLayoutInfo { bpp: 4, planes: 1 },
vk::Format::R16G16B16A16_UNORM => FormatLayoutInfo { bpp: 8, planes: 1 },
vk::Format::R16G16B16A16_SFLOAT => FormatLayoutInfo { bpp: 8, planes: 1 },
vk::Format::G8B8G8R8_422_UNORM => FormatLayoutInfo { bpp: 2, planes: 1 },
vk::Format::G8_B8_R8_3PLANE_420_UNORM => FormatLayoutInfo { bpp: 2, planes: 3 },
vk::Format::G8_B8_R8_3PLANE_422_UNORM => FormatLayoutInfo { bpp: 2, planes: 3 },
vk::Format::G8_B8_R8_3PLANE_444_UNORM => FormatLayoutInfo { bpp: 2, planes: 3 },
vk::Format::G8_B8R8_2PLANE_420_UNORM => FormatLayoutInfo { bpp: 2, planes: 2 },
vk::Format::G8_B8R8_2PLANE_422_UNORM => FormatLayoutInfo { bpp: 2, planes: 2 },
vk::Format::G16_B16R16_2PLANE_420_UNORM => FormatLayoutInfo { bpp: 2, planes: 2 },
vk::Format::G16_B16_R16_3PLANE_444_UNORM => FormatLayoutInfo { bpp: 2, planes: 3 },
_ => unreachable!("Format {:?} should have been implemented", f),
}
}
/** Convert a Wayland fourcc format code to a DRM format code.
*
* Wayland and DRM differ in encodings for Argb8888 and Xrgb8888 only */
#[allow(dead_code)]
#[cfg(any(test, feature = "test_proto"))]
pub const fn wayland_to_drm(wl_format: WlShmFormat) -> u32 {
match wl_format {
WlShmFormat::Argb8888 => fourcc('A', 'R', '2', '4'),
WlShmFormat::Xrgb8888 => fourcc('X', 'R', '2', '4'),
_ => wl_format as u32,
}
}
/** Convert a DRM fourcc format to a canonical Vulkan format with an equivalent layout
* (but possibly different channel names -- those can be either ignored or fixed by swizzling.)
*
* (The other direction is not well defined, because _multiple_ DRM formats may map
* onto a Vulkan format.) */
pub fn drm_to_vulkan(drm_format: u32) -> Option {
use WlShmFormat::*;
if drm_format == 0 || drm_format == 1 {
/* not a DRM format, and clients should not send this for DMABUFs */
return None;
}
/* First, convert to Wayland format */
let shm_format = if let Ok(shm_format) = drm_format.try_into() {
shm_format
} else {
/* Unfortunately wayland uses different values for Argb8888, Xrgb8888 */
if drm_format == fourcc('A', 'R', '2', '4') {
Argb8888
} else if drm_format == fourcc('X', 'R', '2', '4') {
Xrgb8888
} else {
return None;
}
};
// TODO: is it safe to bundle multiple original channels into one? e.g. RGB233 => R8_UNORM
// TODO: UNORM vs interpreting everything as UINT
/* 8-bit RGB, the endianness-independent formats */
match shm_format {
R8 => return Some(vk::Format::R8_UNORM),
Gr88 => return Some(vk::Format::R8G8_UNORM),
Rgb888 => return Some(vk::Format::B8G8R8_UNORM),
Bgr888 => return Some(vk::Format::R8G8B8_UNORM),
Abgr8888 | Xbgr8888 => return Some(vk::Format::R8G8B8A8_UNORM),
Argb8888 | Xrgb8888 => return Some(vk::Format::B8G8R8A8_UNORM),
/* Bgra/Rgba/Ayuv/Xyuv-type have no direct analogue and using
* R8G8B8A8_UNORM/B8G8R8A8_UNORM for either could potentially cause
* channel swaps on import */
_ => (),
}
/* Vulkan physical device endianness matches host endianness, while the Wayland and
* DRM formats are endianness-independent (typically little-endian). To keep things simple,
* on big endian systems, only permit formats with endianness-independent layout. */
if cfg!(not(target_endian = "little")) {
return None;
}
Some(match shm_format {
/* Packed formats */
Rgba4444 | Rgbx4444 => vk::Format::R4G4B4A4_UNORM_PACK16,
Bgra4444 | Bgrx4444 => vk::Format::B4G4R4A4_UNORM_PACK16,
Rgb565 => vk::Format::R5G6B5_UNORM_PACK16,
Bgr565 => vk::Format::B5G6R5_UNORM_PACK16,
Abgr1555 | Xbgr1555 => vk::Format::A1B5G5R5_UNORM_PACK16_KHR,
Argb1555 | Xrgb1555 => vk::Format::A1R5G5B5_UNORM_PACK16,
Bgra5551 | Bgrx5551 => vk::Format::B5G5R5A1_UNORM_PACK16,
Rgba5551 | Rgbx5551 => vk::Format::R5G5B5A1_UNORM_PACK16,
/* 10-bit RGB */
Argb2101010 | Xrgb2101010 => vk::Format::A2R10G10B10_UNORM_PACK32,
Abgr2101010 | Xbgr2101010 => vk::Format::A2B10G10R10_UNORM_PACK32,
/* 16-bit RGB */
R16 => vk::Format::R16_UNORM,
Gr1616 => vk::Format::R16G16_UNORM,
Abgr16161616 | Xbgr16161616 => vk::Format::R16G16B16A16_UNORM,
Abgr16161616f | Xbgr16161616f => vk::Format::R16G16B16A16_SFLOAT,
/* YUV */
Yuyv => vk::Format::G8B8G8R8_422_UNORM,
Uyvy => vk::Format::B8G8R8G8_422_UNORM,
Yuv420 => vk::Format::G8_B8_R8_3PLANE_420_UNORM,
Yuv422 => vk::Format::G8_B8_R8_3PLANE_422_UNORM,
Yuv444 => vk::Format::G8_B8_R8_3PLANE_444_UNORM,
Nv12 => vk::Format::G8_B8R8_2PLANE_420_UNORM,
Nv16 => vk::Format::G8_B8R8_2PLANE_422_UNORM,
P016 => vk::Format::G16_B16R16_2PLANE_420_UNORM,
Q401 => vk::Format::G16_B16_R16_3PLANE_444_UNORM,
_ => return None,
})
}
/* Definitions from drm.h and linux/dma-buf.h */
const DRM_IOCTL_SYNCOBJ_DESTROY: (u32, u8) = ('d' as u32, 0xC0);
const DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE: (u32, u8) = ('d' as u32, 0xC2);
const DRM_IOCTL_SYNCOBJ_EVENTFD: (u32, u8) = ('d' as u32, 0xCF);
const DMABUF_IOCTL_EXPORT_SYNC_FILE: (u32, u8) = ('b' as u32, 0x02);
#[repr(C)]
struct DrmSyncobjDestroy {
handle: u32,
pad: u32,
}
#[repr(C)]
struct DrmSyncobjHandle {
handle: u32,
flags: u32,
fd: i32,
pad: u32,
}
#[repr(C)]
struct DrmSyncobjEventFd {
handle: u32,
flags: u32,
point: u64,
fd: i32,
pad: u32,
}
#[repr(C)]
struct DmabufExportSyncFile {
flags: u32,
fd: i32,
}
const DMA_BUF_SYNC_READ: u32 = 1 << 0;
/** Requirements: for the specific ioctl used, arg must be properly
* aligned, have the right type, and have the correct lifespan. */
unsafe fn ioctl_loop(
drm_fd: &OwnedFd,
typ: u32,
code: u8,
arg: *mut T,
about: &str,
) -> Result<(), String> {
loop {
// Note: Platforms vary in the signedness of the argument type passed
// to libc, and some old big-endian platforms have a different ioctl code format
let ret = libc::ioctl(
drm_fd.as_raw_fd(),
request_code_readwrite!(typ, code, std::mem::size_of::()),
arg as *mut c_void,
);
let errno = errno::Errno::last_raw();
if ret == 0 {
return Ok(());
} else if (errno == errno::Errno::EINTR as i32) || (errno == errno::Errno::EAGAIN as i32) {
continue;
} else {
return Err(tag!("ioctl {:x} ({}) failed: {}", code, about, errno));
}
}
}
/** Link a drm syncobj handle and time point to an eventfd */
fn drm_syncobj_eventfd(
drm_fd: &OwnedFd,
event_fd: &OwnedFd,
handle: u32,
point: u64,
) -> Result<(), String> {
let mut x = DrmSyncobjEventFd {
handle,
flags: 0, // or: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
point,
fd: event_fd.as_raw_fd(),
pad: 0,
};
unsafe {
// SAFETY: x is repr(C), x has proper type for the ioctl,
// and the ioctl does not use the pointer after the call
ioctl_loop::(
drm_fd,
DRM_IOCTL_SYNCOBJ_EVENTFD.0,
DRM_IOCTL_SYNCOBJ_EVENTFD.1,
&mut x,
"eventfd",
)
}
}
/** Convert a DRM syncobj fd to a handle */
fn drm_syncobj_fd_to_handle(drm_fd: &OwnedFd, syncobj_fd: &OwnedFd) -> Result {
let mut x = DrmSyncobjHandle {
handle: 0,
flags: 0,
fd: syncobj_fd.as_raw_fd(),
pad: 0,
};
unsafe {
// SAFETY: x is repr(C), x has proper type for the ioctl,
// and the ioctl does not use the pointer after the call
ioctl_loop::(
drm_fd,
DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE.0,
DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE.1,
&mut x,
"fd to handle",
)?;
Ok(x.handle)
}
}
/** Destroy a drm syncobj handle.
*
* To get full IO-safety for DRM handles, would need an OwnedDrmHandle
* wrapper. As-is, the caller should only call this on syncobj handles
* it exclusively controls. */
fn drm_syncobj_destroy(drm_fd: &OwnedFd, handle: u32) -> Result<(), String> {
let mut x = DrmSyncobjDestroy { handle, pad: 0 };
unsafe {
// SAFETY: x is repr(C), x has proper type for the ioctl,
// and the ioctl does not use the pointer after the call
ioctl_loop(
drm_fd,
DRM_IOCTL_SYNCOBJ_DESTROY.0,
DRM_IOCTL_SYNCOBJ_DESTROY.1,
&mut x,
"handle destroy",
)
}
}
/** Export the sync file holding read fences associated with the given dmabuf.
*
* Returns Some(fd) is successful, None if operation possibly not supported, Err
* on error.
*/
fn dmabuf_sync_file_export(dmabuf_fd: &OwnedFd) -> Result