Cut the comments back to the genuinely subtle ones
This commit is contained in:
+12
-23
@@ -11,12 +11,10 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// cabletest drives the panel through drm and page flips between two scanout
|
||||
// buffers of its own, so /dev/fb0 holds the kernel console and there is nothing
|
||||
// in it worth reading. The buffer being displayed is reachable from out here
|
||||
// though: GETCRTC names it, and root is allowed a handle to it without being
|
||||
// drm master, so it can be mapped and read without the program that owns it
|
||||
// having to cooperate or even notice.
|
||||
// cabletest drives the panel through drm, so /dev/fb0 holds the kernel console
|
||||
// and is not worth reading. The displayed buffer is reachable from out here
|
||||
// instead: GETCRTC names it, and root is allowed a handle to it without being
|
||||
// drm master, so it can be read without the owning process cooperating.
|
||||
const (
|
||||
drmCardGlob = "/dev/dri/card*"
|
||||
|
||||
@@ -95,8 +93,6 @@ type grabber struct {
|
||||
index int
|
||||
}
|
||||
|
||||
// The card and crtc actually putting something on a display, which is whichever
|
||||
// one cabletest chose when it set its mode.
|
||||
func openGrabber() (*grabber, error) {
|
||||
paths, err := filepath.Glob(drmCardGlob)
|
||||
if err != nil {
|
||||
@@ -145,11 +141,9 @@ func activeCrtc(fd int) (uint32, int, error) {
|
||||
|
||||
func (g *grabber) close() { unix.Close(g.fd) }
|
||||
|
||||
// Reading the buffer takes about as long as a frame, so where the read starts
|
||||
// in the flip cycle is what decides whether it stays ahead of the writer. Woken
|
||||
// at a blank, the buffer named next has just gone on screen, which leaves a
|
||||
// whole frame plus however long cabletest spends drawing before anything
|
||||
// touches it again.
|
||||
// Reading a buffer takes about as long as a frame, so where the read starts in
|
||||
// the flip cycle decides whether it stays ahead of the writer. Woken at a
|
||||
// blank, the buffer GETCRTC then names has just gone on screen.
|
||||
func (g *grabber) waitVblank() error {
|
||||
v := drmWaitVblank{
|
||||
typ: drmVblankRelative | uint32(g.index<<drmVblankHighCrtcShft)&drmVblankHighCrtcMask,
|
||||
@@ -164,8 +158,6 @@ func (g *grabber) waitVblank() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Maps whichever buffer is on screen right now. The caller is expected to have
|
||||
// just woken at a blank, so this is the one with the longest life ahead of it.
|
||||
func (g *grabber) mapFront() (mem []byte, pitch, pw, ph int, err error) {
|
||||
c := drmModeCrtc{crtcID: g.crtc}
|
||||
if err := drmIoctl(g.fd, drmGetCrtc, unsafe.Pointer(&c)); err != nil {
|
||||
@@ -200,14 +192,11 @@ func (g *grabber) mapFront() (mem []byte, pitch, pw, ph int, err error) {
|
||||
return mem, pitch, pw, ph, nil
|
||||
}
|
||||
|
||||
// Scanout memory is uncached, so reading a frame out of it costs a good
|
||||
// fraction of a frame's time and could in principle be overtaken by the next
|
||||
// redraw. Rather than trust that it was not, the buffer is read twice and the
|
||||
// pair only accepted if they agree: the writer cycles through its buffers in
|
||||
// order and leaves this one alone for several frames after putting it on
|
||||
// screen, which is comfortably long enough for both reads. Disagreement means
|
||||
// that reasoning is wrong somewhere, which is worth hearing about rather than
|
||||
// papering over with another go.
|
||||
// Scanout memory is uncached, so a read costs a good fraction of a frame and
|
||||
// could be overtaken by the next redraw. Read twice and accept only if the two
|
||||
// agree: the writer leaves a buffer alone for several frames after displaying
|
||||
// it, which is long enough for both. Disagreement means that reasoning is
|
||||
// wrong, which is worth hearing about rather than retrying past.
|
||||
func (g *grabber) frame() (*image.NRGBA, error) {
|
||||
if err := g.waitVblank(); err != nil {
|
||||
return nil, fmt.Errorf("wait for vblank: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user