detached fdd661a

scene_solid_test.go RawHistoryFolder

1package vulkan
2
3import (
4	"image"
5	"math"
6	"testing"
7
8	"github.com/bnema/neferwl/internal/ports"
9)
10
11// These walk tests need no Vulkan device: a single-pixel buffer is a solid
12// quad, which imports nothing.
13func TestSceneSolid(t *testing.T) {
14	walk := func(r *Renderer, c ports.SurfaceContent) []draw {
15		c.ID = 1
16		c.Width, c.Height, c.LogicalW, c.LogicalH = 1, 1, 20, 20
17		s := ports.Scene{Windows: []ports.SceneWindow{{ID: 1, Rect: ports.Rect{W: 20, H: 20}}}}
18		contents := map[ports.WindowID]ports.SurfaceContent{1: c}
19		return r.draws(s, contents, newDamage(&target{}, s, image.Rect(0, 0, 80, 60)))
20	}
21	// The window's own background fill comes first; the content follows.
22	solids := func(ds []draw) []draw {
23		if len(ds) == 0 || ds[0].pc.misc[0] != modeSolid || ds[0].pc.rect != [4]int32{0, 0, 20, 20} {
24			t.Fatalf("no window background first: %+v", ds)
25		}
26		return ds[1:]
27	}
28	near := func(a, b [4]float32) bool {
29		for i := range a {
30			if math.Abs(float64(a[i]-b[i])) > 1e-6 {
31				return false
32			}
33		}
34		return true
35	}
36	half := &ports.SolidColor{R: 0.25, G: 0.125, B: 0, A: 0.5} // premultiplied
37	t.Run("premultiplied", func(t *testing.T) {
38		r := &Renderer{width: 80, height: 60}
39		got := solids(walk(r, ports.SurfaceContent{Solid: half}))
40		if len(got) != 1 || got[0].pc.color != [4]float32{0.25, 0.125, 0, 0.5} {
41			t.Fatalf("draws = %+v", got)
42		}
43	})
44	t.Run("fade", func(t *testing.T) {
45		r := &Renderer{width: 80, height: 60}
46		got := solids(walk(r, ports.SurfaceContent{Solid: half, Fade: 0.5}))
47		if len(got) != 1 || got[0].pc.color != [4]float32{0.125, 0.0625, 0, 0.25} {
48			t.Fatalf("draws = %+v", got)
49		}
50	})
51	t.Run("opaque", func(t *testing.T) {
52		r := &Renderer{width: 80, height: 60}
53		got := solids(walk(r, ports.SurfaceContent{Solid: half, Opaque: true}))
54		if len(got) != 1 || got[0].pc.color != [4]float32{0.25, 0.125, 0, 1} {
55			t.Fatalf("draws = %+v", got)
56		}
57	})
58	t.Run("hdr", func(t *testing.T) {
59		r := &Renderer{width: 80, height: 60, hdrNits: 203}
60		got := solids(walk(r, ports.SurfaceContent{Solid: half}))
61		if len(got) != 1 {
62			t.Fatalf("draws = %+v", got)
63		}
64		// The HDR shader decodes rgb (decodeSRGB) and blends linear light:
65		// decoded values must be the linear straight color times alpha.
66		c := got[0].pc.color
67		decoded := [4]float32{float32(srgbToLinear(float64(c[0]))), float32(srgbToLinear(float64(c[1]))), float32(srgbToLinear(float64(c[2]))), c[3]}
68		want := [4]float32{float32(srgbToLinear(0.5) * 0.5), float32(srgbToLinear(0.25) * 0.5), 0, 0.5}
69		if !near(decoded, want) {
70			t.Fatalf("decoded = %v, want %v", decoded, want)
71		}
72	})
73	t.Run("transparent", func(t *testing.T) {
74		r := &Renderer{width: 80, height: 60}
75		if got := solids(walk(r, ports.SurfaceContent{Solid: &ports.SolidColor{}})); len(got) != 0 {
76			t.Fatalf("draws = %+v", got)
77		}
78		// Fully faded away too.
79		if got := walk(r, ports.SurfaceContent{Solid: half, Fade: 1}); len(solids(got)) != 0 {
80			t.Fatalf("faded draws = %+v", got)
81		}
82	})
83}
84
85func TestLinearToSRGB(t *testing.T) {
86	for _, v := range []float64{0, 0.002, 0.04045, 0.5, 1} {
87		if got := srgbToLinear(linearToSRGB(v)); math.Abs(got-v) > 1e-6 {
88			t.Errorf("round trip of %v = %v", v, got)
89		}
90		if got := linearToSRGB(srgbToLinear(v)); math.Abs(got-v) > 1e-6 {
91			t.Errorf("inverse round trip of %v = %v", v, got)
92		}
93	}
94}

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 23

Tags 10

↑↓ moveenter openesc close