| /* |
| * Copyright 2010 The Emscripten Authors. All rights reserved. |
| * Emscripten is available under two separate licenses, the MIT license and the |
| * University of Illinois/NCSA Open Source License. Both these licenses can be |
| * found in the LICENSE file. |
| * |
| * GL support. See http://kripken.github.io/emscripten-site/docs/porting/multimedia_and_graphics/OpenGL-support.html |
| * for current status. |
| */ |
| |
| var LibraryWebGL2 = { |
| glGetStringi__deps: ['$stringToNewUTF8'], |
| glGetStringi__sig: 'iii', |
| glGetStringi: function(name, index) { |
| if (GL.currentContext.version < 2) { |
| GL.recordError(0x502 /* GL_INVALID_OPERATION */); // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context |
| return 0; |
| } |
| var stringiCache = GL.stringiCache[name]; |
| if (stringiCache) { |
| if (index < 0 || index >= stringiCache.length) { |
| GL.recordError(0x501/*GL_INVALID_VALUE*/); |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetStringi: index out of range (' + index + ')!'); |
| #endif |
| return 0; |
| } |
| return stringiCache[index]; |
| } |
| switch(name) { |
| case 0x1F03 /* GL_EXTENSIONS */: |
| var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. |
| #if GL_EXTENSIONS_IN_PREFIXED_FORMAT |
| exts = exts.concat(exts.map(function(e) { return "GL_" + e; })); |
| #endif |
| exts = exts.map(function(e) { return stringToNewUTF8(e); }); |
| |
| stringiCache = GL.stringiCache[name] = exts; |
| if (index < 0 || index >= stringiCache.length) { |
| GL.recordError(0x501/*GL_INVALID_VALUE*/); |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetStringi: index out of range (' + index + ') in a call to GL_EXTENSIONS!'); |
| #endif |
| return 0; |
| } |
| return stringiCache[index]; |
| default: |
| GL.recordError(0x500/*GL_INVALID_ENUM*/); |
| #if GL_ASSERTIONS |
| err('GL_INVALID_ENUM in glGetStringi: Unknown parameter ' + name + '!'); |
| #endif |
| return 0; |
| } |
| }, |
| |
| glGetInteger64v__sig: 'vii', |
| glGetInteger64v__deps: ['$emscriptenWebGLGet'], |
| glGetInteger64v: function(name_, p) { |
| emscriptenWebGLGet(name_, p, {{{ cDefine('EM_FUNC_SIG_PARAM_I64') }}}); |
| }, |
| |
| glGetInternalformativ__sig: 'viiiii', |
| glGetInternalformativ: function(target, internalformat, pname, bufSize, params) { |
| if (bufSize < 0) { |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetInternalformativ(target=' + target + ', internalformat=' + internalformat + ', pname=' + pname + ', bufSize=' + bufSize + ', params=' + params + '): Function called with bufSize < 0!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| if (!params) { |
| // GLES3 specification does not specify how to behave if values is a null pointer. Since calling this function does not make sense |
| // if values == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetInternalformativ(target=' + target + ', internalformat=' + internalformat + ', pname=' + pname + ', bufSize=' + bufSize + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| var ret = GLctx['getInternalformatParameter'](target, internalformat, pname); |
| if (ret === null) return; |
| for (var i = 0; i < ret.length && i < bufSize; ++i) { |
| {{{ makeSetValue('params', 'i', 'ret[i]', 'i32') }}}; |
| } |
| }, |
| |
| glCompressedTexImage3D__sig: 'viiiiiiiii', |
| glCompressedTexImage3D: function(target, level, internalFormat, width, height, depth, border, imageSize, data) { |
| if (GLctx.currentPixelUnpackBufferBinding) { |
| GLctx['compressedTexImage3D'](target, level, internalFormat, width, height, depth, border, imageSize, data); |
| } else { |
| GLctx['compressedTexImage3D'](target, level, internalFormat, width, height, depth, border, HEAPU8, data, imageSize); |
| } |
| }, |
| |
| glCompressedTexSubImage3D__sig: 'viiiiiiiiiii', |
| glCompressedTexSubImage3D: function(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) { |
| if (GLctx.currentPixelUnpackBufferBinding) { |
| GLctx['compressedTexSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); |
| } else { |
| GLctx['compressedTexSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, HEAPU8, data, imageSize); |
| } |
| }, |
| |
| glGetBufferParameteri64v__sig: 'viii', |
| glGetBufferParameteri64v: function(target, value, data) { |
| if (!data) { |
| // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense |
| // if data == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetBufferParameteri64v(target=' + target + ', value=' + value + ', data=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| {{{ makeSetValue('data', '0', 'GLctx.getBufferParameter(target, value)', 'i64') }}}; |
| }, |
| |
| glInvalidateFramebuffer__deps: ['_tempFixedLengthArray'], |
| glInvalidateFramebuffer__sig: 'viii', |
| glInvalidateFramebuffer: function(target, numAttachments, attachments) { |
| #if GL_ASSERTIONS |
| assert(numAttachments < __tempFixedLengthArray.length, 'Invalid count of numAttachments=' + numAttachments + ' passed to glInvalidateFramebuffer (that many attachment points do not exist in GL)'); |
| #endif |
| var list = __tempFixedLengthArray[numAttachments]; |
| for (var i = 0; i < numAttachments; i++) { |
| list[i] = {{{ makeGetValue('attachments', 'i*4', 'i32') }}}; |
| } |
| |
| GLctx['invalidateFramebuffer'](target, list); |
| }, |
| |
| glInvalidateSubFramebuffer__deps: ['_tempFixedLengthArray'], |
| glInvalidateSubFramebuffer__sig: 'viiiiiii', |
| glInvalidateSubFramebuffer: function(target, numAttachments, attachments, x, y, width, height) { |
| #if GL_ASSERTIONS |
| assert(numAttachments < __tempFixedLengthArray.length, 'Invalid count of numAttachments=' + numAttachments + ' passed to glInvalidateSubFramebuffer (that many attachment points do not exist in GL)'); |
| #endif |
| var list = __tempFixedLengthArray[numAttachments]; |
| for (var i = 0; i < numAttachments; i++) { |
| list[i] = {{{ makeGetValue('attachments', 'i*4', 'i32') }}}; |
| } |
| |
| GLctx['invalidateSubFramebuffer'](target, list, x, y, width, height); |
| }, |
| |
| glTexImage3D__sig: 'viiiiiiiiii', |
| glTexImage3D__deps: ['_heapObjectForWebGLType', '_heapAccessShiftForWebGLHeap'], |
| glTexImage3D: function(target, level, internalFormat, width, height, depth, border, format, type, pixels) { |
| if (GLctx.currentPixelUnpackBufferBinding) { |
| GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, pixels); |
| } else if (pixels) { |
| var heap = __heapObjectForWebGLType(type); |
| GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, heap, pixels >> __heapAccessShiftForWebGLHeap(heap)); |
| } else { |
| GLctx['texImage3D'](target, level, internalFormat, width, height, depth, border, format, type, null); |
| } |
| }, |
| |
| glTexSubImage3D__sig: 'viiiiiiiiiii', |
| glTexSubImage3D__deps: ['_heapObjectForWebGLType', '_heapAccessShiftForWebGLHeap'], |
| glTexSubImage3D: function(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) { |
| if (GLctx.currentPixelUnpackBufferBinding) { |
| GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); |
| } else if (pixels) { |
| var heap = __heapObjectForWebGLType(type); |
| GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, heap, pixels >> __heapAccessShiftForWebGLHeap(heap)); |
| } else { |
| GLctx['texSubImage3D'](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, null); |
| } |
| }, |
| |
| // Queries |
| glGenQueries__sig: 'vii', |
| glGenQueries__deps: ['_glGenObject'], |
| glGenQueries: function(n, ids) { |
| __glGenObject(n, ids, 'createQuery', GL.queries |
| #if GL_ASSERTIONS |
| , 'glGenQueries' |
| #endif |
| ); |
| }, |
| |
| glDeleteQueries__sig: 'vii', |
| glDeleteQueries: function(n, ids) { |
| for (var i = 0; i < n; i++) { |
| var id = {{{ makeGetValue('ids', 'i*4', 'i32') }}}; |
| var query = GL.queries[id]; |
| if (!query) continue; // GL spec: "unused names in ids are ignored, as is the name zero." |
| GLctx['deleteQuery'](query); |
| GL.queries[id] = null; |
| } |
| }, |
| |
| glIsQuery__sig: 'ii', |
| glIsQuery: function(id) { |
| var query = GL.queries[id]; |
| if (!query) return 0; |
| return GLctx['isQuery'](query); |
| }, |
| |
| glBeginQuery__sig: 'vii', |
| glBeginQuery: function(target, id) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.queries, id, 'glBeginQuery', 'id'); |
| #endif |
| GLctx['beginQuery'](target, GL.queries[id]); |
| }, |
| |
| glGetQueryiv__sig: 'viii', |
| glGetQueryiv: function(target, pname, params) { |
| if (!params) { |
| // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if p == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetQueryiv(target=' + target +', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| {{{ makeSetValue('params', '0', 'GLctx[\'getQuery\'](target, pname)', 'i32') }}}; |
| }, |
| |
| glGetQueryObjectuiv__sig: 'viii', |
| glGetQueryObjectuiv: function(id, pname, params) { |
| if (!params) { |
| // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if p == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetQueryObjectuiv(id=' + id +', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.queries, id, 'glGetQueryObjectuiv', 'id'); |
| #endif |
| var query = GL.queries[id]; |
| var param = GLctx['getQueryParameter'](query, pname); |
| var ret; |
| if (typeof param == 'boolean') { |
| ret = param ? 1 : 0; |
| } else { |
| ret = param; |
| } |
| {{{ makeSetValue('params', '0', 'ret', 'i32') }}}; |
| }, |
| |
| // Sampler objects |
| glGenSamplers__sig: 'vii', |
| glGenSamplers__deps: ['_glGenObject'], |
| glGenSamplers: function(n, samplers) { |
| __glGenObject(n, samplers, 'createSampler', GL.samplers |
| #if GL_ASSERTIONS |
| , 'glGenSamplers' |
| #endif |
| ); |
| }, |
| |
| glDeleteSamplers__sig: 'vii', |
| glDeleteSamplers: function(n, samplers) { |
| for (var i = 0; i < n; i++) { |
| var id = {{{ makeGetValue('samplers', 'i*4', 'i32') }}}; |
| var sampler = GL.samplers[id]; |
| if (!sampler) continue; |
| GLctx['deleteSampler'](sampler); |
| sampler.name = 0; |
| GL.samplers[id] = null; |
| } |
| }, |
| |
| glIsSampler__sig: 'ii', |
| glIsSampler: function(id) { |
| var sampler = GL.samplers[id]; |
| if (!sampler) return 0; |
| return GLctx['isSampler'](sampler); |
| }, |
| |
| glBindSampler__sig: 'vii', |
| glBindSampler: function(unit, sampler) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.samplers, sampler, 'glBindSampler', 'sampler'); |
| #endif |
| GLctx['bindSampler'](unit, GL.samplers[sampler]); |
| }, |
| |
| glSamplerParameterf__sig: 'viif', |
| glSamplerParameterf: function(sampler, pname, param) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.samplers, sampler, 'glBindSampler', 'sampler'); |
| #endif |
| GLctx['samplerParameterf'](GL.samplers[sampler], pname, param); |
| }, |
| |
| glSamplerParameteri__sig: 'viii', |
| glSamplerParameteri: function(sampler, pname, param) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.samplers, sampler, 'glBindSampler', 'sampler'); |
| #endif |
| GLctx['samplerParameteri'](GL.samplers[sampler], pname, param); |
| }, |
| |
| glSamplerParameterfv__sig: 'viii', |
| glSamplerParameterfv: function(sampler, pname, params) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.samplers, sampler, 'glBindSampler', 'sampler'); |
| #endif |
| var param = {{{ makeGetValue('params', '0', 'float') }}}; |
| GLctx['samplerParameterf'](GL.samplers[sampler], pname, param); |
| }, |
| |
| glSamplerParameteriv__sig: 'viii', |
| glSamplerParameteriv: function(sampler, pname, params) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.samplers, sampler, 'glBindSampler', 'sampler'); |
| #endif |
| var param = {{{ makeGetValue('params', '0', 'i32') }}}; |
| GLctx['samplerParameteri'](GL.samplers[sampler], pname, param); |
| }, |
| |
| glGetSamplerParameterfv__sig: 'viii', |
| glGetSamplerParameterfv: function(sampler, pname, params) { |
| if (!params) { |
| // GLES3 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if p == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetSamplerParameterfv(sampler=' + sampler +', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| sampler = GL.samplers[sampler]; |
| {{{ makeSetValue('params', '0', 'GLctx[\'getSamplerParameter\'](sampler, pname)', 'float') }}}; |
| }, |
| |
| glGetSamplerParameteriv__sig: 'viii', |
| glGetSamplerParameteriv: function(sampler, pname, params) { |
| if (!params) { |
| // GLES3 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if p == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetSamplerParameteriv(sampler=' + sampler +', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| sampler = GL.samplers[sampler]; |
| {{{ makeSetValue('params', '0', 'GLctx[\'getSamplerParameter\'](sampler, pname)', 'i32') }}}; |
| }, |
| |
| // Transform Feedback |
| glGenTransformFeedbacks__sig: 'vii', |
| glGenTransformFeedbacks__deps: ['_glGenObject'], |
| glGenTransformFeedbacks: function(n, ids) { |
| __glGenObject(n, ids, 'createTransformFeedback', GL.transformFeedbacks |
| #if GL_ASSERTIONS |
| , 'glGenTransformFeedbacks' |
| #endif |
| ); |
| }, |
| |
| glDeleteTransformFeedbacks__sig: 'vii', |
| glDeleteTransformFeedbacks: function(n, ids) { |
| for (var i = 0; i < n; i++) { |
| var id = {{{ makeGetValue('ids', 'i*4', 'i32') }}}; |
| var transformFeedback = GL.transformFeedbacks[id]; |
| if (!transformFeedback) continue; // GL spec: "unused names in ids are ignored, as is the name zero." |
| GLctx['deleteTransformFeedback'](transformFeedback); |
| transformFeedback.name = 0; |
| GL.transformFeedbacks[id] = null; |
| } |
| }, |
| |
| glIsTransformFeedback__sig: 'ii', |
| glIsTransformFeedback: function(id) { |
| return GLctx['isTransformFeedback'](GL.transformFeedbacks[id]); |
| }, |
| |
| glBindTransformFeedback__sig: 'vii', |
| glBindTransformFeedback: function(target, id) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.transformFeedbacks, id, 'glBindTransformFeedback', 'id'); |
| #endif |
| GLctx['bindTransformFeedback'](target, GL.transformFeedbacks[id]); |
| }, |
| |
| glTransformFeedbackVaryings__sig: 'viiii', |
| glTransformFeedbackVaryings: function(program, count, varyings, bufferMode) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glTransformFeedbackVaryings', 'program'); |
| #endif |
| program = GL.programs[program]; |
| var vars = []; |
| for (var i = 0; i < count; i++) |
| vars.push(UTF8ToString({{{ makeGetValue('varyings', 'i*4', 'i32') }}})); |
| |
| GLctx['transformFeedbackVaryings'](program, vars, bufferMode); |
| }, |
| |
| glGetTransformFeedbackVarying__sig: 'viiiiiii', |
| glGetTransformFeedbackVarying: function(program, index, bufSize, length, size, type, name) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetTransformFeedbackVarying', 'program'); |
| #endif |
| program = GL.programs[program]; |
| var info = GLctx['getTransformFeedbackVarying'](program, index); |
| if (!info) return; // If an error occurred, the return parameters length, size, type and name will be unmodified. |
| |
| if (name && bufSize > 0) { |
| var numBytesWrittenExclNull = stringToUTF8(info.name, name, bufSize); |
| if (length) {{{ makeSetValue('length', '0', 'numBytesWrittenExclNull', 'i32') }}}; |
| } else { |
| if (length) {{{ makeSetValue('length', '0', 0, 'i32') }}}; |
| } |
| |
| if (size) {{{ makeSetValue('size', '0', 'info.size', 'i32') }}}; |
| if (type) {{{ makeSetValue('type', '0', 'info.type', 'i32') }}}; |
| }, |
| |
| $emscriptenWebGLGetIndexed: function(target, index, data, type) { |
| if (!data) { |
| // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense |
| // if data == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetInteger(64)i_v(target=' + target + ', index=' + index + ', data=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| var result = GLctx['getIndexedParameter'](target, index); |
| var ret; |
| switch (typeof result) { |
| case 'boolean': |
| ret = result ? 1 : 0; |
| break; |
| case 'number': |
| ret = result; |
| break; |
| case 'object': |
| if (result === null) { |
| switch (target) { |
| case 0x8C8F: // TRANSFORM_FEEDBACK_BUFFER_BINDING |
| case 0x8A28: // UNIFORM_BUFFER_BINDING |
| ret = 0; |
| break; |
| default: { |
| GL.recordError(0x500); // GL_INVALID_ENUM |
| #if GL_ASSERTIONS |
| err('GL_INVALID_ENUM in glGetInteger(64)i_v(' + target + ') and it returns null!'); |
| #endif |
| return; |
| } |
| } |
| } else if (result instanceof WebGLBuffer) { |
| ret = result.name | 0; |
| } else { |
| GL.recordError(0x500); // GL_INVALID_ENUM |
| #if GL_ASSERTIONS |
| err('GL_INVALID_ENUM in glGetInteger(64)i_v: Unknown object returned from WebGL getIndexedParameter(' + target + ')!'); |
| #endif |
| return; |
| } |
| break; |
| default: |
| GL.recordError(0x500); // GL_INVALID_ENUM |
| #if GL_ASSERTIONS |
| err('GL_INVALID_ENUM in glGetInteger(64)i_v: Native code calling glGetInteger(64)i_v(' + target + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); |
| #endif |
| return; |
| } |
| |
| switch (type) { |
| case {{{ cDefine('EM_FUNC_SIG_PARAM_I64') }}}: {{{ makeSetValue('data', '0', 'ret', 'i64') }}}; break; |
| case {{{ cDefine('EM_FUNC_SIG_PARAM_I') }}}: {{{ makeSetValue('data', '0', 'ret', 'i32') }}}; break; |
| case {{{ cDefine('EM_FUNC_SIG_PARAM_F') }}}: {{{ makeSetValue('data', '0', 'ret', 'float') }}}; break; |
| case {{{ cDefine('EM_FUNC_SIG_PARAM_B') }}}: {{{ makeSetValue('data', '0', 'ret ? 1 : 0', 'i8') }}}; break; |
| default: throw 'internal emscriptenWebGLGetIndexed() error, bad type: ' + type; |
| } |
| }, |
| |
| glGetIntegeri_v__sig: 'viii', |
| glGetIntegeri_v__deps: ['$emscriptenWebGLGetIndexed'], |
| glGetIntegeri_v: function(target, index, data) { |
| emscriptenWebGLGetIndexed(target, index, data, {{{ cDefine('EM_FUNC_SIG_PARAM_I') }}}); |
| }, |
| |
| glGetInteger64i_v__sig: 'viii', |
| glGetInteger64i_v__deps: ['$emscriptenWebGLGetIndexed'], |
| glGetInteger64i_v: function(target, index, data) { |
| emscriptenWebGLGetIndexed(target, index, data, {{{ cDefine('EM_FUNC_SIG_PARAM_I64') }}}); |
| }, |
| |
| // Uniform Buffer objects |
| glBindBufferBase__sig: 'viii', |
| glBindBufferBase: function(target, index, buffer) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.buffers, buffer, 'glBindBufferBase', 'buffer'); |
| #endif |
| GLctx['bindBufferBase'](target, index, GL.buffers[buffer]); |
| }, |
| |
| glBindBufferRange__sig: 'viiiii', |
| glBindBufferRange: function(target, index, buffer, offset, ptrsize) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.buffers, buffer, 'glBindBufferRange', 'buffer'); |
| #endif |
| GLctx['bindBufferRange'](target, index, GL.buffers[buffer], offset, ptrsize); |
| }, |
| |
| glGetUniformIndices__sig: 'viiii', |
| glGetUniformIndices: function(program, uniformCount, uniformNames, uniformIndices) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetUniformIndices', 'program'); |
| #endif |
| if (!uniformIndices) { |
| // GLES2 specification does not specify how to behave if uniformIndices is a null pointer. Since calling this function does not make sense |
| // if uniformIndices == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetUniformIndices(program=' + program + ', uniformCount=' + uniformCount + ', uniformNames=' + uniformNames + ', uniformIndices=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| if (uniformCount > 0 && (uniformNames == 0 || uniformIndices == 0)) { |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| program = GL.programs[program]; |
| var names = []; |
| for (var i = 0; i < uniformCount; i++) |
| names.push(UTF8ToString({{{ makeGetValue('uniformNames', 'i*4', 'i32') }}})); |
| |
| var result = GLctx['getUniformIndices'](program, names); |
| if (!result) return; // GL spec: If an error is generated, nothing is written out to uniformIndices. |
| |
| var len = result.length; |
| for (var i = 0; i < len; i++) { |
| {{{ makeSetValue('uniformIndices', 'i*4', 'result[i]', 'i32') }}}; |
| } |
| }, |
| |
| glGetActiveUniformsiv__sig: 'viiiii', |
| glGetActiveUniformsiv: function(program, uniformCount, uniformIndices, pname, params) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetActiveUniformsiv', 'program'); |
| #endif |
| if (!params) { |
| // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if params == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetActiveUniformsiv(program=' + program + ', uniformCount=' + uniformCount + ', uniformIndices=' + uniformIndices + ', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| if (uniformCount > 0 && uniformIndices == 0) { |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| program = GL.programs[program]; |
| var ids = []; |
| for (var i = 0; i < uniformCount; i++) { |
| ids.push({{{ makeGetValue('uniformIndices', 'i*4', 'i32') }}}); |
| } |
| |
| var result = GLctx['getActiveUniforms'](program, ids, pname); |
| if (!result) return; // GL spec: If an error is generated, nothing is written out to params. |
| |
| var len = result.length; |
| for (var i = 0; i < len; i++) { |
| {{{ makeSetValue('params', 'i*4', 'result[i]', 'i32') }}}; |
| } |
| }, |
| |
| glGetUniformBlockIndex__sig: 'iii', |
| glGetUniformBlockIndex: function(program, uniformBlockName) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetUniformBlockIndex', 'program'); |
| #endif |
| return GLctx['getUniformBlockIndex'](GL.programs[program], UTF8ToString(uniformBlockName)); |
| }, |
| |
| glGetActiveUniformBlockiv__sig: 'viiii', |
| glGetActiveUniformBlockiv: function(program, uniformBlockIndex, pname, params) { |
| if (!params) { |
| // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense |
| // if params == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetActiveUniformBlockiv(program=' + program + ', uniformBlockIndex=' + uniformBlockIndex + ', pname=' + pname + ', params=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetActiveUniformBlockiv', 'program'); |
| #endif |
| program = GL.programs[program]; |
| |
| switch(pname) { |
| case 0x8A41: /* GL_UNIFORM_BLOCK_NAME_LENGTH */ |
| var name = GLctx['getActiveUniformBlockName'](program, uniformBlockIndex); |
| {{{ makeSetValue('params', 0, 'name.length+1', 'i32') }}}; |
| return; |
| default: |
| var result = GLctx['getActiveUniformBlockParameter'](program, uniformBlockIndex, pname); |
| if (!result) return; // If an error occurs, nothing will be written to params. |
| if (typeof result == 'number') { |
| {{{ makeSetValue('params', '0', 'result', 'i32') }}}; |
| } else { |
| for (var i = 0; i < result.length; i++) { |
| {{{ makeSetValue('params', 'i*4', 'result[i]', 'i32') }}}; |
| } |
| } |
| } |
| }, |
| |
| glGetActiveUniformBlockName__sig: 'viiiii', |
| glGetActiveUniformBlockName: function(program, uniformBlockIndex, bufSize, length, uniformBlockName) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetActiveUniformBlockName', 'program'); |
| #endif |
| program = GL.programs[program]; |
| |
| var result = GLctx['getActiveUniformBlockName'](program, uniformBlockIndex); |
| if (!result) return; // If an error occurs, nothing will be written to uniformBlockName or length. |
| if (uniformBlockName && bufSize > 0) { |
| var numBytesWrittenExclNull = stringToUTF8(result, uniformBlockName, bufSize); |
| if (length) {{{ makeSetValue('length', '0', 'numBytesWrittenExclNull', 'i32') }}}; |
| } else { |
| if (length) {{{ makeSetValue('length', '0', 0, 'i32') }}}; |
| } |
| }, |
| |
| glUniformBlockBinding__sig: 'viii', |
| glUniformBlockBinding: function(program, uniformBlockIndex, uniformBlockBinding) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glUniformBlockBinding', 'program'); |
| #endif |
| program = GL.programs[program]; |
| |
| GLctx['uniformBlockBinding'](program, uniformBlockIndex, uniformBlockBinding); |
| }, |
| |
| glClearBufferiv__sig: 'viii', |
| glClearBufferiv: function(buffer, drawbuffer, value) { |
| #if GL_ASSERTIONS |
| assert((value & 3) == 0, 'Pointer to integer data passed to glClearBufferiv must be aligned to four bytes!'); |
| #endif |
| |
| GLctx['clearBufferiv'](buffer, drawbuffer, HEAP32, value>>2); |
| }, |
| |
| glClearBufferuiv__sig: 'viii', |
| glClearBufferuiv: function(buffer, drawbuffer, value) { |
| #if GL_ASSERTIONS |
| assert((value & 3) == 0, 'Pointer to integer data passed to glClearBufferuiv must be aligned to four bytes!'); |
| #endif |
| |
| GLctx['clearBufferuiv'](buffer, drawbuffer, HEAPU32, value>>2); |
| }, |
| |
| glClearBufferfv__sig: 'viii', |
| glClearBufferfv: function(buffer, drawbuffer, value) { |
| #if GL_ASSERTIONS |
| assert((value & 3) == 0, 'Pointer to float data passed to glClearBufferfv must be aligned to four bytes!'); |
| #endif |
| |
| GLctx['clearBufferfv'](buffer, drawbuffer, HEAPF32, value>>2); |
| }, |
| |
| glFenceSync__sig: 'iii', |
| glFenceSync: function(condition, flags) { |
| var sync = GLctx.fenceSync(condition, flags); |
| if (sync) { |
| var id = GL.getNewId(GL.syncs); |
| sync.name = id; |
| GL.syncs[id] = sync; |
| return id; |
| } else { |
| return 0; // Failed to create a sync object |
| } |
| }, |
| |
| glDeleteSync__sig: 'vi', |
| glDeleteSync: function(id) { |
| if (!id) return; |
| var sync = GL.syncs[id]; |
| if (!sync) { // glDeleteSync signals an error when deleting a nonexisting object, unlike some other GL delete functions. |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| GLctx.deleteSync(sync); |
| sync.name = 0; |
| GL.syncs[id] = null; |
| }, |
| |
| glClientWaitSync__sig: 'iiiii', |
| glClientWaitSync: function(sync, flags, timeoutLo, timeoutHi) { |
| // WebGL2 vs GLES3 differences: in GLES3, the timeout parameter is a uint64, where 0xFFFFFFFFFFFFFFFFULL means GL_TIMEOUT_IGNORED. |
| // In JS, there's no 64-bit value types, so instead timeout is taken to be signed, and GL_TIMEOUT_IGNORED is given value -1. |
| // Inherently the value accepted in the timeout is lossy, and can't take in arbitrary u64 bit pattern (but most likely doesn't matter) |
| // See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15 |
| timeoutLo = timeoutLo >>> 0; |
| timeoutHi = timeoutHi >>> 0; |
| var timeout = (timeoutLo == 0xFFFFFFFF && timeoutHi == 0xFFFFFFFF) ? -1 : makeBigInt(timeoutLo, timeoutHi, true); |
| return GLctx.clientWaitSync(GL.syncs[sync], flags, timeout); |
| }, |
| |
| glWaitSync__sig: 'viiii', |
| glWaitSync: function(sync, flags, timeoutLo, timeoutHi) { |
| // See WebGL2 vs GLES3 difference on GL_TIMEOUT_IGNORED above (https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.15) |
| timeoutLo = timeoutLo >>> 0; |
| timeoutHi = timeoutHi >>> 0; |
| var timeout = (timeoutLo == 0xFFFFFFFF && timeoutHi == 0xFFFFFFFF) ? -1 : makeBigInt(timeoutLo, timeoutHi, true); |
| GLctx.waitSync(GL.syncs[sync], flags, timeout); |
| }, |
| |
| glGetSynciv__sig: 'viiiii', |
| glGetSynciv: function(sync, pname, bufSize, length, values) { |
| if (bufSize < 0) { |
| // GLES3 specification does not specify how to behave if bufSize < 0, however in the spec wording for glGetInternalformativ, it does say that GL_INVALID_VALUE should be raised, |
| // so raise GL_INVALID_VALUE here as well. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetSynciv(sync=' + sync + ', pname=' + pname + ', bufSize=' + bufSize + ', length=' + length + ', values='+values+'): Function called with bufSize < 0!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| if (!values) { |
| // GLES3 specification does not specify how to behave if values is a null pointer. Since calling this function does not make sense |
| // if values == null, issue a GL error to notify user about it. |
| #if GL_ASSERTIONS |
| err('GL_INVALID_VALUE in glGetSynciv(sync=' + sync + ', pname=' + pname + ', bufSize=' + bufSize + ', length=' + length + ', values=0): Function called with null out pointer!'); |
| #endif |
| GL.recordError(0x501 /* GL_INVALID_VALUE */); |
| return; |
| } |
| var ret = GLctx.getSyncParameter(GL.syncs[sync], pname); |
| {{{ makeSetValue('length', '0', 'ret', 'i32') }}}; |
| if (ret !== null && length) {{{ makeSetValue('length', '0', '1', 'i32') }}}; // Report a single value outputted. |
| }, |
| |
| glIsSync__sig: 'ii', |
| glIsSync: function(sync) { |
| var sync = GL.syncs[sync]; |
| if (!sync) return 0; |
| return GLctx.isSync(sync); |
| }, |
| |
| glGetUniformuiv__sig: 'viii', |
| glGetUniformuiv__deps: ['$emscriptenWebGLGetUniform'], |
| glGetUniformuiv: function(program, location, params) { |
| emscriptenWebGLGetUniform(program, location, params, {{{ cDefine('EM_FUNC_SIG_PARAM_I') }}}); |
| }, |
| |
| glGetFragDataLocation__sig: 'iii', |
| glGetFragDataLocation: function(program, name) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.programs, program, 'glGetFragDataLocation', 'program'); |
| #endif |
| return GLctx['getFragDataLocation'](GL.programs[program], UTF8ToString(name)); |
| }, |
| |
| glGetVertexAttribIiv__sig: 'viii', |
| glGetVertexAttribIiv__deps: ['$emscriptenWebGLGetVertexAttrib'], |
| glGetVertexAttribIiv: function(index, pname, params) { |
| // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttribI4iv(), |
| // otherwise the results are undefined. (GLES3 spec 6.1.12) |
| emscriptenWebGLGetVertexAttrib(index, pname, params, {{{ cDefine('EM_FUNC_SIG_PARAM_I') }}}); |
| }, |
| |
| // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttribI4uiv(), |
| // otherwise the results are undefined. (GLES3 spec 6.1.12) |
| glGetVertexAttribIuiv__sig: 'viii', |
| glGetVertexAttribIuiv__deps: ['$emscriptenWebGLGetVertexAttrib'], |
| glGetVertexAttribIuiv: 'glGetVertexAttribIiv', |
| |
| glUniform1ui__sig: 'vii', |
| glUniform1ui: function(location, v0) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform1ui', 'location'); |
| #endif |
| GLctx.uniform1ui(GL.uniforms[location], v0); |
| }, |
| |
| glUniform2ui__sig: 'viii', |
| glUniform2ui: function(location, v0, v1) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform2ui', 'location'); |
| #endif |
| GLctx.uniform2ui(GL.uniforms[location], v0, v1); |
| }, |
| |
| glUniform3ui__sig: 'viiii', |
| glUniform3ui: function(location, v0, v1, v2) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform3ui', 'location'); |
| #endif |
| GLctx.uniform3ui(GL.uniforms[location], v0, v1, v2); |
| }, |
| |
| glUniform4ui__sig: 'viiiii', |
| glUniform4ui: function(location, v0, v1, v2, v3) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform4ui', 'location'); |
| #endif |
| GLctx.uniform4ui(GL.uniforms[location], v0, v1, v2, v3); |
| }, |
| |
| glUniform1uiv__sig: 'viii', |
| glUniform1uiv: function(location, count, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform1uiv', 'location'); |
| assert((value & 3) == 0, 'Pointer to integer data passed to glUniform1uiv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniform1uiv(GL.uniforms[location], HEAPU32, value>>2, count); |
| }, |
| |
| glUniform2uiv__sig: 'viii', |
| glUniform2uiv: function(location, count, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform2uiv', 'location'); |
| assert((value & 3) == 0, 'Pointer to integer data passed to glUniform2uiv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniform2uiv(GL.uniforms[location], HEAPU32, value>>2, count*2); |
| }, |
| |
| glUniform3uiv__sig: 'viii', |
| glUniform3uiv: function(location, count, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform3uiv', 'location'); |
| assert((value & 3) == 0, 'Pointer to integer data passed to glUniform3uiv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniform3uiv(GL.uniforms[location], HEAPU32, value>>2, count*3); |
| }, |
| |
| glUniform4uiv__sig: 'viii', |
| glUniform4uiv: function(location, count, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniform4uiv', 'location'); |
| assert((value & 3) == 0, 'Pointer to integer data passed to glUniform4uiv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniform4uiv(GL.uniforms[location], HEAPU32, value>>2, count*4); |
| }, |
| |
| glUniformMatrix2x3fv__sig: 'viiii', |
| glUniformMatrix2x3fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix2x3fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix2x3fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix2x3fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*6); |
| }, |
| |
| glUniformMatrix3x2fv__sig: 'viiii', |
| glUniformMatrix3x2fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix3x2fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix3x2fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix3x2fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*6); |
| }, |
| |
| glUniformMatrix2x4fv__sig: 'viiii', |
| glUniformMatrix2x4fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix2x4fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix2x4fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix2x4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*8); |
| }, |
| |
| glUniformMatrix4x2fv__sig: 'viiii', |
| glUniformMatrix4x2fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix4x2fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4x2fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix4x2fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*8); |
| }, |
| |
| glUniformMatrix3x4fv__sig: 'viiii', |
| glUniformMatrix3x4fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix3x4fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix3x4fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix3x4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*12); |
| }, |
| |
| glUniformMatrix4x3fv__sig: 'viiii', |
| glUniformMatrix4x3fv: function(location, count, transpose, value) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.uniforms, location, 'glUniformMatrix4x3fv', 'location'); |
| assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4x3fv must be aligned to four bytes!'); |
| #endif |
| GLctx.uniformMatrix4x3fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*12); |
| }, |
| |
| glVertexAttribI4iv__sig: 'vii', |
| glVertexAttribI4iv: function(index, v) { |
| #if GL_ASSERTIONS |
| assert((v & 3) == 0, 'Pointer to integer data passed to glVertexAttribI4iv must be aligned to four bytes!'); |
| assert(v != 0, 'Null pointer passed to glVertexAttribI4iv!'); |
| #endif |
| GLctx.vertexAttribI4i(index, HEAP32[v>>2], HEAP32[v+4>>2], HEAP32[v+8>>2], HEAP32[v+12>>2]); |
| }, |
| |
| glVertexAttribI4uiv__sig: 'vii', |
| glVertexAttribI4uiv: function(index, v) { |
| #if GL_ASSERTIONS |
| assert((v & 3) == 0, 'Pointer to integer data passed to glVertexAttribI4uiv must be aligned to four bytes!'); |
| assert(v != 0, 'Null pointer passed to glVertexAttribI4uiv!'); |
| #endif |
| GLctx.vertexAttribI4ui(index, HEAPU32[v>>2], HEAPU32[v+4>>2], HEAPU32[v+8>>2], HEAPU32[v+12>>2]); |
| }, |
| |
| glProgramParameteri__sig: 'viii', |
| glProgramParameteri: function(program, pname, value) { |
| GL.recordError(0x500/*GL_INVALID_ENUM*/); |
| #if GL_ASSERTIONS |
| err("GL_INVALID_ENUM in glProgramParameteri: WebGL does not support binary shader formats! Calls to glProgramParameteri always fail. See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.4"); |
| #endif |
| }, |
| |
| glGetProgramBinary__sig: 'viiiii', |
| glGetProgramBinary: function(program, bufSize, length, binaryFormat, binary) { |
| GL.recordError(0x502/*GL_INVALID_OPERATION*/); |
| #if GL_ASSERTIONS |
| err("GL_INVALID_OPERATION in glGetProgramBinary: WebGL does not support binary shader formats! Calls to glGetProgramBinary always fail. See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.4"); |
| #endif |
| }, |
| |
| glProgramBinary__sig: 'viiii', |
| glProgramBinary: function(program, binaryFormat, binary, length) { |
| GL.recordError(0x500/*GL_INVALID_ENUM*/); |
| #if GL_ASSERTIONS |
| err("GL_INVALID_ENUM in glProgramBinary: WebGL does not support binary shader formats! Calls to glProgramBinary always fail. See https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.4"); |
| #endif |
| }, |
| |
| glFramebufferTextureLayer__sig: 'viiiii', |
| glFramebufferTextureLayer: function(target, attachment, texture, level, layer) { |
| #if GL_ASSERTIONS |
| GL.validateGLObjectID(GL.textures, texture, 'glFramebufferTextureLayer', 'texture'); |
| #endif |
| GLctx.framebufferTextureLayer(target, attachment, GL.textures[texture], level, layer); |
| }, |
| |
| glVertexAttribIPointer__sig: 'viiiii', |
| glVertexAttribIPointer: function(index, size, type, stride, ptr) { |
| #if FULL_ES3 |
| var cb = GL.currentContext.clientBuffers[index]; |
| #if GL_ASSERTIONS |
| assert(cb, index); |
| #endif |
| if (!GL.currArrayBuffer) { |
| cb.size = size; |
| cb.type = type; |
| cb.normalized = false; |
| cb.stride = stride; |
| cb.ptr = ptr; |
| cb.clientside = true; |
| cb.vertexAttribPointerAdaptor = function(index, size, type, normalized, stride, ptr) { |
| this.vertexAttribIPointer(index, size, type, stride, ptr); |
| }; |
| return; |
| } |
| cb.clientside = false; |
| #endif |
| #if GL_ASSERTIONS |
| GL.validateVertexAttribPointer(size, type, stride, ptr); |
| #endif |
| GLctx['vertexAttribIPointer'](index, size, type, stride, ptr); |
| }, |
| |
| glDrawRangeElements__sig: 'viiiiii', |
| glDrawRangeElements__deps: ['glDrawElements'], |
| glDrawRangeElements: function(mode, start, end, count, type, indices) { |
| // TODO: This should be a trivial pass-though function registered at the bottom of this page as |
| // glFuncs[6][1] += ' drawRangeElements'; |
| // but due to https://bugzilla.mozilla.org/show_bug.cgi?id=1202427, |
| // we work around by ignoring the range. |
| _glDrawElements(mode, count, type, indices); |
| }, |
| |
| glVertexAttribI4i__sig: 'viiiii', |
| glVertexAttribI4ui__sig: 'viiiii', |
| glCopyBufferSubData__sig: 'viiiii', |
| glTexStorage2D__sig: 'viiiii', |
| glTexStorage3D__sig: 'viiiiii', |
| glBeginTransformFeedback__sig: 'vi', |
| glEndTransformFeedback__sig: 'v', |
| glPauseTransformFeedback__sig: 'v', |
| glResumeTransformFeedback__sig: 'v', |
| glBlitFramebuffer__sig: 'viiiiiiiiii', |
| glReadBuffer__sig: 'vi', |
| glEndQuery__sig: 'vi', |
| glRenderbufferStorageMultisample__sig: 'viiiii', |
| glCopyTexSubImage3D__sig: 'viiiiiiiii', |
| glClearBufferfi__sig: 'viifi', |
| }; |
| |
| // Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name |
| var webgl2Funcs = [[0, 'endTransformFeedback pauseTransformFeedback resumeTransformFeedback'], |
| [1, 'beginTransformFeedback readBuffer endQuery'], |
| [2, ''], |
| [3, ''], |
| [4, 'clearBufferfi'], |
| [5, 'vertexAttribI4i vertexAttribI4ui copyBufferSubData texStorage2D renderbufferStorageMultisample'], |
| [6, 'texStorage3D'], |
| [7, ''], |
| [8, ''], |
| [9, 'copyTexSubImage3D'], |
| [10, 'blitFramebuffer']]; |
| |
| #if MAX_WEBGL_VERSION >= 2 |
| |
| // If user passes -s MAX_WEBGL_VERSION >= 2 -s STRICT=1 but not -lGL (to link in WebGL 1), then WebGL2 library should not |
| // be linked in as well. |
| if (typeof createGLPassthroughFunctions === 'undefined') { |
| throw 'In order to use WebGL 2 in strict mode with -s MAX_WEBGL_VERSION=2, you need to link in WebGL support with -lGL!'; |
| } |
| |
| createGLPassthroughFunctions(LibraryWebGL2, webgl2Funcs); |
| |
| recordGLProcAddressGet(LibraryWebGL2); |
| |
| mergeInto(LibraryManager.library, LibraryWebGL2); |
| |
| #endif |