1 | import * as React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import { NativeModulesProxy, requireNativeViewManager } from '@unimodules/core';
|
4 | import { Platform, View, ViewPropTypes, findNodeHandle } from 'react-native';
|
5 |
|
6 | const packageJSON = require('../package.json');
|
7 |
|
8 | import { SurfaceCreateEvent, GLSnapshot, ExpoWebGLRenderingContext, SnapshotOptions, BaseGLViewProps } from './GLView.types';
|
9 | import { UnavailabilityError } from '@unimodules/core';
|
10 |
|
11 | declare let global: any;
|
12 |
|
13 | const { ExponentGLObjectManager, ExponentGLViewManager } = NativeModulesProxy;
|
14 |
|
15 |
|
16 | type GLViewProps = {
|
17 |
|
18 | |
19 |
|
20 |
|
21 |
|
22 | onContextCreate(gl: ExpoWebGLRenderingContext): void;
|
23 |
|
24 | |
25 |
|
26 |
|
27 | msaaSamples: number;
|
28 |
|
29 | |
30 |
|
31 |
|
32 | nativeRef_EXPERIMENTAL?(callback: ComponentOrHandle | null);
|
33 | } & BaseGLViewProps;
|
34 |
|
35 | type ComponentOrHandle = null | number | React.Component<any, any> | React.ComponentClass<any>;
|
36 | const NativeView = requireNativeViewManager('ExponentGLView');
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | export class GLView extends React.Component<GLViewProps> {
|
42 | static NativeView: any;
|
43 | static propTypes = {
|
44 | onContextCreate: PropTypes.func,
|
45 | msaaSamples: PropTypes.number,
|
46 | nativeRef_EXPERIMENTAL: PropTypes.func,
|
47 | ...ViewPropTypes,
|
48 | };
|
49 |
|
50 | static defaultProps = {
|
51 | msaaSamples: 4,
|
52 | };
|
53 |
|
54 | static async createContextAsync(): Promise<ExpoWebGLRenderingContext> {
|
55 | const { exglCtxId } = await ExponentGLObjectManager.createContextAsync();
|
56 | return getGl(exglCtxId);
|
57 | }
|
58 |
|
59 | static async destroyContextAsync(exgl?: ExpoWebGLRenderingContext | number): Promise<boolean> {
|
60 | const exglCtxId = getContextId(exgl);
|
61 | return ExponentGLObjectManager.destroyContextAsync(exglCtxId);
|
62 | }
|
63 |
|
64 | static async takeSnapshotAsync(
|
65 | exgl?: ExpoWebGLRenderingContext | number,
|
66 | options: SnapshotOptions = {}
|
67 | ): Promise<GLSnapshot> {
|
68 | const exglCtxId = getContextId(exgl);
|
69 | return ExponentGLObjectManager.takeSnapshotAsync(exglCtxId, options);
|
70 | }
|
71 |
|
72 | nativeRef: ComponentOrHandle = null;
|
73 | exglCtxId?: number;
|
74 |
|
75 | render() {
|
76 | const {
|
77 | onContextCreate,
|
78 | msaaSamples,
|
79 | ...viewProps
|
80 | } = this.props;
|
81 |
|
82 | return (
|
83 | <View {...viewProps}>
|
84 | <NativeView
|
85 | ref={this._setNativeRef}
|
86 | style={{
|
87 | flex: 1,
|
88 | ...(Platform.OS === 'ios'
|
89 | ? {
|
90 | backgroundColor: 'transparent',
|
91 | }
|
92 | : {}),
|
93 | }}
|
94 | onSurfaceCreate={this._onSurfaceCreate}
|
95 | msaaSamples={Platform.OS === 'ios' ? msaaSamples : undefined}
|
96 | />
|
97 | </View>
|
98 | );
|
99 | }
|
100 |
|
101 | _setNativeRef = (nativeRef: ComponentOrHandle): void => {
|
102 | if (this.props.nativeRef_EXPERIMENTAL) {
|
103 | this.props.nativeRef_EXPERIMENTAL(nativeRef);
|
104 | }
|
105 | this.nativeRef = nativeRef;
|
106 | };
|
107 |
|
108 | _onSurfaceCreate = ({ nativeEvent: { exglCtxId } }: SurfaceCreateEvent): void => {
|
109 | const gl = getGl(exglCtxId);
|
110 |
|
111 | this.exglCtxId = exglCtxId;
|
112 |
|
113 | if (this.props.onContextCreate) {
|
114 | this.props.onContextCreate(gl);
|
115 | }
|
116 | };
|
117 |
|
118 | async startARSessionAsync(): Promise<any> {
|
119 | if (!ExponentGLViewManager.startARSessionAsync) {
|
120 | throw new UnavailabilityError('expo-gl', 'startARSessionAsync')
|
121 | }
|
122 | return await ExponentGLViewManager.startARSessionAsync(findNodeHandle(this.nativeRef));
|
123 | }
|
124 |
|
125 | async createCameraTextureAsync(cameraRefOrHandle: ComponentOrHandle): Promise<WebGLTexture> {
|
126 | if (!ExponentGLObjectManager.createCameraTextureAsync) {
|
127 | throw new UnavailabilityError('expo-gl', 'createCameraTextureAsync')
|
128 | }
|
129 |
|
130 | const { exglCtxId } = this;
|
131 |
|
132 | if (!exglCtxId) {
|
133 | throw new Error("GLView's surface is not created yet!");
|
134 | }
|
135 |
|
136 | const cameraTag = findNodeHandle(cameraRefOrHandle);
|
137 | const { exglObjId } = await ExponentGLObjectManager.createCameraTextureAsync(
|
138 | exglCtxId,
|
139 | cameraTag
|
140 | );
|
141 | return new WebGLTexture(exglObjId);
|
142 | }
|
143 |
|
144 | async destroyObjectAsync(glObject: WebGLObject): Promise<boolean> {
|
145 | if (!ExponentGLObjectManager.destroyObjectAsync) {
|
146 | throw new UnavailabilityError('expo-gl', 'destroyObjectAsync')
|
147 | }
|
148 | return await ExponentGLObjectManager.destroyObjectAsync(glObject.id);
|
149 | }
|
150 |
|
151 | async takeSnapshotAsync(options: SnapshotOptions = {}): Promise<GLSnapshot> {
|
152 | if (!GLView.takeSnapshotAsync) {
|
153 | throw new UnavailabilityError('expo-gl', 'takeSnapshotAsync')
|
154 | }
|
155 | const { exglCtxId } = this;
|
156 | return await GLView.takeSnapshotAsync(exglCtxId, options);
|
157 | }
|
158 | }
|
159 |
|
160 | GLView.NativeView = NativeView;
|
161 |
|
162 |
|
163 |
|
164 | class WebGLRenderingContext {
|
165 | __exglCtxId?: number;
|
166 | }
|
167 |
|
168 | class WebGL2RenderingContext extends WebGLRenderingContext {}
|
169 |
|
170 | type WebGLObjectId = any;
|
171 |
|
172 | const idToObject = {};
|
173 |
|
174 | class WebGLObject {
|
175 | id: WebGLObjectId;
|
176 |
|
177 | constructor(id: WebGLObjectId) {
|
178 | if (idToObject[id]) {
|
179 | throw new Error(`WebGL object with underlying EXGLObjectId '${id}' already exists!`);
|
180 | }
|
181 | this.id = id;
|
182 | }
|
183 | toString() {
|
184 | return `[WebGLObject ${this.id}]`;
|
185 | }
|
186 | }
|
187 |
|
188 | const wrapObject = (type, id: WebGLObjectId) => {
|
189 | const found = idToObject[id];
|
190 | if (found) {
|
191 | return found;
|
192 | }
|
193 | return (idToObject[id] = new type(id));
|
194 | };
|
195 |
|
196 | const objectId = (obj: WebGLObject) => obj && obj.id;
|
197 |
|
198 | class WebGLBuffer extends WebGLObject {}
|
199 |
|
200 | class WebGLFramebuffer extends WebGLObject {}
|
201 |
|
202 | class WebGLProgram extends WebGLObject {}
|
203 |
|
204 | class WebGLRenderbuffer extends WebGLObject {}
|
205 |
|
206 | class WebGLShader extends WebGLObject {}
|
207 |
|
208 | class WebGLTexture extends WebGLObject {}
|
209 |
|
210 | class WebGLUniformLocation {
|
211 | id: WebGLObjectId;
|
212 |
|
213 | constructor(id: WebGLObjectId) {
|
214 | this.id = id;
|
215 | }
|
216 | }
|
217 |
|
218 | class WebGLActiveInfo {
|
219 | constructor(obj) {
|
220 | Object.assign(this, obj);
|
221 | }
|
222 | }
|
223 |
|
224 | class WebGLShaderPrecisionFormat {
|
225 | constructor(obj) {
|
226 | Object.assign(this, obj);
|
227 | }
|
228 | }
|
229 |
|
230 |
|
231 | class WebGLQuery extends WebGLObject {}
|
232 |
|
233 | class WebGLSampler extends WebGLObject {}
|
234 |
|
235 | class WebGLSync extends WebGLObject {}
|
236 |
|
237 | class WebGLTransformFeedback extends WebGLObject {}
|
238 |
|
239 | class WebGLVertexArrayObject extends WebGLObject {}
|
240 |
|
241 |
|
242 |
|
243 | const wrapMethods = gl => {
|
244 | const wrap = (methodNames, wrapper) =>
|
245 | (Array.isArray(methodNames) ? methodNames : [methodNames]).forEach(
|
246 | methodName => (gl[methodName] = wrapper(gl[methodName]))
|
247 | );
|
248 |
|
249 |
|
250 | const getParameterTypes = {
|
251 | [gl.ARRAY_BUFFER_BINDING]: WebGLBuffer,
|
252 | [gl.COPY_READ_BUFFER_BINDING]: WebGLBuffer,
|
253 | [gl.COPY_WRITE_BUFFER_BINDING]: WebGLBuffer,
|
254 | [gl.CURRENT_PROGRAM]: WebGLProgram,
|
255 | [gl.DRAW_FRAMEBUFFER_BINDING]: WebGLFramebuffer,
|
256 | [gl.ELEMENT_ARRAY_BUFFER_BINDING]: WebGLBuffer,
|
257 | [gl.READ_FRAMEBUFFER_BINDING]: WebGLFramebuffer,
|
258 | [gl.RENDERBUFFER_BINDING]: WebGLRenderbuffer,
|
259 | [gl.SAMPLER_BINDING]: WebGLSampler,
|
260 | [gl.TEXTURE_BINDING_2D_ARRAY]: WebGLTexture,
|
261 | [gl.TEXTURE_BINDING_2D]: WebGLTexture,
|
262 | [gl.TEXTURE_BINDING_3D]: WebGLTexture,
|
263 | [gl.TEXTURE_BINDING_CUBE_MAP]: WebGLTexture,
|
264 | [gl.TRANSFORM_FEEDBACK_BINDING]: WebGLTransformFeedback,
|
265 | [gl.TRANSFORM_FEEDBACK_BUFFER_BINDING]: WebGLBuffer,
|
266 | [gl.UNIFORM_BUFFER_BINDING]: WebGLBuffer,
|
267 | [gl.VERTEX_ARRAY_BINDING]: WebGLVertexArrayObject,
|
268 | };
|
269 | wrap('getParameter', orig => pname => {
|
270 | let ret = orig.call(gl, pname);
|
271 | if (pname === gl.VERSION) {
|
272 |
|
273 | ret = `WebGL 2.0 (Expo-${Platform.OS}-${packageJSON.version}) (${ret})`;
|
274 | }
|
275 | const type = getParameterTypes[pname];
|
276 | return type ? wrapObject(type, ret) : ret;
|
277 | });
|
278 |
|
279 |
|
280 | wrap('bindBuffer', orig => (target, buffer) => orig.call(gl, target, buffer && buffer.id));
|
281 | wrap('createBuffer', orig => () => wrapObject(WebGLBuffer, orig.call(gl)));
|
282 | wrap('deleteBuffer', orig => buffer => orig.call(gl, buffer && buffer.id));
|
283 | wrap('isBuffer', orig => buffer => buffer instanceof WebGLBuffer && orig.call(gl, buffer.id));
|
284 |
|
285 |
|
286 | wrap('bindFramebuffer', orig => (target, framebuffer) =>
|
287 | orig.call(gl, target, framebuffer && framebuffer.id)
|
288 | );
|
289 | wrap('createFramebuffer', orig => () => wrapObject(WebGLFramebuffer, orig.call(gl)));
|
290 | wrap('deleteFramebuffer', orig => framebuffer => orig.call(gl, framebuffer && framebuffer.id));
|
291 | wrap('framebufferRenderbuffer', orig => (target, attachment, rbtarget, rb) =>
|
292 | orig.call(gl, target, attachment, rbtarget, rb && rb.id)
|
293 | );
|
294 | wrap('framebufferTexture2D', orig => (target, attachment, textarget, tex, level) =>
|
295 | orig.call(gl, target, attachment, textarget, tex && tex.id, level)
|
296 | );
|
297 | wrap('isFramebuffer', orig => framebuffer =>
|
298 | framebuffer instanceof WebGLFramebuffer && orig.call(gl, framebuffer.id)
|
299 | );
|
300 | wrap('framebufferTextureLayer', orig => (target, attachment, texture, level, layer) => {
|
301 | return orig.call(gl, target, attachment, objectId(texture), level, layer);
|
302 | });
|
303 |
|
304 |
|
305 | wrap('bindRenderbuffer', orig => (target, renderbuffer) =>
|
306 | orig.call(gl, target, renderbuffer && renderbuffer.id)
|
307 | );
|
308 | wrap('createRenderbuffer', orig => () => wrapObject(WebGLRenderbuffer, orig.call(gl)));
|
309 | wrap('deleteRenderbuffer', orig => renderbuffer =>
|
310 | orig.call(gl, renderbuffer && renderbuffer.id)
|
311 | );
|
312 | wrap('isRenderbuffer', orig => renderbuffer =>
|
313 | renderbuffer instanceof WebGLRenderbuffer && orig.call(gl, renderbuffer.id)
|
314 | );
|
315 |
|
316 |
|
317 | wrap('bindTexture', orig => (target, texture) => orig.call(gl, target, texture && texture.id));
|
318 | wrap('createTexture', orig => () => wrapObject(WebGLTexture, orig.call(gl)));
|
319 | wrap('deleteTexture', orig => texture => orig.call(gl, texture && texture.id));
|
320 | wrap('isTexture', orig => texture =>
|
321 | texture instanceof WebGLTexture && orig.call(gl, texture.id)
|
322 | );
|
323 |
|
324 |
|
325 | wrap('attachShader', orig => (program, shader) =>
|
326 | orig.call(gl, program && program.id, shader && shader.id)
|
327 | );
|
328 | wrap('bindAttribLocation', orig => (program, index, name) =>
|
329 | orig.call(gl, program && program.id, index, name)
|
330 | );
|
331 | wrap('compileShader', orig => shader => orig.call(gl, shader && shader.id));
|
332 | wrap('createProgram', orig => () => wrapObject(WebGLProgram, orig.call(gl)));
|
333 | wrap('createShader', orig => type => wrapObject(WebGLShader, orig.call(gl, type)));
|
334 | wrap('deleteProgram', orig => program => orig.call(gl, program && program.id));
|
335 | wrap('deleteShader', orig => shader => orig.call(gl, shader && shader.id));
|
336 | wrap('detachShader', orig => (program, shader) =>
|
337 | orig.call(gl, program && program.id, shader && shader.id)
|
338 | );
|
339 | wrap('getAttachedShaders', orig => program =>
|
340 | orig.call(gl, program && program.id).map(id => wrapObject(WebGLShader, id))
|
341 | );
|
342 | wrap('getProgramParameter', orig => (program, pname) =>
|
343 | orig.call(gl, program && program.id, pname)
|
344 | );
|
345 | wrap('getProgramInfoLog', orig => program => orig.call(gl, program && program.id));
|
346 | wrap('getShaderParameter', orig => (shader, pname) => orig.call(gl, shader && shader.id, pname));
|
347 | wrap('getShaderPrecisionFormat', orig => (shadertype, precisiontype) =>
|
348 | new WebGLShaderPrecisionFormat(orig.call(gl, shadertype, precisiontype))
|
349 | );
|
350 | wrap('getShaderInfoLog', orig => shader => orig.call(gl, shader && shader.id));
|
351 | wrap('getShaderSource', orig => shader => orig.call(gl, shader && shader.id));
|
352 | wrap('linkProgram', orig => program => orig.call(gl, program && program.id));
|
353 | wrap('shaderSource', orig => (shader, source) => orig.call(gl, shader && shader.id, source));
|
354 | wrap('useProgram', orig => program => orig.call(gl, program && program.id));
|
355 | wrap('validateProgram', orig => program => orig.call(gl, program && program.id));
|
356 | wrap('isShader', orig => shader => shader instanceof WebGLShader && orig.call(gl, shader.id));
|
357 | wrap('isProgram', orig => program =>
|
358 | program instanceof WebGLProgram && orig.call(gl, program.id)
|
359 | );
|
360 | wrap('getFragDataLocation', orig => program => orig.call(gl, objectId(program)));
|
361 |
|
362 |
|
363 | wrap('getActiveAttrib', orig => (program, index) =>
|
364 | new WebGLActiveInfo(orig.call(gl, program && program.id, index))
|
365 | );
|
366 | wrap('getActiveUniform', orig => (program, index) =>
|
367 | new WebGLActiveInfo(orig.call(gl, program && program.id, index))
|
368 | );
|
369 | wrap('getAttribLocation', orig => (program, name) => orig.call(gl, program && program.id, name));
|
370 | wrap('getUniform', orig => (program, location) =>
|
371 | orig.call(gl, program && program.id, location && location.id)
|
372 | );
|
373 | wrap('getUniformLocation', orig => (program, name) =>
|
374 | new WebGLUniformLocation(orig.call(gl, program && program.id, name))
|
375 | );
|
376 | wrap(['uniform1f', 'uniform1i', 'uniform1ui'], orig => (loc, x) =>
|
377 | orig.call(gl, objectId(loc), x)
|
378 | );
|
379 | wrap(['uniform2f', 'uniform2i', 'uniform2ui'], orig => (loc, x, y) =>
|
380 | orig.call(gl, objectId(loc), x, y)
|
381 | );
|
382 | wrap(['uniform3f', 'uniform3i', 'uniform3ui'], orig => (loc, x, y, z) =>
|
383 | orig.call(gl, objectId(loc), x, y, z)
|
384 | );
|
385 | wrap(['uniform4f', 'uniform4i', 'uniform4ui'], orig => (loc, x, y, z, w) =>
|
386 | orig.call(gl, objectId(loc), x, y, z, w)
|
387 | );
|
388 | wrap(['uniform1fv', 'uniform2fv', 'uniform3fv', 'uniform4fv'], orig => (loc, val) =>
|
389 | orig.call(gl, objectId(loc), new Float32Array(val))
|
390 | );
|
391 | wrap(['uniform1iv', 'uniform2iv', 'uniform3iv', 'uniform4iv'], orig => (loc, val) =>
|
392 | orig.call(gl, objectId(loc), new Int32Array(val))
|
393 | );
|
394 | wrap(['uniform1uiv', 'uniform2uiv', 'uniform3uiv', 'uniform4uiv'], orig => (loc, val) =>
|
395 | orig.call(gl, objectId(loc), new Uint32Array(val))
|
396 | );
|
397 | wrap(
|
398 | [
|
399 | 'uniformMatrix2fv',
|
400 | 'uniformMatrix3fv',
|
401 | 'uniformMatrix4fv',
|
402 | 'uniformMatrix3x2fv',
|
403 | 'uniformMatrix4x2fv',
|
404 | 'uniformMatrix2x3fv',
|
405 | 'uniformMatrix4x3fv',
|
406 | 'uniformMatrix2x4fv',
|
407 | 'uniformMatrix3x4fv',
|
408 | ],
|
409 | orig => (loc, transpose, val) => orig.call(gl, loc && loc.id, transpose, new Float32Array(val))
|
410 | );
|
411 | wrap(
|
412 | ['vertexAttrib1fv', 'vertexAttrib2fv', 'vertexAttrib3fv', 'vertexAttrib4fv'],
|
413 | orig => (index, val) => orig.call(gl, index, new Float32Array(val))
|
414 | );
|
415 | wrap('vertexAttribI4iv', orig => (index, val) => orig.call(gl, index, new Int32Array(val)));
|
416 | wrap('vertexAttribI4uiv', orig => (index, val) => orig.call(gl, index, new Uint32Array(val)));
|
417 |
|
418 |
|
419 | wrap('createQuery', orig => () => wrapObject(WebGLQuery, orig.call(gl)));
|
420 | wrap('deleteQuery', orig => query => orig.call(gl, objectId(query)));
|
421 | wrap('beginQuery', orig => (target, query) => orig.call(gl, target, objectId(query)));
|
422 | wrap('getQuery', orig => (target, pname) => {
|
423 | const id = orig.call(gl, target, pname);
|
424 | return id ? wrapObject(WebGLQuery, id) : id;
|
425 | });
|
426 | wrap('getQueryParameter', orig => (query, pname) => orig.call(gl, objectId(query), pname));
|
427 |
|
428 |
|
429 | wrap('bindSampler', orig => (unit, sampler) => orig.call(gl, unit, objectId(sampler)));
|
430 | wrap('createSampler', orig => () => wrapObject(WebGLSampler, orig.call(gl)));
|
431 | wrap('deleteSampler', orig => sampler => orig.call(gl, objectId(sampler)));
|
432 | wrap('isSampler', orig => sampler =>
|
433 | sampler instanceof WebGLSampler && orig.call(gl, sampler.id)
|
434 | );
|
435 | wrap(['samplerParameteri', 'samplerParameterf'], orig => (sampler, pname, param) => {
|
436 | return orig.call(gl, objectId(sampler), pname, param);
|
437 | });
|
438 | wrap('getSamplerParameter', orig => (sampler, pname) => {
|
439 | return orig.call(gl, objectId(sampler), pname);
|
440 | });
|
441 |
|
442 |
|
443 | wrap('bindTransformFeedback', orig => (target, transformFeedback) => {
|
444 | return orig.call(gl, target, objectId(transformFeedback));
|
445 | });
|
446 | wrap('createTransformFeedback', orig => () => wrapObject(WebGLTransformFeedback, orig.call(gl)));
|
447 | wrap('deleteTransformFeedback', orig => transformFeedback => {
|
448 | return orig.call(gl, objectId(transformFeedback));
|
449 | });
|
450 | wrap('transformFeedbackVaryings', orig => (program, varyings, bufferMode) => {
|
451 | return orig.call(gl, objectId(program), varyings, bufferMode);
|
452 | });
|
453 | wrap('getTransformFeedbackVarying', orig => (program, index) => {
|
454 | return new WebGLActiveInfo(orig.call(gl, objectId(program), index));
|
455 | });
|
456 |
|
457 |
|
458 | wrap(['bindBufferBase', 'bindBufferRange'], orig => (target, index, buffer, ...rest) => {
|
459 | return orig.call(gl, target, index, objectId(buffer), ...rest);
|
460 | });
|
461 | wrap('getUniformIndices', orig => (program, uniformNames) => {
|
462 |
|
463 | const uintArray = orig.call(gl, objectId(program), uniformNames);
|
464 | return Array.from(uintArray);
|
465 | });
|
466 | wrap('getActiveUniforms', orig => (program, uniformIndices, pname) => {
|
467 |
|
468 | const intArray = orig.call(gl, objectId(program), new Uint32Array(uniformIndices), pname);
|
469 | const boolResult = pname === gl.UNIFORM_IS_ROW_MAJOR;
|
470 | const arr = Array.from(intArray);
|
471 | return boolResult ? arr.map(val => !!val) : arr;
|
472 | });
|
473 | wrap('getUniformBlockIndex', orig => (program, uniformBlockName) =>
|
474 | orig.call(gl, objectId(program), uniformBlockName)
|
475 | );
|
476 | wrap('getActiveUniformBlockName', orig => (program, uniformBlockIndex) =>
|
477 | orig.call(gl, objectId(program), uniformBlockIndex)
|
478 | );
|
479 | wrap('uniformBlockBinding', orig => (program, uniformBlockIndex, uniformBlockBinding) => {
|
480 | return orig.call(gl, objectId(program), uniformBlockIndex, uniformBlockBinding);
|
481 | });
|
482 |
|
483 |
|
484 | wrap('bindVertexArray', orig => vertexArray => orig.call(gl, vertexArray && vertexArray.id));
|
485 | wrap('createVertexArray', orig => () => wrapObject(WebGLVertexArrayObject, orig.call(gl)));
|
486 | wrap('deleteVertexArray', orig => vertexArray => orig.call(gl, vertexArray && vertexArray.id));
|
487 | wrap('isVertexArray', orig => vertexArray =>
|
488 | vertexArray instanceof WebGLVertexArrayObject && orig.call(gl, vertexArray.id)
|
489 | );
|
490 | };
|
491 |
|
492 |
|
493 | const getGl = (exglCtxId: number): ExpoWebGLRenderingContext => {
|
494 | const gl = global.__EXGLContexts[exglCtxId];
|
495 | gl.__exglCtxId = exglCtxId;
|
496 | delete global.__EXGLContexts[exglCtxId];
|
497 |
|
498 |
|
499 | const glesVersion = gl.getParameter(gl.VERSION);
|
500 | const supportsWebGL2 = parseFloat(glesVersion.split(/[^\d.]+/g).join(' ')) >= 3.0;
|
501 | const prototype = supportsWebGL2
|
502 | ? global.WebGL2RenderingContext.prototype
|
503 | : global.WebGLRenderingContext.prototype;
|
504 |
|
505 | if (Object.setPrototypeOf) {
|
506 | Object.setPrototypeOf(gl, prototype);
|
507 | } else {
|
508 |
|
509 |
|
510 | gl.__proto__ = prototype;
|
511 | }
|
512 |
|
513 | wrapMethods(gl);
|
514 |
|
515 |
|
516 | gl.canvas = null;
|
517 |
|
518 |
|
519 |
|
520 | const viewport = gl.getParameter(gl.VIEWPORT);
|
521 | gl.drawingBufferWidth = viewport[2];
|
522 | gl.drawingBufferHeight = viewport[3];
|
523 |
|
524 |
|
525 | let enableLogging = false;
|
526 |
|
527 |
|
528 | Object.defineProperty(gl, 'enableLogging', {
|
529 | configurable: true,
|
530 | get(): boolean {
|
531 | return enableLogging;
|
532 | },
|
533 | set(enable: boolean): void {
|
534 | if (enable === enableLogging) {
|
535 | return;
|
536 | }
|
537 | if (enable) {
|
538 | Object.keys(gl).forEach(key => {
|
539 | if (typeof gl[key] === 'function') {
|
540 | const original = gl[key];
|
541 | gl[key] = (...args) => {
|
542 | console.log(`EXGL: ${key}(${args.join(', ')})`);
|
543 | const r = original.apply(gl, args);
|
544 | console.log(`EXGL: = ${r}`);
|
545 | return r;
|
546 | };
|
547 | gl[key].original = original;
|
548 | }
|
549 | });
|
550 | } else {
|
551 | Object.keys(gl).forEach(key => {
|
552 | if (typeof gl[key] === 'function' && gl[key].original) {
|
553 | gl[key] = gl[key].original;
|
554 | }
|
555 | });
|
556 | }
|
557 | enableLogging = enable;
|
558 | },
|
559 | });
|
560 |
|
561 | return gl;
|
562 | };
|
563 |
|
564 | const getContextId = (exgl?: ExpoWebGLRenderingContext | number): number => {
|
565 | const exglCtxId = exgl && typeof exgl === 'object' ? exgl.__exglCtxId : exgl;
|
566 |
|
567 | if (!exglCtxId || typeof exglCtxId !== 'number') {
|
568 | throw new Error(`Invalid EXGLContext id: ${String(exglCtxId)}`);
|
569 | }
|
570 | return exglCtxId;
|
571 | };
|
572 |
|
573 | global.WebGLRenderingContext = WebGLRenderingContext;
|
574 | global.WebGL2RenderingContext = WebGL2RenderingContext;
|
575 | global.WebGLObject = WebGLObject;
|
576 | global.WebGLBuffer = WebGLBuffer;
|
577 | global.WebGLFramebuffer = WebGLFramebuffer;
|
578 | global.WebGLProgram = WebGLProgram;
|
579 | global.WebGLRenderbuffer = WebGLRenderbuffer;
|
580 | global.WebGLShader = WebGLShader;
|
581 | global.WebGLTexture = WebGLTexture;
|
582 | global.WebGLUniformLocation = WebGLUniformLocation;
|
583 | global.WebGLActiveInfo = WebGLActiveInfo;
|
584 | global.WebGLShaderPrecisionFormat = WebGLShaderPrecisionFormat;
|
585 | global.WebGLQuery = WebGLQuery;
|
586 | global.WebGLSampler = WebGLSampler;
|
587 | global.WebGLSync = WebGLSync;
|
588 | global.WebGLTransformFeedback = WebGLTransformFeedback;
|
589 | global.WebGLVertexArrayObject = WebGLVertexArrayObject;
|