@xterm/addon-webgl 0.20.0-beta.22 → 0.20.0-beta.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/addon-webgl.js +1 -1
- package/lib/addon-webgl.js.map +1 -1
- package/lib/addon-webgl.mjs +5 -31
- package/lib/addon-webgl.mjs.map +4 -4
- package/package.json +4 -4
- package/src/CellColorResolver.ts +5 -2
- package/src/CharAtlasCache.ts +3 -1
- package/src/CursorBlinkStateManager.ts +67 -8
- package/src/DevicePixelObserver.ts +1 -1
- package/src/GlyphRenderer.ts +28 -20
- package/src/RectangleRenderer.ts +8 -7
- package/src/RenderModel.ts +7 -5
- package/src/TextureAtlas.ts +89 -62
- package/src/Types.ts +3 -3
- package/src/WebglAddon.ts +8 -14
- package/src/WebglRenderer.ts +91 -22
- package/src/customGlyphs/CustomGlyphDefinitions.ts +75 -30
- package/src/customGlyphs/CustomGlyphRasterizer.ts +33 -13
- package/src/renderLayer/BaseRenderLayer.ts +1 -1
- package/typings/addon-webgl.d.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/addon-webgl",
|
|
3
|
-
"version": "0.20.0-beta.
|
|
3
|
+
"version": "0.20.0-beta.221",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "The xterm.js authors",
|
|
6
6
|
"url": "https://xtermjs.org/"
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"xterm.js"
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
|
-
"build": "../../node_modules/.bin/
|
|
20
|
+
"build": "../../node_modules/.bin/tsgo -p .",
|
|
21
21
|
"prepackage": "npm run build",
|
|
22
22
|
"package": "../../node_modules/.bin/webpack",
|
|
23
23
|
"prepublishOnly": "npm run package",
|
|
24
24
|
"start": "node ../../demo/start"
|
|
25
25
|
},
|
|
26
|
-
"commit": "
|
|
26
|
+
"commit": "b665f6259abb9877ced1c790f21138d8f1014ab7",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@xterm/xterm": "^6.1.0-beta.
|
|
28
|
+
"@xterm/xterm": "^6.1.0-beta.222"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/src/CellColorResolver.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { ICellData } from 'common/Types';
|
|
|
7
7
|
import { Terminal } from '@xterm/xterm';
|
|
8
8
|
import { rgba } from 'common/Color';
|
|
9
9
|
import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
|
|
10
|
+
import { blockPatternCodepoints } from './customGlyphs/CustomGlyphDefinitions';
|
|
10
11
|
|
|
11
12
|
// Work variables to avoid garbage collection
|
|
12
13
|
let $fg = 0;
|
|
@@ -42,7 +43,7 @@ export class CellColorResolver {
|
|
|
42
43
|
* Resolves colors for the cell, putting the result into the shared {@link result}. This resolves
|
|
43
44
|
* overrides, inverse and selection for the cell which can then be used to feed into the renderer.
|
|
44
45
|
*/
|
|
45
|
-
public resolve(cell: ICellData, x: number, y: number, deviceCellWidth: number): void {
|
|
46
|
+
public resolve(cell: ICellData, x: number, y: number, deviceCellWidth: number, deviceCellHeight: number): void {
|
|
46
47
|
this.result.bg = cell.bg;
|
|
47
48
|
this.result.fg = cell.fg;
|
|
48
49
|
this.result.ext = cell.bg & BgFlags.HAS_EXTENDED ? cell.extended.ext : 0;
|
|
@@ -63,7 +64,9 @@ export class CellColorResolver {
|
|
|
63
64
|
const lineWidth = Math.max(1, Math.floor(this._optionService.rawOptions.fontSize * this._coreBrowserService.dpr / 15));
|
|
64
65
|
$variantOffset = x * deviceCellWidth % (Math.round(lineWidth) * 2);
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
+
if ($variantOffset === 0 && blockPatternCodepoints.has(code)) {
|
|
68
|
+
$variantOffset = ((x * deviceCellWidth) % 2) * 2 + ((y * deviceCellHeight) % 2);
|
|
69
|
+
}
|
|
67
70
|
// Apply decorations on the bottom layer
|
|
68
71
|
this._decorationService.forEachDecorationAtCell(x, y, 'bottom', d => {
|
|
69
72
|
if (d.backgroundColorRGB) {
|
package/src/CharAtlasCache.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { ITerminalOptions, Terminal } from '@xterm/xterm';
|
|
|
8
8
|
import { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
|
9
9
|
import { ICharAtlasConfig, ITextureAtlas } from './Types';
|
|
10
10
|
import { generateConfig, configEquals } from './CharAtlasUtils';
|
|
11
|
+
import type { ILogService } from 'common/services/Services';
|
|
11
12
|
|
|
12
13
|
interface ITextureAtlasCacheEntry {
|
|
13
14
|
atlas: ITextureAtlas;
|
|
@@ -67,8 +68,9 @@ export function acquireTextureAtlas(
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
const core: ITerminal = (terminal as any)._core;
|
|
71
|
+
const logService = (core as any)._logService as ILogService;
|
|
70
72
|
const newEntry: ITextureAtlasCacheEntry = {
|
|
71
|
-
atlas: new TextureAtlas(document, newConfig, core.unicodeService),
|
|
73
|
+
atlas: new TextureAtlas(document, newConfig, core.unicodeService, logService),
|
|
72
74
|
config: newConfig,
|
|
73
75
|
ownedBy: [terminal]
|
|
74
76
|
};
|
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { RendererConstants } from 'browser/renderer/shared/Constants';
|
|
6
7
|
import { ICoreBrowserService } from 'browser/services/Services';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const enum Constants {
|
|
10
|
+
/**
|
|
11
|
+
* The time between cursor blinks.
|
|
12
|
+
*/
|
|
13
|
+
BLINK_INTERVAL = 600,
|
|
14
|
+
}
|
|
12
15
|
|
|
13
16
|
export class CursorBlinkStateManager {
|
|
14
17
|
public isCursorVisible: boolean;
|
|
@@ -16,6 +19,8 @@ export class CursorBlinkStateManager {
|
|
|
16
19
|
private _animationFrame: number | undefined;
|
|
17
20
|
private _blinkStartTimeout: number | undefined;
|
|
18
21
|
private _blinkInterval: number | undefined;
|
|
22
|
+
private _idleTimeout: number | undefined;
|
|
23
|
+
private _isIdlePaused: boolean = false;
|
|
19
24
|
|
|
20
25
|
/**
|
|
21
26
|
* The time at which the animation frame was restarted, this is used on the
|
|
@@ -31,6 +36,7 @@ export class CursorBlinkStateManager {
|
|
|
31
36
|
this.isCursorVisible = true;
|
|
32
37
|
if (this._coreBrowserService.isFocused) {
|
|
33
38
|
this._restartInterval();
|
|
39
|
+
this._resetIdleTimer();
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
|
|
@@ -49,9 +55,16 @@ export class CursorBlinkStateManager {
|
|
|
49
55
|
this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame);
|
|
50
56
|
this._animationFrame = undefined;
|
|
51
57
|
}
|
|
58
|
+
if (this._idleTimeout) {
|
|
59
|
+
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
|
60
|
+
this._idleTimeout = undefined;
|
|
61
|
+
}
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
public restartBlinkAnimation(): void {
|
|
65
|
+
if (this._isIdlePaused) {
|
|
66
|
+
this._resetIdleTimer();
|
|
67
|
+
}
|
|
55
68
|
if (this.isPaused) {
|
|
56
69
|
return;
|
|
57
70
|
}
|
|
@@ -67,7 +80,7 @@ export class CursorBlinkStateManager {
|
|
|
67
80
|
}
|
|
68
81
|
}
|
|
69
82
|
|
|
70
|
-
private _restartInterval(timeToStart: number = BLINK_INTERVAL): void {
|
|
83
|
+
private _restartInterval(timeToStart: number = Constants.BLINK_INTERVAL): void {
|
|
71
84
|
// Clear any existing interval
|
|
72
85
|
if (this._blinkInterval) {
|
|
73
86
|
this._coreBrowserService.window.clearInterval(this._blinkInterval);
|
|
@@ -82,7 +95,7 @@ export class CursorBlinkStateManager {
|
|
|
82
95
|
// Check if another animation restart was requested while this was being
|
|
83
96
|
// started
|
|
84
97
|
if (this._animationTimeRestarted) {
|
|
85
|
-
const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
|
|
98
|
+
const time = Constants.BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
|
|
86
99
|
this._animationTimeRestarted = undefined;
|
|
87
100
|
if (time > 0) {
|
|
88
101
|
this._restartInterval(time);
|
|
@@ -103,7 +116,7 @@ export class CursorBlinkStateManager {
|
|
|
103
116
|
if (this._animationTimeRestarted) {
|
|
104
117
|
// calc time diff
|
|
105
118
|
// Make restart interval do a setTimeout initially?
|
|
106
|
-
const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
|
|
119
|
+
const time = Constants.BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);
|
|
107
120
|
this._animationTimeRestarted = undefined;
|
|
108
121
|
this._restartInterval(time);
|
|
109
122
|
return;
|
|
@@ -115,12 +128,13 @@ export class CursorBlinkStateManager {
|
|
|
115
128
|
this._renderCallback();
|
|
116
129
|
this._animationFrame = undefined;
|
|
117
130
|
});
|
|
118
|
-
}, BLINK_INTERVAL);
|
|
131
|
+
}, Constants.BLINK_INTERVAL);
|
|
119
132
|
}, timeToStart);
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
public pause(): void {
|
|
123
136
|
this.isCursorVisible = true;
|
|
137
|
+
this._isIdlePaused = false;
|
|
124
138
|
if (this._blinkInterval) {
|
|
125
139
|
this._coreBrowserService.window.clearInterval(this._blinkInterval);
|
|
126
140
|
this._blinkInterval = undefined;
|
|
@@ -133,6 +147,10 @@ export class CursorBlinkStateManager {
|
|
|
133
147
|
this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame);
|
|
134
148
|
this._animationFrame = undefined;
|
|
135
149
|
}
|
|
150
|
+
if (this._idleTimeout) {
|
|
151
|
+
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
|
152
|
+
this._idleTimeout = undefined;
|
|
153
|
+
}
|
|
136
154
|
}
|
|
137
155
|
|
|
138
156
|
public resume(): void {
|
|
@@ -141,6 +159,47 @@ export class CursorBlinkStateManager {
|
|
|
141
159
|
|
|
142
160
|
this._animationTimeRestarted = undefined;
|
|
143
161
|
this._restartInterval();
|
|
162
|
+
this._resetIdleTimer();
|
|
144
163
|
this.restartBlinkAnimation();
|
|
145
164
|
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Resets the idle timer. If the terminal is idle for the idle timeout period,
|
|
168
|
+
* the cursor blinking will stop.
|
|
169
|
+
*/
|
|
170
|
+
private _resetIdleTimer(): void {
|
|
171
|
+
this._isIdlePaused = false;
|
|
172
|
+
if (this._idleTimeout) {
|
|
173
|
+
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
|
174
|
+
}
|
|
175
|
+
this._idleTimeout = this._coreBrowserService.window.setTimeout(() => {
|
|
176
|
+
this._stopBlinkingDueToIdle();
|
|
177
|
+
}, RendererConstants.CURSOR_BLINK_IDLE_TIMEOUT);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Stops cursor blinking due to idle timeout.
|
|
182
|
+
*/
|
|
183
|
+
private _stopBlinkingDueToIdle(): void {
|
|
184
|
+
// Make cursor visible and stop blinking
|
|
185
|
+
this.isCursorVisible = true;
|
|
186
|
+
this._isIdlePaused = true;
|
|
187
|
+
if (this._blinkInterval) {
|
|
188
|
+
this._coreBrowserService.window.clearInterval(this._blinkInterval);
|
|
189
|
+
this._blinkInterval = undefined;
|
|
190
|
+
}
|
|
191
|
+
if (this._blinkStartTimeout) {
|
|
192
|
+
this._coreBrowserService.window.clearTimeout(this._blinkStartTimeout);
|
|
193
|
+
this._blinkStartTimeout = undefined;
|
|
194
|
+
}
|
|
195
|
+
if (this._animationFrame) {
|
|
196
|
+
this._coreBrowserService.window.cancelAnimationFrame(this._animationFrame);
|
|
197
|
+
this._animationFrame = undefined;
|
|
198
|
+
}
|
|
199
|
+
// Clear the idle timeout as we've already acted on it
|
|
200
|
+
this._coreBrowserService.window.clearTimeout(this._idleTimeout);
|
|
201
|
+
this._idleTimeout = undefined;
|
|
202
|
+
// Trigger a render to show the cursor in its final visible state
|
|
203
|
+
this._renderCallback();
|
|
204
|
+
}
|
|
146
205
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { toDisposable, IDisposable } from '
|
|
6
|
+
import { toDisposable, IDisposable } from 'common/Lifecycle';
|
|
7
7
|
|
|
8
8
|
export function observeDevicePixelDimensions(element: HTMLElement, parentWindow: Window & typeof globalThis, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable {
|
|
9
9
|
// Observe any resizes to the element and extract the actual pixel size of the element if the
|
package/src/GlyphRenderer.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { TextureAtlas } from './TextureAtlas';
|
|
6
6
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
|
7
7
|
import { NULL_CELL_CODE } from 'common/buffer/Constants';
|
|
8
|
-
import { Disposable, toDisposable } from '
|
|
8
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
9
9
|
import { Terminal } from '@xterm/xterm';
|
|
10
10
|
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject, type IRasterizedGlyph, type ITextureAtlas } from './Types';
|
|
11
11
|
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
|
|
@@ -78,9 +78,11 @@ void main() {
|
|
|
78
78
|
}`);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const enum Constants {
|
|
82
|
+
INDICES_PER_CELL = 11,
|
|
83
|
+
BYTES_PER_CELL = INDICES_PER_CELL * 4/* Float32Array.BYTES_PER_ELEMENT */,
|
|
84
|
+
CELL_POSITION_INDICES = 2
|
|
85
|
+
}
|
|
84
86
|
|
|
85
87
|
// Work variables to avoid garbage collection
|
|
86
88
|
let $i = 0;
|
|
@@ -160,22 +162,22 @@ export class GlyphRenderer extends Disposable {
|
|
|
160
162
|
this._register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
|
|
161
163
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
|
|
162
164
|
gl.enableVertexAttribArray(VertexAttribLocations.OFFSET);
|
|
163
|
-
gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0);
|
|
165
|
+
gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, Constants.BYTES_PER_CELL, 0);
|
|
164
166
|
gl.vertexAttribDivisor(VertexAttribLocations.OFFSET, 1);
|
|
165
167
|
gl.enableVertexAttribArray(VertexAttribLocations.SIZE);
|
|
166
|
-
gl.vertexAttribPointer(VertexAttribLocations.SIZE, 2, gl.FLOAT, false, BYTES_PER_CELL, 2 * Float32Array.BYTES_PER_ELEMENT);
|
|
168
|
+
gl.vertexAttribPointer(VertexAttribLocations.SIZE, 2, gl.FLOAT, false, Constants.BYTES_PER_CELL, 2 * Float32Array.BYTES_PER_ELEMENT);
|
|
167
169
|
gl.vertexAttribDivisor(VertexAttribLocations.SIZE, 1);
|
|
168
170
|
gl.enableVertexAttribArray(VertexAttribLocations.TEXPAGE);
|
|
169
|
-
gl.vertexAttribPointer(VertexAttribLocations.TEXPAGE, 1, gl.FLOAT, false, BYTES_PER_CELL, 4 * Float32Array.BYTES_PER_ELEMENT);
|
|
171
|
+
gl.vertexAttribPointer(VertexAttribLocations.TEXPAGE, 1, gl.FLOAT, false, Constants.BYTES_PER_CELL, 4 * Float32Array.BYTES_PER_ELEMENT);
|
|
170
172
|
gl.vertexAttribDivisor(VertexAttribLocations.TEXPAGE, 1);
|
|
171
173
|
gl.enableVertexAttribArray(VertexAttribLocations.TEXCOORD);
|
|
172
|
-
gl.vertexAttribPointer(VertexAttribLocations.TEXCOORD, 2, gl.FLOAT, false, BYTES_PER_CELL, 5 * Float32Array.BYTES_PER_ELEMENT);
|
|
174
|
+
gl.vertexAttribPointer(VertexAttribLocations.TEXCOORD, 2, gl.FLOAT, false, Constants.BYTES_PER_CELL, 5 * Float32Array.BYTES_PER_ELEMENT);
|
|
173
175
|
gl.vertexAttribDivisor(VertexAttribLocations.TEXCOORD, 1);
|
|
174
176
|
gl.enableVertexAttribArray(VertexAttribLocations.TEXSIZE);
|
|
175
|
-
gl.vertexAttribPointer(VertexAttribLocations.TEXSIZE, 2, gl.FLOAT, false, BYTES_PER_CELL, 7 * Float32Array.BYTES_PER_ELEMENT);
|
|
177
|
+
gl.vertexAttribPointer(VertexAttribLocations.TEXSIZE, 2, gl.FLOAT, false, Constants.BYTES_PER_CELL, 7 * Float32Array.BYTES_PER_ELEMENT);
|
|
176
178
|
gl.vertexAttribDivisor(VertexAttribLocations.TEXSIZE, 1);
|
|
177
179
|
gl.enableVertexAttribArray(VertexAttribLocations.CELL_POSITION);
|
|
178
|
-
gl.vertexAttribPointer(VertexAttribLocations.CELL_POSITION, 2, gl.FLOAT, false, BYTES_PER_CELL, 9 * Float32Array.BYTES_PER_ELEMENT);
|
|
180
|
+
gl.vertexAttribPointer(VertexAttribLocations.CELL_POSITION, 2, gl.FLOAT, false, Constants.BYTES_PER_CELL, 9 * Float32Array.BYTES_PER_ELEMENT);
|
|
179
181
|
gl.vertexAttribDivisor(VertexAttribLocations.CELL_POSITION, 1);
|
|
180
182
|
|
|
181
183
|
// Setup static uniforms
|
|
@@ -222,12 +224,12 @@ export class GlyphRenderer extends Disposable {
|
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
private _updateCell(array: Float32Array, x: number, y: number, code: number | undefined, bg: number, fg: number, ext: number, chars: string, width: number, lastBg: number): void {
|
|
225
|
-
$i = (y * this._terminal.cols + x) * INDICES_PER_CELL;
|
|
227
|
+
$i = (y * this._terminal.cols + x) * Constants.INDICES_PER_CELL;
|
|
226
228
|
|
|
227
229
|
// Exit early if this is a null character, allow space character to continue as it may have
|
|
228
230
|
// underline/strikethrough styles
|
|
229
231
|
if (code === NULL_CELL_CODE || code === undefined/* This is used for the right side of wide chars */) {
|
|
230
|
-
array.fill(0, $i, $i + INDICES_PER_CELL - 1 - CELL_POSITION_INDICES);
|
|
232
|
+
array.fill(0, $i, $i + Constants.INDICES_PER_CELL - 1 - Constants.CELL_POSITION_INDICES);
|
|
231
233
|
return;
|
|
232
234
|
}
|
|
233
235
|
|
|
@@ -288,7 +290,7 @@ export class GlyphRenderer extends Disposable {
|
|
|
288
290
|
|
|
289
291
|
public clear(): void {
|
|
290
292
|
const terminal = this._terminal;
|
|
291
|
-
const newCount = terminal.cols * terminal.rows * INDICES_PER_CELL;
|
|
293
|
+
const newCount = terminal.cols * terminal.rows * Constants.INDICES_PER_CELL;
|
|
292
294
|
|
|
293
295
|
// Clear vertices
|
|
294
296
|
if (this._vertices.count !== newCount) {
|
|
@@ -310,7 +312,7 @@ export class GlyphRenderer extends Disposable {
|
|
|
310
312
|
for (let x = 0; x < terminal.cols; x++) {
|
|
311
313
|
this._vertices.attributes[i + 9] = x / terminal.cols;
|
|
312
314
|
this._vertices.attributes[i + 10] = y / terminal.rows;
|
|
313
|
-
i += INDICES_PER_CELL;
|
|
315
|
+
i += Constants.INDICES_PER_CELL;
|
|
314
316
|
}
|
|
315
317
|
}
|
|
316
318
|
}
|
|
@@ -318,8 +320,8 @@ export class GlyphRenderer extends Disposable {
|
|
|
318
320
|
public handleResize(): void {
|
|
319
321
|
const gl = this._gl;
|
|
320
322
|
gl.useProgram(this._program);
|
|
321
|
-
gl.viewport(0, 0,
|
|
322
|
-
gl.uniform2f(this._resolutionLocation,
|
|
323
|
+
gl.viewport(0, 0, this._dimensions.device.canvas.width, this._dimensions.device.canvas.height);
|
|
324
|
+
gl.uniform2f(this._resolutionLocation, this._dimensions.device.canvas.width, this._dimensions.device.canvas.height);
|
|
323
325
|
this.clear();
|
|
324
326
|
}
|
|
325
327
|
|
|
@@ -346,8 +348,8 @@ export class GlyphRenderer extends Disposable {
|
|
|
346
348
|
// - So we don't send vertices for all the line-ending whitespace to the GPU
|
|
347
349
|
let bufferLength = 0;
|
|
348
350
|
for (let y = 0; y < renderModel.lineLengths.length; y++) {
|
|
349
|
-
const si = y * this._terminal.cols * INDICES_PER_CELL;
|
|
350
|
-
const sub = this._vertices.attributes.subarray(si, si + renderModel.lineLengths[y] * INDICES_PER_CELL);
|
|
351
|
+
const si = y * this._terminal.cols * Constants.INDICES_PER_CELL;
|
|
352
|
+
const sub = this._vertices.attributes.subarray(si, si + renderModel.lineLengths[y] * Constants.INDICES_PER_CELL);
|
|
351
353
|
activeBuffer.set(sub, bufferLength);
|
|
352
354
|
bufferLength += sub.length;
|
|
353
355
|
}
|
|
@@ -356,7 +358,9 @@ export class GlyphRenderer extends Disposable {
|
|
|
356
358
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
|
|
357
359
|
gl.bufferData(gl.ARRAY_BUFFER, activeBuffer.subarray(0, bufferLength), gl.STREAM_DRAW);
|
|
358
360
|
|
|
359
|
-
// Bind the atlas page texture if they have changed
|
|
361
|
+
// Bind the atlas page texture if they have changed. AtlasPage.version is globally
|
|
362
|
+
// monotonic, so a page object swap at the same index (which happens after a page merge)
|
|
363
|
+
// is detected by the same comparison.
|
|
360
364
|
for (let i = 0; i < this._atlas.pages.length; i++) {
|
|
361
365
|
if (this._atlas.pages[i].version !== this._atlasTextures[i].version) {
|
|
362
366
|
this._bindAtlasPageTexture(gl, this._atlas, i);
|
|
@@ -364,11 +368,15 @@ export class GlyphRenderer extends Disposable {
|
|
|
364
368
|
}
|
|
365
369
|
|
|
366
370
|
// Draw the viewport
|
|
367
|
-
gl.drawElementsInstanced(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_BYTE, 0, bufferLength / INDICES_PER_CELL);
|
|
371
|
+
gl.drawElementsInstanced(gl.TRIANGLE_STRIP, 4, gl.UNSIGNED_BYTE, 0, bufferLength / Constants.INDICES_PER_CELL);
|
|
368
372
|
}
|
|
369
373
|
|
|
370
374
|
public setAtlas(atlas: ITextureAtlas): void {
|
|
371
375
|
this._atlas = atlas;
|
|
376
|
+
this.invalidateAtlasTextures();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public invalidateAtlasTextures(): void {
|
|
372
380
|
for (const glTexture of this._atlasTextures) {
|
|
373
381
|
glTexture.version = -1;
|
|
374
382
|
}
|
package/src/RectangleRenderer.ts
CHANGED
|
@@ -7,10 +7,10 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
|
|
7
7
|
import { IThemeService } from 'browser/services/Services';
|
|
8
8
|
import { ReadonlyColorSet } from 'browser/Types';
|
|
9
9
|
import { Attributes, FgFlags } from 'common/buffer/Constants';
|
|
10
|
-
import { Disposable, toDisposable } from '
|
|
10
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
11
11
|
import { IColor } from 'common/Types';
|
|
12
12
|
import { Terminal } from '@xterm/xterm';
|
|
13
|
-
import {
|
|
13
|
+
import { RenderModelConstants } from './RenderModel';
|
|
14
14
|
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
|
|
15
15
|
import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils';
|
|
16
16
|
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
|
@@ -217,9 +217,9 @@ export class RectangleRenderer extends Disposable {
|
|
|
217
217
|
currentFg = 0;
|
|
218
218
|
currentInverse = false;
|
|
219
219
|
for (x = 0; x < terminal.cols; x++) {
|
|
220
|
-
modelIndex = ((y * terminal.cols) + x) *
|
|
221
|
-
bg = model.cells[modelIndex +
|
|
222
|
-
fg = model.cells[modelIndex +
|
|
220
|
+
modelIndex = ((y * terminal.cols) + x) * RenderModelConstants.INDICIES_PER_CELL;
|
|
221
|
+
bg = model.cells[modelIndex + RenderModelConstants.BG_OFFSET];
|
|
222
|
+
fg = model.cells[modelIndex + RenderModelConstants.FG_OFFSET];
|
|
223
223
|
inverse = !!(fg & FgFlags.INVERSE);
|
|
224
224
|
if (bg !== currentBg || (fg !== currentFg && (currentInverse || inverse))) {
|
|
225
225
|
// A rectangle needs to be drawn if going from non-default to another color
|
|
@@ -336,8 +336,9 @@ export class RectangleRenderer extends Disposable {
|
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
if (vertices.attributes.length < offset +
|
|
340
|
-
|
|
339
|
+
if (vertices.attributes.length < offset + INDICES_PER_RECTANGLE) {
|
|
340
|
+
// +1 for the viewport-clear rectangle at offset 0.
|
|
341
|
+
vertices.attributes = expandFloat32Array(vertices.attributes, (this._terminal.rows * this._terminal.cols + 1) * INDICES_PER_RECTANGLE);
|
|
341
342
|
}
|
|
342
343
|
$x1 = startX * this._dimensions.device.cell.width;
|
|
343
344
|
$y1 = y * this._dimensions.device.cell.height;
|
package/src/RenderModel.ts
CHANGED
|
@@ -7,10 +7,12 @@ import { ICursorRenderModel, IRenderModel } from './Types';
|
|
|
7
7
|
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
|
8
8
|
import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel';
|
|
9
9
|
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
export const enum RenderModelConstants {
|
|
11
|
+
INDICIES_PER_CELL = 4,
|
|
12
|
+
BG_OFFSET = 1,
|
|
13
|
+
FG_OFFSET = 2,
|
|
14
|
+
EXT_OFFSET = 3
|
|
15
|
+
}
|
|
14
16
|
|
|
15
17
|
export const COMBINED_CHAR_BIT_MASK = 0x80000000;
|
|
16
18
|
|
|
@@ -27,7 +29,7 @@ export class RenderModel implements IRenderModel {
|
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
public resize(cols: number, rows: number): void {
|
|
30
|
-
const indexCount = cols * rows *
|
|
32
|
+
const indexCount = cols * rows * RenderModelConstants.INDICIES_PER_CELL;
|
|
31
33
|
if (indexCount !== this.cells.length) {
|
|
32
34
|
this.cells = new Uint32Array(indexCount);
|
|
33
35
|
this.lineLengths = new Uint32Array(rows);
|