Created
January 19, 2022 22:55
-
-
Save danmaas/4f3341b75a147d0c3ffc588a0f4c9b92 to your computer and use it in GitHub Desktop.
Revisions
-
danmaas created this gist
Jan 19, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,127 @@ diff --git a/node_modules/expo-gl/ios/EXGL/EXGLContext.mm b/node_modules/expo-gl/ios/EXGL/EXGLContext.mm index 0a904ab..2bd2fdf 100644 --- a/node_modules/expo-gl/ios/EXGL/EXGLContext.mm +++ b/node_modules/expo-gl/ios/EXGL/EXGLContext.mm @@ -18,6 +18,7 @@ @interface EXGLContext () @property (nonatomic, strong) dispatch_queue_t glQueue; @property (nonatomic, weak) EXModuleRegistry *moduleRegistry; @property (nonatomic, weak) EXGLObjectManager *objectManager; +@property (atomic) BOOL appIsBackground; // tracks the app's foreground/background state @end @@ -32,6 +33,7 @@ - (instancetype)initWithDelegate:(id<EXGLContextDelegate>)delegate andModuleRegi _objectManager = (EXGLObjectManager *)[_moduleRegistry getExportedModuleOfClass:[EXGLObjectManager class]]; _glQueue = dispatch_queue_create("host.exp.gl", DISPATCH_QUEUE_SERIAL); _eaglCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3] ?: [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + _appIsBackground = NO; } return self; } @@ -48,6 +50,11 @@ - (EAGLContext *)createSharedEAGLContext - (void)runInEAGLContext:(EAGLContext*)context callback:(void(^)(void))callback { + if (_appIsBackground) { + // iOS does not allow calls to OpenGL when the app is in background + return; + } + [EAGLContext setCurrentContext:context]; callback(); glFlush(); @@ -86,6 +93,16 @@ - (void)initialize:(void(^)(BOOL))callback self->_contextId = UEXGLContextCreate(jsRuntimePtr); [self->_objectManager saveContext:self]; + // listen for foreground/background transitions + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onApplicationDidBecomeActive:) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(onApplicationWillResignActive:) + name:UIApplicationWillResignActiveNotification + object:nil]; + UEXGLContextSetFlushMethodObjc(self->_contextId, ^{ [self flush]; }); @@ -112,6 +129,21 @@ - (void)flush }]; } +- (void) onApplicationWillResignActive:(NSNotification *) note +{ + // flush all pending GL activity, wait for completion, and then set the appIsBackground flag + [self runAsync:^{ + glFinish(); + self->_appIsBackground = YES; + }]; +} + +- (void) onApplicationDidBecomeActive:(NSNotification *) note { + // unset the appIsBackground flag so that rendering can resume + _appIsBackground = NO; + // [self flush]; +} + - (void)destroy { [self runAsync:^{ @@ -119,6 +151,10 @@ - (void)destroy [self.delegate glContextWillDestroy:self]; } + // stop listening for foreground/background transitions + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + // Flush all the stuff UEXGLContextFlush(self->_contextId); diff --git a/node_modules/expo-gl/ios/EXGL/EXGLView.mm b/node_modules/expo-gl/ios/EXGL/EXGLView.mm index e7ca617..324e148 100644 --- a/node_modules/expo-gl/ios/EXGL/EXGLView.mm +++ b/node_modules/expo-gl/ios/EXGL/EXGLView.mm @@ -235,6 +235,8 @@ - (void)removeFromSuperview - (void)draw { + @synchronized(self) { // DJM + // exglCtxId may be unset if we get here (on the UI thread) before UEXGLContextCreate(...) is // called on the JS thread to create the EXGL context and save its id (see EXGLContext.initializeContextWithBridge method). // In this case no GL work has been sent yet so we skip this frame. @@ -248,7 +250,7 @@ - (void)draw // This happens exactly at `gl.endFrameEXP()` in the queue if (_viewColorbuffer != 0 && !_renderbufferPresented) { // bind renderbuffer and present it on the layer - [_glContext runInEAGLContext:_uiEaglCtx callback:^{ + [_glContext runAsync:^{ glBindRenderbuffer(GL_RENDERBUFFER, self->_viewColorbuffer); [self->_uiEaglCtx presentRenderbuffer:GL_RENDERBUFFER]; }]; @@ -257,12 +259,14 @@ - (void)draw _renderbufferPresented = YES; } } + } // @synchronized(self) } // [GL thread] blits framebuffers and then sets a flag that informs UI thread // about presenting the new content of the renderbuffer on the next draw call - (void)blitFramebuffers { + @synchronized(self) { // DJM if (_glContext.isInitialized && _viewFramebuffer != 0 && _viewColorbuffer != 0) { // Save surrounding framebuffer GLint prevFramebuffer; @@ -290,6 +294,7 @@ - (void)blitFramebuffers // mark renderbuffer as not presented _renderbufferPresented = NO; } + } // @synchronized(self) } #pragma mark - EXGLContextDelegate