expo-gl 15.0.0 → 15.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/android/build.gradle +2 -2
- package/ios/EXGLContext.h +3 -4
- package/ios/EXGLContext.mm +5 -3
- package/ios/EXGLObjectManager.mm +1 -3
- package/ios/GLView.swift +329 -0
- package/ios/GLViewModule.swift +1 -1
- package/package.json +2 -2
- package/ios/EXGLView.h +0 -28
- package/ios/EXGLView.mm +0 -343
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 15.0.2 — 2024-11-14
|
|
14
|
+
|
|
15
|
+
_This version does not introduce any user-facing changes._
|
|
16
|
+
|
|
17
|
+
## 15.0.1 — 2024-11-07
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Converted the native view from Objective-C to Swift to fix support for the New Architecture. ([#32675](https://github.com/expo/expo/pull/32675) by [@tsapeta](https://github.com/tsapeta))
|
|
22
|
+
|
|
13
23
|
## 15.0.0 — 2024-10-22
|
|
14
24
|
|
|
15
25
|
### 🛠 Breaking changes
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '15.0.
|
|
4
|
+
version = '15.0.2'
|
|
5
5
|
|
|
6
6
|
def reactNativeArchitectures() {
|
|
7
7
|
def value = project.getProperties().get("reactNativeArchitectures")
|
|
@@ -26,7 +26,7 @@ android {
|
|
|
26
26
|
namespace "expo.modules.gl"
|
|
27
27
|
defaultConfig {
|
|
28
28
|
versionCode 31
|
|
29
|
-
versionName "15.0.
|
|
29
|
+
versionName "15.0.2"
|
|
30
30
|
|
|
31
31
|
externalNativeBuild {
|
|
32
32
|
cmake {
|
package/ios/EXGLContext.h
CHANGED
|
@@ -17,12 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
@interface EXGLContext : NSObject
|
|
19
19
|
|
|
20
|
-
- (
|
|
21
|
-
|
|
22
|
-
- (void)initialize;
|
|
20
|
+
- (nonnull instancetype)initWithDelegate:(nullable id<EXGLContextDelegate>)delegate
|
|
21
|
+
andModuleRegistry:(nonnull EXModuleRegistry *)moduleRegistry;
|
|
23
22
|
- (void)prepare:(nullable void(^)(BOOL))callback andEnableExperimentalWorkletSupport:(BOOL)enableExperimentalWorkletSupport;
|
|
24
23
|
- (BOOL)isInitialized;
|
|
25
|
-
- (
|
|
24
|
+
- (nonnull EAGLContext *)createSharedEAGLContext;
|
|
26
25
|
- (void)runAsync:(nonnull void(^)(void))callback;
|
|
27
26
|
- (void)runInEAGLContext:(nonnull EAGLContext*)context callback:(nonnull void(^)(void))callback;
|
|
28
27
|
- (void)takeSnapshotWithOptions:(nonnull NSDictionary *)options resolve:(nonnull EXPromiseResolveBlock)resolve reject:(nonnull EXPromiseRejectBlock)reject;
|
package/ios/EXGLContext.mm
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
@implementation EXGLContext
|
|
28
28
|
|
|
29
|
-
- (instancetype)initWithDelegate:(id<EXGLContextDelegate>)delegate
|
|
30
|
-
|
|
29
|
+
- (nonnull instancetype)initWithDelegate:(id<EXGLContextDelegate>)delegate
|
|
30
|
+
andModuleRegistry:(nonnull EXModuleRegistry *)moduleRegistry
|
|
31
31
|
{
|
|
32
32
|
if (self = [super init]) {
|
|
33
33
|
self.delegate = delegate;
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
_isContextReady = NO;
|
|
40
40
|
_wasPrepareCalled = NO;
|
|
41
41
|
_appIsBackgrounded = NO;
|
|
42
|
+
|
|
43
|
+
[self initialize];
|
|
42
44
|
}
|
|
43
45
|
return self;
|
|
44
46
|
}
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
return _isContextReady;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
- (EAGLContext *)createSharedEAGLContext
|
|
53
|
+
- (nonnull EAGLContext *)createSharedEAGLContext
|
|
52
54
|
{
|
|
53
55
|
return [[EAGLContext alloc] initWithAPI:[_eaglCtx API] sharegroup:[_eaglCtx sharegroup]];
|
|
54
56
|
}
|
package/ios/EXGLObjectManager.mm
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
#import <ExpoGL/EXGLObjectManager.h>
|
|
8
8
|
#import <ExpoGL/EXGLObject.h>
|
|
9
|
-
#import <ExpoGL/EXGLView.h>
|
|
10
9
|
#import <ExpoGL/EXGLCameraObject.h>
|
|
11
10
|
|
|
12
11
|
@interface EXGLObjectManager ()
|
|
@@ -99,7 +98,6 @@ EX_EXPORT_METHOD_AS(createContextAsync,
|
|
|
99
98
|
EXGLContext *glContext = [[EXGLContext alloc] initWithDelegate:nil
|
|
100
99
|
andModuleRegistry:_moduleRegistry];
|
|
101
100
|
|
|
102
|
-
[glContext initialize];
|
|
103
101
|
[glContext prepare:^(BOOL success) {
|
|
104
102
|
if (success) {
|
|
105
103
|
resolve(@{ @"exglCtxId": @(glContext.contextId) });
|
|
@@ -150,7 +148,7 @@ EX_EXPORT_METHOD_AS(createCameraTextureAsync,
|
|
|
150
148
|
id<EXCameraInterface> cameraView = (id<EXCameraInterface>)view;
|
|
151
149
|
|
|
152
150
|
if (glContext == nil) {
|
|
153
|
-
reject(@"E_GL_BAD_VIEW_TAG", nil, EXErrorWithMessage(@"ExponentGLObjectManager.createCameraTextureAsync: Expected
|
|
151
|
+
reject(@"E_GL_BAD_VIEW_TAG", nil, EXErrorWithMessage(@"ExponentGLObjectManager.createCameraTextureAsync: Expected a GLView"));
|
|
154
152
|
return;
|
|
155
153
|
}
|
|
156
154
|
if (cameraView == nil) {
|
package/ios/GLView.swift
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// Copyright 2024-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
|
|
5
|
+
internal final class GLView: ExpoView, EXGLContextDelegate {
|
|
6
|
+
lazy var glContext: EXGLContext = {
|
|
7
|
+
guard let legacyModuleRegistry = appContext?.legacyModuleRegistry else {
|
|
8
|
+
fatalError("Legacy module registry is not available")
|
|
9
|
+
}
|
|
10
|
+
return EXGLContext(delegate: self, andModuleRegistry: legacyModuleRegistry)
|
|
11
|
+
}()
|
|
12
|
+
|
|
13
|
+
lazy var eaglContext: EAGLContext = glContext.createSharedEAGLContext()
|
|
14
|
+
|
|
15
|
+
// Props
|
|
16
|
+
var msaaSamples: Int = 0
|
|
17
|
+
var enableExperimentalWorkletSupport: Bool = false
|
|
18
|
+
|
|
19
|
+
// Events
|
|
20
|
+
var onSurfaceCreate: EventDispatcher? = EventDispatcher()
|
|
21
|
+
|
|
22
|
+
// GL
|
|
23
|
+
var layerWidth: GLint = 0
|
|
24
|
+
var layerHeight: GLint = 0
|
|
25
|
+
var viewFramebuffer: GLuint = 0
|
|
26
|
+
var viewColorbuffer: GLuint = 0
|
|
27
|
+
var viewDepthStencilbuffer: GLuint = 0
|
|
28
|
+
var msaaFramebuffer: GLuint = 0
|
|
29
|
+
var msaaRenderbuffer: GLuint = 0
|
|
30
|
+
|
|
31
|
+
var displayLink: CADisplayLink?
|
|
32
|
+
var isAfterLayout: Bool = false
|
|
33
|
+
var isRenderbufferPresented: Bool = true
|
|
34
|
+
var viewBuffersSize: CGSize = .zero
|
|
35
|
+
|
|
36
|
+
override static var layerClass: AnyClass {
|
|
37
|
+
return CAEAGLLayer.self
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
required init(appContext: AppContext? = nil) {
|
|
41
|
+
super.init(appContext: appContext)
|
|
42
|
+
|
|
43
|
+
// Set up a draw loop
|
|
44
|
+
displayLink = CADisplayLink(target: self, selector: #selector(drawGL))
|
|
45
|
+
displayLink?.add(to: RunLoop.main, forMode: .common)
|
|
46
|
+
|
|
47
|
+
contentScaleFactor = EXUtilities.screenScale()
|
|
48
|
+
|
|
49
|
+
// Initialize properties of our backing CAEAGLLayer
|
|
50
|
+
if let eaglLayer = layer as? CAEAGLLayer {
|
|
51
|
+
eaglLayer.isOpaque = false
|
|
52
|
+
eaglLayer.drawableProperties = [
|
|
53
|
+
kEAGLDrawablePropertyRetainedBacking: false,
|
|
54
|
+
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func runOnUIThread(_ callback: @escaping () -> Void) {
|
|
60
|
+
DispatchQueue.main.sync {
|
|
61
|
+
glContext.run(in: self.eaglContext, callback: callback)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// MARK: - UIView
|
|
66
|
+
|
|
67
|
+
override func layoutSubviews() {
|
|
68
|
+
resizeViewBuffersToWidth(width: contentScaleFactor * frame.size.width, height: contentScaleFactor * frame.size.height)
|
|
69
|
+
|
|
70
|
+
isAfterLayout = true
|
|
71
|
+
glContext.prepare(nil, andEnableExperimentalWorkletSupport: enableExperimentalWorkletSupport)
|
|
72
|
+
maybeCallSurfaceCreated()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override func removeFromSuperview() {
|
|
76
|
+
glContext.destroy()
|
|
77
|
+
displayLink?.invalidate()
|
|
78
|
+
displayLink = nil
|
|
79
|
+
super.removeFromSuperview()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// MARK: - GL
|
|
83
|
+
|
|
84
|
+
func resizeViewBuffersToWidth(width: Double, height: Double) {
|
|
85
|
+
let newViewBuffersSize = CGSize(width: width, height: height)
|
|
86
|
+
|
|
87
|
+
// Don't resize if size hasn't changed and the current size is not zero
|
|
88
|
+
if CGSizeEqualToSize(newViewBuffersSize, viewBuffersSize) && !CGSizeEqualToSize(viewBuffersSize, .zero) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// update viewBuffersSize on UI thread (before actual resize takes place)
|
|
93
|
+
// to get rid of redundant resizes if layoutSubviews is called multiple times with the same frame size
|
|
94
|
+
viewBuffersSize = newViewBuffersSize
|
|
95
|
+
|
|
96
|
+
// swiftlint:disable:next closure_body_length
|
|
97
|
+
glContext.runAsync { [self] in
|
|
98
|
+
// Save surrounding framebuffer/renderbuffer
|
|
99
|
+
var prevFramebuffer: GLuint = 0
|
|
100
|
+
var prevRenderbuffer: GLuint = 0
|
|
101
|
+
|
|
102
|
+
glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &prevFramebuffer)
|
|
103
|
+
glGetIntegerv(GLenum(GL_RENDERBUFFER_BINDING), &prevRenderbuffer)
|
|
104
|
+
if prevFramebuffer == viewFramebuffer {
|
|
105
|
+
prevFramebuffer = 0
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Delete old buffers if they exist
|
|
109
|
+
deleteViewBuffers()
|
|
110
|
+
|
|
111
|
+
// Set up view framebuffer
|
|
112
|
+
glGenFramebuffers(1, &viewFramebuffer)
|
|
113
|
+
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), viewFramebuffer)
|
|
114
|
+
|
|
115
|
+
// Set up new color renderbuffer
|
|
116
|
+
glGenRenderbuffers(1, &viewColorbuffer)
|
|
117
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), viewColorbuffer)
|
|
118
|
+
|
|
119
|
+
runOnUIThread { [self] in
|
|
120
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), viewColorbuffer)
|
|
121
|
+
eaglContext.renderbufferStorage(Int(GL_RENDERBUFFER), from: self.layer as? CAEAGLLayer)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
glFramebufferRenderbuffer(
|
|
125
|
+
GLenum(GL_FRAMEBUFFER),
|
|
126
|
+
GLenum(GL_COLOR_ATTACHMENT0),
|
|
127
|
+
GLenum(GL_RENDERBUFFER),
|
|
128
|
+
viewColorbuffer
|
|
129
|
+
)
|
|
130
|
+
glGetRenderbufferParameteriv(
|
|
131
|
+
GLenum(GL_RENDERBUFFER),
|
|
132
|
+
GLenum(GL_RENDERBUFFER_WIDTH),
|
|
133
|
+
&layerWidth
|
|
134
|
+
)
|
|
135
|
+
glGetRenderbufferParameteriv(
|
|
136
|
+
GLenum(GL_RENDERBUFFER),
|
|
137
|
+
GLenum(GL_RENDERBUFFER_HEIGHT),
|
|
138
|
+
&layerHeight
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
// Set up MSAA framebuffer/renderbuffer
|
|
142
|
+
glGenFramebuffers(1, &msaaFramebuffer)
|
|
143
|
+
glGenRenderbuffers(1, &msaaRenderbuffer)
|
|
144
|
+
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), msaaFramebuffer)
|
|
145
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), msaaRenderbuffer)
|
|
146
|
+
glRenderbufferStorageMultisample(
|
|
147
|
+
GLenum(GL_RENDERBUFFER),
|
|
148
|
+
GLsizei(msaaSamples),
|
|
149
|
+
GLenum(GL_RGBA8),
|
|
150
|
+
layerWidth,
|
|
151
|
+
layerHeight
|
|
152
|
+
)
|
|
153
|
+
glFramebufferRenderbuffer(
|
|
154
|
+
GLenum(GL_FRAMEBUFFER),
|
|
155
|
+
GLenum(GL_COLOR_ATTACHMENT0),
|
|
156
|
+
GLenum(GL_RENDERBUFFER),
|
|
157
|
+
msaaRenderbuffer
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
EXGLContextSetDefaultFramebuffer(glContext.contextId, GLint(msaaFramebuffer))
|
|
161
|
+
|
|
162
|
+
// Set up new depth+stencil renderbuffer
|
|
163
|
+
glGenRenderbuffers(1, &viewDepthStencilbuffer)
|
|
164
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), viewDepthStencilbuffer)
|
|
165
|
+
glRenderbufferStorageMultisample(
|
|
166
|
+
GLenum(GL_RENDERBUFFER),
|
|
167
|
+
GLsizei(msaaSamples),
|
|
168
|
+
GLenum(GL_DEPTH24_STENCIL8),
|
|
169
|
+
layerWidth,
|
|
170
|
+
layerHeight
|
|
171
|
+
)
|
|
172
|
+
glFramebufferRenderbuffer(
|
|
173
|
+
GLenum(GL_FRAMEBUFFER),
|
|
174
|
+
GLenum(GL_DEPTH_ATTACHMENT),
|
|
175
|
+
GLenum(GL_RENDERBUFFER),
|
|
176
|
+
viewDepthStencilbuffer
|
|
177
|
+
)
|
|
178
|
+
glFramebufferRenderbuffer(
|
|
179
|
+
GLenum(GL_FRAMEBUFFER),
|
|
180
|
+
GLenum(GL_STENCIL_ATTACHMENT),
|
|
181
|
+
GLenum(GL_RENDERBUFFER),
|
|
182
|
+
viewDepthStencilbuffer
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
// Resize viewport
|
|
186
|
+
glViewport(0, 0, GLsizei(width), GLsizei(height))
|
|
187
|
+
|
|
188
|
+
// Restore surrounding framebuffer/renderbuffer
|
|
189
|
+
if prevFramebuffer != 0 {
|
|
190
|
+
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), prevFramebuffer)
|
|
191
|
+
}
|
|
192
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), prevRenderbuffer)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
func maybeCallSurfaceCreated() {
|
|
197
|
+
// Because initialization things happen asynchronously,
|
|
198
|
+
// we need to be sure that they all are done before we pass GL object to JS.
|
|
199
|
+
|
|
200
|
+
if onSurfaceCreate != nil && glContext.isInitialized() && isAfterLayout {
|
|
201
|
+
onSurfaceCreate?([
|
|
202
|
+
"exglCtxId": glContext.contextId
|
|
203
|
+
])
|
|
204
|
+
|
|
205
|
+
// unset onSurfaceCreate - it will not be needed anymore
|
|
206
|
+
onSurfaceCreate = nil
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@objc
|
|
211
|
+
func drawGL() {
|
|
212
|
+
// exglCtxId may be unset if we get here (on the UI thread) before EXGLContextCreate(...) is
|
|
213
|
+
// called on the JS thread to create the EXGL context and save its id (see EXGLContext.initializeContextWithBridge method).
|
|
214
|
+
// In this case no GL work has been sent yet so we skip this frame.
|
|
215
|
+
//
|
|
216
|
+
// _viewFramebuffer may be 0 if we haven't had a layout event yet and so the size of the
|
|
217
|
+
// framebuffer to create is unknown. In this case we have nowhere to render to so we skip
|
|
218
|
+
// this frame (the GL work to run remains on the queue for next time).
|
|
219
|
+
|
|
220
|
+
if glContext.isInitialized() && viewFramebuffer != 0 {
|
|
221
|
+
// Present current state of view buffers
|
|
222
|
+
// This happens exactly at `gl.endFrameEXP()` in the queue
|
|
223
|
+
if viewColorbuffer != 0 && !isRenderbufferPresented {
|
|
224
|
+
// bind renderbuffer and present it on the layer
|
|
225
|
+
glContext.runAsync {
|
|
226
|
+
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), self.viewColorbuffer)
|
|
227
|
+
self.eaglContext.presentRenderbuffer(Int(GL_RENDERBUFFER))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// mark renderbuffer as presented
|
|
231
|
+
isRenderbufferPresented = true
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// [GL thread] blits framebuffers and then sets a flag that informs UI thread
|
|
237
|
+
// about presenting the new content of the renderbuffer on the next draw call
|
|
238
|
+
func blitFramebuffers() {
|
|
239
|
+
if glContext.isInitialized() && viewFramebuffer != 0 && viewColorbuffer != 0 {
|
|
240
|
+
// Save surrounding framebuffer
|
|
241
|
+
var prevFramebuffer: GLuint = 0
|
|
242
|
+
glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &prevFramebuffer)
|
|
243
|
+
if prevFramebuffer == viewFramebuffer {
|
|
244
|
+
prevFramebuffer = 0
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Resolve multisampling and present
|
|
248
|
+
glBindFramebuffer(GLenum(GL_READ_FRAMEBUFFER), msaaFramebuffer)
|
|
249
|
+
glBindFramebuffer(GLenum(GL_DRAW_FRAMEBUFFER), viewFramebuffer)
|
|
250
|
+
|
|
251
|
+
// glBlitFramebuffer works only on OpenGL ES 3.0, so we need a fallback to Apple's extension for OpenGL ES 2.0
|
|
252
|
+
if glContext.eaglCtx.api == .openGLES3 {
|
|
253
|
+
glBlitFramebuffer(
|
|
254
|
+
0,
|
|
255
|
+
0,
|
|
256
|
+
layerWidth,
|
|
257
|
+
layerHeight,
|
|
258
|
+
0,
|
|
259
|
+
0,
|
|
260
|
+
layerWidth,
|
|
261
|
+
layerHeight,
|
|
262
|
+
GLbitfield(GL_COLOR_BUFFER_BIT),
|
|
263
|
+
GLenum(GL_NEAREST)
|
|
264
|
+
)
|
|
265
|
+
} else {
|
|
266
|
+
glResolveMultisampleFramebufferAPPLE()
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Restore surrounding framebuffer
|
|
270
|
+
if prevFramebuffer != 0 {
|
|
271
|
+
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), prevFramebuffer)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// mark renderbuffer as not presented
|
|
275
|
+
isRenderbufferPresented = false
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
func deleteViewBuffers() {
|
|
280
|
+
if viewDepthStencilbuffer != 0 {
|
|
281
|
+
glDeleteRenderbuffers(1, &viewDepthStencilbuffer)
|
|
282
|
+
viewDepthStencilbuffer = 0
|
|
283
|
+
}
|
|
284
|
+
if viewColorbuffer != 0 {
|
|
285
|
+
glDeleteRenderbuffers(1, &viewColorbuffer)
|
|
286
|
+
viewColorbuffer = 0
|
|
287
|
+
}
|
|
288
|
+
if viewFramebuffer != 0 {
|
|
289
|
+
glDeleteFramebuffers(1, &viewFramebuffer)
|
|
290
|
+
viewFramebuffer = 0
|
|
291
|
+
}
|
|
292
|
+
if msaaRenderbuffer != 0 {
|
|
293
|
+
glDeleteRenderbuffers(1, &msaaRenderbuffer)
|
|
294
|
+
msaaRenderbuffer = 0
|
|
295
|
+
}
|
|
296
|
+
if msaaFramebuffer != 0 {
|
|
297
|
+
glDeleteFramebuffers(1, &msaaFramebuffer)
|
|
298
|
+
msaaFramebuffer = 0
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// MARK: - EXGLContextDelegate
|
|
303
|
+
|
|
304
|
+
// [GL thread]
|
|
305
|
+
func glContextFlushed(_ context: EXGLContext) {
|
|
306
|
+
// blit framebuffers if endFrameEXP was called
|
|
307
|
+
if EXGLContextNeedsRedraw(glContext.contextId) {
|
|
308
|
+
// actually draw isn't yet finished, but it's here to prevent blitting the same thing multiple times
|
|
309
|
+
EXGLContextDrawEnded(glContext.contextId)
|
|
310
|
+
|
|
311
|
+
blitFramebuffers()
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// [JS thread]
|
|
316
|
+
func glContextInitialized(_ context: EXGLContext) {
|
|
317
|
+
maybeCallSurfaceCreated()
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// [GL thread]
|
|
321
|
+
func glContextWillDestroy(_ context: EXGLContext) {
|
|
322
|
+
// Destroy GL objects owned by us
|
|
323
|
+
deleteViewBuffers()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
func glContextGetDefaultFramebuffer() -> EXGLObjectId {
|
|
327
|
+
return msaaFramebuffer
|
|
328
|
+
}
|
|
329
|
+
}
|
package/ios/GLViewModule.swift
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-gl",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.2",
|
|
4
4
|
"description": "Provides GLView that acts as OpenGL ES render target and gives GL context object implementing WebGL 2.0 specification.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"optional": true
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "b7b95a93855cb4863b626c4524fc6e8b3a2305eb"
|
|
61
61
|
}
|
package/ios/EXGLView.h
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Copyright 2016-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
#import <ExpoGL/EXGLNativeApi.h>
|
|
4
|
-
#import <ExpoGL/EXGLContext.h>
|
|
5
|
-
#import <ExpoModulesCore/EXModuleRegistry.h>
|
|
6
|
-
#import <ExpoModulesCore/EXLegacyExpoViewProtocol.h>
|
|
7
|
-
|
|
8
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
9
|
-
|
|
10
|
-
@interface EXGLView : UIView <EXGLContextDelegate, EXLegacyExpoViewProtocol>
|
|
11
|
-
|
|
12
|
-
- (EXGLContextId)exglCtxId;
|
|
13
|
-
|
|
14
|
-
// AR
|
|
15
|
-
- (void)setArSessionManager:(id)arSessionManager;
|
|
16
|
-
- (void)maybeStopARSession;
|
|
17
|
-
|
|
18
|
-
@property (nonatomic, copy, nullable) EXDirectEventBlock onSurfaceCreate;
|
|
19
|
-
@property (nonatomic, assign) NSInteger msaaSamples;
|
|
20
|
-
@property (nonatomic, assign) BOOL enableExperimentalWorkletSupport;
|
|
21
|
-
|
|
22
|
-
// "protected"
|
|
23
|
-
@property (nonatomic, strong, nullable) EXGLContext *glContext;
|
|
24
|
-
@property (nonatomic, strong, nullable) EAGLContext *uiEaglCtx;
|
|
25
|
-
|
|
26
|
-
@end
|
|
27
|
-
|
|
28
|
-
NS_ASSUME_NONNULL_END
|
package/ios/EXGLView.mm
DELETED
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
// Copyright 2016-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
#import <ExpoModulesCore/EXUtilities.h>
|
|
4
|
-
#import <ExpoGL/EXGLView.h>
|
|
5
|
-
#import <ExpoGL/EXGLContext.h>
|
|
6
|
-
|
|
7
|
-
#include <OpenGLES/ES2/glext.h>
|
|
8
|
-
#include <OpenGLES/ES3/gl.h>
|
|
9
|
-
#include <OpenGLES/ES3/glext.h>
|
|
10
|
-
|
|
11
|
-
#define STRINGIZE(x) #x
|
|
12
|
-
#define STRINGIZE2(x) STRINGIZE(x)
|
|
13
|
-
#define SHADER_STRING(text) @ STRINGIZE2(text)
|
|
14
|
-
|
|
15
|
-
@interface EXGLView ()
|
|
16
|
-
|
|
17
|
-
@property (nonatomic, assign) GLint layerWidth;
|
|
18
|
-
@property (nonatomic, assign) GLint layerHeight;
|
|
19
|
-
@property (nonatomic, assign) GLuint viewFramebuffer;
|
|
20
|
-
@property (nonatomic, assign) GLuint viewColorbuffer;
|
|
21
|
-
@property (nonatomic, assign) GLuint viewDepthStencilbuffer;
|
|
22
|
-
@property (nonatomic, assign) GLuint msaaFramebuffer;
|
|
23
|
-
@property (nonatomic, assign) GLuint msaaRenderbuffer;
|
|
24
|
-
@property (nonatomic, strong) dispatch_queue_t glQueue;
|
|
25
|
-
|
|
26
|
-
@property (nonatomic, strong) CADisplayLink *displayLink;
|
|
27
|
-
|
|
28
|
-
@property (nonatomic, assign) BOOL isLayouted;
|
|
29
|
-
@property (nonatomic, assign) BOOL renderbufferPresented;
|
|
30
|
-
@property (nonatomic, assign) CGSize viewBuffersSize;
|
|
31
|
-
|
|
32
|
-
@property (nonatomic, weak) id arSessionManager;
|
|
33
|
-
|
|
34
|
-
@end
|
|
35
|
-
|
|
36
|
-
@implementation EXGLView
|
|
37
|
-
|
|
38
|
-
// Specify that we want this UIView to be backed by a CAEAGLLayer
|
|
39
|
-
+ (Class)layerClass {
|
|
40
|
-
return [CAEAGLLayer class];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
- (instancetype)initWithModuleRegistry:(EXModuleRegistry *)moduleRegistry
|
|
44
|
-
{
|
|
45
|
-
if ((self = [super init])) {
|
|
46
|
-
_isLayouted = NO;
|
|
47
|
-
_renderbufferPresented = YES;
|
|
48
|
-
_viewBuffersSize = CGSizeZero;
|
|
49
|
-
|
|
50
|
-
self.contentScaleFactor = [EXUtilities screenScale];
|
|
51
|
-
|
|
52
|
-
// Initialize properties of our backing CAEAGLLayer
|
|
53
|
-
CAEAGLLayer *eaglLayer = (CAEAGLLayer *) self.layer;
|
|
54
|
-
eaglLayer.opaque = YES;
|
|
55
|
-
eaglLayer.drawableProperties = @{
|
|
56
|
-
kEAGLDrawablePropertyRetainedBacking: @(YES),
|
|
57
|
-
kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Initialize GL context
|
|
61
|
-
_glContext = [[EXGLContext alloc] initWithDelegate:self andModuleRegistry:moduleRegistry];
|
|
62
|
-
_uiEaglCtx = [_glContext createSharedEAGLContext];
|
|
63
|
-
[_glContext initialize];
|
|
64
|
-
|
|
65
|
-
// View buffers will be created on layout event
|
|
66
|
-
_msaaFramebuffer = _msaaRenderbuffer = _viewFramebuffer = _viewColorbuffer = _viewDepthStencilbuffer = 0;
|
|
67
|
-
|
|
68
|
-
// Set up a draw loop
|
|
69
|
-
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(draw)];
|
|
70
|
-
// _displayLink.preferredFramesPerSecond = 60;
|
|
71
|
-
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
72
|
-
}
|
|
73
|
-
return self;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
- (EXGLContextId)exglCtxId
|
|
77
|
-
{
|
|
78
|
-
return [_glContext contextId];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
- (void)maybeCallSurfaceCreated
|
|
82
|
-
{
|
|
83
|
-
// Because initialization things happen asynchronously,
|
|
84
|
-
// we need to be sure that they all are done before we pass GL object to JS.
|
|
85
|
-
|
|
86
|
-
if (_onSurfaceCreate && _glContext.isInitialized && _isLayouted) {
|
|
87
|
-
EXGLContextId exglCtxId = _glContext.contextId;
|
|
88
|
-
_onSurfaceCreate(@{ @"exglCtxId": @(exglCtxId) });
|
|
89
|
-
|
|
90
|
-
// unset onSurfaceCreate - it will not be needed anymore
|
|
91
|
-
_onSurfaceCreate = nil;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
- (void)layoutSubviews
|
|
96
|
-
{
|
|
97
|
-
[self resizeViewBuffersToWidth:self.contentScaleFactor * self.frame.size.width
|
|
98
|
-
height:self.contentScaleFactor * self.frame.size.height];
|
|
99
|
-
|
|
100
|
-
_isLayouted = YES;
|
|
101
|
-
[_glContext prepare:nil andEnableExperimentalWorkletSupport:self.enableExperimentalWorkletSupport];
|
|
102
|
-
[self maybeCallSurfaceCreated];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
- (void)setOnSurfaceCreate:(EXDirectEventBlock)onSurfaceCreate
|
|
106
|
-
{
|
|
107
|
-
_onSurfaceCreate = onSurfaceCreate;
|
|
108
|
-
[self maybeCallSurfaceCreated];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
- (void)runOnUIThread:(void(^)(void))callback
|
|
112
|
-
{
|
|
113
|
-
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
114
|
-
[self->_glContext runInEAGLContext:self->_uiEaglCtx callback:callback];
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
- (void)deleteViewBuffers
|
|
119
|
-
{
|
|
120
|
-
if (_viewDepthStencilbuffer != 0) {
|
|
121
|
-
glDeleteRenderbuffers(1, &_viewDepthStencilbuffer);
|
|
122
|
-
_viewDepthStencilbuffer = 0;
|
|
123
|
-
}
|
|
124
|
-
if (_viewColorbuffer != 0) {
|
|
125
|
-
glDeleteRenderbuffers(1, &_viewColorbuffer);
|
|
126
|
-
_viewColorbuffer = 0;
|
|
127
|
-
}
|
|
128
|
-
if (_viewFramebuffer != 0) {
|
|
129
|
-
glDeleteFramebuffers(1, &_viewFramebuffer);
|
|
130
|
-
_viewFramebuffer = 0;
|
|
131
|
-
}
|
|
132
|
-
if (_msaaRenderbuffer != 0) {
|
|
133
|
-
glDeleteRenderbuffers(1, &_msaaRenderbuffer);
|
|
134
|
-
_msaaRenderbuffer = 0;
|
|
135
|
-
}
|
|
136
|
-
if (_msaaFramebuffer != 0) {
|
|
137
|
-
glDeleteFramebuffers(1, &_msaaFramebuffer);
|
|
138
|
-
_msaaFramebuffer = 0;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
- (void)resizeViewBuffersToWidth:(short)width height:(short)height
|
|
143
|
-
{
|
|
144
|
-
CGSize newViewBuffersSize = CGSizeMake(width, height);
|
|
145
|
-
|
|
146
|
-
// Don't resize if size hasn't changed and the current size is not zero
|
|
147
|
-
if (CGSizeEqualToSize(newViewBuffersSize, _viewBuffersSize) && !CGSizeEqualToSize(_viewBuffersSize, CGSizeZero)) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// update viewBuffersSize on UI thread (before actual resize takes place)
|
|
152
|
-
// to get rid of redundant resizes if layoutSubviews is called multiple times with the same frame size
|
|
153
|
-
_viewBuffersSize = newViewBuffersSize;
|
|
154
|
-
|
|
155
|
-
[_glContext runAsync:^{
|
|
156
|
-
// Save surrounding framebuffer/renderbuffer
|
|
157
|
-
GLint prevFramebuffer;
|
|
158
|
-
GLint prevRenderbuffer;
|
|
159
|
-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFramebuffer);
|
|
160
|
-
glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer);
|
|
161
|
-
if (prevFramebuffer == self->_viewFramebuffer) {
|
|
162
|
-
prevFramebuffer = 0;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Delete old buffers if they exist
|
|
166
|
-
[self deleteViewBuffers];
|
|
167
|
-
|
|
168
|
-
// Set up view framebuffer
|
|
169
|
-
glGenFramebuffers(1, &self->_viewFramebuffer);
|
|
170
|
-
glBindFramebuffer(GL_FRAMEBUFFER, self->_viewFramebuffer);
|
|
171
|
-
|
|
172
|
-
// Set up new color renderbuffer
|
|
173
|
-
glGenRenderbuffers(1, &self->_viewColorbuffer);
|
|
174
|
-
glBindRenderbuffer(GL_RENDERBUFFER, self->_viewColorbuffer);
|
|
175
|
-
|
|
176
|
-
[self runOnUIThread:^{
|
|
177
|
-
glBindRenderbuffer(GL_RENDERBUFFER, self->_viewColorbuffer);
|
|
178
|
-
[self->_uiEaglCtx renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
|
|
179
|
-
}];
|
|
180
|
-
|
|
181
|
-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
182
|
-
GL_RENDERBUFFER, self->_viewColorbuffer);
|
|
183
|
-
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &self->_layerWidth);
|
|
184
|
-
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &self->_layerHeight);
|
|
185
|
-
|
|
186
|
-
// Set up MSAA framebuffer/renderbuffer
|
|
187
|
-
glGenFramebuffers(1, &self->_msaaFramebuffer);
|
|
188
|
-
glGenRenderbuffers(1, &self->_msaaRenderbuffer);
|
|
189
|
-
glBindFramebuffer(GL_FRAMEBUFFER, self->_msaaFramebuffer);
|
|
190
|
-
glBindRenderbuffer(GL_RENDERBUFFER, self->_msaaRenderbuffer);
|
|
191
|
-
glRenderbufferStorageMultisample(GL_RENDERBUFFER, self.msaaSamples, GL_RGBA8,
|
|
192
|
-
self->_layerWidth, self->_layerHeight);
|
|
193
|
-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
194
|
-
GL_RENDERBUFFER, self->_msaaRenderbuffer);
|
|
195
|
-
|
|
196
|
-
EXGLContextSetDefaultFramebuffer(self->_glContext.contextId, self->_msaaFramebuffer);
|
|
197
|
-
|
|
198
|
-
// Set up new depth+stencil renderbuffer
|
|
199
|
-
glGenRenderbuffers(1, &self->_viewDepthStencilbuffer);
|
|
200
|
-
glBindRenderbuffer(GL_RENDERBUFFER, self->_viewDepthStencilbuffer);
|
|
201
|
-
glRenderbufferStorageMultisample(GL_RENDERBUFFER, self.msaaSamples, GL_DEPTH24_STENCIL8,
|
|
202
|
-
self->_layerWidth, self->_layerHeight);
|
|
203
|
-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
|
204
|
-
GL_RENDERBUFFER, self->_viewDepthStencilbuffer);
|
|
205
|
-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
|
|
206
|
-
GL_RENDERBUFFER, self->_viewDepthStencilbuffer);
|
|
207
|
-
|
|
208
|
-
// Resize viewport
|
|
209
|
-
glViewport(0, 0, width, height);
|
|
210
|
-
|
|
211
|
-
// Restore surrounding framebuffer/renderbuffer
|
|
212
|
-
if (prevFramebuffer != 0) {
|
|
213
|
-
glBindFramebuffer(GL_FRAMEBUFFER, prevFramebuffer);
|
|
214
|
-
}
|
|
215
|
-
glBindRenderbuffer(GL_RENDERBUFFER, prevRenderbuffer);
|
|
216
|
-
|
|
217
|
-
// TODO(nikki): Notify JS component of resize
|
|
218
|
-
}];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// TODO(nikki): Should all this be done in `dealloc` instead?
|
|
222
|
-
- (void)removeFromSuperview
|
|
223
|
-
{
|
|
224
|
-
// Destroy EXGLContext
|
|
225
|
-
[_glContext destroy];
|
|
226
|
-
|
|
227
|
-
// Stop draw loop
|
|
228
|
-
[_displayLink invalidate];
|
|
229
|
-
_displayLink = nil;
|
|
230
|
-
|
|
231
|
-
[super removeFromSuperview];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
- (void)draw
|
|
235
|
-
{
|
|
236
|
-
// exglCtxId may be unset if we get here (on the UI thread) before EXGLContextCreate(...) is
|
|
237
|
-
// called on the JS thread to create the EXGL context and save its id (see EXGLContext.initializeContextWithBridge method).
|
|
238
|
-
// In this case no GL work has been sent yet so we skip this frame.
|
|
239
|
-
//
|
|
240
|
-
// _viewFramebuffer may be 0 if we haven't had a layout event yet and so the size of the
|
|
241
|
-
// framebuffer to create is unknown. In this case we have nowhere to render to so we skip
|
|
242
|
-
// this frame (the GL work to run remains on the queue for next time).
|
|
243
|
-
|
|
244
|
-
if (_glContext.isInitialized && _viewFramebuffer != 0) {
|
|
245
|
-
// Present current state of view buffers
|
|
246
|
-
// This happens exactly at `gl.endFrameEXP()` in the queue
|
|
247
|
-
if (_viewColorbuffer != 0 && !_renderbufferPresented) {
|
|
248
|
-
// bind renderbuffer and present it on the layer
|
|
249
|
-
[_glContext runAsync:^{
|
|
250
|
-
glBindRenderbuffer(GL_RENDERBUFFER, self->_viewColorbuffer);
|
|
251
|
-
[self->_uiEaglCtx presentRenderbuffer:GL_RENDERBUFFER];
|
|
252
|
-
}];
|
|
253
|
-
|
|
254
|
-
// mark renderbuffer as presented
|
|
255
|
-
_renderbufferPresented = YES;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// [GL thread] blits framebuffers and then sets a flag that informs UI thread
|
|
261
|
-
// about presenting the new content of the renderbuffer on the next draw call
|
|
262
|
-
- (void)blitFramebuffers
|
|
263
|
-
{
|
|
264
|
-
if (_glContext.isInitialized && _viewFramebuffer != 0 && _viewColorbuffer != 0) {
|
|
265
|
-
// Save surrounding framebuffer
|
|
266
|
-
GLint prevFramebuffer;
|
|
267
|
-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFramebuffer);
|
|
268
|
-
if (prevFramebuffer == _viewFramebuffer) {
|
|
269
|
-
prevFramebuffer = 0;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Resolve multisampling and present
|
|
273
|
-
glBindFramebuffer(GL_READ_FRAMEBUFFER, _msaaFramebuffer);
|
|
274
|
-
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _viewFramebuffer);
|
|
275
|
-
|
|
276
|
-
// glBlitFramebuffer works only on OpenGL ES 3.0, so we need a fallback to Apple's extension for OpenGL ES 2.0
|
|
277
|
-
if (_glContext.eaglCtx.API == kEAGLRenderingAPIOpenGLES3) {
|
|
278
|
-
glBlitFramebuffer(0, 0, _layerWidth, _layerHeight, 0, 0, _layerWidth, _layerHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
279
|
-
} else {
|
|
280
|
-
glResolveMultisampleFramebufferAPPLE();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Restore surrounding framebuffer
|
|
284
|
-
if (prevFramebuffer != 0) {
|
|
285
|
-
glBindFramebuffer(GL_FRAMEBUFFER, prevFramebuffer);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// mark renderbuffer as not presented
|
|
289
|
-
_renderbufferPresented = NO;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
#pragma mark - EXGLContextDelegate
|
|
294
|
-
|
|
295
|
-
// [GL thread]
|
|
296
|
-
- (void)glContextFlushed:(nonnull EXGLContext *)context
|
|
297
|
-
{
|
|
298
|
-
// blit framebuffers if endFrameEXP was called
|
|
299
|
-
if (EXGLContextNeedsRedraw(_glContext.contextId)) {
|
|
300
|
-
// actually draw isn't yet finished, but it's here to prevent blitting the same thing multiple times
|
|
301
|
-
EXGLContextDrawEnded(_glContext.contextId);
|
|
302
|
-
|
|
303
|
-
[self blitFramebuffers];
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// [JS thread]
|
|
308
|
-
- (void)glContextInitialized:(nonnull EXGLContext *)context
|
|
309
|
-
{
|
|
310
|
-
[self maybeCallSurfaceCreated];
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// [GL thread]
|
|
314
|
-
- (void)glContextWillDestroy:(nonnull EXGLContext *)context
|
|
315
|
-
{
|
|
316
|
-
// Stop AR session if running
|
|
317
|
-
[self maybeStopARSession];
|
|
318
|
-
|
|
319
|
-
// Destroy GL objects owned by us
|
|
320
|
-
[self deleteViewBuffers];
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
- (EXGLObjectId)glContextGetDefaultFramebuffer
|
|
324
|
-
{
|
|
325
|
-
return _msaaFramebuffer;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
#pragma mark - maybe AR
|
|
329
|
-
|
|
330
|
-
- (void)setArSessionManager:(id)arSessionManager
|
|
331
|
-
{
|
|
332
|
-
_arSessionManager = arSessionManager;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
- (void)maybeStopARSession
|
|
336
|
-
{
|
|
337
|
-
if (_arSessionManager) {
|
|
338
|
-
[_arSessionManager stop];
|
|
339
|
-
_arSessionManager = nil;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
@end
|