Merge pull request #4252 from Tyriar/4243_merge

Continually merge texture atlas pages
This commit is contained in:
Daniel Imms
2022-11-03 06:48:55 -07:00
committed by GitHub
7 changed files with 175 additions and 27 deletions
+10 -8
View File
@@ -10,6 +10,7 @@ import { Terminal } from 'xterm';
import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
import { Disposable, toDisposable } from 'common/Lifecycle';
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
interface IVertices {
attributes: Float32Array;
@@ -107,8 +108,6 @@ export class GlyphRenderer extends Disposable {
]
};
private static _maxAtlasPages: number | undefined;
constructor(
private readonly _terminal: Terminal,
private readonly _gl: IWebGL2RenderingContext,
@@ -118,11 +117,14 @@ export class GlyphRenderer extends Disposable {
const gl = this._gl;
if (GlyphRenderer._maxAtlasPages === undefined) {
GlyphRenderer._maxAtlasPages = throwIfFalsy(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number | null);
if (TextureAtlas.maxAtlasPages === undefined) {
// Typically 8 or 16
TextureAtlas.maxAtlasPages = throwIfFalsy(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) as number | null);
// Almost all clients will support >= 4096
TextureAtlas.maxTextureSize = throwIfFalsy(gl.getParameter(gl.MAX_TEXTURE_SIZE) as number | null);
}
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, createFragmentShaderSource(GlyphRenderer._maxAtlasPages)));
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, createFragmentShaderSource(TextureAtlas.maxAtlasPages)));
this.register(toDisposable(() => gl.deleteProgram(this._program)));
// Uniform locations
@@ -177,8 +179,8 @@ export class GlyphRenderer extends Disposable {
// Setup static uniforms
gl.useProgram(this._program);
const textureUnits = new Int32Array(GlyphRenderer._maxAtlasPages);
for (let i = 0; i < GlyphRenderer._maxAtlasPages; i++) {
const textureUnits = new Int32Array(TextureAtlas.maxAtlasPages);
for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) {
textureUnits[i] = i;
}
gl.uniform1iv(this._textureLocation, textureUnits);
@@ -187,7 +189,7 @@ export class GlyphRenderer extends Disposable {
// Setup 1x1 red pixel textures for all potential atlas pages, if one of these invalid textures
// is ever drawn it will show characters as red rectangles.
this._atlasTextures = [];
for (let i = 0; i < GlyphRenderer._maxAtlasPages; i++) {
for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) {
const texture = throwIfFalsy(gl.createTexture());
this.register(toDisposable(() => gl.deleteTexture(texture)));
gl.activeTexture(gl.TEXTURE0 + i);
@@ -21,6 +21,8 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onRemoveTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
private readonly _onContextLoss = this.register(new EventEmitter<void>());
public readonly onContextLoss = this._onContextLoss.event;
@@ -67,6 +69,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
this.register(forwardEvent(this._renderer.onContextLoss, this._onContextLoss));
this.register(forwardEvent(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas));
this.register(forwardEvent(this._renderer.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas));
this.register(forwardEvent(this._renderer.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas));
renderService.setRenderer(this._renderer);
this.register(toDisposable(() => {
@@ -16,7 +16,7 @@ import { AttributeData } from 'common/buffer/AttributeData';
import { CellData } from 'common/buffer/CellData';
import { Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
import { Disposable, toDisposable } from 'common/Lifecycle';
import { Disposable, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { CharData, IBufferLine, ICellData } from 'common/Types';
import { IDisposable, Terminal } from 'xterm';
@@ -53,6 +53,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onRemoveTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
private readonly _onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>());
public readonly onRequestRedraw = this._onRequestRedraw.event;
private readonly _onContextLoss = this.register(new EventEmitter<void>());
@@ -268,7 +270,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._charAtlasDisposable?.dispose();
this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
this._charAtlasDisposable = forwardEvent(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas);
this._charAtlasDisposable = getDisposeArrayDisposable([
forwardEvent(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
forwardEvent(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
]);
}
this._charAtlas = atlas;
this._charAtlas.warmUp();
@@ -327,7 +332,6 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Tell renderer the frame is beginning
if (this._glyphRenderer.beginFrame()) {
this._clearModel(true);
this._model.selection.clear();
}
// Update model to reflect what's drawn