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