mirror of
https://github.com/servo/servo.git
synced 2025-07-12 09:53:40 +01:00
162 lines
5.3 KiB
JavaScript
162 lines
5.3 KiB
JavaScript
/*
|
|
Copyright (c) 2016, Brandon Jones.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
|
|
/*
|
|
Caches specified GL state, runs a callback, and restores the cached state when
|
|
done.
|
|
|
|
Example usage:
|
|
|
|
var savedState = [
|
|
gl.ARRAY_BUFFER_BINDING,
|
|
|
|
// TEXTURE_BINDING_2D or _CUBE_MAP must always be followed by the texure unit.
|
|
gl.TEXTURE_BINDING_2D, gl.TEXTURE0,
|
|
|
|
gl.CLEAR_COLOR,
|
|
];
|
|
// After this call the array buffer, texture unit 0, active texture, and clear
|
|
// color will be restored. The viewport will remain changed, however, because
|
|
// gl.VIEWPORT was not included in the savedState list.
|
|
WGLUPreserveGLState(gl, savedState, function(gl) {
|
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, ....);
|
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.texImage2D(gl.TEXTURE_2D, ...);
|
|
|
|
gl.clearColor(1, 0, 0, 1);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
});
|
|
|
|
Note that this is not intended to be fast. Managing state in your own code to
|
|
avoid redundant state setting and querying will always be faster. This function
|
|
is most useful for cases where you may not have full control over the WebGL
|
|
calls being made, such as tooling or effect injectors.
|
|
*/
|
|
|
|
function WGLUPreserveGLState(gl, bindings, callback) {
|
|
if (!bindings) {
|
|
callback(gl);
|
|
return;
|
|
}
|
|
|
|
var boundValues = [];
|
|
|
|
var activeTexture = null;
|
|
for (var i = 0; i < bindings.length; ++i) {
|
|
var binding = bindings[i];
|
|
switch (binding) {
|
|
case gl.TEXTURE_BINDING_2D:
|
|
case gl.TEXTURE_BINDING_CUBE_MAP:
|
|
var textureUnit = bindings[++i];
|
|
if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) {
|
|
console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit");
|
|
boundValues.push(null, null);
|
|
break;
|
|
}
|
|
if (!activeTexture) {
|
|
activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
|
|
}
|
|
gl.activeTexture(textureUnit);
|
|
boundValues.push(gl.getParameter(binding), null);
|
|
break;
|
|
case gl.ACTIVE_TEXTURE:
|
|
activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE);
|
|
boundValues.push(null);
|
|
break;
|
|
default:
|
|
boundValues.push(gl.getParameter(binding));
|
|
break;
|
|
}
|
|
}
|
|
|
|
callback(gl);
|
|
|
|
for (var i = 0; i < bindings.length; ++i) {
|
|
var binding = bindings[i];
|
|
var boundValue = boundValues[i];
|
|
switch (binding) {
|
|
case gl.ACTIVE_TEXTURE:
|
|
break; // Ignore this binding, since we special-case it to happen last.
|
|
case gl.ARRAY_BUFFER_BINDING:
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, boundValue);
|
|
break;
|
|
case gl.COLOR_CLEAR_VALUE:
|
|
gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
|
|
break;
|
|
case gl.COLOR_WRITEMASK:
|
|
gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
|
|
break;
|
|
case gl.CURRENT_PROGRAM:
|
|
gl.useProgram(boundValue);
|
|
break;
|
|
case gl.ELEMENT_ARRAY_BUFFER_BINDING:
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue);
|
|
break;
|
|
case gl.FRAMEBUFFER_BINDING:
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue);
|
|
break;
|
|
case gl.RENDERBUFFER_BINDING:
|
|
gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue);
|
|
break;
|
|
case gl.TEXTURE_BINDING_2D:
|
|
var textureUnit = bindings[++i];
|
|
if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
|
|
break;
|
|
gl.activeTexture(textureUnit);
|
|
gl.bindTexture(gl.TEXTURE_2D, boundValue);
|
|
break;
|
|
case gl.TEXTURE_BINDING_CUBE_MAP:
|
|
var textureUnit = bindings[++i];
|
|
if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31)
|
|
break;
|
|
gl.activeTexture(textureUnit);
|
|
gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue);
|
|
break;
|
|
case gl.VIEWPORT:
|
|
gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]);
|
|
break;
|
|
case gl.BLEND:
|
|
case gl.CULL_FACE:
|
|
case gl.DEPTH_TEST:
|
|
case gl.SCISSOR_TEST:
|
|
case gl.STENCIL_TEST:
|
|
if (boundValue) {
|
|
gl.enable(binding);
|
|
} else {
|
|
gl.disable(binding);
|
|
}
|
|
break;
|
|
default:
|
|
console.log("No GL restore behavior for 0x" + binding.toString(16));
|
|
break;
|
|
}
|
|
|
|
if (activeTexture) {
|
|
gl.activeTexture(activeTexture);
|
|
}
|
|
}
|
|
}
|