diff --git a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts index 0a681d2fe84..89707be51d4 100644 --- a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts +++ b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts @@ -9,7 +9,7 @@ import { EditorOption } from '../../common/config/editorOptions.js'; import { CursorColumns } from '../../common/core/cursorColumns.js'; import type { IViewLineTokens } from '../../common/tokens/lineTokens.js'; import { ViewEventHandler } from '../../common/viewEventHandler.js'; -import type { ViewLinesDeletedEvent, ViewScrollChangedEvent } from '../../common/viewEvents.js'; +import type { ViewConfigurationChangedEvent, ViewLinesChangedEvent, ViewLinesDeletedEvent, ViewLinesInsertedEvent, ViewScrollChangedEvent, ViewTokensChangedEvent } from '../../common/viewEvents.js'; import type { ViewportData } from '../../common/viewLayout/viewLinesViewportData.js'; import type { ViewLineRenderingData } from '../../common/viewModel.js'; import type { ViewContext } from '../../common/viewModel/viewContext.js'; @@ -107,8 +107,66 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend // #region Event handlers + public override onConfigurationChanged(e: ViewConfigurationChangedEvent): boolean { + this._upToDateLines[0].clear(); + this._upToDateLines[1].clear(); + return true; + } + + public override onTokensChanged(e: ViewTokensChangedEvent): boolean { + // TODO: This currently fires for the entire viewport whenever scrolling stops + // https://github.com/microsoft/vscode/issues/233942 + for (const range of e.ranges) { + for (let i = range.fromLineNumber; i <= range.toLineNumber; i++) { + this._upToDateLines[0].delete(i); + this._upToDateLines[1].delete(i); + } + } + return true; + } + public override onLinesDeleted(e: ViewLinesDeletedEvent): boolean { + // TODO: This currently invalidates everything after the deleted line, it could shift the + // line data up to retain some up to date lines + // TODO: This does not invalidate lines that are no longer in the file + for (const i of [0, 1]) { + const upToDateLines = this._upToDateLines[i]; + const lines = Array.from(upToDateLines); + for (const upToDateLine of lines) { + if (upToDateLine > e.fromLineNumber) { + upToDateLines.delete(upToDateLine); + } + } + } + + // Queue updates that need to happen on the active buffer, not just the cache. This is + // deferred since the active buffer could be locked by the GPU which would block the main + // thread. this._queueBufferUpdate(e); + + return true; + } + + public override onLinesInserted(e: ViewLinesInsertedEvent): boolean { + // TODO: This currently invalidates everything after the deleted line, it could shift the + // line data up to retain some up to date lines + for (const i of [0, 1]) { + const upToDateLines = this._upToDateLines[i]; + const lines = Array.from(upToDateLines); + for (const upToDateLine of lines) { + if (upToDateLine > e.fromLineNumber) { + upToDateLines.delete(upToDateLine); + } + } + } + return true; + } + + public override onLinesChanged(e: ViewLinesChangedEvent): boolean { + for (let i = e.fromLineNumber; i < e.fromLineNumber + e.count; i++) { + this._upToDateLines[0].delete(i); + this._upToDateLines[1].delete(i); + } return true; } @@ -201,10 +259,10 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend continue; } - // TODO: Update on dirty lines; is this known by line before rendering? - // if (upToDateLines.has(y)) { - // continue; - // } + // Skip updating the line if it's already up to date + if (upToDateLines.has(y)) { + continue; + } dirtyLineStart = Math.min(dirtyLineStart, y); dirtyLineEnd = Math.max(dirtyLineEnd, y); diff --git a/src/vs/editor/browser/gpu/gpu.ts b/src/vs/editor/browser/gpu/gpu.ts index 02506309202..8d965fcc5aa 100644 --- a/src/vs/editor/browser/gpu/gpu.ts +++ b/src/vs/editor/browser/gpu/gpu.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import type { ViewLinesDeletedEvent } from '../../common/viewEvents.js'; +import type { ViewConfigurationChangedEvent, ViewLinesChangedEvent, ViewLinesDeletedEvent, ViewLinesInsertedEvent, ViewScrollChangedEvent, ViewTokensChangedEvent } from '../../common/viewEvents.js'; import type { ViewportData } from '../../common/viewLayout/viewLinesViewportData.js'; import type { ViewLineOptions } from '../viewParts/viewLines/viewLineOptions.js'; @@ -22,7 +22,12 @@ export interface IGpuRenderStrategy { readonly wgsl: string; readonly bindGroupEntries: GPUBindGroupEntry[]; - onLinesDeleted(e: ViewLinesDeletedEvent): void; + onLinesDeleted(e: ViewLinesDeletedEvent): boolean; + onConfigurationChanged(e: ViewConfigurationChangedEvent): boolean; + onTokensChanged(e: ViewTokensChangedEvent): boolean; + onLinesInserted(e: ViewLinesInsertedEvent): boolean; + onLinesChanged(e: ViewLinesChangedEvent): boolean; + onScrollChanged(e?: ViewScrollChangedEvent): boolean; /** * Resets the render strategy, clearing all data and setting up for a new frame. diff --git a/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts b/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts index 2edd6003d4a..c4d8c0400d2 100644 --- a/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts +++ b/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts @@ -386,6 +386,7 @@ export class ViewLinesGpu extends ViewPart implements IViewLines { override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { return true; } override onFlushed(e: viewEvents.ViewFlushedEvent): boolean { return true; } override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean { return true; } + override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean { return true; } override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean { return true; } override onRevealRangeRequest(e: viewEvents.ViewRevealRangeRequestEvent): boolean { return true; } override onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean { return true; } @@ -396,10 +397,6 @@ export class ViewLinesGpu extends ViewPart implements IViewLines { this._contentLeftObs.set(this._context.configuration.options.get(EditorOption.layoutInfo).contentLeft, undefined); return true; } - override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean { - this._renderStrategy.onLinesDeleted(e); - return true; - } // #endregion