diff --git a/kasmweb/core/decoders/hextile.js b/kasmweb/core/decoders/hextile.js index 8dbe809..f12e7f6 100644 --- a/kasmweb/core/decoders/hextile.js +++ b/kasmweb/core/decoders/hextile.js @@ -13,6 +13,7 @@ export default class HextileDecoder { constructor() { this._tiles = 0; this._lastsubencoding = 0; + this._tileBuffer = new Uint8Array(16 * 16 * 4); } decodeRect(x, y, width, height, sock, display, depth) { @@ -99,7 +100,7 @@ export default class HextileDecoder { rQi += 4; } - display.startTile(tx, ty, tw, th, this._background); + this._startTile(tx, ty, tw, th, this._background); if (subencoding & 0x08) { // AnySubrects let subrects = rQ[rQi]; rQi++; @@ -122,10 +123,10 @@ export default class HextileDecoder { const sw = (wh >> 4) + 1; const sh = (wh & 0x0f) + 1; - display.subTile(sx, sy, sw, sh, color); + this._subTile(sx, sy, sw, sh, color); } } - display.finishTile(); + this._finishTile(display); } sock.rQi = rQi; this._lastsubencoding = subencoding; @@ -134,4 +135,52 @@ export default class HextileDecoder { return true; } + + // start updating a tile + _startTile(x, y, width, height, color) { + this._tileX = x; + this._tileY = y; + this._tileW = width; + this._tileH = height; + + const red = color[2]; + const green = color[1]; + const blue = color[0]; + + const data = this._tileBuffer; + for (let i = 0; i < width * height * 4; i += 4) { + data[i] = blue; + data[i + 1] = green; + data[i + 2] = red; + data[i + 3] = 255; + } + } + + // update sub-rectangle of the current tile + _subTile(x, y, w, h, color) { + const red = color[2]; + const green = color[1]; + const blue = color[0]; + const xend = x + w; + const yend = y + h; + + const data = this._tileBuffer; + const width = this._tileW; + for (let j = y; j < yend; j++) { + for (let i = x; i < xend; i++) { + const p = (i + (j * width)) * 4; + data[p] = blue; + data[p + 1] = green; + data[p + 2] = red; + data[p + 3] = 255; + } + } + } + + // draw the current tile to the screen + _finishTile(display) { + display.blitImage(this._tileX, this._tileY, + this._tileW, this._tileH, + this._tileBuffer, 0); + } } diff --git a/kasmweb/core/display.js b/kasmweb/core/display.js index a7cd237..f153cd8 100644 --- a/kasmweb/core/display.js +++ b/kasmweb/core/display.js @@ -22,10 +22,6 @@ export default class Display { this._fbHeight = 0; this._prevDrawStyle = ""; - this._tile = null; - this._tile16x16 = null; - this._tileX = 0; - this._tileY = 0; Log.Debug(">> Display.constructor"); @@ -64,7 +60,6 @@ export default class Display { throw new Error("Canvas does not support createImageData"); } - this._tile16x16 = this._drawCtx.createImageData(16, 16); Log.Debug("<< Display.constructor"); // ===== PROPERTIES ===== @@ -377,57 +372,6 @@ export default class Display { }); } - // start updating a tile - startTile(x, y, width, height, color) { - this._tileX = x; - this._tileY = y; - if (width === 16 && height === 16) { - this._tile = this._tile16x16; - } else { - this._tile = this._drawCtx.createImageData(width, height); - } - - const red = color[2]; - const green = color[1]; - const blue = color[0]; - - const data = this._tile.data; - for (let i = 0; i < width * height * 4; i += 4) { - data[i] = red; - data[i + 1] = green; - data[i + 2] = blue; - data[i + 3] = 255; - } - } - - // update sub-rectangle of the current tile - subTile(x, y, w, h, color) { - const red = color[2]; - const green = color[1]; - const blue = color[0]; - const xend = x + w; - const yend = y + h; - - const data = this._tile.data; - const width = this._tile.width; - for (let j = y; j < yend; j++) { - for (let i = x; i < xend; i++) { - const p = (i + (j * width)) * 4; - data[p] = red; - data[p + 1] = green; - data[p + 2] = blue; - data[p + 3] = 255; - } - } - } - - // draw the current tile to the screen - finishTile() { - this._drawCtx.putImageData(this._tile, this._tileX, this._tileY); - this._damage(this._tileX, this._tileY, - this._tile.width, this._tile.height); - } - blitImage(x, y, width, height, arr, offset, fromQueue) { if (this._renderQ.length !== 0 && !fromQueue) { // NB(directxman12): it's technically more performant here to use preallocated arrays, diff --git a/kasmweb/docs/API-internal.md b/kasmweb/docs/API-internal.md index f7346a9..0e1b539 100644 --- a/kasmweb/docs/API-internal.md +++ b/kasmweb/docs/API-internal.md @@ -104,9 +104,6 @@ None | fillRect | (x, y, width, height, color, from_queue) | Draw a filled in rectangle | copyImage | (old_x, old_y, new_x, new_y, width, height, from_queue) | Copy a rectangular area | imageRect | (x, y, mime, arr) | Draw a rectangle with an image -| startTile | (x, y, width, height, color) | Begin updating a tile -| subTile | (tile, x, y, w, h, color) | Update a sub-rectangle within the given tile -| finishTile | () | Draw the current tile to the display | blitImage | (x, y, width, height, arr, offset, from_queue) | Blit pixels (of R,G,B,A) to the display | blitRgbImage | (x, y, width, height, arr, offset, from_queue) | Blit RGB encoded image to display | blitRgbxImage | (x, y, width, height, arr, offset, from_queue) | Blit RGBX encoded image to display diff --git a/kasmweb/tests/test.display.js b/kasmweb/tests/test.display.js index a853778..3492f1e 100644 --- a/kasmweb/tests/test.display.js +++ b/kasmweb/tests/test.display.js @@ -309,41 +309,6 @@ describe('Display/Canvas Helper', function () { display.flush(); }); - it('should support drawing tile data with a background color and sub tiles', function () { - display.startTile(0, 0, 4, 4, [0, 0xff, 0]); - display.subTile(0, 0, 2, 2, [0xff, 0, 0]); - display.subTile(2, 2, 2, 2, [0xff, 0, 0]); - display.finishTile(); - display.flip(); - expect(display).to.have.displayed(checkedData); - }); - - // We have a special cache for 16x16 tiles that we need to test - it('should support drawing a 16x16 tile', function () { - const largeCheckedData = new Uint8Array(16*16*4); - display.resize(16, 16); - - for (let y = 0;y < 16;y++) { - for (let x = 0;x < 16;x++) { - let pixel; - if ((x < 4) && (y < 4)) { - // NB: of course IE11 doesn't support #slice on ArrayBufferViews... - pixel = Array.prototype.slice.call(checkedData, (y*4+x)*4, (y*4+x+1)*4); - } else { - pixel = [0, 0xff, 0, 255]; - } - largeCheckedData.set(pixel, (y*16+x)*4); - } - } - - display.startTile(0, 0, 16, 16, [0, 0xff, 0]); - display.subTile(0, 0, 2, 2, [0xff, 0, 0]); - display.subTile(2, 2, 2, 2, [0xff, 0, 0]); - display.finishTile(); - display.flip(); - expect(display).to.have.displayed(largeCheckedData); - }); - it('should support drawing BGRX blit images with true color via #blitImage', function () { const data = []; for (let i = 0; i < 16; i++) {