From 0756be0b68a7854d609b5c62112d7111ef97ef50 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 28 Dec 2022 23:29:25 +0900 Subject: [PATCH] cmd/ebitenmobile: use an independent thread for rendering on iOS Closes #2508 --- .../_files/EbitenViewController.m | 44 ++++++++++++++++--- internal/graphicsdriver/metal/view_ios.go | 5 ++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/cmd/ebitenmobile/_files/EbitenViewController.m b/cmd/ebitenmobile/_files/EbitenViewController.m index 69cdfc4eb..928b60b12 100644 --- a/cmd/ebitenmobile/_files/EbitenViewController.m +++ b/cmd/ebitenmobile/_files/EbitenViewController.m @@ -31,6 +31,7 @@ bool error_; CADisplayLink* displayLink_; bool explicitRendering_; + NSThread* renderThread_; } - (UIView*)metalView { @@ -73,11 +74,6 @@ if (isGL) { self.glkView.delegate = (id)(self); [self.view addSubview: self.glkView]; - - EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - [self glkView].context = context; - - [EAGLContext setCurrentContext:context]; } else { [self.view addSubview: self.metalView]; EbitenmobileviewSetUIView((uintptr_t)(self.metalView), &err); @@ -90,9 +86,39 @@ } } + renderThread_ = [[NSThread alloc] initWithTarget:self + selector:@selector(initRenderer) + object:nil]; + [renderThread_ start]; +} + +- (void)initRenderer { + NSError* err = nil; + BOOL isGL = NO; + EbitenmobileviewIsGL(&isGL, &err); + if (err != nil) { + [self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:) + withObject:err + waitUntilDone:NO]; + @synchronized(self) { + error_ = true; + } + return; + } + + if (isGL) { + EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + [self glkView].context = context; + + [EAGLContext setCurrentContext:context]; + } + displayLink_ = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)]; [displayLink_ addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; EbitenmobileviewSetRenderRequester(self); + + // Run the loop. This will never return. + [[NSRunLoop currentRunLoop] run]; } - (void)viewWillLayoutSubviews { @@ -139,7 +165,9 @@ BOOL isGL = NO; EbitenmobileviewIsGL(&isGL, &err); if (err != nil) { - [self onErrorOnGameUpdate:err]; + [self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:) + withObject:err + waitUntilDone:NO]; @synchronized(self) { error_ = true; } @@ -147,7 +175,9 @@ } if (isGL) { - [[self glkView] setNeedsDisplay]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[self glkView] setNeedsDisplay]; + }); } else { [self updateEbiten]; } diff --git a/internal/graphicsdriver/metal/view_ios.go b/internal/graphicsdriver/metal/view_ios.go index 136335cd3..dff20eb87 100644 --- a/internal/graphicsdriver/metal/view_ios.go +++ b/internal/graphicsdriver/metal/view_ios.go @@ -28,7 +28,10 @@ package metal // } // // static void setFrame(void* cametal, void* uiview) { -// CGSize size = ((UIView*)uiview).frame.size; +// __block CGSize size; +// dispatch_sync(dispatch_get_main_queue(), ^{ +// size = ((UIView*)uiview).frame.size; +// }); // ((CALayer*)cametal).frame = CGRectMake(0, 0, size.width, size.height); // } import "C"