mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
parent
0e74b34705
commit
626c91e360
@ -224,10 +224,11 @@ func (q *commandQueue) Enqueue(command command) {
|
||||
}
|
||||
|
||||
// Flush flushes the command queue.
|
||||
func (q *commandQueue) Flush() error {
|
||||
return runOnMainThread(func() error {
|
||||
return q.flush()
|
||||
func (q *commandQueue) Flush() (err error) {
|
||||
RunOnMainThread(func() {
|
||||
err = q.flush()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// flush must be called the main thread.
|
||||
@ -699,18 +700,19 @@ func (c *newShaderCommand) Exec(indexOffset int) error {
|
||||
}
|
||||
|
||||
// InitializeGraphicsDriverState initialize the current graphics driver state.
|
||||
func InitializeGraphicsDriverState() error {
|
||||
return runOnMainThread(func() error {
|
||||
return theGraphicsDriver.Initialize()
|
||||
func InitializeGraphicsDriverState() (err error) {
|
||||
RunOnMainThread(func() {
|
||||
err = theGraphicsDriver.Initialize()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// ResetGraphicsDriverState resets the current graphics driver state.
|
||||
// If the graphics driver doesn't have an API to reset, ResetGraphicsDriverState does nothing.
|
||||
func ResetGraphicsDriverState() error {
|
||||
func ResetGraphicsDriverState() (err error) {
|
||||
if r, ok := theGraphicsDriver.(interface{ Reset() error }); ok {
|
||||
return runOnMainThread(func() error {
|
||||
return r.Reset()
|
||||
RunOnMainThread(func() {
|
||||
err = r.Reset()
|
||||
})
|
||||
}
|
||||
return nil
|
||||
@ -719,9 +721,8 @@ func ResetGraphicsDriverState() error {
|
||||
// MaxImageSize returns the maximum size of an image.
|
||||
func MaxImageSize() int {
|
||||
var size int
|
||||
_ = runOnMainThread(func() error {
|
||||
RunOnMainThread(func() {
|
||||
size = theGraphicsDriver.MaxImageSize()
|
||||
return nil
|
||||
})
|
||||
return size
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package graphicscommand
|
||||
var theThread Thread
|
||||
|
||||
type Thread interface {
|
||||
Call(f func() error) error
|
||||
Call(f func())
|
||||
}
|
||||
|
||||
// SetMainThread must be called from the main thread (i.e, the goroutine where the thread is created).
|
||||
@ -25,12 +25,14 @@ func SetMainThread(thread Thread) {
|
||||
theThread = thread
|
||||
}
|
||||
|
||||
func runOnMainThread(f func() error) error {
|
||||
// RunOnMainThread calls f on the main thread, and returns an error if any.
|
||||
func RunOnMainThread(f func()) {
|
||||
// The thread is nil when 1) GOOS=js or 2) using golang.org/x/mobile/gl.
|
||||
// When golang.org/x/mobile/gl is used, all the GL functions are called via Context, which already runs on an
|
||||
// appropriate thread.
|
||||
if theThread == nil {
|
||||
return f()
|
||||
f()
|
||||
return
|
||||
}
|
||||
return theThread.Call(f)
|
||||
theThread.Call(f)
|
||||
}
|
||||
|
@ -14,20 +14,18 @@
|
||||
|
||||
package thread
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Thread defines threading behavior in Ebiten.
|
||||
type Thread interface {
|
||||
Call(func() error) error
|
||||
Call(func())
|
||||
Loop()
|
||||
Stop()
|
||||
}
|
||||
|
||||
// OSThread represents an OS thread.
|
||||
type OSThread struct {
|
||||
funcs chan func() error
|
||||
results chan error
|
||||
funcs chan func()
|
||||
done chan struct{}
|
||||
terminate chan struct{}
|
||||
}
|
||||
|
||||
// NewOSThread creates a new thread.
|
||||
@ -35,38 +33,45 @@ type OSThread struct {
|
||||
// It is assumed that the OS thread is fixed by runtime.LockOSThread when NewOSThread is called.
|
||||
func NewOSThread() *OSThread {
|
||||
return &OSThread{
|
||||
funcs: make(chan func() error),
|
||||
results: make(chan error),
|
||||
funcs: make(chan func()),
|
||||
done: make(chan struct{}),
|
||||
terminate: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// BreakLoop represents an termination of the loop.
|
||||
var BreakLoop = errors.New("break loop")
|
||||
|
||||
// Loop starts the thread loop until a posted function returns BreakLoop.
|
||||
// Loop starts the thread loop until Stop is called.
|
||||
//
|
||||
// Loop must be called on the thread.
|
||||
func (t *OSThread) Loop() {
|
||||
for f := range t.funcs {
|
||||
err := f()
|
||||
if err == BreakLoop {
|
||||
t.results <- nil
|
||||
for {
|
||||
select {
|
||||
case fn := <-t.funcs:
|
||||
func() {
|
||||
defer func() {
|
||||
t.done <- struct{}{}
|
||||
}()
|
||||
|
||||
fn()
|
||||
}()
|
||||
case <-t.terminate:
|
||||
return
|
||||
}
|
||||
t.results <- err
|
||||
}
|
||||
}
|
||||
|
||||
// Stop stops the thread loop.
|
||||
func (t *OSThread) Stop() {
|
||||
close(t.terminate)
|
||||
}
|
||||
|
||||
// Call calls f on the thread.
|
||||
//
|
||||
// Do not call this from the same thread. This would block forever.
|
||||
//
|
||||
// If f returns BreakLoop, Loop returns.
|
||||
//
|
||||
// Call blocks if Loop is not called.
|
||||
func (t *OSThread) Call(f func() error) error {
|
||||
func (t *OSThread) Call(f func()) {
|
||||
t.funcs <- f
|
||||
return <-t.results
|
||||
<-t.done
|
||||
}
|
||||
|
||||
// NoopThread is used to disable threading.
|
||||
@ -81,6 +86,7 @@ func NewNoopThread() *NoopThread {
|
||||
func (t *NoopThread) Loop() {}
|
||||
|
||||
// Call executes the func immediately
|
||||
func (t *NoopThread) Call(f func() error) error {
|
||||
return f()
|
||||
}
|
||||
func (t *NoopThread) Call(f func()) { f() }
|
||||
|
||||
// Stop does nothing
|
||||
func (t *NoopThread) Stop() {}
|
||||
|
@ -32,16 +32,13 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
|
||||
|
||||
ch := make(chan error, 1)
|
||||
go func() {
|
||||
defer func() {
|
||||
_ = u.t.Call(func() error {
|
||||
return thread.BreakLoop
|
||||
})
|
||||
}()
|
||||
defer u.t.Stop()
|
||||
|
||||
defer close(ch)
|
||||
|
||||
if err := u.t.Call(func() error {
|
||||
return u.init()
|
||||
var err error
|
||||
if u.t.Call(func() {
|
||||
err = u.init()
|
||||
}); err != nil {
|
||||
ch <- err
|
||||
return
|
||||
@ -77,11 +74,7 @@ func (u *UserInterface) runOnAnotherThreadFromMainThread(f func() error) error {
|
||||
|
||||
var err error
|
||||
go func() {
|
||||
defer func() {
|
||||
_ = u.t.Call(func() error {
|
||||
return thread.BreakLoop
|
||||
})
|
||||
}()
|
||||
defer u.t.Stop()
|
||||
err = f()
|
||||
}()
|
||||
u.t.Loop()
|
||||
|
@ -484,12 +484,11 @@ func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
||||
}
|
||||
|
||||
var w, h int
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
m := u.currentMonitor()
|
||||
v := m.GetVideoMode()
|
||||
w = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m))
|
||||
h = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m))
|
||||
return nil
|
||||
})
|
||||
return w, h
|
||||
}
|
||||
@ -507,9 +506,8 @@ func (u *UserInterface) IsFullscreen() bool {
|
||||
return u.isInitFullscreen()
|
||||
}
|
||||
b := false
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
b = u.isFullscreen()
|
||||
return nil
|
||||
})
|
||||
return b
|
||||
}
|
||||
@ -521,18 +519,16 @@ func (u *UserInterface) SetFullscreen(fullscreen bool) {
|
||||
}
|
||||
|
||||
var update bool
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
update = u.isFullscreen() != fullscreen
|
||||
return nil
|
||||
})
|
||||
if !update {
|
||||
return
|
||||
}
|
||||
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
w, h := u.windowWidthInDIP, u.windowHeightInDIP
|
||||
u.setWindowSizeInDIP(w, h, fullscreen)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -542,9 +538,8 @@ func (u *UserInterface) IsFocused() bool {
|
||||
}
|
||||
|
||||
var focused bool
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
focused = u.window.GetAttrib(glfw.Focused) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return focused
|
||||
}
|
||||
@ -564,14 +559,13 @@ func (u *UserInterface) SetFPSMode(mode driver.FPSMode) {
|
||||
u.m.Unlock()
|
||||
return
|
||||
}
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
if !u.fpsModeInited {
|
||||
u.fpsMode = mode
|
||||
return nil
|
||||
return
|
||||
}
|
||||
u.setFPSMode(mode)
|
||||
u.updateVsync()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -583,9 +577,8 @@ func (u *UserInterface) FPSMode() driver.FPSMode {
|
||||
return m
|
||||
}
|
||||
var v driver.FPSMode
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
v = u.fpsMode
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -603,21 +596,23 @@ func (u *UserInterface) CursorMode() driver.CursorMode {
|
||||
if !u.isRunning() {
|
||||
return u.getInitCursorMode()
|
||||
}
|
||||
var v driver.CursorMode
|
||||
_ = u.t.Call(func() error {
|
||||
mode := u.window.GetInputMode(glfw.CursorMode)
|
||||
switch mode {
|
||||
case glfw.CursorNormal:
|
||||
v = driver.CursorModeVisible
|
||||
case glfw.CursorHidden:
|
||||
v = driver.CursorModeHidden
|
||||
case glfw.CursorDisabled:
|
||||
v = driver.CursorModeCaptured
|
||||
default:
|
||||
panic(fmt.Sprintf("glfw: invalid GLFW cursor mode: %d", mode))
|
||||
}
|
||||
return nil
|
||||
|
||||
var mode int
|
||||
u.t.Call(func() {
|
||||
mode = u.window.GetInputMode(glfw.CursorMode)
|
||||
})
|
||||
|
||||
var v driver.CursorMode
|
||||
switch mode {
|
||||
case glfw.CursorNormal:
|
||||
v = driver.CursorModeVisible
|
||||
case glfw.CursorHidden:
|
||||
v = driver.CursorModeHidden
|
||||
case glfw.CursorDisabled:
|
||||
v = driver.CursorModeCaptured
|
||||
default:
|
||||
panic(fmt.Sprintf("glfw: invalid GLFW cursor mode: %d", mode))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
@ -626,9 +621,8 @@ func (u *UserInterface) SetCursorMode(mode driver.CursorMode) {
|
||||
u.setInitCursorMode(mode)
|
||||
return
|
||||
}
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
u.window.SetInputMode(glfw.CursorMode, driverCursorModeToGLFWCursorMode(mode))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -644,9 +638,8 @@ func (u *UserInterface) SetCursorShape(shape driver.CursorShape) {
|
||||
if !u.isRunning() {
|
||||
return
|
||||
}
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
u.setNativeCursor(shape)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -657,9 +650,8 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
|
||||
}
|
||||
|
||||
f := 0.0
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
f = u.deviceScaleFactor(u.currentMonitor())
|
||||
return nil
|
||||
})
|
||||
return f
|
||||
}
|
||||
@ -745,7 +737,7 @@ func (u *UserInterface) registerWindowSetSizeCallback() {
|
||||
|
||||
var outsideWidth, outsideHeight float64
|
||||
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
if width != 0 || height != 0 {
|
||||
w := int(u.dipFromGLFWPixel(float64(width), u.currentMonitor()))
|
||||
h := int(u.dipFromGLFWPixel(float64(height), u.currentMonitor()))
|
||||
@ -753,16 +745,14 @@ func (u *UserInterface) registerWindowSetSizeCallback() {
|
||||
}
|
||||
|
||||
outsideWidth, outsideHeight = u.updateSize()
|
||||
return nil
|
||||
})
|
||||
u.context.Layout(outsideWidth, outsideHeight)
|
||||
if err := u.context.ForceUpdateFrame(); err != nil {
|
||||
return err
|
||||
}
|
||||
if u.Graphics().IsGL() {
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
u.swapBuffers()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return nil
|
||||
@ -1023,12 +1013,7 @@ func (u *UserInterface) update() (float64, float64, error) {
|
||||
}
|
||||
|
||||
func (u *UserInterface) loop() error {
|
||||
defer func() {
|
||||
_ = u.t.Call(func() error {
|
||||
glfw.Terminate()
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
defer u.t.Call(glfw.Terminate)
|
||||
|
||||
for {
|
||||
var unfocused bool
|
||||
@ -1047,10 +1032,9 @@ func (u *UserInterface) loop() error {
|
||||
}
|
||||
|
||||
var outsideWidth, outsideHeight float64
|
||||
if err := u.t.Call(func() error {
|
||||
var err error
|
||||
var err error
|
||||
if u.t.Call(func() {
|
||||
outsideWidth, outsideHeight, err = u.update()
|
||||
return err
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1084,14 +1068,13 @@ func (u *UserInterface) loop() error {
|
||||
newImgs[i] = rgba
|
||||
}
|
||||
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
// In the fullscreen mode, reset the icon images and try again later.
|
||||
if u.isFullscreen() {
|
||||
u.setIconImages(imgs)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
u.window.SetIcon(newImgs)
|
||||
return nil
|
||||
})
|
||||
}()
|
||||
}
|
||||
@ -1100,10 +1083,7 @@ func (u *UserInterface) loop() error {
|
||||
// However, (*thread).Call is not good for performance due to channels.
|
||||
// Let's avoid this whenever possible (#1367).
|
||||
if u.Graphics().IsGL() {
|
||||
_ = u.t.Call(func() error {
|
||||
u.swapBuffers()
|
||||
return nil
|
||||
})
|
||||
u.t.Call(u.swapBuffers)
|
||||
}
|
||||
|
||||
if unfocused {
|
||||
@ -1399,9 +1379,8 @@ func (u *UserInterface) IsScreenTransparent() bool {
|
||||
return u.isInitScreenTransparent()
|
||||
}
|
||||
val := false
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
val = u.window.GetAttrib(glfw.TransparentFramebuffer) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return val
|
||||
}
|
||||
@ -1409,9 +1388,8 @@ func (u *UserInterface) IsScreenTransparent() bool {
|
||||
func (u *UserInterface) ResetForFrame() {
|
||||
// The offscreens must be updated every frame (#490).
|
||||
var w, h float64
|
||||
_ = u.t.Call(func() error {
|
||||
u.t.Call(func() {
|
||||
w, h = u.updateSize()
|
||||
return nil
|
||||
})
|
||||
u.context.Layout(w, h)
|
||||
u.input.resetForFrame()
|
||||
|
@ -32,9 +32,8 @@ func (w *window) IsDecorated() bool {
|
||||
return w.ui.isInitWindowDecorated()
|
||||
}
|
||||
v := false
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
v = w.ui.window.GetAttrib(glfw.Decorated) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -45,13 +44,12 @@ func (w *window) SetDecorated(decorated bool) {
|
||||
return
|
||||
}
|
||||
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
if w.ui.isNativeFullscreen() {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
w.ui.setWindowDecorated(decorated)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -60,9 +58,8 @@ func (w *window) IsResizable() bool {
|
||||
return w.ui.isInitWindowResizable()
|
||||
}
|
||||
v := false
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
v = w.ui.window.GetAttrib(glfw.Resizable) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -72,12 +69,11 @@ func (w *window) SetResizable(resizable bool) {
|
||||
w.ui.setInitWindowResizable(resizable)
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
if w.ui.isNativeFullscreen() {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
w.ui.setWindowResizable(resizable)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -86,9 +82,8 @@ func (w *window) IsFloating() bool {
|
||||
return w.ui.isInitWindowFloating()
|
||||
}
|
||||
var v bool
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
v = w.ui.window.GetAttrib(glfw.Floating) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -98,12 +93,11 @@ func (w *window) SetFloating(floating bool) {
|
||||
w.ui.setInitWindowFloating(floating)
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
if w.ui.isNativeFullscreen() {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
w.ui.setWindowFloating(floating)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -112,9 +106,8 @@ func (w *window) IsMaximized() bool {
|
||||
return w.ui.isInitWindowMaximized()
|
||||
}
|
||||
var v bool
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
v = w.ui.window.GetAttrib(glfw.Maximized) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -127,10 +120,7 @@ func (w *window) Maximize() {
|
||||
w.ui.setInitWindowMaximized(true)
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.maximizeWindow()
|
||||
return nil
|
||||
})
|
||||
w.ui.t.Call(w.ui.maximizeWindow)
|
||||
}
|
||||
|
||||
func (w *window) IsMinimized() bool {
|
||||
@ -138,9 +128,8 @@ func (w *window) IsMinimized() bool {
|
||||
return false
|
||||
}
|
||||
var v bool
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
v = w.ui.window.GetAttrib(glfw.Iconified) == glfw.True
|
||||
return nil
|
||||
})
|
||||
return v
|
||||
}
|
||||
@ -150,10 +139,7 @@ func (w *window) Minimize() {
|
||||
// Do nothing
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.iconifyWindow()
|
||||
return nil
|
||||
})
|
||||
w.ui.t.Call(w.ui.iconifyWindow)
|
||||
}
|
||||
|
||||
func (w *window) Restore() {
|
||||
@ -161,10 +147,7 @@ func (w *window) Restore() {
|
||||
// Do nothing
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.restoreWindow()
|
||||
return nil
|
||||
})
|
||||
w.ui.t.Call(w.ui.restoreWindow)
|
||||
}
|
||||
|
||||
func (w *window) Position() (int, int) {
|
||||
@ -172,7 +155,7 @@ func (w *window) Position() (int, int) {
|
||||
panic("glfw: WindowPosition can't be called before the main loop starts")
|
||||
}
|
||||
x, y := 0, 0
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
var wx, wy int
|
||||
if w.ui.isFullscreen() && !w.ui.isNativeFullscreenAvailable() {
|
||||
wx, wy = w.ui.origPos()
|
||||
@ -186,7 +169,6 @@ func (w *window) Position() (int, int) {
|
||||
xf := w.ui.dipFromGLFWPixel(float64(wx), m)
|
||||
yf := w.ui.dipFromGLFWPixel(float64(wy), m)
|
||||
x, y = int(xf), int(yf)
|
||||
return nil
|
||||
})
|
||||
return x, y
|
||||
}
|
||||
@ -196,9 +178,8 @@ func (w *window) SetPosition(x, y int) {
|
||||
w.ui.setInitWindowPositionInDIP(x, y)
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
w.ui.setWindowPositionInDIP(x, y, w.ui.currentMonitor())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -208,10 +189,9 @@ func (w *window) Size() (int, int) {
|
||||
return w.ui.adjustWindowSizeBasedOnSizeLimitsInDIP(ww, wh)
|
||||
}
|
||||
ww, wh := 0, 0
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
ww = w.ui.windowWidthInDIP
|
||||
wh = w.ui.windowHeightInDIP
|
||||
return nil
|
||||
})
|
||||
return ww, wh
|
||||
}
|
||||
@ -221,15 +201,14 @@ func (w *window) SetSize(width, height int) {
|
||||
w.ui.setInitWindowSizeInDIP(width, height)
|
||||
return
|
||||
}
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
// When a window is a native fullscreen, forcing to resize the window might leave unexpected image lags.
|
||||
// Forbid this.
|
||||
if w.ui.isNativeFullscreen() {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
w.ui.setWindowSizeInDIP(width, height, w.ui.isFullscreen())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -245,10 +224,7 @@ func (w *window) SetSizeLimits(minw, minh, maxw, maxh int) {
|
||||
return
|
||||
}
|
||||
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.updateWindowSizeLimits()
|
||||
return nil
|
||||
})
|
||||
w.ui.t.Call(w.ui.updateWindowSizeLimits)
|
||||
}
|
||||
|
||||
func (w *window) SetIcon(iconImages []image.Image) {
|
||||
@ -264,9 +240,8 @@ func (w *window) SetTitle(title string) {
|
||||
return
|
||||
}
|
||||
w.ui.title = title
|
||||
_ = w.ui.t.Call(func() error {
|
||||
w.ui.t.Call(func() {
|
||||
w.ui.setWindowTitle(title)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -88,9 +88,7 @@ func (u *UserInterface) Update() error {
|
||||
renderCh <- struct{}{}
|
||||
go func() {
|
||||
<-renderEndCh
|
||||
u.t.Call(func() error {
|
||||
return thread.BreakLoop
|
||||
})
|
||||
u.t.Stop()
|
||||
}()
|
||||
u.t.Loop()
|
||||
return nil
|
||||
|
6
run.go
6
run.go
@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/clock"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
||||
)
|
||||
|
||||
// Game defines necessary functions for a game.
|
||||
@ -168,6 +169,11 @@ func RunGame(game Game) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunOnMainThread calls the given f on the main thread, and blocks until f returns.
|
||||
func RunOnMainThread(f func()) {
|
||||
graphicscommand.RunOnMainThread(f)
|
||||
}
|
||||
|
||||
func isRunGameEnded() bool {
|
||||
return atomic.LoadInt32(&isRunGameEnded_) != 0
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user