blob: dd9340802a01df64dbbaff4635ccaf5a3be7647b [file] [log] [blame]
/**
* @module modules/android-layers-sk
* @description <h2><code>android-layers-sk</code></h2>
*/
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { ElementDocSk } from '../element-doc-sk/element-doc-sk';
import { LayerInfo } from '../commands-sk/commands-sk';
// Types for the wasm bindings
import { LayerSummary } from '../debugger';
import '../cycler-button-sk';
import {
InspectLayerEventDetail,
InspectLayerEvent,
JumpCommandEvent,
JumpCommandEventDetail,
JumpInspectLayerEvent, NextItemEventDetail,
} from '../events';
export interface LayerDescription {
nodeId: number,
frameOfLastUpdate: number,
fullRedraw: boolean,
layerWidth: number,
layerHeight: number
name: string,
// A list of indices of drawImageRectLayer commands that reference this layer
usesThisFrame: number[],
updatedThisFrame: boolean,
}
export class AndroidLayersSk extends ElementDocSk {
private static template = (ele: AndroidLayersSk) => html`
<details open>
<summary><b>Offscreen Buffers</b></summary>
${ele._layerList.map(
(l: LayerDescription) => AndroidLayersSk.layerTemplate(ele, l),
)}
</details>`;
private static layerTemplate = (ele: AndroidLayersSk, item: LayerDescription) => html`
<div class="androidlayerbox ${item.nodeId === ele._inspectedLayer ? 'selected' : ''}">
<span class="layername"><b>${item.nodeId}</b>: ${item.name}</span><br>
Layer size = <b>(${item.layerWidth}, ${item.layerHeight})</b><br>
Uses this frame = <b>${item.usesThisFrame.length}</b>
Last update (<b>${item.fullRedraw ? 'full' : 'partial'}</b>) on frame
<b>${item.frameOfLastUpdate}</b><br>
<cycler-button-sk .text=${'Show Use'} .list=${item.usesThisFrame}
@next-item=${ele._jumpCommand}
title="Cycle through drawImageRectLayer commands on this frame which used this surface as\
a source.">
</cycler-button-sk>
<button @click=${() => ele._inspectLayer(item.nodeId, item.frameOfLastUpdate)}
class="${item.nodeId === ele._inspectedLayer ? 'buttonselected' : ''}"
title="Open the SkPicture representing the update on frame ${item.frameOfLastUpdate}.">
${item.nodeId === ele._inspectedLayer
? 'Exit'
: 'Inspector'
}
</button>
</div>
`;
private _layerList: LayerDescription[] = [];
private _inspectedLayer: number = -1; // a nodeID, not an index
private _frame: number = 0;
constructor() {
super(AndroidLayersSk.template);
}
connectedCallback(): void {
super.connectedCallback();
this._render();
// An event from the image resource viewer, requesting the layer inspector to be opened.
this.addDocumentEventListener(JumpInspectLayerEvent, (e) => {
const detail = (e as CustomEvent<InspectLayerEventDetail>).detail;
this._inspectLayer(detail.id, detail.frame);
});
}
// Given layer info (maps from ids to names and uses) collected in processCommands
// and summaries from wasm, (info about which past frames contain info necessary to
// redraw a layer's offscreen buffer), Create the array used to draw the template.
update(maps: LayerInfo, summaries: LayerSummary[], frame: number): void {
this._layerList = [];
summaries.forEach((item: LayerSummary) => {
const ld: LayerDescription = {
nodeId: item.nodeId,
frameOfLastUpdate: item.frameOfLastUpdate,
fullRedraw: item.fullRedraw,
layerWidth: item.layerWidth,
layerHeight: item.layerHeight,
name: maps.names.get(item.nodeId)!,
usesThisFrame: maps.uses.get(item.nodeId),
updatedThisFrame: item.frameOfLastUpdate === frame,
};
// We only want to see it if it's updated or used this frame.
if (ld.updatedThisFrame || ld.usesThisFrame.length > 0) {
this._layerList.push(ld);
}
});
this._render();
}
private _inspectLayer(id: number, frame: number) {
if (this._inspectedLayer === id) {
id = -1; // means we are not inspecting any layer
}
this._inspectedLayer = id;
// save what frame we were on when we entered the inspector
this._frame = frame;
// The current frame must be set to one which has an update for a layer before opening
// the inspector for that layer. debugger-page-sk will move the frame if necessary.
this.dispatchEvent(
new CustomEvent<InspectLayerEventDetail>(
InspectLayerEvent, {
detail: { id: this._inspectedLayer, frame: frame },
bubbles: true,
},
),
);
this._render();
}
private _jumpCommand(e: Event) {
const index = (e as CustomEvent<NextItemEventDetail>).detail.item;
if (this._inspectedLayer !== -1) {
// if we are inspecting a layer, we must exit in order to show it's use in the top level skp
this._inspectLayer(this._inspectedLayer, this._frame);
}
this.dispatchEvent(
new CustomEvent<JumpCommandEventDetail>(
JumpCommandEvent, {
detail: { unfilteredIndex: index },
bubbles: true,
},
),
);
}
}
define('android-layers-sk', AndroidLayersSk);