diff --git a/lib/modifiedAPI.js b/lib/modifiedAPI.js index cd28c5f..41a313e 100644 --- a/lib/modifiedAPI.js +++ b/lib/modifiedAPI.js @@ -15,6 +15,8 @@ } const colorStatistics = require("./colorStatistics"); + const logging = require("./logging"); + const {copyCanvasToWebgl} = require("./webgl"); // let Cu = require("chrome").Cu; @@ -101,6 +103,7 @@ return canvas; } catch (e){ + logging.warning("Error while faking:", e); return original; } } @@ -363,34 +366,10 @@ fakeGenerator: function(prefs, notify, window, original){ return function readPixels(x, y, width, height, format, type, pixels){ if (!this || canvasSizeShouldBeFaked(this.canvas, prefs)){ - // not able to use the getFakeCanvas function because the context type is wrong... notify.call(this, "fakedReadout"); - var xPixels = pixels; - var ret = original.apply(this, window.Array.from(arguments)); - var l = xPixels.length; - var ignoredColors = {}; - if (prefs("ignoreFrequentColors")){ - var statistic = colorStatistics.compute(pixels); - ignoredColors = statistic.getMaxColors(prefs("ignoreFrequentColors")); - } - var rng = randomSupply.getPixelRng(l, window, ignoredColors); - var fakeAlphaChannel = prefs("fakeAlphaChannel"); - for (var i = 0; i < l; i += 4){ - var [r, g, b, a] = rng( - xPixels[i + 0], - xPixels[i + 1], - xPixels[i + 2], - xPixels[i + 3], - i / 4 - ); - xPixels[i + 0] = r; - xPixels[i + 1] = g; - xPixels[i + 2] = b; - if (fakeAlphaChannel){ - xPixels[i + 3] = a; - } - } - return ret; + var fakeCanvas = getFakeCanvas(window, this.canvas, prefs); + var {context} = copyCanvasToWebgl(window, fakeCanvas, this instanceof window.WebGLRenderingContext? "webgl": "webgl2"); + return original.apply(context, window.Array.from(arguments)); } else { return original.apply(this, window.Array.from(arguments)); diff --git a/lib/webgl.js b/lib/webgl.js new file mode 100644 index 0000000..a92fa07 --- /dev/null +++ b/lib/webgl.js @@ -0,0 +1,121 @@ +/* jslint moz: true */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +(function(){ + "use strict"; + + var logging = require("./logging"); + + var scope; + if ((typeof exports) !== "undefined"){ + scope = exports; + } + else { + window.scope.webgl = {}; + scope = window.scope.webgl; + } + + scope.copyCanvasToWebgl = function copyCanvasToWebgl(window, canvas, webGLVersion = "webgl"){ + var webGlCanvas = canvas.cloneNode(true); + var success; + var context = + window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, webGLVersion) || + window.HTMLCanvasElement.prototype.getContext.call(webGlCanvas, "experimental-" + webGLVersion); + if (!context){ + // unable to get a context... + logging.warning("unable to create webgl context."); + return {canvas: false, context: false}; + } + + context.viewport(0, 0, webGlCanvas.width, webGlCanvas.height); + + var program = context.createProgram(); + + var shader = context.createShader(context.VERTEX_SHADER); + var vertex = "attribute vec4 a_position;\nattribute vec2 a_texCoord;\nvarying vec2 v_texCoord;\nvoid main(){\n\tgl_Position = a_position;\n\tv_texCoord = a_texCoord;\n}"; + context.shaderSource(shader, vertex); + context.compileShader(shader); + success = context.getShaderParameter(shader, context.COMPILE_STATUS); + if (!success){ + context.deleteShader(shader); + logging.warning("webgl: failed to compile vertex shader."); + return {canvas: false, context: false}; + } + context.attachShader(program, shader); + + var shader = context.createShader(context.FRAGMENT_SHADER); + var fragmenter = "precision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\nvoid main(){\n\tgl_FragColor = texture2D(u_image, v_texCoord);\n}" + context.shaderSource(shader, fragmenter); + context.compileShader(shader); + success = context.getShaderParameter(shader, context.COMPILE_STATUS); + if (!success){ + context.deleteShader(shader); + logging.warning("webgl: failed to compile fragmenter shader."); + return {canvas: false, context: false}; + } + context.attachShader(program, shader); + + context.linkProgram(program); + success = context.getProgramParameter(program, context.LINK_STATUS); + if (!success){ + context.deleteProgram(program); + logging.warning("webgl: failed to link program."); + return {canvas: false, context: false}; + } + + context.useProgram(program); + + var positionAttributeLocation = context.getAttribLocation(program, "a_position"); + var positionBuffer = context.createBuffer(); + context.bindBuffer(context.ARRAY_BUFFER, positionBuffer); + context.bufferData(context.ARRAY_BUFFER, new Float32Array([ + -1,-1, + -1, 1, + 1,-1, + 1, 1, + -1, 1, + 1,-1 + + ]), context.STATIC_DRAW); + + context.enableVertexAttribArray(positionAttributeLocation); + var size = 2; // 2 components per iteration + var type = context.FLOAT; // the data is 32bit floats + var normalize = false; // don't normalize the data + var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position + var offset = 0; // start at the beginning of the buffer + context.vertexAttribPointer( positionAttributeLocation, size, type, normalize, stride, offset); + + var texCoordLocation = context.getAttribLocation(program, "a_texCoord"); + + // provide texture coordinates for the rectangle. + var texCoordBuffer = context.createBuffer(); + context.bindBuffer(context.ARRAY_BUFFER, texCoordBuffer); + context.bufferData(context.ARRAY_BUFFER, new Float32Array([ + 0, 1, + 0, 0, + 1, 1, + 1, 0, + 0, 0, + 1, 1 + ]), context.STATIC_DRAW); + context.enableVertexAttribArray(texCoordLocation); + context.vertexAttribPointer(texCoordLocation, 2, context.FLOAT, false, 0, 0); + + var texture = context.createTexture(); + context.bindTexture(context.TEXTURE_2D, texture); + context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_S, context.CLAMP_TO_EDGE); + context.texParameteri(context.TEXTURE_2D, context.TEXTURE_WRAP_T, context.CLAMP_TO_EDGE); + context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MIN_FILTER, context.NEAREST); + context.texParameteri(context.TEXTURE_2D, context.TEXTURE_MAG_FILTER, context.NEAREST); + context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, context.RGBA, context.UNSIGNED_BYTE, canvas); + + var primitiveType = context.TRIANGLES; + var offset = 0; + var count = 6; + context.drawArrays(primitiveType, offset, count); + + return {webGlCanvas, context}; + }; +}()); \ No newline at end of file diff --git a/manifest.json b/manifest.json index a6a423c..9c77e95 100644 --- a/manifest.json +++ b/manifest.json @@ -22,6 +22,7 @@ "lib/logging.js", "lib/colorStatistics.js", + "lib/webgl.js", "lib/modifiedAPI.js", "lib/randomSupplies.js", "lib/intercept.js",