Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / layers / PaintProfilerView.js
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /**
32  * @constructor
33  * @param {!WebInspector.LayerTreeModel} model
34  * @param {!WebInspector.Layers3DView} layers3DView
35  * @extends {WebInspector.VBox}
36  */
37 WebInspector.PaintProfilerView = function(model, layers3DView)
38 {
39     WebInspector.VBox.call(this);
40     this.element.classList.add("paint-profiler-view");
41
42     this._model = model;
43     this._layers3DView = layers3DView;
44
45     this._canvas = this.element.createChild("canvas", "fill");
46     this._context = this._canvas.getContext("2d");
47     this._selectionWindow = new WebInspector.OverviewGrid.Window(this.element, this.element);
48     this._selectionWindow.addEventListener(WebInspector.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this);
49
50     this._innerBarWidth = 4 * window.devicePixelRatio;
51     this._minBarHeight = 4 * window.devicePixelRatio;
52     this._barPaddingWidth = 2 * window.devicePixelRatio;
53     this._outerBarWidth = this._innerBarWidth + this._barPaddingWidth;
54
55     this._reset();
56 }
57
58 WebInspector.PaintProfilerView.prototype = {
59     onResize: function()
60     {
61         this._update();
62     },
63
64     _update: function()
65     {
66         this._canvas.width = this.element.clientWidth * window.devicePixelRatio;
67         this._canvas.height = this.element.clientHeight * window.devicePixelRatio;
68         this._samplesPerBar = 0;
69         if (!this._profiles || !this._profiles.length)
70             return;
71
72         var maxBars = Math.floor((this._canvas.width - 2 * this._barPaddingWidth) / this._outerBarWidth);
73         var sampleCount = this._profiles[0].length;
74         this._samplesPerBar = Math.ceil(sampleCount / maxBars);
75         var barCount = Math.floor(sampleCount / this._samplesPerBar);
76
77         var maxBarTime = 0;
78         var barTimes = [];
79         for (var i = 0, lastBarIndex = 0, lastBarTime = 0; i < sampleCount;) {
80             for (var row = 0; row < this._profiles.length; row++)
81                 lastBarTime += this._profiles[row][i];
82             ++i;
83             if (i - lastBarIndex == this._samplesPerBar || i == sampleCount) {
84                 // Normalize by total number of samples accumulated.
85                 lastBarTime /= this._profiles.length * (i - lastBarIndex);
86                 barTimes.push(lastBarTime);
87                 if (lastBarTime > maxBarTime)
88                     maxBarTime = lastBarTime;
89                 lastBarTime = 0;
90                 lastBarIndex = i;
91             }
92         }
93         const paddingHeight = 4 * window.devicePixelRatio;
94         var scale = (this._canvas.height - paddingHeight - this._minBarHeight) / maxBarTime;
95         this._context.fillStyle = "rgba(110, 180, 110, 0.7)";
96         for (var i = 0; i < barTimes.length; ++i)
97             this._renderBar(i, barTimes[i] * scale + this._minBarHeight);
98     },
99
100     /**
101      * @param {number} index
102      * @param {number} height
103      */
104     _renderBar: function(index, height)
105     {
106         var x = this._barPaddingWidth + index * this._outerBarWidth;
107         var y = this._canvas.height - height;
108         this._context.fillRect(x, y, this._innerBarWidth, height);
109     },
110
111     _onWindowChanged: function()
112     {
113         if (this._updateImageTimer)
114             return;
115         this._updateImageTimer = setTimeout(this._updateImage.bind(this), 100);
116     },
117
118     _updateImage: function()
119     {
120         delete this._updateImageTimer;
121         if (!this._profiles || !this._profiles.length)
122             return;
123
124         var screenLeft = this._selectionWindow.windowLeft * this._canvas.width;
125         var screenRight = this._selectionWindow.windowRight * this._canvas.width;
126
127         var barLeft = Math.floor((screenLeft - this._barPaddingWidth) / this._outerBarWidth);
128         var barRight = Math.floor((screenRight - this._barPaddingWidth + this._innerBarWidth)/ this._outerBarWidth);
129
130         var stepLeft = Math.max(0, barLeft * this._samplesPerBar);
131         var stepRight = Math.min(barRight * this._samplesPerBar, this._profiles[0].length);
132         this._snapshot.requestImage(stepLeft, stepRight, this._layers3DView.showImageForLayer.bind(this._layers3DView, this._layer));
133     },
134
135     _reset: function()
136     {
137         this._snapshot = null;
138         this._profiles = null;
139         this._selectionWindow.reset();
140     },
141
142     /**
143      * @param {!WebInspector.Layer} layer
144      */
145     profile: function(layer)
146     {
147         this._reset();
148         this._layer = layer;
149         this._layer.requestSnapshot(onSnapshotDone.bind(this));
150
151         /**
152          * @param {!WebInspector.PaintProfilerSnapshot=} snapshot
153          * @this {WebInspector.PaintProfilerView}
154          */
155         function onSnapshotDone(snapshot)
156         {
157             this._snapshot = snapshot;
158             if (!snapshot) {
159                 this._profiles = null;
160                 this._update();
161                 return;
162             }
163             snapshot.requestImage(null, null, this._layers3DView.showImageForLayer.bind(this._layers3DView, this._layer));
164             snapshot.profile(onProfileDone.bind(this));
165         }
166
167         /**
168          * @param {!Array.<!LayerTreeAgent.PaintProfile>=} profiles
169          * @this {WebInspector.PaintProfilerView}
170          */
171         function onProfileDone(profiles)
172         {
173             this._profiles = profiles;
174             this._update();
175         }
176     },
177
178     __proto__: WebInspector.VBox.prototype
179 };