main f2d166b

devices.go RawHistoryFolder

1package ports
2
3import (
4	"errors"
5	"fmt"
6	"image"
7	"os"
8	"time"
9)
10
11// MaxCaptureInflight bounds the capture requests admitted but not yet
12// answered, across outputs. The reply channel of the production app has
13// at least this capacity, so an output never blocks on a reply.
14const MaxCaptureInflight = 32
15
16// ErrCaptureTransient marks a capture failure that may clear on its own (the
17// renderer busy, the indicator or an exclusion not shown yet): a protocol
18// frame tries again shortly instead of failing. Test with errors.Is.
19var ErrCaptureTransient = errors.New("capture: transient")
20
21// ErrCaptureBusy: every capture slot of the renderer is leased.
22var ErrCaptureBusy = fmt.Errorf("%w: no free slot", ErrCaptureTransient)
23
24// CaptureFrame is a lease on one renderer readback slot holding a GPU
25// copy of a rendered frame. Done and Read make no Vulkan call: a worker
26// goroutine waits on Done, then reads. EndCapture returns the lease.
27type CaptureFrame interface {
28	// Done is the sync file signalled when the copy finished; nil means it
29	// had finished when BeginCapture returned. The frame owns it: it stays
30	// valid until EndCapture, and the reader must not close it.
31	Done() *os.File
32	// Read copies region (output pixels) as opaque sRGB8 BGRA rows into
33	// dst, stride bytes per row. Valid after Done signalled and before
34	// EndCapture.
35	Read(region image.Rectangle, dst []byte, stride int) error
36}
37
38// Renderer draws scenes for an output. One goroutine owns it. Frames go
39// to its own image until ExportTargets or ImportTargets gives it scanout
40// images; then each Render draws into the target chosen by UseTarget
41// (ADR 014: no CPU pass).
42type Renderer interface {
43	// SetHDR selects the HDR10 output transform (0 disables it).
44	// The DRM output calls this before ExportTargets or ImportTargets.
45	SetHDR(sdrNits float64)
46	// Render draws the scene. done is a sync file signalled when the GPU
47	// finished the frame (nil: already finished); the caller closes it.
48	Render(Scene, map[WindowID]SurfaceContent) (done *os.File, err error)
49	// ExportTargets allocates n images of the renderer's size that the
50	// display can scan out, with one of the given XRGB8888 (SDR) or
51	// XRGB2101010 (HDR) modifiers (none: any the device exports),
52	// and returns them as dmabufs; a modifier may have several memory
53	// planes (DCC metadata), each plane owning its file. singlePlane
54	// restricts the choice to one-plane modifiers.
55	// n = 0 drops the targets.
56	ExportTargets(n int, modifiers []uint64, singlePlane bool) ([]DMABuf, error)
57	// TargetModifiers lists the modifiers an image allocated outside the
58	// renderer (by the display's allocator) can have to be imported as a
59	// target: those the device renders into and imports for the XRGB8888
60	// (SDR) or XRGB2101010 (HDR) format, that the display lists (empty: any),
61	// without multi-plane ones when singlePlane. Empty when the device
62	// cannot import dmabufs.
63	TargetModifiers(display []uint64, singlePlane bool) []uint64
64	// ImportTargets makes images allocated outside the renderer its
65	// targets, replacing the previous ones (no buffers: drops them). Each
66	// is one memory object of the renderer's size and target format, with
67	// a modifier from TargetModifiers: every plane file is the same
68	// dmabuf (the planes differ by offset), and disjoint planes are
69	// refused. The caller keeps its files and must keep the memory alive
70	// while the targets are in use. An error leaves the renderer without
71	// targets.
72	ImportTargets(bufs []DMABuf) error
73	// UseTarget selects the exported image the next Render draws into.
74	UseTarget(i int)
75	// CursorBuffers allocates two linear ARGB8888 images of size×size the
76	// display can show on its cursor plane, and returns them as dmabufs.
77	CursorBuffers(size int) ([2]DMABuf, error)
78	// WriteCursor fills cursor image i with premultiplied ARGB8888 pixels
79	// (w×h, w*4 per row), cropped to the image and cleared around it.
80	WriteCursor(i int, pixels []byte, w, h int) error
81	// Pixels reads the last frame back (headless screenshots, tests). It
82	// waits for the GPU: debug only. Nil when it cannot (every capture
83	// slot leased, or the copy failed).
84	Pixels() *image.RGBA
85	// HDRPixels reads the last HDR frame's XRGB2101010 target back, each
86	// 10-bit code scaled to 16 bits (c<<6 | c>>4), A = 0xffff. It waits for
87	// the GPU: debug only. Nil when the output is SDR, the target is not
88	// readable, a slot is busy or the copy failed.
89	HDRPixels() *image.RGBA64
90	// BeginCapture submits a GPU copy of the last rendered frame into a
91	// free slot and returns without waiting. ErrCaptureBusy when every
92	// slot is leased; another error when the copy cannot be tracked (no
93	// sync file): the caller fails the request.
94	BeginCapture() (CaptureFrame, error)
95	// EndCapture returns a lease. It never waits: a slot whose copy may
96	// still run is reused only once the renderer sees it finished.
97	EndCapture(CaptureFrame)
98	// Trim frees client buffer caches left undrawn for a while and what
99	// finished frames held, without rendering. Outputs call it
100	// periodically: an idle output renders no frame to free them.
101	Trim(now time.Time) error
102	// TakeRedrawn returns the target pixels drawn since the last call
103	// (damage-limited frames count their damage only) and starts over.
104	TakeRedrawn() int
105	Close()
106}
107
108// Seat is the device broker (libseat) input devices are opened through.
109type Seat interface {
110	OpenDevice(path string) (int, error)
111	CloseDevice(fd int)
112	SwitchVT(vt int)
113}

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