Skip to content

Commit 604ea1d

Browse files
authored
Merge branch 'main' into feat/ffi-poll-events
2 parents 4e8a8f7 + cc62a74 commit 604ea1d

81 files changed

Lines changed: 2582 additions & 717 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: 'Install Mesa'
2+
description: "Install the runner release's lavapipe and select it as the only Vulkan driver"
3+
runs:
4+
using: 'composite'
5+
steps:
6+
# Distro Mesa rather than gfx-rs/ci-build: those builds have no window-system support
7+
# (-Dplatforms=), so they can't create the X11 surfaces sketches render to.
8+
- name: Install Mesa
9+
shell: bash
10+
run: |
11+
set -e
12+
sudo apt-get install -y --no-install-recommends mesa-vulkan-drivers libvulkan1
13+
icd=$(dpkg -L mesa-vulkan-drivers | grep -E '/lvp_icd[^/]*\.json$' | head -1)
14+
if [ -z "$icd" ]; then
15+
echo "::error::no lavapipe ICD in mesa-vulkan-drivers"
16+
dpkg -L mesa-vulkan-drivers | grep -E '\.json$'
17+
exit 1
18+
fi
19+
echo "Using $icd"
20+
echo "VK_DRIVER_FILES=$icd" >> "$GITHUB_ENV"
21+
dpkg-query -W mesa-vulkan-drivers
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Visual comment
2+
3+
# Posts visual.yml's PR summary as a sticky comment. Runs from the base repository so it can
4+
# write to PRs from forks; it never checks out PR code and treats the artifact as untrusted.
5+
6+
on:
7+
workflow_run:
8+
workflows: [ Visual ]
9+
types: [ completed ]
10+
11+
permissions: {}
12+
13+
jobs:
14+
comment:
15+
if: >-
16+
github.event.workflow_run.event == 'pull_request' &&
17+
github.event.workflow_run.conclusion != 'cancelled' &&
18+
github.event.workflow_run.conclusion != 'skipped'
19+
runs-on: ubuntu-latest
20+
permissions:
21+
actions: read
22+
pull-requests: write
23+
steps:
24+
- uses: actions/download-artifact@v8
25+
id: download
26+
continue-on-error: true
27+
with:
28+
name: visual-comment
29+
path: comment
30+
run-id: ${{ github.event.workflow_run.id }}
31+
github-token: ${{ github.token }}
32+
33+
- name: Validate
34+
id: pr
35+
if: steps.download.outcome == 'success'
36+
env:
37+
GH_TOKEN: ${{ github.token }}
38+
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
39+
run: |
40+
pr=$(cat comment/pr)
41+
notable=$(cat comment/notable)
42+
[[ "$pr" =~ ^[0-9]+$ ]] || { echo "invalid PR number"; exit 1; }
43+
[[ "$notable" == true || "$notable" == false ]] || { echo "invalid notable flag"; exit 1; }
44+
pr_head=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$pr" --jq .head.sha)
45+
[[ "$pr_head" == "$HEAD_SHA" ]] || { echo "PR #$pr is not at $HEAD_SHA; skipping"; exit 0; }
46+
echo "number=$pr" >> "$GITHUB_OUTPUT"
47+
echo "notable=$notable" >> "$GITHUB_OUTPUT"
48+
49+
- name: Post comment
50+
if: steps.pr.outputs.notable == 'true'
51+
uses: marocchino/sticky-pull-request-comment@v3.0.5
52+
with:
53+
header: visual-regression
54+
number_force: ${{ steps.pr.outputs.number }}
55+
path: comment/comment.md
56+
57+
# A clean run only refreshes an earlier comment, so passing PRs stay quiet.
58+
- name: Update comment
59+
if: steps.pr.outputs.notable == 'false'
60+
uses: marocchino/sticky-pull-request-comment@v3.0.5
61+
with:
62+
header: visual-regression
63+
number_force: ${{ steps.pr.outputs.number }}
64+
path: comment/comment.md
65+
only_update: true

‎.github/workflows/visual.yml‎

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
name: Visual
2+
3+
# Renders tests/visual/cases.toml under lavapipe
4+
5+
on:
6+
push:
7+
branches: [ main ]
8+
pull_request:
9+
branches: [ main ]
10+
types: [ opened, synchronize, reopened, labeled, unlabeled ]
11+
12+
permissions:
13+
contents: read
14+
actions: read
15+
16+
concurrency:
17+
group: visual-${{ github.event.pull_request.number || github.sha }}
18+
cancel-in-progress: true
19+
20+
env:
21+
CARGO_TERM_COLOR: always
22+
CARGO_INCREMENTAL: 0
23+
CARGO_PROFILE_RELEASE_DEBUG: 0
24+
WGPU_BACKEND: vulkan
25+
WGPU_ADAPTER_NAME: llvmpipe
26+
# Catch reads of uninitialized GPU memory instead of rendering whatever was there
27+
LVP_POISON_MEMORY: "true"
28+
# llvmpipe JITs for the host CPU
29+
LP_NATIVE_VECTOR_WIDTH: "256"
30+
ODIFF_VERSION: 4.5.0
31+
32+
jobs:
33+
visual:
34+
name: Visual regression
35+
# Only re-run on label changes that involve the override label.
36+
if: >-
37+
github.event_name == 'push' ||
38+
(github.event.action != 'labeled' && github.event.action != 'unlabeled') ||
39+
github.event.label.name == 'deliberate-rendering-change'
40+
runs-on: ubuntu-24.04
41+
timeout-minutes: 90
42+
steps:
43+
- uses: actions/checkout@v4
44+
with:
45+
submodules: true
46+
# PR checkouts are merge commits; HEAD^1 is the main commit they're compared against.
47+
fetch-depth: 2
48+
persist-credentials: false
49+
50+
- uses: ./.github/actions/setup
51+
52+
- uses: ./.github/actions/install-mesa
53+
54+
- uses: astral-sh/setup-uv@v6
55+
56+
- name: Install xvfb and odiff
57+
run: |
58+
sudo apt-get install -y --no-install-recommends xvfb
59+
npm install -g "odiff-bin@$ODIFF_VERSION"
60+
61+
- uses: actions/cache@v4
62+
with:
63+
path: |
64+
~/.cargo/bin/
65+
~/.cargo/registry/index/
66+
~/.cargo/registry/cache/
67+
~/.cargo/git/db/
68+
target/
69+
key: ${{ runner.os }}-cargo-visual-${{ hashFiles('**/Cargo.lock') }}
70+
restore-keys: |
71+
${{ runner.os }}-cargo-visual-
72+
${{ runner.os }}-cargo-
73+
74+
- name: Render
75+
run: xvfb-run -a -s "-screen 0 1920x1080x24" python3 tests/visual/visual.py render --out out/actual
76+
77+
- uses: actions/upload-artifact@v7
78+
with:
79+
name: visual-screenshots
80+
path: out/actual
81+
retention-days: ${{ github.event_name == 'push' && 90 || 14 }}
82+
83+
- name: Fetch baseline from main
84+
if: github.event_name == 'pull_request'
85+
env:
86+
GH_TOKEN: ${{ github.token }}
87+
run: |
88+
sha=$(git rev-parse HEAD^1)
89+
latest() {
90+
gh run list -R "$GITHUB_REPOSITORY" --workflow visual.yml --branch main --event push \
91+
--commit "$sha" --limit 1 --json databaseId,status,conclusion --jq '.[0] // empty'
92+
}
93+
run=$(latest)
94+
if [ -n "$run" ] && [ "$(jq -r .status <<< "$run")" != completed ]; then
95+
id=$(jq -r .databaseId <<< "$run")
96+
echo "Waiting for main's run $id to publish screenshots"
97+
gh run watch "$id" -R "$GITHUB_REPOSITORY" --interval 30 > /dev/null || true
98+
run=$(latest)
99+
fi
100+
if [ "$(jq -r '.conclusion // empty' <<< "$run")" = success ] &&
101+
gh run download "$(jq -r .databaseId <<< "$run")" -R "$GITHUB_REPOSITORY" -n visual-screenshots -D out/baseline; then
102+
echo "Using screenshots from run $(jq -r .databaseId <<< "$run")"
103+
else
104+
echo "::notice::No screenshots published for main at $sha; cases are reported as new"
105+
fi
106+
107+
- name: Compare
108+
id: compare
109+
if: github.event_name == 'pull_request'
110+
env:
111+
ALLOW_CHANGES: ${{ contains(github.event.pull_request.labels.*.name, 'deliberate-rendering-change') && '--allow-changes' || '' }}
112+
run: |
113+
mkdir -p out/baseline
114+
python3 tests/visual/visual.py compare --baseline out/baseline --actual out/actual --out out/report $ALLOW_CHANGES
115+
116+
- uses: actions/upload-artifact@v7
117+
id: report
118+
if: always() && hashFiles('out/report/report.html') != ''
119+
with:
120+
path: out/report/report.html
121+
archive: false
122+
retention-days: 14
123+
124+
- name: Summarize
125+
if: always() && hashFiles('out/report/summary.md') != ''
126+
env:
127+
PR_NUMBER: ${{ github.event.pull_request.number }}
128+
REPORT_URL: ${{ steps.report.outputs.artifact-url }}
129+
run: |
130+
mkdir -p out/comment
131+
{
132+
cat out/report/summary.md
133+
echo
134+
echo "[Open the visual report]($REPORT_URL) · [workflow run]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)"
135+
} > out/comment/comment.md
136+
cat out/comment/comment.md >> "$GITHUB_STEP_SUMMARY"
137+
echo "$PR_NUMBER" > out/comment/pr
138+
jq '[.results[] | select(.status != "pass")] | length > 0' out/report/results.json > out/comment/notable
139+
140+
- uses: actions/upload-artifact@v7
141+
if: always() && hashFiles('out/comment/comment.md') != ''
142+
with:
143+
name: visual-comment
144+
path: out/comment
145+
retention-days: 1

‎Cargo.lock‎

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ processing_glfw = { workspace = true }
9494
rand = { workspace = true }
9595

9696
[target.'cfg(target_os = "linux")'.dev-dependencies]
97-
processing_glfw = { workspace = true, features = ["wayland"] }
97+
processing_glfw = { workspace = true, features = ["wayland", "x11"] }
9898

9999
## TODO: Remove these patches once we've moved back to depending on upstream bevy
100100
[patch."https://github.com/bevyengine/bevy"]

‎README.md‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ You can learn more about this project from this [talk at LibreGraphicsMeeting 20
99

1010
## Getting started
1111

12+
There is two different things at work here :
13+
- libprocessing (this repo) is the low-level cross-platform library for the core Processing API. It's written in Rust, and thus lets write Processing sketches in Rust.
14+
- mewnala is a Python package built directly from libprocessing, providing Python bindings for the library. It's available as any other Python package out there and lets you write Processing sketches in a Python environment, regardless of you having libprocessing or Rust installed.
15+
1216
### mewnala (the python library)
1317

1418
Inside of our `processing_pyo3` crate we have created a python package that you can easily install with pip.
@@ -28,21 +32,65 @@ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | ie
2832
```
2933

3034
#### Install a mewnala
35+
36+
We're going to create a folder named `mewnala-sketchbook` and install the `mewnala` package inside:
37+
3138
```bash
3239
# Initialize a project with uv
3340
uv init mewnala-sketchbook && cd mewnala-sketchbook
3441

3542
# add the package
3643
uv add mewnala
44+
```
45+
46+
Now create a file named `sketch.py` at the root of `mewnala-sketchbook`.
47+
48+
You can use this code to test
49+
50+
```python
51+
from mewnala import *
3752

53+
def setup():
54+
size(400, 400)
55+
background(255)
56+
57+
def draw():
58+
push_matrix()
59+
translate(mouse_x, mouse_y)
60+
fill(255, 100, 200)
61+
circle(0, 0, 50)
62+
pop_matrix()
63+
64+
run()
65+
```
66+
67+
Now run your sketch using:
68+
69+
```bash
3870
# run a sketch
3971
uv run sketch.py
4072
```
4173

74+
_Note: you can use any file name you want for your sketch_
75+
4276
### Rust (libprocessing)
4377

4478
You'll need to install the Rust toolchain to work on this project. Most users will want to install Rust via [`rustup`](https://rustup.rs/), which helps manage Rust toolchain versions.
4579

80+
### Clone the project and its submodules
81+
82+
When cloning this repo (or your fork), don't forget to install its submodules (eg. Lygia)
83+
84+
```bash
85+
git clone --recurse-submodules git@github.com:processing/libprocessing.git
86+
```
87+
88+
if you already cloned the repo without `--recurse-submodules`, you can run
89+
90+
```bash
91+
git submodule update --init
92+
```
93+
4694
### Build commands
4795

4896
This project uses [just](https://github.com/casey/just) as a command runner:
@@ -65,6 +113,12 @@ Install [wasm-pack](https://rustwasm.github.io/wasm-pack/):
65113
cargo install wasm-pack
66114
```
67115

116+
On Windows, you'll need to manually install `wasm-opt`
117+
118+
```bash
119+
cargo install wasm-opt
120+
```
121+
68122
You'll also need the wasm32 target:
69123

70124
```bash
@@ -84,6 +138,7 @@ This outputs the package to `target/wasm/`.
84138
```bash
85139
just wasm-serve
86140
```
141+
_Note: you'll need python installed on your machine to run this command_
87142

88143

89144
## Contributing

0 commit comments

Comments
 (0)