blob: 48bca1175108e1674d941d438a8b1b798c83eb2d [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="stylesheet" href="/tracing/ui/extras/chrome/cc/layer_picker.css">
<link rel="import" href="/tracing/base/unit.html">
<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
<link rel="import" href="/tracing/extras/chrome/cc/util.html">
<link rel="import" href="/tracing/model/event.html">
<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
<link rel="import" href="/tracing/ui/base/dom_helpers.html">
<link rel="import" href="/tracing/ui/base/drag_handle.html">
<link rel="import" href="/tracing/ui/base/list_view.html">
<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
<script>
'use strict';
tr.exportTo('tr.ui.e.chrome.cc', function() {
var constants = tr.e.cc.constants;
var RENDER_PASS_QUADS =
Math.max(constants.ACTIVE_TREE, constants.PENDING_TREE) + 1;
/**
* @constructor
*/
var LayerPicker = tr.ui.b.define('tr-ui-e-chrome-cc-layer-picker');
LayerPicker.prototype = {
__proto__: HTMLUnknownElement.prototype,
decorate: function() {
this.lthi_ = undefined;
this.controls_ = document.createElement('top-controls');
this.renderPassQuads_ = false;
this.itemList_ = new tr.ui.b.ListView();
Polymer.dom(this).appendChild(this.controls_);
Polymer.dom(this).appendChild(this.itemList_);
this.itemList_.addEventListener(
'selection-changed', this.onItemSelectionChanged_.bind(this));
Polymer.dom(this.controls_).appendChild(tr.ui.b.createSelector(
this, 'whichTree',
'layerPicker.whichTree', constants.ACTIVE_TREE,
[{label: 'Active tree', value: constants.ACTIVE_TREE},
{label: 'Pending tree', value: constants.PENDING_TREE},
{label: 'Render pass quads', value: RENDER_PASS_QUADS}]));
this.showPureTransformLayers_ = false;
var showPureTransformLayers = tr.ui.b.createCheckBox(
this, 'showPureTransformLayers',
'layerPicker.showPureTransformLayers', false,
'Transform layers');
Polymer.dom(showPureTransformLayers).classList.add(
'show-transform-layers');
showPureTransformLayers.title =
'When checked, pure transform layers are shown';
Polymer.dom(this.controls_).appendChild(showPureTransformLayers);
},
get lthiSnapshot() {
return this.lthiSnapshot_;
},
set lthiSnapshot(lthiSnapshot) {
this.lthiSnapshot_ = lthiSnapshot;
this.updateContents_();
},
get whichTree() {
return this.renderPassQuads_ ? constants.ACTIVE_TREE : this.whichTree_;
},
set whichTree(whichTree) {
this.whichTree_ = whichTree;
this.renderPassQuads_ = (whichTree == RENDER_PASS_QUADS);
this.updateContents_();
tr.b.dispatchSimpleEvent(this, 'selection-change', false);
},
get layerTreeImpl() {
if (this.lthiSnapshot === undefined)
return undefined;
return this.lthiSnapshot.getTree(this.whichTree);
},
get isRenderPassQuads() {
return this.renderPassQuads_;
},
get showPureTransformLayers() {
return this.showPureTransformLayers_;
},
set showPureTransformLayers(show) {
if (this.showPureTransformLayers_ === show)
return;
this.showPureTransformLayers_ = show;
this.updateContents_();
},
getRenderPassInfos_: function() {
if (!this.lthiSnapshot_)
return [];
var renderPassInfo = [];
if (!this.lthiSnapshot_.args.frame ||
!this.lthiSnapshot_.args.frame.renderPasses)
return renderPassInfo;
var renderPasses = this.lthiSnapshot_.args.frame.renderPasses;
for (var i = 0; i < renderPasses.length; ++i) {
var info = {renderPass: renderPasses[i],
depth: 0,
id: i,
name: 'cc::RenderPass'};
renderPassInfo.push(info);
}
return renderPassInfo;
},
getLayerInfos_: function() {
if (!this.lthiSnapshot_)
return [];
var tree = this.lthiSnapshot_.getTree(this.whichTree_);
if (!tree)
return [];
var layerInfos = [];
var showPureTransformLayers = this.showPureTransformLayers_;
function isPureTransformLayer(layer) {
if (layer.args.compositingReasons &&
layer.args.compositingReasons.length != 1 &&
layer.args.compositingReasons[0] != 'No reasons given')
return false;
if (layer.args.drawsContent)
return false;
return true;
}
var visitedLayers = {};
function visitLayer(layer, depth, isMask, isReplica) {
if (visitedLayers[layer.layerId])
return;
visitedLayers[layer.layerId] = true;
var info = {layer: layer,
depth: depth};
if (layer.args.drawsContent)
info.name = layer.objectInstance.name;
else
info.name = 'cc::LayerImpl';
if (layer.usingGpuRasterization)
info.name += ' (G)';
info.isMaskLayer = isMask;
info.replicaLayer = isReplica;
if (showPureTransformLayers || !isPureTransformLayer(layer))
layerInfos.push(info);
}
tree.iterLayers(visitLayer);
return layerInfos;
},
updateContents_: function() {
if (this.renderPassQuads_)
this.updateRenderPassContents_();
else
this.updateLayerContents_();
},
updateRenderPassContents_: function() {
this.itemList_.clear();
var selectedRenderPassId;
if (this.selection_ && this.selection_.associatedRenderPassId)
selectedRenderPassId = this.selection_.associatedRenderPassId;
var renderPassInfos = this.getRenderPassInfos_();
renderPassInfos.forEach(function(renderPassInfo) {
var renderPass = renderPassInfo.renderPass;
var id = renderPassInfo.id;
var item = this.createElementWithDepth_(renderPassInfo.depth);
var labelEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
Polymer.dom(labelEl).textContent = renderPassInfo.name + ' ' + id;
item.renderPass = renderPass;
item.renderPassId = id;
Polymer.dom(this.itemList_).appendChild(item);
if (id == selectedRenderPassId) {
renderPass.selectionState =
tr.model.SelectionState.SELECTED;
}
}, this);
},
updateLayerContents_: function() {
this.changingItemSelection_ = true;
try {
this.itemList_.clear();
var selectedLayerId;
if (this.selection_ && this.selection_.associatedLayerId)
selectedLayerId = this.selection_.associatedLayerId;
var layerInfos = this.getLayerInfos_();
layerInfos.forEach(function(layerInfo) {
var layer = layerInfo.layer;
var id = layer.layerId;
var item = this.createElementWithDepth_(layerInfo.depth);
var labelEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
Polymer.dom(labelEl).textContent = layerInfo.name + ' ' + id;
var notesEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
if (layerInfo.isMaskLayer)
Polymer.dom(notesEl).textContent += '(mask)';
if (layerInfo.isReplicaLayer)
Polymer.dom(notesEl).textContent += '(replica)';
if ((layer.gpuMemoryUsageInBytes !== undefined) &&
(layer.gpuMemoryUsageInBytes > 0)) {
var gpuUsageStr = tr.b.Unit.byName.sizeInBytes.format(
layer.gpuMemoryUsageInBytes);
Polymer.dom(notesEl).textContent += ' (' + gpuUsageStr + ' MiB)';
}
item.layer = layer;
Polymer.dom(this.itemList_).appendChild(item);
if (layer.layerId == selectedLayerId) {
layer.selectionState = tr.model.SelectionState.SELECTED;
item.selected = true;
}
}, this);
} finally {
this.changingItemSelection_ = false;
}
},
createElementWithDepth_: function(depth) {
var item = document.createElement('div');
var indentEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
indentEl.style.whiteSpace = 'pre';
for (var i = 0; i < depth; i++) {
Polymer.dom(indentEl).textContent =
Polymer.dom(indentEl).textContent + ' ';
}
return item;
},
onItemSelectionChanged_: function(e) {
if (this.changingItemSelection_)
return;
if (this.renderPassQuads_)
this.onRenderPassSelected_(e);
else
this.onLayerSelected_(e);
tr.b.dispatchSimpleEvent(this, 'selection-change', false);
},
onRenderPassSelected_: function(e) {
var selectedRenderPass;
var selectedRenderPassId;
if (this.itemList_.selectedElement) {
selectedRenderPass = this.itemList_.selectedElement.renderPass;
selectedRenderPassId =
this.itemList_.selectedElement.renderPassId;
}
if (selectedRenderPass) {
this.selection_ = new tr.ui.e.chrome.cc.RenderPassSelection(
selectedRenderPass, selectedRenderPassId);
} else {
this.selection_ = undefined;
}
},
onLayerSelected_: function(e) {
var selectedLayer;
if (this.itemList_.selectedElement)
selectedLayer = this.itemList_.selectedElement.layer;
if (selectedLayer)
this.selection_ = new tr.ui.e.chrome.cc.LayerSelection(selectedLayer);
else
this.selection_ = undefined;
},
get selection() {
return this.selection_;
},
set selection(selection) {
if (this.selection_ == selection)
return;
this.selection_ = selection;
this.updateContents_();
}
};
return {
LayerPicker: LayerPicker
};
});
</script>