driver: Remove UI.Loop and add UI.RunWithoutMainLoop

This commit is contained in:
Hajime Hoshi 2019-04-09 21:44:02 -04:00
parent dea7118733
commit db689f4e50
5 changed files with 67 additions and 58 deletions

View File

@ -39,8 +39,8 @@ type UI interface {
IsVsyncEnabled() bool IsVsyncEnabled() bool
IsWindowDecorated() bool IsWindowDecorated() bool
IsWindowResizable() bool IsWindowResizable() bool
Loop(ch <-chan error) error Run(width, height int, scale float64, title string, context UIContext, graphics Graphics) error
Run(width, height int, scale float64, title string, context UIContext, mainloop bool, graphics Graphics) error RunWithoutMainLoop(width, height int, scale float64, title string, context UIContext, graphics Graphics) <-chan error
ScreenPadding() (x0, y0, x1, y1 float64) ScreenPadding() (x0, y0, x1, y1 float64)
ScreenScale() float64 ScreenScale() float64
ScreenSizeInFullscreen() (int, int) ScreenSizeInFullscreen() (int, int)

View File

@ -170,7 +170,7 @@ func getCachedMonitor(wx, wy int) (*cachedMonitor, bool) {
return nil, false return nil, false
} }
func (u *UserInterface) Loop(ch <-chan error) error { func (u *UserInterface) mainThreadLoop(ch <-chan error) error {
u.setRunning(true) u.setRunning(true)
if err := mainthread.Loop(ch); err != nil { if err := mainthread.Loop(ch); err != nil {
return err return err
@ -555,7 +555,26 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
return f return f
} }
func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, mainloop bool, graphics driver.Graphics) error { func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) error {
ch := make(chan error)
go func() {
defer close(ch)
if err := u.run(width, height, scale, title, context, graphics); err != nil {
ch <- err
}
}()
if err := u.mainThreadLoop(ch); err != nil {
return err
}
return nil
}
func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error {
panic("glfw: RunWithoutMainLoop is not implemented")
}
func (u *UserInterface) run(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) error {
_ = mainthread.Run(func() error { _ = mainthread.Run(func() error {
u.graphics = graphics u.graphics = graphics

View File

@ -384,11 +384,7 @@ func init() {
})) }))
} }
func (u *UserInterface) Loop(ch <-chan error) error { func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) error {
return <-ch
}
func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, mainloop bool, graphics driver.Graphics) error {
document.Set("title", title) document.Set("title", title)
u.setScreenSize(width, height, scale, u.fullscreen) u.setScreenSize(width, height, scale, u.fullscreen)
canvas.Call("focus") canvas.Call("focus")
@ -407,6 +403,10 @@ func (u *UserInterface) Run(width, height int, scale float64, title string, cont
return nil return nil
} }
func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error {
panic("js: RunWithoutMainLoop is not implemented")
}
func (u *UserInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool { func (u *UserInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
if u.width == width && u.height == height && if u.width == width && u.height == height &&
u.scale == scale && fullscreen == u.fullscreen { u.scale == scale && fullscreen == u.fullscreen {

View File

@ -153,7 +153,29 @@ func (u *UserInterface) appMain(a app.App) {
} }
} }
func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, mainloop bool, graphics driver.Graphics) error { func (u *UserInterface) Run(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) error {
go func() {
if err := u.run(width, height, scale, title, context, graphics, true); err != nil {
// As mobile apps never ends, Loop can't return. Just panic here.
panic(err)
}
}()
app.Main(u.appMain)
return nil
}
func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error {
ch := make(chan error)
go func() {
defer close(ch)
if err := u.run(width, height, scale, title, context, graphics, false); err != nil {
ch <- err
}
}()
return ch
}
func (u *UserInterface) run(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics, mainloop bool) error {
if graphics != opengl.Get() { if graphics != opengl.Get() {
panic("ui: graphics driver must be OpenGL") panic("ui: graphics driver must be OpenGL")
} }
@ -182,17 +204,6 @@ func (u *UserInterface) Run(width, height int, scale float64, title string, cont
} }
} }
// Loop runs the main routine for gomobile-build.
func (u *UserInterface) Loop(ch <-chan error) error {
go func() {
// As mobile apps never ends, Loop can't return. Just panic here.
err := <-ch
panic(err)
}()
app.Main(u.appMain)
return nil
}
func (u *UserInterface) updateSize(context driver.UIContext) { func (u *UserInterface) updateSize(context driver.UIContext) {
width, height := 0, 0 width, height := 0, 0
actualScale := 0.0 actualScale := 0.0

53
run.go
View File

@ -90,21 +90,6 @@ func IsRunningSlowly() bool {
var theUIContext atomic.Value var theUIContext atomic.Value
func run(width, height int, scale float64, title string, context *uiContext, mainloop bool) error {
atomic.StoreInt32(&isRunning, 1)
// On GopherJS, run returns immediately.
if !web.IsGopherJS() {
defer atomic.StoreInt32(&isRunning, 0)
}
if err := uiDriver().Run(width, height, scale, title, context, mainloop, graphicsDriver()); err != nil {
if err == driver.RegularTermination {
return nil
}
return err
}
return nil
}
// Run runs the game. // Run runs the game.
// f is a function which is called at every frame. // f is a function which is called at every frame.
// The argument (*Image) is the render target that represents the screen. // The argument (*Image) is the render target that represents the screen.
@ -143,21 +128,22 @@ func run(width, height int, scale float64, title string, context *uiContext, mai
func Run(f func(*Image) error, width, height int, scale float64, title string) error { func Run(f func(*Image) error, width, height int, scale float64, title string) error {
f = (&imageDumper{f: f}).update f = (&imageDumper{f: f}).update
ch := make(chan error) c := newUIContext(f)
go func() { theUIContext.Store(c)
defer close(ch)
g := newUIContext(f) atomic.StoreInt32(&isRunning, 1)
theUIContext.Store(g) // On GopherJS, run returns immediately.
if err := run(width, height, scale, title, g, true); err != nil { if !web.IsGopherJS() {
ch <- err defer atomic.StoreInt32(&isRunning, 0)
return }
if err := uiDriver().Run(width, height, scale, title, c, graphicsDriver()); err != nil {
if err == driver.RegularTermination {
return nil
} }
}()
// TODO: Use context in Go 1.7?
if err := uiDriver().Loop(ch); err != nil {
return err return err
} }
return nil return nil
} }
@ -169,18 +155,11 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64, title string) <-chan error { func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64, title string) <-chan error {
f = (&imageDumper{f: f}).update f = (&imageDumper{f: f}).update
ch := make(chan error) c := newUIContext(f)
go func() { theUIContext.Store(c)
defer close(ch)
g := newUIContext(f) atomic.StoreInt32(&isRunning, 1)
theUIContext.Store(g) return uiDriver().RunWithoutMainLoop(width, height, scale, title, c, graphicsDriver())
if err := run(width, height, scale, title, g, false); err != nil {
ch <- err
return
}
}()
return ch
} }
// ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen. // ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen.