Expose API to clear texture atlas

Using canvases on Electron (and plain Chromium I believe), when resuming
from sleep the graphics card may release the texture which results in
the terminal display and char atlas being corrupt. This API allows the
consumer to clear the texture atlas right after resuming, atlas warm up
is not done to simplify this process because the fact that atlases are
shared between multiple terminals complicates this.

Related microsoft/vscode#69665
This commit is contained in:
Daniel Imms
2020-09-06 14:50:09 -07:00
parent ecfc7336c5
commit e07b9684bb
6 changed files with 39 additions and 11 deletions
@@ -43,7 +43,6 @@ export class RenderModel implements IRenderModel {
public clear(): void {
fill(this.cells, 0, 0);
fill(this.lineLengths, 0, 0);
this.clearSelection();
}
public clearSelection(): void {
@@ -40,4 +40,8 @@ export class WebglAddon implements ITerminalAddon {
public get textureAtlas(): HTMLCanvasElement | undefined {
return this._renderer?.textureAtlas;
}
public clearTextureAtlas(): void {
this._renderer?.clearCharAtlas();
}
}
@@ -121,6 +121,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Force a full refresh
this._model.clear();
this._model.clearSelection();
}
public onDevicePixelRatioChange(): void {
@@ -158,6 +159,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Force a full refresh
this._model.clear();
this._model.clearSelection();
}
public onCharSizeChanged(): void {
@@ -214,6 +216,14 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._glyphRenderer.setAtlas(this._charAtlas);
}
public clearCharAtlas(): void {
this._charAtlas?.clearTexture();
this._model.clear();
this._updateModel(0, this._terminal.rows - 1);
this._glyphRenderer.updateSelection(this._model);
this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 });
}
public clear(): void {
this._renderLayers.forEach(l => l.reset(this._terminal));
}
@@ -243,6 +253,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Tell renderer the frame is beginning
if (this._glyphRenderer.beginFrame()) {
this._model.clear();
this._model.clearSelection();
}
// Update model to reflect what's drawn
@@ -101,7 +101,7 @@ export class WebglCharAtlas implements IDisposable {
}
}
protected _doWarmUp(): void {
private _doWarmUp(): void {
// Pre-fill with ASCII 33-126
for (let i = 33; i < 126; i++) {
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR);
@@ -115,17 +115,26 @@ export class WebglCharAtlas implements IDisposable {
public beginFrame(): boolean {
if (this._currentRowY > TEXTURE_CAPACITY) {
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
this._cacheMap = {};
this._currentRowHeight = 0;
this._currentRowX = 0;
this._currentRowY = 0;
this._doWarmUp();
this.clearTexture();
this.warmUp();
return true;
}
return false;
}
public clearTexture(): void {
if (this._currentRowX === 0 && this._currentRowY === 0) {
return;
}
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
this._cacheMap = {};
this._cacheMapCombined = {};
this._currentRowHeight = 0;
this._currentRowX = 0;
this._currentRowY = 0;
this._didWarmUp = false;
}
public getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMapCombined[chars];
if (!rasterizedGlyphSet) {
+7 -2
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
import { Terminal, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-webgl' {
/**
@@ -15,7 +15,7 @@ declare module 'xterm-addon-webgl' {
constructor(preserveDrawingBuffer?: boolean);
/**
* Activates the addon
* Activates the addon.
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
@@ -24,5 +24,10 @@ declare module 'xterm-addon-webgl' {
* Disposes the addon.
*/
public dispose(): void;
/**
* Clears the terminal's texture atlas and triggers a redraw.
*/
public clearTextureAtlas(): void;
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ export abstract class BaseCharAtlas implements IDisposable {
* Perform any work needed to warm the cache before it can be used. Used by the default
* implementation of warmUp(), and will only be called once.
*/
protected _doWarmUp(): void { }
private _doWarmUp(): void { }
/**
* Called when we start drawing a new frame.