perf(overview): skip separator allocation for rounded outline
3 files · +23 -5
M internal/adapters/vulkan/damage_delta_test.go +4 -1
| @@ -444,7 +444,10 @@ func TestDamageSelectionOutlineDelta(t *testing.T) { | |||
| 444 | 444 | a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true} | |
| 445 | 445 | b := *a | |
| 446 | 446 | b.Rect.X = 60 | |
| 447 | - | for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, a}} { | |
| 447 | + | wider, rounder := *a, *a | |
| 448 | + | wider.Width++ | |
| 449 | + | rounder.Radius++ | |
| 450 | + | for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, &wider}, {a, &rounder}, {a, a}} { | |
| 448 | 451 | old, cur := deltaScene(1), deltaScene(2) | |
| 449 | 452 | old.Outline, cur.Outline = pair[0], pair[1] | |
| 450 | 453 | area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000) | |
| @@ -444,7 +444,10 @@ func TestDamageSelectionOutlineDelta(t *testing.T) { | |||||
| 444 | a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true} | 444 | a := &ports.SelectionOutline{Rect: ports.Rect{X: 10, Y: 10, W: 40, H: 30}, Width: 2, Radius: 10, Active: true} | ||
| 445 | b := *a | 445 | b := *a | ||
| 446 | b.Rect.X = 60 | 446 | b.Rect.X = 60 | ||
| 447 | - | for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, a}} { | 447 | + | wider, rounder := *a, *a |
| 448 | + | wider.Width++ | |||
| 449 | + | rounder.Radius++ | |||
| 450 | + | for _, pair := range [][2]*ports.SelectionOutline{{nil, a}, {a, nil}, {a, &b}, {a, &wider}, {a, &rounder}, {a, a}} { | |||
| 448 | old, cur := deltaScene(1), deltaScene(2) | 451 | old, cur := deltaScene(1), deltaScene(2) | ||
| 449 | old.Outline, cur.Outline = pair[0], pair[1] | 452 | old.Outline, cur.Outline = pair[0], pair[1] | ||
| 450 | area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000) | 453 | area, ok := sceneDelta(old, cur, func(r ports.Rect) image.Rectangle { return image.Rect(r.X, r.Y, r.X+r.W, r.Y+r.H) }, 500000) | ||
M internal/core/overview.go +4 -4
| @@ -1338,7 +1338,6 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i | |||
| 1338 | 1338 | if sel < 0 { | |
| 1339 | 1339 | return dst, nil | |
| 1340 | 1340 | } | |
| 1341 | - | dst = slices.Grow(dst, outlineLines) | |
| 1342 | 1341 | r := layout[sel].Rect | |
| 1343 | 1342 | edges := [4]Rect{ | |
| 1344 | 1343 | {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b}, | |
| @@ -1355,10 +1354,11 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i | |||
| 1355 | 1354 | } | |
| 1356 | 1355 | } | |
| 1357 | 1356 | } | |
| 1357 | + | if radius := windowRadius(layout[sel], gap, radius); !cut && radius > 0 { | |
| 1358 | + | return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true} | |
| 1359 | + | } | |
| 1360 | + | dst = slices.Grow(dst, outlineLines) | |
| 1358 | 1361 | if !cut { | |
| 1359 | - | if radius := windowRadius(layout[sel], gap, radius); radius > 0 { | |
| 1360 | - | return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true} | |
| 1361 | - | } | |
| 1362 | 1362 | for _, e := range edges { | |
| 1363 | 1363 | dst = append(dst, ports.Separator{Rect: e, Active: true}) | |
| 1364 | 1364 | } | |
| @@ -1338,7 +1338,6 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i | |||||
| 1338 | if sel < 0 { | 1338 | if sel < 0 { | ||
| 1339 | return dst, nil | 1339 | return dst, nil | ||
| 1340 | } | 1340 | } | ||
| 1341 | - | dst = slices.Grow(dst, outlineLines) | |||
| 1342 | r := layout[sel].Rect | 1341 | r := layout[sel].Rect | ||
| 1343 | edges := [4]Rect{ | 1342 | edges := [4]Rect{ | ||
| 1344 | {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b}, | 1343 | {X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: b}, | ||
| @@ -1355,10 +1354,11 @@ func overviewOutline(dst []ports.Separator, layout []Placement, b, gap, radius i | |||||
| 1355 | } | 1354 | } | ||
| 1356 | } | 1355 | } | ||
| 1357 | } | 1356 | } | ||
| 1357 | + | if radius := windowRadius(layout[sel], gap, radius); !cut && radius > 0 { | |||
| 1358 | + | return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true} | |||
| 1359 | + | } | |||
| 1360 | + | dst = slices.Grow(dst, outlineLines) | |||
| 1358 | if !cut { | 1361 | if !cut { | ||
| 1359 | - | if radius := windowRadius(layout[sel], gap, radius); radius > 0 { | |||
| 1360 | - | return dst, &ports.SelectionOutline{Rect: Rect{X: r.X - b, Y: r.Y - b, W: r.W + 2*b, H: r.H + 2*b}, Width: b, Radius: radius + b, Active: true} | |||
| 1361 | - | } | |||
| 1362 | for _, e := range edges { | 1362 | for _, e := range edges { | ||
| 1363 | dst = append(dst, ports.Separator{Rect: e, Active: true}) | 1363 | dst = append(dst, ports.Separator{Rect: e, Active: true}) | ||
| 1364 | } | 1364 | } | ||
M internal/core/overview_cascade_test.go +15 -0
| @@ -1215,6 +1215,21 @@ func TestOverviewOutlinePileAllocations(t *testing.T) { | |||
| 1215 | 1215 | } | |
| 1216 | 1216 | } | |
| 1217 | 1217 | ||
| 1218 | + | func TestOverviewOutlineRoundedAllocations(t *testing.T) { | |
| 1219 | + | ps := []Placement{{Rect: Rect{X: 20, Y: 20, W: 100, H: 80}, Preview: 0.5, Focused: true, Floating: true}} | |
| 1220 | + | // Keep the returned outline alive so its one snapshot allocation is counted. | |
| 1221 | + | var outline *ports.SelectionOutline | |
| 1222 | + | n := testing.AllocsPerRun(50, func() { | |
| 1223 | + | _, outline = overviewOutline(nil, ps, 2, 0, 12) | |
| 1224 | + | }) | |
| 1225 | + | if outline == nil { | |
| 1226 | + | t.Fatal("setup: no rounded outline") | |
| 1227 | + | } | |
| 1228 | + | if n != 1 { | |
| 1229 | + | t.Fatalf("rounded overviewOutline allocs = %v, want 1 (outline only)", n) | |
| 1230 | + | } | |
| 1231 | + | } | |
| 1232 | + | ||
| 1218 | 1233 | func TestSubtractRects(t *testing.T) { | |
| 1219 | 1234 | h := Rect{X: 0, Y: 10, W: 100, H: 2} | |
| 1220 | 1235 | v := Rect{X: 10, Y: 0, W: 2, H: 100} | |
| @@ -1215,6 +1215,21 @@ func TestOverviewOutlinePileAllocations(t *testing.T) { | |||||
| 1215 | } | 1215 | } | ||
| 1216 | } | 1216 | } | ||
| 1217 | 1217 | ||||
| 1218 | + | func TestOverviewOutlineRoundedAllocations(t *testing.T) { | |||
| 1219 | + | ps := []Placement{{Rect: Rect{X: 20, Y: 20, W: 100, H: 80}, Preview: 0.5, Focused: true, Floating: true}} | |||
| 1220 | + | // Keep the returned outline alive so its one snapshot allocation is counted. | |||
| 1221 | + | var outline *ports.SelectionOutline | |||
| 1222 | + | n := testing.AllocsPerRun(50, func() { | |||
| 1223 | + | _, outline = overviewOutline(nil, ps, 2, 0, 12) | |||
| 1224 | + | }) | |||
| 1225 | + | if outline == nil { | |||
| 1226 | + | t.Fatal("setup: no rounded outline") | |||
| 1227 | + | } | |||
| 1228 | + | if n != 1 { | |||
| 1229 | + | t.Fatalf("rounded overviewOutline allocs = %v, want 1 (outline only)", n) | |||
| 1230 | + | } | |||
| 1231 | + | } | |||
| 1232 | + | ||||
| 1218 | func TestSubtractRects(t *testing.T) { | 1233 | func TestSubtractRects(t *testing.T) { | ||
| 1219 | h := Rect{X: 0, Y: 10, W: 100, H: 2} | 1234 | h := Rect{X: 0, Y: 10, W: 100, H: 2} | ||
| 1220 | v := Rect{X: 10, Y: 0, W: 2, H: 100} | 1235 | v := Rect{X: 10, Y: 0, W: 2, H: 100} | ||