From c8acb16fa7428fe927caa6143602935dbdbd7426 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 9 Mar 2023 17:30:04 +0000 Subject: [PATCH] Added `{ willReadFrequently }` to every canvas context, no matter where it comes from --- src/create/GenerateTexture.js | 10 +-- src/display/canvas/CanvasPool.js | 2 +- src/gameobjects/graphics/Graphics.js | 19 +++--- src/gameobjects/text/Text.js | 2 +- src/gameobjects/tilesprite/TileSprite.js | 4 +- src/physics/matter-js/lib/render/Render.js | 76 +++++++++++----------- src/renderer/snapshot/CanvasSnapshot.js | 4 +- src/textures/DynamicTexture.js | 2 +- src/textures/TextureManager.js | 2 +- 9 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/create/GenerateTexture.js b/src/create/GenerateTexture.js index c03b3b37c..b7e79322f 100644 --- a/src/create/GenerateTexture.js +++ b/src/create/GenerateTexture.js @@ -10,7 +10,7 @@ var GetValue = require('../utils/object/GetValue'); /** * Generates a texture based on the given Create configuration object. - * + * * The texture is drawn using a fixed-size indexed palette of 16 colors, where the hex value in the * data cells map to a single color. For example, if the texture config looked like this: * @@ -29,14 +29,14 @@ var GetValue = require('../utils/object/GetValue'); * '.27887.78872.', * '.787.....787.' * ]; - * + * * this.textures.generate('star', { data: star, pixelWidth: 4 }); * ``` - * + * * Then it would generate a texture that is 52 x 48 pixels in size, because each cell of the data array * represents 1 pixel multiplied by the `pixelWidth` value. The cell values, such as `8`, maps to color * number 8 in the palette. If a cell contains a period character `.` then it is transparent. - * + * * The default palette is Arne16, but you can specify your own using the `palette` property. * * @function Phaser.Create.GenerateTexture @@ -74,7 +74,7 @@ var GenerateTexture = function (config) canvas.height = height; } - var ctx = canvas.getContext('2d'); + var ctx = canvas.getContext('2d', { willReadFrequently: true }); if (clearCanvas) { diff --git a/src/display/canvas/CanvasPool.js b/src/display/canvas/CanvasPool.js index 505cf961b..a81407491 100644 --- a/src/display/canvas/CanvasPool.js +++ b/src/display/canvas/CanvasPool.js @@ -82,7 +82,7 @@ var CanvasPool = function () if (_disableContextSmoothing && canvasType === CONST.CANVAS) { - Smoothing.disable(canvas.getContext('2d')); + Smoothing.disable(canvas.getContext('2d', { willReadFrequently: false })); } return canvas; diff --git a/src/gameobjects/graphics/Graphics.js b/src/gameobjects/graphics/Graphics.js index 8cce60ef2..65540125d 100644 --- a/src/gameobjects/graphics/Graphics.js +++ b/src/gameobjects/graphics/Graphics.js @@ -762,7 +762,7 @@ var Graphics = new Class({ var tr = radius; var bl = radius; var br = radius; - + var maxRadius = Math.min(width, height) / 2; if (typeof radius !== 'number') @@ -772,7 +772,7 @@ var Graphics = new Class({ bl = GetFastValue(radius, 'bl', 20); br = GetFastValue(radius, 'br', 20); } - + var convexTL = (tl >= 0); var convexTR = (tr >= 0); var convexBL = (bl >= 0); @@ -782,12 +782,12 @@ var Graphics = new Class({ tr = Math.min(Math.abs(tr), maxRadius); bl = Math.min(Math.abs(bl), maxRadius); br = Math.min(Math.abs(br), maxRadius); - + this.beginPath(); this.moveTo(x + tl, y); this.lineTo(x + width - tr, y); this.moveTo(x + width - tr, y); - + if (convexTR) { this.arc(x + width - tr, y + tr, tr, -MATH_CONST.TAU, 0); @@ -796,7 +796,7 @@ var Graphics = new Class({ { this.arc(x + width, y, tr, Math.PI, MATH_CONST.TAU, true); } - + this.lineTo(x + width, y + height - br); this.moveTo(x + width, y + height - br); @@ -808,7 +808,7 @@ var Graphics = new Class({ { this.arc(x + width, y + height, br, -MATH_CONST.TAU, Math.PI, true); } - + this.lineTo(x + bl, y + height); this.moveTo(x + bl, y + height); @@ -1498,6 +1498,7 @@ var Graphics = new Class({ var texture; var ctx; + var willRead = { willReadFrequently: true }; if (typeof key === 'string') { @@ -1511,7 +1512,7 @@ var Graphics = new Class({ if (src instanceof HTMLCanvasElement) { - ctx = src.getContext('2d'); + ctx = src.getContext('2d', willRead); } } else @@ -1520,14 +1521,14 @@ var Graphics = new Class({ texture = sys.textures.createCanvas(key, width, height); - ctx = texture.getSourceImage().getContext('2d'); + ctx = texture.getSourceImage().getContext('2d', willRead); } } else if (key instanceof HTMLCanvasElement) { // Key is a Canvas, so draw to it - ctx = key.getContext('2d'); + ctx = key.getContext('2d', willRead); } if (ctx) diff --git a/src/gameobjects/text/Text.js b/src/gameobjects/text/Text.js index 173a14bf7..99ba2ecef 100644 --- a/src/gameobjects/text/Text.js +++ b/src/gameobjects/text/Text.js @@ -144,7 +144,7 @@ var Text = new Class({ * @type {CanvasRenderingContext2D} * @since 3.0.0 */ - this.context = this.canvas.getContext('2d'); + this.context = this.canvas.getContext('2d', { willReadFrequently: true }); /** * The Text Style object. diff --git a/src/gameobjects/tilesprite/TileSprite.js b/src/gameobjects/tilesprite/TileSprite.js index 70bd96144..fd0e8e023 100644 --- a/src/gameobjects/tilesprite/TileSprite.js +++ b/src/gameobjects/tilesprite/TileSprite.js @@ -187,7 +187,7 @@ var TileSprite = new Class({ * @type {CanvasRenderingContext2D} * @since 3.12.0 */ - this.context = this.canvas.getContext('2d'); + this.context = this.canvas.getContext('2d', { willReadFrequently: false }); /** * The Texture the TileSprite is using as its fill pattern. @@ -272,7 +272,7 @@ var TileSprite = new Class({ * @type {CanvasRenderingContext2D} * @since 3.12.0 */ - this.fillContext = this.fillCanvas.getContext('2d'); + this.fillContext = this.fillCanvas.getContext('2d', { willReadFrequently: false }); /** * The texture that the Tile Sprite is rendered to, which is then rendered to a Scene. diff --git a/src/physics/matter-js/lib/render/Render.js b/src/physics/matter-js/lib/render/Render.js index 96ce1e88c..aa36dbe8a 100644 --- a/src/physics/matter-js/lib/render/Render.js +++ b/src/physics/matter-js/lib/render/Render.js @@ -19,16 +19,16 @@ var Vector = require('../geometry/Vector'); // var Mouse = require('../core/Mouse'); (function() { - + var _requestAnimationFrame, _cancelAnimationFrame; if (typeof window !== 'undefined') { _requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame - || window.mozRequestAnimationFrame || window.msRequestAnimationFrame + || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(function() { callback(Common.now()); }, 1000 / 60); }; - - _cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame + + _cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; } @@ -86,15 +86,15 @@ var Vector = require('../geometry/Vector'); render.mouse = options.mouse; render.engine = options.engine; render.canvas = render.canvas || _createCanvas(render.options.width, render.options.height); - render.context = render.canvas.getContext('2d'); + render.context = render.canvas.getContext('2d', { willReadFrequently: true }); render.textures = {}; - render.bounds = render.bounds || { - min: { + render.bounds = render.bounds || { + min: { x: 0, y: 0 - }, - max: { + }, + max: { x: render.canvas.width, y: render.canvas.height } @@ -188,19 +188,19 @@ var Vector = require('../geometry/Vector'); for (var i = 0; i < objects.length; i += 1) { var object = objects[i], min = object.bounds ? object.bounds.min : (object.min || object.position || object), - max = object.bounds ? object.bounds.max : (object.max || object.position || object); + max = object.bounds ? object.bounds.max : (object.max || object.position || object); - if (min && max) { - if (min.x < bounds.min.x) + if (min && max) { + if (min.x < bounds.min.x) bounds.min.x = min.x; - - if (max.x > bounds.max.x) + + if (max.x > bounds.max.x) bounds.max.x = max.x; - if (min.y < bounds.min.y) + if (min.y < bounds.min.y) bounds.min.y = min.y; - if (max.y > bounds.max.y) + if (max.y > bounds.max.y) bounds.max.y = max.y; } } @@ -375,7 +375,7 @@ var Vector = require('../geometry/Vector'); if (options.showAxes || options.showAngleIndicator) Render.bodyAxes(render, bodies, context); - + if (options.showPositions) Render.bodyPositions(render, bodies, context); @@ -456,7 +456,7 @@ var Vector = require('../geometry/Vector'); text += "mid: " + metrics.midEff + space; text += "narrow: " + metrics.narrowEff + space; } - // @endif + // @endif render.debugString = text; render.debugTimestamp = engine.timing.timestamp; @@ -555,7 +555,7 @@ var Vector = require('../geometry/Vector'); } } }; - + /** * Description * @private @@ -647,20 +647,20 @@ var Vector = require('../geometry/Vector'); var sprite = part.render.sprite, texture = _getTexture(render, sprite.texture); - c.translate(part.position.x, part.position.y); + c.translate(part.position.x, part.position.y); c.rotate(part.angle); c.drawImage( texture, - texture.width * -sprite.xOffset * sprite.xScale, - texture.height * -sprite.yOffset * sprite.yScale, - texture.width * sprite.xScale, + texture.width * -sprite.xOffset * sprite.xScale, + texture.height * -sprite.yOffset * sprite.yScale, + texture.width * sprite.xScale, texture.height * sprite.yScale ); // revert translation, hopefully faster than save / restore c.rotate(-part.angle); - c.translate(-part.position.x, -part.position.y); + c.translate(-part.position.x, -part.position.y); } else { // part polygon if (part.circleRadius) { @@ -681,7 +681,7 @@ var Vector = require('../geometry/Vector'); c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y); } } - + c.lineTo(part.vertices[0].x, part.vertices[0].y); c.closePath(); } @@ -751,7 +751,7 @@ var Vector = require('../geometry/Vector'); c.moveTo(part.vertices[(j + 1) % part.vertices.length].x, part.vertices[(j + 1) % part.vertices.length].y); } } - + c.lineTo(part.vertices[0].x, part.vertices[0].y); } } @@ -791,7 +791,7 @@ var Vector = require('../geometry/Vector'); for (j = 1; j < body.vertices.length; j++) { c.lineTo(body.vertices[j].x, body.vertices[j].y); } - + c.lineTo(body.vertices[0].x, body.vertices[0].y); } @@ -919,7 +919,7 @@ var Vector = require('../geometry/Vector'); for (k = 0; k < part.axes.length; k++) { // render a single axis indicator c.moveTo(part.position.x, part.position.y); - c.lineTo((part.vertices[0].x + part.vertices[part.vertices.length-1].x) / 2, + c.lineTo((part.vertices[0].x + part.vertices[part.vertices.length-1].x) / 2, (part.vertices[0].y + part.vertices[part.vertices.length-1].y) / 2); } } @@ -1094,7 +1094,7 @@ var Vector = require('../geometry/Vector'); c.fill(); c.beginPath(); - + // render collision normals for (i = 0; i < pairs.length; i++) { pair = pairs[i]; @@ -1112,7 +1112,7 @@ var Vector = require('../geometry/Vector'); normalPosX = (pair.activeContacts[0].vertex.x + pair.activeContacts[1].vertex.x) / 2; normalPosY = (pair.activeContacts[0].vertex.y + pair.activeContacts[1].vertex.y) / 2; } - + if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic === true) { c.moveTo(normalPosX - collision.normal.x * 8, normalPosY - collision.normal.y * 8); } else { @@ -1219,9 +1219,9 @@ var Vector = require('../geometry/Vector'); continue; var region = bucketId.split(/C|R/); - c.rect(0.5 + parseInt(region[1], 10) * grid.bucketWidth, - 0.5 + parseInt(region[2], 10) * grid.bucketHeight, - grid.bucketWidth, + c.rect(0.5 + parseInt(region[1], 10) * grid.bucketWidth, + 0.5 + parseInt(region[2], 10) * grid.bucketHeight, + grid.bucketWidth, grid.bucketHeight); } @@ -1248,7 +1248,7 @@ var Vector = require('../geometry/Vector'); boundsHeight = render.bounds.max.y - render.bounds.min.y, boundsScaleX = boundsWidth / render.options.width, boundsScaleY = boundsHeight / render.options.height; - + context.scale(1 / boundsScaleX, 1 / boundsScaleY); context.translate(-render.bounds.min.x, -render.bounds.min.y); } @@ -1268,7 +1268,7 @@ var Vector = require('../geometry/Vector'); // render body selections bounds = item.bounds; context.beginPath(); - context.rect(Math.floor(bounds.min.x - 3), Math.floor(bounds.min.y - 3), + context.rect(Math.floor(bounds.min.x - 3), Math.floor(bounds.min.y - 3), Math.floor(bounds.max.x - bounds.min.x + 6), Math.floor(bounds.max.y - bounds.min.y + 6)); context.closePath(); context.stroke(); @@ -1302,7 +1302,7 @@ var Vector = require('../geometry/Vector'); context.fillStyle = 'rgba(255,165,0,0.1)'; bounds = inspector.selectBounds; context.beginPath(); - context.rect(Math.floor(bounds.min.x), Math.floor(bounds.min.y), + context.rect(Math.floor(bounds.min.x), Math.floor(bounds.min.y), Math.floor(bounds.max.x - bounds.min.x), Math.floor(bounds.max.y - bounds.min.y)); context.closePath(); context.stroke(); @@ -1339,7 +1339,7 @@ var Vector = require('../geometry/Vector'); * @return {Number} pixel ratio */ var _getPixelRatio = function(canvas) { - var context = canvas.getContext('2d'), + var context = canvas.getContext('2d', { willReadFrequently: true }), devicePixelRatio = window.devicePixelRatio || 1, backingStorePixelRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio @@ -1480,7 +1480,7 @@ var Vector = require('../geometry/Vector'); */ /** - * A `Bounds` object that specifies the drawing view region. + * A `Bounds` object that specifies the drawing view region. * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`). * This allows for creating views that can pan or zoom around the scene. * You must also set `render.options.hasBounds` to `true` to enable bounded rendering. diff --git a/src/renderer/snapshot/CanvasSnapshot.js b/src/renderer/snapshot/CanvasSnapshot.js index 16d23f988..b545b3920 100644 --- a/src/renderer/snapshot/CanvasSnapshot.js +++ b/src/renderer/snapshot/CanvasSnapshot.js @@ -33,7 +33,7 @@ var CanvasSnapshot = function (canvas, config) if (getPixel) { - var context = canvas.getContext('2d'); + var context = canvas.getContext('2d', { willReadFrequently: false }); var imageData = context.getImageData(x, y, 1, 1); var data = imageData.data; @@ -43,7 +43,7 @@ var CanvasSnapshot = function (canvas, config) { // Area Grab var copyCanvas = CanvasPool.createWebGL(this, width, height); - var ctx = copyCanvas.getContext('2d'); + var ctx = copyCanvas.getContext('2d', { willReadFrequently: true }); if (width > 0 && height > 0) { diff --git a/src/textures/DynamicTexture.js b/src/textures/DynamicTexture.js index 09f3a513a..d138e6887 100644 --- a/src/textures/DynamicTexture.js +++ b/src/textures/DynamicTexture.js @@ -127,7 +127,7 @@ var DynamicTexture = new Class({ * @type {CanvasRenderingContext2D} * @since 3.7.0 */ - this.context = (isCanvas) ? source.getContext('2d') : null; + this.context = (isCanvas) ? source.getContext('2d', { willReadFrequently: true }) : null; /** * Is this Dynamic Texture dirty or not? If not it won't spend time clearing or filling itself. diff --git a/src/textures/TextureManager.js b/src/textures/TextureManager.js index 018973d7c..f5847d31c 100644 --- a/src/textures/TextureManager.js +++ b/src/textures/TextureManager.js @@ -397,7 +397,7 @@ var TextureManager = new Class({ var cd = textureFrame.canvasData; var canvas = CanvasPool.create2D(this, cd.width, cd.height); - var ctx = canvas.getContext('2d'); + var ctx = canvas.getContext('2d', { willReadFrequently: true }); if (cd.width > 0 && cd.height > 0) {