Revert "Add mskp player, use in viewer slide"
This reverts commit 9230fc59b7
.
Reason for revert: broke something in housekeeping docker build.
Original change's description:
> Add mskp player, use in viewer slide
>
> viewer now takes --mskps <dir> and will have a slide per mskp and
> overview slide (just like --skps).
>
> Player uses offscreen surfaces to draw offscreen layers, allows
> random access to mskp frames.
>
> slide just plays mskp at fixed frame rate (for now).
>
> Bug: skia:11900
> Change-Id: I66104ffe88f5df721a1a835570acc3e4c23c3f07
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/400537
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Jim Van Verth <jvanverth@google.com>
TBR=jvanverth@google.com,bsalomon@google.com,nifong@google.com
Change-Id: I97fb7a64d5ef2ca14dba1cf9e2ba91ab0e9d0018
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:11900
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/402639
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
1450643c1d
commit
0d174586c4
9
BUILD.gn
9
BUILD.gn
@ -1679,11 +1679,6 @@ if (skia_enable_tools) {
|
||||
"trim string")) {
|
||||
data_sources += [ "skps" ]
|
||||
}
|
||||
if ("True" == exec_script("//gn/checkdir.py",
|
||||
[ rebase_path("mskps", root_build_dir) ],
|
||||
"trim string")) {
|
||||
data_sources += [ "mskps" ]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# !is_ios
|
||||
@ -1882,8 +1877,6 @@ if (skia_enable_tools) {
|
||||
"tools/DDLTileHelper.cpp",
|
||||
"tools/DDLTileHelper.h",
|
||||
"tools/LsanSuppressions.cpp",
|
||||
"tools/MSKPPlayer.cpp",
|
||||
"tools/MSKPPlayer.h",
|
||||
"tools/ProcStats.cpp",
|
||||
"tools/ProcStats.h",
|
||||
"tools/Resources.cpp",
|
||||
@ -2714,8 +2707,6 @@ if (skia_enable_tools) {
|
||||
"tools/viewer/ImGuiLayer.h",
|
||||
"tools/viewer/ImageSlide.cpp",
|
||||
"tools/viewer/ImageSlide.h",
|
||||
"tools/viewer/MSKPSlide.cpp",
|
||||
"tools/viewer/MSKPSlide.h",
|
||||
"tools/viewer/ParticlesSlide.cpp",
|
||||
"tools/viewer/ParticlesSlide.h",
|
||||
"tools/viewer/SKPSlide.cpp",
|
||||
|
@ -199,9 +199,6 @@ bool SkMultiPictureDocumentRead(SkStreamSeekable* stream,
|
||||
}
|
||||
|
||||
auto picture = SkPicture::MakeFromStream(stream, procs);
|
||||
if (!picture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PagerCanvas canvas(joined.toCeil(), dstArray, dstArrayCount);
|
||||
// Must call playback(), not drawPicture() to reach
|
||||
|
@ -1,412 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tools/MSKPPlayer.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkCanvasVirtualEnforcer.h"
|
||||
#include "include/core/SkPicture.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/private/SkTArray.h"
|
||||
#include "include/utils/SkNoDrawCanvas.h"
|
||||
#include "src/core/SkCanvasPriv.h"
|
||||
#include "src/utils/SkMultiPictureDocument.h"
|
||||
#include "tools/SkSharingProc.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Base Cmd struct.
|
||||
struct MSKPPlayer::Cmd {
|
||||
virtual ~Cmd() = default;
|
||||
virtual void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const = 0;
|
||||
};
|
||||
|
||||
// Draws a SkPicture.
|
||||
struct MSKPPlayer::PicCmd : Cmd {
|
||||
sk_sp<SkPicture> fContent;
|
||||
|
||||
void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override {
|
||||
canvas->drawPicture(fContent.get());
|
||||
}
|
||||
};
|
||||
|
||||
// Draws another layer. Stores the ID of the layer to draw and what command index on that
|
||||
// layer should be current when the layer is drawn. The layer contents are updated to the
|
||||
// stored command index before the layer is drawn.
|
||||
struct MSKPPlayer::DrawLayerCmd : Cmd {
|
||||
int fLayerId;
|
||||
size_t fLayerCmdCnt;
|
||||
SkRect fSrcRect;
|
||||
SkRect fDstRect;
|
||||
SkSamplingOptions fSampling;
|
||||
SkCanvas::SrcRectConstraint fConstraint;
|
||||
std::optional<SkPaint> fPaint;
|
||||
|
||||
void draw(SkCanvas* canvas, const LayerMap&, LayerStateMap*) const override;
|
||||
};
|
||||
|
||||
void MSKPPlayer::DrawLayerCmd::draw(SkCanvas* canvas,
|
||||
const LayerMap& layerMap,
|
||||
LayerStateMap* layerStateMap) const {
|
||||
const Layer& layer = layerMap.at(fLayerId);
|
||||
LayerState* layerState = &(*layerStateMap)[fLayerId];
|
||||
if (!layerState->fSurface) {
|
||||
layerState->fCurrCmd = 0;
|
||||
// Assume layer has same surface props and info as this (mskp doesn't currently record this
|
||||
// data).
|
||||
SkSurfaceProps props;
|
||||
canvas->getProps(&props);
|
||||
layerState->fSurface =
|
||||
canvas->makeSurface(canvas->imageInfo().makeDimensions(layer.fDimensions), &props);
|
||||
if (!layerState->fSurface) {
|
||||
SkDebugf("Couldn't create surface for layer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t cmd = layerState->fCurrCmd;
|
||||
if (cmd > fLayerCmdCnt) {
|
||||
// If the layer contains contents from later commands then replay from the beginning.
|
||||
cmd = 0;
|
||||
}
|
||||
SkCanvas* layerCanvas = layerState->fSurface->getCanvas();
|
||||
for (; cmd < fLayerCmdCnt; ++cmd) {
|
||||
layer.fCmds[cmd]->draw(layerCanvas, layerMap, layerStateMap);
|
||||
}
|
||||
const SkPaint* paint = fPaint.has_value() ? &fPaint.value() : nullptr;
|
||||
canvas->drawImageRect(layerState->fSurface->makeImageSnapshot(),
|
||||
fSrcRect,
|
||||
fDstRect,
|
||||
fSampling,
|
||||
paint,
|
||||
fConstraint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class MSKPPlayer::CmdRecordCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {
|
||||
public:
|
||||
CmdRecordCanvas(Layer* dst, LayerMap* offscreenLayers)
|
||||
: fDst(dst), fOffscreenLayers(offscreenLayers) {
|
||||
fRecorder.beginRecording(SkRect::Make(dst->fDimensions));
|
||||
}
|
||||
~CmdRecordCanvas() override { this->recordPicCmd(); }
|
||||
|
||||
protected:
|
||||
void onDrawPaint(const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawPaint(paint);
|
||||
}
|
||||
|
||||
void onDrawBehind(const SkPaint& paint) override {
|
||||
SkCanvasPriv::DrawBehind(fRecorder.getRecordingCanvas(), paint);
|
||||
}
|
||||
|
||||
void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawRect(rect, paint);
|
||||
}
|
||||
|
||||
void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawRRect(rrect, paint);
|
||||
}
|
||||
|
||||
void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawDRRect(outer, inner, paint);
|
||||
}
|
||||
|
||||
void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawOval(rect, paint);
|
||||
}
|
||||
|
||||
void onDrawArc(const SkRect& rect,
|
||||
SkScalar startAngle,
|
||||
SkScalar sweepAngle,
|
||||
bool useCenter,
|
||||
const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawArc(rect, startAngle, sweepAngle, useCenter, paint);
|
||||
}
|
||||
|
||||
void onDrawPath(const SkPath& path, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawPath(path, paint);
|
||||
}
|
||||
|
||||
void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawRegion(region, paint);
|
||||
}
|
||||
|
||||
void onDrawTextBlob(const SkTextBlob* blob,
|
||||
SkScalar x,
|
||||
SkScalar y,
|
||||
const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawTextBlob(blob, x, y, paint);
|
||||
}
|
||||
|
||||
void onDrawPatch(const SkPoint cubics[12],
|
||||
const SkColor colors[4],
|
||||
const SkPoint texCoords[4],
|
||||
SkBlendMode mode,
|
||||
const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawPatch(cubics, colors, texCoords, mode, paint);
|
||||
}
|
||||
|
||||
void onDrawPoints(SkCanvas::PointMode mode,
|
||||
size_t count,
|
||||
const SkPoint pts[],
|
||||
const SkPaint& paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawPoints(mode, count, pts, paint);
|
||||
}
|
||||
|
||||
void onDrawImage2(const SkImage* image,
|
||||
SkScalar dx,
|
||||
SkScalar dy,
|
||||
const SkSamplingOptions& sampling,
|
||||
const SkPaint* paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawImage(image, dx, dy, sampling, paint);
|
||||
}
|
||||
|
||||
void onDrawImageRect2(const SkImage* image,
|
||||
const SkRect& src,
|
||||
const SkRect& dst,
|
||||
const SkSamplingOptions& sampling,
|
||||
const SkPaint* paint,
|
||||
SrcRectConstraint constraint) override {
|
||||
if (fNextDrawImageFromLayerID != -1) {
|
||||
this->recordPicCmd();
|
||||
auto drawLayer = std::make_unique<DrawLayerCmd>();
|
||||
drawLayer->fLayerId = fNextDrawImageFromLayerID;
|
||||
drawLayer->fLayerCmdCnt = fOffscreenLayers->at(fNextDrawImageFromLayerID).fCmds.size();
|
||||
drawLayer->fSrcRect = src;
|
||||
drawLayer->fDstRect = dst;
|
||||
drawLayer->fSampling = sampling;
|
||||
drawLayer->fConstraint = constraint;
|
||||
if (paint) {
|
||||
drawLayer->fPaint.emplace(*paint);
|
||||
}
|
||||
fDst->fCmds.push_back(std::move(drawLayer));
|
||||
fNextDrawImageFromLayerID = -1;
|
||||
return;
|
||||
}
|
||||
fRecorder.getRecordingCanvas()->drawImageRect(image, src, dst, sampling, paint, constraint);
|
||||
}
|
||||
|
||||
void onDrawImageLattice2(const SkImage* image,
|
||||
const Lattice& lattice,
|
||||
const SkRect& dst,
|
||||
SkFilterMode mode,
|
||||
const SkPaint* paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawImageLattice(image, lattice, dst, mode, paint);
|
||||
}
|
||||
|
||||
void onDrawAtlas2(const SkImage* image,
|
||||
const SkRSXform rsxForms[],
|
||||
const SkRect src[],
|
||||
const SkColor colors[],
|
||||
int count,
|
||||
SkBlendMode mode,
|
||||
const SkSamplingOptions& sampling,
|
||||
const SkRect* cull,
|
||||
const SkPaint* paint) override {
|
||||
fRecorder.getRecordingCanvas()->drawAtlas(image,
|
||||
rsxForms,
|
||||
src,
|
||||
colors,
|
||||
count,
|
||||
mode,
|
||||
sampling,
|
||||
cull,
|
||||
paint);
|
||||
}
|
||||
|
||||
void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[],
|
||||
int count,
|
||||
const SkPoint dstClips[],
|
||||
const SkMatrix preViewMatrices[],
|
||||
const SkSamplingOptions& sampling,
|
||||
const SkPaint* paint,
|
||||
SrcRectConstraint constraint) override {
|
||||
fRecorder.getRecordingCanvas()->experimental_DrawEdgeAAImageSet(imageSet,
|
||||
count,
|
||||
dstClips,
|
||||
preViewMatrices,
|
||||
sampling,
|
||||
paint,
|
||||
constraint);
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
void onDrawEdgeAAQuad(const SkRect& rect,
|
||||
const SkPoint clip[4],
|
||||
SkCanvas::QuadAAFlags aaFlags,
|
||||
const SkColor4f& color,
|
||||
SkBlendMode mode) override {}
|
||||
#else
|
||||
void onDrawEdgeAAQuad(const SkRect& rect,
|
||||
const SkPoint clip[4],
|
||||
SkCanvas::QuadAAFlags aaFlags,
|
||||
const SkColor4f& color,
|
||||
SkBlendMode mode) override {
|
||||
fRecorder.getRecordingCanvas()->experimental_DrawEdgeAAQuad(rect,
|
||||
clip,
|
||||
aaFlags,
|
||||
color,
|
||||
mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override {
|
||||
static constexpr char kOffscreenLayerDraw[] = "OffscreenLayerDraw";
|
||||
static constexpr char kSurfaceID[] = "SurfaceID";
|
||||
SkTArray<SkString> tokens;
|
||||
SkStrSplit(key, "|", kStrict_SkStrSplitMode, &tokens);
|
||||
if (tokens.size() == 2) {
|
||||
if (tokens[0].equals(kOffscreenLayerDraw)) {
|
||||
// Indicates that the next drawPicture command contains the SkPicture to render
|
||||
// to the layer identified by the ID. 'rect' indicates the dirty area to update
|
||||
// (and indicates the layer size if this command is introducing a new layer id).
|
||||
fNextDrawToLayerID = std::stoi(tokens[1].c_str());
|
||||
if (fOffscreenLayers->find(fNextDrawToLayerID) == fOffscreenLayers->end()) {
|
||||
SkASSERT(rect.left() == 0 && rect.top() == 0);
|
||||
SkISize size = {SkScalarCeilToInt(rect.right()),
|
||||
SkScalarCeilToInt(rect.bottom())};
|
||||
(*fOffscreenLayers)[fNextDrawToLayerID].fDimensions = size;
|
||||
}
|
||||
// The next draw picture will notice that fNextDrawLayerID is set and redirect
|
||||
// the picture to the offscreen layer.
|
||||
return;
|
||||
} else if (tokens[0].equals(kSurfaceID)) {
|
||||
// Indicates that the following drawImageRect should draw an offscreen layer
|
||||
// to this layer.
|
||||
fNextDrawImageFromLayerID = std::stoi(tokens[1].c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override {
|
||||
fRecorder.getRecordingCanvas()->private_draw_shadow_rec(path, rec);
|
||||
}
|
||||
|
||||
void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
|
||||
fRecorder.getRecordingCanvas()->drawDrawable(drawable, matrix);
|
||||
}
|
||||
|
||||
void onDrawPicture(const SkPicture* picture,
|
||||
const SkMatrix* matrix,
|
||||
const SkPaint* paint) override {
|
||||
if (fNextDrawToLayerID != -1) {
|
||||
SkASSERT(!matrix);
|
||||
SkASSERT(!paint);
|
||||
CmdRecordCanvas sc(&fOffscreenLayers->at(fNextDrawToLayerID), fOffscreenLayers);
|
||||
picture->playback(&sc);
|
||||
fNextDrawToLayerID = -1;
|
||||
return;
|
||||
}
|
||||
if (paint) {
|
||||
this->saveLayer(nullptr, paint);
|
||||
}
|
||||
if (matrix) {
|
||||
this->save();
|
||||
this->concat(*matrix);
|
||||
}
|
||||
|
||||
picture->playback(this);
|
||||
|
||||
if (matrix) {
|
||||
this->restore();
|
||||
}
|
||||
if (paint) {
|
||||
this->restore();
|
||||
}
|
||||
fRecorder.getRecordingCanvas()->drawPicture(picture, matrix, paint);
|
||||
}
|
||||
|
||||
private:
|
||||
void recordPicCmd() {
|
||||
auto cmd = std::make_unique<PicCmd>();
|
||||
cmd->fContent = fRecorder.finishRecordingAsPicture();
|
||||
if (cmd->fContent) {
|
||||
fDst->fCmds.push_back(std::move(cmd));
|
||||
}
|
||||
// Set up to accumulate again.
|
||||
fRecorder.beginRecording(SkRect::Make(fDst->fDimensions));
|
||||
}
|
||||
|
||||
SkPictureRecorder fRecorder; // accumulates draws until we draw an offscreen into this layer.
|
||||
Layer* fDst = nullptr;
|
||||
int fNextDrawToLayerID = -1;
|
||||
int fNextDrawImageFromLayerID = -1;
|
||||
LayerMap* fOffscreenLayers = nullptr;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<MSKPPlayer> MSKPPlayer::Make(SkStreamSeekable* stream) {
|
||||
auto deserialContext = std::make_unique<SkSharingDeserialContext>();
|
||||
SkDeserialProcs procs;
|
||||
procs.fImageProc = SkSharingDeserialContext::deserializeImage;
|
||||
procs.fImageCtx = deserialContext.get();
|
||||
|
||||
int pageCount = SkMultiPictureDocumentReadPageCount(stream);
|
||||
if (!pageCount) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<SkDocumentPage> pages(pageCount);
|
||||
if (!SkMultiPictureDocumentRead(stream, pages.data(), pageCount, &procs)) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<MSKPPlayer> result(new MSKPPlayer);
|
||||
result->fRootLayers.reserve(pages.size());
|
||||
for (const auto& page : pages) {
|
||||
SkISize dims = {SkScalarCeilToInt(page.fSize.width()),
|
||||
SkScalarCeilToInt(page.fSize.height())};
|
||||
result->fRootLayers.emplace_back();
|
||||
result->fRootLayers.back().fDimensions = dims;
|
||||
result->fMaxDimensions.fWidth = std::max(dims.width() , result->fMaxDimensions.width() );
|
||||
result->fMaxDimensions.fHeight = std::max(dims.height(), result->fMaxDimensions.height());
|
||||
CmdRecordCanvas sc(&result->fRootLayers.back(), &result->fOffscreenLayers);
|
||||
page.fPicture->playback(&sc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MSKPPlayer::~MSKPPlayer() = default;
|
||||
|
||||
SkISize MSKPPlayer::frameDimensions(int i) const {
|
||||
if (i < 0 || i >= this->numFrames()) {
|
||||
return {-1, -1};
|
||||
}
|
||||
return fRootLayers[i].fDimensions;
|
||||
}
|
||||
|
||||
bool MSKPPlayer::playFrame(SkCanvas* canvas, int i) {
|
||||
if (i < 0 || i >= this->numFrames()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the first offscreen layer that has a valid surface. If it's recording context
|
||||
// differs from the passed canvas's then reset all the layers. Playback will
|
||||
// automatically allocate new surfaces for offscreen layers as they're encountered.
|
||||
for (const auto& ols : fOffscreenLayerStates) {
|
||||
const LayerState& state = ols.second;
|
||||
if (state.fSurface) {
|
||||
if (state.fSurface->recordingContext() != canvas->recordingContext()) {
|
||||
this->resetLayers();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Replay all the commands for this frame to the caller's canvas.
|
||||
const Layer& layer = fRootLayers[i];
|
||||
for (const auto& cmd : layer.fCmds) {
|
||||
cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MSKPPlayer::resetLayers() { fOffscreenLayerStates.clear(); }
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef MSKPPlayer_DEFINED
|
||||
#define MSKPPlayer_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSize.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class SkCanvas;
|
||||
class SkStreamSeekable;
|
||||
class SkSurface;
|
||||
|
||||
/**
|
||||
* Plays frames/pages of a MSKP to a canvas. This class uses the term "frame" as though the MSKP
|
||||
* contains an animation, though it could indeed contain pages of a static document.
|
||||
*/
|
||||
class MSKPPlayer {
|
||||
public:
|
||||
~MSKPPlayer();
|
||||
|
||||
/** Make a player from a MSKP stream, or null if stream can't be read as MSKP. */
|
||||
static std::unique_ptr<MSKPPlayer> Make(SkStreamSeekable* stream);
|
||||
|
||||
/** Maximum width and height across all frames. */
|
||||
SkISize maxDimensions() const { return fMaxDimensions; }
|
||||
|
||||
/** Total number of frames. */
|
||||
int numFrames() const { return static_cast<int>(fRootLayers.size()); }
|
||||
|
||||
/** Size of an individual frame. */
|
||||
SkISize frameDimensions(int i) const;
|
||||
|
||||
/**
|
||||
* Plays a frame into the passed canvas. Frames can be randomly accessed. Offscreen layers are
|
||||
* incrementally updated from their current state to the state required for the frame
|
||||
* (redrawing from scratch if their current state is ahead of the passed frame index).
|
||||
*/
|
||||
bool playFrame(SkCanvas* canvas, int i);
|
||||
|
||||
/** Destroys any cached offscreen layers. */
|
||||
void resetLayers();
|
||||
|
||||
private:
|
||||
MSKPPlayer() = default;
|
||||
// noncopyable, nonmoveable.
|
||||
MSKPPlayer(const MSKPPlayer&) = delete;
|
||||
MSKPPlayer(MSKPPlayer&&) = delete;
|
||||
MSKPPlayer& operator=(const MSKPPlayer&) = delete;
|
||||
MSKPPlayer& operator=(MSKPPlayer&&) = delete;
|
||||
|
||||
// Cmds are used to draw content to the frame root layer and to offscreen layers.
|
||||
struct Cmd;
|
||||
// Draws a SkPicture.
|
||||
struct PicCmd;
|
||||
// Draws another layer. Stores the ID of the layer to draw and what command index on that
|
||||
// layer should be current when the layer is drawn. The layer contents are updated to the
|
||||
// stored command index before the layer is drawn.
|
||||
struct DrawLayerCmd;
|
||||
|
||||
// The commands for a root/offscreen layer and dimensions of the layer.
|
||||
struct Layer {
|
||||
Layer() = default;
|
||||
Layer(Layer&&) = default;
|
||||
SkISize fDimensions;
|
||||
std::vector<std::unique_ptr<Cmd>> fCmds;
|
||||
};
|
||||
|
||||
// Playback state of layer: the last command index drawn to it and the SkSurface with contents.
|
||||
struct LayerState {
|
||||
size_t fCurrCmd = -1;
|
||||
sk_sp<SkSurface> fSurface;
|
||||
};
|
||||
|
||||
// MSKP layer ID -> Layer
|
||||
using LayerMap = std::unordered_map<int, Layer>;
|
||||
// MSKP layer ID -> LayerState
|
||||
using LayerStateMap = std::unordered_map<int, LayerState>;
|
||||
|
||||
/**
|
||||
* A SkCanvas that consumes the SkPicture and records Cmds into a Layer. It will spawn
|
||||
* additional Layers and record nested SkPictures into those using additional CmdRecordCanvas
|
||||
* CmdRecordCanvas instances. It needs access to fOffscreenLayers to create and update Layer
|
||||
* structs for offscreen layers.
|
||||
*/
|
||||
class CmdRecordCanvas;
|
||||
|
||||
SkISize fMaxDimensions = {0, 0}; // Max dimensions across all frames.
|
||||
LayerMap fOffscreenLayers; // All the offscreen layers for all frames.
|
||||
LayerStateMap fOffscreenLayerStates; // Current surfaces and command idx for offscreen
|
||||
// layers
|
||||
std::vector<Layer> fRootLayers; // One root layer for each frame.
|
||||
};
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tools/viewer/MSKPSlide.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkStream.h"
|
||||
#include "src/core/SkOSFile.h"
|
||||
|
||||
MSKPSlide::MSKPSlide(const SkString& name, const SkString& path)
|
||||
: MSKPSlide(name, SkStream::MakeFromFile(path.c_str())) {}
|
||||
|
||||
MSKPSlide::MSKPSlide(const SkString& name, std::unique_ptr<SkStreamSeekable> stream)
|
||||
: fStream(std::move(stream)) {
|
||||
fName = name;
|
||||
}
|
||||
|
||||
SkISize MSKPSlide::getDimensions() const {
|
||||
return fPlayer ? fPlayer->maxDimensions() : SkISize{0, 0};
|
||||
}
|
||||
|
||||
void MSKPSlide::draw(SkCanvas* canvas) {
|
||||
if (fPlayer) {
|
||||
fPlayer->playFrame(canvas, fFrame);
|
||||
}
|
||||
}
|
||||
|
||||
bool MSKPSlide::animate(double nanos) {
|
||||
if (!fPlayer) {
|
||||
return false;
|
||||
}
|
||||
double elapsed = nanos - fLastFrameTime;
|
||||
double frameTime = 1E9/fFPS;
|
||||
int framesToAdvance = elapsed/frameTime;
|
||||
fFrame = (fFrame + framesToAdvance)%fPlayer->numFrames();
|
||||
// Instead of just adding elapsed, note the time when this frame should have begun.
|
||||
fLastFrameTime += framesToAdvance*frameTime;
|
||||
return framesToAdvance%fPlayer->numFrames() != 0;
|
||||
}
|
||||
|
||||
void MSKPSlide::load(SkScalar, SkScalar) {
|
||||
if (!fStream) {
|
||||
SkDebugf("No skp stream for slide %s.\n", fName.c_str());
|
||||
return;
|
||||
}
|
||||
fStream->rewind();
|
||||
fPlayer = MSKPPlayer::Make(fStream.get());
|
||||
if (!fPlayer) {
|
||||
SkDebugf("Could parse MSKP from stream for slide %s.\n", fName.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MSKPSlide::unload() { fPlayer.reset(); }
|
||||
|
||||
void MSKPSlide::gpuTeardown() { fPlayer->resetLayers(); }
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef MSKPSlide_DEFINED
|
||||
#define MSKPSlide_DEFINED
|
||||
|
||||
#include "tools/MSKPPlayer.h"
|
||||
#include "tools/viewer/Slide.h"
|
||||
|
||||
class SkStreamSeekable;
|
||||
|
||||
class MSKPSlide : public Slide {
|
||||
public:
|
||||
MSKPSlide(const SkString& name, const SkString& path);
|
||||
MSKPSlide(const SkString& name, std::unique_ptr<SkStreamSeekable>);
|
||||
|
||||
SkISize getDimensions() const override;
|
||||
|
||||
void draw(SkCanvas* canvas) override;
|
||||
bool animate(double nanos) override;
|
||||
void load(SkScalar winWidth, SkScalar winHeight) override;
|
||||
void unload() override;
|
||||
void gpuTeardown() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<SkStreamSeekable> fStream;
|
||||
std::unique_ptr<MSKPPlayer> fPlayer;
|
||||
int fFrame = 0;
|
||||
int fFPS = 15; // TODO: make this adjustable. This happens to work well for calendar.mskp
|
||||
double fLastFrameTime = 0;
|
||||
|
||||
using INHERITED = Slide;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,8 +5,6 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tools/viewer/Viewer.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkGraphics.h"
|
||||
@ -45,13 +43,13 @@
|
||||
#include "tools/viewer/BisectSlide.h"
|
||||
#include "tools/viewer/GMSlide.h"
|
||||
#include "tools/viewer/ImageSlide.h"
|
||||
#include "tools/viewer/MSKPSlide.h"
|
||||
#include "tools/viewer/ParticlesSlide.h"
|
||||
#include "tools/viewer/SKPSlide.h"
|
||||
#include "tools/viewer/SampleSlide.h"
|
||||
#include "tools/viewer/SkSLSlide.h"
|
||||
#include "tools/viewer/SlideDir.h"
|
||||
#include "tools/viewer/SvgSlide.h"
|
||||
#include "tools/viewer/Viewer.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
@ -152,18 +150,19 @@ static DEFINE_string2(match, m, nullptr,
|
||||
"it is skipped unless some list entry starts with ~");
|
||||
|
||||
#if defined(SK_BUILD_FOR_ANDROID)
|
||||
# define PATH_PREFIX "/data/local/tmp/"
|
||||
static DEFINE_string(jpgs, "/data/local/tmp/resources", "Directory to read jpgs from.");
|
||||
static DEFINE_string(skps, "/data/local/tmp/skps", "Directory to read skps from.");
|
||||
static DEFINE_string(lotties, "/data/local/tmp/lotties",
|
||||
"Directory to read (Bodymovin) jsons from.");
|
||||
static DEFINE_string(rives, "/data/local/tmp/rives",
|
||||
"Directory to read Rive (Flare) files from.");
|
||||
#else
|
||||
# define PATH_PREFIX ""
|
||||
static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
|
||||
static DEFINE_string(skps, "skps", "Directory to read skps from.");
|
||||
static DEFINE_string(lotties, "lotties", "Directory to read (Bodymovin) jsons from.");
|
||||
static DEFINE_string(rives, "rives", "Directory to read Rive (Flare) files from.");
|
||||
#endif
|
||||
|
||||
static DEFINE_string(jpgs , PATH_PREFIX "jpgs" , "Directory to read jpgs from.");
|
||||
static DEFINE_string(skps , PATH_PREFIX "skps" , "Directory to read skps from.");
|
||||
static DEFINE_string(mskps , PATH_PREFIX "mskps" , "Directory to read mskps from.");
|
||||
static DEFINE_string(lotties, PATH_PREFIX "lotties", "Directory to read (Bodymovin) jsons from.");
|
||||
static DEFINE_string(rives , PATH_PREFIX "rives" , "Directory to read Rive (Flare) files from.");
|
||||
#undef PATH_PREFIX
|
||||
|
||||
static DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
|
||||
|
||||
static DEFINE_int_2(threads, j, -1,
|
||||
@ -736,10 +735,6 @@ void Viewer::initSlides() {
|
||||
const CommandLineFlags::StringArray& fFlags;
|
||||
const SlideFactory fFactory;
|
||||
} gExternalSlidesInfo[] = {
|
||||
{ ".mskp", "mskp-dir", FLAGS_mskps,
|
||||
[](const SkString& name, const SkString& path) -> sk_sp<Slide> {
|
||||
return sk_make_sp<MSKPSlide>(name, path);}
|
||||
},
|
||||
{ ".skp", "skp-dir", FLAGS_skps,
|
||||
[](const SkString& name, const SkString& path) -> sk_sp<Slide> {
|
||||
return sk_make_sp<SKPSlide>(name, path);}
|
||||
|
Loading…
Reference in New Issue
Block a user