Drive the panel through drm and page flip between four scanout buffers

This commit is contained in:
flamingcow
2026-07-31 16:46:11 -07:00
parent 57d7c91df1
commit 1c5bda37bf
3 changed files with 389 additions and 106 deletions
+12 -13
View File
@@ -602,14 +602,12 @@ func main() {
const (
reportInterval = time.Second
// Redraw fast so the panel feels live, but measure rates over a much longer
// window than a frame, since a frame's worth of a bursty sender is noise.
displayInterval = 16 * time.Millisecond
// What a bucket covers. Deliberately not displayInterval: how often the
// counters are read is a property of the measurement, and tying it to the
// refresh would let a slow or blocked draw stretch the window it reports.
// Short enough that a step lands promptly, long enough that a bucket holds
// tens of thousands of frames at line rate and is not itself noise.
// What a bucket covers. Nothing to do with how often the panel is redrawn:
// how often the counters are read is a property of the measurement, and
// letting the refresh set it would let a slow or blocked draw stretch the
// window it reports. Short enough that a step lands promptly, long enough
// that a bucket holds tens of thousands of frames at line rate and is not
// itself noise.
sampleInterval = 16 * time.Millisecond
// Both how far back the shown errors reach and how many buckets the median
// runs over, so a step in the rate lands half this late.
@@ -778,8 +776,6 @@ func run(aName, bName, sizesArg string,
close(startTx)
tick := time.NewTicker(reportInterval)
defer tick.Stop()
frame := time.NewTicker(displayInterval)
defer frame.Stop()
views := make([]view, len(dirs))
rows := make([]view, len(dirs))
@@ -793,7 +789,8 @@ func run(aName, bName, sizesArg string,
return nil
case <-space:
start = resetAll(dirs, stats)
case now := <-frame.C:
case <-disp.fb.flips:
now := time.Now()
px, py, down := touch.get()
x, y := disp.fb.fromPanel(px, py)
if disp.holdReset(x, y, down, now) {
@@ -806,8 +803,10 @@ func run(aName, bName, sizesArg string,
if m, ok := cfg.cableMetres(views); ok {
cable = fmt.Sprintf("%.1f m", m)
}
disp.render(totalView(views), now.Sub(start),
target*float64(len(dirs)), cable)
if err := disp.render(totalView(views), now.Sub(start),
target*float64(len(dirs)), cable); err != nil {
return err
}
case now := <-tick.C:
elapsed := now.Sub(start)
// Length needs both directions, so every row is sampled before any of