From d4ee0309d9dcb582d290f4461d3c07a67b867cf5 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Mon, 21 Nov 2022 23:21:28 -0500 Subject: [PATCH 1/2] Fixes https://github.com/microsoft/vscode/issues/166158 --- .../xterm-addon-canvas/src/BaseRenderLayer.ts | 7 +++--- addons/xterm-addon-webgl/src/GlyphRenderer.ts | 22 +++++++++---------- addons/xterm-addon-webgl/src/WebglUtils.ts | 10 +++++++++ src/browser/renderer/shared/TextureAtlas.ts | 15 ++++++------- src/browser/renderer/shared/Types.d.ts | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts index 3d16467d95..906347673b 100644 --- a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts +++ b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts @@ -376,12 +376,12 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer this._ctx.save(); this._clipRow(y); // Draw the image, use the bitmap if it's available - if (this._charAtlas.pages[glyph.texturePage].hasCanvasChanged) { + if (this._charAtlas.pages[glyph.texturePage].dirtyId !== this._bitmapGenerator[glyph.texturePage]?.dirtyId) { if (!this._bitmapGenerator[glyph.texturePage]) { this._bitmapGenerator[glyph.texturePage] = new BitmapGenerator(this._charAtlas.pages[glyph.texturePage].canvas); } - this._bitmapGenerator[glyph.texturePage]?.refresh(); - this._charAtlas.pages[glyph.texturePage].hasCanvasChanged = false; + this._bitmapGenerator[glyph.texturePage]!.refresh(); + this._bitmapGenerator[glyph.texturePage]!.dirtyId = this._charAtlas.pages[glyph.texturePage].dirtyId; } this._ctx.drawImage( this._bitmapGenerator[glyph.texturePage]?.bitmap || this._charAtlas!.pages[glyph.texturePage].canvas, @@ -440,6 +440,7 @@ class BitmapGenerator { private _commitTimeout: number | undefined = undefined; private _bitmap: ImageBitmap | undefined = undefined; public get bitmap(): ImageBitmap | undefined { return this._bitmap; } + public dirtyId: number = -1; constructor(private readonly _canvas: HTMLCanvasElement) { } diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index ce71f7b6d0..fd9013bda8 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { createProgram, PROJECTION_MATRIX } from './WebglUtils'; +import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils'; import { IWebGL2RenderingContext, IWebGLVertexArrayObject, IRenderModel } from './Types'; import { NULL_CELL_CODE } from 'common/buffer/Constants'; import { Terminal } from 'xterm'; @@ -94,7 +94,7 @@ export class GlyphRenderer extends Disposable { private readonly _projectionLocation: WebGLUniformLocation; private readonly _resolutionLocation: WebGLUniformLocation; private readonly _textureLocation: WebGLUniformLocation; - private readonly _atlasTextures: WebGLTexture[]; + private readonly _atlasTextures: GLTexture[]; private readonly _attributesBuffer: WebGLBuffer; private _atlas: ITextureAtlas | undefined; @@ -190,14 +190,14 @@ export class GlyphRenderer extends Disposable { // is ever drawn it will show characters as red rectangles. this._atlasTextures = []; for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) { - const texture = throwIfFalsy(gl.createTexture()); - this.register(toDisposable(() => gl.deleteTexture(texture))); + const glTexture = new GLTexture(throwIfFalsy(gl.createTexture())); + this.register(toDisposable(() => gl.deleteTexture(glTexture.texture))); gl.activeTexture(gl.TEXTURE0 + i); - gl.bindTexture(gl.TEXTURE_2D, texture); + gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255])); - this._atlasTextures[i] = texture; + this._atlasTextures[i] = glTexture; } // Allow drawing of transparent texture @@ -348,8 +348,7 @@ export class GlyphRenderer extends Disposable { // Bind the atlas page texture if they have changed for (let i = 0; i < this._atlas.pages.length; i++) { - if (this._atlas.pages[i].hasCanvasChanged) { - this._atlas.pages[i].hasCanvasChanged = false; + if (this._atlas.pages[i].dirtyId !== this._atlasTextures[i].dirtyId) { this._bindAtlasPageTexture(gl, this._atlas, i); } } @@ -360,18 +359,19 @@ export class GlyphRenderer extends Disposable { public setAtlas(atlas: ITextureAtlas): void { this._atlas = atlas; - for (let i = 0; i < atlas.pages.length; i++) { - this._bindAtlasPageTexture(this._gl, atlas, i); + for (const glTexture of this._atlasTextures) { + glTexture.dirtyId = -1; } } private _bindAtlasPageTexture(gl: IWebGL2RenderingContext, atlas: ITextureAtlas, i: number): void { gl.activeTexture(gl.TEXTURE0 + i); - gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[i]); + gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[i].texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, atlas.pages[i].canvas); gl.generateMipmap(gl.TEXTURE_2D); + this._atlasTextures[i].dirtyId = atlas.pages[i].dirtyId; } public setDimensions(dimensions: IRenderDimensions): void { diff --git a/addons/xterm-addon-webgl/src/WebglUtils.ts b/addons/xterm-addon-webgl/src/WebglUtils.ts index 51a273777b..285ce7cd10 100644 --- a/addons/xterm-addon-webgl/src/WebglUtils.ts +++ b/addons/xterm-addon-webgl/src/WebglUtils.ts @@ -51,3 +51,13 @@ export function expandFloat32Array(source: Float32Array, max: number): Float32Ar } return newArray; } + +export class GLTexture { + public texture: WebGLTexture; + public dirtyId: number; + + constructor(texture: WebGLTexture) { + this.texture = texture; + this.dirtyId = -1; + } +} diff --git a/src/browser/renderer/shared/TextureAtlas.ts b/src/browser/renderer/shared/TextureAtlas.ts index 654f368033..81ba165610 100644 --- a/src/browser/renderer/shared/TextureAtlas.ts +++ b/src/browser/renderer/shared/TextureAtlas.ts @@ -61,7 +61,7 @@ export class TextureAtlas implements ITextureAtlas { // The texture that the atlas is drawn to private _pages: AtlasPage[] = []; - public get pages(): { canvas: HTMLCanvasElement, hasCanvasChanged: boolean }[] { return this._pages; } + public get pages(): { canvas: HTMLCanvasElement, dirtyId: number }[] { return this._pages; } // The set of atlas pages that can be written to private _activePages: AtlasPage[] = []; @@ -179,7 +179,7 @@ export class TextureAtlas implements ITextureAtlas { // Merge into the new page const mergedPage = this._mergePages(mergingPages, mergedPageIndex); - mergedPage.hasCanvasChanged = true; + mergedPage.dirtyId++; // Replace the first _merging_ page with the _merged_ page this._pages[mergedPageIndex] = mergedPage; @@ -238,7 +238,7 @@ export class TextureAtlas implements ITextureAtlas { for (const g of adjustingPage.glyphs) { g.texturePage--; } - adjustingPage.hasCanvasChanged = true; + adjustingPage.dirtyId++; } } @@ -826,7 +826,7 @@ export class TextureAtlas implements ITextureAtlas { rasterizedGlyph.size.y ); activePage.addGlyph(rasterizedGlyph); - activePage.hasCanvasChanged = true; + activePage.dirtyId++; return rasterizedGlyph; } @@ -936,10 +936,9 @@ class AtlasPage { } /** - * Whether the canvas of the atlas page has changed, this is only set to true by the atlas, the - * user of the boolean is required to reset its value to false. + * Used to check whether the canvas of the atlas page has changed. */ - public hasCanvasChanged = false; + public dirtyId = 0; // Texture atlas current positioning data. The texture packing strategy used is to fill from // left-to-right and top-to-bottom. When the glyph being written is less than half of the current @@ -982,7 +981,7 @@ class AtlasPage { this.currentRow.y = 0; this.currentRow.height = 0; this.fixedRows.length = 0; - this.hasCanvasChanged = true; + this.dirtyId++; } } diff --git a/src/browser/renderer/shared/Types.d.ts b/src/browser/renderer/shared/Types.d.ts index 78a6b6e5ed..b4168a6691 100644 --- a/src/browser/renderer/shared/Types.d.ts +++ b/src/browser/renderer/shared/Types.d.ts @@ -87,7 +87,7 @@ export interface IRenderer extends IDisposable { } export interface ITextureAtlas extends IDisposable { - readonly pages: { canvas: HTMLCanvasElement, hasCanvasChanged: boolean }[]; + readonly pages: { canvas: HTMLCanvasElement, dirtyId: number }[]; onAddTextureAtlasCanvas: IEvent; onRemoveTextureAtlasCanvas: IEvent; From 188039984943ec9de163c74a07783ae62f11a761 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 23 Nov 2022 08:45:56 -0800 Subject: [PATCH 2/2] dirtyId -> version --- addons/xterm-addon-canvas/src/BaseRenderLayer.ts | 6 +++--- addons/xterm-addon-webgl/src/GlyphRenderer.ts | 6 +++--- addons/xterm-addon-webgl/src/WebglUtils.ts | 4 ++-- src/browser/renderer/shared/TextureAtlas.ts | 12 ++++++------ src/browser/renderer/shared/Types.d.ts | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts index 906347673b..d2a7a4ed2d 100644 --- a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts +++ b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts @@ -376,12 +376,12 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer this._ctx.save(); this._clipRow(y); // Draw the image, use the bitmap if it's available - if (this._charAtlas.pages[glyph.texturePage].dirtyId !== this._bitmapGenerator[glyph.texturePage]?.dirtyId) { + if (this._charAtlas.pages[glyph.texturePage].version !== this._bitmapGenerator[glyph.texturePage]?.version) { if (!this._bitmapGenerator[glyph.texturePage]) { this._bitmapGenerator[glyph.texturePage] = new BitmapGenerator(this._charAtlas.pages[glyph.texturePage].canvas); } this._bitmapGenerator[glyph.texturePage]!.refresh(); - this._bitmapGenerator[glyph.texturePage]!.dirtyId = this._charAtlas.pages[glyph.texturePage].dirtyId; + this._bitmapGenerator[glyph.texturePage]!.version = this._charAtlas.pages[glyph.texturePage].version; } this._ctx.drawImage( this._bitmapGenerator[glyph.texturePage]?.bitmap || this._charAtlas!.pages[glyph.texturePage].canvas, @@ -440,7 +440,7 @@ class BitmapGenerator { private _commitTimeout: number | undefined = undefined; private _bitmap: ImageBitmap | undefined = undefined; public get bitmap(): ImageBitmap | undefined { return this._bitmap; } - public dirtyId: number = -1; + public version: number = -1; constructor(private readonly _canvas: HTMLCanvasElement) { } diff --git a/addons/xterm-addon-webgl/src/GlyphRenderer.ts b/addons/xterm-addon-webgl/src/GlyphRenderer.ts index fd9013bda8..ab7773ef3c 100644 --- a/addons/xterm-addon-webgl/src/GlyphRenderer.ts +++ b/addons/xterm-addon-webgl/src/GlyphRenderer.ts @@ -348,7 +348,7 @@ export class GlyphRenderer extends Disposable { // Bind the atlas page texture if they have changed for (let i = 0; i < this._atlas.pages.length; i++) { - if (this._atlas.pages[i].dirtyId !== this._atlasTextures[i].dirtyId) { + if (this._atlas.pages[i].version !== this._atlasTextures[i].version) { this._bindAtlasPageTexture(gl, this._atlas, i); } } @@ -360,7 +360,7 @@ export class GlyphRenderer extends Disposable { public setAtlas(atlas: ITextureAtlas): void { this._atlas = atlas; for (const glTexture of this._atlasTextures) { - glTexture.dirtyId = -1; + glTexture.version = -1; } } @@ -371,7 +371,7 @@ export class GlyphRenderer extends Disposable { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, atlas.pages[i].canvas); gl.generateMipmap(gl.TEXTURE_2D); - this._atlasTextures[i].dirtyId = atlas.pages[i].dirtyId; + this._atlasTextures[i].version = atlas.pages[i].version; } public setDimensions(dimensions: IRenderDimensions): void { diff --git a/addons/xterm-addon-webgl/src/WebglUtils.ts b/addons/xterm-addon-webgl/src/WebglUtils.ts index 285ce7cd10..da765c8020 100644 --- a/addons/xterm-addon-webgl/src/WebglUtils.ts +++ b/addons/xterm-addon-webgl/src/WebglUtils.ts @@ -54,10 +54,10 @@ export function expandFloat32Array(source: Float32Array, max: number): Float32Ar export class GLTexture { public texture: WebGLTexture; - public dirtyId: number; + public version: number; constructor(texture: WebGLTexture) { this.texture = texture; - this.dirtyId = -1; + this.version = -1; } } diff --git a/src/browser/renderer/shared/TextureAtlas.ts b/src/browser/renderer/shared/TextureAtlas.ts index 81ba165610..811ad165c8 100644 --- a/src/browser/renderer/shared/TextureAtlas.ts +++ b/src/browser/renderer/shared/TextureAtlas.ts @@ -61,7 +61,7 @@ export class TextureAtlas implements ITextureAtlas { // The texture that the atlas is drawn to private _pages: AtlasPage[] = []; - public get pages(): { canvas: HTMLCanvasElement, dirtyId: number }[] { return this._pages; } + public get pages(): { canvas: HTMLCanvasElement, version: number }[] { return this._pages; } // The set of atlas pages that can be written to private _activePages: AtlasPage[] = []; @@ -179,7 +179,7 @@ export class TextureAtlas implements ITextureAtlas { // Merge into the new page const mergedPage = this._mergePages(mergingPages, mergedPageIndex); - mergedPage.dirtyId++; + mergedPage.version++; // Replace the first _merging_ page with the _merged_ page this._pages[mergedPageIndex] = mergedPage; @@ -238,7 +238,7 @@ export class TextureAtlas implements ITextureAtlas { for (const g of adjustingPage.glyphs) { g.texturePage--; } - adjustingPage.dirtyId++; + adjustingPage.version++; } } @@ -826,7 +826,7 @@ export class TextureAtlas implements ITextureAtlas { rasterizedGlyph.size.y ); activePage.addGlyph(rasterizedGlyph); - activePage.dirtyId++; + activePage.version++; return rasterizedGlyph; } @@ -938,7 +938,7 @@ class AtlasPage { /** * Used to check whether the canvas of the atlas page has changed. */ - public dirtyId = 0; + public version = 0; // Texture atlas current positioning data. The texture packing strategy used is to fill from // left-to-right and top-to-bottom. When the glyph being written is less than half of the current @@ -981,7 +981,7 @@ class AtlasPage { this.currentRow.y = 0; this.currentRow.height = 0; this.fixedRows.length = 0; - this.dirtyId++; + this.version++; } } diff --git a/src/browser/renderer/shared/Types.d.ts b/src/browser/renderer/shared/Types.d.ts index b4168a6691..cf4513c26a 100644 --- a/src/browser/renderer/shared/Types.d.ts +++ b/src/browser/renderer/shared/Types.d.ts @@ -87,7 +87,7 @@ export interface IRenderer extends IDisposable { } export interface ITextureAtlas extends IDisposable { - readonly pages: { canvas: HTMLCanvasElement, dirtyId: number }[]; + readonly pages: { canvas: HTMLCanvasElement, version: number }[]; onAddTextureAtlasCanvas: IEvent; onRemoveTextureAtlasCanvas: IEvent;