mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
internal/ui: use a separate render thread for Nintendo Switch
Updates #2512
This commit is contained in:
parent
312dce950c
commit
0bdfeec610
2
doc.go
2
doc.go
@ -99,7 +99,7 @@
|
|||||||
// `ebitenginesinglethread` disables Ebitengine's thread safety to unlock maximum performance. If you use this you will have
|
// `ebitenginesinglethread` disables Ebitengine's thread safety to unlock maximum performance. If you use this you will have
|
||||||
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
|
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
|
||||||
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
|
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
|
||||||
// to RunGame.
|
// to RunGame. `ebitenginesinglethread` works only with desktops.
|
||||||
//
|
//
|
||||||
// `microsoftgdk` is for Microsoft GDK (e.g. Xbox).
|
// `microsoftgdk` is for Microsoft GDK (e.g. Xbox).
|
||||||
//
|
//
|
||||||
|
@ -81,10 +81,13 @@ func (e *egl) init(nativeWindowHandle C.NativeWindowType) error {
|
|||||||
return fmt.Errorf("ui: eglCreateContext failed: error: %d", C.eglGetError())
|
return fmt.Errorf("ui: eglCreateContext failed: error: %d", C.eglGetError())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *egl) makeContextCurrent() error {
|
||||||
if r := C.eglMakeCurrent(e.display, e.surface, e.surface, e.context); r == 0 {
|
if r := C.eglMakeCurrent(e.display, e.surface, e.surface, e.context); r == 0 {
|
||||||
return fmt.Errorf("ui: eglMakeCurrent failed")
|
return fmt.Errorf("ui: eglMakeCurrent failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +21,16 @@ package ui
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
stdcontext "context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/gamepad"
|
"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"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/opengl"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
||||||
)
|
)
|
||||||
|
|
||||||
type graphicsDriverCreatorImpl struct{}
|
type graphicsDriverCreatorImpl struct{}
|
||||||
@ -61,6 +66,9 @@ type userInterfaceImpl struct {
|
|||||||
nativeTouches []C.struct_Touch
|
nativeTouches []C.struct_Touch
|
||||||
|
|
||||||
egl egl
|
egl egl
|
||||||
|
|
||||||
|
mainThread *thread.OSThread
|
||||||
|
renderThread *thread.OSThread
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
|
func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
|
||||||
@ -78,19 +86,54 @@ func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
|
|||||||
|
|
||||||
initializeProfiler()
|
initializeProfiler()
|
||||||
|
|
||||||
|
u.mainThread = thread.NewOSThread()
|
||||||
|
u.renderThread = thread.NewOSThread()
|
||||||
|
graphicscommand.SetRenderThread(u.renderThread)
|
||||||
|
|
||||||
|
ctx, cancel := stdcontext.WithCancel(stdcontext.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var wg errgroup.Group
|
||||||
|
|
||||||
|
// Run the render thread.
|
||||||
|
wg.Go(func() error {
|
||||||
|
defer cancel()
|
||||||
|
_ = u.renderThread.Loop(ctx)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
// Run the game thread.
|
||||||
|
wg.Go(func() error {
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
u.renderThread.Call(func() {
|
||||||
|
u.egl.makeContextCurrent()
|
||||||
|
})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
recordProfilerHeartbeat()
|
recordProfilerHeartbeat()
|
||||||
|
|
||||||
// TODO: Make a separate thread for rendering (#2512).
|
u.mainThread.Call(func() {
|
||||||
gamepad.Update()
|
gamepad.Update()
|
||||||
u.updateInputState()
|
u.updateInputState()
|
||||||
|
})
|
||||||
|
|
||||||
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u); err != nil {
|
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.renderThread.Call(func() {
|
||||||
u.egl.swapBuffers()
|
u.egl.swapBuffers()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Run the main thread.
|
||||||
|
_ = u.mainThread.Loop(ctx)
|
||||||
|
if err := wg.Wait(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*userInterfaceImpl) DeviceScaleFactor() float64 {
|
func (*userInterfaceImpl) DeviceScaleFactor() float64 {
|
||||||
|
Loading…
Reference in New Issue
Block a user