Skip to content

Commit 707332e

Browse files
committed
update Skin textures with ImageData
When possible pass ImageData to texture creation and updating to help remove chance of references that keep canvas and underlying data from being garbage collected.
1 parent 891c527 commit 707332e

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/BitmapSkin.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,34 @@ class BitmapSkin extends Skin {
7070
setBitmap (bitmapData, costumeResolution, rotationCenter) {
7171
const gl = this._renderer.gl;
7272

73+
// Preferably bitmapData is ImageData. ImageData speeds up updating
74+
// Silhouette and is better handled by more browsers in regards to
75+
// memory.
76+
let textureData = bitmapData;
77+
if (bitmapData instanceof HTMLCanvasElement) {
78+
// Given a HTMLCanvasElement get the image data to pass to webgl and
79+
// Silhouette.
80+
const context = bitmapData.getContext('2d');
81+
textureData = context.getImageData(0, 0, bitmapData.width, bitmapData.height);
82+
}
83+
7384
if (this._texture) {
7485
gl.bindTexture(gl.TEXTURE_2D, this._texture);
75-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmapData);
76-
this._silhouette.update(bitmapData);
86+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
87+
this._silhouette.update(textureData);
7788
} else {
7889
// TODO: mipmaps?
7990
const textureOptions = {
8091
auto: true,
8192
wrap: gl.CLAMP_TO_EDGE,
82-
src: bitmapData
93+
src: textureData
8394
};
8495

8596
this._texture = twgl.createTexture(gl, textureOptions);
86-
this._silhouette.update(bitmapData);
97+
this._silhouette.update(textureData);
98+
99+
// Unset src to make garbage collecting textureData easier.
100+
textureOptions.src = null;
87101
}
88102

89103
// Do these last in case any of the above throws an exception

src/SVGSkin.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,14 @@ class SVGSkin extends Skin {
7777
this._textureScale = newScale;
7878
this._svgRenderer._draw(this._textureScale, () => {
7979
if (this._textureScale === newScale) {
80+
const canvas = this._svgRenderer.canvas;
81+
const context = canvas.getContext('2d');
82+
const textureData = context.getImageData(0, 0, canvas.width, canvas.height);
83+
8084
const gl = this._renderer.gl;
8185
gl.bindTexture(gl.TEXTURE_2D, this._texture);
82-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas);
83-
this._silhouette.update(this._svgRenderer.canvas);
86+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
87+
this._silhouette.update(textureData);
8488
}
8589
});
8690
}
@@ -99,20 +103,31 @@ class SVGSkin extends Skin {
99103
this._svgRenderer.fromString(svgData, 1, () => {
100104
const gl = this._renderer.gl;
101105
this._textureScale = this._maxTextureScale = 1;
106+
107+
// Pull out the ImageData from the canvas. ImageData speeds up
108+
// updating Silhouette and is better handled by more browsers in
109+
// regards to memory.
110+
const canvas = this._svgRenderer.canvas;
111+
const context = canvas.getContext('2d');
112+
const textureData = context.getImageData(0, 0, canvas.width, canvas.height);
113+
102114
if (this._texture) {
103115
gl.bindTexture(gl.TEXTURE_2D, this._texture);
104-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas);
105-
this._silhouette.update(this._svgRenderer.canvas);
116+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData);
117+
this._silhouette.update(textureData);
106118
} else {
107119
// TODO: mipmaps?
108120
const textureOptions = {
109121
auto: true,
110122
wrap: gl.CLAMP_TO_EDGE,
111-
src: this._svgRenderer.canvas
123+
src: textureData
112124
};
113125

114126
this._texture = twgl.createTexture(gl, textureOptions);
115-
this._silhouette.update(this._svgRenderer.canvas);
127+
this._silhouette.update(textureData);
128+
129+
// Unset src to make garbage collecting textureData easier.
130+
textureData.src = null;
116131
}
117132

118133
const maxDimension = Math.max(this._svgRenderer.canvas.width, this._svgRenderer.canvas.height);

0 commit comments

Comments
 (0)