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. */ maxDimensions()35 SkISize maxDimensions() const { return fMaxDimensions; } 36 37 /** Total number of frames. */ numFrames()38 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 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 LayerCmds() = default; 101 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 137