Skip to content

Instantly share code, notes, and snippets.

@danmaas
Created January 19, 2022 22:55
Show Gist options
  • Select an option

  • Save danmaas/4f3341b75a147d0c3ffc588a0f4c9b92 to your computer and use it in GitHub Desktop.

Select an option

Save danmaas/4f3341b75a147d0c3ffc588a0f4c9b92 to your computer and use it in GitHub Desktop.

Revisions

  1. danmaas created this gist Jan 19, 2022.
    127 changes: 127 additions & 0 deletions expo-gl+11.0.3.patch
    Original 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