1<!DOCTYPE html>
2<!--
3Copyright (c) 2014 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/ui/tracks/highlighter.html">
9<link rel="import" href="/tracing/ui/timeline_track_view.html">
10<link rel="import" href="/tracing/ui/timeline_viewport.html">
11<link rel="import" href="/tracing/ui/tracks/model_track.html">
12
13<script>
14'use strict';
15
16/**
17 * @fileoverview Provides the VSyncHighlighter class.
18 */
19tr.exportTo('tr.ui.e.highlighter', function() {
20
21  var Highlighter = tr.ui.tracks.Highlighter;
22
23  /**
24   * Highlights VSync events on the model track (using "zebra" striping).
25   * @constructor
26   */
27  function VSyncHighlighter(viewport) {
28    Highlighter.call(this, viewport);
29    this.times_ = [];
30  }
31
32  VSyncHighlighter.VSYNC_HIGHLIGHT_COLOR = new tr.b.Color(0, 0, 255);
33  VSyncHighlighter.VSYNC_HIGHLIGHT_ALPHA = 0.1;
34
35  VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT = 0.20;
36  VSyncHighlighter.VSYNC_DENSITY_OPAQUE = 0.10;
37  VSyncHighlighter.VSYNC_DENSITY_RANGE =
38      VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT -
39      VSyncHighlighter.VSYNC_DENSITY_OPAQUE;
40
41  /**
42   * Generate a zebra striping from a list of times.
43   */
44  VSyncHighlighter.generateStripes = function(times, minTime, maxTime) {
45    if (times.length === 0)
46      return [];
47
48    var stripes = [];
49
50    // Find the lowest and highest index within the viewport.
51    var lowIndex = tr.b.findLowIndexInSortedArray(
52        times,
53        function(time) { return time; },
54        minTime);
55    var highIndex = lowIndex - 1;
56    while (times[highIndex + 1] <= maxTime) {
57      highIndex++;
58    }
59
60    // Must start at an even index and end at an odd index.
61    for (var i = lowIndex - (lowIndex % 2); i <= highIndex; i += 2) {
62      var left = i < lowIndex ? minTime : times[i];
63      var right = i + 1 > highIndex ? maxTime : times[i + 1];
64      stripes.push([left, right]);
65    }
66
67    return stripes;
68  }
69
70  VSyncHighlighter.prototype = {
71    __proto__: Highlighter.prototype,
72
73    processModel: function(model) {
74      this.times_ = model.device.vSyncTimestamps;
75    },
76
77    drawHighlight: function(ctx, dt, viewLWorld, viewRWorld, viewHeight) {
78      if (!this.viewport_.highlightVSync) {
79        return;
80      }
81
82      var stripes = VSyncHighlighter.generateStripes(
83          this.times_, viewLWorld, viewRWorld);
84      if (stripes.length == 0) {
85        return;
86      }
87
88      var stripeRange = stripes[stripes.length - 1][1] - stripes[0][0];
89      var stripeDensity = stripes.length / (dt.scaleX * stripeRange);
90      var clampedStripeDensity = tr.b.clamp(stripeDensity,
91          VSyncHighlighter.VSYNC_DENSITY_OPAQUE,
92          VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT);
93      var opacity =
94          (VSyncHighlighter.VSYNC_DENSITY_TRANSPARENT - clampedStripeDensity) /
95          VSyncHighlighter.VSYNC_DENSITY_RANGE;
96      if (opacity == 0) {
97        return;
98      }
99
100      var pixelRatio = window.devicePixelRatio || 1;
101      var height = viewHeight * pixelRatio;
102
103      var c = VSyncHighlighter.VSYNC_HIGHLIGHT_COLOR;
104      ctx.fillStyle = c.toStringWithAlphaOverride(
105          VSyncHighlighter.VSYNC_HIGHLIGHT_ALPHA * opacity);
106
107      for (var i = 0; i < stripes.length; i++) {
108        var xLeftView = dt.xWorldToView(stripes[i][0]);
109        var xRightView = dt.xWorldToView(stripes[i][1]);
110        ctx.fillRect(xLeftView, 0, xRightView - xLeftView, height);
111      }
112    }
113  };
114
115  // Register the highlighter.
116  tr.ui.tracks.Highlighter.register(VSyncHighlighter);
117
118  return {
119    VSyncHighlighter: VSyncHighlighter
120  };
121});
122</script>
123