Double buffering damage tracking
Optimise the copy from the hidden canvas to the visible one a bit by only copying the modified area.
This commit is contained in:
parent
2ba767a7fe
commit
84cd0e719e
|
@ -69,6 +69,10 @@
|
||||||
this._backbuffer = document.createElement('canvas');
|
this._backbuffer = document.createElement('canvas');
|
||||||
this._drawCtx = this._backbuffer.getContext('2d');
|
this._drawCtx = this._backbuffer.getContext('2d');
|
||||||
|
|
||||||
|
this._damageBounds = { left:0, top:0,
|
||||||
|
right: this._backbuffer.width,
|
||||||
|
bottom: this._backbuffer.height };
|
||||||
|
|
||||||
Util.Debug("User Agent: " + navigator.userAgent);
|
Util.Debug("User Agent: " + navigator.userAgent);
|
||||||
if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); }
|
if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); }
|
||||||
if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); }
|
if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); }
|
||||||
|
@ -149,6 +153,8 @@
|
||||||
vp.x += deltaX;
|
vp.x += deltaX;
|
||||||
vp.y += deltaY;
|
vp.y += deltaY;
|
||||||
|
|
||||||
|
this._damage(vp.x, vp.y, vp.w, vp.h);
|
||||||
|
|
||||||
this.flip();
|
this.flip();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -186,6 +192,7 @@
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
canvas.style.height = height + 'px';
|
canvas.style.height = height + 'px';
|
||||||
}
|
}
|
||||||
|
this._damage(vp.x, vp.y, vp.w, vp.h);
|
||||||
this.flip();
|
this.flip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,6 +238,22 @@
|
||||||
this.viewportChangeSize();
|
this.viewportChangeSize();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Track what parts of the visible canvas that need updating
|
||||||
|
_damage: function(x, y, w, h) {
|
||||||
|
if (x < this._damageBounds.left) {
|
||||||
|
this._damageBounds.left = x;
|
||||||
|
}
|
||||||
|
if (y < this._damageBounds.top) {
|
||||||
|
this._damageBounds.top = y;
|
||||||
|
}
|
||||||
|
if ((x + w) > this._damageBounds.right) {
|
||||||
|
this._damageBounds.right = x + w;
|
||||||
|
}
|
||||||
|
if ((y + h) > this._damageBounds.bottom) {
|
||||||
|
this._damageBounds.bottom = y + h;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Update the visible canvas with the contents of the
|
// Update the visible canvas with the contents of the
|
||||||
// rendering canvas
|
// rendering canvas
|
||||||
flip: function(from_queue) {
|
flip: function(from_queue) {
|
||||||
|
@ -239,17 +262,45 @@
|
||||||
'type': 'flip'
|
'type': 'flip'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// FIXME: We may need to disable image smoothing here
|
var x, y, vx, vy, w, h;
|
||||||
// as well (see copyImage()), but we haven't
|
|
||||||
// noticed any problem yet.
|
x = this._damageBounds.left;
|
||||||
this._targetCtx.drawImage(this._backbuffer,
|
y = this._damageBounds.top;
|
||||||
this._viewportLoc.x,
|
w = this._damageBounds.right - x;
|
||||||
this._viewportLoc.y,
|
h = this._damageBounds.bottom - y;
|
||||||
this._viewportLoc.w,
|
|
||||||
this._viewportLoc.h,
|
vx = x - this._viewportLoc.x;
|
||||||
0, 0,
|
vy = y - this._viewportLoc.y;
|
||||||
this._viewportLoc.w,
|
|
||||||
this._viewportLoc.h);
|
if (vx < 0) {
|
||||||
|
w += vx;
|
||||||
|
x -= vx;
|
||||||
|
vx = 0;
|
||||||
|
}
|
||||||
|
if (vy < 0) {
|
||||||
|
h += vy;
|
||||||
|
y -= vy;
|
||||||
|
vy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vx + w) > this._viewportLoc.w) {
|
||||||
|
w = this._viewportLoc.w - vx;
|
||||||
|
}
|
||||||
|
if ((vy + h) > this._viewportLoc.h) {
|
||||||
|
h = this._viewportLoc.h - vy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((w > 0) && (h > 0)) {
|
||||||
|
// FIXME: We may need to disable image smoothing here
|
||||||
|
// as well (see copyImage()), but we haven't
|
||||||
|
// noticed any problem yet.
|
||||||
|
this._targetCtx.drawImage(this._backbuffer,
|
||||||
|
x, y, w, h,
|
||||||
|
vx, vy, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._damageBounds.left = this._damageBounds.top = 65535;
|
||||||
|
this._damageBounds.right = this._damageBounds.bottom = 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -289,6 +340,7 @@
|
||||||
} else {
|
} else {
|
||||||
this._setFillColor(color);
|
this._setFillColor(color);
|
||||||
this._drawCtx.fillRect(x, y, width, height);
|
this._drawCtx.fillRect(x, y, width, height);
|
||||||
|
this._damage(x, y, width, height);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -319,6 +371,7 @@
|
||||||
this._drawCtx.drawImage(this._backbuffer,
|
this._drawCtx.drawImage(this._backbuffer,
|
||||||
old_x, old_y, w, h,
|
old_x, old_y, w, h,
|
||||||
new_x, new_y, w, h);
|
new_x, new_y, w, h);
|
||||||
|
this._damage(new_x, new_y, w, h);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -401,6 +454,8 @@
|
||||||
finishTile: function () {
|
finishTile: function () {
|
||||||
if (this._prefer_js) {
|
if (this._prefer_js) {
|
||||||
this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
|
this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
|
||||||
|
this._damage(this._tile_x, this._tile_y,
|
||||||
|
this._tile.width, this._tile.height);
|
||||||
}
|
}
|
||||||
// else: No-op -- already done by setSubTile
|
// else: No-op -- already done by setSubTile
|
||||||
},
|
},
|
||||||
|
@ -472,6 +527,7 @@
|
||||||
|
|
||||||
drawImage: function (img, x, y) {
|
drawImage: function (img, x, y) {
|
||||||
this._drawCtx.drawImage(img, x, y);
|
this._drawCtx.drawImage(img, x, y);
|
||||||
|
this._damage(x, y, img.width, img.height);
|
||||||
},
|
},
|
||||||
|
|
||||||
changeCursor: function (pixels, mask, hotx, hoty, w, h) {
|
changeCursor: function (pixels, mask, hotx, hoty, w, h) {
|
||||||
|
@ -613,6 +669,7 @@
|
||||||
data[i + 3] = 255; // Alpha
|
data[i + 3] = 255; // Alpha
|
||||||
}
|
}
|
||||||
this._drawCtx.putImageData(img, x, y);
|
this._drawCtx.putImageData(img, x, y);
|
||||||
|
this._damage(x, y, img.width, img.height);
|
||||||
},
|
},
|
||||||
|
|
||||||
_bgrxImageData: function (x, y, width, height, arr, offset) {
|
_bgrxImageData: function (x, y, width, height, arr, offset) {
|
||||||
|
@ -625,6 +682,7 @@
|
||||||
data[i + 3] = 255; // Alpha
|
data[i + 3] = 255; // Alpha
|
||||||
}
|
}
|
||||||
this._drawCtx.putImageData(img, x, y);
|
this._drawCtx.putImageData(img, x, y);
|
||||||
|
this._damage(x, y, img.width, img.height);
|
||||||
},
|
},
|
||||||
|
|
||||||
_rgbxImageData: function (x, y, width, height, arr, offset) {
|
_rgbxImageData: function (x, y, width, height, arr, offset) {
|
||||||
|
@ -637,6 +695,7 @@
|
||||||
img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4));
|
img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4));
|
||||||
}
|
}
|
||||||
this._drawCtx.putImageData(img, x, y);
|
this._drawCtx.putImageData(img, x, y);
|
||||||
|
this._damage(x, y, img.width, img.height);
|
||||||
},
|
},
|
||||||
|
|
||||||
_cmapImageData: function (x, y, width, height, arr, offset) {
|
_cmapImageData: function (x, y, width, height, arr, offset) {
|
||||||
|
@ -651,6 +710,7 @@
|
||||||
data[i + 3] = 255; // Alpha
|
data[i + 3] = 255; // Alpha
|
||||||
}
|
}
|
||||||
this._drawCtx.putImageData(img, x, y);
|
this._drawCtx.putImageData(img, x, y);
|
||||||
|
this._damage(x, y, img.width, img.height);
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderQ_push: function (action) {
|
_renderQ_push: function (action) {
|
||||||
|
|
Loading…
Reference in New Issue