mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-23 03:34:01 -04:00
173 lines
4.2 KiB
Go
173 lines
4.2 KiB
Go
package screenshot
|
|
|
|
import (
|
|
"bytes"
|
|
"math/rand"
|
|
"testing"
|
|
)
|
|
|
|
func rectArea(r dirtyRect) int {
|
|
if r.empty() {
|
|
return 0
|
|
}
|
|
return (r.x2 - r.x1) * (r.y2 - r.y1)
|
|
}
|
|
|
|
func TestDirtyRectMinus(t *testing.T) {
|
|
a := dirtyRect{0, 0, 10, 10}
|
|
cases := []struct {
|
|
name string
|
|
b dirtyRect
|
|
parts int
|
|
area int
|
|
}{
|
|
{"disjoint", dirtyRect{20, 20, 30, 30}, 1, 100},
|
|
{"covered", dirtyRect{-1, -1, 11, 11}, 0, 0},
|
|
{"center", dirtyRect{3, 3, 6, 6}, 4, 91},
|
|
{"corner", dirtyRect{5, 5, 20, 20}, 2, 75},
|
|
{"zero", dirtyRect{}, 1, 100},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
parts := a.minus(tc.b)
|
|
if len(parts) != tc.parts {
|
|
t.Fatalf("parts = %d, want %d", len(parts), tc.parts)
|
|
}
|
|
area := 0
|
|
for i, p := range parts {
|
|
area += rectArea(p)
|
|
if !p.intersect(a).equal(p) || !p.intersect(tc.b).empty() {
|
|
t.Errorf("part %v outside a or inside b", p)
|
|
}
|
|
for _, q := range parts[i+1:] {
|
|
if !p.intersect(q).empty() {
|
|
t.Errorf("parts %v and %v overlap", p, q)
|
|
}
|
|
}
|
|
}
|
|
if area != tc.area {
|
|
t.Errorf("area = %d, want %d", area, tc.area)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (d dirtyRect) equal(o dirtyRect) bool { return d == o }
|
|
|
|
func newOverlayFixture(t testing.TB, w, h int) (*RegionSelector, *OutputSurface) {
|
|
t.Helper()
|
|
src, err := CreateShmBuffer(w, h, w*4+16)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { src.Close() })
|
|
rng := rand.New(rand.NewSource(7))
|
|
rng.Read(src.Data())
|
|
|
|
os := &OutputSurface{
|
|
output: &WaylandOutput{},
|
|
screenBuf: src,
|
|
screenFormat: uint32(FormatXRGB8888),
|
|
logicalW: w,
|
|
logicalH: h,
|
|
}
|
|
r := &RegionSelector{showCapturedCursor: true}
|
|
r.selection.surface = os
|
|
return r, os
|
|
}
|
|
|
|
func newFrameBuffer(t testing.TB, r *RegionSelector, os *OutputSurface) *ShmBuffer {
|
|
t.Helper()
|
|
buf, err := CreateShmBuffer(os.screenBuf.Width, os.screenBuf.Height, os.screenBuf.Stride)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { buf.Close() })
|
|
paintDimmedFrame(buf, os.screenBuf)
|
|
return buf
|
|
}
|
|
|
|
func (r *RegionSelector) selectRect(x1, y1, x2, y2 float64) {
|
|
r.selection.hasSelection = true
|
|
r.selection.anchorX, r.selection.anchorY = x1, y1
|
|
r.selection.currentX, r.selection.currentY = x2, y2
|
|
}
|
|
|
|
func inRects(x, y int, rects []dirtyRect) bool {
|
|
for _, d := range rects {
|
|
if x >= d.x1 && x < d.x2 && y >= d.y1 && y < d.y2 {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func TestDrawOverlayIncremental(t *testing.T) {
|
|
const w, h = 160, 120
|
|
r, os := newOverlayFixture(t, w, h)
|
|
incr := newFrameBuffer(t, r, os)
|
|
shown := newFrameBuffer(t, r, os)
|
|
rng := rand.New(rand.NewSource(3))
|
|
|
|
var prev *overlay
|
|
for i := range 300 {
|
|
var cur *overlay
|
|
switch rng.Intn(8) {
|
|
case 0:
|
|
r.selection.hasSelection = false
|
|
default:
|
|
r.selectRect(rng.Float64()*w, rng.Float64()*h, rng.Float64()*w, rng.Float64()*h)
|
|
cur = r.overlayFor(os, incr)
|
|
}
|
|
damage := overlayDamage(prev, cur)
|
|
r.drawOverlay(os, incr, prev, cur)
|
|
|
|
full := newFrameBuffer(t, r, os)
|
|
r.drawOverlay(os, full, nil, cur)
|
|
if !bytes.Equal(incr.Data(), full.Data()) {
|
|
t.Fatalf("step %d: incremental frame differs from full render (%v -> %v)", i, prev, cur)
|
|
}
|
|
|
|
for y := range h {
|
|
for x := range w {
|
|
off := y*full.Stride + x*4
|
|
if bytes.Equal(full.Data()[off:off+4], shown.Data()[off:off+4]) {
|
|
continue
|
|
}
|
|
if !inRects(x, y, damage) {
|
|
t.Fatalf("step %d: pixel %d,%d changed outside damage %v", i, x, y, damage)
|
|
}
|
|
}
|
|
}
|
|
copy(shown.Data(), full.Data())
|
|
prev = cur
|
|
}
|
|
}
|
|
|
|
func BenchmarkDrawOverlayStep(b *testing.B) {
|
|
r, os := newOverlayFixture(b, 2560, 1440)
|
|
buf := newFrameBuffer(b, r, os)
|
|
r.selectRect(10, 10, 2000, 1400)
|
|
prev := r.overlayFor(os, buf)
|
|
r.drawOverlay(os, buf, nil, prev)
|
|
b.ResetTimer()
|
|
for i := range b.N {
|
|
r.selectRect(10, 10, float64(2000+i%8), float64(1400-i%8))
|
|
cur := r.overlayFor(os, buf)
|
|
r.drawOverlay(os, buf, prev, cur)
|
|
prev = cur
|
|
}
|
|
}
|
|
|
|
func BenchmarkDrawOverlayFull(b *testing.B) {
|
|
r, os := newOverlayFixture(b, 2560, 1440)
|
|
buf := newFrameBuffer(b, r, os)
|
|
b.ResetTimer()
|
|
for i := range b.N {
|
|
r.selectRect(10, 10, float64(2000+i%8), float64(1400-i%8))
|
|
cur := r.overlayFor(os, buf)
|
|
r.paintRect(os, buf, dirtyRect{0, 0, buf.Width, buf.Height}, true)
|
|
r.drawOverlay(os, buf, nil, cur)
|
|
}
|
|
}
|