mirror of
https://github.com/boxgaming/qbjs.git
synced 2024-09-20 04:24:45 +00:00
implemented screen cache to improve performance of PSet-intensive programs
This commit is contained in:
parent
fce1e16005
commit
2bf17466d9
1 changed files with 52 additions and 40 deletions
92
qb.js
92
qb.js
|
@ -137,6 +137,7 @@ var QB = new function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.end = function() {
|
this.end = function() {
|
||||||
|
_flushAllScreenCache();
|
||||||
_runningFlag = false;
|
_runningFlag = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -407,6 +408,7 @@ var QB = new function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sub__Limit = async function(fps) {
|
this.sub__Limit = async function(fps) {
|
||||||
|
_flushAllScreenCache();
|
||||||
await GX.sleep((1000 - (new Date() - _lastLimitTime))/fps);
|
await GX.sleep((1000 - (new Date() - _lastLimitTime))/fps);
|
||||||
_lastLimitTime = new Date();
|
_lastLimitTime = new Date();
|
||||||
};
|
};
|
||||||
|
@ -414,6 +416,7 @@ var QB = new function() {
|
||||||
this.autoLimit = async function() {
|
this.autoLimit = async function() {
|
||||||
var timeElapsed = new Date() - _lastLimitTime;
|
var timeElapsed = new Date() - _lastLimitTime;
|
||||||
if (timeElapsed > 1000) {
|
if (timeElapsed > 1000) {
|
||||||
|
_flushAllScreenCache();
|
||||||
await GX.sleep(1);
|
await GX.sleep(1);
|
||||||
_lastLimitTime = new Date();
|
_lastLimitTime = new Date();
|
||||||
}
|
}
|
||||||
|
@ -524,7 +527,7 @@ var QB = new function() {
|
||||||
// TODO: check the background opacity mode
|
// TODO: check the background opacity mode
|
||||||
// Draw the text background
|
// Draw the text background
|
||||||
var ctx = _images[_activeImage].ctx;
|
var ctx = _images[_activeImage].ctx;
|
||||||
_images[_activeImage].dirty = true;
|
_flushScreenCache(_images[_activeImage]);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.fillStyle = _bgColor.rgba();
|
ctx.fillStyle = _bgColor.rgba();
|
||||||
ctx.fillRect(x, y, QB.func__FontWidth(), QB.func__FontHeight());
|
ctx.fillRect(x, y, QB.func__FontWidth(), QB.func__FontHeight());
|
||||||
|
@ -625,8 +628,8 @@ var QB = new function() {
|
||||||
sourceImage.lastX = sx1 + sw;
|
sourceImage.lastX = sx1 + sw;
|
||||||
sourceImage.lastY = sy2 + sh;
|
sourceImage.lastY = sy2 + sh;
|
||||||
|
|
||||||
|
_flushScreenCache(_images[destImageId]);
|
||||||
destImage.ctx.drawImage(sourceImage.canvas, sx1, sy1, sw, sh, dx1, dy1, dw, dh);
|
destImage.ctx.drawImage(sourceImage.canvas, sx1, sy1, sw, sh, dx1, dy1, dw, dh);
|
||||||
_images[sourceImageId].dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _rgb(r, g, b, a) {
|
function _rgb(r, g, b, a) {
|
||||||
|
@ -899,7 +902,7 @@ var QB = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = _images[_activeImage].ctx;
|
ctx = _images[_activeImage].ctx;
|
||||||
_images[_activeImage].dirty = true;
|
_flushScreenCache(_images[_activeImage]);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.clearRect(0, 0, _width(), _height());
|
ctx.clearRect(0, 0, _width(), _height());
|
||||||
//if (_screenMode == 1) { TODO: Finish implementing this.
|
//if (_screenMode == 1) { TODO: Finish implementing this.
|
||||||
|
@ -933,23 +936,12 @@ var QB = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sub_Color = function(x, y) {
|
this.sub_Color = function(x, y) {
|
||||||
/*if (_screenMode == 1) { This code is fine.
|
|
||||||
if (x == 0) { _bgColor = _rgb(0, 0, 0);
|
|
||||||
} else if (x == 1) { _bgColor = _rgb(0, 0, 168);
|
|
||||||
} else if (x == 2) { _bgColor = _rgb(0, 168, 0);
|
|
||||||
} else if (x == 3) { _bgColor = _rgb(0, 168, 168); }
|
|
||||||
ctx = _images[_activeImage].ctx;
|
|
||||||
ctx.fillStyle = _bgColor.rgba();
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(0, 0, _width(), _height());
|
|
||||||
} else {*/
|
|
||||||
if (x != undefined) {
|
if (x != undefined) {
|
||||||
_fgColor = _color(x);
|
_fgColor = _color(x);
|
||||||
}
|
}
|
||||||
if (y != undefined) {
|
if (y != undefined) {
|
||||||
_bgColor = _color(y);
|
_bgColor = _color(y);
|
||||||
}
|
}
|
||||||
//}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.func_Command = function() {
|
this.func_Command = function() {
|
||||||
|
@ -1059,7 +1051,7 @@ var QB = new function() {
|
||||||
["H",Math.PI*(7/4),Math.sqrt(2)]];
|
["H",Math.PI*(7/4),Math.sqrt(2)]];
|
||||||
|
|
||||||
// Screen variables.
|
// Screen variables.
|
||||||
_images[_activeImage].dirty = true;
|
_flushScreenCache(_images[_activeImage]);
|
||||||
var screen = _images[_activeImage];
|
var screen = _images[_activeImage];
|
||||||
var ctx = screen.ctx;
|
var ctx = screen.ctx;
|
||||||
|
|
||||||
|
@ -1342,6 +1334,8 @@ var QB = new function() {
|
||||||
var str = "";
|
var str = "";
|
||||||
_inputMode = true;
|
_inputMode = true;
|
||||||
|
|
||||||
|
_flushScreenCache(_images[_activeImage]);
|
||||||
|
|
||||||
if (prompt != undefined) {
|
if (prompt != undefined) {
|
||||||
await QB.sub_Print([prompt, QB.PREVENT_NEWLINE]);
|
await QB.sub_Print([prompt, QB.PREVENT_NEWLINE]);
|
||||||
}
|
}
|
||||||
|
@ -1391,7 +1385,6 @@ var QB = new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_inputMode = false;
|
_inputMode = false;
|
||||||
_images[_activeImage].dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sub_InputFromFile = async function(fh, returnValues) {
|
this.sub_InputFromFile = async function(fh, returnValues) {
|
||||||
|
@ -1492,7 +1485,7 @@ var QB = new function() {
|
||||||
|
|
||||||
var screen = _images[_activeImage];
|
var screen = _images[_activeImage];
|
||||||
var ctx = screen.ctx;
|
var ctx = screen.ctx;
|
||||||
_images[_activeImage].dirty = true;
|
_flushScreenCache(screen);
|
||||||
|
|
||||||
if (color == undefined) {
|
if (color == undefined) {
|
||||||
color = _fgColor;
|
color = _fgColor;
|
||||||
|
@ -1557,17 +1550,10 @@ var QB = new function() {
|
||||||
|
|
||||||
this.sub_Line = function(sstep, sx, sy, estep, ex, ey, color, style, pattern) {
|
this.sub_Line = function(sstep, sx, sy, estep, ex, ey, color, style, pattern) {
|
||||||
var screen = _images[_activeImage];
|
var screen = _images[_activeImage];
|
||||||
//var ctx = screen.ctx;
|
_flushScreenCache(_images[_activeImage]);
|
||||||
_images[_activeImage].dirty = true;
|
|
||||||
|
|
||||||
if (color == undefined) {
|
if (color == undefined) {
|
||||||
color = _fgColor;
|
color = _fgColor;
|
||||||
/*if (style == "BF") {
|
|
||||||
color = _bgColor;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
color = _fgColor;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
color = _color(color);
|
color = _color(color);
|
||||||
|
@ -1811,7 +1797,8 @@ var QB = new function() {
|
||||||
|
|
||||||
this.sub_Paint = function(sstep, startX, startY, fillColor, borderColor) {
|
this.sub_Paint = function(sstep, startX, startY, fillColor, borderColor) {
|
||||||
// See: http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
|
// See: http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
|
||||||
_images[_activeImage].dirty = true;
|
// TODO: this method should probably utilize the same screen cache as PSet
|
||||||
|
_flushScreenCache(_images[_activeImage]);
|
||||||
var screen = _images[_activeImage];
|
var screen = _images[_activeImage];
|
||||||
var ctx = screen.ctx;
|
var ctx = screen.ctx;
|
||||||
var data = ctx.getImageData(0, 0, screen.canvas.width, screen.canvas.height).data;
|
var data = ctx.getImageData(0, 0, screen.canvas.width, screen.canvas.height).data;
|
||||||
|
@ -1915,18 +1902,16 @@ var QB = new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (screen.dirty != false) {
|
if (!screen.cached) {
|
||||||
var ctx = screen.ctx;
|
var ctx = screen.ctx;
|
||||||
screen.data = ctx.getImageData(0, 0, screen.canvas.width, screen.canvas.height).data;
|
screen.imgdata = ctx.getImageData(0, 0, screen.canvas.width, screen.canvas.height);
|
||||||
screen.dirty = false;
|
screen.cached = true;
|
||||||
}
|
}
|
||||||
//var data = ctx.getImageData(x, y, 1, 1).data;
|
|
||||||
//ret = QB.func__RGBA(data[0],data[1],data[2],data[3]);
|
|
||||||
var pixelIndex = (y * screen.canvas.width + x) * 4;
|
var pixelIndex = (y * screen.canvas.width + x) * 4;
|
||||||
ret = _rgb(screen.data[pixelIndex],
|
ret = _rgb(screen.imgdata.data[pixelIndex],
|
||||||
screen.data[pixelIndex + 1],
|
screen.imgdata.data[pixelIndex + 1],
|
||||||
screen.data[pixelIndex + 2],
|
screen.imgdata.data[pixelIndex + 2],
|
||||||
screen.data[pixelIndex + 3]);
|
screen.imgdata.data[pixelIndex + 3]);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -2018,7 +2003,8 @@ var QB = new function() {
|
||||||
args = [""];
|
args = [""];
|
||||||
}
|
}
|
||||||
|
|
||||||
_images[_activeImage].dirty = true;
|
_flushScreenCache(_images[_activeImage]);
|
||||||
|
|
||||||
var ctx = _images[_activeImage].ctx;
|
var ctx = _images[_activeImage].ctx;
|
||||||
var preventNewline = (args[args.length-1] == QB.PREVENT_NEWLINE || args[args.length-1] == QB.COLUMN_ADVANCE);
|
var preventNewline = (args[args.length-1] == QB.PREVENT_NEWLINE || args[args.length-1] == QB.COLUMN_ADVANCE);
|
||||||
|
|
||||||
|
@ -2095,9 +2081,11 @@ var QB = new function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sub_PSet = function(sstep, x, y, color) {
|
this.sub_PSet = function(sstep, x, y, color) {
|
||||||
_images[_activeImage].dirty = true;
|
|
||||||
var screen = _images[_activeImage];
|
var screen = _images[_activeImage];
|
||||||
|
|
||||||
|
x = Math.round(x);
|
||||||
|
y = Math.round(y);
|
||||||
|
|
||||||
if (color == undefined) {
|
if (color == undefined) {
|
||||||
color = _fgColor;
|
color = _fgColor;
|
||||||
}
|
}
|
||||||
|
@ -2122,14 +2110,38 @@ var QB = new function() {
|
||||||
screen.lastX = x;
|
screen.lastX = x;
|
||||||
screen.lastY = y;
|
screen.lastY = y;
|
||||||
|
|
||||||
|
if (!screen.cached) {
|
||||||
var ctx = screen.ctx;
|
var ctx = screen.ctx;
|
||||||
ctx.fillStyle = color.rgba();
|
screen.imgdata = ctx.getImageData(0, 0, screen.canvas.width, screen.canvas.height);
|
||||||
ctx.beginPath();
|
screen.cached = true;
|
||||||
ctx.fillRect(x, y, 1, 1);
|
}
|
||||||
|
var pixelIndex = (y * screen.canvas.width + x) * 4;
|
||||||
|
screen.imgdata.data[pixelIndex] = color.r;
|
||||||
|
screen.imgdata.data[pixelIndex + 1] = color.g;
|
||||||
|
screen.imgdata.data[pixelIndex + 2] = color.b;
|
||||||
|
screen.imgdata.data[pixelIndex + 3] = color.a * 255;
|
||||||
|
|
||||||
_strokeDrawColor = _color(color);
|
_strokeDrawColor = _color(color);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function _flushScreenCache(screen) {
|
||||||
|
if (screen.cached) {
|
||||||
|
var ctx = screen.ctx;
|
||||||
|
ctx.putImageData(screen.imgdata, 0, 0);
|
||||||
|
screen.imgdata = undefined;
|
||||||
|
screen.cached = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _flushAllScreenCache() {
|
||||||
|
// TODO: this is brute force - fix it
|
||||||
|
for (var i=0; i < _nextImageId; i++) {
|
||||||
|
if (_images[i]) {
|
||||||
|
_flushScreenCache(_images[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.sub_Get = function(fhi, position, type, valueObj) {
|
this.sub_Get = function(fhi, position, type, valueObj) {
|
||||||
if (!_fileHandles[fhi]) {
|
if (!_fileHandles[fhi]) {
|
||||||
throw new Error("Invalid file handle");
|
throw new Error("Invalid file handle");
|
||||||
|
|
Loading…
Reference in a new issue