Clear texture atlas on zoom change and rasterizer on config change
Fixes #234213
This commit is contained in:
Родитель
1dd8c77ac7
Коммит
f154193b01
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { getActiveWindow } from '../../../base/browser/dom.js';
|
||||
import { BugIndicatingError } from '../../../base/common/errors.js';
|
||||
import { MandatoryMutableDisposable } from '../../../base/common/lifecycle.js';
|
||||
import { EditorOption } from '../../common/config/editorOptions.js';
|
||||
import { CursorColumns } from '../../common/core/cursorColumns.js';
|
||||
import type { IViewLineTokens } from '../../common/tokens/lineTokens.js';
|
||||
|
@ -38,13 +39,17 @@ const enum CellBufferInfo {
|
|||
TextureIndex = 5,
|
||||
}
|
||||
|
||||
type QueuedBufferEvent = ViewLinesDeletedEvent | ViewZonesChangedEvent;
|
||||
type QueuedBufferEvent = (
|
||||
ViewConfigurationChangedEvent |
|
||||
ViewLinesDeletedEvent |
|
||||
ViewZonesChangedEvent
|
||||
);
|
||||
|
||||
export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRenderStrategy {
|
||||
|
||||
readonly wgsl: string = fullFileRenderStrategyWgsl;
|
||||
|
||||
private readonly _glyphRasterizer: GlyphRasterizer;
|
||||
private readonly _glyphRasterizer: MandatoryMutableDisposable<GlyphRasterizer>;
|
||||
|
||||
private _cellBindBuffer!: GPUBuffer;
|
||||
|
||||
|
@ -81,11 +86,10 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend
|
|||
|
||||
this._context.addEventHandler(this);
|
||||
|
||||
// TODO: Detect when lines have been tokenized and clear _upToDateLines
|
||||
const fontFamily = this._context.configuration.options.get(EditorOption.fontFamily);
|
||||
const fontSize = this._context.configuration.options.get(EditorOption.fontSize);
|
||||
|
||||
this._glyphRasterizer = this._register(new GlyphRasterizer(fontSize, fontFamily));
|
||||
this._glyphRasterizer = this._register(new MandatoryMutableDisposable(new GlyphRasterizer(fontSize, fontFamily)));
|
||||
|
||||
const bufferSize = this._viewGpuContext.maxGpuLines * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell * Float32Array.BYTES_PER_ELEMENT;
|
||||
this._cellBindBuffer = this._register(GPULifecycle.createBuffer(this._device, {
|
||||
|
@ -112,6 +116,17 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend
|
|||
public override onConfigurationChanged(e: ViewConfigurationChangedEvent): boolean {
|
||||
this._upToDateLines[0].clear();
|
||||
this._upToDateLines[1].clear();
|
||||
this._queueBufferUpdate(e);
|
||||
|
||||
const fontFamily = this._context.configuration.options.get(EditorOption.fontFamily);
|
||||
const fontSize = this._context.configuration.options.get(EditorOption.fontSize);
|
||||
if (
|
||||
this._glyphRasterizer.value.fontFamily !== fontFamily ||
|
||||
this._glyphRasterizer.value.fontSize !== fontSize
|
||||
) {
|
||||
this._glyphRasterizer.value = new GlyphRasterizer(fontSize, fontFamily);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -245,6 +260,15 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend
|
|||
const e = queuedBufferUpdates.shift()!;
|
||||
|
||||
switch (e.type) {
|
||||
case ViewEventType.ViewConfigurationChanged: {
|
||||
// TODO: Refine the cases for when we throw away all the data
|
||||
cellBuffer.fill(0);
|
||||
|
||||
dirtyLineStart = 1;
|
||||
dirtyLineEnd = this._finalRenderedLine;
|
||||
this._finalRenderedLine = 0;
|
||||
break;
|
||||
}
|
||||
case ViewEventType.ViewLinesDeleted: {
|
||||
// Shift content below deleted line up
|
||||
const deletedLineContentStartIndex = (e.fromLineNumber - 1) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell;
|
||||
|
@ -324,7 +348,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend
|
|||
continue;
|
||||
}
|
||||
|
||||
glyph = this._viewGpuContext.atlas.getGlyph(this._glyphRasterizer, chars, tokenMetadata);
|
||||
glyph = this._viewGpuContext.atlas.getGlyph(this._glyphRasterizer.value, chars, tokenMetadata);
|
||||
|
||||
// TODO: Support non-standard character widths
|
||||
absoluteOffsetX = Math.round((x + xOffset) * viewLineOptions.spaceWidth * dpr);
|
||||
|
|
|
@ -18,7 +18,7 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer {
|
|||
|
||||
@memoize
|
||||
public get cacheKey(): string {
|
||||
return `${this._fontFamily}_${this._fontSize}px`;
|
||||
return `${this.fontFamily}_${this.fontSize}px`;
|
||||
}
|
||||
|
||||
private _canvas: OffscreenCanvas;
|
||||
|
@ -40,12 +40,12 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer {
|
|||
private _workGlyphConfig: { chars: string | undefined; metadata: number } = { chars: undefined, metadata: 0 };
|
||||
|
||||
constructor(
|
||||
private readonly _fontSize: number,
|
||||
private readonly _fontFamily: string,
|
||||
readonly fontSize: number,
|
||||
readonly fontFamily: string,
|
||||
) {
|
||||
super();
|
||||
|
||||
const devicePixelFontSize = Math.ceil(this._fontSize * getActiveWindow().devicePixelRatio);
|
||||
const devicePixelFontSize = Math.ceil(this.fontSize * getActiveWindow().devicePixelRatio);
|
||||
this._canvas = new OffscreenCanvas(devicePixelFontSize * 3, devicePixelFontSize * 3);
|
||||
this._ctx = ensureNonNullable(this._canvas.getContext('2d', {
|
||||
willReadFrequently: true
|
||||
|
@ -87,7 +87,7 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer {
|
|||
metadata: number,
|
||||
colorMap: string[],
|
||||
): Readonly<IRasterizedGlyph> {
|
||||
const devicePixelFontSize = Math.ceil(this._fontSize * getActiveWindow().devicePixelRatio);
|
||||
const devicePixelFontSize = Math.ceil(this.fontSize * getActiveWindow().devicePixelRatio);
|
||||
const canvasDim = devicePixelFontSize * 3;
|
||||
if (this._canvas.width !== canvasDim) {
|
||||
this._canvas.width = canvasDim;
|
||||
|
@ -105,7 +105,7 @@ export class GlyphRasterizer extends Disposable implements IGlyphRasterizer {
|
|||
if (fontStyle & FontStyle.Bold) {
|
||||
fontSb.appendString('bold ');
|
||||
}
|
||||
fontSb.appendString(`${devicePixelFontSize}px ${this._fontFamily}`);
|
||||
fontSb.appendString(`${devicePixelFontSize}px ${this.fontFamily}`);
|
||||
this._ctx.font = fontSb.build();
|
||||
|
||||
// TODO: Support FontStyle.Strikethrough and FontStyle.Underline text decorations, these
|
||||
|
|
|
@ -106,7 +106,6 @@ export class ViewGpuContext extends Disposable {
|
|||
this.device.then(device => {
|
||||
if (!ViewGpuContext._atlas) {
|
||||
ViewGpuContext._atlas = this._instantiationService.createInstance(TextureAtlas, device.limits.maxTextureDimension2D, undefined);
|
||||
runOnChange(this.devicePixelRatio, () => ViewGpuContext.atlas.clear());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -117,6 +116,7 @@ export class ViewGpuContext extends Disposable {
|
|||
dprObs.set(getActiveWindow().devicePixelRatio, undefined);
|
||||
}));
|
||||
this.devicePixelRatio = dprObs;
|
||||
this._register(runOnChange(this.devicePixelRatio, () => ViewGpuContext.atlas?.clear()));
|
||||
|
||||
const canvasDevicePixelDimensions = observableValue(this, { width: this.canvas.domNode.width, height: this.canvas.domNode.height });
|
||||
this._register(observeDevicePixelDimensions(
|
||||
|
|
Загрузка…
Ссылка в новой задаче