/src/skia/tools/debugger/DebugLayerManager.h
Line | Count | Source (jump to first uncovered line) |
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: |
47 | 0 | 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, const 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 | 0 | bool operator==(const LayerKey& b) const { |
130 | 0 | return this->frame==b.frame && this->nodeId==b.nodeId; |
131 | 0 | } |
132 | | }; |
133 | | |
134 | | // return list of keys that identify layer update events |
135 | 0 | 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 | | skia_private::THashMap<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 |