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