From 813c45166da21c04a29633ef481007f9d92f32d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Thu, 5 Nov 2015 14:37:37 +0100 Subject: [PATCH] Fixes #25: replace GLShadersRegistry singleton by RNGLContext bridge This fix livereload issues with a more robust and react-native' compliant approach for holding contextual gl context and shaders via the bridge. --- RNGL.xcodeproj/project.pbxproj | 12 ++--- RNGL/GLCanvas.h | 3 +- RNGL/GLCanvas.m | 13 +++-- RNGL/GLCanvasManager.m | 4 +- RNGL/GLShadersRegistry.h | 19 -------- RNGL/GLShadersRegistry.m | 87 ---------------------------------- RNGL/RNGLContext.h | 24 ++++++++++ RNGL/RNGLContext.m | 71 +++++++++++++++++++++++++++ src/Shaders.js | 4 +- 9 files changed, 111 insertions(+), 126 deletions(-) delete mode 100644 RNGL/GLShadersRegistry.h delete mode 100644 RNGL/GLShadersRegistry.m create mode 100644 RNGL/RNGLContext.h create mode 100644 RNGL/RNGLContext.m diff --git a/RNGL.xcodeproj/project.pbxproj b/RNGL.xcodeproj/project.pbxproj index ad09207..067be48 100644 --- a/RNGL.xcodeproj/project.pbxproj +++ b/RNGL.xcodeproj/project.pbxproj @@ -16,9 +16,9 @@ 34D202A31B8DDDEF000A6FB5 /* GLFBO.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D202A21B8DDDEF000A6FB5 /* GLFBO.m */; }; 34EA054A1B82179E00A4FAFF /* GLImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EA053B1B82179E00A4FAFF /* GLImage.m */; }; 34EA054B1B82179E00A4FAFF /* GLShader.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EA053D1B82179E00A4FAFF /* GLShader.m */; }; - 34EA054C1B82179E00A4FAFF /* GLShadersRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EA053F1B82179E00A4FAFF /* GLShadersRegistry.m */; }; 34EA054D1B82179E00A4FAFF /* GLTexture.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EA05411B82179E00A4FAFF /* GLTexture.m */; }; 34EA05511B82179E00A4FAFF /* GLImageData.m in Sources */ = {isa = PBXBuildFile; fileRef = 34EA05491B82179E00A4FAFF /* GLImageData.m */; }; + 34F489BE1BEB8DC400148438 /* RNGLContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F489BD1BEB8DC400148438 /* RNGLContext.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -63,12 +63,12 @@ 34EA053B1B82179E00A4FAFF /* GLImage.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = GLImage.m; sourceTree = ""; tabWidth = 2; }; 34EA053C1B82179E00A4FAFF /* GLShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShader.h; sourceTree = ""; }; 34EA053D1B82179E00A4FAFF /* GLShader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLShader.m; sourceTree = ""; }; - 34EA053E1B82179E00A4FAFF /* GLShadersRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLShadersRegistry.h; sourceTree = ""; }; - 34EA053F1B82179E00A4FAFF /* GLShadersRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLShadersRegistry.m; sourceTree = ""; }; 34EA05401B82179E00A4FAFF /* GLTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLTexture.h; sourceTree = ""; }; 34EA05411B82179E00A4FAFF /* GLTexture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLTexture.m; sourceTree = ""; }; 34EA05481B82179E00A4FAFF /* GLImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GLImageData.h; sourceTree = ""; }; 34EA05491B82179E00A4FAFF /* GLImageData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GLImageData.m; sourceTree = ""; }; + 34F489BC1BEB8DC400148438 /* RNGLContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGLContext.h; sourceTree = ""; }; + 34F489BD1BEB8DC400148438 /* RNGLContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGLContext.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -139,8 +139,8 @@ 34EA05491B82179E00A4FAFF /* GLImageData.m */, 34EA053C1B82179E00A4FAFF /* GLShader.h */, 34EA053D1B82179E00A4FAFF /* GLShader.m */, - 34EA053E1B82179E00A4FAFF /* GLShadersRegistry.h */, - 34EA053F1B82179E00A4FAFF /* GLShadersRegistry.m */, + 34F489BC1BEB8DC400148438 /* RNGLContext.h */, + 34F489BD1BEB8DC400148438 /* RNGLContext.m */, 34EA05401B82179E00A4FAFF /* GLTexture.h */, 34EA05411B82179E00A4FAFF /* GLTexture.m */, ); @@ -251,8 +251,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 34F489BE1BEB8DC400148438 /* RNGLContext.m in Sources */, 34D202901B8DC278000A6FB5 /* RCTConvert+GLData.m in Sources */, - 34EA054C1B82179E00A4FAFF /* GLShadersRegistry.m in Sources */, 34EA054A1B82179E00A4FAFF /* GLImage.m in Sources */, 34D2029F1B8DD2FC000A6FB5 /* GLRenderData.m in Sources */, 34EA054D1B82179E00A4FAFF /* GLTexture.m in Sources */, diff --git a/RNGL/GLCanvas.h b/RNGL/GLCanvas.h index 835fe5a..6532981 100644 --- a/RNGL/GLCanvas.h +++ b/RNGL/GLCanvas.h @@ -16,7 +16,6 @@ @property (nonatomic, assign) BOOL onLoad; @property (nonatomic, assign) BOOL onChange; -- (instancetype)initWithBridge:(RCTBridge *)bridge - withContext:(EAGLContext *)context; +- (instancetype)initWithBridge:(RCTBridge *)bridge; @end diff --git a/RNGL/GLCanvas.m b/RNGL/GLCanvas.m index 3b8bcfb..a19c97d 100644 --- a/RNGL/GLCanvas.m +++ b/RNGL/GLCanvas.m @@ -4,9 +4,9 @@ #import "RCTConvert.h" #import "RCTEventDispatcher.h" #import "RCTLog.h" +#import "RNGLContext.h" #import "GLCanvas.h" #import "GLShader.h" -#import "GLShadersRegistry.h" #import "GLTexture.h" #import "GLImage.h" #import "GLRenderData.h" @@ -30,7 +30,7 @@ NSString* srcResource (id res) @implementation GLCanvas { - RCTBridge *_bridge; // bridge is required to instanciate GLReactImage + RCTBridge *_bridge; GLRenderData *_renderData; @@ -52,7 +52,6 @@ NSString* srcResource (id res) } - (instancetype)initWithBridge:(RCTBridge *)bridge - withContext:(EAGLContext *)context { if ((self = [super init])) { _bridge = bridge; @@ -60,7 +59,7 @@ NSString* srcResource (id res) _preloaded = [[NSMutableArray alloc] init]; _preloadingDone = false; _lastCaptureId = 0; - self.context = context; + self.context = [bridge.rnglContext getContext]; self.contentScaleFactor = RCTScreenScale(); } return self; @@ -182,7 +181,7 @@ RCT_NOT_IMPLEMENTED(-init) [children addObject:weak_traverseTree(child)]; } - GLShader *shader = [GLShadersRegistry getShader:data.shader]; + GLShader *shader = [_bridge.rnglContext getShader:data.shader]; NSDictionary *uniformTypes = [shader uniformTypes]; NSMutableDictionary *uniforms = [[NSMutableDictionary alloc] init]; @@ -210,7 +209,7 @@ RCT_NOT_IMPLEMENTED(-init) } else if ([type isEqualToString:@"fbo"]) { NSNumber *id = [RCTConvert NSNumber:value[@"id"]]; - GLFBO *fbo = [GLShadersRegistry getFBO:id]; + GLFBO *fbo = [_bridge.rnglContext getFBO:id]; textures[uniformName] = fbo.color[0]; } else if ([type isEqualToString:@"uri"]) { @@ -357,7 +356,7 @@ RCT_NOT_IMPLEMENTED(-init) glViewport(0, 0, w, h); } else { - GLFBO *fbo = [GLShadersRegistry getFBO:[NSNumber numberWithInt:renderData.fboId]]; + GLFBO *fbo = [_bridge.rnglContext getFBO:[NSNumber numberWithInt:renderData.fboId]]; [fbo setShapeWithWidth:w withHeight:h]; [fbo bind]; } diff --git a/RNGL/GLCanvasManager.m b/RNGL/GLCanvasManager.m index 7e8cdb3..cc41340 100644 --- a/RNGL/GLCanvasManager.m +++ b/RNGL/GLCanvasManager.m @@ -4,8 +4,6 @@ #import "RCTLog.h" #import -#import "GLShadersRegistry.h" - @implementation GLCanvasManager RCT_EXPORT_MODULE(); @@ -34,7 +32,7 @@ RCT_EXPORT_VIEW_PROPERTY(onChange, BOOL); - (UIView *)view { GLCanvas * v; - v = [[GLCanvas alloc] initWithBridge:self.bridge withContext:[GLShadersRegistry getContext]]; + v = [[GLCanvas alloc] initWithBridge:self.bridge]; return v; } diff --git a/RNGL/GLShadersRegistry.h b/RNGL/GLShadersRegistry.h deleted file mode 100644 index 5002aba..0000000 --- a/RNGL/GLShadersRegistry.h +++ /dev/null @@ -1,19 +0,0 @@ -#import -#import "RCTBridgeModule.h" -#import "GLShader.h" -#import "GLFBO.h" - - -@interface GLShadersRegistry : NSObject - -/** - * Get the global shader for a given id. - */ -+ (GLShader*) getShader: (NSNumber *)id; - -+ (GLFBO*) getFBO: (NSNumber *)id; - -+ (EAGLContext *) getContext; - -@property NSMutableDictionary *shaders; -@end diff --git a/RNGL/GLShadersRegistry.m b/RNGL/GLShadersRegistry.m deleted file mode 100644 index 04eb311..0000000 --- a/RNGL/GLShadersRegistry.m +++ /dev/null @@ -1,87 +0,0 @@ -#import - -#import "RCTBridgeModule.h" -#import "RCTConvert.h" -#import "RCTLog.h" -#import "GLShadersRegistry.h" - -// FIXME: current context and fbos live here... this should be global somewhere else. - -@implementation GLShadersRegistry -{ - NSMutableDictionary *_shaders; - EAGLContext *_context; - NSMutableDictionary *_fbos; -} - -GLShadersRegistry *GLShadersRegistry_instance; // FIXME is that the proper way to do singleton? - -RCT_EXPORT_MODULE(); - -+ (GLShader*) getShader: (NSNumber *)id -{ - return [GLShadersRegistry_instance getShader:id]; -} - -+ (GLFBO *) getFBO: (NSNumber *)id -{ - return [GLShadersRegistry_instance getFBO:id]; -} - -+ (EAGLContext *) getContext -{ - return [GLShadersRegistry_instance getContext]; -} - -// methods - -- (instancetype)init -{ - self = [super init]; - if (self) { - _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!_context) { - RCTLogError(@"Failed to initialize OpenGLES 2.0 context"); - } - _shaders = @{}.mutableCopy; - _fbos = @{}.mutableCopy; - GLShadersRegistry_instance = self; - } - return self; -} - -- (GLShader *) getShader: (NSNumber *)id -{ - return _shaders[id]; -} - -- (GLFBO *) getFBO: (NSNumber *)id -{ - GLFBO *fbo = _fbos[id]; - if (!fbo) { - fbo = [[GLFBO alloc] init]; - _fbos[id] = fbo; - } - return fbo; -} - -- (EAGLContext *) getContext -{ - return _context; -} - -static NSString* fullViewportVert = @"attribute vec2 position;varying vec2 uv;void main() {gl_Position = vec4(position,0.0,1.0);uv = vec2(0.5, 0.5) * (position+vec2(1.0, 1.0));}"; - -RCT_EXPORT_METHOD(register:(nonnull NSNumber *)id withConfig:(NSDictionary *)config) { - NSString *frag = [RCTConvert NSString:config[@"frag"]]; - NSString *name = [RCTConvert NSString:config[@"name"]]; - if (!frag) { - RCTLogError(@"Shader '%@': missing frag field", name); - return; - } - GLShader *shader = [[GLShader alloc] initWithContext:_context withName:name withVert:fullViewportVert withFrag:frag]; - _shaders[id] = shader; -} - -@end diff --git a/RNGL/RNGLContext.h b/RNGL/RNGLContext.h new file mode 100644 index 0000000..6ef556c --- /dev/null +++ b/RNGL/RNGLContext.h @@ -0,0 +1,24 @@ + +#import + +#import "RCTBridge.h" +#import "GLShader.h" +#import "GLFBO.h" + + +@interface RNGLContext : NSObject + +- (GLShader*) getShader: (NSNumber *)id; + +- (GLFBO*) getFBO: (NSNumber *)id; + +- (EAGLContext *) getContext; + +@end + + +@interface RCTBridge (RNGLContext) + +@property (nonatomic, readonly) RNGLContext *rnglContext; + +@end diff --git a/RNGL/RNGLContext.m b/RNGL/RNGLContext.m new file mode 100644 index 0000000..ab009e8 --- /dev/null +++ b/RNGL/RNGLContext.m @@ -0,0 +1,71 @@ + +#import "RNGLContext.h" + +#import "RCTConvert.h" +#import "RCTLog.h" + + +@implementation RNGLContext +{ + NSMutableDictionary *_shaders; + EAGLContext *_context; + NSMutableDictionary *_fbos; +} + +@synthesize bridge = _bridge; + +RCT_EXPORT_MODULE() + +- (void)setBridge:(RCTBridge *)bridge +{ + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + if (!_context) { + RCTLogError(@"Failed to initialize OpenGLES 2.0 context"); + } + _shaders = @{}.mutableCopy; + _fbos = @{}.mutableCopy; +} + +- (GLShader *) getShader: (NSNumber *)id +{ + return _shaders[id]; +} + +- (GLFBO *) getFBO: (NSNumber *)id +{ + GLFBO *fbo = _fbos[id]; + if (!fbo) { + fbo = [[GLFBO alloc] init]; + _fbos[id] = fbo; + } + return fbo; +} + +- (EAGLContext *) getContext +{ + return _context; +} + +static NSString* fullViewportVert = @"attribute vec2 position;varying vec2 uv;void main() {gl_Position = vec4(position,0.0,1.0);uv = vec2(0.5, 0.5) * (position+vec2(1.0, 1.0));}"; + +RCT_EXPORT_METHOD(addShader:(nonnull NSNumber *)id withConfig:(NSDictionary *)config) { + NSString *frag = [RCTConvert NSString:config[@"frag"]]; + NSString *name = [RCTConvert NSString:config[@"name"]]; + if (!frag) { + RCTLogError(@"Shader '%@': missing frag field", name); + return; + } + GLShader *shader = [[GLShader alloc] initWithContext:_context withName:name withVert:fullViewportVert withFrag:frag]; + _shaders[id] = shader; +} + +@end + +@implementation RCTBridge (RNGLContext) + +- (RNGLContext *)rnglContext +{ + return self.modules[RCTBridgeModuleNameForClass([RNGLContext class])]; +} + +@end \ No newline at end of file diff --git a/src/Shaders.js b/src/Shaders.js index 88b1d8b..62c46d8 100644 --- a/src/Shaders.js +++ b/src/Shaders.js @@ -1,6 +1,6 @@ const {createShaders} = require("gl-react-core"); -const { NativeModules: { GLShadersRegistry } } = require("react-native"); +const { NativeModules: { RNGLContext } } = require("react-native"); module.exports = createShaders(function (id, shader) { - GLShadersRegistry.register(id, shader); + RNGLContext.addShader(id, shader); }); -- 2.26.2