test(wayland): reuse the surface mapper and shm buffer in the damage log test
TestClientDamageLog built its own xdg surface and wl_shm pool. It now maps a window with surfaceMapper (new surfaceMapperAt binds wl_compositor at a given version, since damage_buffer needs 4) and takes a 16x16 buffer from shmBuffer's new sized variant. The LogDamage on/off loop is split into subtests. The mapping commit now logs one extra damage entry that the test skips.
- commit
- ffe1c25ef556c532a464751bd6d5533736fa6519
- author
- brice · · 2026-10-14 03:43 UTC
- committer
- brice · · 2026-10-14 04:34 UTC
- parent
- fa55dc9
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +70 -87
M internal/adapters/wayland/damage_log_test.go +54 -82
| @@ -1,105 +1,77 @@ | |||
| 1 | 1 | package wayland | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "fmt" | |
| 4 | 5 | "strings" | |
| 5 | 6 | "testing" | |
| 6 | 7 | "time" | |
| 7 | 8 | ||
| 8 | 9 | "github.com/bnema/go-wayland-bindings/server/wayland" | |
| 9 | - | "github.com/bnema/go-wayland-bindings/server/xdgshell" | |
| 10 | 10 | "github.com/bnema/zerowrap" | |
| 11 | - | "golang.org/x/sys/unix" | |
| 12 | 11 | ) | |
| 13 | 12 | ||
| 14 | 13 | // --debug=wayland-damage logs one "client damage" entry per fresh commit | |
| 15 | 14 | // with the damage in buffer pixels; without it nothing is logged. | |
| 16 | 15 | func TestClientDamageLog(t *testing.T) { | |
| 17 | 16 | for _, on := range []bool{true, false} { | |
| 18 | - | var out lockedBuffer | |
| 19 | - | log := zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: &out}).WithField("component", "wayland") | |
| 20 | - | s, events, _, contents, dir := contentServerWith(t, Options{LogDamage: on}, log) | |
| 21 | - | c := protocolClient(t, s, dir) | |
| 22 | - | comp := bindVersion(t, c, "wl_compositor", 4) | |
| 23 | - | wm := bindProtocol(t, c, "xdg_wm_base") | |
| 24 | - | shm := bindProtocol(t, c, "wl_shm") | |
| 25 | - | registerProtocol(t, c, shm) | |
| 26 | - | surf, xdg, top := c.AllocateID(), c.AllocateID(), c.AllocateID() | |
| 27 | - | requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf) | |
| 28 | - | registerProtocol(t, c, surf) | |
| 29 | - | requestProtocol(t, c, wm, xdgshell.WmBaseRequestGetXdgSurface, xdg, surf) | |
| 30 | - | serials := make(chan uint32, 8) | |
| 31 | - | xp := &configureProxy{serial: serials} | |
| 32 | - | xp.SetID(xdg) | |
| 33 | - | registerWireProxy(c, xp) | |
| 34 | - | registerProtocol(t, c, top) | |
| 35 | - | requestProtocol(t, c, xdg, xdgshell.SurfaceRequestGetToplevel, top) | |
| 36 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) | |
| 37 | - | if err := c.Roundtrip(); err != nil { | |
| 38 | - | t.Fatal(err) | |
| 39 | - | } | |
| 40 | - | requestProtocol(t, c, xdg, xdgshell.SurfaceRequestAckConfigure, <-serials) | |
| 41 | - | fd, err := unix.MemfdCreate("damagelog", 0) | |
| 42 | - | if err != nil { | |
| 43 | - | t.Fatal(err) | |
| 44 | - | } | |
| 45 | - | defer unix.Close(fd) | |
| 46 | - | if err := unix.Ftruncate(fd, 16*16*4); err != nil { | |
| 47 | - | t.Fatal(err) | |
| 48 | - | } | |
| 49 | - | pool, buf := c.AllocateID(), c.AllocateID() | |
| 50 | - | registerProtocol(t, c, pool) | |
| 51 | - | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, int32(16*16*4)); err != nil { | |
| 52 | - | t.Fatal(err) | |
| 53 | - | } | |
| 54 | - | registerProtocol(t, c, buf) | |
| 55 | - | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buf, int32(0), int32(16), int32(16), int32(64), uint32(0)) | |
| 56 | - | commit := func(rects ...[4]int32) { | |
| 57 | - | t.Helper() | |
| 58 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestAttach, buf, int32(0), int32(0)) | |
| 59 | - | for _, r := range rects { | |
| 60 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestDamageBuffer, r[0], r[1], r[2], r[3]) | |
| 17 | + | t.Run(fmt.Sprintf("LogDamage=%v", on), func(t *testing.T) { | |
| 18 | + | var out lockedBuffer | |
| 19 | + | log := zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: &out}).WithField("component", "wayland") | |
| 20 | + | s, events, _, contents, dir := contentServerWith(t, Options{LogDamage: on}, log) | |
| 21 | + | c := protocolClient(t, s, dir) | |
| 22 | + | // A mapped window (its 1×1 first buffer is not under test), then | |
| 23 | + | // the 16×16 buffer the commits below attach. | |
| 24 | + | _, surf, _ := surfaceMapperAt(t, c, events, 4)() | |
| 25 | + | drainContents(contents) | |
| 26 | + | buf := shmBufferSized(t, c, 16, 16) | |
| 27 | + | commit := func(rects ...[4]int32) { | |
| 28 | + | t.Helper() | |
| 29 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestAttach, buf, int32(0), int32(0)) | |
| 30 | + | for _, r := range rects { | |
| 31 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestDamageBuffer, r[0], r[1], r[2], r[3]) | |
| 32 | + | } | |
| 33 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) | |
| 34 | + | if err := c.Roundtrip(); err != nil { | |
| 35 | + | t.Fatal(err) | |
| 36 | + | } | |
| 37 | + | select { | |
| 38 | + | case <-contents: | |
| 39 | + | case <-time.After(2 * time.Second): | |
| 40 | + | t.Fatal("no content") | |
| 41 | + | } | |
| 61 | 42 | } | |
| 62 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) | |
| 63 | - | if err := c.Roundtrip(); err != nil { | |
| 64 | - | t.Fatal(err) | |
| 43 | + | // First buffer: a new size, full. Then a small rect, then one | |
| 44 | + | // covering the whole buffer. | |
| 45 | + | commit([4]int32{0, 0, 4, 4}) | |
| 46 | + | commit([4]int32{2, 3, 4, 5}) | |
| 47 | + | commit([4]int32{0, 0, 16, 16}) | |
| 48 | + | var damage []string | |
| 49 | + | for _, l := range strings.Split(strings.TrimSpace(out.String()), "\n") { | |
| 50 | + | if strings.Contains(l, `"client damage"`) { | |
| 51 | + | damage = append(damage, l) | |
| 52 | + | } | |
| 65 | 53 | } | |
| 66 | - | select { | |
| 67 | - | case <-contents: | |
| 68 | - | case <-time.After(2 * time.Second): | |
| 69 | - | t.Fatal("no content") | |
| 54 | + | if !on { | |
| 55 | + | if len(damage) != 0 { | |
| 56 | + | t.Fatalf("logged with LogDamage off: %q", damage) | |
| 57 | + | } | |
| 58 | + | return | |
| 70 | 59 | } | |
| 71 | - | } | |
| 72 | - | // First buffer: a new size, full. Then a small rect, then one | |
| 73 | - | // covering the whole buffer. | |
| 74 | - | commit([4]int32{0, 0, 4, 4}) | |
| 75 | - | mapped(t, events, 2*time.Second) | |
| 76 | - | commit([4]int32{2, 3, 4, 5}) | |
| 77 | - | commit([4]int32{0, 0, 16, 16}) | |
| 78 | - | lines := strings.Split(strings.TrimSpace(out.String()), "\n") | |
| 79 | - | var damage []string | |
| 80 | - | for _, l := range lines { | |
| 81 | - | if strings.Contains(l, `"client damage"`) { | |
| 82 | - | damage = append(damage, l) | |
| 60 | + | // The mapping commit logged one entry of its own. | |
| 61 | + | if len(damage) != 4 { | |
| 62 | + | t.Fatalf("%d client damage entries, want 4 (mapping commit and 3 commits): %q", len(damage), damage) | |
| 83 | 63 | } | |
| 84 | - | } | |
| 85 | - | if !on { | |
| 86 | - | if len(damage) != 0 { | |
| 87 | - | t.Fatalf("logged with LogDamage off: %q", damage) | |
| 64 | + | damage = damage[1:] | |
| 65 | + | for i, want := range []string{`"full_buffer":true`, `"full_buffer":false`, `"full_buffer":true`} { | |
| 66 | + | if !strings.Contains(damage[i], want) { | |
| 67 | + | t.Errorf("entry %d lacks %s: %s", i, want, damage[i]) | |
| 68 | + | } | |
| 88 | 69 | } | |
| 89 | - | continue | |
| 90 | - | } | |
| 91 | - | if len(damage) != 3 { | |
| 92 | - | t.Fatalf("%d client damage entries, want 3: %q", len(damage), damage) | |
| 93 | - | } | |
| 94 | - | for i, want := range []string{`"full_buffer":true`, `"full_buffer":false`, `"full_buffer":true`} { | |
| 95 | - | if !strings.Contains(damage[i], want) { | |
| 96 | - | t.Errorf("entry %d lacks %s: %s", i, want, damage[i]) | |
| 70 | + | for _, want := range []string{`"component":"wayland"`, `"bw":16`, `"bh":16`, `"rects":1`, `"window":`, `"first_rects":[{"x":2,"y":3,"w":4,"h":5}]`} { | |
| 71 | + | if !strings.Contains(damage[1], want) { | |
| 72 | + | t.Errorf("entry 1 lacks %s: %s", want, damage[1]) | |
| 73 | + | } | |
| 97 | 74 | } | |
| 98 | - | } | |
| 99 | - | for _, want := range []string{`"component":"wayland"`, `"bw":16`, `"bh":16`, `"rects":1`, `"window":`, `"first_rects":[{"x":2,"y":3,"w":4,"h":5}]`} { | |
| 100 | - | if !strings.Contains(damage[1], want) { | |
| 101 | - | t.Errorf("entry 1 lacks %s: %s", want, damage[1]) | |
| 102 | - | } | |
| 103 | - | } | |
| 75 | + | }) | |
| 104 | 76 | } | |
| 105 | 77 | } | |
| @@ -1,105 +1,77 @@ | |||||
| 1 | package wayland | 1 | package wayland | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "fmt" | |||
| 4 | "strings" | 5 | "strings" | ||
| 5 | "testing" | 6 | "testing" | ||
| 6 | "time" | 7 | "time" | ||
| 7 | 8 | ||||
| 8 | "github.com/bnema/go-wayland-bindings/server/wayland" | 9 | "github.com/bnema/go-wayland-bindings/server/wayland" | ||
| 9 | - | "github.com/bnema/go-wayland-bindings/server/xdgshell" | |||
| 10 | "github.com/bnema/zerowrap" | 10 | "github.com/bnema/zerowrap" | ||
| 11 | - | "golang.org/x/sys/unix" | |||
| 12 | ) | 11 | ) | ||
| 13 | 12 | ||||
| 14 | // --debug=wayland-damage logs one "client damage" entry per fresh commit | 13 | // --debug=wayland-damage logs one "client damage" entry per fresh commit | ||
| 15 | // with the damage in buffer pixels; without it nothing is logged. | 14 | // with the damage in buffer pixels; without it nothing is logged. | ||
| 16 | func TestClientDamageLog(t *testing.T) { | 15 | func TestClientDamageLog(t *testing.T) { | ||
| 17 | for _, on := range []bool{true, false} { | 16 | for _, on := range []bool{true, false} { | ||
| 18 | - | var out lockedBuffer | 17 | + | t.Run(fmt.Sprintf("LogDamage=%v", on), func(t *testing.T) { |
| 19 | - | log := zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: &out}).WithField("component", "wayland") | 18 | + | var out lockedBuffer |
| 20 | - | s, events, _, contents, dir := contentServerWith(t, Options{LogDamage: on}, log) | 19 | + | log := zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: &out}).WithField("component", "wayland") |
| 21 | - | c := protocolClient(t, s, dir) | 20 | + | s, events, _, contents, dir := contentServerWith(t, Options{LogDamage: on}, log) |
| 22 | - | comp := bindVersion(t, c, "wl_compositor", 4) | 21 | + | c := protocolClient(t, s, dir) |
| 23 | - | wm := bindProtocol(t, c, "xdg_wm_base") | 22 | + | // A mapped window (its 1×1 first buffer is not under test), then |
| 24 | - | shm := bindProtocol(t, c, "wl_shm") | 23 | + | // the 16×16 buffer the commits below attach. |
| 25 | - | registerProtocol(t, c, shm) | 24 | + | _, surf, _ := surfaceMapperAt(t, c, events, 4)() |
| 26 | - | surf, xdg, top := c.AllocateID(), c.AllocateID(), c.AllocateID() | 25 | + | drainContents(contents) |
| 27 | - | requestProtocol(t, c, comp, wayland.CompositorRequestCreateSurface, surf) | 26 | + | buf := shmBufferSized(t, c, 16, 16) |
| 28 | - | registerProtocol(t, c, surf) | 27 | + | commit := func(rects ...[4]int32) { |
| 29 | - | requestProtocol(t, c, wm, xdgshell.WmBaseRequestGetXdgSurface, xdg, surf) | 28 | + | t.Helper() |
| 30 | - | serials := make(chan uint32, 8) | 29 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestAttach, buf, int32(0), int32(0)) |
| 31 | - | xp := &configureProxy{serial: serials} | 30 | + | for _, r := range rects { |
| 32 | - | xp.SetID(xdg) | 31 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestDamageBuffer, r[0], r[1], r[2], r[3]) |
| 33 | - | registerWireProxy(c, xp) | 32 | + | } |
| 34 | - | registerProtocol(t, c, top) | 33 | + | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) |
| 35 | - | requestProtocol(t, c, xdg, xdgshell.SurfaceRequestGetToplevel, top) | 34 | + | if err := c.Roundtrip(); err != nil { |
| 36 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) | 35 | + | t.Fatal(err) |
| 37 | - | if err := c.Roundtrip(); err != nil { | 36 | + | } |
| 38 | - | t.Fatal(err) | 37 | + | select { |
| 39 | - | } | 38 | + | case <-contents: |
| 40 | - | requestProtocol(t, c, xdg, xdgshell.SurfaceRequestAckConfigure, <-serials) | 39 | + | case <-time.After(2 * time.Second): |
| 41 | - | fd, err := unix.MemfdCreate("damagelog", 0) | 40 | + | t.Fatal("no content") |
| 42 | - | if err != nil { | 41 | + | } |
| 43 | - | t.Fatal(err) | |||
| 44 | - | } | |||
| 45 | - | defer unix.Close(fd) | |||
| 46 | - | if err := unix.Ftruncate(fd, 16*16*4); err != nil { | |||
| 47 | - | t.Fatal(err) | |||
| 48 | - | } | |||
| 49 | - | pool, buf := c.AllocateID(), c.AllocateID() | |||
| 50 | - | registerProtocol(t, c, pool) | |||
| 51 | - | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, int32(16*16*4)); err != nil { | |||
| 52 | - | t.Fatal(err) | |||
| 53 | - | } | |||
| 54 | - | registerProtocol(t, c, buf) | |||
| 55 | - | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buf, int32(0), int32(16), int32(16), int32(64), uint32(0)) | |||
| 56 | - | commit := func(rects ...[4]int32) { | |||
| 57 | - | t.Helper() | |||
| 58 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestAttach, buf, int32(0), int32(0)) | |||
| 59 | - | for _, r := range rects { | |||
| 60 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestDamageBuffer, r[0], r[1], r[2], r[3]) | |||
| 61 | } | 42 | } | ||
| 62 | - | requestProtocol(t, c, surf, wayland.SurfaceRequestCommit) | 43 | + | // First buffer: a new size, full. Then a small rect, then one |
| 63 | - | if err := c.Roundtrip(); err != nil { | 44 | + | // covering the whole buffer. |
| 64 | - | t.Fatal(err) | 45 | + | commit([4]int32{0, 0, 4, 4}) |
| 46 | + | commit([4]int32{2, 3, 4, 5}) | |||
| 47 | + | commit([4]int32{0, 0, 16, 16}) | |||
| 48 | + | var damage []string | |||
| 49 | + | for _, l := range strings.Split(strings.TrimSpace(out.String()), "\n") { | |||
| 50 | + | if strings.Contains(l, `"client damage"`) { | |||
| 51 | + | damage = append(damage, l) | |||
| 52 | + | } | |||
| 65 | } | 53 | } | ||
| 66 | - | select { | 54 | + | if !on { |
| 67 | - | case <-contents: | 55 | + | if len(damage) != 0 { |
| 68 | - | case <-time.After(2 * time.Second): | 56 | + | t.Fatalf("logged with LogDamage off: %q", damage) |
| 69 | - | t.Fatal("no content") | 57 | + | } |
| 58 | + | return | |||
| 70 | } | 59 | } | ||
| 71 | - | } | 60 | + | // The mapping commit logged one entry of its own. |
| 72 | - | // First buffer: a new size, full. Then a small rect, then one | 61 | + | if len(damage) != 4 { |
| 73 | - | // covering the whole buffer. | 62 | + | t.Fatalf("%d client damage entries, want 4 (mapping commit and 3 commits): %q", len(damage), damage) |
| 74 | - | commit([4]int32{0, 0, 4, 4}) | |||
| 75 | - | mapped(t, events, 2*time.Second) | |||
| 76 | - | commit([4]int32{2, 3, 4, 5}) | |||
| 77 | - | commit([4]int32{0, 0, 16, 16}) | |||
| 78 | - | lines := strings.Split(strings.TrimSpace(out.String()), "\n") | |||
| 79 | - | var damage []string | |||
| 80 | - | for _, l := range lines { | |||
| 81 | - | if strings.Contains(l, `"client damage"`) { | |||
| 82 | - | damage = append(damage, l) | |||
| 83 | } | 63 | } | ||
| 84 | - | } | 64 | + | damage = damage[1:] |
| 85 | - | if !on { | 65 | + | for i, want := range []string{`"full_buffer":true`, `"full_buffer":false`, `"full_buffer":true`} { |
| 86 | - | if len(damage) != 0 { | 66 | + | if !strings.Contains(damage[i], want) { |
| 87 | - | t.Fatalf("logged with LogDamage off: %q", damage) | 67 | + | t.Errorf("entry %d lacks %s: %s", i, want, damage[i]) |
| 68 | + | } | |||
| 88 | } | 69 | } | ||
| 89 | - | continue | 70 | + | for _, want := range []string{`"component":"wayland"`, `"bw":16`, `"bh":16`, `"rects":1`, `"window":`, `"first_rects":[{"x":2,"y":3,"w":4,"h":5}]`} { |
| 90 | - | } | 71 | + | if !strings.Contains(damage[1], want) { |
| 91 | - | if len(damage) != 3 { | 72 | + | t.Errorf("entry 1 lacks %s: %s", want, damage[1]) |
| 92 | - | t.Fatalf("%d client damage entries, want 3: %q", len(damage), damage) | 73 | + | } |
| 93 | - | } | |||
| 94 | - | for i, want := range []string{`"full_buffer":true`, `"full_buffer":false`, `"full_buffer":true`} { | |||
| 95 | - | if !strings.Contains(damage[i], want) { | |||
| 96 | - | t.Errorf("entry %d lacks %s: %s", i, want, damage[i]) | |||
| 97 | } | 74 | } | ||
| 98 | - | } | 75 | + | }) |
| 99 | - | for _, want := range []string{`"component":"wayland"`, `"bw":16`, `"bh":16`, `"rects":1`, `"window":`, `"first_rects":[{"x":2,"y":3,"w":4,"h":5}]`} { | |||
| 100 | - | if !strings.Contains(damage[1], want) { | |||
| 101 | - | t.Errorf("entry 1 lacks %s: %s", want, damage[1]) | |||
| 102 | - | } | |||
| 103 | - | } | |||
| 104 | } | 76 | } | ||
| 105 | } | 77 | } | ||
M internal/adapters/wayland/fifo_test.go +8 -4
| @@ -29,7 +29,10 @@ func nextContent(t *testing.T, contents <-chan ports.SurfaceContent, id ports.Wi | |||
| 29 | 29 | } | |
| 30 | 30 | ||
| 31 | 31 | // shmBuffer creates a 1x1 wl_shm buffer. | |
| 32 | - | func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { | |
| 32 | + | func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { return shmBufferSized(t, c, 1, 1) } | |
| 33 | + | ||
| 34 | + | // shmBufferSized is a w×h ARGB8888 wl_shm buffer. | |
| 35 | + | func shmBufferSized(t *testing.T, c *wlturbo.Display, w, h int32) uint32 { | |
| 33 | 36 | t.Helper() | |
| 34 | 37 | shm := bindProtocol(t, c, "wl_shm") | |
| 35 | 38 | registerProtocol(t, c, shm) | |
| @@ -38,16 +41,17 @@ func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { | |||
| 38 | 41 | t.Fatal(err) | |
| 39 | 42 | } | |
| 40 | 43 | defer unix.Close(fd) | |
| 41 | - | if err := unix.Ftruncate(fd, 4); err != nil { | |
| 44 | + | size := w * h * 4 | |
| 45 | + | if err := unix.Ftruncate(fd, int64(size)); err != nil { | |
| 42 | 46 | t.Fatal(err) | |
| 43 | 47 | } | |
| 44 | 48 | pool, buffer := c.AllocateID(), c.AllocateID() | |
| 45 | 49 | registerProtocol(t, c, pool) | |
| 46 | 50 | registerProtocol(t, c, buffer) | |
| 47 | - | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, int32(4)); err != nil { | |
| 51 | + | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, size); err != nil { | |
| 48 | 52 | t.Fatal(err) | |
| 49 | 53 | } | |
| 50 | - | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buffer, int32(0), int32(1), int32(1), int32(4), uint32(0)) | |
| 54 | + | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buffer, int32(0), w, h, w*4, uint32(0)) | |
| 51 | 55 | return buffer | |
| 52 | 56 | } | |
| 53 | 57 | ||
| @@ -29,7 +29,10 @@ func nextContent(t *testing.T, contents <-chan ports.SurfaceContent, id ports.Wi | |||||
| 29 | } | 29 | } | ||
| 30 | 30 | ||||
| 31 | // shmBuffer creates a 1x1 wl_shm buffer. | 31 | // shmBuffer creates a 1x1 wl_shm buffer. | ||
| 32 | - | func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { | 32 | + | func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { return shmBufferSized(t, c, 1, 1) } |
| 33 | + | ||||
| 34 | + | // shmBufferSized is a w×h ARGB8888 wl_shm buffer. | |||
| 35 | + | func shmBufferSized(t *testing.T, c *wlturbo.Display, w, h int32) uint32 { | |||
| 33 | t.Helper() | 36 | t.Helper() | ||
| 34 | shm := bindProtocol(t, c, "wl_shm") | 37 | shm := bindProtocol(t, c, "wl_shm") | ||
| 35 | registerProtocol(t, c, shm) | 38 | registerProtocol(t, c, shm) | ||
| @@ -38,16 +41,17 @@ func shmBuffer(t *testing.T, c *wlturbo.Display) uint32 { | |||||
| 38 | t.Fatal(err) | 41 | t.Fatal(err) | ||
| 39 | } | 42 | } | ||
| 40 | defer unix.Close(fd) | 43 | defer unix.Close(fd) | ||
| 41 | - | if err := unix.Ftruncate(fd, 4); err != nil { | 44 | + | size := w * h * 4 |
| 45 | + | if err := unix.Ftruncate(fd, int64(size)); err != nil { | |||
| 42 | t.Fatal(err) | 46 | t.Fatal(err) | ||
| 43 | } | 47 | } | ||
| 44 | pool, buffer := c.AllocateID(), c.AllocateID() | 48 | pool, buffer := c.AllocateID(), c.AllocateID() | ||
| 45 | registerProtocol(t, c, pool) | 49 | registerProtocol(t, c, pool) | ||
| 46 | registerProtocol(t, c, buffer) | 50 | registerProtocol(t, c, buffer) | ||
| 47 | - | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, int32(4)); err != nil { | 51 | + | if err := wireRequest(c, shm, uint16(wayland.ShmRequestCreatePool), []int{fd}, pool, size); err != nil { |
| 48 | t.Fatal(err) | 52 | t.Fatal(err) | ||
| 49 | } | 53 | } | ||
| 50 | - | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buffer, int32(0), int32(1), int32(1), int32(4), uint32(0)) | 54 | + | requestProtocol(t, c, pool, wayland.ShmPoolRequestCreateBuffer, buffer, int32(0), w, h, w*4, uint32(0)) |
| 51 | return buffer | 55 | return buffer | ||
| 52 | } | 56 | } | ||
| 53 | 57 | ||||
M internal/adapters/wayland/protocol_test.go +8 -1
| @@ -627,7 +627,14 @@ func toplevelMapper(t *testing.T, c *wlturbo.Display, events <-chan ports.Client | |||
| 627 | 627 | // xdg_surface IDs. | |
| 628 | 628 | func surfaceMapper(t *testing.T, c *wlturbo.Display, events <-chan ports.ClientEvent) func() (ports.WindowMapped, uint32, uint32) { | |
| 629 | 629 | t.Helper() | |
| 630 | - | comp := bindProtocol(t, c, "wl_compositor") | |
| 630 | + | return surfaceMapperAt(t, c, events, 1) | |
| 631 | + | } | |
| 632 | + | ||
| 633 | + | // surfaceMapperAt is surfaceMapper with wl_compositor bound at compositorVersion | |
| 634 | + | // (damage_buffer needs 4). | |
| 635 | + | func surfaceMapperAt(t *testing.T, c *wlturbo.Display, events <-chan ports.ClientEvent, compositorVersion uint32) func() (ports.WindowMapped, uint32, uint32) { | |
| 636 | + | t.Helper() | |
| 637 | + | comp := bindVersion(t, c, "wl_compositor", compositorVersion) | |
| 631 | 638 | wm := bindProtocol(t, c, "xdg_wm_base") | |
| 632 | 639 | shm := bindProtocol(t, c, "wl_shm") | |
| 633 | 640 | registerProtocol(t, c, shm) | |
| @@ -627,7 +627,14 @@ func toplevelMapper(t *testing.T, c *wlturbo.Display, events <-chan ports.Client | |||||
| 627 | // xdg_surface IDs. | 627 | // xdg_surface IDs. | ||
| 628 | func surfaceMapper(t *testing.T, c *wlturbo.Display, events <-chan ports.ClientEvent) func() (ports.WindowMapped, uint32, uint32) { | 628 | func surfaceMapper(t *testing.T, c *wlturbo.Display, events <-chan ports.ClientEvent) func() (ports.WindowMapped, uint32, uint32) { | ||
| 629 | t.Helper() | 629 | t.Helper() | ||
| 630 | - | comp := bindProtocol(t, c, "wl_compositor") | 630 | + | return surfaceMapperAt(t, c, events, 1) |
| 631 | + | } | |||
| 632 | + | ||||
| 633 | + | // surfaceMapperAt is surfaceMapper with wl_compositor bound at compositorVersion | |||
| 634 | + | // (damage_buffer needs 4). | |||
| 635 | + | func surfaceMapperAt(t *testing.T, c *wlturbo.Display, events <-chan ports.ClientEvent, compositorVersion uint32) func() (ports.WindowMapped, uint32, uint32) { | |||
| 636 | + | t.Helper() | |||
| 637 | + | comp := bindVersion(t, c, "wl_compositor", compositorVersion) | |||
| 631 | wm := bindProtocol(t, c, "xdg_wm_base") | 638 | wm := bindProtocol(t, c, "xdg_wm_base") | ||
| 632 | shm := bindProtocol(t, c, "wl_shm") | 639 | shm := bindProtocol(t, c, "wl_shm") | ||
| 633 | registerProtocol(t, c, shm) | 640 | registerProtocol(t, c, shm) | ||