1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tools/MSKPPlayer.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
11cb93a386Sopenharmony_ci#include "include/core/SkCanvasVirtualEnforcer.h"
12cb93a386Sopenharmony_ci#include "include/core/SkPicture.h"
13cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h"
14cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
15cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
16cb93a386Sopenharmony_ci#include "include/private/SkTArray.h"
17cb93a386Sopenharmony_ci#include "include/utils/SkNoDrawCanvas.h"
18cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h"
19cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h"
20cb93a386Sopenharmony_ci#include "src/utils/SkMultiPictureDocument.h"
21cb93a386Sopenharmony_ci#include "tools/SkSharingProc.h"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci// Base Cmd struct.
26cb93a386Sopenharmony_cistruct MSKPPlayer::Cmd {
27cb93a386Sopenharmony_ci    virtual ~Cmd() = default;
28cb93a386Sopenharmony_ci    virtual bool isFullRedraw(SkCanvas*) const = 0;
29cb93a386Sopenharmony_ci    virtual void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const = 0;
30cb93a386Sopenharmony_ci    // If this command draws another layer, return it's ID. Otherwise, -1.
31cb93a386Sopenharmony_ci    virtual int layerID() const { return -1; }
32cb93a386Sopenharmony_ci};
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci// Draws a SkPicture.
35cb93a386Sopenharmony_cistruct MSKPPlayer::PicCmd : Cmd {
36cb93a386Sopenharmony_ci    sk_sp<SkPicture> fContent;
37cb93a386Sopenharmony_ci    SkIRect fClipRect = SkIRect::MakeEmpty(); // clip for picture (no clip if empty).
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    bool isFullRedraw(SkCanvas* canvas) const override {
40cb93a386Sopenharmony_ci        if (fClipRect.isEmpty()) {
41cb93a386Sopenharmony_ci            return false;
42cb93a386Sopenharmony_ci        }
43cb93a386Sopenharmony_ci        return fClipRect.contains(SkIRect::MakeSize(canvas->getBaseLayerSize()));
44cb93a386Sopenharmony_ci    }
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override {
47cb93a386Sopenharmony_ci        if (!fClipRect.isEmpty()) {
48cb93a386Sopenharmony_ci            canvas->save();
49cb93a386Sopenharmony_ci            canvas->clipIRect(fClipRect);
50cb93a386Sopenharmony_ci        }
51cb93a386Sopenharmony_ci        canvas->drawPicture(fContent.get());
52cb93a386Sopenharmony_ci        if (!fClipRect.isEmpty()) {
53cb93a386Sopenharmony_ci            canvas->restore();
54cb93a386Sopenharmony_ci        }
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci};
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci// Draws another layer. Stores the ID of the layer to draw and what command index on that
59cb93a386Sopenharmony_ci// layer should be current when the layer is drawn. The layer contents are updated to the
60cb93a386Sopenharmony_ci// stored command index before the layer is drawn.
61cb93a386Sopenharmony_cistruct MSKPPlayer::DrawLayerCmd : Cmd {
62cb93a386Sopenharmony_ci    int                         fLayerId;
63cb93a386Sopenharmony_ci    size_t                      fLayerCmdCnt;
64cb93a386Sopenharmony_ci    SkRect                      fSrcRect;
65cb93a386Sopenharmony_ci    SkRect                      fDstRect;
66cb93a386Sopenharmony_ci    SkSamplingOptions           fSampling;
67cb93a386Sopenharmony_ci    SkCanvas::SrcRectConstraint fConstraint;
68cb93a386Sopenharmony_ci    SkTLazy<SkPaint>            fPaint;
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    bool isFullRedraw(SkCanvas* canvas) const override { return false; }
71cb93a386Sopenharmony_ci    void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override;
72cb93a386Sopenharmony_ci    int layerID() const override { return fLayerId; }
73cb93a386Sopenharmony_ci};
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_civoid MSKPPlayer::DrawLayerCmd::draw(SkCanvas* canvas,
76cb93a386Sopenharmony_ci                                    const LayerMap& layerMap,
77cb93a386Sopenharmony_ci                                    LayerStateMap* layerStateMap) const {
78cb93a386Sopenharmony_ci    const LayerCmds& layer = layerMap.at(fLayerId);
79cb93a386Sopenharmony_ci    LayerState* layerState = &(*layerStateMap)[fLayerId];
80cb93a386Sopenharmony_ci    if (!layerState->fSurface) {
81cb93a386Sopenharmony_ci        layerState->fCurrCmd = 0;
82cb93a386Sopenharmony_ci        layerState->fSurface = MSKPPlayer::MakeSurfaceForLayer(layer, canvas);
83cb93a386Sopenharmony_ci        if (!layerState->fSurface) {
84cb93a386Sopenharmony_ci            SkDebugf("Couldn't create surface for layer");
85cb93a386Sopenharmony_ci            return;
86cb93a386Sopenharmony_ci        }
87cb93a386Sopenharmony_ci    }
88cb93a386Sopenharmony_ci    size_t cmd = layerState->fCurrCmd;
89cb93a386Sopenharmony_ci    if (cmd > fLayerCmdCnt) {
90cb93a386Sopenharmony_ci        // If the layer contains contents from later commands then replay from the beginning.
91cb93a386Sopenharmony_ci        cmd = 0;
92cb93a386Sopenharmony_ci    }
93cb93a386Sopenharmony_ci    SkCanvas* layerCanvas = layerState->fSurface->getCanvas();
94cb93a386Sopenharmony_ci    // Check if there is a full redraw between cmd and fLayerCmdCnt and if so jump to it and ensure
95cb93a386Sopenharmony_ci    // we clear the canvas if starting from a full redraw.
96cb93a386Sopenharmony_ci    for (size_t checkCmd = fLayerCmdCnt - 1; checkCmd > cmd; --checkCmd) {
97cb93a386Sopenharmony_ci        if (layer.fCmds[checkCmd]->isFullRedraw(layerCanvas)) {
98cb93a386Sopenharmony_ci            cmd = checkCmd;
99cb93a386Sopenharmony_ci            break;
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci    for (; cmd < fLayerCmdCnt; ++cmd) {
103cb93a386Sopenharmony_ci        if (cmd == 0 || layer.fCmds[cmd]->isFullRedraw(layerCanvas)) {
104cb93a386Sopenharmony_ci            layerState->fSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci        layer.fCmds[cmd]->draw(layerCanvas, layerMap, layerStateMap);
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci    layerState->fCurrCmd = fLayerCmdCnt;
109cb93a386Sopenharmony_ci    const SkPaint* paint = fPaint.isValid() ? fPaint.get() : nullptr;
110cb93a386Sopenharmony_ci    canvas->drawImageRect(layerState->fSurface->makeImageSnapshot(),
111cb93a386Sopenharmony_ci                          fSrcRect,
112cb93a386Sopenharmony_ci                          fDstRect,
113cb93a386Sopenharmony_ci                          fSampling,
114cb93a386Sopenharmony_ci                          paint,
115cb93a386Sopenharmony_ci                          fConstraint);
116cb93a386Sopenharmony_ci}
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ciclass MSKPPlayer::CmdRecordCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {
121cb93a386Sopenharmony_cipublic:
122cb93a386Sopenharmony_ci    CmdRecordCanvas(LayerCmds* dst, LayerMap* offscreenLayers, const SkIRect* clipRect = nullptr)
123cb93a386Sopenharmony_ci            : fDst(dst), fOffscreenLayers(offscreenLayers) {
124cb93a386Sopenharmony_ci        if (clipRect) {
125cb93a386Sopenharmony_ci            fClipRect = *clipRect;
126cb93a386Sopenharmony_ci        }
127cb93a386Sopenharmony_ci        fRecorder.beginRecording(SkRect::Make(dst->fDimensions));
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci    ~CmdRecordCanvas() override { this->recordPicCmd(); }
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ciprotected:
132cb93a386Sopenharmony_ci    void onDrawPaint(const SkPaint& paint) override {
133cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawPaint(paint);
134cb93a386Sopenharmony_ci    }
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    void onDrawBehind(const SkPaint& paint) override {
137cb93a386Sopenharmony_ci        SkCanvasPriv::DrawBehind(fRecorder.getRecordingCanvas(), paint);
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
141cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawRect(rect, paint);
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
145cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawRRect(rrect, paint);
146cb93a386Sopenharmony_ci    }
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
149cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawDRRect(outer, inner, paint);
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci    void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
153cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawOval(rect, paint);
154cb93a386Sopenharmony_ci    }
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    void onDrawArc(const SkRect& rect,
157cb93a386Sopenharmony_ci                   SkScalar startAngle,
158cb93a386Sopenharmony_ci                   SkScalar sweepAngle,
159cb93a386Sopenharmony_ci                   bool useCenter,
160cb93a386Sopenharmony_ci                   const SkPaint& paint) override {
161cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawArc(rect, startAngle, sweepAngle, useCenter, paint);
162cb93a386Sopenharmony_ci    }
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci    void onDrawPath(const SkPath& path, const SkPaint& paint) override {
165cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawPath(path, paint);
166cb93a386Sopenharmony_ci    }
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
169cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawRegion(region, paint);
170cb93a386Sopenharmony_ci    }
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    void onDrawTextBlob(const SkTextBlob* blob,
173cb93a386Sopenharmony_ci                        SkScalar x,
174cb93a386Sopenharmony_ci                        SkScalar y,
175cb93a386Sopenharmony_ci                        const SkPaint& paint) override {
176cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawTextBlob(blob, x, y, paint);
177cb93a386Sopenharmony_ci    }
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ci    void onDrawPatch(const SkPoint cubics[12],
180cb93a386Sopenharmony_ci                     const SkColor colors[4],
181cb93a386Sopenharmony_ci                     const SkPoint texCoords[4],
182cb93a386Sopenharmony_ci                     SkBlendMode mode,
183cb93a386Sopenharmony_ci                     const SkPaint& paint) override {
184cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawPatch(cubics, colors, texCoords, mode, paint);
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci    void onDrawPoints(SkCanvas::PointMode mode,
188cb93a386Sopenharmony_ci                      size_t count,
189cb93a386Sopenharmony_ci                      const SkPoint pts[],
190cb93a386Sopenharmony_ci                      const SkPaint& paint) override {
191cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawPoints(mode, count, pts, paint);
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    void onDrawImage2(const SkImage* image,
195cb93a386Sopenharmony_ci                      SkScalar dx,
196cb93a386Sopenharmony_ci                      SkScalar dy,
197cb93a386Sopenharmony_ci                      const SkSamplingOptions& sampling,
198cb93a386Sopenharmony_ci                      const SkPaint* paint) override {
199cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawImage(image, dx, dy, sampling, paint);
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    void onDrawImageRect2(const SkImage* image,
203cb93a386Sopenharmony_ci                          const SkRect& src,
204cb93a386Sopenharmony_ci                          const SkRect& dst,
205cb93a386Sopenharmony_ci                          const SkSamplingOptions& sampling,
206cb93a386Sopenharmony_ci                          const SkPaint* paint,
207cb93a386Sopenharmony_ci                          SrcRectConstraint constraint) override {
208cb93a386Sopenharmony_ci        if (fNextDrawImageFromLayerID != -1) {
209cb93a386Sopenharmony_ci            this->recordPicCmd();
210cb93a386Sopenharmony_ci            auto drawLayer = std::make_unique<DrawLayerCmd>();
211cb93a386Sopenharmony_ci            drawLayer->fLayerId = fNextDrawImageFromLayerID;
212cb93a386Sopenharmony_ci            drawLayer->fLayerCmdCnt = fOffscreenLayers->at(fNextDrawImageFromLayerID).fCmds.size();
213cb93a386Sopenharmony_ci            drawLayer->fSrcRect = src;
214cb93a386Sopenharmony_ci            drawLayer->fDstRect = dst;
215cb93a386Sopenharmony_ci            drawLayer->fSampling = sampling;
216cb93a386Sopenharmony_ci            drawLayer->fConstraint = constraint;
217cb93a386Sopenharmony_ci            if (paint) {
218cb93a386Sopenharmony_ci                drawLayer->fPaint.init(*paint);
219cb93a386Sopenharmony_ci            }
220cb93a386Sopenharmony_ci            fDst->fCmds.push_back(std::move(drawLayer));
221cb93a386Sopenharmony_ci            fNextDrawImageFromLayerID = -1;
222cb93a386Sopenharmony_ci            return;
223cb93a386Sopenharmony_ci        }
224cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawImageRect(image, src, dst, sampling, paint, constraint);
225cb93a386Sopenharmony_ci    }
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    void onDrawImageLattice2(const SkImage* image,
228cb93a386Sopenharmony_ci                             const Lattice& lattice,
229cb93a386Sopenharmony_ci                             const SkRect& dst,
230cb93a386Sopenharmony_ci                             SkFilterMode mode,
231cb93a386Sopenharmony_ci                             const SkPaint* paint) override {
232cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawImageLattice(image, lattice, dst, mode, paint);
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    void onDrawAtlas2(const SkImage* image,
236cb93a386Sopenharmony_ci                      const SkRSXform rsxForms[],
237cb93a386Sopenharmony_ci                      const SkRect src[],
238cb93a386Sopenharmony_ci                      const SkColor colors[],
239cb93a386Sopenharmony_ci                      int count,
240cb93a386Sopenharmony_ci                      SkBlendMode mode,
241cb93a386Sopenharmony_ci                      const SkSamplingOptions& sampling,
242cb93a386Sopenharmony_ci                      const SkRect* cull,
243cb93a386Sopenharmony_ci                      const SkPaint* paint) override {
244cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawAtlas(image,
245cb93a386Sopenharmony_ci                                                  rsxForms,
246cb93a386Sopenharmony_ci                                                  src,
247cb93a386Sopenharmony_ci                                                  colors,
248cb93a386Sopenharmony_ci                                                  count,
249cb93a386Sopenharmony_ci                                                  mode,
250cb93a386Sopenharmony_ci                                                  sampling,
251cb93a386Sopenharmony_ci                                                  cull,
252cb93a386Sopenharmony_ci                                                  paint);
253cb93a386Sopenharmony_ci    }
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci    void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[],
256cb93a386Sopenharmony_ci                               int count,
257cb93a386Sopenharmony_ci                               const SkPoint dstClips[],
258cb93a386Sopenharmony_ci                               const SkMatrix preViewMatrices[],
259cb93a386Sopenharmony_ci                               const SkSamplingOptions& sampling,
260cb93a386Sopenharmony_ci                               const SkPaint* paint,
261cb93a386Sopenharmony_ci                               SrcRectConstraint constraint) override {
262cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->experimental_DrawEdgeAAImageSet(imageSet,
263cb93a386Sopenharmony_ci                                                                        count,
264cb93a386Sopenharmony_ci                                                                        dstClips,
265cb93a386Sopenharmony_ci                                                                        preViewMatrices,
266cb93a386Sopenharmony_ci                                                                        sampling,
267cb93a386Sopenharmony_ci                                                                        paint,
268cb93a386Sopenharmony_ci                                                                        constraint);
269cb93a386Sopenharmony_ci    }
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
272cb93a386Sopenharmony_ci    void onDrawEdgeAAQuad(const SkRect& rect,
273cb93a386Sopenharmony_ci                          const SkPoint clip[4],
274cb93a386Sopenharmony_ci                          SkCanvas::QuadAAFlags aaFlags,
275cb93a386Sopenharmony_ci                          const SkColor4f& color,
276cb93a386Sopenharmony_ci                          SkBlendMode mode) override {}
277cb93a386Sopenharmony_ci#else
278cb93a386Sopenharmony_ci    void onDrawEdgeAAQuad(const SkRect& rect,
279cb93a386Sopenharmony_ci                          const SkPoint clip[4],
280cb93a386Sopenharmony_ci                          SkCanvas::QuadAAFlags aaFlags,
281cb93a386Sopenharmony_ci                          const SkColor4f& color,
282cb93a386Sopenharmony_ci                          SkBlendMode mode) override {
283cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->experimental_DrawEdgeAAQuad(rect,
284cb93a386Sopenharmony_ci                                                                    clip,
285cb93a386Sopenharmony_ci                                                                    aaFlags,
286cb93a386Sopenharmony_ci                                                                    color,
287cb93a386Sopenharmony_ci                                                                    mode);
288cb93a386Sopenharmony_ci    }
289cb93a386Sopenharmony_ci#endif
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci    void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override {
292cb93a386Sopenharmony_ci        static constexpr char kOffscreenLayerDraw[] = "OffscreenLayerDraw";
293cb93a386Sopenharmony_ci        static constexpr char kSurfaceID[] = "SurfaceID";
294cb93a386Sopenharmony_ci        SkTArray<SkString> tokens;
295cb93a386Sopenharmony_ci        SkStrSplit(key, "|", kStrict_SkStrSplitMode, &tokens);
296cb93a386Sopenharmony_ci        if (tokens.size() == 2) {
297cb93a386Sopenharmony_ci            if (tokens[0].equals(kOffscreenLayerDraw)) {
298cb93a386Sopenharmony_ci                // Indicates that the next drawPicture command contains the SkPicture to render
299cb93a386Sopenharmony_ci                // to the layer identified by the ID. 'rect' indicates the dirty area to update
300cb93a386Sopenharmony_ci                // (and indicates the layer size if this command is introducing a new layer id).
301cb93a386Sopenharmony_ci                fNextDrawPictureToLayerID = std::stoi(tokens[1].c_str());
302cb93a386Sopenharmony_ci                fNextDrawPictureToLayerClipRect = rect.roundOut();
303cb93a386Sopenharmony_ci                if (fOffscreenLayers->find(fNextDrawPictureToLayerID) == fOffscreenLayers->end()) {
304cb93a386Sopenharmony_ci                    SkASSERT(fNextDrawPictureToLayerClipRect.left() == 0 &&
305cb93a386Sopenharmony_ci                             fNextDrawPictureToLayerClipRect.top()  == 0);
306cb93a386Sopenharmony_ci                    (*fOffscreenLayers)[fNextDrawPictureToLayerID].fDimensions =
307cb93a386Sopenharmony_ci                            fNextDrawPictureToLayerClipRect.size();
308cb93a386Sopenharmony_ci                }
309cb93a386Sopenharmony_ci                // The next draw picture will notice that fNextDrawPictureToLayerID is set and
310cb93a386Sopenharmony_ci                // redirect the picture to the offscreen layer.
311cb93a386Sopenharmony_ci                return;
312cb93a386Sopenharmony_ci            } else if (tokens[0].equals(kSurfaceID)) {
313cb93a386Sopenharmony_ci                // Indicates that the following drawImageRect should draw an offscreen layer
314cb93a386Sopenharmony_ci                // to this layer.
315cb93a386Sopenharmony_ci                fNextDrawImageFromLayerID = std::stoi(tokens[1].c_str());
316cb93a386Sopenharmony_ci                return;
317cb93a386Sopenharmony_ci            }
318cb93a386Sopenharmony_ci        }
319cb93a386Sopenharmony_ci    }
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override {
322cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->private_draw_shadow_rec(path, rec);
323cb93a386Sopenharmony_ci    }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
326cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawDrawable(drawable, matrix);
327cb93a386Sopenharmony_ci    }
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    void onDrawPicture(const SkPicture* picture,
330cb93a386Sopenharmony_ci                       const SkMatrix* matrix,
331cb93a386Sopenharmony_ci                       const SkPaint* paint) override {
332cb93a386Sopenharmony_ci        if (fNextDrawPictureToLayerID != -1) {
333cb93a386Sopenharmony_ci            SkASSERT(!matrix);
334cb93a386Sopenharmony_ci            SkASSERT(!paint);
335cb93a386Sopenharmony_ci            LayerCmds* layer = &fOffscreenLayers->at(fNextDrawPictureToLayerID);
336cb93a386Sopenharmony_ci            CmdRecordCanvas sc(layer, fOffscreenLayers, &fNextDrawPictureToLayerClipRect);
337cb93a386Sopenharmony_ci            picture->playback(&sc);
338cb93a386Sopenharmony_ci            fNextDrawPictureToLayerID = -1;
339cb93a386Sopenharmony_ci            fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
340cb93a386Sopenharmony_ci            return;
341cb93a386Sopenharmony_ci        }
342cb93a386Sopenharmony_ci        if (paint) {
343cb93a386Sopenharmony_ci            this->saveLayer(nullptr, paint);
344cb93a386Sopenharmony_ci        }
345cb93a386Sopenharmony_ci        if (matrix) {
346cb93a386Sopenharmony_ci            this->save();
347cb93a386Sopenharmony_ci            this->concat(*matrix);
348cb93a386Sopenharmony_ci        }
349cb93a386Sopenharmony_ci
350cb93a386Sopenharmony_ci        picture->playback(this);
351cb93a386Sopenharmony_ci
352cb93a386Sopenharmony_ci        if (matrix) {
353cb93a386Sopenharmony_ci            this->restore();
354cb93a386Sopenharmony_ci        }
355cb93a386Sopenharmony_ci        if (paint) {
356cb93a386Sopenharmony_ci            this->restore();
357cb93a386Sopenharmony_ci        }
358cb93a386Sopenharmony_ci        fRecorder.getRecordingCanvas()->drawPicture(picture, matrix, paint);
359cb93a386Sopenharmony_ci    }
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_ciprivate:
362cb93a386Sopenharmony_ci    void recordPicCmd() {
363cb93a386Sopenharmony_ci        auto cmd = std::make_unique<PicCmd>();
364cb93a386Sopenharmony_ci        cmd->fContent = fRecorder.finishRecordingAsPicture();
365cb93a386Sopenharmony_ci        cmd->fClipRect = fClipRect;
366cb93a386Sopenharmony_ci        if (cmd->fContent) {
367cb93a386Sopenharmony_ci            fDst->fCmds.push_back(std::move(cmd));
368cb93a386Sopenharmony_ci        }
369cb93a386Sopenharmony_ci        // Set up to accumulate again.
370cb93a386Sopenharmony_ci        fRecorder.beginRecording(SkRect::Make(fDst->fDimensions));
371cb93a386Sopenharmony_ci    }
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ci    SkPictureRecorder fRecorder; // accumulates draws until we draw an offscreen into this layer.
374cb93a386Sopenharmony_ci    LayerCmds*        fDst                            = nullptr;
375cb93a386Sopenharmony_ci    SkIRect           fClipRect                       = SkIRect::MakeEmpty();
376cb93a386Sopenharmony_ci    int               fNextDrawPictureToLayerID       = -1;
377cb93a386Sopenharmony_ci    SkIRect           fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
378cb93a386Sopenharmony_ci    int               fNextDrawImageFromLayerID       = -1;
379cb93a386Sopenharmony_ci    LayerMap*         fOffscreenLayers                = nullptr;
380cb93a386Sopenharmony_ci};
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_cistd::unique_ptr<MSKPPlayer> MSKPPlayer::Make(SkStreamSeekable* stream) {
385cb93a386Sopenharmony_ci    auto deserialContext = std::make_unique<SkSharingDeserialContext>();
386cb93a386Sopenharmony_ci    SkDeserialProcs procs;
387cb93a386Sopenharmony_ci    procs.fImageProc = SkSharingDeserialContext::deserializeImage;
388cb93a386Sopenharmony_ci    procs.fImageCtx = deserialContext.get();
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci    int pageCount = SkMultiPictureDocumentReadPageCount(stream);
391cb93a386Sopenharmony_ci    if (!pageCount) {
392cb93a386Sopenharmony_ci        return nullptr;
393cb93a386Sopenharmony_ci    }
394cb93a386Sopenharmony_ci    std::vector<SkDocumentPage> pages(pageCount);
395cb93a386Sopenharmony_ci    if (!SkMultiPictureDocumentRead(stream, pages.data(), pageCount, &procs)) {
396cb93a386Sopenharmony_ci        return nullptr;
397cb93a386Sopenharmony_ci    }
398cb93a386Sopenharmony_ci    std::unique_ptr<MSKPPlayer> result(new MSKPPlayer);
399cb93a386Sopenharmony_ci    result->fRootLayers.reserve(pages.size());
400cb93a386Sopenharmony_ci    for (const auto& page : pages) {
401cb93a386Sopenharmony_ci        SkISize dims = {SkScalarCeilToInt(page.fSize.width()),
402cb93a386Sopenharmony_ci                        SkScalarCeilToInt(page.fSize.height())};
403cb93a386Sopenharmony_ci        result->fRootLayers.emplace_back();
404cb93a386Sopenharmony_ci        result->fRootLayers.back().fDimensions = dims;
405cb93a386Sopenharmony_ci        result->fMaxDimensions.fWidth  = std::max(dims.width() , result->fMaxDimensions.width() );
406cb93a386Sopenharmony_ci        result->fMaxDimensions.fHeight = std::max(dims.height(), result->fMaxDimensions.height());
407cb93a386Sopenharmony_ci        CmdRecordCanvas sc(&result->fRootLayers.back(), &result->fOffscreenLayers);
408cb93a386Sopenharmony_ci        page.fPicture->playback(&sc);
409cb93a386Sopenharmony_ci    }
410cb93a386Sopenharmony_ci    return result;
411cb93a386Sopenharmony_ci}
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ciMSKPPlayer::~MSKPPlayer() = default;
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ciSkISize MSKPPlayer::frameDimensions(int i) const {
416cb93a386Sopenharmony_ci    if (i < 0 || i >= this->numFrames()) {
417cb93a386Sopenharmony_ci        return {-1, -1};
418cb93a386Sopenharmony_ci    }
419cb93a386Sopenharmony_ci    return fRootLayers[i].fDimensions;
420cb93a386Sopenharmony_ci}
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_cibool MSKPPlayer::playFrame(SkCanvas* canvas, int i) {
423cb93a386Sopenharmony_ci    if (i < 0 || i >= this->numFrames()) {
424cb93a386Sopenharmony_ci        return false;
425cb93a386Sopenharmony_ci    }
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_ci    // Find the first offscreen layer that has a valid surface. If it's recording context
428cb93a386Sopenharmony_ci    // differs from the passed canvas's then reset all the layers. Playback will
429cb93a386Sopenharmony_ci    // automatically allocate new surfaces for offscreen layers as they're encountered.
430cb93a386Sopenharmony_ci    for (const auto& ols : fOffscreenLayerStates) {
431cb93a386Sopenharmony_ci        const LayerState& state = ols.second;
432cb93a386Sopenharmony_ci        if (state.fSurface) {
433cb93a386Sopenharmony_ci            if (state.fSurface->recordingContext() != canvas->recordingContext()) {
434cb93a386Sopenharmony_ci                this->resetLayers();
435cb93a386Sopenharmony_ci            }
436cb93a386Sopenharmony_ci            break;
437cb93a386Sopenharmony_ci        }
438cb93a386Sopenharmony_ci    }
439cb93a386Sopenharmony_ci
440cb93a386Sopenharmony_ci    // Replay all the commands for this frame to the caller's canvas.
441cb93a386Sopenharmony_ci    const LayerCmds& layer = fRootLayers[i];
442cb93a386Sopenharmony_ci    for (const auto& cmd : layer.fCmds) {
443cb93a386Sopenharmony_ci        cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
444cb93a386Sopenharmony_ci    }
445cb93a386Sopenharmony_ci    return true;
446cb93a386Sopenharmony_ci}
447cb93a386Sopenharmony_ci
448cb93a386Sopenharmony_cisk_sp<SkSurface> MSKPPlayer::MakeSurfaceForLayer(const LayerCmds& layer, SkCanvas* rootCanvas) {
449cb93a386Sopenharmony_ci    // Assume layer has same surface props and info as this (mskp doesn't currently record this
450cb93a386Sopenharmony_ci    // data).
451cb93a386Sopenharmony_ci    SkSurfaceProps props;
452cb93a386Sopenharmony_ci    rootCanvas->getProps(&props);
453cb93a386Sopenharmony_ci    return rootCanvas->makeSurface(rootCanvas->imageInfo().makeDimensions(layer.fDimensions),
454cb93a386Sopenharmony_ci                                   &props);
455cb93a386Sopenharmony_ci}
456cb93a386Sopenharmony_ci
457cb93a386Sopenharmony_civoid MSKPPlayer::resetLayers() { fOffscreenLayerStates.clear(); }
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_civoid MSKPPlayer::rewindLayers() {
460cb93a386Sopenharmony_ci    for (auto& [id, state] : fOffscreenLayerStates) {
461cb93a386Sopenharmony_ci        state.fCurrCmd = -1;
462cb93a386Sopenharmony_ci    }
463cb93a386Sopenharmony_ci}
464cb93a386Sopenharmony_ci
465cb93a386Sopenharmony_civoid MSKPPlayer::allocateLayers(SkCanvas* canvas) {
466cb93a386Sopenharmony_ci    // Iterate over layers not states as states are lazily created in playback but here we want to
467cb93a386Sopenharmony_ci    // create any that don't already exist.
468cb93a386Sopenharmony_ci    for (auto& [id, layer] : fOffscreenLayers) {
469cb93a386Sopenharmony_ci        LayerState& state = fOffscreenLayerStates[id];
470cb93a386Sopenharmony_ci        if (!state.fSurface || state.fSurface->recordingContext() != canvas->recordingContext()) {
471cb93a386Sopenharmony_ci            state.fCurrCmd = -1;
472cb93a386Sopenharmony_ci            state.fSurface = MakeSurfaceForLayer(fOffscreenLayers[id], canvas);
473cb93a386Sopenharmony_ci        }
474cb93a386Sopenharmony_ci    }
475cb93a386Sopenharmony_ci}
476cb93a386Sopenharmony_ci
477cb93a386Sopenharmony_cistd::vector<int> MSKPPlayer::layerIDs(int frame) const {
478cb93a386Sopenharmony_ci    std::vector<int> result;
479cb93a386Sopenharmony_ci    if (frame < 0) {
480cb93a386Sopenharmony_ci        result.reserve(fOffscreenLayers.size());
481cb93a386Sopenharmony_ci        for (auto& [id, _] : fOffscreenLayers) {
482cb93a386Sopenharmony_ci            result.push_back(id);
483cb93a386Sopenharmony_ci        }
484cb93a386Sopenharmony_ci        return result;
485cb93a386Sopenharmony_ci    }
486cb93a386Sopenharmony_ci    if (frame < static_cast<int>(fRootLayers.size())) {
487cb93a386Sopenharmony_ci        this->collectReferencedLayers(fRootLayers[frame], &result);
488cb93a386Sopenharmony_ci    }
489cb93a386Sopenharmony_ci    return result;
490cb93a386Sopenharmony_ci}
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_cisk_sp<SkImage> MSKPPlayer::layerSnapshot(int layerID) const {
493cb93a386Sopenharmony_ci    auto iter = fOffscreenLayerStates.find(layerID);
494cb93a386Sopenharmony_ci    if (iter == fOffscreenLayerStates.end() || !iter->second.fSurface) {
495cb93a386Sopenharmony_ci        return nullptr;
496cb93a386Sopenharmony_ci    }
497cb93a386Sopenharmony_ci    return iter->second.fSurface->makeImageSnapshot();
498cb93a386Sopenharmony_ci}
499cb93a386Sopenharmony_ci
500cb93a386Sopenharmony_civoid MSKPPlayer::collectReferencedLayers(const LayerCmds& layer, std::vector<int>* out) const {
501cb93a386Sopenharmony_ci    for (const auto& cmd : layer.fCmds) {
502cb93a386Sopenharmony_ci        if (int id = cmd->layerID(); id >= 0) {
503cb93a386Sopenharmony_ci            // Linear, but we'd need to have a lot of layers to actually care.
504cb93a386Sopenharmony_ci            if (std::find(out->begin(), out->end(), id) == out->end()) {
505cb93a386Sopenharmony_ci                out->push_back(id);
506cb93a386Sopenharmony_ci                auto iter = fOffscreenLayers.find(id);
507cb93a386Sopenharmony_ci                SkASSERT(iter != fOffscreenLayers.end());
508cb93a386Sopenharmony_ci                this->collectReferencedLayers(iter->second, out);
509cb93a386Sopenharmony_ci            }
510cb93a386Sopenharmony_ci        }
511cb93a386Sopenharmony_ci    }
512cb93a386Sopenharmony_ci}
513