Skip to content

Commit

Permalink
Merge pull request #2287 from Tyriar/webgl_simplify_atlas
Browse files Browse the repository at this point in the history
Enable strict mode in webgl addon
  • Loading branch information
Tyriar authored Jul 4, 2019
2 parents ff82d35 + bc07225 commit fb6ec7f
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 81 deletions.
25 changes: 16 additions & 9 deletions addons/xterm-addon-webgl/src/GlyphRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @license MIT
*/

import { createProgram, PROJECTION_MATRIX } from './WebglUtils';
import { createProgram, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { WebglCharAtlas } from './atlas/WebglCharAtlas';
import { IWebGL2RenderingContext, IWebGLVertexArrayObject, IRenderModel, IRasterizedGlyph } from './Types';
import { INDICIES_PER_CELL } from './WebglRenderer';
Expand Down Expand Up @@ -75,7 +75,7 @@ const BYTES_PER_CELL = INDICES_PER_CELL * Float32Array.BYTES_PER_ELEMENT;
const CELL_POSITION_INDICES = 2;

export class GlyphRenderer {
private _atlas: WebglCharAtlas;
private _atlas: WebglCharAtlas | undefined;

private _program: WebGLProgram;
private _vertexArrayObject: IWebGLVertexArrayObject;
Expand Down Expand Up @@ -104,12 +104,16 @@ export class GlyphRenderer {
) {
const gl = this._gl;

this._program = createProgram(gl, vertexShaderSource, fragmentShaderSource);
const program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
if (program === undefined) {
throw new Error('Could not create WebGL program');
}
this._program = program;

// Uniform locations
this._projectionLocation = gl.getUniformLocation(this._program, 'u_projection');
this._resolutionLocation = gl.getUniformLocation(this._program, 'u_resolution');
this._textureLocation = gl.getUniformLocation(this._program, 'u_texture');
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
this._resolutionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_resolution'));
this._textureLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_texture'));

// Create and set the vertex array object
this._vertexArrayObject = gl.createVertexArray();
Expand All @@ -131,7 +135,7 @@ export class GlyphRenderer {
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);

// Setup attributes
this._attributesBuffer = gl.createBuffer();
this._attributesBuffer = throwIfFalsy(gl.createBuffer());
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.OFFSET);
gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0);
Expand All @@ -150,7 +154,7 @@ export class GlyphRenderer {
gl.vertexAttribDivisor(VertexAttribLocations.CELL_POSITION, 1);

// Setup empty texture atlas
this._atlasTexture = gl.createTexture();
this._atlasTexture = throwIfFalsy(gl.createTexture());
gl.bindTexture(gl.TEXTURE_2D, this._atlasTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
Expand Down Expand Up @@ -184,6 +188,9 @@ export class GlyphRenderer {
}

let rasterizedGlyph: IRasterizedGlyph;
if (!this._atlas) {
throw new Error('atlas must be set before updating cell');
}
if (chars && chars.length > 1) {
rasterizedGlyph = this._atlas.getRasterizedGlyphCombinedChar(chars, attr, bg, fg);
} else {
Expand Down Expand Up @@ -264,7 +271,7 @@ export class GlyphRenderer {
if (!line) {
line = terminal.buffer.getLine(row);
}
const chars = line.getCell(x).char;
const chars = line!.getCell(x)!.char;
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], attr, bg, fg, chars);
} else {
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], attr, bg, fg);
Expand Down
14 changes: 7 additions & 7 deletions addons/xterm-addon-webgl/src/RectangleRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @license MIT
*/

import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils';
import { createProgram, expandFloat32Array, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { IRenderModel, IWebGLVertexArrayObject, IWebGL2RenderingContext, ISelectionRenderModel } from './Types';
import { fill } from 'common/TypedArrayUtils';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
Expand Down Expand Up @@ -66,8 +66,8 @@ export class RectangleRenderer {
private _resolutionLocation: WebGLUniformLocation;
private _attributesBuffer: WebGLBuffer;
private _projectionLocation: WebGLUniformLocation;
private _bgFloat: Float32Array;
private _selectionFloat: Float32Array;
private _bgFloat!: Float32Array;
private _selectionFloat!: Float32Array;

private _vertices: IVertices = {
count: 0,
Expand All @@ -83,11 +83,11 @@ export class RectangleRenderer {
) {
const gl = this._gl;

this._program = createProgram(gl, vertexShaderSource, fragmentShaderSource);
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));

// Uniform locations
this._resolutionLocation = gl.getUniformLocation(this._program, 'u_resolution');
this._projectionLocation = gl.getUniformLocation(this._program, 'u_projection');
this._resolutionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_resolution'));
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));

// Create and set the vertex array object
this._vertexArrayObject = gl.createVertexArray();
Expand All @@ -109,7 +109,7 @@ export class RectangleRenderer {
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);

// Setup attributes
this._attributesBuffer = gl.createBuffer();
this._attributesBuffer = throwIfFalsy(gl.createBuffer());
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.POSITION);
gl.vertexAttribPointer(VertexAttribLocations.POSITION, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 0);
Expand Down
28 changes: 14 additions & 14 deletions addons/xterm-addon-webgl/src/WebglRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const INDICIES_PER_CELL = 4;

export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
private _charAtlas: WebglCharAtlas;
private _charAtlas: WebglCharAtlas | undefined;
private _devicePixelRatio: number;

private _model: RenderModel = new RenderModel();
Expand Down Expand Up @@ -57,18 +57,18 @@ export class WebglRenderer extends Disposable implements IRenderer {
new CursorRenderLayer(this._core.screenElement, 3, this._colors)
];
this.dimensions = {
scaledCharWidth: null,
scaledCharHeight: null,
scaledCellWidth: null,
scaledCellHeight: null,
scaledCharLeft: null,
scaledCharTop: null,
scaledCanvasWidth: null,
scaledCanvasHeight: null,
canvasWidth: null,
canvasHeight: null,
actualCellWidth: null,
actualCellHeight: null
scaledCharWidth: 0,
scaledCharHeight: 0,
scaledCellWidth: 0,
scaledCellHeight: 0,
scaledCharLeft: 0,
scaledCharTop: 0,
scaledCanvasWidth: 0,
scaledCanvasHeight: 0,
canvasWidth: 0,
canvasHeight: 0,
actualCellWidth: 0,
actualCellHeight: 0
};
this._devicePixelRatio = window.devicePixelRatio;
this._updateDimensions();
Expand Down Expand Up @@ -252,7 +252,7 @@ export class WebglRenderer extends Disposable implements IRenderer {

for (let y = start; y <= end; y++) {
const row = y + terminal.buffer.ydisp;
const line = terminal.buffer.lines.get(row);
const line = terminal.buffer.lines.get(row)!;
this._model.lineLengths[y] = 0;
for (let x = 0; x < terminal.cols; x++) {
const charData = line.get(x);
Expand Down
15 changes: 11 additions & 4 deletions addons/xterm-addon-webgl/src/WebglUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export const PROJECTION_MATRIX = new Float32Array([
]);

export function createProgram(gl: WebGLRenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram | undefined {
const program = gl.createProgram();
gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vertexSource));
gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fragmentSource));
const program = throwIfFalsy(gl.createProgram());
gl.attachShader(program, throwIfFalsy(createShader(gl, gl.VERTEX_SHADER, vertexSource)));
gl.attachShader(program, throwIfFalsy(createShader(gl, gl.FRAGMENT_SHADER, fragmentSource)));
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
Expand All @@ -29,7 +29,7 @@ export function createProgram(gl: WebGLRenderingContext, vertexSource: string, f
}

export function createShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader | undefined {
const shader = gl.createShader(type);
const shader = throwIfFalsy(gl.createShader(type));
gl.shaderSource(shader, source);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
Expand All @@ -49,3 +49,10 @@ export function expandFloat32Array(source: Float32Array, max: number): Float32Ar
}
return newArray;
}

export function throwIfFalsy<T>(value: T | undefined | null): T {
if (!value) {
throw new Error('value must not be falsy');
}
return value;
}
13 changes: 9 additions & 4 deletions addons/xterm-addon-webgl/src/atlas/CharAtlasUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@
import { ICharAtlasConfig } from './Types';
import { DEFAULT_COLOR } from 'common/buffer/Constants';
import { Terminal, FontWeight } from 'xterm';
import { IColorSet } from 'browser/Types';
import { IColorSet, IColor } from 'browser/Types';

const NULL_COLOR: IColor = {
css: '',
rgba: 0
};

export function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: Terminal, colors: IColorSet): ICharAtlasConfig {
// null out some fields that don't matter
const clonedColors: IColorSet = {
foreground: colors.foreground,
background: colors.background,
cursor: null,
cursorAccent: null,
selection: null,
cursor: NULL_COLOR,
cursorAccent: NULL_COLOR,
selection: NULL_COLOR,
// For the static char atlas, we only use the first 16 colors, but we need all 256 for the
// dynamic character atlas.
ansi: colors.ansi.slice()
Expand Down
5 changes: 3 additions & 2 deletions addons/xterm-addon-webgl/src/atlas/WebglCharAtlas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Cons
import { IRasterizedGlyph, IBoundingBox, IRasterizedGlyphSet } from '../Types';
import { DEFAULT_COLOR, DEFAULT_ATTR } from 'common/buffer/Constants';
import { is256Color } from './CharAtlasUtils';
import { throwIfFalsy } from '../WebglUtils';
import { IColor } from 'browser/Types';
import { FLAGS } from '../Constants';
import { IDisposable } from 'xterm';
Expand Down Expand Up @@ -75,12 +76,12 @@ export class WebglCharAtlas implements IDisposable {
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
// It might also contain some characters with transparent backgrounds if allowTransparency is
// set.
this._cacheCtx = this.cacheCanvas.getContext('2d', {alpha: true});
this._cacheCtx = throwIfFalsy(this.cacheCanvas.getContext('2d', {alpha: true}));

this._tmpCanvas = document.createElement('canvas');
this._tmpCanvas.width = this._config.scaledCharWidth * 2 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCharHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCtx = this._tmpCanvas.getContext('2d', {alpha: this._config.allowTransparency});
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', {alpha: this._config.allowTransparency}));

// This is useful for debugging
document.body.appendChild(this.cacheCanvas);
Expand Down
7 changes: 4 additions & 3 deletions addons/xterm-addon-webgl/src/renderLayer/BaseRenderLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@ import { IRenderDimensions } from 'browser/renderer/Types';
import { CellData } from 'common/buffer/CellData';
import { AttributeData } from 'common/buffer/AttributeData';
import { WebglCharAtlas } from 'atlas/WebglCharAtlas';
import { throwIfFalsy } from '../WebglUtils';

export abstract class BaseRenderLayer implements IRenderLayer {
private _canvas: HTMLCanvasElement;
protected _ctx: CanvasRenderingContext2D;
protected _ctx!: CanvasRenderingContext2D;
private _scaledCharWidth: number = 0;
private _scaledCharHeight: number = 0;
private _scaledCellWidth: number = 0;
private _scaledCellHeight: number = 0;
private _scaledCharLeft: number = 0;
private _scaledCharTop: number = 0;

protected _charAtlas: WebglCharAtlas;
protected _charAtlas: WebglCharAtlas | undefined;

/**
* An object that's reused when drawing glyphs in order to reduce GC.
Expand Down Expand Up @@ -63,7 +64,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
}

private _initCanvas(): void {
this._ctx = this._canvas.getContext('2d', {alpha: this._alpha});
this._ctx = throwIfFalsy(this._canvas.getContext('2d', {alpha: this._alpha}));
// Draw the background if this is an opaque layer
if (!this._alpha) {
this._clearAll();
Expand Down
Loading

0 comments on commit fb6ec7f

Please sign in to comment.