public onRender()

in web/src/app/timeline/canvas/timeline_renderer.service.ts [397:549]


  public onRender(
    gl: WebGL2RenderingContext,
    canvasSize: CanvasSize,
    offsetToFirstItemFromVisibleArea: number,
    visibleItemRange: ListRange,
    perRowScrollingProperties: PerRowScrollingProperty[],
    rowRenderers: Map<ResourceTimeline, TimelineRowWebGLRenderer>,
    timeRange: TimeRange,
    stickyTimelines: ResourceTimeline[],
    selectedTimeline: ResourceTimeline | null,
    highlightedTimeline: ResourceTimeline | null,
    highlightedByParentSelection: Set<ResourceTimeline>,
    logs: LogEntry[],
    selectedLog: number,
    filteredLog: Set<number>,
    highlightLogs: Set<number>,
    pixelPerTime: number,
    timeOffset: number,
    pixelRatio: number,
  ) {
    if (gl.isContextLost()) {
      if (!this.initializingGLResources) {
        console.warn(
          'Detected the webgl context being lost. Reinitializing gl resources',
        );
        this.refleshGL();
      }
      return;
    }

    this.sharedGLResources!.updateViewState(
      canvasSize.width * pixelRatio,
      canvasSize.height * pixelRatio,
      pixelPerTime * pixelRatio,
      pixelRatio,
      timeOffset - timeRange.begin,
    );
    // No items to render
    if (visibleItemRange.end - visibleItemRange.start === 0) {
      gl.disable(gl.SCISSOR_TEST);
      gl.clearColor(0, 0, 0, 0);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
      gl.finish();
      console.warn('no items to render. Clear screen');
      return;
    }
    const firstItemOffset =
      perRowScrollingProperties.length > 0
        ? perRowScrollingProperties[visibleItemRange.start].offset
        : 0;
    for (let i = visibleItemRange.start; i < visibleItemRange.end; i++) {
      if (perRowScrollingProperties.length <= i) continue;
      const row = perRowScrollingProperties[i];
      if (!row.source) continue;
      const renderer = rowRenderers.get(row.source);
      if (!renderer) continue;

      // Calculate the draw area for each timelines
      const bottom =
        canvasSize.height - (row.offset - firstItemOffset) - row.height;
      const region: GLRect = {
        left: 0 * pixelRatio,
        width: canvasSize.width * pixelRatio,
        bottom: bottom * pixelRatio,
        height: row.height * pixelRatio,
      };
      renderer.loadGLResources();
      renderer.updateInteractiveBuffer(selectedLog, highlightLogs, filteredLog);
      renderer.render(
        pixelRatio,
        region,
        row.source === selectedTimeline,
        row.source === highlightedTimeline,
        highlightedByParentSelection.has(row.source),
      );
    }
    // render sticky timelines
    let offset = 0;
    for (const timeline of stickyTimelines) {
      const row: PerRowScrollingProperty = {
        height: TIMELINE_ITEM_HEIGHTS[timeline.layer],
        offset: offset,
        source: timeline,
      };
      if (!row.source) continue;
      const renderer = rowRenderers.get(row.source);
      if (!renderer) continue;
      // Calculate the draw area for each timelines
      const bottom =
        canvasSize.height -
        row.offset -
        row.height +
        offsetToFirstItemFromVisibleArea;
      const region: GLRect = {
        left: 0 * pixelRatio,
        width: canvasSize.width * pixelRatio,
        bottom: bottom * pixelRatio,
        height: row.height * pixelRatio,
      };
      renderer.loadGLResources();
      renderer.updateInteractiveBuffer(selectedLog, highlightLogs, filteredLog);
      renderer.render(
        pixelRatio,
        region,
        row.source === selectedTimeline,
        row.source === highlightedTimeline,
        highlightedByParentSelection.has(row.source),
      );
      offset += row.height;
    }

    if (selectedLog !== -1) {
      this.selectedTimeVerticalLineRenderer!.render(
        canvasSize,
        pixelRatio,
        this.sharedGLResources!,
        logs[selectedLog].time - timeRange.begin,
        4,
        [0, 1, 0, 0.9],
      );
    }
    gl.flush();
    gl.finish();

    // To prevent blocking rendering the timeline currently shown, preloading step is after calling gl.finish()
    for (
      let i = visibleItemRange.start;
      i >=
      Math.max(
        0,
        Math.min(visibleItemRange.start, perRowScrollingProperties.length) -
          TimelineRendererService.PRELOAD_GL_RESOURCE_AREA,
      );
      i--
    ) {
      const row = perRowScrollingProperties[i];
      if (!row.source) continue;
      rowRenderers.get(row.source)?.loadGLResources();
    }
    for (
      let i = visibleItemRange.end;
      i <
      Math.min(
        perRowScrollingProperties.length,
        visibleItemRange.end + TimelineRendererService.PRELOAD_GL_RESOURCE_AREA,
      );
      i++
    ) {
      const row = perRowScrollingProperties[i];
      if (!row.source) continue;
      rowRenderers.get(row.source)?.loadGLResources();
    }
  }