Get Webgl rendering fg/bg overrides

This commit is contained in:
Daniel Imms
2022-05-10 04:53:31 -07:00
parent 714d4b1cd6
commit d29388394c
7 changed files with 88 additions and 9 deletions
+42 -2
View File
@@ -15,6 +15,7 @@ import { IColor } from 'common/Types';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { AttributeData } from 'common/buffer/AttributeData';
import { IDecorationService } from 'common/services/Services';
interface IVertices {
attributes: Float32Array;
@@ -100,7 +101,8 @@ export class GlyphRenderer {
private _terminal: Terminal,
private _colors: IColorSet,
private _gl: IWebGL2RenderingContext,
private _dimensions: IRenderDimensions
private _dimensions: IRenderDimensions,
private readonly _decorationService: IDecorationService
) {
const gl = this._gl;
const program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
@@ -188,10 +190,48 @@ export class GlyphRenderer {
if (!this._atlas) {
return;
}
// Get any decoration foreground/background overrides
const decorations = this._decorationService.getDecorationsOnLine(y);
let bgOverride: number | undefined;
let fgOverride: number | undefined;
for (const d of decorations) {
const xmin = d.options.x ?? 0;
const xmax = xmin + (d.options.width ?? 1);
if (x >= xmin && x < xmax) {
if (d.backgroundColorRGB) {
bgOverride = d.backgroundColorRGB.rgba;
}
if (d.foregroundColorRGB) {
fgOverride = d.foregroundColorRGB.rgba;
}
}
}
// Convert any overrides from rgba to the fg/bg packed format. This resolves the inverse flag
// ahead of time in order to use the correct cache key
if (bgOverride !== undefined) {
// Non-RGB attributes from model + override + force RGB color mode
if (fg & FgFlags.INVERSE) {
bgOverride = (bg & ~Attributes.RGB_MASK) | (fgOverride !== undefined ? fgOverride >> 8 : fg) | Attributes.CM_RGB;
} else {
bgOverride = (bg & ~Attributes.RGB_MASK) | bgOverride >> 8 | Attributes.CM_RGB;
}
}
if (fgOverride !== undefined) {
// Non-RGB attributes from model + force disable inverse + override + force RGB color mode
if (fg & FgFlags.INVERSE) {
fgOverride = (fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | (bgOverride !== undefined ? bgOverride >> 8 : bg) | Attributes.CM_RGB;
} else {
fgOverride = (fg & ~Attributes.RGB_MASK & ~FgFlags.INVERSE) | fgOverride >> 8 | Attributes.CM_RGB;
}
}
// Get the glyph
if (chars && chars.length > 1) {
rasterizedGlyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg);
} else {
rasterizedGlyph = this._atlas.getRasterizedGlyph(code, bg, fg);
rasterizedGlyph = this._atlas.getRasterizedGlyph(code, bgOverride ?? bg, fgOverride ?? fg);
}
// Fill empty if no glyph was found
@@ -12,6 +12,7 @@ import { IColor } from 'common/Types';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
import { IDecorationService } from 'common/services/Services';
const enum VertexAttribLocations {
POSITION = 0,
@@ -79,7 +80,8 @@ export class RectangleRenderer {
private _terminal: Terminal,
private _colors: IColorSet,
private _gl: IWebGL2RenderingContext,
private _dimensions: IRenderDimensions
private _dimensions: IRenderDimensions,
private readonly _decorationService: IDecorationService
) {
const gl = this._gl;
@@ -252,8 +254,37 @@ export class RectangleRenderer {
let currentInverse = false;
for (let x = 0; x < terminal.cols; x++) {
const modelIndex = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
const bg = model.cells[modelIndex + RENDER_MODEL_BG_OFFSET];
const fg = model.cells[modelIndex + RENDER_MODEL_FG_OFFSET];
// Get any decoration foreground/background overrides
const decorations = this._decorationService.getDecorationsOnLine(y);
let bgOverride: number | undefined;
let fgOverride: number | undefined;
for (const d of decorations) {
const xmin = d.options.x ?? 0;
const xmax = xmin + (d.options.width ?? 1);
if (x >= xmin && x < xmax) {
if (d.backgroundColorRGB) {
bgOverride = d.backgroundColorRGB.rgba;
}
if (d.foregroundColorRGB) {
fgOverride = d.foregroundColorRGB.rgba;
}
}
}
// Convert any overrides from rgba to the fg/bg packed format:
// Non RGB attributes from model + RGB from override + force RGB color mode
if (bgOverride !== undefined) {
bgOverride = (model.cells[modelIndex + RENDER_MODEL_BG_OFFSET] & ~Attributes.RGB_MASK) | bgOverride >> 8 | Attributes.CM_RGB;
}
if (fgOverride !== undefined) {
fgOverride = (model.cells[modelIndex + RENDER_MODEL_FG_OFFSET] & ~Attributes.RGB_MASK) | fgOverride >> 8 | Attributes.CM_RGB;
}
// TODO: This isn't handling invert correctly
const bg = bgOverride ?? model.cells[modelIndex + RENDER_MODEL_BG_OFFSET];
const fg = fgOverride ?? model.cells[modelIndex + RENDER_MODEL_FG_OFFSET];
const inverse = !!(fg & FgFlags.INVERSE);
if (bg !== currentBg || (fg !== currentFg && (currentInverse || inverse))) {
// A rectangle needs to be drawn if going from non-default to another color
+3 -1
View File
@@ -9,6 +9,7 @@ import { ICharacterJoinerService, IRenderService } from 'browser/services/Servic
import { IColorSet } from 'browser/Types';
import { EventEmitter } from 'common/EventEmitter';
import { isSafari } from 'common/Platform';
import { IDecorationService } from 'common/services/Services';
export class WebglAddon implements ITerminalAddon {
private _terminal?: Terminal;
@@ -30,8 +31,9 @@ export class WebglAddon implements ITerminalAddon {
this._terminal = terminal;
const renderService: IRenderService = (terminal as any)._core._renderService;
const characterJoinerService: ICharacterJoinerService = (terminal as any)._core._characterJoinerService;
const decorationService: IDecorationService = (terminal as any)._core._decorationService;
const colors: IColorSet = (terminal as any)._core._colorManager.colors;
this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, this._preserveDrawingBuffer);
this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, decorationService, this._preserveDrawingBuffer);
this._renderer.onContextLoss(() => this._onContextLoss.fire());
renderService.setRenderer(this._renderer);
}
@@ -23,6 +23,7 @@ import { addDisposableDomListener } from 'browser/Lifecycle';
import { ICharacterJoinerService } from 'browser/services/Services';
import { CharData, ICellData } from 'common/Types';
import { AttributeData } from 'common/buffer/AttributeData';
import { IDecorationService } from 'common/services/Services';
export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
@@ -52,6 +53,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
private _terminal: Terminal,
private _colors: IColorSet,
private readonly _characterJoinerService: ICharacterJoinerService,
decorationService: IDecorationService,
preserveDrawingBuffer?: boolean
) {
super();
@@ -95,8 +97,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._core.screenElement!.appendChild(this._canvas);
this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions);
this._glyphRenderer = new GlyphRenderer(this._terminal, this._colors, this._gl, this.dimensions);
this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions, decorationService);
this._glyphRenderer = new GlyphRenderer(this._terminal, this._colors, this._gl, this.dimensions, decorationService);
// Update dimensions and acquire char atlas
this.onCharSizeChanged();
@@ -88,6 +88,9 @@ export class WebglCharAtlas implements IDisposable {
this._tmpCanvas.width = this._config.scaledCellWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCellHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', { alpha: this._config.allowTransparency }));
// This is useful for debugging
document.body.appendChild(this.cacheCanvas);
}
public dispose(): void {
@@ -20,6 +20,7 @@
]
},
"strict": true,
"downlevelIteration": true,
"types": [
"../../../node_modules/@types/mocha"
]
@@ -105,7 +105,7 @@ export class DynamicCharAtlas extends BaseCharAtlas {
this._cacheMap.prealloc(capacity);
// This is useful for debugging
document.body.appendChild(this._cacheCanvas);
// document.body.appendChild(this._cacheCanvas);
}
public dispose(): void {