Flutter Engine
The Flutter Engine
DebugLayerManager.h
Go to the documentation of this file.
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
14#include "include/core/SkSize.h"
15#include "src/core/SkTHash.h"
17
18#include <memory>
19#include <vector>
20
21class SkCanvas;
22class SkJSONWriter;
23class SkPicture;
24class SkSurface;
25class UrlDataManager;
26struct 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
46public:
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
87 // true when the drawEvent represents a valid result.
88 bool found = false;
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.
101 // Whether the last update was a full redraw.
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
135 const std::vector<DebugLayerManager::LayerKey>& getKeys() const { return keys; }
136
137private:
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.
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
160 // The list of all keys in the map above (it has no keys() method)
161 std::vector<LayerKey> keys;
162};
163
164#endif
uint32_t SkColor
Definition: SkColor.h:37
DrawEventSummary event(int nodeId, int frame) const
std::vector< int > listNodesForFrame(int frame) const
void setCommand(int nodeId, int frame, int command)
DebugCanvas * getEventDebugCanvas(int nodeid, int frame)
void drawLayerEventTo(SkSurface *, const int nodeId, const int frame)
void setClipVizColor(SkColor clipVizColor)
void setOverdrawViz(bool overdrawViz)
void storeSkPicture(int nodeId, int frame, const sk_sp< SkPicture > &picture, SkIRect dirty)
const std::vector< DebugLayerManager::LayerKey > & getKeys() const
void setDrawGpuOpBounds(bool drawGpuOpBounds)
void toJSON(SkJSONWriter &, UrlDataManager &, SkCanvas *, int nodeId, int frame)
std::vector< int > listFramesForNode(int nodeId) const
sk_sp< SkImage > getLayerAsImage(const int nodeId, const int frame)
std::vector< LayerSummary > summarizeLayers(int frame) const
double frame
Definition: examples.cpp:31
static bool b
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299
list command
Definition: valgrind.py:24
bool operator==(const LayerKey &b) const
Definition: SkRect.h:32
Definition: SkSize.h:16