Coverage Report

Created: 2024-05-20 07:14

/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