Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ members = [
"tests/examples/libffi",
"tests/examples/expat",
"tests/examples/wayland",
"tests/examples/wayland-egl",
"tests/examples/egl",
"tests/examples/gl",
"tests/examples/libevdev",
Expand Down
51 changes: 51 additions & 0 deletions pkgs/f/freedesktop.wayland-egl.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-- freedesktop.wayland-egl — libwayland-egl, and the reason a Wayland client
-- could not use the GPU until now.
--
-- A Wayland client that draws with EGL needs three things: a `wl_surface` from
-- libwayland-client, an `EGLDisplay` from libEGL, and something to join them.
-- That something is `wl_egl_window_create(surface, w, h)` — the only way to get
-- an `EGLNativeWindowType` on Wayland, and it lives in this library and nowhere
-- else. Without it the sequence
--
-- wl_surface -> wl_egl_window -> eglCreateWindowSurface -> draw
--
-- has no second step.
--
-- WHY IT WAS MISSING, since the gap is instructive: the fork built the four
-- members a COMPOSITOR needs — client, server, util, scanner — and a compositor
-- renders into GBM buffers, so it never asks for this. The index therefore
-- looked complete from the server side and was unusable from the client side.
-- Upstream ships the source in the same tarball (`upstream/egl/`, 118 lines);
-- this was a member nobody had written, not a decision anyone had made.
--
-- ─────────────────────────────────────────────────────────────────────────
-- FIFTH MEMBER OF THE SAME TARBALL
--
-- `freedesktop.wayland`, `-server`, `-util`, `-scanner` and this one are five
-- index entries backed by ONE archive, each naming a different workspace
-- member. Adding this one changed the archive, so all five carry the new
-- sha256 in the same commit — see the note in that commit on why the tag was
-- left alone and a release ASSET was published instead.
package = {
spec = "1",
namespace = "freedesktop",
name = "wayland-egl",
description = "libwayland-egl 1.26.0 — wl_egl_window, the bridge from a wl_surface to an EGL window surface",
licenses = {"MIT"},
repo = "https://github.com/mcpplibs/wayland",
type = "package",

xpm = {
linux = {
["1.26.0"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/wayland/releases/download/v1.26.0/wayland-1.26.0-mcpp2.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0-mcpp2.tar.gz",
},
sha256 = "bcf388cc1dd6617fdce5cb595defbe2aa1fae8db292ca5d7fd84afda2811be32",
},
},
},

mcpp = "*/mcpp/egl/mcpp.toml",
}
6 changes: 3 additions & 3 deletions pkgs/f/freedesktop.wayland-scanner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ package = {
linux = {
["1.26.0"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/wayland/archive/refs/tags/v1.26.0.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0.tar.gz",
GLOBAL = "https://github.com/mcpplibs/wayland/releases/download/v1.26.0/wayland-1.26.0-mcpp2.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0-mcpp2.tar.gz",
},
sha256 = "961a900dafe76e713c2e46d9a064ff3a6375622f4057013472a04c44d8bcb6e8",
sha256 = "bcf388cc1dd6617fdce5cb595defbe2aa1fae8db292ca5d7fd84afda2811be32",
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions pkgs/f/freedesktop.wayland-server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ package = {
linux = {
["1.26.0"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/wayland/archive/refs/tags/v1.26.0.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0.tar.gz",
GLOBAL = "https://github.com/mcpplibs/wayland/releases/download/v1.26.0/wayland-1.26.0-mcpp2.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0-mcpp2.tar.gz",
},
sha256 = "961a900dafe76e713c2e46d9a064ff3a6375622f4057013472a04c44d8bcb6e8",
sha256 = "bcf388cc1dd6617fdce5cb595defbe2aa1fae8db292ca5d7fd84afda2811be32",
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions pkgs/f/freedesktop.wayland-util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ package = {
linux = {
["1.26.0"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/wayland/archive/refs/tags/v1.26.0.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0.tar.gz",
GLOBAL = "https://github.com/mcpplibs/wayland/releases/download/v1.26.0/wayland-1.26.0-mcpp2.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0-mcpp2.tar.gz",
},
sha256 = "961a900dafe76e713c2e46d9a064ff3a6375622f4057013472a04c44d8bcb6e8",
sha256 = "bcf388cc1dd6617fdce5cb595defbe2aa1fae8db292ca5d7fd84afda2811be32",
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions pkgs/f/freedesktop.wayland.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ package = {
linux = {
["1.26.0"] = {
url = {
GLOBAL = "https://github.com/mcpplibs/wayland/archive/refs/tags/v1.26.0.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0.tar.gz",
GLOBAL = "https://github.com/mcpplibs/wayland/releases/download/v1.26.0/wayland-1.26.0-mcpp2.tar.gz",
CN = "https://gitcode.com/mcpp-res/wayland/releases/download/1.26.0/wayland-1.26.0-mcpp2.tar.gz",
},
sha256 = "961a900dafe76e713c2e46d9a064ff3a6375622f4057013472a04c44d8bcb6e8",
sha256 = "bcf388cc1dd6617fdce5cb595defbe2aa1fae8db292ca5d7fd84afda2811be32",
},
},
},
Expand Down
31 changes: 31 additions & 0 deletions tests/examples/wayland-egl/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# wayland-egl test member — the client-side GPU path.
#
# Its own `[indices]`, for the reason the sibling wayland member documents: the
# workspace root maps `compat` to this checkout and lookup is BY NAMESPACE, so
# `freedesktop.*` would otherwise resolve against the published index instead of
# the packages under test.
[indices]
freedesktop = { path = "../../.." }

[package]
name = "wayland-egl-tests"
version = "0.1.0"
standard = "c++23"

# ONE package named, and libwayland-client arrives with it.
#
# `freedesktop.wayland-egl`'s own manifest declares `freedesktop.wayland` as a
# PATH dependency — the two are workspace members of the same fork — and naming
# it here as a version dependency as well is rejected outright:
#
# error: dependency 'freedesktop.wayland' is requested as both a version
# dep (by 'wayland-egl-tests') and a path dep (by
# 'freedesktop.wayland-egl@1.26.0'). Pick one.
#
# That is the right diagnostic: two spellings of one dependency could resolve
# to two different trees. So the client comes in transitively, which is also
# what a real consumer gets — `wl_egl_window_create` takes a `wl_surface *`
# that only libwayland-client can produce, so the edge exists whether or not
# the consumer names it.
[target.'cfg(linux)'.dependencies.freedesktop]
wayland-egl = "1.26.0"
126 changes: 126 additions & 0 deletions tests/examples/wayland-egl/tests/wayland-egl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// freedesktop.wayland-egl — the step that used to be missing.
//
// WHAT THIS CAN AND CANNOT ASSERT, decided by what the library actually is.
//
// libwayland-egl is 118 lines and holds no connection: `wl_egl_window_create`
// allocates a struct, stores the `wl_surface *` it was handed, and records a
// size. It calls no client function and talks to no compositor — an EGL
// implementation later reads and writes the struct through
// `wayland-egl-backend.h`.
//
// So a CI runner with no compositor can exercise the whole library honestly.
// What it cannot do is `eglCreateWindowSurface`, which needs a real
// `wl_display` from a real compositor — asserting that here would only assert
// that the runner has a desktop session.
//
// THE BACKEND HEADER IS INCLUDED ON PURPOSE. `wayland-egl-core.h` exposes four
// functions and an opaque type, so through it alone the only observable is
// "create returned non-null". `wayland-egl-backend.h` is the contract this
// library has with an EGL implementation — Mesa includes it — and reading the
// struct through it is what lets the test check that create and resize wrote
// what they claim.
//
// The `wl_surface *` is a null pointer ON PURPOSE: upstream stores it without
// dereferencing (wayland-egl.c:93), so this exercises the real path, and the
// test can then assert the pointer round-tripped.

#ifdef __linux__

#include <wayland-client.h>
#include <wayland-egl.h>
#include <wayland-egl-backend.h>

#include <cstdio>
#include <cstring>

import freedesktop.wayland.egl;

namespace {

int failures = 0;

void check(bool ok, const char *what)
{
std::printf("%-58s %s\n", what, ok ? "ok" : "FAILED");
if (!ok) {
++failures;
}
}

} // namespace

int main()
{
// ── 1. The module carries the API ────────────────────────────────────
// Taking the address of each is what makes this a check rather than a
// comment: a name that vanished from the module is a compile error here,
// which is the guarantee genmod.py gives the client and server wrappers
// and that this hand-written module needs by other means.
check(&wl_egl_window_create != nullptr, "module exports wl_egl_window_create");
check(&wl_egl_window_destroy != nullptr, "module exports wl_egl_window_destroy");
check(&wl_egl_window_resize != nullptr, "module exports wl_egl_window_resize");
check(&wl_egl_window_get_attached_size != nullptr, "module exports wl_egl_window_get_attached_size");

// ── 2. The bridge itself ─────────────────────────────────────────────
// This is the call that did not exist in this ecosystem before: the only
// way to turn a wl_surface into something EGL can render into.
wl_egl_window *w = wl_egl_window_create(nullptr, 640, 480);
check(w != nullptr, "wl_egl_window_create(surface, 640, 480)");
if (w == nullptr) {
std::printf("\n%d check(s) failed\n", failures);
return 1;
}

// ── 3. It wrote what it was given ────────────────────────────────────
// Read back through the backend header, which is how Mesa reads it.
// `version` matters most of the three: an EGL implementation switches on
// it, and it is the field upstream casts away constness to set.
std::printf(" version=%ld size=%d x %d\n",
(long)w->version, w->width, w->height);
check(w->version == WL_EGL_WINDOW_VERSION, "…and stamped WL_EGL_WINDOW_VERSION");
check(w->width == 640 && w->height == 480, "…and recorded 640 x 480");
check(w->surface == nullptr, "…and round-tripped the wl_surface pointer");

// ── 4. attached size is 0 BEFORE any EGL implementation attaches ─────
// Not an oversight and not the creation size: `attached_width/height` are
// written by the EGL side when it attaches a buffer, and `create` calloc's
// them to zero. The first version of this test asserted 640 x 480 here and
// was wrong — the check now encodes the real contract, which is that a
// window nothing has rendered into reports nothing attached.
int aw = -1, ah = -1;
wl_egl_window_get_attached_size(w, &aw, &ah);
std::printf(" attached size before any EGL attach: %d x %d\n", aw, ah);
check(aw == 0 && ah == 0, "get_attached_size reports 0 x 0 until EGL attaches");

// ── 5. Resize is what a client calls on every configure event ────────
wl_egl_window_resize(w, 800, 600, 0, 0);
check(w->width == 800 && w->height == 600, "wl_egl_window_resize updated the geometry");

// A rejected resize, which is a real branch: upstream returns early on a
// non-positive dimension rather than storing it, so the previous size must
// survive. Same guard `create` uses.
wl_egl_window_resize(w, 0, 600, 0, 0);
check(w->width == 800 && w->height == 600, "…and a width of 0 is refused, not stored");

wl_egl_window_destroy(w);
check(true, "wl_egl_window_destroy");

// ── 6. create rejects a degenerate size ──────────────────────────────
check(wl_egl_window_create(nullptr, 0, 480) == nullptr,
"wl_egl_window_create refuses a width of 0");

// ── 7. The two halves agree on the linkage they share ────────────────
// `wl_display_connect` comes from libwayland-client and is NOT in
// libwayland-egl — the fork's CI asserts that separation on the library,
// and this asserts the consumer side: both are reachable from one program,
// which is the arrangement a real client is in.
check(&wl_display_connect != nullptr,
"libwayland-client is in the same program (wl_display_connect)");

std::printf("\n%d check(s) failed\n", failures);
return failures == 0 ? 0 : 1;
}

#else
int main() { return 0; }
#endif
Loading