UNPKG

@quick-game/cli

Version:

Command line interface for rapid qg development

308 lines 11.6 kB
// Copyright 2016 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. /* eslint-disable @typescript-eslint/naming-convention */ import * as Common from '../../core/common/common.js'; import * as SDK from '../../core/sdk/sdk.js'; export class TracingLayerTree extends SDK.LayerTreeBase.LayerTreeBase { tileById; paintProfilerModel; constructor(target) { super(target); this.tileById = new Map(); this.paintProfilerModel = target && target.model(SDK.PaintProfiler.PaintProfilerModel); } async setLayers(root, layers, paints) { const idsToResolve = new Set(); if (root) { // This is a legacy code path for compatibility, as cc is removing // layer tree hierarchy, this code will eventually be removed. this.extractNodeIdsToResolve(idsToResolve, {}, root); } else if (layers) { for (let i = 0; i < layers.length; ++i) { this.extractNodeIdsToResolve(idsToResolve, {}, layers[i]); } } await this.resolveBackendNodeIds(idsToResolve); const oldLayersById = this.layersById; this.layersById = new Map(); this.setContentRoot(null); if (root) { const convertedLayers = this.innerSetLayers(oldLayersById, root); this.setRoot(convertedLayers); } else if (layers) { const processedLayers = layers.map(this.innerSetLayers.bind(this, oldLayersById)); const contentRoot = this.contentRoot(); if (!contentRoot) { throw new Error('Content root is not set.'); } this.setRoot(contentRoot); for (let i = 0; i < processedLayers.length; ++i) { if (processedLayers[i].id() !== contentRoot.id()) { contentRoot.addChild(processedLayers[i]); } } } this.setPaints(paints); } setTiles(tiles) { this.tileById = new Map(); for (const tile of tiles) { this.tileById.set(tile.id, tile); } } pictureForRasterTile(tileId) { const tile = this.tileById.get('cc::Tile/' + tileId); if (!tile) { Common.Console.Console.instance().error(`Tile ${tileId} is missing`); return Promise.resolve(null); } const layer = this.layerById(tile.layer_id); if (!layer) { Common.Console.Console.instance().error(`Layer ${tile.layer_id} for tile ${tileId} is not found`); return Promise.resolve(null); } return layer.pictureForRect(tile.content_rect); } setPaints(paints) { for (let i = 0; i < paints.length; ++i) { const layer = this.layersById.get(paints[i].layerId()); if (layer) { layer.addPaintEvent(paints[i]); } } } innerSetLayers(oldLayersById, payload) { let layer = oldLayersById.get(payload.layer_id); if (layer) { layer.reset(payload); } else { layer = new TracingLayer(this.paintProfilerModel, payload); } this.layersById.set(payload.layer_id, layer); if (payload.owner_node) { layer.setNode(this.backendNodeIdToNode().get(payload.owner_node) || null); } if (!this.contentRoot() && layer.drawsContent()) { this.setContentRoot(layer); } for (let i = 0; payload.children && i < payload.children.length; ++i) { layer.addChild(this.innerSetLayers(oldLayersById, payload.children[i])); } return layer; } extractNodeIdsToResolve(nodeIdsToResolve, seenNodeIds, payload) { const backendNodeId = payload.owner_node; if (backendNodeId && !this.backendNodeIdToNode().has(backendNodeId)) { nodeIdsToResolve.add(backendNodeId); } for (let i = 0; payload.children && i < payload.children.length; ++i) { this.extractNodeIdsToResolve(nodeIdsToResolve, seenNodeIds, payload.children[i]); } } } export class TracingLayer { parentLayerId; parentInternal; layerId; nodeInternal; offsetXInternal; offsetYInternal; widthInternal; heightInternal; childrenInternal; quadInternal; scrollRectsInternal; gpuMemoryUsageInternal; paints; compositingReasons; compositingReasonIds; drawsContentInternal; paintProfilerModel; constructor(paintProfilerModel, payload) { this.parentLayerId = null; this.parentInternal = null; this.layerId = ''; this.nodeInternal = null; this.offsetXInternal = -1; this.offsetYInternal = -1; this.widthInternal = -1; this.heightInternal = -1; this.childrenInternal = []; this.quadInternal = []; this.scrollRectsInternal = []; this.gpuMemoryUsageInternal = -1; this.paints = []; this.compositingReasons = []; this.compositingReasonIds = []; this.drawsContentInternal = false; this.paintProfilerModel = paintProfilerModel; this.reset(payload); } reset(payload) { this.nodeInternal = null; this.layerId = String(payload.layer_id); this.offsetXInternal = payload.position[0]; this.offsetYInternal = payload.position[1]; this.widthInternal = payload.bounds.width; this.heightInternal = payload.bounds.height; this.childrenInternal = []; this.parentLayerId = null; this.parentInternal = null; this.quadInternal = payload.layer_quad || []; this.createScrollRects(payload); this.compositingReasons = payload.compositing_reasons || []; this.compositingReasonIds = payload.compositing_reason_ids || []; this.drawsContentInternal = Boolean(payload.draws_content); this.gpuMemoryUsageInternal = payload.gpu_memory_usage; this.paints = []; } id() { return this.layerId; } parentId() { return this.parentLayerId; } parent() { return this.parentInternal; } isRoot() { return !this.parentId(); } children() { return this.childrenInternal; } addChild(childParam) { const child = childParam; if (child.parentInternal) { console.assert(false, 'Child already has a parent'); } this.childrenInternal.push(child); child.parentInternal = this; child.parentLayerId = this.layerId; } setNode(node) { this.nodeInternal = node; } node() { return this.nodeInternal; } nodeForSelfOrAncestor() { let layer = this; for (; layer; layer = layer.parent()) { if (layer.node()) { return layer.node(); } } return null; } offsetX() { return this.offsetXInternal; } offsetY() { return this.offsetYInternal; } width() { return this.widthInternal; } height() { return this.heightInternal; } transform() { return null; } quad() { return this.quadInternal; } anchorPoint() { return [0.5, 0.5, 0]; } invisible() { return false; } paintCount() { return 0; } lastPaintRect() { return null; } scrollRects() { return this.scrollRectsInternal; } stickyPositionConstraint() { // TODO(smcgruer): Provide sticky layer information in traces. return null; } gpuMemoryUsage() { return this.gpuMemoryUsageInternal; } snapshots() { return this.paints.map(paint => paint.snapshotPromise().then(snapshot => { if (!snapshot) { return null; } const rect = { x: snapshot.rect[0], y: snapshot.rect[1], width: snapshot.rect[2], height: snapshot.rect[3] }; return { rect: rect, snapshot: snapshot.snapshot }; })); } pictureForRect(targetRect) { return Promise.all(this.paints.map(paint => paint.picturePromise())).then(pictures => { const filteredPictures = pictures.filter(picture => picture && rectsOverlap(picture.rect, targetRect)); const fragments = filteredPictures.map(picture => ({ x: picture.rect[0], y: picture.rect[1], picture: picture.serializedPicture })); if (!fragments.length || !this.paintProfilerModel) { return null; } const x0 = fragments.reduce((min, item) => Math.min(min, item.x), Infinity); const y0 = fragments.reduce((min, item) => Math.min(min, item.y), Infinity); // Rect is in layer content coordinates, make it relative to picture by offsetting to the top left corner. const rect = { x: targetRect[0] - x0, y: targetRect[1] - y0, width: targetRect[2], height: targetRect[3] }; return this.paintProfilerModel.loadSnapshotFromFragments(fragments).then(snapshot => snapshot ? { rect: rect, snapshot: snapshot } : null); }); function segmentsOverlap(a1, a2, b1, b2) { console.assert(a1 <= a2 && b1 <= b2, 'segments should be specified as ordered pairs'); return a2 > b1 && a1 < b2; } function rectsOverlap(a, b) { return segmentsOverlap(a[0], a[0] + a[2], b[0], b[0] + b[2]) && segmentsOverlap(a[1], a[1] + a[3], b[1], b[1] + b[3]); } } scrollRectsFromParams(params, type) { return { rect: { x: params[0], y: params[1], width: params[2], height: params[3] }, type: type }; } createScrollRects(payload) { const nonPayloadScrollRects = []; if (payload.non_fast_scrollable_region) { nonPayloadScrollRects.push(this.scrollRectsFromParams(payload.non_fast_scrollable_region, 'NonFastScrollable')); } if (payload.touch_event_handler_region) { nonPayloadScrollRects.push(this.scrollRectsFromParams(payload.touch_event_handler_region, "TouchEventHandler" /* Protocol.LayerTree.ScrollRectType.TouchEventHandler */)); } if (payload.wheel_event_handler_region) { nonPayloadScrollRects.push(this.scrollRectsFromParams(payload.wheel_event_handler_region, "WheelEventHandler" /* Protocol.LayerTree.ScrollRectType.WheelEventHandler */)); } if (payload.scroll_event_handler_region) { nonPayloadScrollRects.push(this.scrollRectsFromParams(payload.scroll_event_handler_region, "RepaintsOnScroll" /* Protocol.LayerTree.ScrollRectType.RepaintsOnScroll */)); } // SDK.LayerBaseTree.Layer.ScrollRectType and Protocol.LayerTree.ScrollRectType are the // same type, but we need to use the indirection of the nonPayloadScrollRects since // the ScrollRectType is defined as a string in SDK.LayerBaseTree.Layer.ScrollRectType. this.scrollRectsInternal = nonPayloadScrollRects; } addPaintEvent(paint) { this.paints.push(paint); } requestCompositingReasons() { return Promise.resolve(this.compositingReasons); } requestCompositingReasonIds() { return Promise.resolve(this.compositingReasonIds); } drawsContent() { return this.drawsContentInternal; } } //# sourceMappingURL=TracingLayerTree.js.map