Coverage Report

Created: 2024-05-20 07:14

/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