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