Skip to content

Commit aaed7e2

Browse files
committed
build
1 parent d78e7c5 commit aaed7e2

File tree

1 file changed

+126
-5
lines changed

1 file changed

+126
-5
lines changed

webgl-memory.js

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* [email protected].9, license MIT */
1+
/* [email protected].10, license MIT */
22
(function (factory) {
33
typeof define === 'function' && define.amd ? define(factory) :
44
factory();
@@ -411,6 +411,9 @@
411411
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
412412
*/
413413

414+
415+
const augmentedSet = new Set();
416+
414417
/**
415418
* Given a WebGL context replaces all the functions with wrapped functions
416419
* that call gl.getError after every command
@@ -419,6 +422,12 @@
419422
* @param {string} nameOfClass (eg, webgl, webgl2, OES_texture_float)
420423
*/
421424
function augmentAPI(ctx, nameOfClass, options = {}) {
425+
426+
if (augmentedSet.has(ctx)) {
427+
return ctx;
428+
}
429+
augmentedSet.add(ctx);
430+
422431
const origGLErrorFn = options.origGLErrorFn || ctx.getError;
423432

424433
function createSharedState(ctx) {
@@ -456,8 +465,66 @@
456465
defaultVertexArray: {},
457466
webglObjectToMemory: new Map(),
458467
};
459-
sharedState.webglObjectToMemory.set(sharedState.defaultVertexArray, {});
460-
sharedState.currentVertexArray = sharedState.defaultVertexArray;
468+
469+
const unRestorableAPIs = new Set([
470+
'webgl',
471+
'webgl2',
472+
'webgl_lose_context',
473+
]);
474+
475+
function resetSharedState() {
476+
sharedState.bindings.clear();
477+
sharedState.webglObjectToMemory.clear();
478+
sharedState.webglObjectToMemory.set(sharedState.defaultVertexArray, {});
479+
sharedState.currentVertexArray = sharedState.defaultVertexArray;
480+
[sharedState.resources, sharedState.memory].forEach(function(obj) {
481+
for (let prop in obj) {
482+
obj[prop] = 0;
483+
}
484+
});
485+
}
486+
487+
function handleContextLost() {
488+
// Issues:
489+
// * all resources are lost.
490+
// Solution: handled by resetSharedState
491+
// * all functions are no-op
492+
// Solutions:
493+
// * swap all functions for noop
494+
// (not so easy because some functions return values)
495+
// * wrap all functions is a isContextLost check forwarder
496+
// (slow? and same as above)
497+
// * have each function manually check for context lost
498+
// (simple but repetitive)
499+
// * all extensions are lost
500+
// Solution: For these we go through and restore all the functions
501+
// on each extension
502+
resetSharedState();
503+
sharedState.isContextLost = true;
504+
505+
// restore all original functions for extensions since
506+
// user will have to get new extensions.
507+
for (const [name, {ctx, origFuncs}] of [...Object.entries(sharedState.apis)]) {
508+
if (!unRestorableAPIs.has(name) && origFuncs) {
509+
augmentedSet.delete(ctx);
510+
for (const [funcName, origFn] of Object.entries(origFuncs)) {
511+
ctx[funcName] = origFn;
512+
}
513+
delete apis[name];
514+
}
515+
}
516+
}
517+
518+
function handleContextRestored() {
519+
sharedState.isContextLost = false;
520+
}
521+
522+
if (ctx.canvas) {
523+
ctx.canvas.addEventListener('webglcontextlost', handleContextLost);
524+
ctx.canvas.addEventListener('webglcontextrestored', handleContextRestored);
525+
}
526+
527+
resetSharedState();
461528
return sharedState;
462529
}
463530

@@ -486,6 +553,9 @@
486553
}
487554
resources[typeName] = 0;
488555
return function(ctx, funcName, args, webglObj) {
556+
if (sharedState.isContextLost) {
557+
return null;
558+
}
489559
++resources[typeName];
490560
webglObjectToMemory.set(webglObj, {
491561
size: 0,
@@ -499,6 +569,9 @@
499569
return;
500570
}
501571
return function(ctx, funcName, args) {
572+
if (sharedState.isContextLost) {
573+
return;
574+
}
502575
const [obj] = args;
503576
const info = webglObjectToMemory.get(obj);
504577
if (info) {
@@ -511,6 +584,9 @@
511584
}
512585

513586
function updateRenderbuffer(target, samples, internalFormat, width, height) {
587+
if (sharedState.isContextLost) {
588+
return;
589+
}
514590
const obj = bindings.get(target);
515591
if (!obj) {
516592
throw new Error(`no renderbuffer bound to ${target}`);
@@ -581,14 +657,14 @@
581657
info.mips[level] = info.mips[level] || [];
582658
const mipFaceInfo = info.mips[level][faceNdx] || {};
583659
info.size -= mipFaceInfo.size || 0;
584-
660+
585661
mipFaceInfo.size = newMipSize;
586662
mipFaceInfo.internalFormat = internalFormat;
587663
mipFaceInfo.type = type;
588664
mipFaceInfo.width = width;
589665
mipFaceInfo.height = height;
590666
mipFaceInfo.depth = depth;
591-
667+
592668
info.mips[level][faceNdx] = mipFaceInfo;
593669
info.size += newMipSize;
594670

@@ -610,11 +686,17 @@
610686
}
611687

612688
function handleBindVertexArray(gl, funcName, args) {
689+
if (sharedState.isContextLost) {
690+
return;
691+
}
613692
const [va] = args;
614693
sharedState.currentVertexArray = va ? va : sharedState.defaultVertexArray;
615694
}
616695

617696
function handleBufferBinding(target, obj) {
697+
if (sharedState.isContextLost) {
698+
return;
699+
}
618700
switch (target) {
619701
case ELEMENT_ARRAY_BUFFER:
620702
const info = webglObjectToMemory.get(sharedState.currentVertexArray);
@@ -635,6 +717,9 @@
635717
// void bufferData(GLenum target, [AllowShared] ArrayBufferView srcData, GLenum usage, GLuint srcOffset,
636718
// optional GLuint length = 0);
637719
bufferData(gl, funcName, args) {
720+
if (sharedState.isContextLost) {
721+
return;
722+
}
638723
const [target, src, /* usage */, srcOffset = 0, length = undefined] = args;
639724
let obj;
640725
switch (target) {
@@ -691,17 +776,26 @@
691776
},
692777

693778
bindRenderbuffer(gl, funcName, args) {
779+
if (sharedState.isContextLost) {
780+
return;
781+
}
694782
const [target, obj] = args;
695783
bindings.set(target, obj);
696784
},
697785

698786
bindTexture(gl, funcName, args) {
787+
if (sharedState.isContextLost) {
788+
return;
789+
}
699790
const [target, obj] = args;
700791
bindings.set(target, obj);
701792
},
702793

703794
// void gl.copyTexImage2D(target, level, internalformat, x, y, width, height, border);
704795
copyTexImage2D(ctx, funcName, args) {
796+
if (sharedState.isContextLost) {
797+
return;
798+
}
705799
const [target, level, internalFormat, x, y, width, height, border] = args;
706800
const info = getTextureInfo(target);
707801
updateMipLevel(info, target, level, internalFormat, width, height, 1, UNSIGNED_BYTE);
@@ -728,6 +822,9 @@
728822
// void gl.compressedTexImage2D(target, level, internalformat, width, height, border,
729823
// ArrayBufferView srcData, optional srcOffset, optional srcLengthOverride);
730824
compressedTexImage2D(ctx, funcName, args) {
825+
if (sharedState.isContextLost) {
826+
return;
827+
}
731828
const [target, level, internalFormat, width, height] = args;
732829
const info = getTextureInfo(target);
733830
updateMipLevel(info, target, level, internalFormat, width, height, 1, UNSIGNED_BYTE);
@@ -738,6 +835,9 @@
738835
// void gl.compressedTexImage3D(target, level, internalformat, width, height, depth, border,
739836
// ArrayBufferView srcData, optional srcOffset, optional srcLengthOverride);
740837
compressedTexImage3D(ctx, funcName, args) {
838+
if (sharedState.isContextLost) {
839+
return;
840+
}
741841
const [target, level, internalFormat, width, height, depth] = args;
742842
const info = getTextureInfo(target);
743843
updateMipLevel(info, target, level, internalFormat, width, height, depth, UNSIGNED_BYTE);
@@ -763,6 +863,9 @@
763863
deleteVertexArrayOES: makeDeleteWrapper('vertexArray', noop, 'deleteVertexArrayOES'),
764864

765865
fenceSync: function(ctx) {
866+
if (sharedState.isContextLost) {
867+
return;
868+
}
766869
if (!ctx.fenceSync) {
767870
return;
768871
}
@@ -777,6 +880,9 @@
777880
}(ctx),
778881

779882
generateMipmap(ctx, funcName, args) {
883+
if (sharedState.isContextLost) {
884+
return;
885+
}
780886
const [target] = args;
781887
const info = getTextureInfo(target);
782888
const baseMipNdx = info.parameters ? info.parameters.get(TEXTURE_BASE_LEVEL) || 0 : 0;
@@ -797,6 +903,9 @@
797903
},
798904

799905
getSupportedExtensions(ctx, funcName, args, result) {
906+
if (sharedState.isContextLost) {
907+
return;
908+
}
800909
result.push('GMAN_webgl_memory');
801910
},
802911

@@ -819,6 +928,9 @@
819928
},
820929

821930
texImage2D(ctx, funcName, args) {
931+
if (sharedState.isContextLost) {
932+
return;
933+
}
822934
// WebGL1:
823935
// void gl.texImage2D(target, level, internalformat, width, height, border, format, type, ArrayBufferView? pixels);
824936
// void gl.texImage2D(target, level, internalformat, format, type, ImageData? pixels);
@@ -865,12 +977,18 @@
865977
// void gl.texImage3D(target, level, internalformat, width, height, depth, border, format, type, ArrayBufferView srcData, srcOffset);
866978

867979
texImage3D(ctx, funcName, args) {
980+
if (sharedState.isContextLost) {
981+
return;
982+
}
868983
let [target, level, internalFormat, width, height, depth, border, format, type] = args;
869984
const info = getTextureInfo(target);
870985
updateMipLevel(info, target, level, internalFormat, width, height, depth, type);
871986
},
872987

873988
texParameteri(ctx, funcName, args) {
989+
if (sharedState.isContextLost) {
990+
return;
991+
}
874992
let [target, pname, value] = args;
875993
const info = getTextureInfo(target);
876994
info.parameters = info.parameters || new Map();
@@ -892,6 +1010,9 @@
8921010

8931011
const extraWrappers = {
8941012
getExtension(ctx, propertyName) {
1013+
if (sharedState.isContextLost) {
1014+
return null;
1015+
}
8951016
const origFn = ctx[propertyName];
8961017
ctx[propertyName] = function(...args) {
8971018
const extensionName = args[0].toLowerCase();

0 commit comments

Comments
 (0)