mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Get pages working, add to demo
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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');
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user