Skip to content

Commit

Permalink
Merge pull request #3783 from Tyriar/bg_decorations__selection_refactor
Browse files Browse the repository at this point in the history
Remove selection-specific render pass, use bg overrides instead
  • Loading branch information
Tyriar authored May 11, 2022
2 parents 8b9fa32 + 8164c63 commit bc4158c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 195 deletions.
99 changes: 4 additions & 95 deletions addons/xterm-addon-webgl/src/GlyphRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@
import { createProgram, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { WebglCharAtlas } from './atlas/WebglCharAtlas';
import { IWebGL2RenderingContext, IWebGLVertexArrayObject, IRenderModel, IRasterizedGlyph } from './Types';
import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_INDICIES_PER_CELL, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_BG_OFFSET } from './RenderModel';
import { fill } from 'common/TypedArrayUtils';
import { slice } from './TypedArray';
import { NULL_CELL_CODE, Attributes, FgFlags } from 'common/buffer/Constants';
import { NULL_CELL_CODE } from 'common/buffer/Constants';
import { Terminal, IBufferLine } from 'xterm';
import { IColor } from 'common/Types';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { AttributeData } from 'common/buffer/AttributeData';

interface IVertices {
attributes: Float32Array;
Expand All @@ -25,7 +21,6 @@ interface IVertices {
* working on the next frame.
*/
attributesBuffers: Float32Array[];
selectionAttributes: Float32Array;
count: number;
}

Expand Down Expand Up @@ -92,8 +87,7 @@ export class GlyphRenderer {
attributesBuffers: [
new Float32Array(0),
new Float32Array(0)
],
selectionAttributes: new Float32Array(0)
]
};

constructor(
Expand Down Expand Up @@ -217,91 +211,6 @@ export class GlyphRenderer {
// a_cellpos only changes on resize
}

public updateSelection(model: IRenderModel): void {
const terminal = this._terminal;

this._vertices.selectionAttributes = slice(this._vertices.attributes, 0);

const bg = (this._colors.selectionOpaque.rgba >>> 8) | Attributes.CM_RGB;

if (model.selection.columnSelectMode) {
const startCol = model.selection.startCol;
const width = model.selection.endCol - startCol;
const height = model.selection.viewportCappedEndRow - model.selection.viewportCappedStartRow + 1;
for (let y = model.selection.viewportCappedStartRow; y < model.selection.viewportCappedStartRow + height; y++) {
this._updateSelectionRange(startCol, startCol + width, y, model, bg);
}
} else {
// Draw first row
const startCol = model.selection.viewportStartRow === model.selection.viewportCappedStartRow ? model.selection.startCol : 0;
const startRowEndCol = model.selection.viewportCappedStartRow === model.selection.viewportCappedEndRow ? model.selection.endCol : terminal.cols;
this._updateSelectionRange(startCol, startRowEndCol, model.selection.viewportCappedStartRow, model, bg);

// Draw middle rows
const middleRowsCount = Math.max(model.selection.viewportCappedEndRow - model.selection.viewportCappedStartRow - 1, 0);
for (let y = model.selection.viewportCappedStartRow + 1; y <= model.selection.viewportCappedStartRow + middleRowsCount; y++) {
this._updateSelectionRange(0, startRowEndCol, y, model, bg);
}

// Draw final row
if (model.selection.viewportCappedStartRow !== model.selection.viewportCappedEndRow) {
// Only draw viewportEndRow if it's not the same as viewportStartRow
const endCol = model.selection.viewportEndRow === model.selection.viewportCappedEndRow ? model.selection.endCol : terminal.cols;
this._updateSelectionRange(0, endCol, model.selection.viewportCappedEndRow, model, bg);
}
}
}

private _updateSelectionRange(startCol: number, endCol: number, y: number, model: IRenderModel, bg: number): void {
const terminal = this._terminal;
const row = y + terminal.buffer.active.viewportY;
let line: IBufferLine | undefined;
for (let x = startCol; x < endCol; x++) {
const offset = (y * this._terminal.cols + x) * RENDER_MODEL_INDICIES_PER_CELL;
const code = model.cells[offset];
let fg = model.cells[offset + RENDER_MODEL_FG_OFFSET];
if (fg & FgFlags.INVERSE) {
const workCell = new AttributeData();
workCell.fg = fg;
workCell.bg = model.cells[offset + RENDER_MODEL_BG_OFFSET];
// Get attributes from fg (excluding inverse) and resolve inverse by pullibng rgb colors
// from bg. This is needed since the inverse fg color should be based on the original bg
// color, not on the selection color
fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK | FgFlags.INVERSE);
switch (workCell.getBgColorMode()) {
case Attributes.CM_P16:
case Attributes.CM_P256:
const c = this._getColorFromAnsiIndex(workCell.getBgColor()).rgba;
fg |= (c >> 8) & Attributes.RED_MASK | (c >> 8) & Attributes.GREEN_MASK | (c >> 8) & Attributes.BLUE_MASK;
case Attributes.CM_RGB:
const arr = AttributeData.toColorRGB(workCell.getBgColor());
fg |= arr[0] << Attributes.RED_SHIFT | arr[1] << Attributes.GREEN_SHIFT | arr[2] << Attributes.BLUE_SHIFT;
case Attributes.CM_DEFAULT:
default:
const c2 = this._colors.background.rgba;
fg |= (c2 >> 8) & Attributes.RED_MASK | (c2 >> 8) & Attributes.GREEN_MASK | (c2 >> 8) & Attributes.BLUE_MASK;
}
fg |= Attributes.CM_RGB;
}
if (code & COMBINED_CHAR_BIT_MASK) {
if (!line) {
line = terminal.buffer.active.getLine(row);
}
const chars = line!.getCell(x)!.getChars();
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg, chars);
} else {
this._updateCell(this._vertices.selectionAttributes, x, y, model.cells[offset], bg, fg);
}
}
}

private _getColorFromAnsiIndex(idx: number): IColor {
if (idx >= this._colors.ansi.length) {
throw new Error('No color found for idx ' + idx);
}
return this._colors.ansi[idx];
}

public clear(force?: boolean): void {
const terminal = this._terminal;
const newCount = terminal.cols * terminal.rows * INDICES_PER_CELL;
Expand Down Expand Up @@ -336,7 +245,7 @@ export class GlyphRenderer {
public setColors(): void {
}

public render(renderModel: IRenderModel, isSelectionVisible: boolean): void {
public render(renderModel: IRenderModel): void {
if (!this._atlas) {
return;
}
Expand All @@ -360,7 +269,7 @@ export class GlyphRenderer {
let bufferLength = 0;
for (let y = 0; y < renderModel.lineLengths.length; y++) {
const si = y * this._terminal.cols * INDICES_PER_CELL;
const sub = (isSelectionVisible ? this._vertices.selectionAttributes : this._vertices.attributes).subarray(si, si + renderModel.lineLengths[y] * INDICES_PER_CELL);
const sub = this._vertices.attributes.subarray(si, si + renderModel.lineLengths[y] * INDICES_PER_CELL);
activeBuffer.set(sub, bufferLength);
bufferLength += sub.length;
}
Expand Down
81 changes: 2 additions & 79 deletions addons/xterm-addon-webgl/src/RectangleRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*/

import { createProgram, expandFloat32Array, PROJECTION_MATRIX, throwIfFalsy } from './WebglUtils';
import { IRenderModel, IWebGLVertexArrayObject, IWebGL2RenderingContext, ISelectionRenderModel } from './Types';
import { fill } from 'common/TypedArrayUtils';
import { IRenderModel, IWebGLVertexArrayObject, IWebGL2RenderingContext } from './Types';
import { Attributes, FgFlags } from 'common/buffer/Constants';
import { Terminal } from 'xterm';
import { IColor } from 'common/Types';
Expand Down Expand Up @@ -50,7 +49,6 @@ void main() {

interface IVertices {
attributes: Float32Array;
selection: Float32Array;
count: number;
}

Expand All @@ -67,12 +65,10 @@ export class RectangleRenderer {
private _attributesBuffer: WebGLBuffer;
private _projectionLocation: WebGLUniformLocation;
private _bgFloat!: Float32Array;
private _selectionFloat!: Float32Array;

private _vertices: IVertices = {
count: 0,
attributes: new Float32Array(INITIAL_BUFFER_RECTANGLE_CAPACITY),
selection: new Float32Array(3 * INDICES_PER_RECTANGLE)
attributes: new Float32Array(INITIAL_BUFFER_RECTANGLE_CAPACITY)
};

constructor(
Expand Down Expand Up @@ -138,11 +134,6 @@ export class RectangleRenderer {
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this._vertices.attributes, gl.DYNAMIC_DRAW);
gl.drawElementsInstanced(this._gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, this._vertices.count);

// Bind selection buffer and draw
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, this._vertices.selection, gl.DYNAMIC_DRAW);
gl.drawElementsInstanced(this._gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 3);
}

public onResize(): void {
Expand All @@ -156,7 +147,6 @@ export class RectangleRenderer {

private _updateCachedColors(): void {
this._bgFloat = this._colorToFloat32Array(this._colors.background);
this._selectionFloat = this._colorToFloat32Array(this._colors.selectionOpaque);
}

private _updateViewportRectangle(): void {
Expand All @@ -172,73 +162,6 @@ export class RectangleRenderer {
);
}

public updateSelection(model: ISelectionRenderModel): void {
const terminal = this._terminal;

if (!model.hasSelection) {
fill(this._vertices.selection, 0, 0);
return;
}

if (model.columnSelectMode) {
const startCol = model.startCol;
const width = model.endCol - startCol;
const height = model.viewportCappedEndRow - model.viewportCappedStartRow + 1;
this._addRectangleFloat(
this._vertices.selection,
0,
startCol * this._dimensions.scaledCellWidth,
model.viewportCappedStartRow * this._dimensions.scaledCellHeight,
width * this._dimensions.scaledCellWidth,
height * this._dimensions.scaledCellHeight,
this._selectionFloat
);
fill(this._vertices.selection, 0, INDICES_PER_RECTANGLE);
} else {
// Draw first row
const startCol = model.viewportStartRow === model.viewportCappedStartRow ? model.startCol : 0;
const startRowEndCol = model.viewportCappedStartRow === model.viewportEndRow ? model.endCol : terminal.cols;
this._addRectangleFloat(
this._vertices.selection,
0,
startCol * this._dimensions.scaledCellWidth,
model.viewportCappedStartRow * this._dimensions.scaledCellHeight,
(startRowEndCol - startCol) * this._dimensions.scaledCellWidth,
this._dimensions.scaledCellHeight,
this._selectionFloat
);

// Draw middle rows
const middleRowsCount = Math.max(model.viewportCappedEndRow - model.viewportCappedStartRow - 1, 0);
this._addRectangleFloat(
this._vertices.selection,
INDICES_PER_RECTANGLE,
0,
(model.viewportCappedStartRow + 1) * this._dimensions.scaledCellHeight,
terminal.cols * this._dimensions.scaledCellWidth,
middleRowsCount * this._dimensions.scaledCellHeight,
this._selectionFloat
);

// Draw final row
if (model.viewportCappedStartRow !== model.viewportCappedEndRow) {
// Only draw viewportEndRow if it's not the same as viewportStartRow
const endCol = model.viewportEndRow === model.viewportCappedEndRow ? model.endCol : terminal.cols;
this._addRectangleFloat(
this._vertices.selection,
INDICES_PER_RECTANGLE * 2,
0,
model.viewportCappedEndRow * this._dimensions.scaledCellHeight,
endCol * this._dimensions.scaledCellWidth,
this._dimensions.scaledCellHeight,
this._selectionFloat
);
} else {
fill(this._vertices.selection, 0, INDICES_PER_RECTANGLE * 2);
}
}
}

public updateBackgrounds(model: IRenderModel): void {
const terminal = this._terminal;
const vertices = this._vertices;
Expand Down
Loading

0 comments on commit bc4158c

Please sign in to comment.