diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 125499040..a4998529c 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -83,13 +83,13 @@ func Get() *UserInterface { } func (u *UserInterface) imageAt(mipmap *mipmap.Mipmap, x, y int) (r, g, b, a byte, err error) { - return mipmap.At(graphicsDriver(), x, y) + return mipmap.At(u.graphicsDriver, x, y) } func (u *UserInterface) dumpScreenshot(mipmap *mipmap.Mipmap, name string, blackbg bool) error { - return mipmap.DumpScreenshot(graphicsDriver(), name, blackbg) + return mipmap.DumpScreenshot(u.graphicsDriver, name, blackbg) } func (u *UserInterface) dumpImages(dir string) error { - return atlas.DumpImages(graphicsDriver(), dir) + return atlas.DumpImages(u.graphicsDriver, dir) } diff --git a/internal/ui/ui_cbackend.go b/internal/ui/ui_cbackend.go index 3d047b3e0..21eb53ab8 100644 --- a/internal/ui/ui_cbackend.go +++ b/internal/ui/ui_cbackend.go @@ -21,6 +21,7 @@ import ( "runtime" "github.com/hajimehoshi/ebiten/v2/internal/cbackend" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" ) const deviceScaleFactor = 1 @@ -30,19 +31,22 @@ func init() { } type userInterfaceImpl struct { + graphicsDriver graphicsdriver.Graphics + context *contextImpl input Input } func (u *userInterfaceImpl) Run(game Game) error { u.context = newContextImpl(game) + u.graphicsDriver = graphicsDriver() cbackend.InitializeGame() for { cbackend.BeginFrame() u.input.update(u.context) w, h := cbackend.ScreenSize() - if err := u.context.updateFrame(graphicsDriver(), float64(w), float64(h), deviceScaleFactor); err != nil { + if err := u.context.updateFrame(u.graphicsDriver, float64(w), float64(h), deviceScaleFactor); err != nil { return err } diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 8fe5d3df3..644fc59eb 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -28,6 +28,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/devicescale" "github.com/hajimehoshi/ebiten/v2/internal/glfw" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/hooks" "github.com/hajimehoshi/ebiten/v2/internal/thread" ) @@ -46,6 +47,8 @@ func driverCursorModeToGLFWCursorMode(mode CursorMode) int { } type userInterfaceImpl struct { + graphicsDriver graphicsdriver.Graphics + context *contextImpl title string window *glfw.Window @@ -660,7 +663,7 @@ func (u *userInterfaceImpl) createWindow(width, height int) error { // Ensure to consume this callback. u.waitForFramebufferSizeCallback(u.window, nil) - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { u.window.MakeContextCurrent() } @@ -708,13 +711,13 @@ func (u *userInterfaceImpl) registerWindowSetSizeCallback() { // In order to call it safely, use runOnAnotherThreadFromMainThread. var err error u.runOnAnotherThreadFromMainThread(func() { - err = u.context.forceUpdateFrame(graphicsDriver(), outsideWidth, outsideHeight, deviceScaleFactor) + err = u.context.forceUpdateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor) }) if err != nil { u.err = err } - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { u.swapBuffers() } }) @@ -808,7 +811,8 @@ event: } func (u *userInterfaceImpl) init() error { - if graphicsDriver().IsGL() { + u.graphicsDriver = graphicsDriver() + if u.graphicsDriver.IsGL() { glfw.WindowHint(glfw.ClientAPI, glfw.OpenGLAPI) glfw.WindowHint(glfw.ContextVersionMajor, 2) glfw.WindowHint(glfw.ContextVersionMinor, 1) @@ -829,7 +833,7 @@ func (u *userInterfaceImpl) init() error { transparent = glfw.True } glfw.WindowHint(glfw.TransparentFramebuffer, transparent) - graphicsDriver().SetTransparent(u.isInitScreenTransparent()) + u.graphicsDriver.SetTransparent(u.isInitScreenTransparent()) // Before creating a window, set it unresizable no matter what u.isInitWindowResizable() is (#1987). // Making the window resizable here doesn't work correctly when switching to enable resizing. @@ -881,7 +885,7 @@ func (u *userInterfaceImpl) init() error { u.window.Show() - if g, ok := graphicsDriver().(interface{ SetWindow(uintptr) }); ok { + if g, ok := u.graphicsDriver.(interface{ SetWindow(uintptr) }); ok { g.SetWindow(u.nativeWindow()) } @@ -1018,7 +1022,7 @@ func (u *userInterfaceImpl) loop() error { return err } - if err := u.context.updateFrame(graphicsDriver(), outsideWidth, outsideHeight, deviceScaleFactor); err != nil { + if err := u.context.updateFrame(u.graphicsDriver, outsideWidth, outsideHeight, deviceScaleFactor); err != nil { return err } @@ -1060,7 +1064,7 @@ func (u *userInterfaceImpl) loop() error { // swapBuffers also checks IsGL, so this condition is redundant. // However, (*thread).Call is not good for performance due to channels. // Let's avoid this whenever possible (#1367). - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { u.t.Call(u.swapBuffers) } @@ -1082,7 +1086,7 @@ func (u *userInterfaceImpl) loop() error { // swapBuffers must be called from the main thread. func (u *userInterfaceImpl) swapBuffers() { - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { u.window.SwapBuffers() } } @@ -1139,7 +1143,7 @@ func (u *userInterfaceImpl) adjustWindowSizeBasedOnSizeLimitsInDIP(width, height func (u *userInterfaceImpl) setWindowSizeInDIP(width, height int, fullscreen bool) { width, height = u.adjustWindowSizeBasedOnSizeLimitsInDIP(width, height) - graphicsDriver().SetFullscreen(fullscreen) + u.graphicsDriver.SetFullscreen(fullscreen) scale := u.deviceScaleFactor(u.currentMonitor()) if u.windowWidthInDIP == width && u.windowHeightInDIP == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == scale { @@ -1213,7 +1217,7 @@ func (u *userInterfaceImpl) setWindowSizeInDIPImpl(width, height int, fullscreen // Swapping buffer is necesary to prevent the image lag (#1004). // TODO: This might not work when vsync is disabled. - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { glfw.PollEvents() u.swapBuffers() } @@ -1260,7 +1264,7 @@ func (u *userInterfaceImpl) setWindowSizeInDIPImpl(width, height int, fullscreen // updateVsync must be called on the main thread. func (u *userInterfaceImpl) updateVsync() { - if graphicsDriver().IsGL() { + if u.graphicsDriver.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). @@ -1274,7 +1278,7 @@ func (u *userInterfaceImpl) updateVsync() { glfw.SwapInterval(0) } } - graphicsDriver().SetVsyncEnabled(u.fpsMode == FPSModeVsyncOn) + u.graphicsDriver.SetVsyncEnabled(u.fpsMode == FPSModeVsyncOn) } // currentMonitor returns the current active monitor. diff --git a/internal/ui/ui_glfw_darwin.go b/internal/ui/ui_glfw_darwin.go index 2e9658dbf..bd5624a62 100644 --- a/internal/ui/ui_glfw_darwin.go +++ b/internal/ui/ui_glfw_darwin.go @@ -316,7 +316,7 @@ func (u *userInterfaceImpl) setNativeFullscreen(fullscreen bool) { } func (u *userInterfaceImpl) adjustViewSize() { - if graphicsDriver().IsGL() { + if u.graphicsDriver.IsGL() { return } C.adjustViewSize(C.uintptr_t(u.window.GetCocoaWindow())) diff --git a/internal/ui/ui_js.go b/internal/ui/ui_js.go index 4705de7d5..c8fe8b86d 100644 --- a/internal/ui/ui_js.go +++ b/internal/ui/ui_js.go @@ -20,6 +20,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/devicescale" "github.com/hajimehoshi/ebiten/v2/internal/gamepad" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/hooks" ) @@ -47,6 +48,8 @@ func driverCursorShapeToCSSCursor(cursor CursorShape) string { } type userInterfaceImpl struct { + graphicsDriver graphicsdriver.Graphics + runnableOnUnfocused bool fpsMode FPSModeType renderingScheduled bool @@ -279,11 +282,11 @@ func (u *userInterfaceImpl) updateImpl(force bool) error { w, h := u.outsideSize() if force { - if err := u.context.forceUpdateFrame(graphicsDriver(), w, h, u.DeviceScaleFactor()); err != nil { + if err := u.context.forceUpdateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor()); err != nil { return err } } else { - if err := u.context.updateFrame(graphicsDriver(), w, h, u.DeviceScaleFactor()); err != nil { + if err := u.context.updateFrame(u.graphicsDriver, w, h, u.DeviceScaleFactor()); err != nil { return err } } @@ -306,6 +309,7 @@ func (u *userInterfaceImpl) needsUpdate() bool { func (u *userInterfaceImpl) loop(game Game) <-chan error { u.context = newContextImpl(game) + u.graphicsDriver = graphicsDriver() errCh := make(chan error, 1) reqStopAudioCh := make(chan struct{}) diff --git a/internal/ui/ui_mobile.go b/internal/ui/ui_mobile.go index c4d9bba79..173639f11 100644 --- a/internal/ui/ui_mobile.go +++ b/internal/ui/ui_mobile.go @@ -36,6 +36,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/devicescale" "github.com/hajimehoshi/ebiten/v2/internal/gamepad" "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" + "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl" "github.com/hajimehoshi/ebiten/v2/internal/hooks" "github.com/hajimehoshi/ebiten/v2/internal/restorable" @@ -90,6 +91,8 @@ func (u *userInterfaceImpl) Update() error { } type userInterfaceImpl struct { + graphicsDriver graphicsdriver.Graphics + outsideWidth float64 outsideHeight float64 @@ -267,12 +270,13 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) { }() u.context = newContextImpl(game) + u.graphicsDriver = graphicsDriver() if mainloop { // When mainloop is true, gomobile-build is used. In this case, GL functions must be called via // gl.Context so that they are called on the appropriate thread. ctx := <-glContextCh - graphicsDriver().(*opengl.Graphics).SetGomobileGLContext(ctx) + u.graphicsDriver.(*opengl.Graphics).SetGomobileGLContext(ctx) } else { u.t = thread.NewOSThread() graphicscommand.SetRenderingThread(u.t) @@ -316,7 +320,7 @@ func (u *userInterfaceImpl) update() error { }() w, h := u.outsideSize() - if err := u.context.updateFrame(graphicsDriver(), w, h, deviceScale()); err != nil { + if err := u.context.updateFrame(u.graphicsDriver, w, h, deviceScale()); err != nil { return err } return nil