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