From a5a03c40f21ab4c473313453e09f9c353ff184c5 Mon Sep 17 00:00:00 2001 From: Benjamin Woodruff Date: Tue, 24 Apr 2018 23:15:22 -0700 Subject: [PATCH 1/4] Batch background draws together to reduce draws Adjacent cells on the same row sharing the same background color will be drawn using the same `fillCells` call. This should make drawing an application with a solid or mostly solid background color (e.g. vim) faster. I set vim to draw the background color for a file, and started scrolling through it. Before, _drawBackground was taking around 6ms per frame. After this commit, it was taking around 0.5ms per frame. Based on prior experience, I'd expect these results to be more drastic for larger terminal windows. The demo's window is pretty small. --- src/renderer/BaseRenderLayer.ts | 2 +- src/renderer/TextRenderLayer.ts | 52 +++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index fbffd547..4200e112 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -26,7 +26,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { private _container: HTMLElement, id: string, zIndex: number, - private _alpha: boolean, + protected _alpha: boolean, protected _colors: IColorSet ) { this._canvas = document.createElement('canvas'); diff --git a/src/renderer/TextRenderLayer.ts b/src/renderer/TextRenderLayer.ts index 58d0d790..6c9a72c5 100644 --- a/src/renderer/TextRenderLayer.ts +++ b/src/renderer/TextRenderLayer.ts @@ -128,18 +128,58 @@ export class TextRenderLayer extends BaseRenderLayer { } } + /** + * Draws the background for a specified range of columns. Tries to batch adjacent cells of the + * same color together to reduce draw calls. + */ private _drawBackground(terminal: ITerminal, firstRow: number, lastRow: number): void { + const ctx = this._ctx; + const cols = terminal.cols; + let startX: number = 0; + let startY: number = 0; + let prevFillStyle: string | null = null; + + ctx.save(); + this._forEachCell(terminal, firstRow, lastRow, (code, char, width, x, y, fg, bg, flags) => { // libvte and xterm both draw the background (but not foreground) of invisible characters, // so we should too. - const isDefaultBackground = bg >= 256; - if (!isDefaultBackground) { - this._ctx.save(); - this._ctx.fillStyle = (bg === INVERTED_DEFAULT_COLOR ? this._colors.foreground.css : this._colors.ansi[bg].css); - this.fillCells(x, y, width, 1); - this._ctx.restore(); + let nextFillStyle = null; // null represents default background color + if (bg === INVERTED_DEFAULT_COLOR) { + nextFillStyle = this._colors.foreground.css; + } else if (bg < 256) { + nextFillStyle = this._colors.ansi[bg].css; } + + if (prevFillStyle === null) { + // This is either the first iteration, or the default background was set. Either way, we + // don't need to draw anything. + startX = x; + startY = y; + } if (y !== startY) { + // our row changed, draw the previous row + ctx.fillStyle = prevFillStyle; + this.fillCells(startX, startY, cols - startX, 1); + startX = x; + startY = y; + } else if (prevFillStyle !== nextFillStyle) { + // our color changed, draw the previous characters in this row + ctx.fillStyle = prevFillStyle; + this.fillCells(startX, startY, x - startX, 1); + startX = x; + startY = y; + } + + prevFillStyle = nextFillStyle; }); + + // flush the last color we encountered + if (prevFillStyle !== null) { + ctx.fillStyle = prevFillStyle; + this.fillCells(startX, startY, cols - startX, 1); + } + + ctx.restore(); } private _drawForeground(terminal: ITerminal, firstRow: number, lastRow: number): void { From 994895af6de250d89d05365d7ef7213269c6f7c1 Mon Sep 17 00:00:00 2001 From: pro-src <34285059+pro-src@users.noreply.github.com> Date: Thu, 26 Apr 2018 11:53:20 -0500 Subject: [PATCH 2/4] Update README.md Replace the deprecated octal escapes with Unicode escapes. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Deprecated_octal --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 48a46fd9..50e954da 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t From 882d5a86d390f220545c42b302a2a2bb8318da2c Mon Sep 17 00:00:00 2001 From: pro-src <34285059+pro-src@users.noreply.github.com> Date: Fri, 27 Apr 2018 02:19:48 -0500 Subject: [PATCH 3/4] Update README.md - prefer hex escapes over octal --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50e954da..07baec5a 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to t From 513847fd806b55719fb08a522d11f2ff5aab2216 Mon Sep 17 00:00:00 2001 From: Benjamin Woodruff Date: Fri, 27 Apr 2018 20:47:55 -0700 Subject: [PATCH 4/4] Make BaseRenderLayer's _alpha private again This was accidentally left over from some earlier changes I was playing with. --- src/renderer/BaseRenderLayer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/BaseRenderLayer.ts b/src/renderer/BaseRenderLayer.ts index 4200e112..fbffd547 100644 --- a/src/renderer/BaseRenderLayer.ts +++ b/src/renderer/BaseRenderLayer.ts @@ -26,7 +26,7 @@ export abstract class BaseRenderLayer implements IRenderLayer { private _container: HTMLElement, id: string, zIndex: number, - protected _alpha: boolean, + private _alpha: boolean, protected _colors: IColorSet ) { this._canvas = document.createElement('canvas');