ui: Fix flow rendering for pinned tracks & improve canvas performance

Flow rendering for pinned tracks was broken (again). This CL fixes this
and also makes rendering flows for pinned tracks much more efficient, as
we only have to build a map for the pinned tracks instead of all the
tracks.

Change-Id: I5952ab6af870a9b3af6f1ad7e796a480e8994fed
diff --git a/ui/src/frontend/flow_events_renderer.ts b/ui/src/frontend/flow_events_renderer.ts
index 28ee34b..e221954 100644
--- a/ui/src/frontend/flow_events_renderer.ts
+++ b/ui/src/frontend/flow_events_renderer.ts
@@ -18,7 +18,7 @@
 import {Flow} from '../core/flow_types';
 import {RenderedPanelInfo} from './panel_container';
 import {TimeScale} from '../base/time_scale';
-import {TrackNode} from '../public/workspace';
+import {TrackNode, TrackNodeContainer} from '../public/workspace';
 import {TraceImpl} from '../core/trace_impl';
 
 const TRACK_GROUP_CONNECTION_OFFSET = 5;
@@ -57,6 +57,7 @@
   ctx: CanvasRenderingContext2D,
   size: Size2D,
   panels: ReadonlyArray<RenderedPanelInfo>,
+  tracks: TrackNodeContainer,
 ): void {
   const timescale = new TimeScale(trace.timeline.visibleWindow, {
     left: 0,
@@ -74,7 +75,7 @@
   // the tree to find containing groups.
 
   const sqlTrackIdToTrack = new Map<number, TrackNode>();
-  trace.workspace.flatTracks.forEach((track) =>
+  tracks.flatTracks.forEach((track) =>
     track.uri
       ? trace.tracks
           .getTrack(track.uri)
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 0e5668f..7bb2af7 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -24,7 +24,7 @@
 import {TimeScale} from '../base/time_scale';
 import {featureFlags} from '../core/feature_flags';
 import {raf} from '../core/raf_scheduler';
-import {TrackNode} from '../public/workspace';
+import {TrackNode, TrackNodeContainer} from '../public/workspace';
 import {TRACK_BORDER_COLOR, TRACK_SHELL_WIDTH} from './css_constants';
 import {renderFlows} from './flow_events_renderer';
 import {generateTicks, getMaxMajorTicks, TickType} from './gridline_helper';
@@ -349,7 +349,13 @@
               }),
           renderUnderlay: (ctx, size) => renderUnderlay(attrs.trace, ctx, size),
           renderOverlay: (ctx, size, panels) =>
-            renderOverlay(attrs.trace, ctx, size, panels),
+            renderOverlay(
+              attrs.trace,
+              ctx,
+              size,
+              panels,
+              attrs.trace.workspace.pinnedRoot,
+            ),
           selectedYRange: this.getYRange('pinned-panel-container'),
         }),
         m(PanelContainer, {
@@ -362,7 +368,13 @@
           },
           renderUnderlay: (ctx, size) => renderUnderlay(attrs.trace, ctx, size),
           renderOverlay: (ctx, size, panels) =>
-            renderOverlay(attrs.trace, ctx, size, panels),
+            renderOverlay(
+              attrs.trace,
+              ctx,
+              size,
+              panels,
+              attrs.trace.workspace,
+            ),
           selectedYRange: this.getYRange('scrolling-panel-container'),
         }),
       ),
@@ -413,6 +425,7 @@
   ctx: CanvasRenderingContext2D,
   canvasSize: Size2D,
   panels: ReadonlyArray<RenderedPanelInfo>,
+  trackContainer: TrackNodeContainer,
 ): void {
   const size = {
     width: canvasSize.width - TRACK_SHELL_WIDTH,
@@ -424,7 +437,7 @@
   canvasClip(ctx, 0, 0, size.width, size.height);
 
   // TODO(primiano): plumb the TraceImpl obj throughout the viwer page.
-  renderFlows(trace, ctx, size, panels);
+  renderFlows(trace, ctx, size, panels, trackContainer);
 
   const timewindow = trace.timeline.visibleWindow;
   const timescale = new TimeScale(timewindow, {left: 0, right: size.width});
diff --git a/ui/src/public/workspace.ts b/ui/src/public/workspace.ts
index a2bab1f..c6766b9 100644
--- a/ui/src/public/workspace.ts
+++ b/ui/src/public/workspace.ts
@@ -472,7 +472,7 @@
   onchange: (w: Workspace) => void = () => {};
 
   // Dummy node to contain the pinned tracks
-  private pinnedRoot = new TrackNode();
+  public readonly pinnedRoot = new TrackNode();
 
   get pinnedTracks(): ReadonlyArray<TrackNode> {
     return this.pinnedRoot.children;