mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
internal/ui: bug fix: IsGL / SetUIView can be called before initialization is done
The functions in the package `mobile/ebitenmobileview` could be invoked from EbitenViewController even before the graphics driver initialization is done in theory. This change fixes this issue by waiting the initialization by channels. Also, this change adds error handlings at these functions. Closes #2455
This commit is contained in:
parent
f4e63602d3
commit
7d146fb70b
@ -59,7 +59,18 @@
|
||||
started_ = true;
|
||||
}
|
||||
|
||||
if (EbitenmobileviewIsGL()) {
|
||||
NSError* err = nil;
|
||||
BOOL isGL = NO;
|
||||
EbitenmobileviewIsGL(&isGL, &err);
|
||||
if (err != nil) {
|
||||
[self onErrorOnGameUpdate:err];
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGL) {
|
||||
self.glkView.delegate = (id<GLKViewDelegate>)(self);
|
||||
[self.view addSubview: self.glkView];
|
||||
|
||||
@ -69,7 +80,14 @@
|
||||
[EAGLContext setCurrentContext:context];
|
||||
} else {
|
||||
[self.view addSubview: self.metalView];
|
||||
EbitenmobileviewSetUIView((uintptr_t)(self.metalView));
|
||||
EbitenmobileviewSetUIView((uintptr_t)(self.metalView), &err);
|
||||
if (err != nil) {
|
||||
[self onErrorOnGameUpdate:err];
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
displayLink_ = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
|
||||
@ -78,8 +96,19 @@
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews {
|
||||
NSError* err = nil;
|
||||
BOOL isGL = NO;
|
||||
EbitenmobileviewIsGL(&isGL, &err);
|
||||
if (err != nil) {
|
||||
[self onErrorOnGameUpdate:err];
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
CGRect viewRect = [[self view] frame];
|
||||
if (EbitenmobileviewIsGL()) {
|
||||
if (isGL) {
|
||||
[[self glkView] setFrame:viewRect];
|
||||
} else {
|
||||
[[self metalView] setFrame:viewRect];
|
||||
@ -106,7 +135,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (EbitenmobileviewIsGL()) {
|
||||
NSError* err = nil;
|
||||
BOOL isGL = NO;
|
||||
EbitenmobileviewIsGL(&isGL, &err);
|
||||
if (err != nil) {
|
||||
[self onErrorOnGameUpdate:err];
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGL) {
|
||||
[[self glkView] setNeedsDisplay];
|
||||
} else {
|
||||
[self updateEbiten];
|
||||
@ -124,8 +164,10 @@
|
||||
}
|
||||
|
||||
- (void)updateEbiten {
|
||||
if (error_) {
|
||||
return;
|
||||
@synchronized(self) {
|
||||
if (error_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NSError* err = nil;
|
||||
@ -134,7 +176,9 @@
|
||||
[self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:)
|
||||
withObject:err
|
||||
waitUntilDone:NO];
|
||||
error_ = true;
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,8 +187,19 @@
|
||||
}
|
||||
|
||||
- (void)updateTouches:(NSSet*)touches {
|
||||
NSError* err = nil;
|
||||
BOOL isGL = NO;
|
||||
EbitenmobileviewIsGL(&isGL, &err);
|
||||
if (err != nil) {
|
||||
[self onErrorOnGameUpdate:err];
|
||||
@synchronized(self) {
|
||||
error_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (UITouch* touch in touches) {
|
||||
if (EbitenmobileviewIsGL()) {
|
||||
if (isGL) {
|
||||
if (touch.view != [self glkView]) {
|
||||
continue;
|
||||
}
|
||||
|
@ -55,13 +55,34 @@ func (g *graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error)
|
||||
return metal.NewGraphics()
|
||||
}
|
||||
|
||||
func SetUIView(uiview uintptr) {
|
||||
// This function should be called only when the graphics library is Metal.
|
||||
if g, ok := theUI.graphicsDriver.(interface{ SetUIView(uintptr) }); ok {
|
||||
g.SetUIView(uiview)
|
||||
}
|
||||
func SetUIView(uiview uintptr) error {
|
||||
return theUI.setUIView(uiview)
|
||||
}
|
||||
|
||||
func IsGL() bool {
|
||||
return theUI.graphicsDriver.IsGL()
|
||||
func IsGL() (bool, error) {
|
||||
return theUI.isGL()
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) setUIView(uiview uintptr) error {
|
||||
select {
|
||||
case err := <-u.errCh:
|
||||
return err
|
||||
case <-u.graphicsDriverInitCh:
|
||||
}
|
||||
|
||||
// This function should be called only when the graphics library is Metal.
|
||||
if g, ok := u.graphicsDriver.(interface{ SetUIView(uintptr) }); ok {
|
||||
g.SetUIView(uiview)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) isGL() (bool, error) {
|
||||
select {
|
||||
case err := <-u.errCh:
|
||||
return false, err
|
||||
case <-u.graphicsDriverInitCh:
|
||||
}
|
||||
|
||||
return u.graphicsDriver.IsGL(), nil
|
||||
}
|
||||
|
@ -52,8 +52,9 @@ var (
|
||||
|
||||
func init() {
|
||||
theUI.userInterfaceImpl = userInterfaceImpl{
|
||||
foreground: 1,
|
||||
errCh: make(chan error),
|
||||
foreground: 1,
|
||||
graphicsDriverInitCh: make(chan struct{}),
|
||||
errCh: make(chan error),
|
||||
|
||||
// Give a default outside size so that the game can start without initializing them.
|
||||
outsideWidth: 640,
|
||||
@ -90,7 +91,8 @@ func (u *userInterfaceImpl) Update() error {
|
||||
}
|
||||
|
||||
type userInterfaceImpl struct {
|
||||
graphicsDriver graphicsdriver.Graphics
|
||||
graphicsDriver graphicsdriver.Graphics
|
||||
graphicsDriverInitCh chan struct{}
|
||||
|
||||
outsideWidth float64
|
||||
outsideHeight float64
|
||||
@ -287,6 +289,7 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) {
|
||||
return err
|
||||
}
|
||||
u.graphicsDriver = g
|
||||
close(u.graphicsDriverInitCh)
|
||||
|
||||
// If gomobile-build is used, wait for the outside size fixed.
|
||||
if u.setGBuildSizeCh != nil {
|
||||
|
@ -18,10 +18,10 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
func SetUIView(uiview int64) {
|
||||
ui.SetUIView(uintptr(uiview))
|
||||
func SetUIView(uiview int64) error {
|
||||
return ui.SetUIView(uintptr(uiview))
|
||||
}
|
||||
|
||||
func IsGL() bool {
|
||||
func IsGL() (bool, error) {
|
||||
return ui.IsGL()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user