1package vulkan
2
3import (
4 "testing"
5 "unsafe"
6)
7
8// Cursor images are packed (pitch = size*4), exported, and WriteCursor
9// crops to the image and clears around the pixels.
10func TestCursorBuffersWriteCursor(t *testing.T) {
11 r, err := New(64, 48)
12 if err != nil {
13 t.Skipf("Vulkan unavailable: %v", err)
14 }
15 defer r.Close()
16 bufs, err := r.CursorBuffers(64)
17 if err != nil {
18 t.Skipf("no exportable cursor images: %v", err)
19 }
20 for _, b := range bufs {
21 if p := b.Planes[0]; p.Stride != 64*4 || p.Offset != 0 || b.Format != fourccARGB {
22 t.Fatalf("layout %+v format %#x", p, b.Format)
23 }
24 b.Planes[0].File.Close()
25 }
26 mem := func() []byte { c := r.cursors[1]; return unsafe.Slice((*byte)(c.mapped), c.pitch*c.size) }
27 // A first image fills the corner; a second, smaller one must clear it.
28 big := make([]byte, 100*100*4)
29 for i := range big {
30 big[i] = 0xff
31 }
32 if err := r.WriteCursor(1, big, 100, 100); err != nil { // cropped to 64
33 t.Fatal(err)
34 }
35 if m := mem(); m[63*256+63*4] != 0xff {
36 t.Fatal("cropped image not written")
37 }
38 if err := r.WriteCursor(1, []byte{1, 2, 3, 4}, 1, 1); err != nil {
39 t.Fatal(err)
40 }
41 m := mem()
42 if m[0] != 1 || m[3] != 4 || m[4] != 0 || m[256] != 0 || m[63*256+63*4] != 0 {
43 t.Fatal("image not cleared around the new pixels")
44 }
45 if err := r.WriteCursor(1, []byte{1}, 1, 1); err == nil {
46 t.Fatal("short image accepted")
47 }
48}
49
50func TestHDRCursorCachesConversion(t *testing.T) {
51 r, err := New(32, 16)
52 if err != nil {
53 t.Skipf("Vulkan unavailable: %v", err)
54 }
55 defer r.Close()
56 bufs, err := r.CursorBuffers(64)
57 if err != nil {
58 t.Skipf("no cursor images: %v", err)
59 }
60 for _, b := range bufs {
61 b.Planes[0].File.Close()
62 }
63 r.SetHDR(203)
64 px := []byte{255, 255, 255, 255}
65 if err := r.WriteCursor(0, px, 1, 1); err != nil {
66 t.Fatal(err)
67 }
68 if len(r.cursorCache.pixels) != 4 {
69 t.Fatalf("cache size %d", len(r.cursorCache.pixels))
70 }
71 if err := r.WriteCursor(1, px, 1, 1); err != nil {
72 t.Fatal(err)
73 }
74 if len(r.cursorCache.pixels) != 4 {
75 t.Fatalf("cache grew on reselect: %d", len(r.cursorCache.pixels))
76 }
77 first := r.cursorCache.key
78 for i := 0; i < 12; i++ {
79 color := byte(i * 18)
80 if err := r.WriteCursor(1, []byte{color, color, color, 255}, 1, 1); err != nil {
81 t.Fatal(err)
82 }
83 if len(r.cursorCache.pixels) != 4 {
84 t.Fatalf("cache grew after image %d: %d", i, len(r.cursorCache.pixels))
85 }
86 }
87 if first == r.cursorCache.key {
88 t.Fatal("cursor conversion not replaced")
89 }
90 if err := r.WriteCursor(1, px, 1, 1); err != nil {
91 t.Fatal(err)
92 }
93 for _, c := range r.cursors {
94 got := unsafe.Slice((*byte)(c.mapped), 4)
95 if got[0] != 148 || got[1] != 148 || got[2] != 148 || got[3] != 255 {
96 t.Fatalf("cursor HDR pixel: %v", got)
97 }
98 }
99 r.SetHDR(0)
100 if err := r.WriteCursor(0, px, 1, 1); err != nil {
101 t.Fatal(err)
102 }
103 if got := unsafe.Slice((*byte)(r.cursors[0].mapped), 4); got[0] != 255 || len(r.cursorCache.pixels) != 0 {
104 t.Fatalf("SDR cursor/cache: %v %d", got, len(r.cursorCache.pixels))
105 }
106}