app: accept pending frame before reporting error

If creating a GPU instance fails for some reason, we need to
receive the incoming frame from the application before reporting
the error in a DestroyEvent. If we don't, the a deadlock will occur
where the app is waiting for FrameEvent.Frame to complete, while
the Window waits for the app the receive a DestroyEvent.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-11-01 19:38:13 +01:00
parent 15e34e9ca2
commit 9126da41f4
+11 -12
View File
@@ -8,6 +8,7 @@ import (
"image"
"time"
"gioui.org/app/internal/gl"
"gioui.org/app/internal/gpu"
"gioui.org/app/internal/input"
"gioui.org/app/internal/window"
@@ -261,26 +262,20 @@ func (w *Window) run(opts *window.Options) {
w.hasNextFrame = false
e2.Frame = w.update
w.out <- e2.FrameEvent
var err error
if w.gpu != nil {
if e2.Sync {
w.gpu.Refresh()
}
if err := w.gpu.Flush(); err != nil {
if err = w.gpu.Flush(); err != nil {
w.gpu.Release()
w.gpu = nil
w.destroy(err)
return
}
} else {
ctx, err := w.driver.NewContext()
if err != nil {
w.destroy(err)
return
}
w.gpu, err = gpu.NewGPU(ctx)
if err != nil {
w.destroy(err)
return
var ctx gl.Context
ctx, err = w.driver.NewContext()
if err == nil {
w.gpu, err = gpu.NewGPU(ctx)
}
}
var frame *op.Ops
@@ -290,6 +285,10 @@ func (w *Window) run(opts *window.Options) {
case frame = <-w.frames:
case w.out <- ackEvent:
}
if err != nil {
w.destroy(err)
return
}
w.draw(e2.Size, frame)
if e2.Sync {
if err := w.gpu.Flush(); err != nil {