| /* | 
 |  * Copyright 2019 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #ifndef DEBUGLAYERMANAGER_H_ | 
 | #define DEBUGLAYERMANAGER_H_ | 
 |  | 
 | #include "include/core/SkColor.h" | 
 | #include "include/core/SkImage.h" | 
 | #include "include/core/SkRefCnt.h" | 
 | #include "include/core/SkSize.h" | 
 | #include "src/core/SkTHash.h" | 
 | #include "tools/debugger/DebugCanvas.h" | 
 |  | 
 | #include <memory> | 
 | #include <vector> | 
 |  | 
 | class SkCanvas; | 
 | class SkJSONWriter; | 
 | class SkPicture; | 
 | class SkSurface; | 
 | class UrlDataManager; | 
 | struct SkIRect; | 
 |  | 
 | // A class to assist in playing back and debugging an mskp file containing offscreen layer commands. | 
 |  | 
 | // Holds SkPictures necessary to draw layers in one or more DebugCanvases. During | 
 | // recording of the mskp file on Android, each layer had a RenderNode id, which is recorded with | 
 | // the layer's draw commands. | 
 | // Creates one surface (cpu only for now) for each layer, and renders | 
 | // pictures to it up to the requested command using a DebugCanvas. | 
 |  | 
 | // Animations are expected to, but may not always use a layer on more than frame. | 
 | // the layer may be drawn to more than once, and each different draw is saved for reconstructing the | 
 | // layer as it was on any frame. Draws may be partial, meaning their commands were clipped to not | 
 | // cover the entire layer. | 
 |  | 
 | // Clients may ask for a rendering of a given layer by its RenderNode id and frame, and | 
 | // this class will return a rendering of how it looked on that frame. | 
 | // returning an SkImage snapshot of the internally managed surface. | 
 |  | 
 | class DebugLayerManager { | 
 | public: | 
 |     DebugLayerManager() {} | 
 |  | 
 |     // Store an SkPicture under a given nodeId (and under the currently set frame number) | 
 |     // `dirty` is the recorded rect that was used to call androidFramework_setDeviceClipRestriction | 
 |     // when the layer was drawn. | 
 |     void storeSkPicture(int nodeId, int frame, sk_sp<SkPicture> picture, SkIRect dirty); | 
 |  | 
 |     // Set's the command playback head for a given picture/draw event. | 
 |     void setCommand(int nodeId, int frame, int command); | 
 |  | 
 |     void drawLayerEventTo(SkSurface*, const int nodeId, const int frame); | 
 |  | 
 |     // getLayerAsImage draws the given layer as it would have looked on frame and returns an image. | 
 |     // Though each picture can be played back in as many ways as there are commands, we will let | 
 |     // that be determined by the user who sets an independent playhead for each draw event, tracked | 
 |     // here, so it stays how they left it. | 
 |     // For example: Say we are drawing a layer at frame 10. | 
 |     // Frame 0:  Layer was completely redrawn. By default we draw it to its last command. We always | 
 |     //           save the result by (nodeId, frame) | 
 |     // Frame 5:  Layer was partially redrawn, and the user has inspected this draw event, leaving | 
 |     //           its command playhead at command 50/100. We have drew this at the time and save how | 
 |     //           the result looked (all of the commands at frame 0, then half of the commands in the | 
 |     //           partial draw at frame 5) | 
 |     // Frame 10: Another partial redraw, un-altered, drawn on top of the result from frame 5. We | 
 |     //           return this as the image of how the layer should look on frame 10 | 
 |     // Frame 15: A full redraw | 
 |     // | 
 |     // If the user then comes along and moves the command playhead of the picture at frame 0, | 
 |     // we invalidate the stored images for 0, 5, and 10, but we can leave 15 alone if we have it. | 
 |     // | 
 |     // Which leaves us with one less degree of freedom to think about when implementing this | 
 |     // function: We can assume there is only one way to play back a given picture. :) | 
 |     // | 
 |     // The reason the public version of this function doesn't let you specify the frame, is that | 
 |     // I expect DebugCanvas to call it, which doesn't know which frame it's rendering. The code in | 
 |     // debugger_bindings.cpp does know, which it why I'm having it set the frame via setFrame(int) | 
 |     sk_sp<SkImage> getLayerAsImage(const int nodeId, const int frame); | 
 |  | 
 |     // Flat because it's meant to be bindable by emscripten and returned to the javascript side | 
 |     struct DrawEventSummary { | 
 |         // true when the drawEvent represents a valid result. | 
 |         bool found = false; | 
 |         int commandCount; | 
 |         int layerWidth; | 
 |         int layerHeight; | 
 |     }; | 
 |     // return the summary of a single event | 
 |     DrawEventSummary event(int nodeId, int frame) const; | 
 |  | 
 |     struct LayerSummary { | 
 |         int nodeId; | 
 |         // Last frame less than or equal to the given frame which has an update for this layer | 
 |         // -1 if the layer has no updates satisfying that constraint. | 
 |         int frameOfLastUpdate; | 
 |         // Whether the last update was a full redraw. | 
 |         bool fullRedraw; | 
 |         int layerWidth; | 
 |         int layerHeight; | 
 |     }; | 
 |     // Return a list summarizing all layers, with info relevant to the current frame. | 
 |     std::vector<LayerSummary> summarizeLayers(int frame) const; | 
 |  | 
 |     // Return the list of node ids which have DrawEvents on the given frame | 
 |     std::vector<int> listNodesForFrame(int frame) const; | 
 |     // Return the list of frames on which the given node had DrawEvents. | 
 |     std::vector<int> listFramesForNode(int nodeId) const; | 
 |  | 
 |     // asks the DebugCanvas of the indicated draw event to serialize it's commands as JSON. | 
 |     void toJSON(SkJSONWriter&, UrlDataManager&, SkCanvas*, int nodeId, int frame); | 
 |  | 
 |     // return a pointer to the debugcanvas of a given draw event. | 
 |     DebugCanvas* getEventDebugCanvas(int nodeid, int frame); | 
 |  | 
 |     // forwards the provided setting to all debugcanvases. | 
 |     void setOverdrawViz(bool overdrawViz); | 
 |     void setClipVizColor(SkColor clipVizColor); | 
 |     void setDrawGpuOpBounds(bool drawGpuOpBounds); | 
 |  | 
 |     struct LayerKey{ | 
 |         int frame; // frame of animation on which this event was recorded. | 
 |         int nodeId; // the render node id of the layer which was drawn to. | 
 |  | 
 |         bool operator==(const LayerKey& b) const { | 
 |             return this->frame==b.frame && this->nodeId==b.nodeId; | 
 |         } | 
 |     }; | 
 |  | 
 |     // return list of keys that identify layer update events | 
 |     const std::vector<DebugLayerManager::LayerKey>& getKeys() const { return keys; } | 
 |  | 
 | private: | 
 |     // This class is basically a map from (frame, node) to draw-event | 
 |     // during recording, at the beginning of any frame, one or more layers could have been drawn on. | 
 |     // every draw event was recorded, and when reading the mskp file they are stored and organized | 
 |     // here. | 
 |  | 
 |     struct DrawEvent { | 
 |         // true the pic's clip equals the layer bounds. | 
 |         bool fullRedraw; | 
 |         // the saved result of how the layer looks on this frame. | 
 |         // null if we don't have it. | 
 |         sk_sp<SkImage> image; | 
 |         // A debug canvas used for drawing this picture. | 
 |         // the SkPicture itself isn't saved, since it's in the DebugCanvas. | 
 |         std::unique_ptr<DebugCanvas> debugCanvas; | 
 |         // the command index where the debugCanvas was left off. | 
 |         int command; | 
 |         // the size of the layer this drew into. redundant between multiple DrawEvents on the same | 
 |         // layer but helpful. | 
 |         SkISize layerBounds; | 
 |     }; | 
 |  | 
 |     skia_private::THashMap<LayerKey, DrawEvent> fDraws; | 
 |     // The list of all keys in the map above (it has no keys() method) | 
 |     std::vector<LayerKey> keys; | 
 | }; | 
 |  | 
 | #endif |