blob: a765cfbf6ce6a4164853bb0b22c5a116c381e789 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FLOW_DISPLAY_LIST_H_
#define FLUTTER_FLOW_DISPLAY_LIST_H_
#include "third_party/skia/include/core/SkBlender.h"
#include "third_party/skia/include/core/SkBlurTypes.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkPathEffect.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/core/SkVertices.h"
// The Flutter DisplayList mechanism encapsulates a persistent sequence of
// rendering operations.
//
// This file contains the definitions for:
// DisplayList: the base class that holds the information about the
// sequence of operations and can dispatch them to a Dispatcher
// Dispatcher: a pure virtual interface which can be implemented to field
// the requests for purposes such as sending them to an SkCanvas
// or detecting various rendering optimization scenarios
// DisplayListBuilder: a class for constructing a DisplayList from the same
// calls defined in the Dispatcher
//
// Other files include various class definitions for dealing with display
// lists, such as:
// display_list_canvas.h: classes to interact between SkCanvas and DisplayList
// (SkCanvas->DisplayList adapter and vice versa)
//
// display_list_utils.h: various utility classes to ease implementing
// a Dispatcher, including NOP implementations of
// the attribute, clip, and transform methods,
// classes to track attributes, clips, and transforms
// and a class to compute the bounds of a DisplayList
// Any class implementing Dispatcher can inherit from
// these utility classes to simplify its creation
//
// The Flutter DisplayList mechanism can be used in place of the Skia
// SkPicture mechanism. The primary means of communication into and out
// of the DisplayList is through the Dispatcher virtual class which
// provides a nearly 1:1 translation between the records of the DisplayList
// to method calls.
//
// A DisplayList can be created directly using a DisplayListBuilder and
// the Dispatcher methods that it implements, or it can be created from
// a sequence of SkCanvas calls using the DisplayListCanvasRecorder class.
//
// A DisplayList can be read back by implementing the Dispatcher virtual
// methods (with help from some of the classes in the utils file) and
// passing an instance to the dispatch() method, or it can be rendered
// to Skia using a DisplayListCanvasDispatcher or simply by passing an
// SkCanvas pointer to its renderTo() method.
//
// The mechanism is inspired by the SkLiteDL class that is not directly
// supported by Skia, but has been recommended as a basis for custom
// display lists for a number of their customers.
namespace flutter {
#define FOR_EACH_DISPLAY_LIST_OP(V) \
V(SetAA) \
V(SetDither) \
V(SetInvertColors) \
\
V(SetCaps) \
V(SetJoins) \
\
V(SetDrawStyle) \
V(SetStrokeWidth) \
V(SetMiterLimit) \
\
V(SetColor) \
V(SetBlendMode) \
\
V(SetBlender) \
V(ClearBlender) \
V(SetShader) \
V(ClearShader) \
V(SetColorFilter) \
V(ClearColorFilter) \
V(SetImageFilter) \
V(ClearImageFilter) \
V(SetPathEffect) \
V(ClearPathEffect) \
\
V(ClearMaskFilter) \
V(SetMaskFilter) \
V(SetMaskBlurFilterNormal) \
V(SetMaskBlurFilterSolid) \
V(SetMaskBlurFilterOuter) \
V(SetMaskBlurFilterInner) \
\
V(Save) \
V(SaveLayer) \
V(SaveLayerBounds) \
V(Restore) \
\
V(Translate) \
V(Scale) \
V(Rotate) \
V(Skew) \
V(Transform2x3) \
V(Transform3x3) \
\
V(ClipIntersectRect) \
V(ClipIntersectRRect) \
V(ClipIntersectPath) \
V(ClipDifferenceRect) \
V(ClipDifferenceRRect) \
V(ClipDifferencePath) \
\
V(DrawPaint) \
V(DrawColor) \
\
V(DrawLine) \
V(DrawRect) \
V(DrawOval) \
V(DrawCircle) \
V(DrawRRect) \
V(DrawDRRect) \
V(DrawArc) \
V(DrawPath) \
\
V(DrawPoints) \
V(DrawLines) \
V(DrawPolygon) \
V(DrawVertices) \
\
V(DrawImage) \
V(DrawImageRectStrict) \
V(DrawImageRectFast) \
V(DrawImageNine) \
V(DrawImageLattice) \
V(DrawAtlas) \
V(DrawAtlasColored) \
V(DrawAtlasCulled) \
V(DrawAtlasColoredCulled) \
\
V(DrawSkPicture) \
V(DrawSkPictureMatrix) \
V(DrawDisplayList) \
V(DrawTextBlob) \
\
V(DrawShadow) \
V(DrawShadowOccludes)
#define DL_OP_TO_ENUM_VALUE(name) k##name,
enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) };
#undef DL_OP_TO_ENUM_VALUE
class Dispatcher;
class DisplayListBuilder;
// The base class that contains a sequence of rendering operations
// for dispatch to a Dispatcher. These objects must be instantiated
// through an instance of DisplayListBuilder::build().
class DisplayList : public SkRefCnt {
public:
static const SkSamplingOptions NearestSampling;
static const SkSamplingOptions LinearSampling;
static const SkSamplingOptions MipmapSampling;
static const SkSamplingOptions CubicSampling;
DisplayList()
: ptr_(nullptr),
used_(0),
op_count_(0),
unique_id_(0),
bounds_({0, 0, 0, 0}),
bounds_cull_({0, 0, 0, 0}) {}
~DisplayList();
void Dispatch(Dispatcher& ctx) const { Dispatch(ctx, ptr_, ptr_ + used_); }
void RenderTo(SkCanvas* canvas) const;
size_t bytes() const { return used_; }
int op_count() const { return op_count_; }
uint32_t unique_id() const { return unique_id_; }
const SkRect& bounds() {
if (bounds_.width() < 0.0) {
// ComputeBounds() will leave the variable with a
// non-negative width and height
ComputeBounds();
}
return bounds_;
}
bool Equals(const DisplayList& other) const;
private:
DisplayList(uint8_t* ptr, size_t used, int op_count, const SkRect& cull_rect);
uint8_t* ptr_;
size_t used_;
int op_count_;
uint32_t unique_id_;
SkRect bounds_;
// Only used for drawPaint() and drawColor()
SkRect bounds_cull_;
void ComputeBounds();
void Dispatch(Dispatcher& ctx, uint8_t* ptr, uint8_t* end) const;
friend class DisplayListBuilder;
};
// The pure virtual interface for interacting with a display list.
// This interface represents the methods used to build a list
// through the DisplayListBuilder and also the methods that will
// be invoked through the DisplayList::dispatch() method.
class Dispatcher {
public:
// MaxDrawPointsCount * sizeof(SkPoint) must be less than 1 << 32
static constexpr int kMaxDrawPointsCount = ((1 << 29) - 1);
virtual void setAA(bool aa) = 0;
virtual void setDither(bool dither) = 0;
virtual void setInvertColors(bool invert) = 0;
virtual void setCaps(SkPaint::Cap cap) = 0;
virtual void setJoins(SkPaint::Join join) = 0;
virtual void setDrawStyle(SkPaint::Style style) = 0;
virtual void setStrokeWidth(SkScalar width) = 0;
virtual void setMiterLimit(SkScalar limit) = 0;
virtual void setColor(SkColor color) = 0;
virtual void setBlendMode(SkBlendMode mode) = 0;
virtual void setBlender(sk_sp<SkBlender> blender) = 0;
virtual void setShader(sk_sp<SkShader> shader) = 0;
virtual void setImageFilter(sk_sp<SkImageFilter> filter) = 0;
virtual void setColorFilter(sk_sp<SkColorFilter> filter) = 0;
virtual void setPathEffect(sk_sp<SkPathEffect> effect) = 0;
virtual void setMaskFilter(sk_sp<SkMaskFilter> filter) = 0;
virtual void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) = 0;
virtual void save() = 0;
virtual void restore() = 0;
virtual void saveLayer(const SkRect* bounds, bool restoreWithPaint) = 0;
virtual void translate(SkScalar tx, SkScalar ty) = 0;
virtual void scale(SkScalar sx, SkScalar sy) = 0;
virtual void rotate(SkScalar degrees) = 0;
virtual void skew(SkScalar sx, SkScalar sy) = 0;
virtual void transform2x3(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
SkScalar myx,
SkScalar myy,
SkScalar myt) = 0;
virtual void transform3x3(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
SkScalar myx,
SkScalar myy,
SkScalar myt,
SkScalar px,
SkScalar py,
SkScalar pt) = 0;
virtual void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) = 0;
virtual void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) = 0;
virtual void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) = 0;
virtual void drawPaint() = 0;
virtual void drawColor(SkColor color, SkBlendMode mode) = 0;
virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0;
virtual void drawRect(const SkRect& rect) = 0;
virtual void drawOval(const SkRect& bounds) = 0;
virtual void drawCircle(const SkPoint& center, SkScalar radius) = 0;
virtual void drawRRect(const SkRRect& rrect) = 0;
virtual void drawDRRect(const SkRRect& outer, const SkRRect& inner) = 0;
virtual void drawPath(const SkPath& path) = 0;
virtual void drawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter) = 0;
virtual void drawPoints(SkCanvas::PointMode mode,
uint32_t count,
const SkPoint pts[]) = 0;
virtual void drawVertices(const sk_sp<SkVertices> vertices,
SkBlendMode mode) = 0;
virtual void drawImage(const sk_sp<SkImage> image,
const SkPoint point,
const SkSamplingOptions& sampling) = 0;
virtual void drawImageRect(const sk_sp<SkImage> image,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions& sampling,
SkCanvas::SrcRectConstraint constraint) = 0;
virtual void drawImageNine(const sk_sp<SkImage> image,
const SkIRect& center,
const SkRect& dst,
SkFilterMode filter) = 0;
virtual void drawImageLattice(const sk_sp<SkImage> image,
const SkCanvas::Lattice& lattice,
const SkRect& dst,
SkFilterMode filter,
bool with_paint) = 0;
virtual void drawAtlas(const sk_sp<SkImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
const SkColor colors[],
int count,
SkBlendMode mode,
const SkSamplingOptions& sampling,
const SkRect* cullRect) = 0;
virtual void drawPicture(const sk_sp<SkPicture> picture,
const SkMatrix* matrix,
bool with_save_layer) = 0;
virtual void drawDisplayList(const sk_sp<DisplayList> display_list) = 0;
virtual void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) = 0;
virtual void drawShadow(const SkPath& path,
const SkColor color,
const SkScalar elevation,
bool occludes,
SkScalar dpr) = 0;
};
// The primary class used to build a display list. The list of methods
// here matches the list of methods invoked during dispatch().
// If there is some code that already renders to an SkCanvas object,
// those rendering commands can be captured into a DisplayList using
// the DisplayListCanvasRecorder class.
class DisplayListBuilder final : public virtual Dispatcher, public SkRefCnt {
public:
DisplayListBuilder(const SkRect& cull = kMaxCull_);
~DisplayListBuilder();
void setAA(bool aa) override;
void setDither(bool dither) override;
void setInvertColors(bool invert) override;
void setCaps(SkPaint::Cap cap) override;
void setJoins(SkPaint::Join join) override;
void setDrawStyle(SkPaint::Style style) override;
void setStrokeWidth(SkScalar width) override;
void setMiterLimit(SkScalar limit) override;
void setColor(SkColor color) override;
void setBlendMode(SkBlendMode mode) override;
void setBlender(sk_sp<SkBlender> blender) override;
void setShader(sk_sp<SkShader> shader) override;
void setImageFilter(sk_sp<SkImageFilter> filter) override;
void setColorFilter(sk_sp<SkColorFilter> filter) override;
void setPathEffect(sk_sp<SkPathEffect> effect) override;
void setMaskFilter(sk_sp<SkMaskFilter> filter) override;
void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override;
void save() override;
void restore() override;
void saveLayer(const SkRect* bounds, bool restoreWithPaint) override;
void translate(SkScalar tx, SkScalar ty) override;
void scale(SkScalar sx, SkScalar sy) override;
void rotate(SkScalar degrees) override;
void skew(SkScalar sx, SkScalar sy) override;
void transform2x3(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
SkScalar myx,
SkScalar myy,
SkScalar myt) override;
void transform3x3(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
SkScalar myx,
SkScalar myy,
SkScalar myt,
SkScalar px,
SkScalar py,
SkScalar pt) override;
void clipRect(const SkRect& rect, bool isAA, SkClipOp clip_op) override;
void clipRRect(const SkRRect& rrect, bool isAA, SkClipOp clip_op) override;
void clipPath(const SkPath& path, bool isAA, SkClipOp clip_op) override;
void drawPaint() override;
void drawColor(SkColor color, SkBlendMode mode) override;
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
void drawRect(const SkRect& rect) override;
void drawOval(const SkRect& bounds) override;
void drawCircle(const SkPoint& center, SkScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
void drawPath(const SkPath& path) override;
void drawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter) override;
void drawPoints(SkCanvas::PointMode mode,
uint32_t count,
const SkPoint pts[]) override;
void drawVertices(const sk_sp<SkVertices> vertices,
SkBlendMode mode) override;
void drawImage(const sk_sp<SkImage> image,
const SkPoint point,
const SkSamplingOptions& sampling) override;
void drawImageRect(
const sk_sp<SkImage> image,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions& sampling,
SkCanvas::SrcRectConstraint constraint =
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint) override;
void drawImageNine(const sk_sp<SkImage> image,
const SkIRect& center,
const SkRect& dst,
SkFilterMode filter) override;
void drawImageLattice(const sk_sp<SkImage> image,
const SkCanvas::Lattice& lattice,
const SkRect& dst,
SkFilterMode filter,
bool with_paint) override;
void drawAtlas(const sk_sp<SkImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
const SkColor colors[],
int count,
SkBlendMode mode,
const SkSamplingOptions& sampling,
const SkRect* cullRect) override;
void drawPicture(const sk_sp<SkPicture> picture,
const SkMatrix* matrix,
bool with_save_layer) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
void drawShadow(const SkPath& path,
const SkColor color,
const SkScalar elevation,
bool occludes,
SkScalar dpr) override;
sk_sp<DisplayList> Build();
private:
SkAutoTMalloc<uint8_t> storage_;
size_t used_ = 0;
size_t allocated_ = 0;
int op_count_ = 0;
int save_level_ = 0;
SkRect cull_;
static constexpr SkRect kMaxCull_ =
SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
template <typename T, typename... Args>
void* Push(size_t extra, Args&&... args);
};
} // namespace flutter
#endif // FLUTTER_FLOW_DISPLAY_LIST_H_