1
1
Fork 0
mirror of https://github.com/boxgaming/qbjs.git synced 2024-09-19 20:14:58 +00:00

implemented screen cache to improve performance of PSet-intensive programs

This commit is contained in:
boxgaming 2022-11-21 09:42:27 -06:00
parent fce1e16005
commit 2bf17466d9

92
qb.js
View file

@ -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,8 +2081,10 @@ 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");