v0.2.0 13c6a90

game_performance_test.go RawHistoryFolder

1package drm
2
3import (
4	"bytes"
5	"testing"
6
7	"github.com/bnema/neferwl/internal/ports"
8	"github.com/bnema/zerowrap"
9	"github.com/stretchr/testify/mock"
10	"golang.org/x/sys/unix"
11)
12
13func TestScaledScanoutRectAndCachedRefusal(t *testing.T) {
14	o, _, commits := testOutput(t, unix.EINVAL)
15	o.cursor = nil
16	o.primary.formats = []ports.DMABufFormat{{Format: fourccXRGB}}
17	o.clientFBs[9] = &clientFB{fbID: 87}
18	s := ports.Scene{OutputWidth: 200, OutputHeight: 100, Windows: []ports.SceneWindow{{ID: 1, Rect: ports.Rect{W: 200, H: 100}, Fullscreen: true}}}
19	c := ports.SurfaceContent{ID: 1, Width: 100, Height: 50, LogicalW: 200, LogicalH: 100, Source: [4]float32{5, 2, 90, 46}, DMABuf: &ports.DMABuf{ID: 9, Format: fourccXRGB}}
20	var log bytes.Buffer
21	o.log = zerowrap.New(zerowrap.Config{Output: &log})
22	surfaces := map[ports.WindowID]ports.SurfaceContent{1: c}
23	if fb, _ := o.scanoutFrame(s, surfaces); fb != 0 || o.reason != "scale_refused" {
24		t.Fatalf("fb %d reason %s", fb, o.reason)
25	}
26	if len(*commits) != 1 || (*commits)[0].flags != atomicTestOnly {
27		t.Fatalf("test commits %+v", *commits)
28	}
29	if v, _ := (*commits)[0].req.value(tPrimary, planeProps["SRC_X"]); v != 5<<16 {
30		t.Fatalf("source x: %d", v)
31	}
32	if v, _ := (*commits)[0].req.value(tPrimary, planeProps["SRC_W"]); v != 90<<16 {
33		t.Fatalf("source width: %d", v)
34	}
35	if v, _ := (*commits)[0].req.value(tPrimary, planeProps["CRTC_W"]); v != 200 {
36		t.Fatalf("destination width: %d", v)
37	}
38	if fb, _ := o.scanoutFrame(s, surfaces); fb != 0 || len(*commits) != 1 {
39		t.Fatal("refused geometry retried")
40	}
41	if !bytes.Contains(log.Bytes(), []byte("scale_refused")) {
42		t.Fatalf("refusal not logged: %s", log.String())
43	}
44}
45
46func TestModesetInvalidatesScaleDecision(t *testing.T) {
47	o, k, commits := testOutput(t)
48	o.cursor = nil
49	o.primary.formats = []ports.DMABufFormat{{Format: fourccXRGB}}
50	fb := &clientFB{fbID: 87}
51	o.clientFBs[9] = fb
52	s := ports.Scene{OutputWidth: 200, OutputHeight: 100, Windows: []ports.SceneWindow{{ID: 1, Rect: ports.Rect{W: 200, H: 100}, Fullscreen: true}}}
53	c := ports.SurfaceContent{ID: 1, Width: 100, Height: 50, LogicalW: 200, LogicalH: 100, DMABuf: &ports.DMABuf{ID: 9, Format: fourccXRGB}}
54	contents := map[ports.WindowID]ports.SurfaceContent{1: c}
55	if got, _ := o.scanoutFrame(s, contents); got != 87 || len(*commits) != 1 || !fb.scaleTestedOK {
56		t.Fatalf("initial scale: %d, commits: %d", got, len(*commits))
57	}
58	k.EXPECT().createBlob(mock.Anything).Return(uint32(77), nil).Once()
59	if err := o.modeset(); err != nil {
60		t.Fatal(err)
61	}
62	if fb.scaleTestedOK || fb.scaleRefused {
63		t.Fatal("cached scale survived modeset")
64	}
65	if got, _ := o.scanoutFrame(s, contents); got != 87 || len(*commits) != 3 || (*commits)[2].flags != atomicTestOnly {
66		t.Fatalf("scale not retested: fb %d commits %+v", got, *commits)
67	}
68}
69
70func TestContentTypeFrameAndReset(t *testing.T) {
71	o, _, commits := testOutput(t)
72	o.cursor = nil
73	o.contentProp = 81
74	o.contentValues = [5]uint64{0, 1, 2, 3, 4}
75	s := ports.Scene{OutputWidth: 200, OutputHeight: 100, Windows: []ports.SceneWindow{{ID: 1, Rect: ports.Rect{W: 200, H: 100}, Fullscreen: true}}}
76	o.wantContent(s, map[ports.WindowID]ports.SurfaceContent{1: {ContentType: ports.ContentGame}})
77	for i := 0; i < 2; i++ {
78		if err := o.commitFrame(70, nil, false, false, pendingFrame{}); err != nil {
79			t.Fatal(err)
80		}
81	}
82	if v, ok := (*commits)[0].req.value(tConn, 81); !ok || v != 4 {
83		t.Fatalf("game hint: %d %v", v, ok)
84	}
85	if _, ok := (*commits)[1].req.value(tConn, 81); ok {
86		t.Fatal("hint repeated")
87	}
88	o.wantContent(ports.Scene{}, nil)
89	if err := o.commitFrame(70, nil, false, false, pendingFrame{}); err != nil {
90		t.Fatal(err)
91	}
92	if v, ok := (*commits)[2].req.value(tConn, 81); !ok || v != 0 {
93		t.Fatalf("reset hint: %d %v", v, ok)
94	}
95	o.contentProp = 0
96	o.wantContent(s, map[ports.WindowID]ports.SurfaceContent{1: {ContentType: ports.ContentGame}})
97	if err := o.commitFrame(70, nil, false, false, pendingFrame{}); err != nil {
98		t.Fatal(err)
99	}
100	if _, ok := (*commits)[3].req.value(tConn, 81); ok {
101		t.Fatal("absent property set")
102	}
103}

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