From 53d3d5fd320361c2ba0ee1afeed9f64a9ba92e07 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:23:19 +0900 Subject: [PATCH 1/2] feat: ui dev window --- Cargo.lock | 469 ++++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 + src/backend/mod.rs | 3 + src/backend/uidev/mod.rs | 241 ++++++++++++++++++++ src/graphics.rs | 136 ++++++++++++ src/gui/modular/mod.rs | 2 +- src/hid.rs | 9 +- src/main.rs | 11 + src/overlays/keyboard.rs | 2 +- src/state.rs | 3 - 10 files changed, 872 insertions(+), 7 deletions(-) create mode 100644 src/backend/uidev/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 2b00b14..619505e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ab_glyph" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f90148830dac590fac7ccfe78ec4a8ea404c60f75a24e16407a71f0f40de775" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + [[package]] name = "ahash" version = "0.8.11" @@ -45,6 +61,33 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "android-activity" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +dependencies = [ + "android-properties", + "bitflags 2.5.0", + "cc", + "cesu8", + "jni 0.21.1", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -146,6 +189,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -522,6 +583,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" +dependencies = [ + "objc-sys", +] + +[[package]] +name = "block2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +dependencies = [ + "block-sys", + "objc2", +] + [[package]] name = "blocking" version = "1.5.1" @@ -866,6 +946,19 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.1.3" @@ -1112,6 +1205,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "dlib" version = "0.5.2" @@ -1279,6 +1378,18 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1318,6 +1429,33 @@ dependencies = [ "yeslogic-fontconfig-sys", ] +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1461,6 +1599,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + [[package]] name = "getrandom" version = "0.2.14" @@ -1593,6 +1741,17 @@ dependencies = [ "cc", ] +[[package]] +name = "icrate" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +dependencies = [ + "block2", + "dispatch", + "objc2", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1657,6 +1816,26 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "input-linux" version = "0.6.0" @@ -1792,6 +1971,26 @@ dependencies = [ "serde", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1839,6 +2038,17 @@ dependencies = [ "windows-targets 0.52.4", ] +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.5.0", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "libspa" version = "0.8.0" @@ -1993,6 +2203,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "moveit" version = "0.6.0" @@ -2013,6 +2235,7 @@ dependencies = [ "log", "ndk-sys", "num_enum", + "raw-window-handle", "thiserror", ] @@ -2087,6 +2310,23 @@ dependencies = [ "winapi", ] +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.5.0", + "filetime", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -2146,6 +2386,28 @@ dependencies = [ "malloc_buf", ] +[[package]] +name = "objc-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" + +[[package]] +name = "objc2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" + [[package]] name = "oboe" version = "0.6.1" @@ -2197,6 +2459,15 @@ dependencies = [ "libc", ] +[[package]] +name = "orbclient" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" +dependencies = [ + "libredox", +] + [[package]] name = "ordered-multimap" version = "0.6.0" @@ -2243,6 +2514,15 @@ dependencies = [ "normpath", ] +[[package]] +name = "owned_ttf_parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" +dependencies = [ + "ttf-parser", +] + [[package]] name = "parking" version = "2.2.0" @@ -2267,7 +2547,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -2586,6 +2866,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -2745,6 +3034,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sctk-adwaita" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +dependencies = [ + "ab_glyph", + "log", + "memmap2 0.9.4", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "semver" version = "1.0.22" @@ -2928,12 +3230,27 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "smol_str" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +dependencies = [ + "serde", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + [[package]] name = "strsim" version = "0.11.1" @@ -3076,6 +3393,31 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3167,6 +3509,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "ttf-parser" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" + [[package]] name = "typenum" version = "1.17.0" @@ -3464,6 +3812,19 @@ dependencies = [ "wayland-scanner", ] +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-wlr" version = "0.2.0" @@ -3496,6 +3857,7 @@ checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" dependencies = [ "dlib", "log", + "once_cell", "pkg-config", ] @@ -3509,6 +3871,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "which" version = "4.4.2" @@ -3788,6 +4160,54 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +[[package]] +name = "winit" +version = "0.29.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.5.0", + "bytemuck", + "calloop", + "cfg_aliases", + "core-foundation", + "core-graphics", + "cursor-icon", + "icrate", + "js-sys", + "libc", + "log", + "memmap2 0.9.4", + "ndk", + "ndk-sys", + "objc2", + "once_cell", + "orbclient", + "percent-encoding", + "raw-window-handle", + "redox_syscall 0.3.5", + "rustix", + "sctk-adwaita", + "smithay-client-toolkit", + "smol_str", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.48.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + [[package]] name = "winnow" version = "0.5.40" @@ -3841,6 +4261,7 @@ dependencies = [ "json5", "libc", "log", + "notify", "once_cell", "openxr", "ovr_overlay", @@ -3855,10 +4276,43 @@ dependencies = [ "thiserror", "vulkano", "vulkano-shaders", + "winit", "wlx-capture", "xdg", ] +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.8.3", + "once_cell", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" + [[package]] name = "xcb" version = "1.3.0" @@ -3903,6 +4357,19 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.5.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + [[package]] name = "xkeysym" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 910be72..c7099e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,9 @@ thiserror = "1.0.56" vulkano = { git = "https://github.com/vulkano-rs/vulkano", rev = "94f50f1" } vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano", rev = "94f50f1" } wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.8", default-features = false } +winit = { version = "0.29.15", optional = true } xdg = "2.5.2" +notify = { version = "6.1.1", default-features = false, optional = true } [features] default = ["openvr", "openxr", "osc", "x11", "wayland"] @@ -61,3 +63,4 @@ openxr = ["dep:openxr"] osc = ["dep:rosc"] x11 = ["wlx-capture/xshm"] wayland = ["wlx-capture/pipewire", "wlx-capture/wlr"] +uidev = ["dep:notify", "dep:winit"] diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 23d4e3b..9d6a682 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -8,6 +8,9 @@ pub mod openvr; #[cfg(feature = "openxr")] pub mod openxr; +#[cfg(feature = "uidev")] +pub mod uidev; + #[cfg(feature = "osc")] pub mod osc; diff --git a/src/backend/uidev/mod.rs b/src/backend/uidev/mod.rs new file mode 100644 index 0000000..ca0f5bf --- /dev/null +++ b/src/backend/uidev/mod.rs @@ -0,0 +1,241 @@ +use std::sync::Arc; + +use vulkano::{ + command_buffer::CommandBufferUsage, + image::{sampler::Filter, view::ImageView, ImageUsage}, + swapchain::{ + acquire_next_image, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo, + }, + sync::GpuFuture, + Validated, VulkanError, +}; +use winit::{ + dpi::LogicalSize, + event::{Event, WindowEvent}, + event_loop::ControlFlow, + window::Window, +}; + +use crate::{ + config::load_custom_ui, + config_io, + graphics::{DynamicPass, DynamicPipeline, WlxGraphics, BLEND_ALPHA}, + gui::{ + modular::{modular_canvas, ModularData}, + Canvas, + }, + hid::USE_UINPUT, + state::AppState, +}; + +use super::overlay::OverlayRenderer; + +struct PreviewState { + canvas: Canvas<(), ModularData>, + pipeline: Arc, + pass: DynamicPass, + swapchain: Arc, + images: Vec>, +} + +impl PreviewState { + fn new( + state: &mut AppState, + surface: Arc, + window: Arc, + panel_name: &str, + ) -> anyhow::Result { + let config = load_custom_ui(panel_name)?; + let (swapchain, images) = create_swapchain(&state.graphics, surface.clone(), config.size)?; + + let logical_size = LogicalSize::new(config.size[0], config.size[1]); + log::info!("Setting window size to {:?}", logical_size); + let _ = window.request_inner_size(logical_size); + window.set_min_inner_size(Some(logical_size)); + window.set_max_inner_size(Some(logical_size)); + window.set_resizable(false); + window.set_title("WlxOverlay UI Preview"); + + let mut canvas = modular_canvas(&config.size, &config.elements, state)?; + canvas.init(state)?; + canvas.render(state).unwrap(); + let view = canvas.view().unwrap(); + let extent = view.image().extent(); + + let pipeline = { + let shaders = state.graphics.shared_shaders.read().unwrap(); + state.graphics.create_pipeline_dynamic( + shaders.get("vert_common").unwrap().clone(), // want panic + shaders.get("frag_sprite").unwrap().clone(), // want panic + state.graphics.native_format, + Some(BLEND_ALPHA), + ) + }?; + let set0 = pipeline + .uniform_sampler(0, view.clone(), Filter::Linear) + .unwrap(); + + let pass = pipeline + .create_pass( + [extent[0] as f32, extent[1] as f32], + state.graphics.quad_verts.clone(), + state.graphics.quad_indices.clone(), + vec![set0], + ) + .unwrap(); + + Ok(PreviewState { + canvas, + pipeline, + pass, + swapchain, + images, + }) + } +} + +pub fn uidev_run(panel_name: &str) -> anyhow::Result<()> { + let (graphics, event_loop, window, surface) = WlxGraphics::new_window()?; + + USE_UINPUT.store(false, std::sync::atomic::Ordering::Relaxed); + + let mut state = AppState::from_graphics(graphics.clone())?; + let mut preview = Some(PreviewState::new( + &mut state, + surface.clone(), + window.clone(), + panel_name, + )?); + let mut previous_frame_end = Some(vulkano::sync::now(graphics.device.clone()).boxed()); + + let watch_path = config_io::CONFIG_ROOT_PATH.join(format!("{}.yaml", panel_name)); + let mut path_last_modified = watch_path.metadata()?.modified()?; + + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + let new_modified = watch_path.metadata().unwrap().modified().unwrap(); + if new_modified > path_last_modified { + { + let _ = preview.take(); // free swapchain + } + preview = Some( + PreviewState::new(&mut state, surface.clone(), window.clone(), panel_name) + .unwrap(), + ); + path_last_modified = new_modified; + } + + { + let preview = preview.as_ref().unwrap(); + + let (image_index, _, acquire_future) = + match acquire_next_image(preview.swapchain.clone(), None) + .map_err(Validated::unwrap) + { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + elwt.exit(); + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + let target = preview.images[image_index as usize].clone(); + + let mut cmd_buf = state + .graphics + .create_command_buffer(CommandBufferUsage::OneTimeSubmit) + .unwrap(); + cmd_buf.begin_rendering(target).unwrap(); + let _ = cmd_buf.run_ref(&preview.pass); + cmd_buf.end_rendering().unwrap(); + + let command_buffer = cmd_buf.build().unwrap(); + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(graphics.queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + graphics.queue.clone(), + SwapchainPresentInfo::swapchain_image_index( + preview.swapchain.clone(), + image_index, + ), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + previous_frame_end = + Some(vulkano::sync::now(state.graphics.device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = + Some(vulkano::sync::now(state.graphics.device.clone()).boxed()); + } + } + } + } + Event::AboutToWait => window.request_redraw(), + _ => (), + } + })?; + + Ok(()) +} + +fn create_swapchain( + graphics: &WlxGraphics, + surface: Arc, + extent: [u32; 2], +) -> anyhow::Result<(Arc, Vec>)> { + let surface_capabilities = graphics + .device + .physical_device() + .surface_capabilities(&surface, Default::default()) + .unwrap(); + + let (swapchain, images) = Swapchain::new( + graphics.device.clone(), + surface.clone(), + SwapchainCreateInfo { + min_image_count: surface_capabilities.min_image_count.max(2), + image_format: graphics.native_format, + image_extent: extent, + image_usage: ImageUsage::COLOR_ATTACHMENT, + composite_alpha: surface_capabilities + .supported_composite_alpha + .into_iter() + .next() + .unwrap(), + ..Default::default() + }, + )?; + + let image_views = images + .into_iter() + .map(|image| ImageView::new_default(image).unwrap()) + .collect::>(); + + Ok((swapchain, image_views)) +} diff --git a/src/graphics.rs b/src/graphics.rs index 9b4e68f..cffe3bd 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -490,6 +490,142 @@ impl WlxGraphics { Ok(Arc::new(me)) } + #[cfg(feature = "uidev")] + pub fn new_window() -> anyhow::Result<( + Arc, + winit::event_loop::EventLoop<()>, + Arc, + Arc, + )> { + use vulkano::swapchain::Surface; + use winit::{event_loop::EventLoop, window::WindowBuilder}; + + let event_loop = EventLoop::new().unwrap(); + let mut vk_instance_extensions = Surface::required_extensions(&event_loop).unwrap(); + vk_instance_extensions.khr_get_physical_device_properties2 = true; + log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions); + + let instance = Instance::new( + get_vulkan_library().clone(), + InstanceCreateInfo { + flags: InstanceCreateFlags::ENUMERATE_PORTABILITY, + enabled_extensions: vk_instance_extensions, + ..Default::default() + }, + )?; + + let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap()); + let surface = Surface::from_window(instance.clone(), window.clone())?; + + let device_extensions = DeviceExtensions { + khr_swapchain: true, + khr_external_memory: true, + khr_external_memory_fd: true, + ext_external_memory_dma_buf: true, + ext_image_drm_format_modifier: true, + ..DeviceExtensions::empty() + }; + + log::debug!("Device exts for app: {:?}", &device_extensions); + + let (physical_device, my_extensions, queue_family_index) = instance + .enumerate_physical_devices()? + .filter_map(|p| { + if p.supported_extensions().contains(&device_extensions) { + Some((p, device_extensions)) + } else { + log::debug!( + "Not using {} because it does not implement the following device extensions:", + p.properties().device_name, + ); + for (ext, missing) in p.supported_extensions().difference(&device_extensions) { + if missing { + log::debug!(" {}", ext); + } + } + None + } + }) + .filter_map(|(p, my_extensions)| { + p.queue_family_properties() + .iter() + .enumerate() + .position(|(i, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS) + && p.surface_support(i as u32, &surface).unwrap_or(false)) + .map(|i| (p, my_extensions, i as u32)) + }) + .min_by_key(|(p, _, _)| match p.properties().device_type { + PhysicalDeviceType::DiscreteGpu => 0, + PhysicalDeviceType::IntegratedGpu => 1, + PhysicalDeviceType::VirtualGpu => 2, + PhysicalDeviceType::Cpu => 3, + PhysicalDeviceType::Other => 4, + _ => 5, + }) + .expect("no suitable physical device found"); + + log::info!( + "Using vkPhysicalDevice: {}", + physical_device.properties().device_name, + ); + + let (device, mut queues) = Device::new( + physical_device, + DeviceCreateInfo { + enabled_extensions: my_extensions, + enabled_features: Features { + dynamic_rendering: true, + ..Features::empty() + }, + queue_create_infos: vec![QueueCreateInfo { + queue_family_index, + ..Default::default() + }], + ..Default::default() + }, + )?; + + let native_format = device + .physical_device() + .surface_formats(&surface, Default::default()) + .unwrap()[0] + .0; + log::info!("Using surface format: {:?}", native_format); + + let queue = queues + .next() + .ok_or_else(|| anyhow::anyhow!("no GPU queues available"))?; + + let memory_allocator = memory_allocator(device.clone()); + let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new( + device.clone(), + StandardCommandBufferAllocatorCreateInfo { + secondary_buffer_count: 32, + ..Default::default() + }, + )); + let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( + device.clone(), + Default::default(), + )); + + let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?; + + let me = Self { + instance, + device, + queue, + memory_allocator, + native_format, + command_buffer_allocator, + descriptor_set_allocator, + quad_indices, + quad_verts, + shared_shaders: RwLock::new(HashMap::new()), + }; + + Ok((Arc::new(me), event_loop, window, surface)) + } fn default_quad( memory_allocator: Arc, ) -> anyhow::Result<(Vert2Buf, IndexBuf)> { diff --git a/src/gui/modular/mod.rs b/src/gui/modular/mod.rs index c10dbeb..f2aedd8 100644 --- a/src/gui/modular/mod.rs +++ b/src/gui/modular/mod.rs @@ -120,7 +120,7 @@ pub fn modular_canvas( size[0] as _, size[1] as _, state.graphics.clone(), - state.format, + state.graphics.native_format, (), )?; let empty_str: Arc = Arc::from(""); diff --git a/src/hid.rs b/src/hid.rs index 825f097..1d49e6f 100644 --- a/src/hid.rs +++ b/src/hid.rs @@ -7,11 +7,18 @@ use input_linux::{ }; use libc::{input_event, timeval}; use once_cell::sync::Lazy; -use std::fs::File; use std::mem::transmute; +use std::{fs::File, sync::atomic::AtomicBool}; use strum::{EnumIter, EnumString, IntoEnumIterator}; +pub static USE_UINPUT: AtomicBool = AtomicBool::new(true); + pub fn initialize() -> Box { + if !USE_UINPUT.load(std::sync::atomic::Ordering::Relaxed) { + log::info!("Uinput disabled by user."); + return Box::new(DummyProvider {}); + } + if let Some(uinput) = UInputProvider::try_new() { log::info!("Initialized uinput."); return Box::new(uinput); diff --git a/src/main.rs b/src/main.rs index b76289b..df904dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,6 +41,11 @@ struct Args { /// Path to write logs to #[arg(short, long, value_name = "FILE_PATH")] log_to: Option, + + #[cfg(feature = "uidev")] + /// Show a desktop window of a UI panel for development + #[arg(short, long, value_name = "UI_NAME")] + uidev: Option, } fn main() -> Result<(), Box> { @@ -60,6 +65,12 @@ fn main() -> Result<(), Box> { return Ok(()); } + #[cfg(feature = "uidev")] + if let Some(panel_name) = args.uidev.as_ref() { + crate::backend::uidev::uidev_run(panel_name.as_str())?; + return Ok(()); + } + let running = Arc::new(AtomicBool::new(true)); let _ = ctrlc::set_handler({ let running = running.clone(); diff --git a/src/overlays/keyboard.rs b/src/overlays/keyboard.rs index ef4ee28..f63a4e9 100644 --- a/src/overlays/keyboard.rs +++ b/src/overlays/keyboard.rs @@ -43,7 +43,7 @@ where size.x as _, size.y as _, app.graphics.clone(), - app.format, + app.graphics.native_format, data, )?; diff --git a/src/state.rs b/src/state.rs index 68c2728..52b2026 100644 --- a/src/state.rs +++ b/src/state.rs @@ -6,7 +6,6 @@ use idmap::IdMap; use rodio::{Decoder, OutputStream, OutputStreamHandle, Source}; use serde::{Deserialize, Serialize}; use smallvec::{smallvec, SmallVec}; -use vulkano::format::Format; use crate::{ backend::{common::TaskContainer, input::InputState}, @@ -24,7 +23,6 @@ pub struct AppState { pub session: AppSession, pub tasks: TaskContainer, pub graphics: Arc, - pub format: vulkano::format::Format, pub input_state: InputState, pub hid_provider: Box, pub audio: AudioOutput, @@ -63,7 +61,6 @@ impl AppState { session: AppSession::load(), tasks: TaskContainer::new(), graphics, - format: Format::R8G8B8A8_UNORM, input_state: InputState::new(), hid_provider: crate::hid::initialize(), audio: AudioOutput::new(), From 159bd96b93b0dafe8e894518f9bc403a7defcb84 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:27:35 +0900 Subject: [PATCH 2/2] remove unneeded dep --- Cargo.lock | 82 ------------------------------------------------------ Cargo.toml | 3 +- 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 619505e..e2c59f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1378,18 +1378,6 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] - [[package]] name = "fixedbitset" version = "0.4.2" @@ -1816,26 +1804,6 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "input-linux" version = "0.6.0" @@ -1971,26 +1939,6 @@ dependencies = [ "serde", ] -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -2203,18 +2151,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "moveit" version = "0.6.0" @@ -2310,23 +2246,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "notify" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.5.0", - "filetime", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "walkdir", - "windows-sys 0.48.0", -] - [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -4261,7 +4180,6 @@ dependencies = [ "json5", "libc", "log", - "notify", "once_cell", "openxr", "ovr_overlay", diff --git a/Cargo.toml b/Cargo.toml index c7099e0..76fb90e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,6 @@ vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano", rev = "94f50f wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.8", default-features = false } winit = { version = "0.29.15", optional = true } xdg = "2.5.2" -notify = { version = "6.1.1", default-features = false, optional = true } [features] default = ["openvr", "openxr", "osc", "x11", "wayland"] @@ -63,4 +62,4 @@ openxr = ["dep:openxr"] osc = ["dep:rosc"] x11 = ["wlx-capture/xshm"] wayland = ["wlx-capture/pipewire", "wlx-capture/wlr"] -uidev = ["dep:notify", "dep:winit"] +uidev = ["dep:winit"]