devices.go RawHistoryFolder
1package ports
2
3import (
4 "errors"
5 "image"
6 "os"
7 "time"
8)
9
10// MaxCaptureInflight bounds the capture requests admitted but not yet
11// answered, across outputs. The reply channel of the production app has
12// at least this capacity, so an output never blocks on a reply.
13const MaxCaptureInflight = 32
14
15// ErrCaptureBusy: every capture slot of the renderer is leased.
16var ErrCaptureBusy = errors.New("capture: no free slot")
17
18// CaptureFrame is a lease on one renderer readback slot holding a GPU
19// copy of a rendered frame. Done and Read make no Vulkan call: a worker
20// goroutine waits on Done, then reads. EndCapture returns the lease.
21type CaptureFrame interface {
22 // Done is the sync file signalled when the copy finished; nil means it
23 // had finished when BeginCapture returned. The frame owns it.
24 Done() *os.File
25 // Read copies region (output pixels) as opaque sRGB8 BGRA rows into
26 // dst, stride bytes per row. Valid after Done signalled and before
27 // EndCapture.
28 Read(region image.Rectangle, dst []byte, stride int) error
29}
30
31// Renderer draws scenes for an output. One goroutine owns it. Frames go
32// to its own image until ExportTargets gives it scanout images; then each
33// Render draws into the target chosen by UseTarget (ADR 014: no CPU pass).
34type Renderer interface {
35 // SetHDR selects the HDR10 output transform (0 disables it).
36 // The DRM output calls this before ExportTargets.
37 SetHDR(sdrNits float64)
38 // Render draws the scene. done is a sync file signalled when the GPU
39 // finished the frame (nil: already finished); the caller closes it.
40 Render(Scene, map[WindowID]SurfaceContent) (done *os.File, err error)
41 // ExportTargets allocates n images of the renderer's size that the
42 // display can scan out, with one of the given XRGB8888 (SDR) or
43 // XRGB2101010 (HDR) modifiers (none: any the device exports),
44 // and returns them as dmabufs.
45 // n = 0 drops the targets.
46 ExportTargets(n int, modifiers []uint64) ([]DMABuf, error)
47 // UseTarget selects the exported image the next Render draws into.
48 UseTarget(i int)
49 // CursorBuffers allocates two linear ARGB8888 images of size×size the
50 // display can show on its cursor plane, and returns them as dmabufs.
51 CursorBuffers(size int) ([2]DMABuf, error)
52 // WriteCursor fills cursor image i with premultiplied ARGB8888 pixels
53 // (w×h, w*4 per row), cropped to the image and cleared around it.
54 WriteCursor(i int, pixels []byte, w, h int) error
55 // Pixels reads the last frame back (headless screenshots, tests). It
56 // waits for the GPU: debug only. Nil when it cannot (every capture
57 // slot leased, or the copy failed).
58 Pixels() *image.RGBA
59 // BeginCapture submits a GPU copy of the last rendered frame into a
60 // free slot and returns without waiting. ErrCaptureBusy when every
61 // slot is leased; another error when the copy cannot be tracked (no
62 // sync file): the caller fails the request.
63 BeginCapture() (CaptureFrame, error)
64 // EndCapture returns a lease. It never waits: a slot whose copy may
65 // still run is reused only once the renderer sees it finished.
66 EndCapture(CaptureFrame)
67 // Trim frees client buffer caches left undrawn for a while and what
68 // finished frames held, without rendering. Outputs call it
69 // periodically: an idle output renders no frame to free them.
70 Trim(now time.Time) error
71 Close()
72}
73
74// Seat is the device broker (libseat) input devices are opened through.
75type Seat interface {
76 OpenDevice(path string) (int, error)
77 CloseDevice(fd int)
78 SwitchVT(vt int)
79}