diff --git a/app/ui.js b/app/ui.js index 766736ae..9c5e922f 100644 --- a/app/ui.js +++ b/app/ui.js @@ -163,6 +163,7 @@ const UI = { UI.initSetting('resize', 'off'); UI.initSetting('shared', true); UI.initSetting('view_only', false); + UI.initSetting('img_bgrx_mode', false); UI.initSetting('show_dot', false); UI.initSetting('path', 'websockify'); UI.initSetting('repeaterID', ''); @@ -352,6 +353,8 @@ const UI = { UI.addSettingChangeHandler('shared'); UI.addSettingChangeHandler('view_only'); UI.addSettingChangeHandler('view_only', UI.updateViewOnly); + UI.addSettingChangeHandler('img_bgrx_mode'); + UI.addSettingChangeHandler('img_bgrx_mode', UI.applyBGRXMode); UI.addSettingChangeHandler('show_dot'); UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor); UI.addSettingChangeHandler('host'); @@ -1028,6 +1031,7 @@ const UI = { UI.rfb.addEventListener("bell", UI.bell); UI.rfb.addEventListener("desktopname", UI.updateDesktopName); UI.rfb.clipViewport = UI.getSetting('view_clip'); + UI.rfb.bgrxImgMode = UI.getSetting('img_bgrx_mode'); UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale'; UI.rfb.resizeSession = UI.getSetting('resize') === 'remote'; UI.rfb.showDotCursor = UI.getSetting('show_dot'); @@ -1251,6 +1255,19 @@ const UI = { UI.rfb.resizeSession = UI.getSetting('resize') === 'remote'; }, +/* ------^------- + * /img_bgrx_mode + * ============== + * BGRX mode + * ------v------*/ + + // Apply bgrx transform to images + applyBGRXMode() { + if (!UI.rfb) return; + + UI.rfb.bgrxImgMode = UI.getSetting('img_bgrx_mode'); + }, + /* ------^------- * /RESIZE * ============== diff --git a/core/display.js b/core/display.js index 3dd5fcea..2c3cfc0a 100644 --- a/core/display.js +++ b/core/display.js @@ -72,6 +72,7 @@ export default class Display { this._scale = 1.0; this._clipViewport = false; + this._bgrxImgMode = false; // ===== EVENT HANDLERS ===== @@ -102,6 +103,10 @@ export default class Display { return this._fb_height; } + set bgrxImgMode(val) { + this._bgrxImgMode = val; + } + // ===== PUBLIC METHODS ===== viewportChangePos(deltaX, deltaY) { @@ -489,6 +494,26 @@ export default class Display { } } + blitBgrxImage(x, y, width, height, arr, offset, from_queue) { + if (this._renderQ.length !== 0 && !from_queue) { + // NB(directxman12): it's technically more performant here to use preallocated arrays, + // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue, + // this probably isn't getting called *nearly* as much + const new_arr = new Uint8Array(width * height * 4); + new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length)); + this._renderQ_push({ + 'type': 'blitBgrx', + 'data': new_arr, + 'x': x, + 'y': y, + 'width': width, + 'height': height, + }); + } else { + this._bgrxImageData(x, y, width, height, arr, offset); + } + } + drawImage(img, x, y) { this._drawCtx.drawImage(img, x, y); this._damage(x, y, img.width, img.height); @@ -599,6 +624,15 @@ export default class Display { this._noVNC_display._scan_renderQ(); } + _get_image_data(image) { + let tmpC = document.createElement('canvas'); + let ctx = tmpC.getContext('2d'); + tmpC.width = image.width; + tmpC.height = image.height; + ctx.drawImage(image.img, 0, 0, image.width, image.height); + return ctx.getImageData(0, 0, image.width, image.height).data; + } + _scan_renderQ() { let ready = true; while (ready && this._renderQ.length > 0) { @@ -631,7 +665,11 @@ export default class Display { a.width + "x" + a.height + "."); return; } - this.drawImage(a.img, a.x, a.y); + if (this._bgrxImgMode) { + this.blitBgrxImage(a.x, a.y, a.width, a.height, this._get_image_data(a), 0, true) + } else { + this.drawImage(a.img, a.x, a.y); + } } else { a.img._noVNC_display = this; a.img.addEventListener('load', this._resume_renderQ); diff --git a/core/rfb.js b/core/rfb.js index e3e3a0f7..49a16bb6 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -282,6 +282,9 @@ export default class RFB extends EventTargetMixin { this._updateClip(); } + get bgrxImgMode() { return this._display.bgrxImgMode; } + set bgrxImgMode(val) { this._display.bgrxImgMode = val; } + get scaleViewport() { return this._scaleViewport; } set scaleViewport(scale) { this._scaleViewport = scale; diff --git a/vnc.html b/vnc.html index ef7150c8..d1e6c683 100644 --- a/vnc.html +++ b/vnc.html @@ -195,6 +195,9 @@