Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate foreground & background rendering passes #1393

Merged
merged 3 commits into from
Apr 24, 2018

Conversation

bgw
Copy link
Member

@bgw bgw commented Apr 18, 2018

I'm primarily interested in doing this because it'll allow me to optimize the background rendering in later diffs, but this may also make it possible to fix some minor rendering issues.

Right now, if we draw a single-width character that overflows its cell's bounds, and the character to the right of it has a background, that background may cover up the first character's foreground. By drawing the background in a separate pass, we can avoid those cases.

There's still some issues with how dirty regions are computed that makes rendering stuff like that flaky, but this at least gets us closer to "correct" rendering.

Other terminal emulators (e.g. alacritty) render the foreground and background in separate passes:
https://github.com/jwilm/alacritty/blob/1b7ffea/src/renderer/mod.rs#L766

I'm primarily interested in doing this because it'll allow me to
optimize the background rendering in later diffs, but this may also make
it possible to fix some minor rendering issues.

Right now, if we draw a single-width character that overflows its cell's
bounds, and the character to the right of it has a background, that
background may cover up the first character's foreground. By drawing the
background in a separate pass, we can avoid those cases.

There's still some issues with how dirty regions are computed that makes
rendering stuff like that flaky, but this at least gets us closer to
"correct" rendering.

Other terminal emulators (e.g. alacritty) render the foreground and
background in separate passes:
https://github.com/jwilm/alacritty/blob/1b7ffea/src/renderer/mod.rs#L766
@bgw bgw requested a review from Tyriar April 18, 2018 05:00
}

this.clearCells(0, startRow, terminal.cols, endRow - startRow + 1); // endRow is inclusive
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could remove the comment if the params were renamed to firstRow and lastRow?


this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & FLAGS.BOLD), !!(flags & FLAGS.DIM));
private _drawBackground(terminal: ITerminal, startRow: number, endRow: number): void {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This would be better structured imo as _drawBackgroundCell/_drawForegroundCell and called like this:

this._forEachCell(terminal, startRow, endRow, this._drawBackgroundCell);
this._forEachCell(terminal, startRow, endRow, this._drawForegroundCell);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My plan is to keep track of the previously drawn background color as a variable scoped to the top-level of _drawBackground, and then minimize fillRect calls by only using fillRect once the background color changes or we've stopped iterating over cells.

While your API looks a little nicer, I don't know how I'd accomplish that optimization with it.

@Tyriar
Copy link
Member

Tyriar commented Apr 18, 2018

This is related to this but looks like it was caused by another commit. Do you know why this is what I see on the master branch in vim README.md when the cursor is on the * next to "Note":

image

And this is what I see in vscode (close to master)?

image

@bgw
Copy link
Member Author

bgw commented Apr 18, 2018

Do you know why this is what I see on the master branch in vim README.md when the cursor is on the * next to "Note"

Are you saying that the highlight only appears when you move the cursor over the *?

A lot of vim theme/syntax combinations will try to make text like this italic, and if the terminal emulator doesn't support italics (sometimes this requires messing with terminfo to get it to work), it'll often fall back to something else, like inverting the output. I think there's a lot of reasons this could be happening for you, but I'm not sure what it is exactly. I expect that it's related to differences between the demo environment and vscode's environment, rather than a regression in xtermjs.

@Tyriar
Copy link
Member

Tyriar commented Apr 18, 2018

@bgw the major issue is that the cursor is not visible at all, this may be because the background color is the same color as the cursor. I'll check your other questions when I get back to my Linux box 😄

Renaming these to firstRow/lastRow makes the inclusivity of the range
clearer.

Addresses this comment:
xtermjs#1393 (comment)
@Tyriar
Copy link
Member

Tyriar commented Apr 19, 2018

@bgw did you consider splitting up the bg and fg into separate render layers? I can't remember why I merged them to begin with, but it may have been because I was drawing the background with the character to the cache initially, before this existed:

/**
* Makes a partiicular rgb color in an ImageData completely transparent.
*/
function clearColor(imageData: ImageData, r: number, g: number, b: number): void {
for (let offset = 0; offset < imageData.data.length; offset += 4) {
if (imageData.data[offset] === r &&
imageData.data[offset + 1] === g &&
imageData.data[offset + 2] === b) {
imageData.data[offset + 3] = 0;
}
}
}

That would make drawing minimal diffs on the background layer super easy as we can keep a _state cache like we used to.

@bgw
Copy link
Member Author

bgw commented Apr 19, 2018

did you consider splitting up the bg and fg into separate render layers?

This would be fine for characters drawn from the cache, but the foreground layer would need to be transparent for this to work, and uncached characters drawn directly to the foreground layer wouldn't get SPAA.

We could render uncached characters to an intermediate buffer, and use clearColor on it, but that'll make the uncached codepath that much slower, so I don't think it's good idea.

@Tyriar
Copy link
Member

Tyriar commented Apr 23, 2018

uncached characters drawn directly to the foreground layer wouldn't get SPAA.

@bgw ah yes, that was probably the reason i did it 👍

Copy link
Member

@Tyriar Tyriar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement 🚀

@bgw bgw merged commit ff19ba8 into xtermjs:master Apr 24, 2018
@Tyriar Tyriar added this to the 3.4.0 milestone May 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants