xref: /aosp_15_r20/external/skia/tools/debugger/DebugLayerManager.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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