Skip to content

Commit a7b98de

Browse files
committed
Handle overflowing to new row
1 parent ff9a3a1 commit a7b98de

File tree

6 files changed

+31
-18
lines changed

6 files changed

+31
-18
lines changed

addons/addon-webgl/src/WebglRenderer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
3333
private _charAtlasDisposable = this._register(new MutableDisposable());
3434
private _charAtlas: ITextureAtlas | undefined;
3535
private _devicePixelRatio: number;
36+
private _deviceMaxTextureSize: number;
3637
private _observerDisposable = this._register(new MutableDisposable());
3738

3839
private _model: RenderModel = new RenderModel();
@@ -102,6 +103,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
102103
throw new Error('WebGL2 not supported ' + this._gl);
103104
}
104105

106+
this._deviceMaxTextureSize = this._gl.getParameter(this._gl.MAX_TEXTURE_SIZE);
107+
105108
this._register(addDisposableListener(this._canvas, 'webglcontextlost', (e) => {
106109
console.log('webglcontextlost event received');
107110
// Prevent the default behavior in order to enable WebGL context restoration.
@@ -272,7 +275,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
272275
this.dimensions.device.cell.height,
273276
this.dimensions.device.char.width,
274277
this.dimensions.device.char.height,
275-
this._coreBrowserService.dpr
278+
this._coreBrowserService.dpr,
279+
this._deviceMaxTextureSize
276280
);
277281
if (this._charAtlas !== atlas) {
278282
this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);

addons/addon-webgl/src/renderLayer/BaseRenderLayer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
9494
if (this._deviceCharWidth <= 0 && this._deviceCharHeight <= 0) {
9595
return;
9696
}
97-
this._charAtlas = acquireTextureAtlas(terminal, this._optionsService.rawOptions, colorSet, this._deviceCellWidth, this._deviceCellHeight, this._deviceCharWidth, this._deviceCharHeight, this._coreBrowserService.dpr);
97+
98+
this._charAtlas = acquireTextureAtlas(terminal, this._optionsService.rawOptions, colorSet, this._deviceCellWidth, this._deviceCellHeight, this._deviceCharWidth, this._deviceCharHeight, this._coreBrowserService.dpr, 2048);
9899
this._charAtlas.warmUp();
99100
}
100101

src/browser/renderer/shared/CharAtlasCache.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ export function acquireTextureAtlas(
3131
deviceCellHeight: number,
3232
deviceCharWidth: number,
3333
deviceCharHeight: number,
34-
devicePixelRatio: number
34+
devicePixelRatio: number,
35+
deviceMaxTextureSize: number
3536
): ITextureAtlas {
36-
const newConfig = generateConfig(deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, options, colors, devicePixelRatio);
37+
const newConfig = generateConfig(deviceCellWidth, deviceCellHeight, deviceCharWidth, deviceCharHeight, options, colors, devicePixelRatio, deviceMaxTextureSize);
3738

3839
// Check to see if the terminal already owns this config
3940
for (let i = 0; i < charAtlasCache.length; i++) {

src/browser/renderer/shared/CharAtlasUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { ITerminalOptions } from '@xterm/xterm';
99
import { IColorSet, ReadonlyColorSet } from 'browser/Types';
1010
import { NULL_COLOR } from 'common/Color';
1111

12-
export function generateConfig(deviceCellWidth: number, deviceCellHeight: number, deviceCharWidth: number, deviceCharHeight: number, options: Required<ITerminalOptions>, colors: ReadonlyColorSet, devicePixelRatio: number): ICharAtlasConfig {
12+
export function generateConfig(deviceCellWidth: number, deviceCellHeight: number, deviceCharWidth: number, deviceCharHeight: number, options: Required<ITerminalOptions>, colors: ReadonlyColorSet, devicePixelRatio: number, deviceMaxTextureSize: number): ICharAtlasConfig {
1313
// null out some fields that don't matter
1414
const clonedColors: IColorSet = {
1515
foreground: colors.foreground,
@@ -34,6 +34,7 @@ export function generateConfig(deviceCellWidth: number, deviceCellHeight: number
3434
return {
3535
customGlyphs: options.customGlyphs,
3636
devicePixelRatio,
37+
deviceMaxTextureSize,
3738
letterSpacing: options.letterSpacing,
3839
lineHeight: options.lineHeight,
3940
deviceCellWidth: deviceCellWidth,

src/browser/renderer/shared/TextureAtlas.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export class TextureAtlas implements ITextureAtlas {
6666

6767
// The set of atlas pages that can be written to
6868
private _activePages: AtlasPage[] = [];
69+
private _overflowSizePage: AtlasPage | undefined;
6970

7071
private _tmpCanvas: HTMLCanvasElement;
7172
// A temporary context that glyphs are drawn to before being transfered to the atlas.
@@ -75,8 +76,6 @@ export class TextureAtlas implements ITextureAtlas {
7576
private _workAttributeData: AttributeData = new AttributeData();
7677

7778
private _textureSize: number = 512;
78-
// TODO: Use actual value
79-
private _deviceMaxTextureSize: number = 2048;
8079

8180
public static maxAtlasPages: number | undefined;
8281
public static maxTextureSize: number | undefined;
@@ -433,7 +432,7 @@ export class TextureAtlas implements ITextureAtlas {
433432
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
434433
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
435434
// giant ligatures (eg. =====>) don't impact overall performance.
436-
const allowedWidth = Math.min(this._config.deviceCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2, this._deviceMaxTextureSize);
435+
const allowedWidth = Math.min(this._config.deviceCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2, this._config.deviceMaxTextureSize);
437436
if (this._tmpCanvas.width < allowedWidth) {
438437
this._tmpCanvas.width = allowedWidth;
439438
}
@@ -774,19 +773,24 @@ export class TextureAtlas implements ITextureAtlas {
774773
}
775774
}
776775

777-
// TODO: Move below after page merging to ensure page limit isn't hit
778776
// Create a new page for oversized glyphs as they come up
779777
if (rasterizedGlyph.size.x > this._textureSize) {
780-
// TODO: Reuse a single oversized glyphs page
781-
const newPage = new AtlasPage(this._document, this._deviceMaxTextureSize);
782-
this.pages.push(newPage);
778+
if (!this._overflowSizePage) {
779+
this._overflowSizePage = new AtlasPage(this._document, this._config.deviceMaxTextureSize);
780+
this.pages.push(this._overflowSizePage);
783781

784-
// Request the model to be cleared to refresh all texture pages.
785-
this._requestClearModel = true;
786-
this._onAddTextureAtlasCanvas.fire(newPage.canvas);
787-
788-
newPage.addGlyph(rasterizedGlyph);
789-
activePage.fixedRows.push(newPage.currentRow);
782+
// Request the model to be cleared to refresh all texture pages.
783+
this._requestClearModel = true;
784+
this._onAddTextureAtlasCanvas.fire(this._overflowSizePage.canvas);
785+
}
786+
activePage = this._overflowSizePage;
787+
activeRow = this._overflowSizePage.currentRow;
788+
// Move to next row if necessary
789+
if (activeRow.x + rasterizedGlyph.size.x >= activePage.canvas.width) {
790+
activeRow.x = 0;
791+
activeRow.y += activeRow.height;
792+
activeRow.height = 0;
793+
}
790794
break;
791795
}
792796

@@ -800,6 +804,7 @@ export class TextureAtlas implements ITextureAtlas {
800804
if (activePage.currentRow.y + activePage.currentRow.height + rasterizedGlyph.size.y >= activePage.canvas.height) {
801805
// Find the first page with room to create the new row on
802806
let candidatePage: AtlasPage | undefined;
807+
803808
for (const p of this._activePages) {
804809
if (p.currentRow.y + p.currentRow.height + rasterizedGlyph.size.y < p.canvas.height) {
805810
candidatePage = p;

src/browser/renderer/shared/Types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { Event } from 'vs/base/common/event';
1111
export interface ICharAtlasConfig {
1212
customGlyphs: boolean;
1313
devicePixelRatio: number;
14+
deviceMaxTextureSize: number;
1415
letterSpacing: number;
1516
lineHeight: number;
1617
fontSize: number;

0 commit comments

Comments
 (0)