From 423e6869c0b72308817676bc7a10ba070bd019fd Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 7 Mar 2023 12:48:29 -0500 Subject: [PATCH] X backend better handles expose events Previously, when an expose event was recieved, the backend would call Window.paste, converting RGBA image data to BGRA image data. Now we only call Window.pushRegion with the bounds given to us by the expose event(s). This speeds up window resizing significantly. --- artist/patterns/texture.go | 19 ++++++++++++------- backends/x/event.go | 17 ++++++++++++++--- backends/x/window.go | 2 ++ examples/piano/main.go | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/artist/patterns/texture.go b/artist/patterns/texture.go index 3c2b236..47f0596 100644 --- a/artist/patterns/texture.go +++ b/artist/patterns/texture.go @@ -24,22 +24,27 @@ func (pattern Texture) Draw (destination canvas.Canvas, clip image.Rectangle) { srcPoint := bounds.Min.Sub(realBounds.Min).Add(srcBounds.Min) srcPoint.X = wrap(srcPoint.X, srcBounds.Min.X, srcBounds.Max.X) srcPoint.Y = wrap(srcPoint.Y, srcBounds.Min.Y, srcBounds.Max.Y) - srcPointXStart := srcPoint.X for dstPoint.Y = bounds.Min.Y; dstPoint.Y < bounds.Max.Y; dstPoint.Y ++ { - srcPoint.X = srcPointXStart + srcPoint.X = srcBounds.Min.X + dstPoint.X = bounds.Min.X + dstYComponent := dstPoint.Y * dstStride + srcYComponent := srcPoint.Y * srcStride - for dstPoint.X = bounds.Min.X; dstPoint.X < bounds.Max.X; dstPoint.X ++ { - dstIndex := dstPoint.X + dstPoint.Y * dstStride - srcIndex := - srcPoint.X + - srcPoint.Y * srcStride + for { + dstIndex := dstYComponent + dstPoint.X + srcIndex := srcYComponent + srcPoint.X dstData[dstIndex] = srcData[srcIndex] srcPoint.X ++ if srcPoint.X >= srcBounds.Max.X { srcPoint.X = srcBounds.Min.X } + + dstPoint.X ++ + if dstPoint.X >= bounds.Max.X { + break + } } srcPoint.Y ++ diff --git a/backends/x/event.go b/backends/x/event.go index 2aaf77c..5f6b773 100644 --- a/backends/x/event.go +++ b/backends/x/event.go @@ -1,5 +1,6 @@ package x +import "image" import "git.tebibyte.media/sashakoshka/tomo/input" import "git.tebibyte.media/sashakoshka/tomo/elements" @@ -47,8 +48,8 @@ func (window *Window) handleExpose ( connection *xgbutil.XUtil, event xevent.ExposeEvent, ) { - _ = window.compressExpose(*event.ExposeEvent) - window.redrawChildEntirely() + _, region := window.compressExpose(*event.ExposeEvent) + window.pushRegion(region) } func (window *Window) handleConfigureNotify ( @@ -234,7 +235,13 @@ func (window *Window) compressExpose ( firstEvent xproto.ExposeEvent, ) ( lastEvent xproto.ExposeEvent, + region image.Rectangle, ) { + region = image.Rect ( + int(firstEvent.X), int(firstEvent.Y), + int(firstEvent.X + firstEvent.Width), + int(firstEvent.Y + firstEvent.Height)) + window.backend.connection.Sync() xevent.Read(window.backend.connection, false) lastEvent = firstEvent @@ -245,8 +252,12 @@ func (window *Window) compressExpose ( typedEvent, ok := untypedEvent.Event.(xproto.ExposeEvent) if !ok { continue } - // FIXME: union all areas into the last event if firstEvent.Window == typedEvent.Window { + region = region.Union (image.Rect ( + int(typedEvent.X), int(typedEvent.Y), + int(typedEvent.X + typedEvent.Width), + int(typedEvent.Y + typedEvent.Height))) + lastEvent = typedEvent defer func (index int) { xevent.DequeueAt(window.backend.connection, index) diff --git a/backends/x/window.go b/backends/x/window.go index d1bc360..37d2466 100644 --- a/backends/x/window.go +++ b/backends/x/window.go @@ -12,6 +12,7 @@ import "git.tebibyte.media/sashakoshka/tomo/theme" import "git.tebibyte.media/sashakoshka/tomo/config" import "git.tebibyte.media/sashakoshka/tomo/canvas" import "git.tebibyte.media/sashakoshka/tomo/elements" +// import "runtime/debug" type Window struct { backend *Backend @@ -290,6 +291,7 @@ func (window *Window) childDrawCallback (region canvas.Canvas) { func (window *Window) paste (canvas canvas.Canvas) (updatedRegion image.Rectangle) { data, stride := canvas.Buffer() bounds := canvas.Bounds().Intersect(window.xCanvas.Bounds()) + // debug.PrintStack() for x := bounds.Min.X; x < bounds.Max.X; x ++ { for y := bounds.Min.Y; y < bounds.Max.Y; y ++ { rgba := data[x + y * stride] diff --git a/examples/piano/main.go b/examples/piano/main.go index 872fc08..350c602 100644 --- a/examples/piano/main.go +++ b/examples/piano/main.go @@ -150,7 +150,7 @@ func run () { window.OnClose(tomo.Stop) window.Show() go func () { - http.ListenAndServe("localhost:6060", nil) + http.ListenAndServe("localhost:9090", nil) } () }