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
IsWindowDecorated() bool
IsWindowResizable() bool
Loop(ch <-chan error) error
Run(width, height int, scale float64, title string, context UIContext, mainloop bool, graphics Graphics) error
Run(width, height int, scale float64, title string, context UIContext, graphics Graphics) error
RunWithoutMainLoop(width, height int, scale float64, title string, context UIContext, graphics Graphics) <-chan error
ScreenPadding() (x0, y0, x1, y1 float64)
ScreenScale() float64
ScreenSizeInFullscreen() (int, int)

View File

@ -170,7 +170,7 @@ func getCachedMonitor(wx, wy int) (*cachedMonitor, bool) {
return nil, false
}
func (u *UserInterface) Loop(ch <-chan error) error {
func (u *UserInterface) mainThreadLoop(ch <-chan error) error {
u.setRunning(true)
if err := mainthread.Loop(ch); err != nil {
return err
@ -555,7 +555,26 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
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 {
u.graphics = graphics

View File

@ -384,11 +384,7 @@ func init() {
}))
}
func (u *UserInterface) Loop(ch <-chan error) error {
return <-ch
}
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 {
document.Set("title", title)
u.setScreenSize(width, height, scale, u.fullscreen)
canvas.Call("focus")
@ -407,6 +403,10 @@ func (u *UserInterface) Run(width, height int, scale float64, title string, cont
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 {
if u.width == width && u.height == height &&
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() {
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) {
width, height := 0, 0
actualScale := 0.0

53
run.go
View File

@ -90,21 +90,6 @@ func IsRunningSlowly() bool {
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.
// f is a function which is called at every frame.
// 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 {
f = (&imageDumper{f: f}).update
ch := make(chan error)
go func() {
defer close(ch)
c := newUIContext(f)
theUIContext.Store(c)
g := newUIContext(f)
theUIContext.Store(g)
if err := run(width, height, scale, title, g, true); err != nil {
ch <- err
return
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, 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 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 {
f = (&imageDumper{f: f}).update
ch := make(chan error)
go func() {
defer close(ch)
c := newUIContext(f)
theUIContext.Store(c)
g := newUIContext(f)
theUIContext.Store(g)
if err := run(width, height, scale, title, g, false); err != nil {
ch <- err
return
}
}()
return ch
atomic.StoreInt32(&isRunning, 1)
return uiDriver().RunWithoutMainLoop(width, height, scale, title, c, graphicsDriver())
}
// ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen.