cmd/ebitenmobile: use an independent thread for rendering on iOS

Closes #2508
This commit is contained in:
Hajime Hoshi 2022-12-28 23:29:25 +09:00
parent c638727759
commit 0756be0b68
2 changed files with 41 additions and 8 deletions

View File

@ -31,6 +31,7 @@
bool error_; bool error_;
CADisplayLink* displayLink_; CADisplayLink* displayLink_;
bool explicitRendering_; bool explicitRendering_;
NSThread* renderThread_;
} }
- (UIView*)metalView { - (UIView*)metalView {
@ -73,11 +74,6 @@
if (isGL) { if (isGL) {
self.glkView.delegate = (id<GLKViewDelegate>)(self); self.glkView.delegate = (id<GLKViewDelegate>)(self);
[self.view addSubview: self.glkView]; [self.view addSubview: self.glkView];
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[self glkView].context = context;
[EAGLContext setCurrentContext:context];
} else { } else {
[self.view addSubview: self.metalView]; [self.view addSubview: self.metalView];
EbitenmobileviewSetUIView((uintptr_t)(self.metalView), &err); 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_ = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
[displayLink_ addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [displayLink_ addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
EbitenmobileviewSetRenderRequester(self); EbitenmobileviewSetRenderRequester(self);
// Run the loop. This will never return.
[[NSRunLoop currentRunLoop] run];
} }
- (void)viewWillLayoutSubviews { - (void)viewWillLayoutSubviews {
@ -139,7 +165,9 @@
BOOL isGL = NO; BOOL isGL = NO;
EbitenmobileviewIsGL(&isGL, &err); EbitenmobileviewIsGL(&isGL, &err);
if (err != nil) { if (err != nil) {
[self onErrorOnGameUpdate:err]; [self performSelectorOnMainThread:@selector(onErrorOnGameUpdate:)
withObject:err
waitUntilDone:NO];
@synchronized(self) { @synchronized(self) {
error_ = true; error_ = true;
} }
@ -147,7 +175,9 @@
} }
if (isGL) { if (isGL) {
[[self glkView] setNeedsDisplay]; dispatch_async(dispatch_get_main_queue(), ^{
[[self glkView] setNeedsDisplay];
});
} else { } else {
[self updateEbiten]; [self updateEbiten];
} }

View File

@ -28,7 +28,10 @@ package metal
// } // }
// //
// static void setFrame(void* cametal, void* uiview) { // 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); // ((CALayer*)cametal).frame = CGRectMake(0, 0, size.width, size.height);
// } // }
import "C" import "C"