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 | const packageJSON = require('../package.json');
|
6 | import { UnavailabilityError } from '@unimodules/core';
|
7 | const { ExponentGLObjectManager, ExponentGLViewManager } = NativeModulesProxy;
|
8 | const NativeView = requireNativeViewManager('ExponentGLView');
|
9 |
|
10 |
|
11 |
|
12 | export class GLView extends React.Component {
|
13 | constructor() {
|
14 | super(...arguments);
|
15 | this.nativeRef = null;
|
16 | this._setNativeRef = (nativeRef) => {
|
17 | if (this.props.nativeRef_EXPERIMENTAL) {
|
18 | this.props.nativeRef_EXPERIMENTAL(nativeRef);
|
19 | }
|
20 | this.nativeRef = nativeRef;
|
21 | };
|
22 | this._onSurfaceCreate = ({ nativeEvent: { exglCtxId } }) => {
|
23 | const gl = getGl(exglCtxId);
|
24 | this.exglCtxId = exglCtxId;
|
25 | if (this.props.onContextCreate) {
|
26 | this.props.onContextCreate(gl);
|
27 | }
|
28 | };
|
29 | }
|
30 | static async createContextAsync() {
|
31 | const { exglCtxId } = await ExponentGLObjectManager.createContextAsync();
|
32 | return getGl(exglCtxId);
|
33 | }
|
34 | static async destroyContextAsync(exgl) {
|
35 | const exglCtxId = getContextId(exgl);
|
36 | return ExponentGLObjectManager.destroyContextAsync(exglCtxId);
|
37 | }
|
38 | static async takeSnapshotAsync(exgl, options = {}) {
|
39 | const exglCtxId = getContextId(exgl);
|
40 | return ExponentGLObjectManager.takeSnapshotAsync(exglCtxId, options);
|
41 | }
|
42 | render() {
|
43 | const { onContextCreate,
|
44 | msaaSamples, ...viewProps } = this.props;
|
45 | return (<View {...viewProps}>
|
46 | <NativeView ref={this._setNativeRef} style={{
|
47 | flex: 1,
|
48 | ...(Platform.OS === 'ios'
|
49 | ? {
|
50 | backgroundColor: 'transparent',
|
51 | }
|
52 | : {}),
|
53 | }} onSurfaceCreate={this._onSurfaceCreate} msaaSamples={Platform.OS === 'ios' ? msaaSamples : undefined}/>
|
54 | </View>);
|
55 | }
|
56 | async startARSessionAsync() {
|
57 | if (!ExponentGLViewManager.startARSessionAsync) {
|
58 | throw new UnavailabilityError('expo-gl', 'startARSessionAsync');
|
59 | }
|
60 | return await ExponentGLViewManager.startARSessionAsync(findNodeHandle(this.nativeRef));
|
61 | }
|
62 | async createCameraTextureAsync(cameraRefOrHandle) {
|
63 | if (!ExponentGLObjectManager.createCameraTextureAsync) {
|
64 | throw new UnavailabilityError('expo-gl', 'createCameraTextureAsync');
|
65 | }
|
66 | const { exglCtxId } = this;
|
67 | if (!exglCtxId) {
|
68 | throw new Error("GLView's surface is not created yet!");
|
69 | }
|
70 | const cameraTag = findNodeHandle(cameraRefOrHandle);
|
71 | const { exglObjId } = await ExponentGLObjectManager.createCameraTextureAsync(exglCtxId, cameraTag);
|
72 | return new WebGLTexture(exglObjId);
|
73 | }
|
74 | async destroyObjectAsync(glObject) {
|
75 | if (!ExponentGLObjectManager.destroyObjectAsync) {
|
76 | throw new UnavailabilityError('expo-gl', 'destroyObjectAsync');
|
77 | }
|
78 | return await ExponentGLObjectManager.destroyObjectAsync(glObject.id);
|
79 | }
|
80 | async takeSnapshotAsync(options = {}) {
|
81 | if (!GLView.takeSnapshotAsync) {
|
82 | throw new UnavailabilityError('expo-gl', 'takeSnapshotAsync');
|
83 | }
|
84 | const { exglCtxId } = this;
|
85 | return await GLView.takeSnapshotAsync(exglCtxId, options);
|
86 | }
|
87 | }
|
88 | GLView.propTypes = {
|
89 | onContextCreate: PropTypes.func,
|
90 | msaaSamples: PropTypes.number,
|
91 | nativeRef_EXPERIMENTAL: PropTypes.func,
|
92 | ...ViewPropTypes,
|
93 | };
|
94 | GLView.defaultProps = {
|
95 | msaaSamples: 4,
|
96 | };
|
97 | GLView.NativeView = NativeView;
|
98 | // JavaScript WebGL types to wrap around native objects
|
99 | class WebGLRenderingContext {
|
100 | }
|
101 | class WebGL2RenderingContext extends WebGLRenderingContext {
|
102 | }
|
103 | const idToObject = {};
|
104 | class WebGLObject {
|
105 | constructor(id) {
|
106 | if (idToObject[id]) {
|
107 | throw new Error(`WebGL object with underlying EXGLObjectId '${id}' already exists!`);
|
108 | }
|
109 | this.id = id; // Native GL object id
|
110 | }
|
111 | toString() {
|
112 | return `[WebGLObject ${this.id}]`;
|
113 | }
|
114 | }
|
115 | const wrapObject = (type, id) => {
|
116 | const found = idToObject[id];
|
117 | if (found) {
|
118 | return found;
|
119 | }
|
120 | return (idToObject[id] = new type(id));
|
121 | };
|
122 | const objectId = (obj) => obj && obj.id;
|
123 | class WebGLBuffer extends WebGLObject {
|
124 | }
|
125 | class WebGLFramebuffer extends WebGLObject {
|
126 | }
|
127 | class WebGLProgram extends WebGLObject {
|
128 | }
|
129 | class WebGLRenderbuffer extends WebGLObject {
|
130 | }
|
131 | class WebGLShader extends WebGLObject {
|
132 | }
|
133 | class WebGLTexture extends WebGLObject {
|
134 | }
|
135 | class WebGLUniformLocation {
|
136 | constructor(id) {
|
137 | this.id = id; // Native GL object id
|
138 | }
|
139 | }
|
140 | class WebGLActiveInfo {
|
141 | constructor(obj) {
|
142 | Object.assign(this, obj);
|
143 | }
|
144 | }
|
145 | class WebGLShaderPrecisionFormat {
|
146 | constructor(obj) {
|
147 | Object.assign(this, obj);
|
148 | }
|
149 | }
|
150 | // WebGL2 classes
|
151 | class WebGLQuery extends WebGLObject {
|
152 | }
|
153 | class WebGLSampler extends WebGLObject {
|
154 | }
|
155 | class WebGLSync extends WebGLObject {
|
156 | }
|
157 | class WebGLTransformFeedback extends WebGLObject {
|
158 | }
|
159 | class WebGLVertexArrayObject extends WebGLObject {
|
160 | }
|
161 | // Many functions need wrapping/unwrapping of arguments and return value. We handle each case
|
162 | // specifically so we can write the tightest code for better performance.
|
163 | const wrapMethods = gl => {
|
164 | const wrap = (methodNames, wrapper) => (Array.isArray(methodNames) ? methodNames : [methodNames]).forEach(methodName => (gl[methodName] = wrapper(gl[methodName])));
|
165 | // We can be slow in `gl.getParameter(...)` since it's a blocking call anyways
|
166 | const getParameterTypes = {
|
167 | [gl.ARRAY_BUFFER_BINDING]: WebGLBuffer,
|
168 | [gl.COPY_READ_BUFFER_BINDING]: WebGLBuffer,
|
169 | [gl.COPY_WRITE_BUFFER_BINDING]: WebGLBuffer,
|
170 | [gl.CURRENT_PROGRAM]: WebGLProgram,
|
171 | [gl.DRAW_FRAMEBUFFER_BINDING]: WebGLFramebuffer,
|
172 | [gl.ELEMENT_ARRAY_BUFFER_BINDING]: WebGLBuffer,
|
173 | [gl.READ_FRAMEBUFFER_BINDING]: WebGLFramebuffer,
|
174 | [gl.RENDERBUFFER_BINDING]: WebGLRenderbuffer,
|
175 | [gl.SAMPLER_BINDING]: WebGLSampler,
|
176 | [gl.TEXTURE_BINDING_2D_ARRAY]: WebGLTexture,
|
177 | [gl.TEXTURE_BINDING_2D]: WebGLTexture,
|
178 | [gl.TEXTURE_BINDING_3D]: WebGLTexture,
|
179 | [gl.TEXTURE_BINDING_CUBE_MAP]: WebGLTexture,
|
180 | [gl.TRANSFORM_FEEDBACK_BINDING]: WebGLTransformFeedback,
|
181 | [gl.TRANSFORM_FEEDBACK_BUFFER_BINDING]: WebGLBuffer,
|
182 | [gl.UNIFORM_BUFFER_BINDING]: WebGLBuffer,
|
183 | [gl.VERTEX_ARRAY_BINDING]: WebGLVertexArrayObject,
|
184 | };
|
185 | wrap('getParameter', orig => pname => {
|
186 | let ret = orig.call(gl, pname);
|
187 | if (pname === gl.VERSION) {
|
188 | // Wrap native version name
|
189 | ret = `WebGL 2.0 (Expo-${Platform.OS}-${packageJSON.version}) (${ret})`;
|
190 | }
|
191 | const type = getParameterTypes[pname];
|
192 | return type ? wrapObject(type, ret) : ret;
|
193 | });
|
194 | // Buffers
|
195 | wrap('bindBuffer', orig => (target, buffer) => orig.call(gl, target, buffer && buffer.id));
|
196 | wrap('createBuffer', orig => () => wrapObject(WebGLBuffer, orig.call(gl)));
|
197 | wrap('deleteBuffer', orig => buffer => orig.call(gl, buffer && buffer.id));
|
198 | wrap('isBuffer', orig => buffer => buffer instanceof WebGLBuffer && orig.call(gl, buffer.id));
|
199 | // Framebuffers
|
200 | wrap('bindFramebuffer', orig => (target, framebuffer) => orig.call(gl, target, framebuffer && framebuffer.id));
|
201 | wrap('createFramebuffer', orig => () => wrapObject(WebGLFramebuffer, orig.call(gl)));
|
202 | wrap('deleteFramebuffer', orig => framebuffer => orig.call(gl, framebuffer && framebuffer.id));
|
203 | wrap('framebufferRenderbuffer', orig => (target, attachment, rbtarget, rb) => orig.call(gl, target, attachment, rbtarget, rb && rb.id));
|
204 | wrap('framebufferTexture2D', orig => (target, attachment, textarget, tex, level) => orig.call(gl, target, attachment, textarget, tex && tex.id, level));
|
205 | wrap('isFramebuffer', orig => framebuffer => framebuffer instanceof WebGLFramebuffer && orig.call(gl, framebuffer.id));
|
206 | wrap('framebufferTextureLayer', orig => (target, attachment, texture, level, layer) => {
|
207 | return orig.call(gl, target, attachment, objectId(texture), level, layer);
|
208 | });
|
209 | // Renderbuffers
|
210 | wrap('bindRenderbuffer', orig => (target, renderbuffer) => orig.call(gl, target, renderbuffer && renderbuffer.id));
|
211 | wrap('createRenderbuffer', orig => () => wrapObject(WebGLRenderbuffer, orig.call(gl)));
|
212 | wrap('deleteRenderbuffer', orig => renderbuffer => orig.call(gl, renderbuffer && renderbuffer.id));
|
213 | wrap('isRenderbuffer', orig => renderbuffer => renderbuffer instanceof WebGLRenderbuffer && orig.call(gl, renderbuffer.id));
|
214 | // Textures
|
215 | wrap('bindTexture', orig => (target, texture) => orig.call(gl, target, texture && texture.id));
|
216 | wrap('createTexture', orig => () => wrapObject(WebGLTexture, orig.call(gl)));
|
217 | wrap('deleteTexture', orig => texture => orig.call(gl, texture && texture.id));
|
218 | wrap('isTexture', orig => texture => texture instanceof WebGLTexture && orig.call(gl, texture.id));
|
219 | // Programs and shaders
|
220 | wrap('attachShader', orig => (program, shader) => orig.call(gl, program && program.id, shader && shader.id));
|
221 | wrap('bindAttribLocation', orig => (program, index, name) => orig.call(gl, program && program.id, index, name));
|
222 | wrap('compileShader', orig => shader => orig.call(gl, shader && shader.id));
|
223 | wrap('createProgram', orig => () => wrapObject(WebGLProgram, orig.call(gl)));
|
224 | wrap('createShader', orig => type => wrapObject(WebGLShader, orig.call(gl, type)));
|
225 | wrap('deleteProgram', orig => program => orig.call(gl, program && program.id));
|
226 | wrap('deleteShader', orig => shader => orig.call(gl, shader && shader.id));
|
227 | wrap('detachShader', orig => (program, shader) => orig.call(gl, program && program.id, shader && shader.id));
|
228 | wrap('getAttachedShaders', orig => program => orig.call(gl, program && program.id).map(id => wrapObject(WebGLShader, id)));
|
229 | wrap('getProgramParameter', orig => (program, pname) => orig.call(gl, program && program.id, pname));
|
230 | wrap('getProgramInfoLog', orig => program => orig.call(gl, program && program.id));
|
231 | wrap('getShaderParameter', orig => (shader, pname) => orig.call(gl, shader && shader.id, pname));
|
232 | wrap('getShaderPrecisionFormat', orig => (shadertype, precisiontype) => new WebGLShaderPrecisionFormat(orig.call(gl, shadertype, precisiontype)));
|
233 | wrap('getShaderInfoLog', orig => shader => orig.call(gl, shader && shader.id));
|
234 | wrap('getShaderSource', orig => shader => orig.call(gl, shader && shader.id));
|
235 | wrap('linkProgram', orig => program => orig.call(gl, program && program.id));
|
236 | wrap('shaderSource', orig => (shader, source) => orig.call(gl, shader && shader.id, source));
|
237 | wrap('useProgram', orig => program => orig.call(gl, program && program.id));
|
238 | wrap('validateProgram', orig => program => orig.call(gl, program && program.id));
|
239 | wrap('isShader', orig => shader => shader instanceof WebGLShader && orig.call(gl, shader.id));
|
240 | wrap('isProgram', orig => program => program instanceof WebGLProgram && orig.call(gl, program.id));
|
241 | wrap('getFragDataLocation', orig => program => orig.call(gl, objectId(program)));
|
242 | // Uniforms and attributes
|
243 | wrap('getActiveAttrib', orig => (program, index) => new WebGLActiveInfo(orig.call(gl, program && program.id, index)));
|
244 | wrap('getActiveUniform', orig => (program, index) => new WebGLActiveInfo(orig.call(gl, program && program.id, index)));
|
245 | wrap('getAttribLocation', orig => (program, name) => orig.call(gl, program && program.id, name));
|
246 | wrap('getUniform', orig => (program, location) => orig.call(gl, program && program.id, location && location.id));
|
247 | wrap('getUniformLocation', orig => (program, name) => new WebGLUniformLocation(orig.call(gl, program && program.id, name)));
|
248 | wrap(['uniform1f', 'uniform1i', 'uniform1ui'], orig => (loc, x) => orig.call(gl, objectId(loc), x));
|
249 | wrap(['uniform2f', 'uniform2i', 'uniform2ui'], orig => (loc, x, y) => orig.call(gl, objectId(loc), x, y));
|
250 | wrap(['uniform3f', 'uniform3i', 'uniform3ui'], orig => (loc, x, y, z) => orig.call(gl, objectId(loc), x, y, z));
|
251 | wrap(['uniform4f', 'uniform4i', 'uniform4ui'], orig => (loc, x, y, z, w) => orig.call(gl, objectId(loc), x, y, z, w));
|
252 | wrap(['uniform1fv', 'uniform2fv', 'uniform3fv', 'uniform4fv'], orig => (loc, val) => orig.call(gl, objectId(loc), new Float32Array(val)));
|
253 | wrap(['uniform1iv', 'uniform2iv', 'uniform3iv', 'uniform4iv'], orig => (loc, val) => orig.call(gl, objectId(loc), new Int32Array(val)));
|
254 | wrap(['uniform1uiv', 'uniform2uiv', 'uniform3uiv', 'uniform4uiv'], orig => (loc, val) => orig.call(gl, objectId(loc), new Uint32Array(val)));
|
255 | wrap([
|
256 | 'uniformMatrix2fv',
|
257 | 'uniformMatrix3fv',
|
258 | 'uniformMatrix4fv',
|
259 | 'uniformMatrix3x2fv',
|
260 | 'uniformMatrix4x2fv',
|
261 | 'uniformMatrix2x3fv',
|
262 | 'uniformMatrix4x3fv',
|
263 | 'uniformMatrix2x4fv',
|
264 | 'uniformMatrix3x4fv',
|
265 | ], orig => (loc, transpose, val) => orig.call(gl, loc && loc.id, transpose, new Float32Array(val)));
|
266 | wrap(['vertexAttrib1fv', 'vertexAttrib2fv', 'vertexAttrib3fv', 'vertexAttrib4fv'], orig => (index, val) => orig.call(gl, index, new Float32Array(val)));
|
267 | wrap('vertexAttribI4iv', orig => (index, val) => orig.call(gl, index, new Int32Array(val)));
|
268 | wrap('vertexAttribI4uiv', orig => (index, val) => orig.call(gl, index, new Uint32Array(val)));
|
269 | // Query objects
|
270 | wrap('createQuery', orig => () => wrapObject(WebGLQuery, orig.call(gl)));
|
271 | wrap('deleteQuery', orig => query => orig.call(gl, objectId(query)));
|
272 | wrap('beginQuery', orig => (target, query) => orig.call(gl, target, objectId(query)));
|
273 | wrap('getQuery', orig => (target, pname) => {
|
274 | const id = orig.call(gl, target, pname);
|
275 | return id ? wrapObject(WebGLQuery, id) : id;
|
276 | });
|
277 | wrap('getQueryParameter', orig => (query, pname) => orig.call(gl, objectId(query), pname));
|
278 | // Samplers
|
279 | wrap('bindSampler', orig => (unit, sampler) => orig.call(gl, unit, objectId(sampler)));
|
280 | wrap('createSampler', orig => () => wrapObject(WebGLSampler, orig.call(gl)));
|
281 | wrap('deleteSampler', orig => sampler => orig.call(gl, objectId(sampler)));
|
282 | wrap('isSampler', orig => sampler => sampler instanceof WebGLSampler && orig.call(gl, sampler.id));
|
283 | wrap(['samplerParameteri', 'samplerParameterf'], orig => (sampler, pname, param) => {
|
284 | return orig.call(gl, objectId(sampler), pname, param);
|
285 | });
|
286 | wrap('getSamplerParameter', orig => (sampler, pname) => {
|
287 | return orig.call(gl, objectId(sampler), pname);
|
288 | });
|
289 | // Transform feedback
|
290 | wrap('bindTransformFeedback', orig => (target, transformFeedback) => {
|
291 | return orig.call(gl, target, objectId(transformFeedback));
|
292 | });
|
293 | wrap('createTransformFeedback', orig => () => wrapObject(WebGLTransformFeedback, orig.call(gl)));
|
294 | wrap('deleteTransformFeedback', orig => transformFeedback => {
|
295 | return orig.call(gl, objectId(transformFeedback));
|
296 | });
|
297 | wrap('transformFeedbackVaryings', orig => (program, varyings, bufferMode) => {
|
298 | return orig.call(gl, objectId(program), varyings, bufferMode);
|
299 | });
|
300 | wrap('getTransformFeedbackVarying', orig => (program, index) => {
|
301 | return new WebGLActiveInfo(orig.call(gl, objectId(program), index));
|
302 | });
|
303 | // Uniforms and attributes
|
304 | wrap(['bindBufferBase', 'bindBufferRange'], orig => (target, index, buffer, ...rest) => {
|
305 | return orig.call(gl, target, index, objectId(buffer), ...rest);
|
306 | });
|
307 | wrap('getUniformIndices', orig => (program, uniformNames) => {
|
308 | // according to WebGL2 specs, it returns Array instead of Uint32Array
|
309 | const uintArray = orig.call(gl, objectId(program), uniformNames);
|
310 | return Array.from(uintArray);
|
311 | });
|
312 | wrap('getActiveUniforms', orig => (program, uniformIndices, pname) => {
|
313 | // according to WebGL2 specs, it returns Array instead of Int32Array
|
314 | const intArray = orig.call(gl, objectId(program), new Uint32Array(uniformIndices), pname);
|
315 | const boolResult = pname === gl.UNIFORM_IS_ROW_MAJOR;
|
316 | const arr = Array.from(intArray);
|
317 | return boolResult ? arr.map(val => !!val) : arr;
|
318 | });
|
319 | wrap('getUniformBlockIndex', orig => (program, uniformBlockName) => orig.call(gl, objectId(program), uniformBlockName));
|
320 | wrap('getActiveUniformBlockName', orig => (program, uniformBlockIndex) => orig.call(gl, objectId(program), uniformBlockIndex));
|
321 | wrap('uniformBlockBinding', orig => (program, uniformBlockIndex, uniformBlockBinding) => {
|
322 | return orig.call(gl, objectId(program), uniformBlockIndex, uniformBlockBinding);
|
323 | });
|
324 | // Vertex array objects
|
325 | wrap('bindVertexArray', orig => vertexArray => orig.call(gl, vertexArray && vertexArray.id));
|
326 | wrap('createVertexArray', orig => () => wrapObject(WebGLVertexArrayObject, orig.call(gl)));
|
327 | wrap('deleteVertexArray', orig => vertexArray => orig.call(gl, vertexArray && vertexArray.id));
|
328 | wrap('isVertexArray', orig => vertexArray => vertexArray instanceof WebGLVertexArrayObject && orig.call(gl, vertexArray.id));
|
329 | };
|
330 | // Get the GL interface from an EXGLContextID and do JS-side setup
|
331 | const getGl = (exglCtxId) => {
|
332 | const gl = global.__EXGLContexts[exglCtxId];
|
333 | gl.__exglCtxId = exglCtxId;
|
334 | delete global.__EXGLContexts[exglCtxId];
|
335 | // determine the prototype to use, depending on OpenGL ES version
|
336 | const glesVersion = gl.getParameter(gl.VERSION);
|
337 | const supportsWebGL2 = parseFloat(glesVersion.split(/[^\d.]+/g).join(' ')) >= 3.0;
|
338 | const prototype = supportsWebGL2
|
339 | ? global.WebGL2RenderingContext.prototype
|
340 | : global.WebGLRenderingContext.prototype;
|
341 | if (Object.setPrototypeOf) {
|
342 | Object.setPrototypeOf(gl, prototype);
|
343 | }
|
344 | else {
|
345 | // Delete this path when we are competely sure we're using modern JSC on Android. iOS 9+
|
346 | // supports Object.setPrototypeOf.
|
347 | gl.__proto__ = prototype; // eslint-disable-line no-proto
|
348 | }
|
349 | wrapMethods(gl);
|
350 | // No canvas yet...
|
351 | gl.canvas = null;
|
352 | // Drawing buffer width/height
|
353 | // TODO(nikki): Make this dynamic
|
354 | const viewport = gl.getParameter(gl.VIEWPORT);
|
355 | gl.drawingBufferWidth = viewport[2];
|
356 | gl.drawingBufferHeight = viewport[3];
|
357 | // Enable/disable logging of all GL function calls
|
358 | let enableLogging = false;
|
359 | // $FlowIssue: Flow wants a "value" field
|
360 | Object.defineProperty(gl, 'enableLogging', {
|
361 | configurable: true,
|
362 | get() {
|
363 | return enableLogging;
|
364 | },
|
365 | set(enable) {
|
366 | if (enable === enableLogging) {
|
367 | return;
|
368 | }
|
369 | if (enable) {
|
370 | Object.keys(gl).forEach(key => {
|
371 | if (typeof gl[key] === 'function') {
|
372 | const original = gl[key];
|
373 | gl[key] = (...args) => {
|
374 | console.log(`EXGL: ${key}(${args.join(', ')})`);
|
375 | const r = original.apply(gl, args);
|
376 | console.log(`EXGL: = ${r}`);
|
377 | return r;
|
378 | };
|
379 | gl[key].original = original;
|
380 | }
|
381 | });
|
382 | }
|
383 | else {
|
384 | Object.keys(gl).forEach(key => {
|
385 | if (typeof gl[key] === 'function' && gl[key].original) {
|
386 | gl[key] = gl[key].original;
|
387 | }
|
388 | });
|
389 | }
|
390 | enableLogging = enable;
|
391 | },
|
392 | });
|
393 | return gl;
|
394 | };
|
395 | const getContextId = (exgl) => {
|
396 | const exglCtxId = exgl && typeof exgl === 'object' ? exgl.__exglCtxId : exgl;
|
397 | if (!exglCtxId || typeof exglCtxId !== 'number') {
|
398 | throw new Error(`Invalid EXGLContext id: ${String(exglCtxId)}`);
|
399 | }
|
400 | return exglCtxId;
|
401 | };
|
402 | global.WebGLRenderingContext = WebGLRenderingContext;
|
403 | global.WebGL2RenderingContext = WebGL2RenderingContext;
|
404 | global.WebGLObject = WebGLObject;
|
405 | global.WebGLBuffer = WebGLBuffer;
|
406 | global.WebGLFramebuffer = WebGLFramebuffer;
|
407 | global.WebGLProgram = WebGLProgram;
|
408 | global.WebGLRenderbuffer = WebGLRenderbuffer;
|
409 | global.WebGLShader = WebGLShader;
|
410 | global.WebGLTexture = WebGLTexture;
|
411 | global.WebGLUniformLocation = WebGLUniformLocation;
|
412 | global.WebGLActiveInfo = WebGLActiveInfo;
|
413 | global.WebGLShaderPrecisionFormat = WebGLShaderPrecisionFormat;
|
414 | global.WebGLQuery = WebGLQuery;
|
415 | global.WebGLSampler = WebGLSampler;
|
416 | global.WebGLSync = WebGLSync;
|
417 | global.WebGLTransformFeedback = WebGLTransformFeedback;
|
418 | global.WebGLVertexArrayObject = WebGLVertexArrayObject;
|
419 | //# sourceMappingURL=GLView.js.map |
\ | No newline at end of file |