From 0bdc2e04322b71d24bbe60ca4065a4100ff8a332 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 4 Aug 2021 12:03:04 +0200 Subject: [PATCH] app,app/internal/wm: fold context MakeCurrent/ReleaseCurrent into Lock/Unlock While here, make context Refresh useful and remove the redundant MakeCurrent from the window loop. Signed-off-by: Elias Naur --- app/internal/wm/d3d11_windows.go | 18 +++-------- app/internal/wm/egl_android.go | 26 +++++---------- app/internal/wm/egl_wayland.go | 17 ++++------ app/internal/wm/egl_windows.go | 17 +++++----- app/internal/wm/egl_x11.go | 13 ++++---- app/internal/wm/gl_ios.go | 19 ++++++----- app/internal/wm/gl_js.go | 10 ++---- app/internal/wm/gl_macos.go | 16 +++------- app/internal/wm/window.go | 4 +-- app/loop.go | 55 +++++++++++++++----------------- app/window.go | 20 ++++-------- 11 files changed, 83 insertions(+), 132 deletions(-) diff --git a/app/internal/wm/d3d11_windows.go b/app/internal/wm/d3d11_windows.go index f048d018..78a05cae 100644 --- a/app/internal/wm/d3d11_windows.go +++ b/app/internal/wm/d3d11_windows.go @@ -72,16 +72,9 @@ func (c *d3d11Context) Present() error { } func (c *d3d11Context) Refresh() error { - return nil -} - -func (c *d3d11Context) MakeCurrent() error { var width, height int - c.win.w.Run(func() { - _, width, height = c.win.HWND() - }) + _, width, height = c.win.HWND() if c.renderTarget != nil && width == c.width && height == c.height { - c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView) return nil } c.releaseFBO() @@ -112,14 +105,13 @@ func (c *d3d11Context) MakeCurrent() error { } c.renderTarget = renderTarget c.depthView = depthView - - c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView) return nil } -func (c *d3d11Context) ReleaseCurrent() {} - -func (c *d3d11Context) Lock() {} +func (c *d3d11Context) Lock() error { + c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView) + return nil +} func (c *d3d11Context) Unlock() {} diff --git a/app/internal/wm/egl_android.go b/app/internal/wm/egl_android.go index 69e75a1b..759620a7 100644 --- a/app/internal/wm/egl_android.go +++ b/app/internal/wm/egl_android.go @@ -35,33 +35,23 @@ func (c *context) Release() { } func (c *context) Refresh() error { - return nil -} - -func (c *context) MakeCurrent() error { c.Context.ReleaseSurface() var ( win *C.ANativeWindow width, height int ) - // Run on main thread. Deadlock is avoided because MakeCurrent is only - // called during a FrameEvent. - c.win.callbacks.Run(func() { - win, width, height = c.win.nativeWindow(c.Context.VisualID()) - }) + win, width, height = c.win.nativeWindow(c.Context.VisualID()) if win == nil { return nil } eglSurf := egl.NativeWindowType(unsafe.Pointer(win)) - if err := c.Context.CreateSurface(eglSurf, width, height); err != nil { - return err - } - if err := c.Context.MakeCurrent(); err != nil { - return err - } - return nil + return c.Context.CreateSurface(eglSurf, width, height) } -func (c *context) Lock() {} +func (c *context) Lock() error { + return c.Context.MakeCurrent() +} -func (c *context) Unlock() {} +func (c *context) Unlock() { + c.Context.ReleaseCurrent() +} diff --git a/app/internal/wm/egl_wayland.go b/app/internal/wm/egl_wayland.go index 685b0c53..abd92770 100644 --- a/app/internal/wm/egl_wayland.go +++ b/app/internal/wm/egl_wayland.go @@ -50,10 +50,6 @@ func (c *context) Release() { } func (c *context) Refresh() error { - return nil -} - -func (c *context) MakeCurrent() error { c.Context.ReleaseSurface() if c.eglWin != nil { C.wl_egl_window_destroy(c.eglWin) @@ -69,12 +65,13 @@ func (c *context) MakeCurrent() error { } c.eglWin = eglWin eglSurf := egl.NativeWindowType(uintptr(unsafe.Pointer(eglWin))) - if err := c.Context.CreateSurface(eglSurf, width, height); err != nil { - return err - } + return c.Context.CreateSurface(eglSurf, width, height) +} + +func (c *context) Lock() error { return c.Context.MakeCurrent() } -func (c *context) Lock() {} - -func (c *context) Unlock() {} +func (c *context) Unlock() { + c.Context.ReleaseCurrent() +} diff --git a/app/internal/wm/egl_windows.go b/app/internal/wm/egl_windows.go index dc2d93b3..b2b66ecc 100644 --- a/app/internal/wm/egl_windows.go +++ b/app/internal/wm/egl_windows.go @@ -35,18 +35,12 @@ func (c *glContext) Release() { } func (c *glContext) Refresh() error { - return nil -} - -func (c *glContext) MakeCurrent() error { c.Context.ReleaseSurface() var ( win windows.Handle width, height int ) - c.win.w.Run(func() { - win, width, height = c.win.HWND() - }) + win, width, height = c.win.HWND() eglSurf := egl.NativeWindowType(win) if err := c.Context.CreateSurface(eglSurf, width, height); err != nil { return err @@ -55,9 +49,14 @@ func (c *glContext) MakeCurrent() error { return err } c.Context.EnableVSync(true) + c.Context.ReleaseCurrent() return nil } -func (c *glContext) Lock() {} +func (c *glContext) Lock() error { + return c.Context.MakeCurrent() +} -func (c *glContext) Unlock() {} +func (c *glContext) Unlock() { + c.Context.ReleaseCurrent() +} diff --git a/app/internal/wm/egl_x11.go b/app/internal/wm/egl_x11.go index ca8dd5ce..b16ebd7a 100644 --- a/app/internal/wm/egl_x11.go +++ b/app/internal/wm/egl_x11.go @@ -33,10 +33,6 @@ func (c *x11Context) Release() { } func (c *x11Context) Refresh() error { - return nil -} - -func (c *x11Context) MakeCurrent() error { c.Context.ReleaseSurface() win, width, height := c.win.window() eglSurf := egl.NativeWindowType(uintptr(win)) @@ -47,9 +43,14 @@ func (c *x11Context) MakeCurrent() error { return err } c.Context.EnableVSync(true) + c.Context.ReleaseCurrent() return nil } -func (c *x11Context) Lock() {} +func (c *x11Context) Lock() error { + return c.Context.MakeCurrent() +} -func (c *x11Context) Unlock() {} +func (c *x11Context) Unlock() { + c.Context.ReleaseCurrent() +} diff --git a/app/internal/wm/gl_ios.go b/app/internal/wm/gl_ios.go index 4dd6e29e..4957c0b5 100644 --- a/app/internal/wm/gl_ios.go +++ b/app/internal/wm/gl_ios.go @@ -97,15 +97,18 @@ func (c *context) Present() error { return nil } -func (c *context) Lock() {} - -func (c *context) Unlock() {} - -func (c *context) Refresh() error { +func (c *context) Lock() error { + if C.gio_makeCurrent(c.ctx) == 0 { + return errors.New("[EAGLContext setCurrentContext] failed") + } return nil } -func (c *context) MakeCurrent() error { +func (c *context) Unlock() { + C.gio_makeCurrent(0) +} + +func (c *context) Refresh() error { if C.gio_makeCurrent(c.ctx) == 0 { return errors.New("[EAGLContext setCurrentContext] failed") } @@ -139,10 +142,6 @@ func (c *context) MakeCurrent() error { return nil } -func (c *context) ReleaseCurrent() { - C.gio_makeCurrent(0) -} - func (w *window) NewContext() (Context, error) { return newContext(w) } diff --git a/app/internal/wm/gl_js.go b/app/internal/wm/gl_js.go index 7588dd68..5d2f4b5f 100644 --- a/app/internal/wm/gl_js.go +++ b/app/internal/wm/gl_js.go @@ -50,7 +50,9 @@ func (c *context) Present() error { return nil } -func (c *context) Lock() {} +func (c *context) Lock() error { + return nil +} func (c *context) Unlock() {} @@ -58,12 +60,6 @@ func (c *context) Refresh() error { return nil } -func (c *context) MakeCurrent() error { - return nil -} - -func (c *context) ReleaseCurrent() {} - func (w *window) NewContext() (Context, error) { return newContext(w) } diff --git a/app/internal/wm/gl_macos.go b/app/internal/wm/gl_macos.go index 55cbc4e8..ca7ae71e 100644 --- a/app/internal/wm/gl_macos.go +++ b/app/internal/wm/gl_macos.go @@ -68,11 +68,14 @@ func (c *context) Present() error { return nil } -func (c *context) Lock() { +func (c *context) Lock() error { C.gio_lockContext(c.ctx) + C.gio_makeCurrentContext(c.ctx) + return nil } func (c *context) Unlock() { + C.gio_clearCurrentContext() C.gio_unlockContext(c.ctx) } @@ -83,17 +86,6 @@ func (c *context) Refresh() error { return nil } -func (c *context) MakeCurrent() error { - c.Lock() - defer c.Unlock() - C.gio_makeCurrentContext(c.ctx) - return nil -} - -func (c *context) ReleaseCurrent() { - C.gio_clearCurrentContext() -} - func (w *window) NewContext() (Context, error) { return newContext(w) } diff --git a/app/internal/wm/window.go b/app/internal/wm/window.go index 058c2e1b..68ebabc4 100644 --- a/app/internal/wm/window.go +++ b/app/internal/wm/window.go @@ -69,11 +69,9 @@ type Callbacks interface { type Context interface { API() gpu.API Present() error - MakeCurrent() error - ReleaseCurrent() Refresh() error Release() - Lock() + Lock() error Unlock() } diff --git a/app/loop.go b/app/loop.go index f8058181..ae2e45b2 100644 --- a/app/loop.go +++ b/app/loop.go @@ -17,14 +17,12 @@ type renderLoop struct { drawing bool err error - ctx wm.Context - frames chan frame - results chan frameResult - refresh chan struct{} - refreshErr chan error - ack chan struct{} - stop chan struct{} - stopped chan struct{} + ctx wm.Context + frames chan frame + results chan frameResult + ack chan struct{} + stop chan struct{} + stopped chan struct{} } type frame struct { @@ -39,11 +37,9 @@ type frameResult struct { func newLoop(ctx wm.Context) (*renderLoop, error) { l := &renderLoop{ - ctx: ctx, - frames: make(chan frame), - results: make(chan frameResult), - refresh: make(chan struct{}), - refreshErr: make(chan error), + ctx: ctx, + frames: make(chan frame), + results: make(chan frameResult), // Ack is buffered so GPU commands can be issued after // ack'ing the frame. ack: make(chan struct{}, 1), @@ -65,25 +61,35 @@ func (l *renderLoop) renderLoop(ctx wm.Context) error { runtime.LockOSThread() // Don't UnlockOSThread to avoid reuse by the Go runtime. - if err := ctx.MakeCurrent(); err != nil { + if err := ctx.Lock(); err != nil { initErr <- err return } - defer ctx.ReleaseCurrent() g, err := gpu.New(ctx.API()) if err != nil { + ctx.Unlock() initErr <- err return } - defer g.Release() + defer func() { + if err := ctx.Lock(); err != nil { + return + } + defer ctx.Unlock() + g.Release() + }() + ctx.Unlock() initErr <- nil loop: for { select { - case <-l.refresh: - l.refreshErr <- ctx.MakeCurrent() case frame := <-l.frames: - ctx.Lock() + var res frameResult + res.err = ctx.Lock() + if res.err != nil { + l.results <- res + break + } if runtime.GOOS == "js" { // Use transparent black when Gio is embedded, to allow mixing of Gio and // foreign content below. @@ -94,7 +100,6 @@ func (l *renderLoop) renderLoop(ctx wm.Context) error { g.Collect(frame.viewport, frame.ops) // Signal that we're done with the frame ops. l.ack <- struct{}{} - var res frameResult res.err = g.Frame() if res.err == nil { res.err = ctx.Present() @@ -134,16 +139,6 @@ func (l *renderLoop) Summary() string { return l.summary } -func (l *renderLoop) Refresh() { - if l.err != nil { - return - } - // Make sure any pending frame is complete. - l.Flush() - l.refresh <- struct{}{} - l.setErr(<-l.refreshErr) -} - // Draw initiates a draw of a frame. It returns a channel // than signals when the frame is no longer being accessed. func (l *renderLoop) Draw(viewport image.Point, frameOps *op.Ops) <-chan struct{} { diff --git a/app/window.go b/app/window.go index 35abdbff..42289ee5 100644 --- a/app/window.go +++ b/app/window.go @@ -149,6 +149,7 @@ func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size if err != nil { return err } + sync = true } w.loop, err = newLoop(w.ctx) if err != nil { @@ -156,6 +157,11 @@ func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size return err } } + if sync && w.ctx != nil { + w.driverRun(func(_ wm.Driver) { + w.ctx.Refresh() + }) + } w.processFrame(frameStart, size, frame) if sync && w.loop != nil { if err := w.loop.Flush(); err != nil { @@ -416,13 +422,6 @@ func (w *Window) destroy(err error) { } } -func (w *Window) refresh() { - w.driverRun(func(_ wm.Driver) { - w.ctx.Refresh() - }) - w.loop.Refresh() -} - func (w *Window) destroyGPU() { if w.loop != nil { w.loop.Release() @@ -484,8 +483,6 @@ func (w *Window) run(opts *wm.Options) { w.loop.Release() w.loop = nil } - } else { - w.refresh() } } w.stage = e2.Stage @@ -505,11 +502,6 @@ func (w *Window) run(opts *wm.Options) { e2.Frame = w.update e2.Queue = &w.queue w.out <- e2.FrameEvent - if w.loop != nil { - if e2.Sync { - w.refresh() - } - } frame, gotFrame := w.waitFrame() err := w.validateAndProcess(driver, frameStart, e2.Size, e2.Sync, frame) if gotFrame {