app: don't touch the frame after returning from FrameEvent.Frame

It was already true that the GPU wouldn't touch the frame after
calling GPU.Draw. This change makes FrameEvent.Frame block until
GPU.Draw is complete.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-11-07 17:34:32 +01:00
parent 6fedfaf3af
commit d980c4652a
+15 -2
View File
@@ -36,6 +36,7 @@ type Window struct {
ack chan struct{} ack chan struct{}
invalidates chan struct{} invalidates chan struct{}
frames chan *op.Ops frames chan *op.Ops
frameAck chan struct{}
stage system.Stage stage system.Stage
animating bool animating bool
@@ -95,6 +96,7 @@ func NewWindow(options ...Option) *Window {
ack: make(chan struct{}), ack: make(chan struct{}),
invalidates: make(chan struct{}, 1), invalidates: make(chan struct{}, 1),
frames: make(chan *op.Ops), frames: make(chan *op.Ops),
frameAck: make(chan struct{}),
} }
w.callbacks.w = w w.callbacks.w = w
go w.run(opts) go w.run(opts)
@@ -118,6 +120,7 @@ func (w *Window) Queue() *Queue {
// the window state from previous calls. // the window state from previous calls.
func (w *Window) update(frame *op.Ops) { func (w *Window) update(frame *op.Ops) {
w.frames <- frame w.frames <- frame
<-w.frameAck
} }
func (w *Window) draw(size image.Point, frame *op.Ops) { func (w *Window) draw(size image.Point, frame *op.Ops) {
@@ -279,17 +282,27 @@ func (w *Window) run(opts *window.Options) {
} }
} }
var frame *op.Ops var frame *op.Ops
// Wait for either a frame or the ack event, // Wait for either a frame or an ack event to go
// which meant that the client didn't draw. // through, which means that the client didn't give us
// a frame.
gotFrame := false
select { select {
case frame = <-w.frames: case frame = <-w.frames:
gotFrame = true
case w.out <- ackEvent: case w.out <- ackEvent:
} }
if err != nil { if err != nil {
if gotFrame {
w.frameAck <- struct{}{}
}
w.destroy(err) w.destroy(err)
return return
} }
if gotFrame {
w.draw(e2.Size, frame) w.draw(e2.Size, frame)
// We're done with frame, let the client continue.
w.frameAck <- struct{}{}
}
if e2.Sync { if e2.Sync {
if err := w.gpu.Flush(); err != nil { if err := w.gpu.Flush(); err != nil {
w.gpu.Release() w.gpu.Release()