Get pages working, add to demo

This commit is contained in:
Daniel Imms
2022-10-28 19:30:42 -07:00
parent 67ef455515
commit efba2c9040
7 changed files with 57 additions and 34 deletions
+24 -24
View File
@@ -62,7 +62,7 @@ precision lowp float;
in vec2 v_texcoord;
flat in int v_texpage;
uniform sampler2D u_texture[2];
uniform sampler2D u_texture[8];
out vec4 outColor;
@@ -71,6 +71,18 @@ void main() {
outColor = texture(u_texture[0], v_texcoord);
} else if (v_texpage == 1) {
outColor = texture(u_texture[1], v_texcoord);
} else if (v_texpage == 2) {
outColor = texture(u_texture[2], v_texcoord);
} else if (v_texpage == 3) {
outColor = texture(u_texture[3], v_texcoord);
} else if (v_texpage == 4) {
outColor = texture(u_texture[4], v_texcoord);
} else if (v_texpage == 5) {
outColor = texture(u_texture[5], v_texcoord);
} else if (v_texpage == 6) {
outColor = texture(u_texture[6], v_texcoord);
} else if (v_texpage == 7) {
outColor = texture(u_texture[7], v_texcoord);
}
}`;
@@ -327,23 +339,17 @@ export class GlyphRenderer extends Disposable {
if (this._atlas.hasCanvasChanged) {
this._atlas.hasCanvasChanged = false;
// TODO: Make nicer
const layerTextureUnits = new Int32Array([0, 1]);
const layerTextureUnits = new Int32Array([0, 1, 2, 3, 4, 5, 6, 7]);
gl.uniform1iv(this._textureLocation, layerTextureUnits);
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[0]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._atlas.pages[0].canvas);
gl.generateMipmap(gl.TEXTURE_2D);
if (this._atlas.pages.length > 1) {
// TODO: Check if the particular texture page changed
gl.activeTexture(gl.TEXTURE0 + 1);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[1]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._atlas.pages[1].canvas);
// TODO: Only upload the texture(s) that changed
for (let i = 0; i < this._atlas.pages.length; i++) {
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[i]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._atlas.pages[i].canvas);
gl.generateMipmap(gl.TEXTURE_2D);
}
}
// Set uniforms
gl.uniformMatrix4fv(this._projectionLocation, false, PROJECTION_MATRIX);
gl.uniform2f(this._resolutionLocation, gl.canvas.width, gl.canvas.height);
@@ -356,19 +362,13 @@ export class GlyphRenderer extends Disposable {
const gl = this._gl;
this._atlas = atlas;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[0]);
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[0].canvas);
gl.generateMipmap(gl.TEXTURE_2D);
if (atlas.pages.length > 1) {
gl.activeTexture(gl.TEXTURE0 + 1);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[1]);
// TODO: Share code
for (let i = 0; i < this._atlas.pages.length; i++) {
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, this._atlasTextures[i]);
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[1].canvas);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._atlas.pages[i].canvas);
gl.generateMipmap(gl.TEXTURE_2D);
}
}
+4 -1
View File
@@ -17,8 +17,10 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
private _terminal?: Terminal;
private _renderer?: WebglRenderer;
private readonly _onChangeTextureAtlas = this.register(new EventEmitter<HTMLElement>());
private readonly _onChangeTextureAtlas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onContextLoss = this.register(new EventEmitter<void>());
public readonly onContextLoss = this._onContextLoss.event;
@@ -64,6 +66,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));
renderService.setRenderer(this._renderer);
this.register(toDisposable(() => {
@@ -14,7 +14,7 @@ import { ITerminal } from 'browser/Types';
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 } from 'common/EventEmitter';
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
import { Disposable, toDisposable } from 'common/Lifecycle';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { CharData, IBufferLine, ICellData } from 'common/Types';
@@ -49,6 +49,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
private readonly _onChangeTextureAtlas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>());
public readonly onRequestRedraw = this._onRequestRedraw.event;
private readonly _onContextLoss = this.register(new EventEmitter<void>());
@@ -262,6 +264,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
);
if (this._charAtlas !== atlas) {
this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
// TODO: Dispose this when there's a new atlas
forwardEvent(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas);
}
this._charAtlas = atlas;
this._charAtlas.warmUp();
@@ -22,6 +22,9 @@ declare module 'xterm-addon-webgl' {
*/
public readonly onChangeTextureAtlas: IEvent<HTMLCanvasElement>;
// TODO: Doc
public readonly onAddTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
constructor(preserveDrawingBuffer?: boolean);
/**
+11 -7
View File
@@ -273,8 +273,9 @@ function createTerminal(): void {
typedTerm.loadAddon(addons.webgl.instance);
setTimeout(() => {
if (addons.webgl.instance !== undefined) {
addTextureAtlas(addons.webgl.instance.textureAtlas);
addons.webgl.instance.onChangeTextureAtlas(e => addTextureAtlas(e));
setTextureAtlas(addons.webgl.instance.textureAtlas);
addons.webgl.instance.onChangeTextureAtlas(e => setTextureAtlas(e));
addons.webgl.instance.onAddTextureAtlasCanvas(e => appendTextureAtlas(e));
}
}, 0);
@@ -551,13 +552,13 @@ function initAddons(term: TerminalType): void {
term.loadAddon(addon.instance);
if (name === 'webgl') {
setTimeout(() => {
addTextureAtlas(addons.webgl.instance.textureAtlas);
addons.webgl.instance.onChangeTextureAtlas(e => addTextureAtlas(e));
setTextureAtlas(addons.webgl.instance.textureAtlas);
addons.webgl.instance.onChangeTextureAtlas(e => setTextureAtlas(e));
}, 0);
} else if (name === 'canvas') {
setTimeout(() => {
addTextureAtlas(addons.canvas.instance.textureAtlas);
addons.canvas.instance.onChangeTextureAtlas(e => addTextureAtlas(e));
setTextureAtlas(addons.canvas.instance.textureAtlas);
addons.canvas.instance.onChangeTextureAtlas(e => setTextureAtlas(e));
}, 0);
} else if (name === 'unicode11') {
term.unicode.activeVersion = '11';
@@ -648,9 +649,12 @@ function htmlSerializeButtonHandler(): void {
document.getElementById('htmlserialize-output-result').innerText = 'Copied to clipboard';
}
function addTextureAtlas(e: HTMLCanvasElement): void {
function setTextureAtlas(e: HTMLCanvasElement): void {
document.querySelector('#texture-atlas').replaceChildren(e);
}
function appendTextureAtlas(e: HTMLCanvasElement): void {
document.querySelector('#texture-atlas').appendChild(e);
}
function writeCustomGlyphHandler(): void {
term.write('\n\r');
+8 -1
View File
@@ -14,6 +14,7 @@ import { IUnicodeService } from 'common/services/Services';
import { FourKeyMap } from 'common/MultiKeyMap';
import { IdleTaskQueue } from 'common/TaskQueue';
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
import { EventEmitter } from 'common/EventEmitter';
// For debugging purposes, it can be useful to set this to a really tiny value.
const TEXTURE_WIDTH = 512;
@@ -67,6 +68,10 @@ export class TextureAtlas implements ITextureAtlas {
private _workBoundingBox: IBoundingBox = { top: 0, left: 0, bottom: 0, right: 0 };
private _workAttributeData: AttributeData = new AttributeData();
// TODO: Register
private readonly _onAddTextureAtlasCanvas = new EventEmitter<HTMLCanvasElement>();
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
constructor(
private readonly _document: Document,
private readonly _config: ICharAtlasConfig,
@@ -114,7 +119,9 @@ export class TextureAtlas implements ITextureAtlas {
if (this._pages[this._pages.length - 1].currentRow.y > TEXTURE_CAPACITY) {
// TODO: Support drawing to multiple pages at once
console.log(`Add page #${this._pages.length + 1}`);
this._pages.push(new AtlasPage(this._document));
const newPage = new AtlasPage(this._document);
this._pages.push(newPage);
this._onAddTextureAtlasCanvas.fire(newPage.canvas);
return true;
}
return false;
+2
View File
@@ -91,6 +91,8 @@ export interface ITextureAtlas extends IDisposable {
hasCanvasChanged: boolean;
onAddTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
/**
* Warm up the texture atlas, adding common glyphs to avoid slowing early frame.
*/