mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +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;
|
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.glkView.delegate = (id<GLKViewDelegate>)(self);
|
||||||
[self.view addSubview: self.glkView];
|
[self.view addSubview: self.glkView];
|
||||||
|
|
||||||
@ -69,7 +80,14 @@
|
|||||||
[EAGLContext setCurrentContext:context];
|
[EAGLContext setCurrentContext:context];
|
||||||
} else {
|
} else {
|
||||||
[self.view addSubview: self.metalView];
|
[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)];
|
displayLink_ = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
|
||||||
@ -78,8 +96,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillLayoutSubviews {
|
- (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];
|
CGRect viewRect = [[self view] frame];
|
||||||
if (EbitenmobileviewIsGL()) {
|
if (isGL) {
|
||||||
[[self glkView] setFrame:viewRect];
|
[[self glkView] setFrame:viewRect];
|
||||||
} else {
|
} else {
|
||||||
[[self metalView] setFrame:viewRect];
|
[[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];
|
[[self glkView] setNeedsDisplay];
|
||||||
} else {
|
} else {
|
||||||
[self updateEbiten];
|
[self updateEbiten];
|
||||||
@ -124,8 +164,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateEbiten {
|
- (void)updateEbiten {
|
||||||
if (error_) {
|
@synchronized(self) {
|
||||||
return;
|
if (error_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSError* err = nil;
|
NSError* err = nil;
|
||||||
@ -134,7 +176,9 @@
|
|||||||
[self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:)
|
[self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:)
|
||||||
withObject:err
|
withObject:err
|
||||||
waitUntilDone:NO];
|
waitUntilDone:NO];
|
||||||
error_ = true;
|
@synchronized(self) {
|
||||||
|
error_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +187,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateTouches:(NSSet*)touches {
|
- (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) {
|
for (UITouch* touch in touches) {
|
||||||
if (EbitenmobileviewIsGL()) {
|
if (isGL) {
|
||||||
if (touch.view != [self glkView]) {
|
if (touch.view != [self glkView]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -55,13 +55,34 @@ func (g *graphicsDriverCreatorImpl) newMetal() (graphicsdriver.Graphics, error)
|
|||||||
return metal.NewGraphics()
|
return metal.NewGraphics()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetUIView(uiview uintptr) {
|
func SetUIView(uiview uintptr) error {
|
||||||
// This function should be called only when the graphics library is Metal.
|
return theUI.setUIView(uiview)
|
||||||
if g, ok := theUI.graphicsDriver.(interface{ SetUIView(uintptr) }); ok {
|
|
||||||
g.SetUIView(uiview)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsGL() bool {
|
func IsGL() (bool, error) {
|
||||||
return theUI.graphicsDriver.IsGL()
|
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() {
|
func init() {
|
||||||
theUI.userInterfaceImpl = userInterfaceImpl{
|
theUI.userInterfaceImpl = userInterfaceImpl{
|
||||||
foreground: 1,
|
foreground: 1,
|
||||||
errCh: make(chan error),
|
graphicsDriverInitCh: make(chan struct{}),
|
||||||
|
errCh: make(chan error),
|
||||||
|
|
||||||
// Give a default outside size so that the game can start without initializing them.
|
// Give a default outside size so that the game can start without initializing them.
|
||||||
outsideWidth: 640,
|
outsideWidth: 640,
|
||||||
@ -90,7 +91,8 @@ func (u *userInterfaceImpl) Update() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type userInterfaceImpl struct {
|
type userInterfaceImpl struct {
|
||||||
graphicsDriver graphicsdriver.Graphics
|
graphicsDriver graphicsdriver.Graphics
|
||||||
|
graphicsDriverInitCh chan struct{}
|
||||||
|
|
||||||
outsideWidth float64
|
outsideWidth float64
|
||||||
outsideHeight float64
|
outsideHeight float64
|
||||||
@ -287,6 +289,7 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
u.graphicsDriver = g
|
u.graphicsDriver = g
|
||||||
|
close(u.graphicsDriverInitCh)
|
||||||
|
|
||||||
// If gomobile-build is used, wait for the outside size fixed.
|
// If gomobile-build is used, wait for the outside size fixed.
|
||||||
if u.setGBuildSizeCh != nil {
|
if u.setGBuildSizeCh != nil {
|
||||||
|
@ -18,10 +18,10 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetUIView(uiview int64) {
|
func SetUIView(uiview int64) error {
|
||||||
ui.SetUIView(uintptr(uiview))
|
return ui.SetUIView(uintptr(uiview))
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsGL() bool {
|
func IsGL() (bool, error) {
|
||||||
return ui.IsGL()
|
return ui.IsGL()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user