mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 11:12:44 +01:00
internal/ui: refactoring: integrate (*UserInterface).run
This commit is contained in:
parent
ea842495cf
commit
5fe8c29b4c
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//go:build !android && !ios && !js && !nintendosdk && !playstation5 && !ebitenginesinglethread && !ebitensinglethread
|
//go:build !android && !ios && !js && !ebitenginesinglethread && !ebitensinglethread
|
||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) run(game Game, options *RunOptions) error {
|
||||||
u.mainThread = thread.NewOSThread()
|
u.mainThread = thread.NewOSThread()
|
||||||
u.renderThread = thread.NewOSThread()
|
u.renderThread = thread.NewOSThread()
|
||||||
graphicscommand.SetRenderThread(u.renderThread)
|
graphicscommand.SetRenderThread(u.renderThread)
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//go:build !android && !ios && !js && !nintendosdk && !playstation5 && (ebitenginesinglethread || ebitensinglethread)
|
//go:build js || (!android && !ios && (ebitenginesinglethread || ebitensinglethread))
|
||||||
|
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) run(game Game, options *RunOptions) error {
|
||||||
// Initialize the main thread first so the thread is available at u.run (#809).
|
// Initialize the main thread first so the thread is available at u.run (#809).
|
||||||
u.mainThread = thread.NewNoopThread()
|
u.mainThread = thread.NewNoopThread()
|
||||||
u.renderThread = thread.NewNoopThread()
|
u.renderThread = thread.NewNoopThread()
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegularTermination represents a regular termination.
|
// RegularTermination represents a regular termination.
|
||||||
@ -79,6 +80,9 @@ type UserInterface struct {
|
|||||||
|
|
||||||
whiteImage *Image
|
whiteImage *Image
|
||||||
|
|
||||||
|
mainThread thread.Thread
|
||||||
|
renderThread thread.Thread
|
||||||
|
|
||||||
userInterfaceImpl
|
userInterfaceImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +107,7 @@ type userInterfaceImpl struct {
|
|||||||
darwinInitOnce sync.Once
|
darwinInitOnce sync.Once
|
||||||
bufferOnceSwappedOnce sync.Once
|
bufferOnceSwappedOnce sync.Once
|
||||||
|
|
||||||
mainThread thread.Thread
|
m sync.RWMutex
|
||||||
renderThread thread.Thread
|
|
||||||
m sync.RWMutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -123,6 +121,10 @@ func init() {
|
|||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
|
return u.run(game, options)
|
||||||
|
}
|
||||||
|
|
||||||
func (u *UserInterface) init() error {
|
func (u *UserInterface) init() error {
|
||||||
u.userInterfaceImpl = userInterfaceImpl{
|
u.userInterfaceImpl = userInterfaceImpl{
|
||||||
runnableOnUnfocused: true,
|
runnableOnUnfocused: true,
|
||||||
|
@ -390,9 +390,7 @@ func (u *UserInterface) needsUpdate() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) loop(game Game) <-chan error {
|
func (u *UserInterface) loopGame() error {
|
||||||
u.context = newContext(game)
|
|
||||||
|
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
reqStopAudioCh := make(chan struct{})
|
reqStopAudioCh := make(chan struct{})
|
||||||
resStopAudioCh := make(chan struct{})
|
resStopAudioCh := make(chan struct{})
|
||||||
@ -476,7 +474,7 @@ func (u *UserInterface) loop(game Game) <-chan error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return errCh
|
return <-errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) init() error {
|
func (u *UserInterface) init() error {
|
||||||
@ -743,9 +741,10 @@ func (u *UserInterface) forceUpdateOnMinimumFPSMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.setRunning(true)
|
return u.run(game, options)
|
||||||
defer u.setRunning(false)
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) initOnMainThread(options *RunOptions) error {
|
||||||
if !options.InitUnfocused && window.Truthy() {
|
if !options.InitUnfocused && window.Truthy() {
|
||||||
// Do not focus the canvas when the current document is in an iframe.
|
// Do not focus the canvas when the current document is in an iframe.
|
||||||
// Otherwise, the parent page tries to focus the iframe on every loading, which is annoying (#1373).
|
// Otherwise, the parent page tries to focus the iframe on every loading, which is annoying (#1373).
|
||||||
@ -770,7 +769,7 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
bodyStyle.Set("backgroundColor", "#000")
|
bodyStyle.Set("backgroundColor", "#000")
|
||||||
}
|
}
|
||||||
|
|
||||||
return <-u.loop(game)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) updateScreenSize() {
|
func (u *UserInterface) updateScreenSize() {
|
||||||
|
@ -241,7 +241,7 @@ func (u *UserInterface) SetForeground(foreground bool) error {
|
|||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.setGBuildSizeCh = make(chan struct{})
|
u.setGBuildSizeCh = make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
if err := u.run(game, true, options); err != nil {
|
if err := u.runMobile(game, true, options); err != nil {
|
||||||
// As mobile apps never ends, Loop can't return. Just panic here.
|
// As mobile apps never ends, Loop can't return. Just panic here.
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -252,13 +252,13 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
|
|
||||||
func (u *UserInterface) RunWithoutMainLoop(game Game, options *RunOptions) {
|
func (u *UserInterface) RunWithoutMainLoop(game Game, options *RunOptions) {
|
||||||
go func() {
|
go func() {
|
||||||
if err := u.run(game, false, options); err != nil {
|
if err := u.runMobile(game, false, options); err != nil {
|
||||||
u.errCh <- err
|
u.errCh <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) run(game Game, mainloop bool, options *RunOptions) (err error) {
|
func (u *UserInterface) runMobile(game Game, mainloop bool, options *RunOptions) (err error) {
|
||||||
// Convert the panic to a regular error so that Java/Objective-C layer can treat this easily e.g., for
|
// 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
|
// Crashlytics. A panic is treated as SIGABRT, and there is no way to handle this on Java/Objective-C layer
|
||||||
// unfortunately.
|
// unfortunately.
|
||||||
|
@ -21,15 +21,11 @@ package ui
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
stdcontext "context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
|
|
||||||
"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"
|
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
||||||
@ -84,15 +80,10 @@ func (u *UserInterface) init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.mainThread = thread.NewOSThread()
|
return u.run(game, options)
|
||||||
u.renderThread = thread.NewOSThread()
|
}
|
||||||
graphicscommand.SetRenderThread(u.renderThread)
|
|
||||||
|
|
||||||
u.setRunning(true)
|
|
||||||
defer u.setRunning(false)
|
|
||||||
|
|
||||||
u.context = newContext(game)
|
|
||||||
|
|
||||||
|
func (u *UserInterface) initOnMainThread(options *RunOptions) error {
|
||||||
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary)
|
g, lib, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -107,45 +98,25 @@ func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
|||||||
|
|
||||||
initializeProfiler()
|
initializeProfiler()
|
||||||
|
|
||||||
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 {
|
|
||||||
recordProfilerHeartbeat()
|
|
||||||
|
|
||||||
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u, func() {
|
|
||||||
u.egl.swapBuffers()
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Run the main thread.
|
|
||||||
_ = u.mainThread.Loop(ctx)
|
|
||||||
if err := wg.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) loopGame() error {
|
||||||
|
u.renderThread.Call(func() {
|
||||||
|
u.egl.makeContextCurrent()
|
||||||
|
})
|
||||||
|
|
||||||
|
for {
|
||||||
|
recordProfilerHeartbeat()
|
||||||
|
|
||||||
|
if err := u.context.updateFrame(u.graphicsDriver, float64(C.kScreenWidth), float64(C.kScreenHeight), deviceScaleFactor, u, func() {
|
||||||
|
u.egl.swapBuffers()
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (*UserInterface) DeviceScaleFactor() float64 {
|
func (*UserInterface) DeviceScaleFactor() float64 {
|
||||||
return deviceScaleFactor
|
return deviceScaleFactor
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,15 @@ func (u *UserInterface) init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
func (u *UserInterface) Run(game Game, options *RunOptions) error {
|
||||||
u.setRunning(true)
|
return u.run(game, options)
|
||||||
defer u.setRunning(false)
|
}
|
||||||
|
|
||||||
// TODO: Implement this.
|
func (u *UserInterface) initOnMainThread(options *RunOptions) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) loopGame() error {
|
||||||
|
// TODO: Implement this
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user