test(drm): cover overlay commit results and probe cache invalidation
Check that finishOverlayCommit turns colour and overlay refusals into errOverlayDropped without queuing the buffer, and that the overlay probe cache is dropped by a colour state change and by client framebuffer removal.
- commit
- d2eadf3a9c6c64c315981048fb3c30ec78e453d6
- author
- brice · · 2026-10-14 08:03 UTC
- parent
- d251ec8
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +43 -0
M internal/adapters/drm/front_test.go +43 -0
| @@ -339,6 +339,36 @@ func TestSubmitFrameOverlayOnlyRefused(t *testing.T) { | |||
| 339 | 339 | } | |
| 340 | 340 | } | |
| 341 | 341 | ||
| 342 | + | // A commit result with the overlay on: refusals the overlay causes ask for a | |
| 343 | + | // frame without it and leave the queue; a commit queues the buffer. | |
| 344 | + | func TestFinishOverlayCommit(t *testing.T) { | |
| 345 | + | boom := errors.New("boom") | |
| 346 | + | for _, tc := range []struct { | |
| 347 | + | name string | |
| 348 | + | err error | |
| 349 | + | want error | |
| 350 | + | wantQueued uint64 | |
| 351 | + | reason string | |
| 352 | + | }{ | |
| 353 | + | {"committed", nil, nil, 9, ""}, | |
| 354 | + | {"colour refused", errColorRefused, errOverlayDropped, 1, "color_refused"}, | |
| 355 | + | {"overlay conflict", unix.EINVAL, errOverlayDropped, 1, "cursor_conflict"}, | |
| 356 | + | {"other", boom, boom, 1, ""}, | |
| 357 | + | } { | |
| 358 | + | t.Run(tc.name, func(t *testing.T) { | |
| 359 | + | o, _, _ := testOutput(t) | |
| 360 | + | o.queued = 1 | |
| 361 | + | o.clientFBs[9] = &clientFB{} | |
| 362 | + | if err := o.finishOverlayCommit(tc.err, 9); err != tc.want { | |
| 363 | + | t.Fatalf("err %v, want %v", err, tc.want) | |
| 364 | + | } | |
| 365 | + | if o.queued != tc.wantQueued || o.overlayReason != tc.reason { | |
| 366 | + | t.Fatalf("queued %d reason %q", o.queued, o.overlayReason) | |
| 367 | + | } | |
| 368 | + | }) | |
| 369 | + | } | |
| 370 | + | } | |
| 371 | + | ||
| 342 | 372 | // A frame whose buffer KMS took before is not probed again. | |
| 343 | 373 | func TestOverlayProbeCached(t *testing.T) { | |
| 344 | 374 | o, k, commits := overlayOutput(t) | |
| @@ -370,6 +400,19 @@ func TestOverlayProbeCached(t *testing.T) { | |||
| 370 | 400 | if v, _ := (*commits)[3].req.value(tCursor, 14); v != 20-uint64(o.cursor.hotX) { | |
| 371 | 401 | t.Fatalf("probe cursor x %d", v) | |
| 372 | 402 | } | |
| 403 | + | // New colour state (HDR brightness) is probed again. | |
| 404 | + | o.colorMult++ | |
| 405 | + | o.testOverlay(70, ov) | |
| 406 | + | if len(*commits) != 5 { | |
| 407 | + | t.Fatalf("%d probes after a colour change, want 5", len(*commits)) | |
| 408 | + | } | |
| 409 | + | // A removed client framebuffer may give its id to another buffer. | |
| 410 | + | k.EXPECT().rmFB(uint32(88)).Return(nil).Once() | |
| 411 | + | o.dropClientFBs(time.Now(), true) | |
| 412 | + | o.testOverlay(70, ov) | |
| 413 | + | if len(*commits) != 6 { | |
| 414 | + | t.Fatal("probe cached across a framebuffer removal") | |
| 415 | + | } | |
| 373 | 416 | // A modeset (VT resume) forgets them. | |
| 374 | 417 | k.EXPECT().createBlob(mock.Anything).Return(99, nil).Once() | |
| 375 | 418 | k.EXPECT().objProps(uint32(tOverlay), uint32(objPlane)).Return(map[string][2]uint64{}, nil).Maybe() | |
| @@ -339,6 +339,36 @@ func TestSubmitFrameOverlayOnlyRefused(t *testing.T) { | |||||
| 339 | } | 339 | } | ||
| 340 | } | 340 | } | ||
| 341 | 341 | ||||
| 342 | + | // A commit result with the overlay on: refusals the overlay causes ask for a | |||
| 343 | + | // frame without it and leave the queue; a commit queues the buffer. | |||
| 344 | + | func TestFinishOverlayCommit(t *testing.T) { | |||
| 345 | + | boom := errors.New("boom") | |||
| 346 | + | for _, tc := range []struct { | |||
| 347 | + | name string | |||
| 348 | + | err error | |||
| 349 | + | want error | |||
| 350 | + | wantQueued uint64 | |||
| 351 | + | reason string | |||
| 352 | + | }{ | |||
| 353 | + | {"committed", nil, nil, 9, ""}, | |||
| 354 | + | {"colour refused", errColorRefused, errOverlayDropped, 1, "color_refused"}, | |||
| 355 | + | {"overlay conflict", unix.EINVAL, errOverlayDropped, 1, "cursor_conflict"}, | |||
| 356 | + | {"other", boom, boom, 1, ""}, | |||
| 357 | + | } { | |||
| 358 | + | t.Run(tc.name, func(t *testing.T) { | |||
| 359 | + | o, _, _ := testOutput(t) | |||
| 360 | + | o.queued = 1 | |||
| 361 | + | o.clientFBs[9] = &clientFB{} | |||
| 362 | + | if err := o.finishOverlayCommit(tc.err, 9); err != tc.want { | |||
| 363 | + | t.Fatalf("err %v, want %v", err, tc.want) | |||
| 364 | + | } | |||
| 365 | + | if o.queued != tc.wantQueued || o.overlayReason != tc.reason { | |||
| 366 | + | t.Fatalf("queued %d reason %q", o.queued, o.overlayReason) | |||
| 367 | + | } | |||
| 368 | + | }) | |||
| 369 | + | } | |||
| 370 | + | } | |||
| 371 | + | ||||
| 342 | // A frame whose buffer KMS took before is not probed again. | 372 | // A frame whose buffer KMS took before is not probed again. | ||
| 343 | func TestOverlayProbeCached(t *testing.T) { | 373 | func TestOverlayProbeCached(t *testing.T) { | ||
| 344 | o, k, commits := overlayOutput(t) | 374 | o, k, commits := overlayOutput(t) | ||
| @@ -370,6 +400,19 @@ func TestOverlayProbeCached(t *testing.T) { | |||||
| 370 | if v, _ := (*commits)[3].req.value(tCursor, 14); v != 20-uint64(o.cursor.hotX) { | 400 | if v, _ := (*commits)[3].req.value(tCursor, 14); v != 20-uint64(o.cursor.hotX) { | ||
| 371 | t.Fatalf("probe cursor x %d", v) | 401 | t.Fatalf("probe cursor x %d", v) | ||
| 372 | } | 402 | } | ||
| 403 | + | // New colour state (HDR brightness) is probed again. | |||
| 404 | + | o.colorMult++ | |||
| 405 | + | o.testOverlay(70, ov) | |||
| 406 | + | if len(*commits) != 5 { | |||
| 407 | + | t.Fatalf("%d probes after a colour change, want 5", len(*commits)) | |||
| 408 | + | } | |||
| 409 | + | // A removed client framebuffer may give its id to another buffer. | |||
| 410 | + | k.EXPECT().rmFB(uint32(88)).Return(nil).Once() | |||
| 411 | + | o.dropClientFBs(time.Now(), true) | |||
| 412 | + | o.testOverlay(70, ov) | |||
| 413 | + | if len(*commits) != 6 { | |||
| 414 | + | t.Fatal("probe cached across a framebuffer removal") | |||
| 415 | + | } | |||
| 373 | // A modeset (VT resume) forgets them. | 416 | // A modeset (VT resume) forgets them. | ||
| 374 | k.EXPECT().createBlob(mock.Anything).Return(99, nil).Once() | 417 | k.EXPECT().createBlob(mock.Anything).Return(99, nil).Once() | ||
| 375 | k.EXPECT().objProps(uint32(tOverlay), uint32(objPlane)).Return(map[string][2]uint64{}, nil).Maybe() | 418 | k.EXPECT().objProps(uint32(tOverlay), uint32(objPlane)).Return(map[string][2]uint64{}, nil).Maybe() | ||