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