mobile: Implement Pause and Resume to work correctly

This commit is contained in:
Hajime Hoshi 2016-06-10 01:21:46 +09:00
parent f03a99e89a
commit 8121b2102f
3 changed files with 64 additions and 25 deletions

View File

@ -173,10 +173,12 @@ func Run(g GraphicsContext, width, height, scale int, title string, fps int) err
if err := g.Pause(); err != nil { if err := g.Pause(); err != nil {
return err return err
} }
e.Done <- struct{}{}
case ui.ResumeEvent: case ui.ResumeEvent:
if err := g.Resume(); err != nil { if err := g.Resume(); err != nil {
return err return err
} }
e.Done <- struct{}{}
default: default:
panic("not reach") panic("not reach")
} }

View File

@ -28,7 +28,9 @@ type RenderEvent struct {
} }
type PauseEvent struct { type PauseEvent struct {
Done chan struct{}
} }
type ResumeEvent struct { type ResumeEvent struct {
Done chan struct{}
} }

View File

@ -18,6 +18,7 @@ package ui
import ( import (
"errors" "errors"
"time"
"github.com/hajimehoshi/ebiten/internal/graphics/opengl" "github.com/hajimehoshi/ebiten/internal/graphics/opengl"
) )
@ -35,7 +36,28 @@ func Render(chError <-chan error) error {
return errors.New("ui: chError must not be nil") return errors.New("ui: chError must not be nil")
} }
// TODO: Check this is called on the rendering thread // TODO: Check this is called on the rendering thread
chRender <- struct{}{} select {
case <-chPauseStart:
if err := doGLWorks(chError, chPauseEnd); err != nil {
return err
}
chPauseEnd2 <- struct{}{}
return nil
case <-chResumeStart:
if err := doGLWorks(chError, chResumeEnd); err != nil {
return err
}
return nil
case chRender <- struct{}{}:
return doGLWorks(chError, chRenderEnd)
case <-time.After(500 * time.Millisecond):
// This function must not be blocked so we need to break after a while.
return nil
}
}
func doGLWorks(chError <-chan error, chDone <-chan struct{}) error {
// TODO: Check this is called on the rendering thread
worker := glContext.Worker() worker := glContext.Worker()
loop: loop:
for { for {
@ -46,7 +68,7 @@ loop:
worker.DoWork() worker.DoWork()
default: default:
select { select {
case <-chRenderEnd: case <-chDone:
break loop break loop
default: default:
} }
@ -60,19 +82,23 @@ type userInterface struct {
height int height int
scale int scale int
sizeChanged bool sizeChanged bool
chRender chan struct{} paused bool
chRenderEnd chan struct{}
chPause chan struct{}
chResume chan struct{}
} }
var ( var (
chRender = make(chan struct{}) // TODO: Rename these channels
chRenderEnd = make(chan struct{}) chRender = make(chan struct{})
currentUI = &userInterface{ chRenderEnd = make(chan struct{})
chPause = make(chan struct{})
chPauseStart = make(chan struct{})
chPauseEnd = make(chan struct{})
chPauseEnd2 = make(chan struct{})
chResume = make(chan struct{})
chResumeStart = make(chan struct{})
chResumeEnd = make(chan struct{})
currentUI = &userInterface{
sizeChanged: true, sizeChanged: true,
chRender: chRender, paused: false,
chRenderEnd: chRenderEnd,
} }
) )
@ -104,12 +130,20 @@ func (u *userInterface) Update() (interface{}, error) {
} }
return e, nil return e, nil
} }
if u.paused {
select {
case <-chResume:
u.paused = false
chResumeStart <- struct{}{}
return ResumeEvent{chResumeEnd}, nil
}
}
select { select {
case <-u.chPause: case <-chPause:
return PauseEvent{}, nil u.paused = true
case <-u.chResume: chPauseStart <- struct{}{}
return ResumeEvent{}, nil return PauseEvent{chPauseEnd}, nil
case <-u.chRender: case <-chRender:
return RenderEvent{}, nil return RenderEvent{}, nil
} }
} }
@ -119,7 +153,7 @@ func (u *userInterface) SwapBuffers() error {
} }
func (u *userInterface) FinishRendering() error { func (u *userInterface) FinishRendering() error {
u.chRenderEnd <- struct{}{} chRenderEnd <- struct{}{}
return nil return nil
} }
@ -141,16 +175,17 @@ func (u *userInterface) actualScreenScale() int {
return u.scale return u.scale
} }
func Pause() { func Pause() error {
go func() { // Pause must be done in the current GL context.
currentUI.chPause <- struct{}{} chPause <- struct{}{}
}() <-chPauseEnd2
return nil
} }
func Resume() { func Resume() error {
go func() { chResume <- struct{}{}
currentUI.chResume <- struct{}{} // Don't have to wait for resumeing done.
}() return nil
} }
func UpdateTouches(touches []Touch) { func UpdateTouches(touches []Touch) {