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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render using canvas #938

Merged
merged 108 commits into from Sep 8, 2017

Conversation

@Tyriar
Copy link
Member

commented Sep 4, 2017

@parisk @mofux I don't expect the code to change much now, it's mainly just tests, documentation and any bugs that pop up at this point. Please review, I know it's big but most of the changes are in new files inside src/renderer 馃槃

Resolves #935
Fixes #936
Fixes #681
Fixes #730
Fixes #720
Fixes #475
Fixes #937
Fixes #920
Fixes #919


New Stuff!

  • Ascii characters with their foreground, 8 color and 8 bright/bold colors are pre-rendered and stored in an ImageBitmap. This is used as a texture atlas to draw to canvas really fast.

    image

  • Multiple canvases are used to layer different things onto the terminal, this method is fast and allows for a nice separation of logic.

    image

  • Render layers keep track of what they have drawn (when it makes sense) and as such will diff the new contents and only draw when necessary. This turns single character changes in lines to typically take < 0.25ms, down from ~6ms.

    image

  • Better support for line height, font size and font family. As they're all managed within Terminal now, just setOption and run the fit addon if necessary.

    image

  • There is now a very clean separation from the model and everything rendering, pretty mcuh everything that renders is within ./src/renderer (viewport being the only exception, which needs a background color set). We should move towards doing similar with the model and the DOM in Terminal to simplify and make testing easier.

  • Link handlers are getting reworked quite a bit as previously the validationCallback exposes the HTMLElement of the link to allow tooltips to be attached. There is now a hoverCallback which achieves a similar goal.

  • This fixes a bunch of bugs (see the link of "Fixes #x" above), a notable bug fixes is line characters being misaligned in vtop #937.

API Changes

See complete list of changes in the xterm.d.ts diff.

Limitations & regressions

  • Zooming the browser window will zoom the canvas, meaning at > 100% the text may be a little blurry.
  • Blink character attribute support was dropped. This is a little difficult to implement and not really worth the effort given its usage. #944
  • Link underlines are no longer the same color as the fg color #957
  • Ligatures are no longer supported #958

Deferred

  • Add new features to demo #939
  • The selection render layer should do incremental draws, currently it clears and redraws the entire selection #941
  • Window resizes that change devicePixelRatio is expensive (60ms+) #955

Benchmarks

This table contains the average time it takes to render when running various actions or programs.

Render time 2.9.2 canvas_render Improvement
Typing a single letter 4-5ms 0.4-0.5ms 10x faster
vtop idle 22-73ms* 0.8-1.6ms 27-46x faster
ls -lR large_folder 17-25ms* 2.3-4.6ms 5-7x faster
yes 17-30ms* 1-1.3ms 17-23x faster

* Rendering took multiple frames

Setup

  • Measured on Chrome 60, Macbook Pro.
  • Compared cc7c310 (master, 2.9.2) and Tyriar@2d1a1bf
  • The times are all rendering-related chunks exposed in devtools added up (render script, rendering, paint, composite layers).
  • I tried to take the smallest and largest samples for the range.

In pictures

Here's one of my favorites; comparing vtop's performance 馃敟.

Before

screen shot 2017-09-03 at 9 52 10 am

After

screen shot 2017-09-03 at 9 53 53 am


TODO List

  • API: Move setting of theme into Terminal.setOption
  • Better emoji support
  • Add selection color to ITheme
  • Resolve/accept TODO's in code
  • Document important classes/methods
  • Test
    • Add unit tests
    • Chrome
      • macOS
      • Linux
      • Windows
    • Safari/macOS - Does not support ImageBitmap so falls back to HTMLCanvas
    • Firefox - Buggy and bad performance drawing from ImageBitmap, explicit fallback to HTMLCanvas
      • Linux
      • macOS
      • Windows
    • Edge/Windows - seems just as good as Chrome
    • IE11/Windows - 馃挘
  • Redraw terminal when devicePixelRatio changes (causes blurry text)
  • Support floating point devicePixelRatio (causes jagged text)
  • Fix right padding getting larger when resizing
  • Investigate support for ctrl only clicks in the linkifier (a render layer in an addon?)
@mofux

This comment has been minimized.

Copy link
Contributor

commented Sep 8, 2017

@Tyriar Support for ligatures seems to be broken (works in v3 and master). I think we should check if there is a way to support it with canvas - I'm afraid there are lots of people that use it (and some like powerline users can hardly live without it).

@Tyriar

This comment has been minimized.

Copy link
Member Author

commented Sep 8, 2017

Support for ligatures seems to be broken (works in v3 and master)

I didn't think powerline used ligatures? powerline/fonts#42 Do you have a screenshot of the problem?

@mofux

This comment has been minimized.

Copy link
Contributor

commented Sep 8, 2017

@Tyriar Just double-checked, I thought some of the glyphs that are used by powerline are coming from the ligatures, but I was wrong, sorry 馃槗

@Tyriar Tyriar force-pushed the Tyriar:canvas_render branch from 0e5b62d to 75b91c6 Sep 8, 2017

@Tyriar Tyriar merged commit 948eedb into xtermjs:v3 Sep 8, 2017

1 check was pending

continuous-integration/travis-ci/pr The Travis CI build is in progress
Details

@Tyriar Tyriar deleted the Tyriar:canvas_render branch Sep 8, 2017

@parisk

This comment has been minimized.

Copy link
Contributor

commented Sep 10, 2017

馃帀

@@ -63,6 +64,7 @@ export class CompositionHelper {
* @param {CompositionEvent} ev The event.
*/
public compositionupdate(ev: CompositionEvent): void {
console.log('compositionupdate');

This comment has been minimized.

Copy link
@Krinkle

Krinkle Sep 12, 2017

Left a logger here I think?

This comment has been minimized.

Copy link
@Tyriar

Tyriar Sep 13, 2017

Author Member

Nice catch 馃槄 #983

@arcanis

This comment has been minimized.

Copy link
Contributor

commented Oct 10, 2017

I'm curious, does this renderer supports copy/pasting?

@weihanglo

This comment has been minimized.

Copy link

commented Oct 10, 2017

Hi @arcanis.
I am not from the Xterm.js team. But after reading the sources, I think the selection of canvas renderer was built almost as same as the custom selection logic shown in #670. There is a separate render layer to make selections work. You can also run the demo and experience its performance directly. All copy/pasting stuff works well in my MacBook.

@Tyriar

This comment has been minimized.

Copy link
Member Author

commented Oct 10, 2017

@arcanis copy and paste was barely touched at all, only the drawing of the selection and the events that copy/paste listened to were tweaked.

@Tyriar Tyriar referenced this pull request Oct 13, 2017
4 of 13 tasks complete
this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
return result;
}

This comment has been minimized.

Copy link
@weihanglo

weihanglo Oct 14, 2017

Hi. I am curious about why we chose createImageBitmap over passing canvas out directly. I thought ImageBitmap is for worker thread or image decoding on background thread. Does this gain any performance improvement?

This comment has been minimized.

Copy link
@Tyriar

Tyriar Oct 15, 2017

Author Member

There's a comment that explains this:

// ImageBitmap's draw about twice as fast as from a canvas

This is when I initially measured it. I also found that ImageBitmap was cripplingly slow on Firefox and wasn't supported on Safari, these fall back to drawing from HTMLCanvas.

This comment has been minimized.

Copy link
@weihanglo

weihanglo Oct 15, 2017

Got it.ImageBitmap is for fast accessing and drawing. Thanks for the reply!

@tbodt

This comment has been minimized.

Copy link

commented Nov 5, 2017

Will selection and copy/paste still work on iOS?

@Tyriar

This comment has been minimized.

Copy link
Member Author

commented Nov 6, 2017

@tbodt probably not, I'm thinking we should probably bring back the old renderer anyway for environment edge cases. Some computers take much longer to render using canvas which I think it something to do with GPU rendering being disabled or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can鈥檛 perform that action at this time.