/src/skia/tools/MSKPPlayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021 Google LLC |
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 MSKPPlayer_DEFINED |
9 | | #define MSKPPlayer_DEFINED |
10 | | |
11 | | #include "include/core/SkRefCnt.h" |
12 | | #include "include/core/SkSize.h" |
13 | | |
14 | | #include <memory> |
15 | | #include <unordered_map> |
16 | | #include <vector> |
17 | | |
18 | | class SkCanvas; |
19 | | class SkImage; |
20 | | class SkStreamSeekable; |
21 | | class SkSurface; |
22 | | |
23 | | /** |
24 | | * Plays frames/pages of a MSKP to a canvas. This class uses the term "frame" as though the MSKP |
25 | | * contains an animation, though it could indeed contain pages of a static document. |
26 | | */ |
27 | | class MSKPPlayer { |
28 | | public: |
29 | | ~MSKPPlayer(); |
30 | | |
31 | | /** Make a player from a MSKP stream, or null if stream can't be read as MSKP. */ |
32 | | static std::unique_ptr<MSKPPlayer> Make(SkStreamSeekable* stream); |
33 | | |
34 | | /** Maximum width and height across all frames. */ |
35 | 0 | SkISize maxDimensions() const { return fMaxDimensions; } |
36 | | |
37 | | /** Total number of frames. */ |
38 | 0 | int numFrames() const { return static_cast<int>(fRootLayers.size()); } |
39 | | |
40 | | /** Size of an individual frame. */ |
41 | | SkISize frameDimensions(int i) const; |
42 | | |
43 | | /** |
44 | | * Plays a frame into the passed canvas. Frames can be randomly accessed. Offscreen layers are |
45 | | * incrementally updated from their current state to the state required for the frame |
46 | | * (redrawing from scratch if their current state is ahead of the passed frame index). |
47 | | */ |
48 | | bool playFrame(SkCanvas* canvas, int i); |
49 | | |
50 | | /** Destroys any cached offscreen layers. */ |
51 | | void resetLayers(); |
52 | | |
53 | | /** |
54 | | * Forces all offscreen layers to re-render the next time they're required for a frame but |
55 | | * preserves the backing stores for them if already allocated. |
56 | | */ |
57 | | void rewindLayers(); |
58 | | |
59 | | /** |
60 | | * Creates backing stores for any offscreen layers using the passed canvas's makeSurface(). |
61 | | * Existing layers that match the canvas's recording context are not reallocated or rewound. |
62 | | */ |
63 | | void allocateLayers(SkCanvas*); |
64 | | |
65 | | /** |
66 | | * A set of IDs of offscreen layers in no particular order. If frame value >= 0 is specified |
67 | | * then the layer set is filtered to layers used by that frame (or empty if >= numFrames). If |
68 | | * < 0 then gathers all the layers across all frames. |
69 | | */ |
70 | | std::vector<int> layerIDs(int frame = -1) const; |
71 | | |
72 | | /** |
73 | | * Gets the contents of an offscreen layer. It's contents will depend on current playback state |
74 | | * (playFrame(), updateFrameLayers(), resetLayers()). If the layer currently has no backing |
75 | | * store because it hasn't been drawn or resetLayers() was called then this will return nullptr. |
76 | | * Layer contents are not affected by rewindLayers() as that simply lazily redraws the frame |
77 | | * contents the next time it is required by playFrame*() or updateFrameLayers(). |
78 | | */ |
79 | | sk_sp<SkImage> layerSnapshot(int layerID) const; |
80 | | |
81 | | private: |
82 | 0 | MSKPPlayer() = default; |
83 | | // noncopyable, nonmoveable. |
84 | | MSKPPlayer(const MSKPPlayer&) = delete; |
85 | | MSKPPlayer(MSKPPlayer&&) = delete; |
86 | | MSKPPlayer& operator=(const MSKPPlayer&) = delete; |
87 | | MSKPPlayer& operator=(MSKPPlayer&&) = delete; |
88 | | |
89 | | // Cmds are used to draw content to the frame root layer and to offscreen layers. |
90 | | struct Cmd; |
91 | | // Draws a SkPicture. |
92 | | struct PicCmd; |
93 | | // Draws another layer. Stores the ID of the layer to draw and what command index on that |
94 | | // layer should be current when the layer is drawn. The layer contents are updated to the |
95 | | // stored command index before the layer is drawn. |
96 | | struct DrawLayerCmd; |
97 | | |
98 | | // The commands for a root/offscreen layer and dimensions of the layer. |
99 | | struct LayerCmds { |
100 | 0 | LayerCmds() = default; |
101 | 0 | LayerCmds(LayerCmds&&) = default; |
102 | | SkISize fDimensions; |
103 | | std::vector<std::unique_ptr<Cmd>> fCmds; |
104 | | }; |
105 | | |
106 | | // Playback state of layer: the last command index drawn to it and the SkSurface with contents. |
107 | | struct LayerState { |
108 | | size_t fCurrCmd = -1; |
109 | | sk_sp<SkSurface> fSurface; |
110 | | }; |
111 | | |
112 | | static sk_sp<SkSurface> MakeSurfaceForLayer(const LayerCmds&, SkCanvas* rootCanvas); |
113 | | |
114 | | void collectReferencedLayers(const LayerCmds& layer, std::vector<int>*) const; |
115 | | |
116 | | // MSKP layer ID -> LayerCmds |
117 | | using LayerMap = std::unordered_map<int, LayerCmds>; |
118 | | // MSKP layer ID -> LayerState |
119 | | using LayerStateMap = std::unordered_map<int, LayerState>; |
120 | | |
121 | | /** |
122 | | * A SkCanvas that consumes the SkPicture and records Cmds into a Layer. It will spawn |
123 | | * additional Layers and record nested SkPictures into those using additional CmdRecordCanvas |
124 | | * CmdRecordCanvas instances. It needs access to fOffscreenLayers to create and update LayerCmds |
125 | | * structs for offscreen layers. |
126 | | */ |
127 | | class CmdRecordCanvas; |
128 | | |
129 | | SkISize fMaxDimensions = {0, 0}; // Max dimensions across all frames. |
130 | | LayerMap fOffscreenLayers; // All the offscreen layers for all frames. |
131 | | LayerStateMap fOffscreenLayerStates; // Current surfaces and command idx for offscreen |
132 | | // layers |
133 | | std::vector<LayerCmds> fRootLayers; // One root layer for each frame. |
134 | | }; |
135 | | |
136 | | #endif |