1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef DEBUGLAYERMANAGER_H_ 9cb93a386Sopenharmony_ci#define DEBUGLAYERMANAGER_H_ 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkImage.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTHash.h" 13cb93a386Sopenharmony_ci#include "src/utils/SkJSONWriter.h" 14cb93a386Sopenharmony_ci#include "tools/debugger/DebugCanvas.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#include <vector> 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci// A class to assist in playing back and debugging an mskp file containing offscreen layer commands. 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci// Holds SkPictures necessary to draw layers in one or more DebugCanvases. During 21cb93a386Sopenharmony_ci// recording of the mskp file on Android, each layer had a RenderNode id, which is recorded with 22cb93a386Sopenharmony_ci// the layer's draw commands. 23cb93a386Sopenharmony_ci// Creates one surface (cpu only for now) for each layer, and renders 24cb93a386Sopenharmony_ci// pictures to it up to the requested command using a DebugCanvas. 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci// Animations are expected to, but may not always use a layer on more than frame. 27cb93a386Sopenharmony_ci// the layer may be drawn to more than once, and each different draw is saved for reconstructing the 28cb93a386Sopenharmony_ci// layer as it was on any frame. Draws may be partial, meaning their commands were clipped to not 29cb93a386Sopenharmony_ci// cover the entire layer. 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci// Clients may ask for a rendering of a given layer by its RenderNode id and frame, and 32cb93a386Sopenharmony_ci// this class will return a rendering of how it looked on that frame. 33cb93a386Sopenharmony_ci// returning an SkImage snapshot of the internally managed surface. 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ciclass DebugCanvas; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciclass DebugLayerManager { 38cb93a386Sopenharmony_cipublic: 39cb93a386Sopenharmony_ci DebugLayerManager() {} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci // Store an SkPicture under a given nodeId (and under the currently set frame number) 42cb93a386Sopenharmony_ci // `dirty` is the recorded rect that was used to call androidFramework_setDeviceClipRestriction 43cb93a386Sopenharmony_ci // when the layer was drawn. 44cb93a386Sopenharmony_ci void storeSkPicture(int nodeId, int frame, sk_sp<SkPicture> picture, SkIRect dirty); 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci // Set's the command playback head for a given picture/draw event. 47cb93a386Sopenharmony_ci void setCommand(int nodeId, int frame, int command); 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci void drawLayerEventTo(SkSurface*, const int nodeId, const int frame); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci // getLayerAsImage draws the given layer as it would have looked on frame and returns an image. 52cb93a386Sopenharmony_ci // Though each picture can be played back in as many ways as there are commands, we will let 53cb93a386Sopenharmony_ci // that be determined by the user who sets an independent playhead for each draw event, tracked 54cb93a386Sopenharmony_ci // here, so it stays how they left it. 55cb93a386Sopenharmony_ci // For example: Say we are drawing a layer at frame 10. 56cb93a386Sopenharmony_ci // Frame 0: Layer was completely redrawn. By default we draw it to its last command. We always 57cb93a386Sopenharmony_ci // save the result by (nodeId, frame) 58cb93a386Sopenharmony_ci // Frame 5: Layer was partially redrawn, and the user has inspected this draw event, leaving 59cb93a386Sopenharmony_ci // its command playhead at command 50/100. We have drew this at the time and save how 60cb93a386Sopenharmony_ci // the result looked (all of the commands at frame 0, then half of the commands in the 61cb93a386Sopenharmony_ci // partial draw at frame 5) 62cb93a386Sopenharmony_ci // Frame 10: Another partial redraw, un-altered, drawn on top of the result from frame 5. We 63cb93a386Sopenharmony_ci // return this as the image of how the layer should look on frame 10 64cb93a386Sopenharmony_ci // Frame 15: A full redraw 65cb93a386Sopenharmony_ci // 66cb93a386Sopenharmony_ci // If the user then comes along and moves the command playhead of the picture at frame 0, 67cb93a386Sopenharmony_ci // we invalidate the stored images for 0, 5, and 10, but we can leave 15 alone if we have it. 68cb93a386Sopenharmony_ci // 69cb93a386Sopenharmony_ci // Which leaves us with one less degree of freedom to think about when implementing this 70cb93a386Sopenharmony_ci // function: We can assume there is only one way to play back a given picture. :) 71cb93a386Sopenharmony_ci // 72cb93a386Sopenharmony_ci // The reason the public version of this function doesn't let you specify the frame, is that 73cb93a386Sopenharmony_ci // I expect DebugCanvas to call it, which doesn't know which frame it's rendering. The code in 74cb93a386Sopenharmony_ci // debugger_bindings.cpp does know, which it why I'm having it set the frame via setFrame(int) 75cb93a386Sopenharmony_ci sk_sp<SkImage> getLayerAsImage(const int nodeId, const int frame); 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_ci // Flat because it's meant to be bindable by emscripten and returned to the javascript side 78cb93a386Sopenharmony_ci struct DrawEventSummary { 79cb93a386Sopenharmony_ci // true when the drawEvent represents a valid result. 80cb93a386Sopenharmony_ci bool found = false; 81cb93a386Sopenharmony_ci int commandCount; 82cb93a386Sopenharmony_ci int layerWidth; 83cb93a386Sopenharmony_ci int layerHeight; 84cb93a386Sopenharmony_ci }; 85cb93a386Sopenharmony_ci // return the summary of a single event 86cb93a386Sopenharmony_ci DrawEventSummary event(int nodeId, int frame) const; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci struct LayerSummary { 89cb93a386Sopenharmony_ci int nodeId; 90cb93a386Sopenharmony_ci // Last frame less than or equal to the given frame which has an update for this layer 91cb93a386Sopenharmony_ci // -1 if the layer has no updates satisfying that constraint. 92cb93a386Sopenharmony_ci int frameOfLastUpdate; 93cb93a386Sopenharmony_ci // Whether the last update was a full redraw. 94cb93a386Sopenharmony_ci bool fullRedraw; 95cb93a386Sopenharmony_ci int layerWidth; 96cb93a386Sopenharmony_ci int layerHeight; 97cb93a386Sopenharmony_ci }; 98cb93a386Sopenharmony_ci // Return a list summarizing all layers, with info relevant to the current frame. 99cb93a386Sopenharmony_ci std::vector<LayerSummary> summarizeLayers(int frame) const; 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci // Return the list of node ids which have DrawEvents on the given frame 102cb93a386Sopenharmony_ci std::vector<int> listNodesForFrame(int frame) const; 103cb93a386Sopenharmony_ci // Return the list of frames on which the given node had DrawEvents. 104cb93a386Sopenharmony_ci std::vector<int> listFramesForNode(int nodeId) const; 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci // asks the DebugCanvas of the indicated draw event to serialize it's commands as JSON. 107cb93a386Sopenharmony_ci void toJSON(SkJSONWriter&, UrlDataManager&, SkCanvas*, int nodeId, int frame); 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_ci // return a pointer to the debugcanvas of a given draw event. 110cb93a386Sopenharmony_ci DebugCanvas* getEventDebugCanvas(int nodeid, int frame); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci // forwards the provided setting to all debugcanvases. 113cb93a386Sopenharmony_ci void setOverdrawViz(bool overdrawViz); 114cb93a386Sopenharmony_ci void setClipVizColor(SkColor clipVizColor); 115cb93a386Sopenharmony_ci void setDrawGpuOpBounds(bool drawGpuOpBounds); 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci struct LayerKey{ 118cb93a386Sopenharmony_ci int frame; // frame of animation on which this event was recorded. 119cb93a386Sopenharmony_ci int nodeId; // the render node id of the layer which was drawn to. 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci bool operator==(const LayerKey& b) const { 122cb93a386Sopenharmony_ci return this->frame==b.frame && this->nodeId==b.nodeId; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci }; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci // return list of keys that identify layer update events 127cb93a386Sopenharmony_ci const std::vector<DebugLayerManager::LayerKey>& getKeys() const { return keys; } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ciprivate: 130cb93a386Sopenharmony_ci // This class is basically a map from (frame, node) to draw-event 131cb93a386Sopenharmony_ci // during recording, at the beginning of any frame, one or more layers could have been drawn on. 132cb93a386Sopenharmony_ci // every draw event was recorded, and when reading the mskp file they are stored and organized 133cb93a386Sopenharmony_ci // here. 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci struct DrawEvent { 136cb93a386Sopenharmony_ci // true the pic's clip equals the layer bounds. 137cb93a386Sopenharmony_ci bool fullRedraw; 138cb93a386Sopenharmony_ci // the saved result of how the layer looks on this frame. 139cb93a386Sopenharmony_ci // null if we don't have it. 140cb93a386Sopenharmony_ci sk_sp<SkImage> image; 141cb93a386Sopenharmony_ci // A debug canvas used for drawing this picture. 142cb93a386Sopenharmony_ci // the SkPicture itself isn't saved, since it's in the DebugCanvas. 143cb93a386Sopenharmony_ci std::unique_ptr<DebugCanvas> debugCanvas; 144cb93a386Sopenharmony_ci // the command index where the debugCanvas was left off. 145cb93a386Sopenharmony_ci int command; 146cb93a386Sopenharmony_ci // the size of the layer this drew into. redundant between multiple DrawEvents on the same 147cb93a386Sopenharmony_ci // layer but helpful. 148cb93a386Sopenharmony_ci SkISize layerBounds; 149cb93a386Sopenharmony_ci }; 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci SkTHashMap<LayerKey, DrawEvent> fDraws; 152cb93a386Sopenharmony_ci // The list of all keys in the map above (it has no keys() method) 153cb93a386Sopenharmony_ci std::vector<LayerKey> keys; 154cb93a386Sopenharmony_ci}; 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci#endif 157