1/* 2 * Copyright 2017, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import {transform, nanos_to_string, get_visible_chip} from './transform.js' 18 19const FLAG_HIDDEN = 0x1; 20var RELATIVE_Z_CHIP = {short: 'RelZ', 21 long: "Is relative Z-ordered to another surface", 22 class: 'warn'}; 23var RELATIVE_Z_PARENT_CHIP = {short: 'RelZParent', 24 long: "Something is relative Z-ordered to this surface", 25 class: 'warn'}; 26var MISSING_LAYER = {short: 'MissingLayer', 27 long: "This layer was referenced from the parent, but not present in the trace", 28 class: 'error'}; 29 30function transform_layer(layer, {parentHidden}) { 31 function transform_rect(layer) { 32 var pos = layer.position || {}; 33 var size = layer.size || {}; 34 35 return { 36 left: pos.x || 0, 37 right: pos.x + size.w || 0, 38 top: pos.y || 0, 39 bottom: pos.y + size.h || 0, 40 label: layer.name, 41 } 42 } 43 44 var chips = []; 45 var rect = transform_rect(layer); 46 var hidden = (layer.flags & FLAG_HIDDEN) != 0 || parentHidden; 47 var visible = (layer.activeBuffer || layer.type === 'ColorLayer') 48 && !hidden && layer.color.a > 0; 49 if (visible) { 50 chips.push(get_visible_chip()); 51 } else { 52 rect = undefined; 53 } 54 var bounds = undefined; 55 if (layer.name.startsWith("Display Root#0")) { 56 bounds = {width: layer.size.w, height: layer.size.h}; 57 } 58 if (layer.zOrderRelativeOf !== -1) { 59 chips.push(RELATIVE_Z_CHIP); 60 } 61 if (layer.zOrderRelativeParentOf !== undefined) { 62 chips.push(RELATIVE_Z_PARENT_CHIP); 63 } 64 if (layer.missing) { 65 chips.push(MISSING_LAYER); 66 } 67 68 var transform_layer_with_parent_hidden = 69 (layer) => transform_layer(layer, {parentHidden: hidden}); 70 71 return transform({ 72 obj: layer, 73 kind: 'layer', 74 name: layer.name, 75 children: [ 76 [layer.resolvedChildren, transform_layer_with_parent_hidden], 77 ], 78 rect, 79 bounds, 80 highlight: rect, 81 chips, 82 visible, 83 }); 84} 85 86function missingLayer(childId) { 87 return { 88 name: "layer #" + childId, 89 missing: true, 90 zOrderRelativeOf: -1, 91 } 92} 93 94function transform_layers(layers) { 95 var idToItem = {}; 96 var isChild = {} 97 layers.layers.forEach((e) => { 98 idToItem[e.id] = e; 99 }); 100 layers.layers.forEach((e) => { 101 e.resolvedChildren = []; 102 if (Array.isArray(e.children)) { 103 e.resolvedChildren = e.children.map( 104 (childId) => idToItem[childId] || missingLayer(childId)); 105 e.children.forEach((childId) => { 106 isChild[childId] = true; 107 }); 108 } 109 if (e.zOrderRelativeOf !== -1) { 110 idToItem[e.zOrderRelativeOf].zOrderRelativeParentOf = e.id; 111 } 112 }); 113 var roots = layers.layers.filter((e) => !isChild[e.id]); 114 115 function foreachTree(nodes, fun) { 116 nodes.forEach((n) => { 117 fun(n); 118 foreachTree(n.children, fun); 119 }); 120 } 121 122 var idToTransformed = {}; 123 var transformed_roots = roots.map(transform_layer); 124 foreachTree(transformed_roots, (n) => { 125 idToTransformed[n.obj.id] = n; 126 }); 127 var flattened = []; 128 layers.layers.forEach((e) => { 129 flattened.push(idToTransformed[e.id]); 130 }); 131 132 return transform({ 133 obj: {}, 134 kind: 'layers', 135 name: 'layers', 136 children: [ 137 [transformed_roots, (c) => c], 138 ], 139 rects_transform (r) { 140 var res = []; 141 flattened.forEach((l) => { 142 if (l.rect) { 143 res.push(l.rect); 144 } 145 }); 146 return res.reverse(); 147 }, 148 flattened, 149 }); 150} 151 152function transform_layers_entry(entry) { 153 return transform({ 154 obj: entry, 155 kind: 'entry', 156 name: nanos_to_string(entry.elapsedRealtimeNanos) + " - " + entry.where, 157 children: [ 158 [[entry.layers], transform_layers], 159 ], 160 timestamp: entry.elapsedRealtimeNanos, 161 }); 162} 163 164function transform_layers_trace(entries) { 165 return transform({ 166 obj: entries, 167 kind: 'layerstrace', 168 name: 'layerstrace', 169 children: [ 170 [entries.entry, transform_layers_entry], 171 ], 172 }); 173} 174 175export {transform_layers, transform_layers_trace}; 176