From 5d2e2476b6d1974ea659a8a32b8d3bac25da9cd4 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 7 Jan 2014 02:14:53 +0900 Subject: [PATCH] Refactoring: lazy initializing the application --- example/main.go | 2 +- ui/cocoa/game_window.go | 34 ++++++++++++++------------ ui/cocoa/texture_factory.go | 48 ++++++++++++++++++++++++------------- ui/cocoa/ui.go | 12 ++++++---- ui/ui.go | 2 +- 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/example/main.go b/example/main.go index da2fa38cf..9f5779833 100644 --- a/example/main.go +++ b/example/main.go @@ -59,7 +59,7 @@ func main() { } }() - //u.MainLoop() + u.RunMainLoop() for { u.PollEvents() diff --git a/ui/cocoa/game_window.go b/ui/cocoa/game_window.go index 1b0e29db9..0803feea2 100644 --- a/ui/cocoa/game_window.go +++ b/ui/cocoa/game_window.go @@ -30,6 +30,7 @@ type GameWindow struct { screenWidth int screenHeight int screenScale int + title string closed bool native *C.EbitenGameWindow pressedKeys map[ui.Key]struct{} @@ -41,27 +42,30 @@ type GameWindow struct { var windows = map[*C.EbitenGameWindow]*GameWindow{} -func runGameWindow(graphicsDevice *opengl.Device, width, height, scale int, title string, sharedContext *C.NSOpenGLContext) *GameWindow { - w := &GameWindow{ - graphicsDevice: graphicsDevice, - screenWidth: width, - screenHeight: height, - screenScale: scale, - closed: false, - pressedKeys: map[ui.Key]struct{}{}, - funcs: make(chan func()), - funcsDone: make(chan struct{}), +func newGameWindow(width, height, scale int, title string) *GameWindow { + return &GameWindow{ + screenWidth: width, + screenHeight: height, + screenScale: scale, + title: title, + closed: false, + pressedKeys: map[ui.Key]struct{}{}, + funcs: make(chan func()), + funcsDone: make(chan struct{}), } +} - cTitle := C.CString(title) +func (w *GameWindow) run(graphicsDevice *opengl.Device, sharedContext *C.NSOpenGLContext) { + cTitle := C.CString(w.title) defer C.free(unsafe.Pointer(cTitle)) ch := make(chan struct{}) go func() { runtime.LockOSThread() glContext := C.CreateGLContext(sharedContext) - w.native = C.CreateGameWindow(C.size_t(width*scale), - C.size_t(height*scale), + w.graphicsDevice = graphicsDevice + w.native = C.CreateGameWindow(C.size_t(w.screenWidth*w.screenScale), + C.size_t(w.screenHeight*w.screenScale), cTitle, glContext) windows[w.native] = w @@ -70,9 +74,9 @@ func runGameWindow(graphicsDevice *opengl.Device, width, height, scale int, titl }() <-ch w.useGLContext(func() { - w.context = w.graphicsDevice.CreateContext(width, height, scale) + w.context = w.graphicsDevice.CreateContext( + w.screenWidth, w.screenHeight, w.screenScale) }) - return w } func (w *GameWindow) loop() { diff --git a/ui/cocoa/texture_factory.go b/ui/cocoa/texture_factory.go index 604aaceec..fb480dbb5 100644 --- a/ui/cocoa/texture_factory.go +++ b/ui/cocoa/texture_factory.go @@ -15,37 +15,45 @@ import ( ) type textureFactory struct { - sharedContext *C.NSOpenGLContext + inited chan struct{} graphicsDevice *opengl.Device events chan interface{} funcs chan func() funcsDone chan struct{} + gameWindows chan *GameWindow } -func runTextureFactory() *textureFactory { - t := &textureFactory{ - funcs: make(chan func()), - funcsDone: make(chan struct{}), +func newTextureFactory() *textureFactory { + return &textureFactory{ + inited: make(chan struct{}), + funcs: make(chan func()), + funcsDone: make(chan struct{}), + gameWindows: make(chan *GameWindow), } - ch := make(chan struct{}) +} + +func (t *textureFactory) run() { + var sharedContext *C.NSOpenGLContext go func() { runtime.LockOSThread() - t.sharedContext = C.CreateGLContext(nil) - close(ch) - t.loop() - }() - <-ch - t.useGLContext(func() { t.graphicsDevice = opengl.NewDevice() - }) - return t + sharedContext = C.CreateGLContext(nil) + close(t.inited) + t.loop(sharedContext) + }() + <-t.inited + go func() { + for w := range t.gameWindows { + w.run(t.graphicsDevice, sharedContext) + } + }() } -func (t *textureFactory) loop() { +func (t *textureFactory) loop(sharedContext *C.NSOpenGLContext) { for { select { case f := <-t.funcs: - C.UseGLContext(t.sharedContext) + C.UseGLContext(sharedContext) f() C.UnuseGLContext() t.funcsDone <- struct{}{} @@ -59,7 +67,11 @@ func (t *textureFactory) useGLContext(f func()) { } func (t *textureFactory) createGameWindow(width, height, scale int, title string) *GameWindow { - return runGameWindow(t.graphicsDevice, width, height, scale, title, t.sharedContext) + w := newGameWindow(width, height, scale, title) + go func() { + t.gameWindows <- w + }() + return w } func (t *textureFactory) Events() <-chan interface{} { @@ -72,6 +84,7 @@ func (t *textureFactory) Events() <-chan interface{} { func (t *textureFactory) CreateTexture(tag interface{}, img image.Image, filter graphics.Filter) { go func() { + <-t.inited var id graphics.TextureId var err error t.useGLContext(func() { @@ -91,6 +104,7 @@ func (t *textureFactory) CreateTexture(tag interface{}, img image.Image, filter func (t *textureFactory) CreateRenderTarget(tag interface{}, width, height int) { go func() { + <-t.inited var id graphics.RenderTargetId var err error t.useGLContext(func() { diff --git a/ui/cocoa/ui.go b/ui/cocoa/ui.go index 2640c8ffb..cb9edfa81 100644 --- a/ui/cocoa/ui.go +++ b/ui/cocoa/ui.go @@ -25,10 +25,8 @@ func getCurrentUI() *cocoaUI { } currentUI = &cocoaUI{} + currentUI.textureFactory = newTextureFactory() - C.StartApplication() - - currentUI.textureFactory = runTextureFactory() return currentUI } @@ -48,6 +46,10 @@ func (u *cocoaUI) PollEvents() { C.PollEvents() } -func (u *cocoaUI) MainLoop() { - C.Run() +func (u *cocoaUI) RunMainLoop() { + C.StartApplication() + currentUI.textureFactory.run() + + // TODO: Enable the loop + //C.Run() } diff --git a/ui/ui.go b/ui/ui.go index 02f41ac50..a5de0b383 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -35,7 +35,7 @@ type WindowClosedEvent struct { type UI interface { PollEvents() CreateGameWindow(screenWidth, screenHeight, screenScale int, title string) GameWindow - MainLoop() + RunMainLoop() } type Window interface {