v0.3.0 cf370a0

syncdev.go RawHistoryFolder

1package wayland
2
3import (
4	"fmt"
5	"os"
6	"runtime"
7	"unsafe"
8
9	"golang.org/x/sys/unix"
10)
11
12// syncobjDevice is the DRM syncobj interface of a render node: explicit
13// sync timelines clients import (wp_linux_drm_syncobj_v1).
14type syncobjDevice interface {
15	// fdToHandle imports a timeline syncobj fd.
16	fdToHandle(fd int) (uint32, error)
17	// exportSyncFile returns a sync file of a timeline point's fence.
18	exportSyncFile(h uint32, point uint64) (*os.File, error)
19	// signal signals a timeline point (a release point).
20	signal(h uint32, point uint64) error
21	// signalled checks a point without blocking.
22	signalled(h uint32, point uint64) (bool, error)
23	// eventfd writes efd once the point is signalled.
24	eventfd(h uint32, point uint64, efd int) error
25	destroy(h uint32) error
26}
27
28const (
29	ioctlSyncobjDestroy        = 0xC00864C0 // DRM_IOWR(0xC0, struct drm_syncobj_destroy)
30	ioctlSyncobjHandleToFD     = 0xC01864C1 // DRM_IOWR(0xC1, struct drm_syncobj_handle)
31	ioctlSyncobjFDToHandle     = 0xC01864C2 // DRM_IOWR(0xC2, struct drm_syncobj_handle)
32	ioctlSyncobjTimelineWait   = 0xC02864CA // DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
33	ioctlSyncobjTimelineSignal = 0xC01864CD // DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
34	ioctlSyncobjEventfd        = 0xC01864CF // DRM_IOWR(0xCF, struct drm_syncobj_eventfd)
35	ioctlGetCap                = 0xC010640C // DRM_IOWR(0x0C, struct drm_get_cap)
36
37	syncobjExportSyncFile = 1 << 0
38	syncobjTimeline       = 1 << 1
39	capSyncobjTimeline    = 0x14
40)
41
42type syncobjHandle struct {
43	handle, flags uint32
44	fd            int32
45	pad           uint32
46	point         uint64
47}
48
49type syncobjDestroy struct{ handle, pad uint32 }
50
51type syncobjTimelineArray struct {
52	handles, points uint64
53	count, flags    uint32
54}
55
56type syncobjTimelineWait struct {
57	handles, points uint64
58	timeout         int64
59	count, flags    uint32
60	first           uint32
61	pad             uint32
62}
63
64type syncobjEventfd struct {
65	handle, flags uint32
66	point         uint64
67	fd            int32
68	pad           uint32
69}
70
71type drmCap struct{ capability, value uint64 }
72
73// renderNode is a DRM render node opened for syncobj ioctls.
74type renderNode struct{ fd int }
75
76// openSyncobj opens a render node that supports timeline syncobjs.
77func openSyncobj(path string) (*renderNode, error) {
78	fd, err := unix.Open(path, unix.O_RDWR|unix.O_CLOEXEC, 0)
79	if err != nil {
80		return nil, err
81	}
82	c := drmCap{capability: capSyncobjTimeline}
83	if ioctl(fd, ioctlGetCap, unsafe.Pointer(&c)) != nil || c.value == 0 {
84		unix.Close(fd)
85		return nil, fmt.Errorf("%s: no timeline syncobjs", path)
86	}
87	return &renderNode{fd: fd}, nil
88}
89
90func (n *renderNode) close() { unix.Close(n.fd) }
91
92func ioctl(fd int, req uintptr, arg unsafe.Pointer) error {
93	for {
94		_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), req, uintptr(arg))
95		if errno == unix.EINTR || errno == unix.EAGAIN {
96			continue
97		}
98		if errno != 0 {
99			return errno
100		}
101		return nil
102	}
103}
104
105func (n *renderNode) fdToHandle(fd int) (uint32, error) {
106	a := syncobjHandle{fd: int32(fd)}
107	if err := ioctl(n.fd, ioctlSyncobjFDToHandle, unsafe.Pointer(&a)); err != nil {
108		return 0, err
109	}
110	return a.handle, nil
111}
112
113func (n *renderNode) exportSyncFile(h uint32, point uint64) (*os.File, error) {
114	a := syncobjHandle{handle: h, flags: syncobjExportSyncFile | syncobjTimeline, fd: -1, point: point}
115	if err := ioctl(n.fd, ioctlSyncobjHandleToFD, unsafe.Pointer(&a)); err != nil {
116		return nil, err
117	}
118	return os.NewFile(uintptr(a.fd), "acquire-fence"), nil
119}
120
121func (n *renderNode) signal(h uint32, point uint64) error {
122	handles, points := [1]uint32{h}, [1]uint64{point}
123	a := syncobjTimelineArray{handles: uint64(uintptr(unsafe.Pointer(&handles))), points: uint64(uintptr(unsafe.Pointer(&points))), count: 1}
124	err := ioctl(n.fd, ioctlSyncobjTimelineSignal, unsafe.Pointer(&a))
125	runtime.KeepAlive(&handles)
126	runtime.KeepAlive(&points)
127	return err
128}
129
130func (n *renderNode) signalled(h uint32, point uint64) (bool, error) {
131	handles, points := [1]uint32{h}, [1]uint64{point}
132	a := syncobjTimelineWait{handles: uint64(uintptr(unsafe.Pointer(&handles))), points: uint64(uintptr(unsafe.Pointer(&points))), count: 1}
133	err := ioctl(n.fd, ioctlSyncobjTimelineWait, unsafe.Pointer(&a))
134	runtime.KeepAlive(&handles)
135	runtime.KeepAlive(&points)
136	if err == unix.ETIME {
137		return false, nil
138	}
139	return err == nil, err
140}
141
142func (n *renderNode) eventfd(h uint32, point uint64, efd int) error {
143	a := syncobjEventfd{handle: h, point: point, fd: int32(efd)}
144	return ioctl(n.fd, ioctlSyncobjEventfd, unsafe.Pointer(&a))
145}
146
147func (n *renderNode) destroy(h uint32) error {
148	a := syncobjDestroy{handle: h}
149	return ioctl(n.fd, ioctlSyncobjDestroy, unsafe.Pointer(&a))
150}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 25

Tags 10

↑↓ moveenter openesc close