From 8d8aeef66befc4c91946d46444aafd52b214e361 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 5 Jan 2022 11:42:31 +0100 Subject: [PATCH] app,gpu,internal/egl: lock OS thread when making OpenGL context current OpenGL stores the current context in thread-local memory, but commit 4f5baa9a516 removed a runtime.LockOSThread from app.Window that ensured the goroutine that drives the context stays on the operating thread that has the context current. This change restores the thread lock. As a bonus, this change makes the OpenGL contexts responsible for locking the thread at MakeCurrent, thereby removing LockOSThread calls from GPU backend-agnostic code. Fixes: https://todo.sr.ht/~eliasnaur/gio/334 Signed-off-by: Elias Naur --- app/gl_ios.go | 4 ++++ app/gl_macos.go | 8 ++++++-- gpu/headless/driver_test.go | 1 - gpu/headless/headless.go | 3 --- internal/egl/egl.go | 3 +++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/gl_ios.go b/app/gl_ios.go index 98c98330..2dc2dbfd 100644 --- a/app/gl_ios.go +++ b/app/gl_ios.go @@ -31,6 +31,7 @@ import "C" import ( "errors" "fmt" + "runtime" "gioui.org/gpu" "gioui.org/internal/gl" @@ -101,6 +102,9 @@ func (c *context) Present() error { } func (c *context) Lock() error { + // OpenGL contexts are implicit and thread-local. Lock the OS thread. + runtime.LockOSThread() + if C.gio_makeCurrent(c.ctx) == 0 { return errors.New("[EAGLContext setCurrentContext] failed") } diff --git a/app/gl_macos.go b/app/gl_macos.go index b64213f3..7511bbd7 100644 --- a/app/gl_macos.go +++ b/app/gl_macos.go @@ -7,6 +7,9 @@ package app import ( "errors" + "runtime" + + "unsafe" "gioui.org/gpu" "gioui.org/internal/gl" @@ -35,8 +38,6 @@ static void glFlush(PFN_glFlush f) { */ import "C" -import "unsafe" - type glContext struct { c *gl.Functions ctx C.CFTypeRef @@ -95,6 +96,9 @@ func (c *glContext) Present() error { } func (c *glContext) Lock() error { + // OpenGL contexts are implicit and thread-local. Lock the OS thread. + runtime.LockOSThread() + C.gio_lockContext(c.ctx) C.gio_makeCurrentContext(c.ctx) return nil diff --git a/gpu/headless/driver_test.go b/gpu/headless/driver_test.go index dbfb253a..7e374453 100644 --- a/gpu/headless/driver_test.go +++ b/gpu/headless/driver_test.go @@ -165,7 +165,6 @@ func newDriver(t *testing.T) driver.Device { if err != nil { t.Skipf("no context available: %v", err) } - runtime.LockOSThread() if err := ctx.MakeCurrent(); err != nil { t.Fatal(err) } diff --git a/gpu/headless/headless.go b/gpu/headless/headless.go index 22d86b1e..17fd1c92 100644 --- a/gpu/headless/headless.go +++ b/gpu/headless/headless.go @@ -8,7 +8,6 @@ import ( "errors" "image" "image/color" - "runtime" "gioui.org/gpu" "gioui.org/gpu/internal/driver" @@ -146,8 +145,6 @@ func (w *Window) Screenshot(img *image.RGBA) error { func contextDo(ctx context, f func() error) error { errCh := make(chan error) go func() { - runtime.LockOSThread() - defer runtime.UnlockOSThread() if err := ctx.MakeCurrent(); err != nil { errCh <- err return diff --git a/internal/egl/egl.go b/internal/egl/egl.go index 7605d46e..7d7b5512 100644 --- a/internal/egl/egl.go +++ b/internal/egl/egl.go @@ -135,6 +135,9 @@ func (c *Context) ReleaseCurrent() { } func (c *Context) MakeCurrent() error { + // OpenGL contexts are implicit and thread-local. Lock the OS thread. + runtime.LockOSThread() + if c.eglSurf == nilEGLSurface && !c.eglCtx.surfaceless { return errors.New("no surface created yet EGL_KHR_surfaceless_context is not supported") }