From bcd4c766d61bbaf4d275d7faa1994d72923acdf5 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 09:09:59 -0800 Subject: [PATCH 1/6] Implement webgl renderer dispose Fixes #2254 --- addons/xterm-addon-webgl/src/WebglAddon.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglAddon.ts b/addons/xterm-addon-webgl/src/WebglAddon.ts index 0074f9b2..be867d75 100644 --- a/addons/xterm-addon-webgl/src/WebglAddon.ts +++ b/addons/xterm-addon-webgl/src/WebglAddon.ts @@ -9,20 +9,28 @@ import { IRenderService } from 'browser/services/Services'; import { IColorSet } from 'browser/Types'; export class WebglAddon implements ITerminalAddon { + private _terminal?: Terminal; + constructor( private _preserveDrawingBuffer?: boolean ) {} public activate(terminal: Terminal): void { if (!terminal.element) { - throw new Error('Cannot activate WebglRendererAddon before Terminal.open'); + throw new Error('Cannot activate WebglAddon before Terminal.open'); } + this._terminal = terminal; const renderService: IRenderService = (terminal)._core._renderService; const colors: IColorSet = (terminal)._core._colorManager.colors; renderService.setRenderer(new WebglRenderer(terminal, colors, this._preserveDrawingBuffer)); } public dispose(): void { - throw new Error('WebglRendererAddon.dispose Not yet implemented'); + if (!this._terminal) { + throw new Error('Cannot dispose WebglAddon because it is activated'); + } + const renderService: IRenderService = (this._terminal)._core._renderService; + renderService.setRenderer((this._terminal)._core._createRenderer()); + renderService.onResize(this._terminal.cols, this._terminal.rows); } } From 2aec4e6d29c1b1fd8ed4c2004ceac74b2a1a8634 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 09:27:30 -0800 Subject: [PATCH 2/6] Add a test for removing canvases --- .../src/WebglRenderer.api.ts | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index 9303782d..4debb5f9 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -18,29 +18,25 @@ const height = 600; describe('WebGL Renderer Integration Tests', function(): void { this.timeout(20000); - before(async function(): Promise { - browser = await puppeteer.launch({ - headless: process.argv.indexOf('--headless') !== -1, - slowMo: 80, - args: [`--window-size=${width},${height}`, `--no-sandbox`] - }); - page = (await browser.pages())[0]; - await page.setViewport({ width, height }); - await page.goto(APP); - await openTerminal(); - await page.evaluate(`window.term.loadAddon(new WebglAddon(true));`); - }); - after(() => { browser.close(); }); - beforeEach(async () => { - await page.evaluate(`window.term.reset()`); + it('dispose removes renderer canvases', async () => { + await setupBrowser(); + assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 3); + await page.evaluate(`addon.dispose()`); + assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 0); }); - describe('WebGL Renderer', () => { - it('foreground colors normal', async function(): Promise { + describe('colors', () => { + before(async () => setupBrowser()); + + beforeEach(async () => { + await page.evaluate(`window.term.reset()`); + }); + + it('foreground colors normal', async () => { const theme: ITheme = { black: '#010203', red: '#040506', @@ -63,7 +59,7 @@ describe('WebGL Renderer Integration Tests', function(): void { assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]); }); - it('foreground colors bright', async function(): Promise { + it('foreground colors bright', async () => { const theme: ITheme = { brightBlack: '#010203', brightRed: '#040506', @@ -86,7 +82,7 @@ describe('WebGL Renderer Integration Tests', function(): void { assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]); }); - it('background colors normal', async function(): Promise { + it('background colors normal', async () => { const theme: ITheme = { black: '#010203', red: '#040506', @@ -109,7 +105,7 @@ describe('WebGL Renderer Integration Tests', function(): void { assert.deepEqual(await getCellColor(8, 1), [22, 23, 24, 255]); }); - it('background colors bright', async function(): Promise { + it('background colors bright', async () => { const theme: ITheme = { brightBlack: '#010203', brightRed: '#040506', @@ -161,3 +157,21 @@ async function getCellColor(col: number, row: number): Promise { `); return await page.evaluate(`Array.from(window.result)`); } + +async function setupBrowser(): Promise { + browser = await puppeteer.launch({ + headless: process.argv.indexOf('--headless') !== -1, + slowMo: 80, + args: [`--window-size=${width},${height}`, `--no-sandbox`] + }); + page = (await browser.pages())[0]; + await page.setViewport({ width, height }); + await page.goto(APP); + await openTerminal({ + rendererType: 'dom' + }); + await page.evaluate(` + window.addon = new WebglAddon(true); + window.term.loadAddon(window.addon); + `); +} From d09ac41f75dbedaf104aabae5f16a6849c4a2c1a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 09:29:04 -0800 Subject: [PATCH 3/6] After tests wait for browser close --- addons/xterm-addon-webgl/src/WebglRenderer.api.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index 4debb5f9..be895743 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -18,9 +18,7 @@ const height = 600; describe('WebGL Renderer Integration Tests', function(): void { this.timeout(20000); - after(() => { - browser.close(); - }); + after(async () => browser.close()); it('dispose removes renderer canvases', async () => { await setupBrowser(); @@ -31,10 +29,7 @@ describe('WebGL Renderer Integration Tests', function(): void { describe('colors', () => { before(async () => setupBrowser()); - - beforeEach(async () => { - await page.evaluate(`window.term.reset()`); - }); + beforeEach(async () => page.evaluate(`window.term.reset()`)); it('foreground colors normal', async () => { const theme: ITheme = { From 8adbed84b07a8f278e082f4cc9888beaf92e0f06 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 09:34:40 -0800 Subject: [PATCH 4/6] webgl: Refresh rows on options change Fixes #2549 --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 1f28d589..a32b03e0 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -189,7 +189,6 @@ export class WebglRenderer extends Disposable implements IRenderer { this._rectangleRenderer.updateSelection(this._model.selection, columnSelectMode); this._glyphRenderer.updateSelection(this._model, columnSelectMode); - // TODO: #2102 Should this move to RenderCoordinator? this._onRequestRefreshRows.fire({ start: 0, end: this._terminal.rows - 1 }); } @@ -201,6 +200,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal)); this._updateDimensions(); this._refreshCharAtlas(); + this._onRequestRefreshRows.fire({ start: 0, end: this._terminal.rows - 1 }); } /** From 22f4342194b0576bedc22f370c568992d906ea0e Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 10:07:24 -0800 Subject: [PATCH 5/6] Move options row refresh into render service --- addons/xterm-addon-webgl/src/WebglRenderer.ts | 1 - src/browser/renderer/dom/DomRenderer.ts | 1 - src/browser/services/RenderService.ts | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index a32b03e0..ab2cb354 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -200,7 +200,6 @@ export class WebglRenderer extends Disposable implements IRenderer { this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal)); this._updateDimensions(); this._refreshCharAtlas(); - this._onRequestRefreshRows.fire({ start: 0, end: this._terminal.rows - 1 }); } /** diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 3d544a90..e8fc85f6 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -340,7 +340,6 @@ export class DomRenderer extends Disposable implements IRenderer { // Force a refresh this._updateDimensions(); this._injectCss(); - this._onRequestRefreshRows.fire({ start: 0, end: this._bufferService.rows - 1 }); } public clear(): void { diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index b28c9971..2949c2c5 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -95,6 +95,7 @@ export class RenderService extends Disposable implements IRenderService { public changeOptions(): void { this._renderer.onOptionsChanged(); + this.refreshRows(0, this._rowCount - 1); this._fireOnCanvasResize(); } From 60bda1bbd3fb0df867686426a29c6ae3c57f7d00 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 9 Nov 2019 11:04:55 -0800 Subject: [PATCH 6/6] Fix tests hanging --- addons/xterm-addon-webgl/src/WebglRenderer.api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index be895743..73e83bb2 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -18,17 +18,17 @@ const height = 600; describe('WebGL Renderer Integration Tests', function(): void { this.timeout(20000); - after(async () => browser.close()); - it('dispose removes renderer canvases', async () => { await setupBrowser(); assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 3); await page.evaluate(`addon.dispose()`); assert.equal(await page.evaluate(`document.querySelectorAll('.xterm canvas').length`), 0); + await browser.close(); }); describe('colors', () => { before(async () => setupBrowser()); + after(async () => browser.close()); beforeEach(async () => page.evaluate(`window.term.reset()`)); it('foreground colors normal', async () => {