blob: e30968a1f64a53ed9d6bcfca886ec6a823af2c7a [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_DISPLAY_LIST_DISPLAY_LIST_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
#include <memory>
#include <optional>
#include "flutter/display_list/display_list_rtree.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/logging.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(SetAntiAlias) \
V(SetDither) \
V(SetInvertColors) \
\
V(SetStrokeCap) \
V(SetStrokeJoin) \
\
V(SetStyle) \
V(SetStrokeWidth) \
V(SetStrokeMiter) \
\
V(SetColor) \
V(SetBlendMode) \
\
V(SetBlender) \
V(ClearBlender) \
\
V(SetSkPathEffect) \
V(SetPodPathEffect) \
V(ClearPathEffect) \
\
V(ClearColorFilter) \
V(SetPodColorFilter) \
V(SetSkColorFilter) \
\
V(ClearColorSource) \
V(SetPodColorSource) \
V(SetSkColorSource) \
V(SetImageColorSource) \
V(SetRuntimeEffectColorSource) \
\
V(ClearImageFilter) \
V(SetPodImageFilter) \
V(SetSkImageFilter) \
V(SetSharedImageFilter) \
\
V(ClearMaskFilter) \
V(SetPodMaskFilter) \
V(SetSkMaskFilter) \
\
V(Save) \
V(SaveLayer) \
V(SaveLayerBounds) \
V(SaveLayerBackdrop) \
V(SaveLayerBackdropBounds) \
V(Restore) \
\
V(Translate) \
V(Scale) \
V(Rotate) \
V(Skew) \
V(Transform2DAffine) \
V(TransformFullPerspective) \
V(TransformReset) \
\
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(DrawSkVertices) \
\
V(DrawImage) \
V(DrawImageWithAttr) \
V(DrawImageRect) \
V(DrawImageNine) \
V(DrawImageNineWithAttr) \
V(DrawImageLattice) \
V(DrawAtlas) \
V(DrawAtlasCulled) \
\
V(DrawSkPicture) \
V(DrawSkPictureMatrix) \
V(DrawDisplayList) \
V(DrawTextBlob) \
\
V(DrawShadow) \
V(DrawShadowTransparentOccluder)
#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;
class SaveLayerOptions {
public:
static const SaveLayerOptions kWithAttributes;
static const SaveLayerOptions kNoAttributes;
SaveLayerOptions() : flags_(0) {}
SaveLayerOptions(const SaveLayerOptions& options) : flags_(options.flags_) {}
SaveLayerOptions(const SaveLayerOptions* options) : flags_(options->flags_) {}
SaveLayerOptions without_optimizations() const {
SaveLayerOptions options;
options.fRendersWithAttributes = fRendersWithAttributes;
return options;
}
bool renders_with_attributes() const { return fRendersWithAttributes; }
SaveLayerOptions with_renders_with_attributes() const {
SaveLayerOptions options(this);
options.fRendersWithAttributes = true;
return options;
}
bool can_distribute_opacity() const { return fCanDistributeOpacity; }
SaveLayerOptions with_can_distribute_opacity() const {
SaveLayerOptions options(this);
options.fCanDistributeOpacity = true;
return options;
}
SaveLayerOptions& operator=(const SaveLayerOptions& other) {
flags_ = other.flags_;
return *this;
}
bool operator==(const SaveLayerOptions& other) const {
return flags_ == other.flags_;
}
bool operator!=(const SaveLayerOptions& other) const {
return flags_ != other.flags_;
}
private:
union {
struct {
unsigned fRendersWithAttributes : 1;
unsigned fCanDistributeOpacity : 1;
};
uint32_t flags_;
};
};
// 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:
DisplayList();
~DisplayList();
void Dispatch(Dispatcher& ctx) const {
uint8_t* ptr = storage_.get();
Dispatch(ctx, ptr, ptr + byte_count_);
}
void RenderTo(DisplayListBuilder* builder,
SkScalar opacity = SK_Scalar1) const;
void RenderTo(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) const;
// SkPicture always includes nested bytes, but nested ops are
// only included if requested. The defaults used here for these
// accessors follow that pattern.
size_t bytes(bool nested = true) const {
return sizeof(DisplayList) + byte_count_ +
(nested ? nested_byte_count_ : 0);
}
unsigned int op_count(bool nested = false) const {
return op_count_ + (nested ? nested_op_count_ : 0);
}
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_;
}
sk_sp<const DlRTree> rtree() {
if (!rtree_) {
ComputeRTree();
}
return rtree_;
}
bool Equals(const DisplayList* other) const;
bool Equals(const DisplayList& other) const { return Equals(&other); }
bool Equals(sk_sp<const DisplayList> other) const {
return Equals(other.get());
}
bool can_apply_group_opacity() { return can_apply_group_opacity_; }
static void DisposeOps(uint8_t* ptr, uint8_t* end);
private:
DisplayList(uint8_t* ptr,
size_t byte_count,
unsigned int op_count,
size_t nested_byte_count,
unsigned int nested_op_count,
const SkRect& cull_rect,
bool can_apply_group_opacity);
struct SkFreeDeleter {
void operator()(uint8_t* p) { sk_free(p); }
};
std::unique_ptr<uint8_t, SkFreeDeleter> storage_;
size_t byte_count_;
unsigned int op_count_;
size_t nested_byte_count_;
unsigned int nested_op_count_;
uint32_t unique_id_;
SkRect bounds_;
sk_sp<const DlRTree> rtree_;
// Only used for drawPaint() and drawColor()
SkRect bounds_cull_;
bool can_apply_group_opacity_;
void ComputeBounds();
void ComputeRTree();
void Dispatch(Dispatcher& ctx, uint8_t* ptr, uint8_t* end) const;
friend class DisplayListBuilder;
};
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_