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