From bd249422df4e88bfe3f0750c316d5a62fa36be7d Mon Sep 17 00:00:00 2001 From: Wanjohi Date: Thu, 15 Oct 2026 08:21:39 +0000 Subject: [PATCH] Games that draw with OpenGL or Chromium no longer stream a black screen (#402) Guest image fixes from #401, plus the dev changes that had not reached prod yet. - **OpenGL games render** (Dome Keeper, confirmed on an AMD host). The guest's Mesa gains its EGL/GLX frontends, and `vm.overcommit_memory=1` stops a large reservation being refused before it is used. - **Chromium / NW.js games get past their first frame** (Sheepy). nescope answers every commit, and paces Xwayland windows too. - **Proton patch step.** `build/patches/proton/` and the `-nN` tag. Nothing uses it until hosts are pointed at the new tag. - Also included: the pixelforge update already on dev. It is in the image tested today. **Versions kept, not downgraded.** Dev still had host agent 0.2.13 and desktop 0.1.0. The last commit restores prod's 0.2.16 and 0.1.2, so this merge changes no install versions. **After merge.** `make push` from this prod commit publishes the guest image. The host agent release that raises LAYOUT to 6 makes hosts pull it. --------- Co-authored-by: DatCaptainHorse --- Cargo.lock | 173 +++++++++--------- apps/nescapture/Cargo.toml | 2 +- apps/nescope/src/handlers.rs | 31 ++-- apps/nescope/src/state.rs | 5 +- apps/nesinit/src/system.rs | 42 ++++- build/Containerfile | 18 +- build/Containerfile.proton | 12 ++ build/Makefile | 7 +- ...-ntdll-read-an-ASCII-locale-as-UTF-8.patch | 14 ++ 9 files changed, 190 insertions(+), 114 deletions(-) create mode 100644 build/patches/proton/wine/0001-ntdll-read-an-ASCII-locale-as-UTF-8.patch diff --git a/Cargo.lock b/Cargo.lock index ecb4533a..6cd030f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -335,7 +335,7 @@ checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -346,23 +346,22 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "calloop" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +checksum = "43b32313e937c8721c9d17ee9bf60699a6402b4b7c2cb6ac1bee0ffcaa4b4e5e" dependencies = [ "bitflags 2.13.2", "nix", "polling", "rustix 1.1.5", - "slab", "tracing", ] [[package]] name = "cc" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ "find-msvc-tools", "shlex 2.0.1", @@ -385,9 +384,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4ece8474b5f766c63426647e7b4b316b67431ade1036a8313cee24a03ae917" +checksum = "9ba9e9ec16c447027685b1f897b720e18e9a8afd00bd7332c483537e38086c9f" dependencies = [ "smallvec", "target-lexicon", @@ -490,7 +489,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -680,9 +679,9 @@ dependencies = [ [[package]] name = "ctutils" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" dependencies = [ "cmov", ] @@ -759,7 +758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c54e03a951783e8b327515db3f2a2fd0e3bed362a96b066f341ce66ed49b4ead" dependencies = [ "data-encoding", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -879,7 +878,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -968,9 +967,9 @@ dependencies = [ [[package]] name = "either" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "embedded-io" @@ -1006,7 +1005,7 @@ checksum = "0590c4a94da3372e83493b956755a6e2266830b6e4e3b101afe66e3f39477b91" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -1180,7 +1179,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -1316,9 +1315,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" dependencies = [ "atomic-waker", "bytes", @@ -1422,9 +1421,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c" dependencies = [ "atomic-waker", "bytes", @@ -1889,9 +1888,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +checksum = "b2b005715dcbeb0089a3c0dab99f2ff1cc3b2525323552703d648585d342a383" dependencies = [ "defmt", "jiff-core", @@ -1914,9 +1913,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +checksum = "2cc9817253cf7c7ee4684451bd327e88d6f3658014e54a29198625590650695c" dependencies = [ "jiff-core", "proc-macro2", @@ -2011,15 +2010,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libloading" @@ -2192,9 +2191,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "wasi", @@ -2731,9 +2730,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" dependencies = [ "objc2-encode", ] @@ -2976,7 +2975,7 @@ dependencies = [ [[package]] name = "pixelforge" version = "0.9.1" -source = "git+https://github.com/DatCaptainHorse/pixelforge.git?rev=b4b7b36af6f9cbd0fedae220915edd75de933743#b4b7b36af6f9cbd0fedae220915edd75de933743" +source = "git+https://github.com/DatCaptainHorse/pixelforge.git?rev=21bb5cdb2ae128eb762e4750378916aac8dd3c82#21bb5cdb2ae128eb762e4750378916aac8dd3c82" dependencies = [ "ash", "futures-channel", @@ -3128,9 +3127,9 @@ dependencies = [ [[package]] name = "powerfmt" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958" [[package]] name = "ppv-lite86" @@ -3147,7 +3146,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.15+spec-1.1.0", + "toml_edit 0.25.17+spec-1.1.0", ] [[package]] @@ -3597,14 +3596,14 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -3624,9 +3623,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" dependencies = [ "serde_core", ] @@ -3748,9 +3747,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" [[package]] name = "smithay" @@ -3825,9 +3824,9 @@ checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" [[package]] name = "spki" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" dependencies = [ "base64ct", "der", @@ -3885,9 +3884,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "01016da373cd8f7ef12624f796309f5c31ba8d646dd08856c02cd741d823c622" dependencies = [ "proc-macro2", "quote", @@ -3911,7 +3910,7 @@ checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -3944,7 +3943,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 1.1.6+spec-1.1.0", + "toml 1.1.8+spec-1.1.0", "version-compare", ] @@ -4004,7 +4003,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -4065,9 +4064,9 @@ checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" dependencies = [ "bytes", "libc", @@ -4088,7 +4087,7 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] @@ -4115,9 +4114,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", @@ -4178,14 +4177,14 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.6+spec-1.1.0" +version = "1.1.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" +checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 1.1.1+spec-1.1.0", + "serde_spanned 1.1.2", + "toml_datetime 1.1.2+spec-1.1.0", "toml_parser", "toml_writer", "winnow 1.0.4", @@ -4202,9 +4201,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "1.1.1+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" dependencies = [ "serde_core", ] @@ -4225,21 +4224,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.15+spec-1.1.0" +version = "0.25.17+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" dependencies = [ "indexmap", - "toml_datetime 1.1.1+spec-1.1.0", + "toml_datetime 1.1.2+spec-1.1.0", "toml_parser", "winnow 1.0.4", ] [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" dependencies = [ "winnow 1.0.4", ] @@ -4252,9 +4251,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.2+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" +checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" [[package]] name = "tower" @@ -4389,9 +4388,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-segmentation" @@ -4489,9 +4488,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.1" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -4538,9 +4537,9 @@ dependencies = [ [[package]] name = "want" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" dependencies = [ "try-lock", ] @@ -4603,7 +4602,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", "wasm-bindgen-shared", ] @@ -5271,30 +5270,30 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33811428bee40dbceb6d545e95754741d17a6aef9a4849f0fd62e2ba4f412a78" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.59" +version = "0.8.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +checksum = "86502bf56ac7c77571a32e2647bb2a15894565e981fb2a48d7bde2d91c965a9d" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.59" +version = "0.8.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +checksum = "5457206954b06561e2608c7e19cf58b1926586d999c246eebe4502f7e2039d1a" dependencies = [ "proc-macro2", "quote", @@ -5318,15 +5317,15 @@ checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", "synstructure", ] [[package]] name = "zeroize" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" dependencies = [ "zeroize_derive", ] @@ -5372,7 +5371,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.8", ] [[package]] diff --git a/apps/nescapture/Cargo.toml b/apps/nescapture/Cargo.toml index 58675961..d860ec4f 100644 --- a/apps/nescapture/Cargo.toml +++ b/apps/nescapture/Cargo.toml @@ -32,7 +32,7 @@ toml = "0.8" serde = { version = "1", features = ["derive"] } # Vulkan Video hardware encoding. -pixelforge = { git = "https://github.com/DatCaptainHorse/pixelforge.git", rev = "b4b7b36af6f9cbd0fedae220915edd75de933743" } +pixelforge = { git = "https://github.com/DatCaptainHorse/pixelforge.git", rev = "21bb5cdb2ae128eb762e4750378916aac8dd3c82" } # libc for socket options libc = "0.2" diff --git a/apps/nescope/src/handlers.rs b/apps/nescope/src/handlers.rs index 2a0d341e..075ec57f 100644 --- a/apps/nescope/src/handlers.rs +++ b/apps/nescope/src/handlers.rs @@ -100,22 +100,27 @@ impl CompositorHandler for NescopeState { s }; - let Some(window) = self + // Matched on the window's surface, not its xdg toplevel: an Xwayland + // window has no toplevel. + let window = self .space .elements() - .find(|w| { - w.toplevel() - .map(|t| t.wl_surface() == &root) - .unwrap_or(false) - }) - .cloned() - else { - return; - }; + .find(|w| w.wl_surface().is_some_and(|s| *s == root)) + .cloned(); + if let Some(window) = &window { + window.on_commit(); + self.game_frame_count += 1; + } - window.on_commit(); - self.game_frame_count += 1; - self.present_now(&root, &window); + // Every commit is answered, mapped window or not. A Vulkan client + // presenting FIFO waits in the driver for this frame callback, and + // not every surface a game draws to is a window here: Chromium's GPU + // process draws for a window another process owns, which Wine's + // Wayland driver gives a surface of its own with no role. Unanswered, + // that game presents one frame and waits forever. There is no screen + // here to pace against -- capture paces itself -- so answering every + // commit costs nothing a mapped window does not already get. + self.present_now(&root); } fn destroyed(&mut self, surface: &WlSurface) { diff --git a/apps/nescope/src/state.rs b/apps/nescope/src/state.rs index b3d13fb6..b682ae66 100644 --- a/apps/nescope/src/state.rs +++ b/apps/nescope/src/state.rs @@ -735,13 +735,14 @@ impl NescopeState { } } - pub(crate) fn present_now(&mut self, root: &WlSurface, window: &Window) { + pub(crate) fn present_now(&mut self, root: &WlSurface) { let output = self.output.clone(); let now = self.clock.now(); self.presentation_seq += 1; let mut fb = OutputPresentationFeedback::new(&output); - window.take_presentation_feedback( + take_presentation_feedback_surface_tree( + root, &mut fb, |_, _| Some(output.clone()), |_, _| wp_presentation_feedback::Kind::Vsync, diff --git a/apps/nesinit/src/system.rs b/apps/nesinit/src/system.rs index 5a952c9a..8246b58a 100644 --- a/apps/nesinit/src/system.rs +++ b/apps/nesinit/src/system.rs @@ -219,11 +219,26 @@ fn devices() { /// or Wine, and the process dies — here as a `wineserver crashed` with the game /// already gone. SteamOS and every distribution that packages Proton raise it /// to this value for that reason. -const SYSCTLS: &[(&str, &str, &str)] = &[( - "vm/max_map_count", - "2147483642", - "a game that maps more than 65530 regions (Unreal Engine 5 does) dies on a failed allocation", -)]; +/// - `vm.overcommit_memory`: **the kernel's default refuses any one allocation +/// larger than RAM plus swap**, and a box has no swap, so the ceiling is the +/// box's size: 8 GiB at 1080p. Engines and drivers reserve address space far +/// past what they touch, and a reservation is refused before a byte of it is +/// used — Dome Keeper asked for 9 GiB on an 8 GiB box and never started +/// (2026-10-14). `1` grants every request and leaves the OOM killer to act on +/// what is actually used; in a box that is the game, since this process has +/// already refused it. +const SYSCTLS: &[(&str, &str, &str)] = &[ + ( + "vm/max_map_count", + "2147483642", + "a game that maps more than 65530 regions (Unreal Engine 5 does) dies on a failed allocation", + ), + ( + "vm/overcommit_memory", + "1", + "a game that reserves more address space than the box has RAM is refused it and does not start", + ), +]; /// How many files a process may hold open, which every process in the box /// inherits from here. @@ -678,6 +693,23 @@ mod tests { assert!("2147483642".parse::().unwrap() > 65530 * 1000); } + #[test] + fn a_reservation_bigger_than_the_box_is_granted() { + let root = scratch("overcommit"); + std::fs::create_dir_all(root.join("vm")).unwrap(); + std::fs::write(root.join("vm/overcommit_memory"), "0\n").unwrap(); + + apply_sysctls(&root); + + assert_eq!( + std::fs::read_to_string(root.join("vm/overcommit_memory")) + .unwrap() + .trim(), + "1" + ); + let _ = std::fs::remove_dir_all(&root); + } + /// A box on a kernel without the knob still boots; the cost is said, not /// raised. #[test] diff --git a/build/Containerfile b/build/Containerfile index 0a068d7e..4ff69045 100644 --- a/build/Containerfile +++ b/build/Containerfile @@ -80,6 +80,13 @@ ARG MESA_GIT=https://gitlab.freedesktop.org/mesa/mesa.git ARG MESA_COMMIT=a4a47003a194effad8cabe727f74985e9417476f ARG JOBS= +# OpenGL is zink: GL on top of whichever Vulkan driver the box has, radv over +# native context or the forwarded NVIDIA one, so one build serves both. Its +# frontends have to be on for any of it to be reachable. With EGL, GLX, GBM and +# GLES off, a GL game found no GL at all and ran with sound and a black screen, +# which is what three alpha testers saw. GLX needs the x11 platform for +# Xwayland's clients, and Xwayland needs GBM to give them DRI3. +# # Our patches to the amdgpu native-context path, applied on top of the pinned # commit. They are not cosmetic: upstream's winsys re-queries device-static # facts on a path that costs a synchronous round trip to the host under @@ -93,17 +100,18 @@ RUN test -n "$JOBS" || JOBS=$(nproc) && \ meson setup builddir \ -Dprefix=/usr \ -Dbuildtype=release \ - -Dplatforms=wayland \ + -Dplatforms=wayland,x11 \ -Dgallium-drivers=zink \ -Dvulkan-drivers=amd,intel \ -Damdgpu-virtio=true \ -Dintel-virtio-experimental=true \ -Dvideo-codecs=all \ - -Degl=disabled \ - -Dglx=disabled \ + -Degl=enabled \ + -Dglx=dri \ + -Dglvnd=enabled \ -Dgles1=disabled \ - -Dgles2=disabled \ - -Dgbm=disabled \ + -Dgles2=enabled \ + -Dgbm=enabled \ -Dgallium-va=disabled \ -Db_ndebug=true && \ mold -run ninja -C builddir -j${JOBS:-$(nproc)} && \ diff --git a/build/Containerfile.proton b/build/Containerfile.proton index a8721017..172eea6f 100644 --- a/build/Containerfile.proton +++ b/build/Containerfile.proton @@ -110,6 +110,18 @@ RUN pacman -Syu --noconfirm --needed \ libsm libtheora xz \ && pacman -Scc --noconfirm +# Our own patches, one directory per submodule they apply to: patches/proton/ +# wine/ applies in wine/. Its own layer, after the fetch and the dependencies, +# so a patch change costs the build and nothing before it. A patch that no +# longer applies to a new tag stops here, before the hours of building. +COPY patches/proton /build/patches/proton +RUN set -e; cd /build/patches/proton; \ + for dir in */; do \ + for p in "${dir}"*.patch; do \ + echo "applying ${p}"; \ + patch -d "/build/proton-cachyos/${dir%/}" -p1 --forward < "${p}"; \ + done; \ + done COPY scripts/proton-build.sh /build/proton-build.sh RUN GECKO_VER="${GECKO_VER}" MONO_VER="${MONO_VER}" JOBS="${JOBS}" \ bash /build/proton-build.sh diff --git a/build/Makefile b/build/Makefile index d167742b..be252cfb 100644 --- a/build/Makefile +++ b/build/Makefile @@ -38,8 +38,13 @@ IMAGE_NAME := ghcr.io/nestrilabs/nestri/base # number in two spellings and an image whose name does not say which Proton is # inside it is worse than no image at all. Changing the tag by hand and # forgetting the version is exactly the mistake this removes. +# +# `PROTON_PATCHES` counts our own changes on top of that tag (patches/proton/). +# Bump it whenever they change, so a patched build never takes the name of the +# one before it; reset it to 0 when the tag moves. PROTON_TAG ?= cachyos-11.0-20261005-native -PROTON_VERSION := $(PROTON_TAG:cachyos-%-native=%) +PROTON_PATCHES ?= 1 +PROTON_VERSION := $(PROTON_TAG:cachyos-%-native=%)-n$(PROTON_PATCHES) PROTON_IMAGE ?= ghcr.io/nestrilabs/proton-cachyos-native-wow64 PROTON_REF := $(PROTON_IMAGE):$(PROTON_VERSION) OUTPUT_DIR := output diff --git a/build/patches/proton/wine/0001-ntdll-read-an-ASCII-locale-as-UTF-8.patch b/build/patches/proton/wine/0001-ntdll-read-an-ASCII-locale-as-UTF-8.patch new file mode 100644 index 00000000..50060c15 --- /dev/null +++ b/build/patches/proton/wine/0001-ntdll-read-an-ASCII-locale-as-UTF-8.patch @@ -0,0 +1,14 @@ +--- a/dlls/ntdll/unix/env.c ++++ b/dlls/ntdll/unix/env.c +@@ -286,6 +286,11 @@ + + if (!(ctype = setlocale( LC_CTYPE, "" ))) name = "UTF-8"; + else if (!(name = nl_langinfo( CODESET ))) return; ++ /* The C and POSIX locales name plain ASCII, in which a non-ASCII file ++ * name cannot be created at all. Steam starts games with LC_ALL=C, so ++ * under it every such name failed; ASCII is a subset of UTF-8, so ++ * reading it as UTF-8 changes nothing that worked before. */ ++ if (!strcmp( name, "ANSI_X3.4-1968" )) name = "UTF-8"; + TRACE_(nls)( "Unix LC_CTYPE %s, using %s codeset\n", debugstr_a(ctype), debugstr_a(name) ); + + /* remove punctuation characters from charset name */