mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
Faster minimap character rendering
This commit is contained in:
parent
8c92d305bd
commit
9c856228a9
|
@ -34,6 +34,10 @@ set ELECTRON_ENABLE_LOGGING=1
|
|||
set ELECTRON_ENABLE_STACK_DUMPING=1
|
||||
|
||||
:: Launch Code
|
||||
|
||||
:: Use the following to get v8 tracing:
|
||||
:: %CODE% --js-flags="--trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces" . %*
|
||||
|
||||
%CODE% . %*
|
||||
popd
|
||||
|
||||
|
|
|
@ -14,13 +14,14 @@ import { ViewContext } from 'vs/editor/common/view/viewContext';
|
|||
import { IRenderingContext, IRestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
|
||||
import { /*createMinimapCharRenderer,*/ createMinimapCharRenderer2 } from 'vs/editor/common/view/runtimeMinimapCharRenderer';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { MinimapColors, MinimapTokensColorTracker, Constants } from 'vs/editor/common/view/minimapCharRenderer';
|
||||
import { ParsedColor, MinimapColors, MinimapTokensColorTracker, Constants } from 'vs/editor/common/view/minimapCharRenderer';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { MinimapLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ColorId } from 'vs/editor/common/modes';
|
||||
|
||||
// let charRenderer = createMinimapCharRenderer();
|
||||
let charRenderer2 = createMinimapCharRenderer2();
|
||||
let charRenderer2 = createMinimapCharRenderer2(); // TODO@minimap
|
||||
|
||||
// interface IWidgetData {
|
||||
// widget: IOverlayWidget;
|
||||
|
@ -177,7 +178,7 @@ export class Minimap extends ViewPart {
|
|||
|
||||
public render(ctx: IRestrictedRenderingContext): void {
|
||||
let pixelRatio = browser.getPixelRatio();
|
||||
console.log(pixelRatio);
|
||||
// console.log(pixelRatio);
|
||||
const WIDTH = pixelRatio * this._minimapWidth;
|
||||
const HEIGHT = pixelRatio * this._minimapHeight;
|
||||
this.domNode.width = WIDTH;
|
||||
|
@ -195,7 +196,7 @@ export class Minimap extends ViewPart {
|
|||
// 8 * 4 * lineLen
|
||||
// );
|
||||
|
||||
let start = performance.now();
|
||||
// let start = performance.now();
|
||||
// console.profile();
|
||||
|
||||
let ctx2 = this.domNode.getContext('2d');
|
||||
|
@ -206,7 +207,8 @@ export class Minimap extends ViewPart {
|
|||
let colorTracker = MinimapTokensColorTracker.getInstance();
|
||||
let colors = colorTracker.getColorMaps();
|
||||
|
||||
let background = colors.getBackgroundColor();
|
||||
let background = colors.getColor(ColorId.DefaultBackground);
|
||||
// getBackgroundColor();
|
||||
let backgroundR = background.r;
|
||||
let backgroundG = background.g;
|
||||
let backgroundB = background.b;
|
||||
|
@ -222,18 +224,19 @@ export class Minimap extends ViewPart {
|
|||
}
|
||||
}
|
||||
|
||||
let data: MinimapLineRenderingData[] = [];
|
||||
for (let lineIndex = 0; lineIndex < lineCount; lineIndex++) {
|
||||
let data = this._context.model.getMinimapLineRenderingData(lineIndex + 1);
|
||||
// let length = Math.min(data.content.length, lineLen);
|
||||
|
||||
let dy = lineIndex * Constants.x2_CHAR_HEIGHT;
|
||||
|
||||
Minimap._render2xLine(imageData, colors, dy, this._viewportColumn, data);
|
||||
|
||||
|
||||
// break;
|
||||
data[lineIndex] = this._context.model.getMinimapLineRenderingData(lineIndex + 1);
|
||||
}
|
||||
|
||||
let start2 = performance.now();
|
||||
for (let lineIndex = 0; lineIndex < lineCount; lineIndex++) {
|
||||
let dy = lineIndex * Constants.x2_CHAR_HEIGHT;
|
||||
Minimap._x2RenderLine(imageData, background, colors, dy, data[lineIndex]);
|
||||
}
|
||||
let end2 = performance.now();
|
||||
console.log(`INNER LOOP TOOK ${end2 - start2} ms.`);
|
||||
|
||||
// console.log(imageData.data);
|
||||
// ctx2.strokeStyle = '#000';
|
||||
// for (i = 0; i <)
|
||||
|
@ -242,10 +245,8 @@ export class Minimap extends ViewPart {
|
|||
|
||||
// console.profileEnd();
|
||||
|
||||
let end = performance.now();
|
||||
|
||||
|
||||
console.log('TOOK ' + (end - start) + 'ms.');
|
||||
// let end = performance.now();
|
||||
// console.log('TOOK ' + (end - start) + 'ms.');
|
||||
|
||||
// let data = this._context.model.getViewLineRenderingData(null, 1);
|
||||
|
||||
|
@ -260,11 +261,11 @@ export class Minimap extends ViewPart {
|
|||
// }
|
||||
}
|
||||
|
||||
private static _render2xLine(target: ImageData, colors: MinimapColors, dy: number, maxColumn: number, lineData: MinimapLineRenderingData) {
|
||||
private static _x2RenderLine(target: ImageData, backgroundColor: ParsedColor, colors: MinimapColors, dy: number, lineData: MinimapLineRenderingData) {
|
||||
const content = lineData.content;
|
||||
const tokens = lineData.tokens;
|
||||
const tabSize = lineData.tabSize;
|
||||
const charIndexStop = Math.min(content.length, maxColumn - 1);
|
||||
const maxDx = target.width - Constants.x2_CHAR_WIDTH;
|
||||
|
||||
let dx = 0;
|
||||
let charIndex = 0;
|
||||
|
@ -274,10 +275,10 @@ export class Minimap extends ViewPart {
|
|||
const token = tokens[tokenIndex];
|
||||
const tokenEndIndex = token.endIndex;
|
||||
const tokenColorId = token.getForeground();
|
||||
const tokenColor = colors.getMinimapColor(tokenColorId);
|
||||
const tokenColor = colors.getColor(tokenColorId);
|
||||
|
||||
for (; charIndex < tokenEndIndex; charIndex++) {
|
||||
if (charIndex >= charIndexStop) {
|
||||
if (dx > maxDx) {
|
||||
// hit edge of minimap
|
||||
return;
|
||||
}
|
||||
|
@ -292,7 +293,7 @@ export class Minimap extends ViewPart {
|
|||
// No need to render anything since space is invisible
|
||||
dx += Constants.x2_CHAR_WIDTH;
|
||||
} else {
|
||||
charRenderer2.x2RenderChar(target, dx, dy, charCode, tokenColor);
|
||||
charRenderer2.x2RenderChar(target, dx, dy, charCode, tokenColor, backgroundColor);
|
||||
dx += Constants.x2_CHAR_WIDTH;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,65 +20,18 @@ export class ParsedColor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a color rendered on top of the background at all possible alpha values.
|
||||
*/
|
||||
export class MinimapColor {
|
||||
|
||||
/**
|
||||
* For each 0 <= i <= 255:
|
||||
* data[3*i + 0] = r
|
||||
* data[3*i + 1] = g;
|
||||
* data[3*i + 2] = b;
|
||||
*/
|
||||
public readonly data: Uint8ClampedArray;
|
||||
|
||||
constructor(data: Uint8ClampedArray) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
export class MinimapColors {
|
||||
|
||||
private readonly _backgroundColor: ParsedColor;
|
||||
private readonly _colors: MinimapColor[];
|
||||
private readonly _colors: ParsedColor[];
|
||||
|
||||
constructor(colorMap: string[]) {
|
||||
this._backgroundColor = MinimapColors._parseColor(colorMap[ColorId.DefaultBackground]);
|
||||
let backgroundR = this._backgroundColor.r;
|
||||
let backgroundG = this._backgroundColor.g;
|
||||
let backgroundB = this._backgroundColor.b;
|
||||
|
||||
this._colors = [null];
|
||||
for (let colorId = 1; colorId < colorMap.length; colorId++) {
|
||||
let color = MinimapColors._parseColor(colorMap[colorId]);
|
||||
let colorR = color.r;
|
||||
let colorG = color.g;
|
||||
let colorB = color.b;
|
||||
|
||||
let result = new Uint8ClampedArray(256 * 3), resultOffset = 0;
|
||||
for (let alpha = 0; alpha <= 255; alpha++) {
|
||||
let fAlpha = alpha / 255;
|
||||
let fAlphaInverse = (255 - alpha) / 255;
|
||||
|
||||
let r = (colorR * fAlpha) + (backgroundR * fAlphaInverse);
|
||||
let g = (colorG * fAlpha) + (backgroundG * fAlphaInverse);
|
||||
let b = (colorB * fAlpha) + (backgroundB * fAlphaInverse);
|
||||
|
||||
result[resultOffset++] = r;
|
||||
result[resultOffset++] = g;
|
||||
result[resultOffset++] = b;
|
||||
}
|
||||
|
||||
this._colors[colorId] = new MinimapColor(result);
|
||||
this._colors[colorId] = MinimapColors._parseColor(colorMap[colorId]);
|
||||
}
|
||||
}
|
||||
|
||||
public getBackgroundColor(): ParsedColor {
|
||||
return this._backgroundColor;
|
||||
}
|
||||
|
||||
public getMinimapColor(colorId: ColorId): MinimapColor {
|
||||
public getColor(colorId: ColorId): ParsedColor {
|
||||
if (colorId < 1 || colorId >= this._colors.length) {
|
||||
// background color (basically invisible)
|
||||
colorId = 2;
|
||||
|
@ -243,59 +196,77 @@ export class MinimapCharRenderer2 {
|
|||
return chCode - Constants.START_CH_CODE;
|
||||
}
|
||||
|
||||
public x2RenderChar(target: ImageData, dx: number, dy: number, chCode: number, _color: MinimapColor): void {
|
||||
public x2RenderChar(target: ImageData, dx: number, dy: number, chCode: number, color: ParsedColor, backgroundColor: ParsedColor): void {
|
||||
const x2CharData = this.x2charData;
|
||||
const chIndex = MinimapCharRenderer2._getChIndex(chCode);
|
||||
const sourceOffset = chIndex * Constants.x2_CHAR_HEIGHT * Constants.x2_CHAR_WIDTH;
|
||||
const c1 = x2CharData[sourceOffset];
|
||||
const c2 = x2CharData[sourceOffset + 1];
|
||||
const c3 = x2CharData[sourceOffset + 2];
|
||||
const c4 = x2CharData[sourceOffset + 3];
|
||||
const c5 = x2CharData[sourceOffset + 4];
|
||||
const c6 = x2CharData[sourceOffset + 5];
|
||||
const c7 = x2CharData[sourceOffset + 6];
|
||||
const c8 = x2CharData[sourceOffset + 7];
|
||||
|
||||
const outWidth = target.width * Constants.RGBA_CHANNELS_CNT;
|
||||
let resultOffset = dy * outWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
||||
|
||||
const backgroundR = backgroundColor.r;
|
||||
const backgroundG = backgroundColor.g;
|
||||
const backgroundB = backgroundColor.b;
|
||||
|
||||
const deltaR = color.r - backgroundR;
|
||||
const deltaG = color.g - backgroundG;
|
||||
const deltaB = color.b - backgroundB;
|
||||
|
||||
const dest = target.data;
|
||||
const color = _color.data;
|
||||
dest[resultOffset + 0] = color[3 * c1 + 0];
|
||||
dest[resultOffset + 1] = color[3 * c1 + 1];
|
||||
dest[resultOffset + 2] = color[3 * c1 + 2];
|
||||
dest[resultOffset + 3] = 255;
|
||||
dest[resultOffset + 4] = color[3 * c2 + 0];
|
||||
dest[resultOffset + 5] = color[3 * c2 + 1];
|
||||
dest[resultOffset + 6] = color[3 * c2 + 2];
|
||||
dest[resultOffset + 7] = 255;
|
||||
resultOffset += outWidth;
|
||||
dest[resultOffset + 0] = color[3 * c3 + 0];
|
||||
dest[resultOffset + 1] = color[3 * c3 + 1];
|
||||
dest[resultOffset + 2] = color[3 * c3 + 2];
|
||||
dest[resultOffset + 3] = 255;
|
||||
dest[resultOffset + 4] = color[3 * c4 + 0];
|
||||
dest[resultOffset + 5] = color[3 * c4 + 1];
|
||||
dest[resultOffset + 6] = color[3 * c4 + 2];
|
||||
dest[resultOffset + 7] = 255;
|
||||
resultOffset += outWidth;
|
||||
dest[resultOffset + 0] = color[3 * c5 + 0];
|
||||
dest[resultOffset + 1] = color[3 * c5 + 1];
|
||||
dest[resultOffset + 2] = color[3 * c5 + 2];
|
||||
dest[resultOffset + 3] = 255;
|
||||
dest[resultOffset + 4] = color[3 * c6 + 0];
|
||||
dest[resultOffset + 5] = color[3 * c6 + 1];
|
||||
dest[resultOffset + 6] = color[3 * c6 + 2];
|
||||
dest[resultOffset + 7] = 255;
|
||||
resultOffset += outWidth;
|
||||
dest[resultOffset + 0] = color[3 * c7 + 0];
|
||||
dest[resultOffset + 1] = color[3 * c7 + 1];
|
||||
dest[resultOffset + 2] = color[3 * c7 + 2];
|
||||
dest[resultOffset + 3] = 255;
|
||||
dest[resultOffset + 4] = color[3 * c8 + 0];
|
||||
dest[resultOffset + 5] = color[3 * c8 + 1];
|
||||
dest[resultOffset + 6] = color[3 * c8 + 2];
|
||||
dest[resultOffset + 7] = 255;
|
||||
const sourceOffset = chIndex * Constants.x2_CHAR_HEIGHT * Constants.x2_CHAR_WIDTH;
|
||||
let destOffset = dy * outWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
||||
{
|
||||
const c = x2CharData[sourceOffset] / 255;
|
||||
dest[destOffset + 0] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 1] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 2] = backgroundB + deltaB * c;
|
||||
}
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 1] / 255;
|
||||
dest[destOffset + 4] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 5] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 6] = backgroundB + deltaB * c;
|
||||
}
|
||||
|
||||
destOffset += outWidth;
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 2] / 255;
|
||||
dest[destOffset + 0] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 1] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 2] = backgroundB + deltaB * c;
|
||||
}
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 3] / 255;
|
||||
dest[destOffset + 4] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 5] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 6] = backgroundB + deltaB * c;
|
||||
}
|
||||
|
||||
destOffset += outWidth;
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 4] / 255;
|
||||
dest[destOffset + 0] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 1] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 2] = backgroundB + deltaB * c;
|
||||
}
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 5] / 255;
|
||||
dest[destOffset + 4] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 5] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 6] = backgroundB + deltaB * c;
|
||||
}
|
||||
|
||||
destOffset += outWidth;
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 6] / 255;
|
||||
dest[destOffset + 0] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 1] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 2] = backgroundB + deltaB * c;
|
||||
}
|
||||
{
|
||||
const c = x2CharData[sourceOffset + 7] / 255;
|
||||
dest[destOffset + 4] = backgroundR + deltaR * c;
|
||||
dest[destOffset + 5] = backgroundG + deltaG * c;
|
||||
dest[destOffset + 6] = backgroundB + deltaB * c;
|
||||
}
|
||||
}
|
||||
|
||||
public x1RenderChar(target: ImageData, dx: number, dy: number, chCode: number): void {
|
||||
|
|
Loading…
Reference in a new issue