chore(shell-native): revert P0 probe gate transients

P0 dep-stack probe (Step 1a) cleared all three OS targets in CI
run 25358457742:
- macOS aarch64: full window+GL probe (cross-API state + readback) PASS
- Linux x86_64 (hosted runner): link-time PASS, runtime DEFERRED
  (LINUX_GPU_DEFERRED_NO_RUNNER) — Xvfb GLX limitation; same skip as
  bevy / rust-skia / iced CI.
- Windows x86_64 (hosted runner): link-time PASS, runtime DEFERRED
  (WINDOWS_GPU_DEFERRED_NO_RUNNER per spec §8.2).

Pin versions captured in
`openpencil-docs/superpowers/notes/2026-05-05-skia-glow-loader-compat-probe.md`.

Reverts:
- transient `[dev-dependencies]` block in shell-native Cargo.toml
  (skia-safe / glutin / glutin-winit / glow / raw-window-handle /
  scopeguard / dev-only winit override).
- transient `tests/p0_probe.rs` + `examples/p0_probe.rs`.
- transient workflow steps that gated `--ignored P0_PROBE_GATE` and the
  Xvfb / freetype / mesa apt installs that only the probe needed.

Kept:
- prod winit dep features `["x11", "wayland", "wayland-csd-adwaita",
  "rwh_06"]` — needed for Linux to satisfy winit's
  `compile_error!("...not supported by winit")` guard. Stage F may
  trim this when RenderBackend lands.
- workflow's libxkbcommon / libwayland apt install — winit's link-time
  deps for the features above.
- `.gitattributes` — enforces `eol=lf` so future cross-OS rustfmt stays
  green.

Task 1 will reintroduce skia-safe / glutin / glow / raw-window-handle
/ scopeguard as permanent prod deps when SharedSkiaContext +
RenderBackend land.
This commit is contained in:
Kayshen-X 2026-05-05 12:23:09 +08:00
parent c75eba9964
commit ae13dc9bef
5 changed files with 39 additions and 904 deletions

View file

@ -35,49 +35,20 @@ jobs:
toolchain: "1.85"
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
# Linux GL prerequisites for the P0 probe ignored test step. xvfb gives
# winit a virtual display; mesa software-rasterizes GL when no GPU is
# available; libxkbcommon-x11-dev / libwayland-dev are winit's link-time
# dependencies on Linux; libfreetype-dev / libfontconfig1-dev are
# skia-bindings' link-time dependencies on Linux (skia-safe v0.97 links
# against the system freetype + fontconfig). (No-op on macOS / Windows.)
- name: Install Linux GL prereqs (P0 probe gate)
# Linux GL prerequisites for winit's x11+wayland feature link.
# libxkbcommon-x11-dev / libwayland-dev are winit's link-time deps on
# Linux; the wayland-csd-adwaita feature pulls in xkbcommon + wayland-client.
- name: Install Linux GL prereqs
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
xvfb \
libgl1-mesa-dri libglu1-mesa libegl1 libgles2 \
libxkbcommon-dev libxkbcommon-x11-dev \
libwayland-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
libfreetype-dev libfontconfig1-dev
libwayland-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
- run: cargo fmt --all -- --check
- run: cargo build --workspace
- run: cargo test --workspace
- run: cargo clippy --workspace --all-targets -- -D warnings
# P0 probe gate (Step 1a) — runs only the `#[ignore = "P0_PROBE_GATE"]`
# tests. macOS: runs the full window+GL path natively. Linux/Windows:
# the test body early-returns with a documented deferral marker
# because the GH-hosted runners cannot supply a usable GL window:
# Windows → WINDOWS_GPU_DEFERRED_NO_RUNNER (spec §8.2): no GL driver.
# Linux → LINUX_GPU_DEFERRED_NO_RUNNER (Xvfb's GLX visuals lack
# GLX_WINDOW_BIT, so `glXCreateWindow` returns
# `GLXBadWindow`. Same constraint hits bevy / rust-skia /
# iced CI; they all skip window-bound GL tests on hosted
# Linux runners). The link-time half of the dep-stack
# probe (skia-safe + glutin + glow + winit + EGL link)
# is already verified by `cargo build / test / clippy
# --workspace --all-targets` above. Manual smoke on a
# real Linux desktop with a GLX-capable X server runs
# the full path (env var unset → no early-return).
- name: P0 probe gate (Linux)
if: runner.os == 'Linux'
env:
OPENPENCIL_LINUX_GPU_DEFERRED_NO_RUNNER: '1'
run: cargo test -p openpencil-shell-native --test p0_probe -- --ignored
- name: P0 probe gate (macOS / Windows)
if: runner.os != 'Linux'
run: cargo test -p openpencil-shell-native --test p0_probe -- --ignored
deny:
name: cargo-deny (native)

511
Cargo.lock generated
View file

@ -18,12 +18,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "ahash"
version = "0.8.12"
@ -37,15 +31,6 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
@ -107,26 +92,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bindgen"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
"bitflags 2.11.1",
"cexpr",
"clang-sys",
"itertools",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -145,7 +110,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
dependencies = [
"objc2 0.5.2",
"objc2",
]
[[package]]
@ -218,15 +183,6 @@ dependencies = [
"shlex",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
@ -239,26 +195,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "cgl"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff"
dependencies = [
"libc",
]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "combine"
version = "4.6.7"
@ -330,15 +266,6 @@ dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
@ -357,16 +284,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dispatch2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
dependencies = [
"bitflags 2.11.1",
"objc2 0.6.4",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
@ -399,12 +316,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "equivalent"
version = "1.0.2"
@ -430,33 +341,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "filetime"
version = "0.2.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db"
dependencies = [
"cfg-if",
"libc",
"libredox",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "flate2"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "font-types"
version = "0.7.3"
@ -488,8 +378,8 @@ dependencies = [
"hashbrown 0.14.5",
"icu_locid",
"memmap2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
"peniko",
"roxmltree",
"skrifa",
@ -571,101 +461,6 @@ dependencies = [
"wasip2",
]
[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
"khronos_api",
"log",
"xml-rs",
]
[[package]]
name = "glob"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "glow"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5"
dependencies = [
"js-sys",
"slotmap",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "glutin"
version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325"
dependencies = [
"bitflags 2.11.1",
"cfg_aliases",
"cgl",
"dispatch2",
"glutin_egl_sys",
"glutin_glx_sys",
"glutin_wgl_sys",
"libloading",
"objc2 0.6.4",
"objc2-app-kit 0.3.2",
"objc2-core-foundation",
"objc2-foundation 0.3.2",
"once_cell",
"raw-window-handle",
"wayland-sys",
"windows-sys 0.52.0",
"x11-dl",
]
[[package]]
name = "glutin-winit"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f"
dependencies = [
"cfg_aliases",
"glutin",
"raw-window-handle",
"winit",
]
[[package]]
name = "glutin_egl_sys"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2"
dependencies = [
"gl_generator",
"windows-sys 0.52.0",
]
[[package]]
name = "glutin_glx_sys"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185"
dependencies = [
"gl_generator",
"x11-dl",
]
[[package]]
name = "glutin_wgl_sys"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e"
dependencies = [
"gl_generator",
]
[[package]]
name = "grid"
version = "0.15.0"
@ -688,12 +483,6 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
@ -722,15 +511,6 @@ dependencies = [
"hashbrown 0.17.0",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.18"
@ -817,12 +597,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kurbo"
version = "0.11.3"
@ -901,22 +675,6 @@ dependencies = [
"libc",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -947,16 +705,6 @@ dependencies = [
"jni-sys 0.3.1",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -1004,15 +752,6 @@ dependencies = [
"objc2-encode",
]
[[package]]
name = "objc2"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
dependencies = [
"objc2-encode",
]
[[package]]
name = "objc2-app-kit"
version = "0.2.2"
@ -1022,25 +761,13 @@ dependencies = [
"bitflags 2.11.1",
"block2",
"libc",
"objc2 0.5.2",
"objc2",
"objc2-core-data",
"objc2-core-image",
"objc2-foundation 0.2.2",
"objc2-foundation",
"objc2-quartz-core",
]
[[package]]
name = "objc2-app-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.11.1",
"objc2 0.6.4",
"objc2-core-foundation",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-cloud-kit"
version = "0.2.2"
@ -1049,9 +776,9 @@ checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2",
"objc2-core-location",
"objc2-foundation 0.2.2",
"objc2-foundation",
]
[[package]]
@ -1061,8 +788,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
]
[[package]]
@ -1073,19 +800,8 @@ checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.11.1",
"dispatch2",
"objc2 0.6.4",
"objc2",
"objc2-foundation",
]
[[package]]
@ -1095,8 +811,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
"objc2-metal",
]
@ -1107,9 +823,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2",
"objc2-contacts",
"objc2-foundation 0.2.2",
"objc2-foundation",
]
[[package]]
@ -1128,18 +844,7 @@ dependencies = [
"block2",
"dispatch",
"libc",
"objc2 0.5.2",
]
[[package]]
name = "objc2-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.11.1",
"objc2 0.6.4",
"objc2-core-foundation",
"objc2",
]
[[package]]
@ -1149,9 +854,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-app-kit",
"objc2-foundation",
]
[[package]]
@ -1162,8 +867,8 @@ checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
]
[[package]]
@ -1174,8 +879,8 @@ checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
"objc2-metal",
]
@ -1185,8 +890,8 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
dependencies = [
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
]
[[package]]
@ -1197,12 +902,12 @@ checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-image",
"objc2-core-location",
"objc2-foundation 0.2.2",
"objc2-foundation",
"objc2-link-presentation",
"objc2-quartz-core",
"objc2-symbols",
@ -1217,8 +922,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
dependencies = [
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-foundation",
]
[[package]]
@ -1229,9 +934,9 @@ checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [
"bitflags 2.11.1",
"block2",
"objc2 0.5.2",
"objc2",
"objc2-core-location",
"objc2-foundation 0.2.2",
"objc2-foundation",
]
[[package]]
@ -1257,13 +962,7 @@ dependencies = [
name = "openpencil-shell-native"
version = "0.1.0"
dependencies = [
"glow",
"glutin",
"glutin-winit",
"openpencil-shell-core",
"raw-window-handle",
"scopeguard",
"skia-safe",
"winit",
]
@ -1418,16 +1117,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
@ -1504,47 +1193,12 @@ dependencies = [
"bitflags 2.11.1",
]
[[package]]
name = "regex"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "roxmltree"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
[[package]]
name = "rustc-hash"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -1601,12 +1255,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sctk-adwaita"
version = "0.10.1"
@ -1669,27 +1317,12 @@ dependencies = [
"zmij",
]
[[package]]
name = "serde_spanned"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
dependencies = [
"serde_core",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simd-adler32"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "simd_cesu8"
version = "1.1.1"
@ -1706,33 +1339,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "skia-bindings"
version = "0.97.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6e3bcf8f25bf047e83110838463e8d06696c12fccc3d3794adf448b4d81f34b"
dependencies = [
"bindgen",
"cc",
"flate2",
"heck",
"pkg-config",
"regex",
"serde_json",
"tar",
"toml",
]
[[package]]
name = "skia-safe"
version = "0.97.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "935d4d174fb749bac9265eb41cad75039d32fda2d9c1a1e81b430df0e210a409"
dependencies = [
"bitflags 2.11.1",
"skia-bindings",
]
[[package]]
name = "skrifa"
version = "0.22.3"
@ -1837,17 +1443,6 @@ dependencies = [
"slotmap",
]
[[package]]
name = "tar"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@ -1922,21 +1517,6 @@ dependencies = [
"displaydoc",
]
[[package]]
name = "toml"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
@ -1967,12 +1547,6 @@ dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
[[package]]
name = "tracing"
version = "0.1.44"
@ -2192,7 +1766,6 @@ checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
dependencies = [
"dlib",
"log",
"once_cell",
"pkg-config",
]
@ -2409,9 +1982,9 @@ dependencies = [
"libc",
"memmap2",
"ndk",
"objc2 0.5.2",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"objc2-ui-kit",
"orbclient",
"percent-encoding",
@ -2491,16 +2064,6 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
[[package]]
name = "xattr"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
dependencies = [
"libc",
"rustix 1.1.4",
]
[[package]]
name = "xcursor"
version = "0.3.10"
@ -2526,12 +2089,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
[[package]]
name = "xml-rs"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
[[package]]
name = "zerocopy"
version = "0.8.48"

View file

@ -31,18 +31,3 @@ openpencil-shell-core = { path = "../openpencil-shell-core", version = "0.1.0" }
# 重新审视(可能加 `serde` / `rwh_06` 等)。
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
winit = { version = "0.30", default-features = false, features = ["x11", "wayland", "wayland-csd-adwaita", "rwh_06"] }
# TRANSIENT (Step 1a P0 CI gate only — reverted after notes commit, before Task 1 starts).
# These deps power `examples/p0_probe.rs` + `tests/p0_probe.rs` (gated `#[ignore = "P0_PROBE_GATE"]`).
# Pinned to versions resolved in /tmp/skia-glow-probe per spec §7. Task 1 will
# re-introduce them as permanent prod deps in this same target block.
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
skia-safe = { version = "0.97.0", features = ["gl"] }
glutin = "0.32.3"
glutin-winit = "0.5.0"
glow = "0.17.0"
raw-window-handle = "0.6.2"
scopeguard = "1.2.0"
# Re-enable winit defaults for the dev probe (prod dep is no-default — Stage F
# will choose the final feature set). Defaults pull in x11+wayland on Linux.
winit = { version = "0.30" }

View file

@ -1,290 +0,0 @@
//! P0 probe runner — runs verification (2) cross-API GL state visibility +
//! verification (3) full readback chain. Invoked as a subprocess from
//! `tests/p0_probe.rs` because winit on macOS requires `EventLoop::new()` on
//! the OS main thread (cargo test puts test fns on a worker thread).
//!
//! TRANSIENT (Step 1a P0 CI gate). Reverted before Task 1.
//!
//! Usage: `cargo run --example p0_probe -- <stencil|readback>`
//! Exit code 0 = PASS; non-zero with stderr message = FAIL.
use std::ffi::CString;
use std::num::NonZeroU32;
use std::process::ExitCode;
use glow::HasContext;
use glutin::config::ConfigTemplateBuilder;
use glutin::context::{ContextApi, ContextAttributesBuilder, NotCurrentGlContext};
use glutin::display::{GetGlDisplay, GlDisplay};
use glutin::surface::{GlSurface, SurfaceAttributesBuilder, WindowSurface};
use glutin_winit::DisplayBuilder;
use raw_window_handle::HasWindowHandle;
use skia_safe::gpu::{
backend_render_targets, direct_contexts, gl as skgl, surfaces, SurfaceOrigin,
};
use skia_safe::{Color, ColorType, Paint, Rect};
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};
const WIDTH: i32 = 64;
const HEIGHT: i32 = 64;
#[derive(Clone, Copy)]
enum Mode {
StencilVisibility,
Readback,
}
struct Probe {
mode: Mode,
result: Option<Result<(), String>>,
}
impl ApplicationHandler for Probe {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.result = Some(match self.mode {
Mode::StencilVisibility => run_stencil_visibility(event_loop),
Mode::Readback => run_readback(event_loop),
});
event_loop.exit();
}
fn window_event(&mut self, _event_loop: &ActiveEventLoop, _id: WindowId, _ev: WindowEvent) {}
}
struct GlStack {
_window: Window,
gl_surface: glutin::surface::Surface<WindowSurface>,
gl_context: glutin::context::PossiblyCurrentContext,
glow: glow::Context,
skia: skia_safe::gpu::DirectContext,
surface: skia_safe::Surface,
fb_info: skgl::FramebufferInfo,
}
fn build_stack(event_loop: &ActiveEventLoop) -> Result<GlStack, String> {
let window_attrs = WindowAttributes::default()
.with_visible(false)
.with_inner_size(winit::dpi::PhysicalSize::new(WIDTH as u32, HEIGHT as u32))
.with_title("p0-probe");
let template = ConfigTemplateBuilder::new()
.with_alpha_size(8)
.with_stencil_size(8);
let (window, gl_config) = DisplayBuilder::new()
.with_window_attributes(Some(window_attrs))
.build(event_loop, template, |configs| {
configs.into_iter().next().expect("no GL config available")
})
.map_err(|e| format!("DisplayBuilder::build failed: {e}"))?;
let window = window.ok_or("DisplayBuilder returned no window")?;
let raw_window_handle = window
.window_handle()
.map_err(|e| format!("window_handle: {e}"))?
.as_raw();
let gl_display = gl_config.display();
let context_attrs = ContextAttributesBuilder::new()
.with_context_api(ContextApi::OpenGl(None))
.build(Some(raw_window_handle));
let not_current = unsafe {
gl_display
.create_context(&gl_config, &context_attrs)
.map_err(|e| format!("create_context: {e}"))?
};
let surface_attrs = SurfaceAttributesBuilder::<WindowSurface>::new().build(
raw_window_handle,
NonZeroU32::new(WIDTH as u32).unwrap(),
NonZeroU32::new(HEIGHT as u32).unwrap(),
);
let gl_surface = unsafe {
gl_display
.create_window_surface(&gl_config, &surface_attrs)
.map_err(|e| format!("create_window_surface: {e}"))?
};
let gl_context = not_current
.make_current(&gl_surface)
.map_err(|e| format!("make_current: {e}"))?;
let glow = unsafe {
glow::Context::from_loader_function(|s| {
let cs = CString::new(s).unwrap();
gl_display.get_proc_address(&cs)
})
};
let interface = skgl::Interface::new_load_with(|s| {
if s == "eglGetCurrentDisplay" {
return std::ptr::null();
}
let cs = CString::new(s).unwrap();
gl_display.get_proc_address(&cs)
})
.ok_or("skia gl::Interface::new_load_with returned None")?;
let mut skia =
direct_contexts::make_gl(interface, None).ok_or("DirectContext::make_gl returned None")?;
let fb_info = skgl::FramebufferInfo {
fboid: 0,
// glow::RGBA8 is u32; skia's gl::Enum aliases GrGLenum = c_uint = u32
// on every platform in `deny.toml`'s target list. Use `as _` instead
// of `.try_into().unwrap()` so clippy::useless_conversion stays quiet.
format: glow::RGBA8 as _,
protected: skia_safe::gpu::Protected::No,
};
let backend_rt = backend_render_targets::make_gl((WIDTH, HEIGHT), 0, 8, fb_info);
let surface = surfaces::wrap_backend_render_target(
&mut skia,
&backend_rt,
SurfaceOrigin::BottomLeft,
ColorType::RGBA8888,
None,
None,
)
.ok_or("wrap_backend_render_target returned None")?;
Ok(GlStack {
_window: window,
gl_surface,
gl_context,
glow,
skia,
surface,
fb_info,
})
}
fn run_stencil_visibility(event_loop: &ActiveEventLoop) -> Result<(), String> {
let mut stack = build_stack(event_loop)?;
unsafe { stack.glow.enable(glow::STENCIL_TEST) };
let canvas = stack.surface.canvas();
canvas.clear(Color::TRANSPARENT);
let mut paint = Paint::default();
paint.set_color(Color::RED);
canvas.draw_rect(
Rect::from_xywh(0.0, 0.0, WIDTH as f32, HEIGHT as f32),
&paint,
);
stack.skia.flush_and_submit();
let still_enabled = unsafe { stack.glow.is_enabled(glow::STENCIL_TEST) };
unsafe { stack.glow.disable(glow::STENCIL_TEST) };
let _ = stack.gl_surface.swap_buffers(&stack.gl_context);
if !still_enabled {
return Err("STENCIL_TEST flag lost across Skia flush — context state NOT shared".into());
}
Ok(())
}
fn run_readback(event_loop: &ActiveEventLoop) -> Result<(), String> {
let mut stack = build_stack(event_loop)?;
// c0. save current READ_FRAMEBUFFER binding
let prev_read_fb = unsafe { stack.glow.get_parameter_i32(glow::READ_FRAMEBUFFER_BINDING) };
// c1. draw red into Skia surface
let canvas = stack.surface.canvas();
canvas.clear(Color::from_argb(255, 0, 0, 0));
let mut red = Paint::default();
red.set_color(Color::RED);
red.set_anti_alias(false);
canvas.draw_rect(Rect::from_xywh(0.0, 0.0, WIDTH as f32, HEIGHT as f32), &red);
stack.skia.flush_and_submit();
unsafe { stack.glow.finish() };
// c2-c3. resolve Skia FBO id (we wrapped fboid=0 = window default FBO)
let fboid = stack.fb_info.fboid;
let target_fb = NonZeroU32::new(fboid).map(glow::NativeFramebuffer);
// c4. RAII restore prev binding (panic-safe)
let glow_ref = &stack.glow;
let _restore = scopeguard::guard(prev_read_fb, |prev| unsafe {
let nfb = NonZeroU32::new(prev as u32).map(glow::NativeFramebuffer);
glow_ref.bind_framebuffer(glow::READ_FRAMEBUFFER, nfb);
});
// c5. bind Skia FBO + finish
unsafe {
stack
.glow
.bind_framebuffer(glow::READ_FRAMEBUFFER, target_fb)
};
unsafe { stack.glow.finish() };
// c6. readback
let mut buf = vec![0u8; (WIDTH * HEIGHT * 4) as usize];
unsafe {
stack.glow.read_pixels(
0,
0,
WIDTH,
HEIGHT,
glow::RGBA,
glow::UNSIGNED_BYTE,
glow::PixelPackData::Slice(Some(&mut buf)),
);
}
// c7. assert center pixel is red
let cx = WIDTH / 2;
let cy = HEIGHT / 2;
let i = ((cy * WIDTH + cx) * 4) as usize;
let center = (buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
drop(_restore);
let _ = stack.gl_surface.swap_buffers(&stack.gl_context);
if center.0 < 200 || center.1 > 80 || center.2 > 80 {
return Err(format!(
"center pixel not red — got rgba({}, {}, {}, {}); buf[0..4]={:?}",
center.0,
center.1,
center.2,
center.3,
&buf[..4]
));
}
Ok(())
}
fn main() -> ExitCode {
let mode = match std::env::args().nth(1).as_deref() {
Some("stencil") => Mode::StencilVisibility,
Some("readback") => Mode::Readback,
other => {
eprintln!("usage: readback <stencil|readback>; got {:?}", other);
return ExitCode::from(2);
}
};
let event_loop = match EventLoop::new() {
Ok(el) => el,
Err(e) => {
eprintln!("EventLoop::new failed: {e}");
return ExitCode::from(3);
}
};
let mut probe = Probe { mode, result: None };
if let Err(e) = event_loop.run_app(&mut probe) {
eprintln!("run_app failed: {e}");
return ExitCode::from(4);
}
match probe.result {
Some(Ok(())) => ExitCode::SUCCESS,
Some(Err(e)) => {
eprintln!("FAIL: {e}");
ExitCode::from(1)
}
None => {
eprintln!("FAIL: handler never produced a result (window never resumed?)");
ExitCode::from(5)
}
}
}

View file

@ -1,88 +0,0 @@
//! P0 probe — verifications (2) and (3) per Step 1a spec §7.2.
//!
//! TRANSIENT: this test exists only to drive the three-OS CI matrix for the
//! P0 dep-stack probe gate. After CI is green and probe pin versions are
//! recorded in `openpencil-docs/superpowers/notes/2026-05-05-skia-glow-loader-compat-probe.md`,
//! this file plus `examples/p0_probe.rs` plus the matching dev-dep block in
//! `Cargo.toml` are reverted. Task 1 owns the permanent integration.
//!
//! Why this test shells out to `examples/p0_probe.rs` instead of running the
//! winit `EventLoop` inline: on macOS, winit refuses to construct an
//! `EventLoop` off the OS main thread (panics with "EventLoop must be
//! created on the main thread"). `cargo test` always runs `#[test]` fns on
//! a libtest worker thread. The cross-OS-portable workaround is to put the
//! `fn main()` driver in `examples/p0_probe.rs` (where rustc owns the real
//! main thread) and invoke it as a subprocess from each test. Each
//! `#[test]` subprocess gets a fresh process, side-stepping winit's
//! "EventLoop already created" guard for the second test.
//!
//! `#[ignore = "P0_PROBE_GATE"]` keeps the default `cargo test --workspace`
//! green; CI runs a separate `cargo test --workspace -- --ignored
//! P0_PROBE_GATE` step.
use std::process::Command;
fn run_example(arg: &str) {
if cfg!(target_os = "windows") {
// spec §8.2: standard GitHub Actions Windows runner has no GL driver
// (WINDOWS_GPU_DEFERRED_NO_RUNNER); manual smoke required there.
eprintln!("WINDOWS_GPU_DEFERRED_NO_RUNNER: skipping GL probe on Windows runner");
return;
}
// Mirror Windows §8.2 deferral on the GH-hosted ubuntu-latest runner:
// headless GL via Xvfb cannot satisfy `glXCreateWindow` (Xlib returns
// GLXBadWindow because Xvfb's GLX visuals don't have GLX_WINDOW_BIT
// set) — confirmed by bevy / rust-skia / iced CI which all skip
// window-bound GL tests on Linux runners. Local macOS verifies the
// functional half (cross-API state + readback). Workspace
// `cargo build / test / clippy` already verified the link-time toolchain
// works on Linux x86_64 in the same CI job. CI exports
// `OPENPENCIL_LINUX_GPU_DEFERRED_NO_RUNNER=1` to opt into this skip;
// running the probe locally on a real Linux desktop (with a GLX-capable
// X server) leaves the env var unset and exercises the full path.
if cfg!(target_os = "linux")
&& std::env::var_os("OPENPENCIL_LINUX_GPU_DEFERRED_NO_RUNNER").is_some()
{
eprintln!("LINUX_GPU_DEFERRED_NO_RUNNER: skipping GL probe on Linux CI runner (Xvfb GLX limitation)");
return;
}
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".into());
let mut cmd = Command::new(cargo);
cmd.args([
"run",
"--quiet",
"-p",
"openpencil-shell-native",
"--example",
"p0_probe",
"--",
arg,
]);
let output = cmd
.output()
.expect("failed to spawn `cargo run --example p0_probe`");
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
panic!(
"probe example `{arg}` failed (status {:?}):\n--- stderr ---\n{}\n--- stdout ---\n{}",
output.status.code(),
stderr,
stdout
);
}
}
#[test]
#[ignore = "P0_PROBE_GATE"]
fn cross_api_gl_state_visibility() {
run_example("stencil");
}
#[test]
#[ignore = "P0_PROBE_GATE"]
fn gpu_readback() {
run_example("readback");
}