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