diff --git a/internal/driver/ui.go b/internal/driver/ui.go index fcba01db3..9ff6d001c 100644 --- a/internal/driver/ui.go +++ b/internal/driver/ui.go @@ -31,8 +31,8 @@ type UIContext interface { var RegularTermination = errors.New("regular termination") type UI interface { - Run(context UIContext, graphics Graphics) error - RunWithoutMainLoop(width, height int, scale float64, title string, context UIContext, graphics Graphics) <-chan error + Run(context UIContext) error + RunWithoutMainLoop(width, height int, scale float64, title string, context UIContext) <-chan error DeviceScaleFactor() float64 CursorMode() CursorMode @@ -51,6 +51,7 @@ type UI interface { Input() Input Window() Window + Graphics() Graphics } type Window interface { diff --git a/graphicsdriver_mac.go b/internal/uidriver/glfw/graphics_mac.go similarity index 96% rename from graphicsdriver_mac.go rename to internal/uidriver/glfw/graphics_mac.go index d8f331761..17a72955e 100644 --- a/graphicsdriver_mac.go +++ b/internal/uidriver/glfw/graphics_mac.go @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build darwin,!ios +// +build darwin // +build !js // +build !ebitengl -package ebiten +package glfw // #cgo CFLAGS: -x objective-c // #cgo LDFLAGS: -framework Foundation @@ -48,7 +48,7 @@ var ( isMetalSupportedOnce sync.Once ) -func graphicsDriver() driver.Graphics { +func (*UserInterface) Graphics() driver.Graphics { isMetalSupportedOnce.Do(func() { // On old mac devices like iMac 2011, Metal is not supported (#779). if _, err := mtl.CreateSystemDefaultDevice(); err != nil { diff --git a/graphicsdriver_opengl.go b/internal/uidriver/glfw/graphics_opengl.go similarity index 84% rename from graphicsdriver_opengl.go rename to internal/uidriver/glfw/graphics_opengl.go index c30a8331e..881fda678 100644 --- a/graphicsdriver_opengl.go +++ b/internal/uidriver/glfw/graphics_opengl.go @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build android darwin,ios,386 darwin,ios,amd64 freebsd js linux windows ebitengl +// +build freebsd js linux windows ebitengl -package ebiten +package glfw import ( "github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl" ) -func graphicsDriver() driver.Graphics { +func (*UserInterface) Graphics() driver.Graphics { return opengl.Get() } diff --git a/internal/uidriver/glfw/ui.go b/internal/uidriver/glfw/ui.go index 5206dea73..f59fb34ba 100644 --- a/internal/uidriver/glfw/ui.go +++ b/internal/uidriver/glfw/ui.go @@ -72,9 +72,8 @@ type UserInterface struct { reqWidth int reqHeight int - graphics driver.Graphics - input Input - iwindow window + input Input + iwindow window t *thread.Thread m sync.RWMutex @@ -509,11 +508,10 @@ func init() { runtime.LockOSThread() } -func (u *UserInterface) Run(uicontext driver.UIContext, graphics driver.Graphics) error { +func (u *UserInterface) Run(uicontext driver.UIContext) error { // Initialize the main thread first so the thread is available at u.run (#809). u.t = thread.New() - u.graphics = graphics - u.graphics.SetThread(u.t) + u.Graphics().SetThread(u.t) ctx, cancel := context.WithCancel(context.Background()) @@ -532,7 +530,7 @@ func (u *UserInterface) Run(uicontext driver.UIContext, graphics driver.Graphics return <-ch } -func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error { +func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext) <-chan error { panic("glfw: RunWithoutMainLoop is not implemented") } @@ -553,7 +551,7 @@ func (u *UserInterface) createWindow() error { } u.window = window - if u.graphics.IsGL() { + if u.Graphics().IsGL() { u.window.MakeContextCurrent() } @@ -591,7 +589,7 @@ func (u *UserInterface) run(context driver.UIContext) error { u.window.Destroy() u.window = nil - if u.graphics.IsGL() { + if u.Graphics().IsGL() { glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) } else { @@ -609,7 +607,7 @@ func (u *UserInterface) run(context driver.UIContext) error { transparent = glfw.True } glfw.WindowHint(glfw.TransparentFramebuffer, transparent) - u.graphics.SetTransparent(u.isInitScreenTransparent()) + u.Graphics().SetTransparent(u.isInitScreenTransparent()) resizable := glfw.False if u.isInitWindowResizable() { @@ -652,7 +650,7 @@ func (u *UserInterface) run(context driver.UIContext) error { w = u.nativeWindow() return nil }) - u.graphics.SetWindow(w) + u.Graphics().SetWindow(w) return u.loop(context) } @@ -807,7 +805,7 @@ func (u *UserInterface) loop(context driver.UIContext) error { // swapBuffers must be called from the main thread. func (u *UserInterface) swapBuffers() { - if u.graphics.IsGL() { + if u.Graphics().IsGL() { u.window.SwapBuffers() } } @@ -844,13 +842,13 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync // Swapping buffer is necesary to prevent the image lag (#1004). // TODO: This might not work when vsync is disabled. - if u.graphics.IsGL() { + if u.Graphics().IsGL() { glfw.PollEvents() u.swapBuffers() } } else { if u.window.GetMonitor() != nil { - if u.graphics.IsGL() { + if u.Graphics().IsGL() { // When OpenGL is used, swapping buffer is enough to solve the image-lag // issue (#1004). Rather, recreating window destroys GPU resources. // TODO: This might not work when vsync is disabled. @@ -929,7 +927,7 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync u.windowWidth = width u.windowHeight = height - if u.graphics.IsGL() { + if u.Graphics().IsGL() { // SwapInterval is affected by the current monitor of the window. // This needs to be called at least after SetMonitor. // Without SwapInterval after SetMonitor, vsynch doesn't work (#375). @@ -943,14 +941,14 @@ func (u *UserInterface) setWindowSize(width, height int, fullscreen bool, vsync glfw.SwapInterval(0) } } - u.graphics.SetVsyncEnabled(vsync) + u.Graphics().SetVsyncEnabled(vsync) u.toChangeSize = true return nil }) if windowRecreated { - u.graphics.SetWindow(u.nativeWindow()) + u.Graphics().SetWindow(u.nativeWindow()) } } diff --git a/internal/uidriver/js/ui.go b/internal/uidriver/js/ui.go index 410158804..f03d90cab 100644 --- a/internal/uidriver/js/ui.go +++ b/internal/uidriver/js/ui.go @@ -24,6 +24,7 @@ import ( "github.com/hajimehoshi/ebiten/internal/devicescale" "github.com/hajimehoshi/ebiten/internal/driver" + "github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl" "github.com/hajimehoshi/ebiten/internal/hooks" "github.com/hajimehoshi/ebiten/internal/jsutil" ) @@ -371,7 +372,7 @@ func init() { })) } -func (u *UserInterface) Run(context driver.UIContext, graphics driver.Graphics) error { +func (u *UserInterface) Run(context driver.UIContext) error { canvas.Call("focus") u.running = true ch := u.loop(context) @@ -392,7 +393,7 @@ func (u *UserInterface) Run(context driver.UIContext, graphics driver.Graphics) return nil } -func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error { +func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext) <-chan error { panic("js: RunWithoutMainLoop is not implemented") } @@ -434,3 +435,7 @@ func (u *UserInterface) Input() driver.Input { func (u *UserInterface) Window() driver.Window { return nil } + +func (*UserInterface) Graphics() driver.Graphics { + return opengl.Get() +} diff --git a/graphicsdriver_ios.go b/internal/uidriver/mobile/graphics_ios.go similarity index 91% rename from graphicsdriver_ios.go rename to internal/uidriver/mobile/graphics_ios.go index 76a590c37..009296bb5 100644 --- a/graphicsdriver_ios.go +++ b/internal/uidriver/mobile/graphics_ios.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build darwin,ios,arm darwin,ios,arm64 +// +build ios,arm ios,arm64 // +build !ebitengl -package ebiten +package mobile import ( "fmt" @@ -25,7 +25,7 @@ import ( "github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl" ) -func graphicsDriver() driver.Graphics { +func (*UserInterface) Graphics() driver.Graphics { if _, err := mtl.CreateSystemDefaultDevice(); err != nil { panic(fmt.Sprintf("ebiten: mtl.CreateSystemDefaultDevice failed on iOS: %v", err)) } diff --git a/internal/uidriver/mobile/graphics_opengl.go b/internal/uidriver/mobile/graphics_opengl.go new file mode 100644 index 000000000..d752945e4 --- /dev/null +++ b/internal/uidriver/mobile/graphics_opengl.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build android ios,386 ios,amd64 ebitengl + +package mobile + +import ( + "github.com/hajimehoshi/ebiten/internal/driver" + "github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl" +) + +func (*UserInterface) Graphics() driver.Graphics { + return opengl.Get() +} diff --git a/internal/uidriver/mobile/ui.go b/internal/uidriver/mobile/ui.go index 8e70d3263..e1f2fe2a5 100644 --- a/internal/uidriver/mobile/ui.go +++ b/internal/uidriver/mobile/ui.go @@ -72,7 +72,7 @@ func (u *UserInterface) Update() { } }() - if u.graphics.IsGL() { + if u.Graphics().IsGL() { if u.glWorker == nil { panic("mobile: glWorker must be initialized but not") } @@ -105,8 +105,7 @@ type UserInterface struct { gbuildHeightPx int setGBuildSizeCh chan struct{} - context driver.UIContext - graphics driver.Graphics + context driver.UIContext input Input @@ -182,12 +181,12 @@ func (u *UserInterface) appMain(a app.App) { } } -func (u *UserInterface) Run(context driver.UIContext, graphics driver.Graphics) error { +func (u *UserInterface) Run(context driver.UIContext) error { // TODO: Remove width/height/scale arguments. They are not used from gomobile-build. u.setGBuildSizeCh = make(chan struct{}) go func() { - if err := u.run(16, 16, 1, context, graphics, true); err != nil { + if err := u.run(16, 16, 1, context, true); err != nil { // As mobile apps never ends, Loop can't return. Just panic here. panic(err) } @@ -196,12 +195,12 @@ func (u *UserInterface) Run(context driver.UIContext, graphics driver.Graphics) return nil } -func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext, graphics driver.Graphics) <-chan error { +func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, title string, context driver.UIContext) <-chan error { ch := make(chan error) go func() { defer close(ch) // title is ignored? - if err := u.run(width, height, scale, context, graphics, false); err != nil { + if err := u.run(width, height, scale, context, false); err != nil { ch <- err } }() @@ -209,7 +208,7 @@ func (u *UserInterface) RunWithoutMainLoop(width, height int, scale float64, tit return ch } -func (u *UserInterface) run(width, height int, scale float64, context driver.UIContext, graphics driver.Graphics, mainloop bool) (err error) { +func (u *UserInterface) run(width, height int, scale float64, context driver.UIContext, mainloop bool) (err error) { // Convert the panic to a regular error so that Java/Objective-C layer can treat this easily e.g., for // Crashlytics. A panic is treated as SIGABRT, and there is no way to handle this on Java/Objective-C layer // unfortunately. @@ -226,20 +225,19 @@ func (u *UserInterface) run(width, height int, scale float64, context driver.UIC u.scale = scale u.sizeChanged = true u.context = context - u.graphics = graphics u.m.Unlock() - if graphics.IsGL() { + if u.Graphics().IsGL() { var ctx gl.Context if mainloop { ctx = <-glContextCh } else { ctx, u.glWorker = gl.NewContext() } - graphics.(*opengl.Driver).SetMobileGLContext(ctx) + u.Graphics().(*opengl.Driver).SetMobileGLContext(ctx) } else { u.t = thread.New() - graphics.SetThread(u.t) + u.Graphics().SetThread(u.t) } // If gomobile-build is used, wait for the outside size fixed. diff --git a/run.go b/run.go index 0f3c2bd90..d4c094878 100644 --- a/run.go +++ b/run.go @@ -215,7 +215,7 @@ func RunGame(game Game) error { func runGame(game Game, scale float64) error { theUIContext.set(game, scale) - if err := uiDriver().Run(theUIContext, graphicsDriver()); err != nil { + if err := uiDriver().Run(theUIContext); err != nil { if err == driver.RegularTermination { return nil } @@ -236,7 +236,7 @@ func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64, height: height, } theUIContext.set(game, scale) - return uiDriver().RunWithoutMainLoop(width, height, scale, title, theUIContext, graphicsDriver()) + return uiDriver().RunWithoutMainLoop(width, height, scale, title, theUIContext) } // ScreenSizeInFullscreen is deprecated as of 1.11.0-alpha. diff --git a/uicontext.go b/uicontext.go index 073350ee5..819dc536f 100644 --- a/uicontext.go +++ b/uicontext.go @@ -28,8 +28,8 @@ import ( ) func init() { - shareable.SetGraphicsDriver(graphicsDriver()) - graphicscommand.SetGraphicsDriver(graphicsDriver()) + shareable.SetGraphicsDriver(uiDriver().Graphics()) + graphicscommand.SetGraphicsDriver(uiDriver().Graphics()) } type defaultGame struct { @@ -275,7 +275,7 @@ func (c *uiContext) update(afterFrameUpdate func()) error { op := &DrawImageOptions{} s := c.screenScale() - switch vd := graphicsDriver().VDirection(); vd { + switch vd := uiDriver().Graphics().VDirection(); vd { case driver.VDownward: // c.screen is special: its Y axis is down to up, // and the origin point is lower left.