Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: chrome/browser/resources/gpu_internals/timeline_track.js

Issue 6677166: More about:gpu tracing improvements. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 /** 6 /**
7 * @fileoverview Renders an array of slices into the provided div, 7 * @fileoverview Renders an array of slices into the provided div,
8 * using a child canvas element. Uses a FastRectRenderer to draw only 8 * using a child canvas element. Uses a FastRectRenderer to draw only
9 * the visible slices. 9 * the visible slices.
10 */ 10 */
(...skipping 20 matching lines...) Expand all
31 } 31 }
32 function colorToString(c) { 32 function colorToString(c) {
33 return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')'; 33 return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')';
34 } 34 }
35 35
36 const selectedIdBoost = palletteBase.length; 36 const selectedIdBoost = palletteBase.length;
37 37
38 const pallette = palletteBase.concat(palletteBase.map(brighten)). 38 const pallette = palletteBase.concat(palletteBase.map(brighten)).
39 map(colorToString); 39 map(colorToString);
40 40
41 var textWidthMap = { };
42 function quickMeasureText(ctx, text) {
43 var w = textWidthMap[text];
44 if (!w) {
45 w = ctx.measureText(text).width;
46 textWidthMap[text] = w;
47 }
48 return w;
49 }
50
51 /**
52 * Generic base class for timeline tracks
53 */
54 TimelineThreadTrack = cr.ui.define('div');
55 TimelineThreadTrack.prototype = {
56 __proto__: HTMLDivElement.prototype,
57
58 decorate: function() {
59 this.className = 'timeline-thread-track';
60 },
61
62 set thread(thread) {
63 this.thread_ = thread;
64 this.updateChildTracks_();
65 },
66
67 set viewport(v) {
68 this.viewport_ = v;
69 for (var i = 0; i < this.tracks_.length; i++)
70 this.tracks_[i].viewport = v;
71 this.invalidate();
72 },
73
74 invalidate: function() {
75 if (this.parentNode)
76 this.parentNode.invalidate();
77 },
78
79 onResize: function() {
80 for (var i = 0; i < this.tracks_.length; i++)
81 this.tracks_[i].onResize();
82 },
83
84 get firstCanvas() {
85 if (this.tracks_.length)
86 return this.tracks_[0].firstCanvas;
87 return undefined;
88 },
89
90 redraw: function() {
91 for (var i = 0; i < this.tracks_.length; i++)
92 this.tracks_[i].redraw();
93 },
94
95 updateChildTracks_: function() {
96 this.textContent = '';
97 this.tracks_ = [];
98 if (this.thread_) {
99 for (var srI = 0; srI < this.thread_.subRows.length; ++srI) {
100 var track = new TimelineSliceTrack();
101
102 if (srI == 0)
103 track.heading = this.thread_.parent.pid + ': ' +
104 this.thread_.tid + ': ';
105 else
106 track.heading = '';
107 track.slices = this.thread_.subRows[srI];
108 track.viewport = this.viewport_;
109
110 this.tracks_.push(track);
111 this.appendChild(track);
112 }
113 }
114 },
115
116 /**
117 * Picks a slice, if any, at a given location.
118 * @param {number} wX X location to search at, in worldspace.
119 * @param {number} wY Y location to search at, in offset space.
120 * offset space.
121 * @param {function():*} onHitCallback Callback to call with the slice,
122 * if one is found.
123 * @return {boolean} true if a slice was found, otherwise false.
124 */
125 pick: function(wX, wY, onHitCallback) {
126 for (var i = 0; i < this.tracks_.length; i++) {
127 var track = this.tracks_[i];
128 if (wY >= track.offsetTop && wY < track.offsetTop + track.offsetHeight)
129 return track.pick(wX, onHitCallback);
130 }
131 return false;
132 },
133
134 /**
135 * Finds slices intersecting the given interval.
136 * @param {number} loWX Lower X bound of the interval to search, in
137 * worldspace.
138 * @param {number} hiWX Upper X bound of the interval to search, in
139 * worldspace.
140 * @param {number} loY Lower Y bound of the interval to search, in
141 * offset space.
142 * @param {number} hiY Upper Y bound of the interval to search, in
143 * offset space.
144 * @param {function():*} onHitCallback Function to call for each slice
145 * intersecting the interval.
146 */
147 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) {
148 for (var i = 0; i < this.tracks_.length; i++) {
149 var a = Math.max(loY, this.tracks_[i].offsetTop);
150 var b = Math.min(hiY, this.tracks_[i].offsetTop +
151 this.tracks_[i].offsetHeight);
152 if (a <= b)
153 this.tracks_[i].pickRange(loWX, hiWX, loY, hiY, onHitCallback);
154 }
155 }
156 };
157
41 /** 158 /**
42 * Creates a new timeline track div element 159 * Creates a new timeline track div element
43 * @constructor 160 * @constructor
44 * @extends {HTMLDivElement} 161 * @extends {HTMLDivElement}
45 */ 162 */
46 TimelineTrack = cr.ui.define('div'); 163 TimelineSliceTrack = cr.ui.define('div');
47 164
48 TimelineTrack.prototype = { 165 TimelineSliceTrack.prototype = {
49 __proto__: HTMLDivElement.prototype, 166 __proto__: HTMLDivElement.prototype,
50 167
51 decorate: function() { 168 decorate: function() {
52 this.classList.add('timeline-track'); 169 this.className = 'timeline-slice-track';
53 this.slices_ = null; 170 this.slices_ = null;
54 171
55 this.titleDiv_ = document.createElement('div'); 172 this.titleDiv_ = document.createElement('div');
56 this.titleDiv_.className = 'timeline-track-title'; 173 this.titleDiv_.className = 'timeline-slice-track-title';
57 this.appendChild(this.titleDiv_); 174 this.appendChild(this.titleDiv_);
58 175
59 this.canvasContainer_ = document.createElement('div'); 176 this.canvasContainer_ = document.createElement('div');
60 this.canvasContainer_.className = 'timeline-track-canvas-container'; 177 this.canvasContainer_.className = 'timeline-slice-track-canvas-container';
61 this.appendChild(this.canvasContainer_); 178 this.appendChild(this.canvasContainer_);
62 this.canvas_ = document.createElement('canvas'); 179 this.canvas_ = document.createElement('canvas');
63 this.canvas_.className = 'timeline-track-canvas'; 180 this.canvas_.className = 'timeline-slice-track-canvas';
64 this.canvasContainer_.appendChild(this.canvas_); 181 this.canvasContainer_.appendChild(this.canvas_);
65 182
66 this.ctx_ = this.canvas_.getContext('2d'); 183 this.ctx_ = this.canvas_.getContext('2d');
67 }, 184 },
68 185
69 set heading(text) { 186 set heading(text) {
70 this.titleDiv_.textContent = text; 187 this.titleDiv_.textContent = text;
71 }, 188 },
72 189
73 set slices(slices) { 190 set slices(slices) {
74 this.slices_ = slices; 191 this.slices_ = slices;
75 this.invalidate(); 192 this.invalidate();
76 }, 193 },
77 get canvas() {
78 return this.canvas_;
79 },
80 194
81 onResize: function() { 195 set viewport(v) {
82 this.canvas_.width = this.canvasContainer_.clientWidth; 196 this.viewport_ = v;
83 this.canvas_.height = this.canvasContainer_.clientHeight;
84 this.invalidate(); 197 this.invalidate();
85 }, 198 },
86 199
87 invalidate: function() { 200 invalidate: function() {
88 if (this.parentNode) 201 if (this.parentNode)
89 this.parentNode.invalidate(); 202 this.parentNode.invalidate();
90 }, 203 },
91 204
92 set viewport(v) { 205 get firstCanvas() {
93 this.viewport_ = v; 206 return this.canvas_;
207 },
208
209 onResize: function() {
210 this.canvas_.width = this.canvasContainer_.clientWidth;
211 this.canvas_.height = this.canvasContainer_.clientHeight;
94 this.invalidate(); 212 this.invalidate();
95 }, 213 },
96 214
97 getCanvasWidth: function() {
98 return this.canvas_.width;
99 },
100
101 redraw: function() { 215 redraw: function() {
102 if (!this.viewport_) 216 if (!this.viewport_)
103 return; 217 return;
104 var ctx = this.ctx_; 218 var ctx = this.ctx_;
105 var canvasW = this.canvas_.width; 219 var canvasW = this.canvas_.width;
106 var canvasH = this.canvas_.height; 220 var canvasH = this.canvas_.height;
107 221
108 ctx.clearRect(0, 0, canvasW, canvasH); 222 ctx.clearRect(0, 0, canvasW, canvasH);
109 223
110 // culling... 224 // culling...
(...skipping 19 matching lines...) Expand all
130 colorId = slice.selected ? 244 colorId = slice.selected ?
131 slice.colorId + selectedIdBoost : 245 slice.colorId + selectedIdBoost :
132 slice.colorId; 246 slice.colorId;
133 247
134 if (w < pixWidth) 248 if (w < pixWidth)
135 w = pixWidth; 249 w = pixWidth;
136 tr.fillRect(x, w, colorId); 250 tr.fillRect(x, w, colorId);
137 } 251 }
138 tr.flush(); 252 tr.flush();
139 ctx.restore(); 253 ctx.restore();
254
255 // labels
256 ctx.textAlign = 'center';
257 ctx.textBaseline = 'top';
258 ctx.font = '10px sans-serif';
259 ctx.strokeStyle = 'rgb(0,0,0)';
260 ctx.fillStyle = 'rgb(0,0,0)';
261 var quickDiscardThresshold = pixWidth * 20; // dont render until 20px wide
262 for (var i = 0; i < slices.length; ++i) {
263 var slice = slices[i];
264 if (slice.duration > quickDiscardThresshold) {
265 var labelWidth = quickMeasureText(ctx, slice.title) + 2;
266 var labelWidthWorld = pixWidth * labelWidth;
267 if (labelWidthWorld < slice.duration) {
268 var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration);
269 ctx.fillText(slice.title, cX, 2.5);
270 }
271 }
272 }
140 }, 273 },
141 274
142 /** 275 /**
143 * Picks a slice, if any, at a given location. 276 * Picks a slice, if any, at a given location.
144 * @param {number} wX Location to search at, in worldspace. 277 * @param {number} wX X location to search at, in worldspace.
278 * @param {number} wY Y location to search at, in offset space.
279 * offset space.
145 * @param {function():*} onHitCallback Callback to call with the slice, 280 * @param {function():*} onHitCallback Callback to call with the slice,
146 * if one is found. 281 * if one is found.
147 * @return {boolean} true if a slice was found, otherwise false. 282 * @return {boolean} true if a slice was found, otherwise false.
148 */ 283 */
149 pick: function(wX, onHitCallback) { 284 pick: function(wX, wY, onHitCallback) {
285 if (wY < this.offsetTop || wY >= this.offsetTop + this.offsetHeight)
286 return false;
150 var x = gpu.findLowIndexInSortedIntervals(this.slices_, 287 var x = gpu.findLowIndexInSortedIntervals(this.slices_,
151 function(x) { return x.start; }, 288 function(x) { return x.start; },
152 function(x) { return x.duration; }, 289 function(x) { return x.duration; },
153 wX); 290 wX);
154 if (x >= 0 && x < this.slices_.length) { 291 if (x >= 0 && x < this.slices_.length) {
155 onHitCallback('slice', this, this.slices_[x]); 292 onHitCallback('slice', this, this.slices_[x]);
156 return true; 293 return true;
157 } 294 }
158 return false; 295 return false;
159 }, 296 },
160 297
161 /** 298 /**
162 * Finds slices intersecting the given interval. 299 * Finds slices intersecting the given interval.
163 * @param {number} loWX Lower bound of the interval to search, in 300 * @param {number} loWX Lower X bound of the interval to search, in
164 * worldspace. 301 * worldspace.
165 * @param {number} hiWX Upper bound of the interval to search, in 302 * @param {number} hiWX Upper X bound of the interval to search, in
166 * worldspace. 303 * worldspace.
304 * @param {number} loY Lower Y bound of the interval to search, in
305 * offset space.
306 * @param {number} hiY Upper Y bound of the interval to search, in
307 * offset space.
167 * @param {function():*} onHitCallback Function to call for each slice 308 * @param {function():*} onHitCallback Function to call for each slice
168 * intersecting the interval. 309 * intersecting the interval.
169 */ 310 */
170 pickRange: function(loWX, hiWX, onHitCallback) { 311 pickRange: function(loWX, hiWX, loY, hiY, onHitCallback) {
312 var a = Math.max(loY, this.offsetTop);
313 var b = Math.min(hiY, this.offsetTop + this.offsetHeight);
314 if (a > b)
315 return;
316
171 function onPickHit(slice) { 317 function onPickHit(slice) {
172 onHitCallback('slice', this, slice); 318 onHitCallback('slice', this, slice);
173 } 319 }
174 gpu.iterateOverIntersectingIntervals(this.slices_, 320 gpu.iterateOverIntersectingIntervals(this.slices_,
175 function(x) { return x.start; }, 321 function(x) { return x.start; },
176 function(x) { return x.duration; }, 322 function(x) { return x.duration; },
177 loWX, hiWX, 323 loWX, hiWX,
178 onPickHit); 324 onPickHit);
179 } 325 }
180 326
181 }; 327 };
182 328
183 return { 329 return {
184 TimelineTrack: TimelineTrack 330 TimelineSliceTrack: TimelineSliceTrack,
331 TimelineThreadTrack: TimelineThreadTrack
185 }; 332 };
186 }); 333 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/gpu_internals/timeline_test.html ('k') | chrome/browser/resources/gpu_internals/timeline_view.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698