Reland "Sequester all Skia<->DL interactions into the skia sub-module" (flutter/engine#40114)

Reland "Sequester all Skia<->DL interactions into the skia sub-module"
This commit is contained in:
Jim Graham 2023-03-07 11:03:17 -08:00 committed by GitHub
parent 9369c1ed1f
commit 53a80bdedf
94 changed files with 4697 additions and 3843 deletions

View File

@ -29,12 +29,10 @@
../../../flutter/build
../../../flutter/ci
../../../flutter/common/README.md
../../../flutter/display_list/display_list_canvas_unittests.cc
../../../flutter/display_list/display_list_color_filter_unittests.cc
../../../flutter/display_list/display_list_color_source_unittests.cc
../../../flutter/display_list/display_list_color_unittests.cc
../../../flutter/display_list/display_list_complexity_unittests.cc
../../../flutter/display_list/display_list_enum_unittests.cc
../../../flutter/display_list/display_list_image_filter_unittests.cc
../../../flutter/display_list/display_list_mask_filter_unittests.cc
../../../flutter/display_list/display_list_matrix_clip_tracker_unittests.cc
@ -42,8 +40,10 @@
../../../flutter/display_list/display_list_path_effect_unittests.cc
../../../flutter/display_list/display_list_rtree_unittests.cc
../../../flutter/display_list/display_list_unittests.cc
../../../flutter/display_list/display_list_utils_unittests.cc
../../../flutter/display_list/display_list_vertices_unittests.cc
../../../flutter/display_list/dl_rendering_unittests.cc
../../../flutter/display_list/skia/dl_sk_conversions_unittests.cc
../../../flutter/display_list/skia/dl_sk_utils_unittests.cc
../../../flutter/display_list/testing
../../../flutter/docs
../../../flutter/examples

View File

@ -714,8 +714,6 @@ ORIGIN: ../../../flutter/display_list/display_list_blend_mode.h + ../../../flutt
ORIGIN: ../../../flutter/display_list/display_list_builder.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_builder.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_builder_benchmarks.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_color.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_color_filter.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_color_filter.h + ../../../flutter/LICENSE
@ -729,8 +727,6 @@ ORIGIN: ../../../flutter/display_list/display_list_complexity_gl.h + ../../../fl
ORIGIN: ../../../flutter/display_list/display_list_complexity_helper.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_dispatcher.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_dispatcher.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_flags.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_flags.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_image.cc + ../../../flutter/LICENSE
@ -759,9 +755,18 @@ ORIGIN: ../../../flutter/display_list/display_list_utils.cc + ../../../flutter/L
ORIGIN: ../../../flutter/display_list/display_list_utils.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_vertices.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_vertices.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_canvas.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_canvas.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_op_receiver.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/dl_op_receiver.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/types.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/flow/compositor_context.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/flow/compositor_context.h + ../../../flutter/LICENSE
@ -3244,8 +3249,6 @@ FILE: ../../../flutter/display_list/display_list_blend_mode.h
FILE: ../../../flutter/display_list/display_list_builder.cc
FILE: ../../../flutter/display_list/display_list_builder.h
FILE: ../../../flutter/display_list/display_list_builder_benchmarks.cc
FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.cc
FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.h
FILE: ../../../flutter/display_list/display_list_color.h
FILE: ../../../flutter/display_list/display_list_color_filter.cc
FILE: ../../../flutter/display_list/display_list_color_filter.h
@ -3259,8 +3262,6 @@ FILE: ../../../flutter/display_list/display_list_complexity_gl.h
FILE: ../../../flutter/display_list/display_list_complexity_helper.h
FILE: ../../../flutter/display_list/display_list_complexity_metal.cc
FILE: ../../../flutter/display_list/display_list_complexity_metal.h
FILE: ../../../flutter/display_list/display_list_dispatcher.cc
FILE: ../../../flutter/display_list/display_list_dispatcher.h
FILE: ../../../flutter/display_list/display_list_flags.cc
FILE: ../../../flutter/display_list/display_list_flags.h
FILE: ../../../flutter/display_list/display_list_image.cc
@ -3289,9 +3290,18 @@ FILE: ../../../flutter/display_list/display_list_utils.cc
FILE: ../../../flutter/display_list/display_list_utils.h
FILE: ../../../flutter/display_list/display_list_vertices.cc
FILE: ../../../flutter/display_list/display_list_vertices.h
FILE: ../../../flutter/display_list/dl_canvas.cc
FILE: ../../../flutter/display_list/dl_canvas.h
FILE: ../../../flutter/display_list/dl_op_receiver.cc
FILE: ../../../flutter/display_list/dl_op_receiver.h
FILE: ../../../flutter/display_list/skia/dl_sk_canvas.cc
FILE: ../../../flutter/display_list/skia/dl_sk_canvas.h
FILE: ../../../flutter/display_list/skia/dl_sk_conversions.cc
FILE: ../../../flutter/display_list/skia/dl_sk_conversions.h
FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc
FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.h
FILE: ../../../flutter/display_list/skia/dl_sk_utils.cc
FILE: ../../../flutter/display_list/skia/dl_sk_utils.h
FILE: ../../../flutter/display_list/types.h
FILE: ../../../flutter/flow/compositor_context.cc
FILE: ../../../flutter/flow/compositor_context.h

View File

@ -16,8 +16,6 @@ source_set("display_list") {
"display_list_blend_mode.h",
"display_list_builder.cc",
"display_list_builder.h",
"display_list_canvas_dispatcher.cc",
"display_list_canvas_dispatcher.h",
"display_list_color.h",
"display_list_color_filter.cc",
"display_list_color_filter.h",
@ -29,8 +27,6 @@ source_set("display_list") {
"display_list_complexity_gl.h",
"display_list_complexity_metal.cc",
"display_list_complexity_metal.h",
"display_list_dispatcher.cc",
"display_list_dispatcher.h",
"display_list_flags.cc",
"display_list_flags.h",
"display_list_image.cc",
@ -59,9 +55,18 @@ source_set("display_list") {
"display_list_utils.h",
"display_list_vertices.cc",
"display_list_vertices.h",
"dl_canvas.cc",
"dl_canvas.h",
"dl_op_receiver.cc",
"dl_op_receiver.h",
"skia/dl_sk_canvas.cc",
"skia/dl_sk_canvas.h",
"skia/dl_sk_conversions.cc",
"skia/dl_sk_conversions.h",
"skia/dl_sk_dispatcher.cc",
"skia/dl_sk_dispatcher.h",
"skia/dl_sk_utils.cc",
"skia/dl_sk_utils.h",
"types.h",
]
@ -93,7 +98,6 @@ if (enable_unittests) {
"display_list_color_source_unittests.cc",
"display_list_color_unittests.cc",
"display_list_complexity_unittests.cc",
"display_list_enum_unittests.cc",
"display_list_image_filter_unittests.cc",
"display_list_mask_filter_unittests.cc",
"display_list_matrix_clip_tracker_unittests.cc",
@ -101,8 +105,9 @@ if (enable_unittests) {
"display_list_path_effect_unittests.cc",
"display_list_rtree_unittests.cc",
"display_list_unittests.cc",
"display_list_utils_unittests.cc",
"display_list_vertices_unittests.cc",
"skia/dl_sk_conversions_unittests.cc",
"skia/dl_sk_utils_unittests.cc",
]
deps = [
@ -130,7 +135,7 @@ if (enable_unittests) {
executable("display_list_rendertests") {
testonly = true
sources = [ "display_list_canvas_unittests.cc" ]
sources = [ "dl_rendering_unittests.cc" ]
deps = [
":display_list",

View File

@ -6,7 +6,6 @@
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/display_list/display_list_ops.h"
#include "flutter/fml/trace_event.h"
@ -134,38 +133,40 @@ class VectorCuller final : public Culler {
std::vector<int>::const_iterator end_;
};
void DisplayList::Dispatch(Dispatcher& ctx) const {
void DisplayList::Dispatch(DlOpReceiver& receiver) const {
uint8_t* ptr = storage_.get();
Dispatch(ctx, ptr, ptr + byte_count_, NopCuller::instance);
Dispatch(receiver, ptr, ptr + byte_count_, NopCuller::instance);
}
void DisplayList::Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const {
void DisplayList::Dispatch(DlOpReceiver& receiver,
const SkRect& cull_rect) const {
if (cull_rect.isEmpty()) {
return;
}
if (cull_rect.contains(bounds())) {
Dispatch(ctx);
Dispatch(receiver);
return;
}
const DlRTree* rtree = this->rtree().get();
FML_DCHECK(rtree != nullptr);
if (rtree == nullptr) {
FML_LOG(ERROR) << "dispatched with culling rect on DL with no rtree";
Dispatch(ctx);
Dispatch(receiver);
return;
}
uint8_t* ptr = storage_.get();
std::vector<int> rect_indices;
rtree->search(cull_rect, &rect_indices);
VectorCuller culler(rtree, rect_indices);
Dispatch(ctx, ptr, ptr + byte_count_, culler);
Dispatch(receiver, ptr, ptr + byte_count_, culler);
}
void DisplayList::Dispatch(Dispatcher& dispatcher,
void DisplayList::Dispatch(DlOpReceiver& receiver,
uint8_t* ptr,
uint8_t* end,
Culler& culler) const {
DispatchContext context = {
.dispatcher = dispatcher,
.receiver = receiver,
.cur_index = 0,
// next_render_index will be initialized by culler.init()
.next_restore_index = std::numeric_limits<int>::max(),
@ -294,27 +295,6 @@ static bool CompareOps(uint8_t* ptrA,
return true;
}
void DisplayList::RenderTo(DisplayListBuilder* builder) const {
if (!builder) {
return;
}
if (has_rtree()) {
Dispatch(builder->asDispatcher(), builder->GetLocalClipBounds());
} else {
Dispatch(builder->asDispatcher());
}
}
void DisplayList::RenderTo(SkCanvas* canvas, SkScalar opacity) const {
FML_DCHECK(can_apply_group_opacity() || opacity >= SK_Scalar1);
DisplayListCanvasDispatcher dispatcher(canvas, opacity);
if (has_rtree()) {
Dispatch(dispatcher, canvas->getLocalClipBounds());
} else {
Dispatch(dispatcher);
}
}
bool DisplayList::Equals(const DisplayList* other) const {
if (this == other) {
return true;

View File

@ -18,41 +18,36 @@
//
// 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
// sequence of operations and can dispatch them to a DlOpReceiver
// DlOpReceiver: 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 DlCanvas
// method calls and which can act as a DlOpReceiver as well
//
// 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)
// skia/dl_sk_*.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
// a DlOpReceiver, 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
// Any class implementing DlOpReceiver can inherit from
// these utility classes to simplify its creation
//
// The Flutter DisplayList mechanism is used in a similar manner to 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.
// SkPicture mechanism.
//
// A DisplayList must be created using a DisplayListBuilder using either its
// stateful methods inherited from Dispatcher, or from its stateless methods
// inherited from DlCanvas.
// A DisplayList must be created using a DisplayListBuilder using its stateless
// methods inherited from DlCanvas.
//
// A DisplayList can be read back by implementing the Dispatcher virtual
// A DisplayList can be read back by implementing the DlOpReceiver 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.
// passing an instance to the Dispatch() method, or it can be rendered
// to Skia using a DlSkCanvasDispatcher.
//
// The mechanism is inspired by the SkLiteDL class that is not directly
// supported by Skia, but has been recommended as a basis for custom
@ -155,7 +150,7 @@ enum class DisplayListOpType {
};
#undef DL_OP_TO_ENUM_VALUE
class Dispatcher;
class DlOpReceiver;
class DisplayListBuilder;
class SaveLayerOptions {
@ -231,7 +226,7 @@ class DisplayListStorage {
class Culler;
// The base class that contains a sequence of rendering operations
// for dispatch to a Dispatcher. These objects must be instantiated
// for dispatch to a DlOpReceiver. These objects must be instantiated
// through an instance of DisplayListBuilder::build().
class DisplayList : public SkRefCnt {
public:
@ -239,12 +234,8 @@ class DisplayList : public SkRefCnt {
~DisplayList();
void Dispatch(Dispatcher& ctx) const;
void Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const;
void RenderTo(DisplayListBuilder* builder) const;
void RenderTo(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) const;
void Dispatch(DlOpReceiver& ctx) const;
void Dispatch(DlOpReceiver& ctx, const SkRect& cull_rect) const;
// From historical behavior, SkPicture always included nested bytes,
// but nested ops are only included if requested. The defaults used
@ -300,7 +291,7 @@ class DisplayList : public SkRefCnt {
const bool can_apply_group_opacity_;
const sk_sp<const DlRTree> rtree_;
void Dispatch(Dispatcher& ctx,
void Dispatch(DlOpReceiver& ctx,
uint8_t* ptr,
uint8_t* end,
Culler& culler) const;

View File

@ -36,10 +36,6 @@ namespace flutter {
// wrong type of instance.
// (eg. DlColorFilter::asBlend() or DlMaskFilter::asBlur())
//
// - Skiafiable:
// The classes override an |skia_object| method to easily obtain a Skia
// version of the attribute on demand.
//
// - Immutable:
// Neither the base class or any of the subclasses specify any mutation
// methods. Instances are often passed around as const as a reminder,
@ -56,7 +52,7 @@ namespace flutter {
// compared using a |memcmp| when performing a |DisplayList::Equals|.
//
// - Passed by Pointer:
// The data shared via the |Dispatcher::set<Attribute>| calls are stored
// The data shared via the |DlOpReceiver::set<Attribute>| calls are stored
// in the buffer itself and so their lifetime is controlled by the
// DisplayList. That memory cannot be shared as by a |shared_ptr|
// because the memory may be freed outside the control of the shared
@ -70,7 +66,7 @@ namespace flutter {
// - Shared_Ptr-able:
// The classes support a method to return a |std::shared_ptr| version of
// themselves, safely instantiating a new copy of the object into a
// shared_ptr using |std::make_shared|. For those dispatcher objects
// shared_ptr using |std::make_shared|. For those receiver objects
// that may want to hold on to the contents of the object (typically
// in a |current_attribute_| field), they can obtain a shared_ptr
// copy safely and easily using the |shared| method.
@ -79,11 +75,9 @@ namespace flutter {
// |D| is the base type for the attribute
// (i.e. DlColorFilter, etc.)
// |S| is the base type for the Skia version of the attribute
// (i.e. SkColorFilter, etc.)
// |T| is the enum that describes the specific subclasses
// (i.e DlColorFilterType, etc.)
template <class D, class S, typename T>
template <class D, typename T>
class DlAttribute {
public:
// Return the recognized specific type of the attribute.
@ -98,9 +92,6 @@ class DlAttribute {
// version is not tied to the storage of this particular instance.
virtual std::shared_ptr<D> shared() const = 0;
// Return an equivalent sk_sp<Skia> version of this object.
virtual sk_sp<S> skia_object() const = 0;
// Perform a content aware |==| comparison of the Attribute.
bool operator==(D const& other) const {
return type() == other.type() && equals_(other);

View File

@ -5,6 +5,7 @@
#include "flutter/display_list/display_list_benchmarks.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_flags.h"
#include "flutter/display_list/skia/dl_sk_canvas.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkSurface.h"
@ -76,27 +77,27 @@ void BM_DrawLine(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawLineFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawLineFlags);
size_t length = state.range(0);
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
state.counters["DrawCallCount"] = kLinesToDraw;
for (size_t i = 0; i < kLinesToDraw; i++) {
builder.drawLine(SkPoint::Make(i % length, 0),
SkPoint::Make(length - i % length, length));
builder.DrawLine(SkPoint::Make(i % length, 0),
SkPoint::Make(length - i % length, length), paint);
}
auto display_list = builder.Build();
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -114,15 +115,15 @@ void BM_DrawRect(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawRectFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRectFlags);
size_t length = state.range(0);
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
// As rects have SkScalar dimensions, we want to ensure that we also
// draw rects with non-integer position and size
@ -131,7 +132,7 @@ void BM_DrawRect(benchmark::State& state,
state.counters["DrawCallCount"] = kRectsToDraw;
for (size_t i = 0; i < kRectsToDraw; i++) {
builder.drawRect(rect);
builder.DrawRect(rect, paint);
rect.offset(offset, offset);
if (rect.right() > canvas_size) {
rect.offset(-canvas_size, 0);
@ -145,7 +146,7 @@ void BM_DrawRect(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -163,22 +164,22 @@ void BM_DrawOval(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawOvalFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawOvalFlags);
size_t length = state.range(0);
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length);
const SkScalar offset = 0.5f;
state.counters["DrawCallCount"] = kOvalsToDraw;
for (size_t i = 0; i < kOvalsToDraw; i++) {
builder.drawOval(rect);
builder.DrawOval(rect, paint);
rect.offset(offset, offset);
if (rect.right() > canvas_size) {
rect.offset(-canvas_size, 0);
@ -191,7 +192,7 @@ void BM_DrawOval(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -209,15 +210,15 @@ void BM_DrawCircle(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawCircleFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawCircleFlags);
size_t length = state.range(0);
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkScalar radius = length / 2.0f;
const SkScalar offset = 0.5f;
@ -226,7 +227,7 @@ void BM_DrawCircle(benchmark::State& state,
state.counters["DrawCallCount"] = kCirclesToDraw;
for (size_t i = 0; i < kCirclesToDraw; i++) {
builder.drawCircle(center, radius);
builder.DrawCircle(center, radius, paint);
center.offset(offset, offset);
if (center.x() + radius > canvas_size) {
center.set(radius, center.y());
@ -239,7 +240,7 @@ void BM_DrawCircle(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -258,15 +259,15 @@ void BM_DrawRRect(benchmark::State& state,
SkRRect::Type type) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawRRectFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRRectFlags);
size_t length = state.range(0);
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkVector radii[4] = {};
switch (type) {
@ -304,7 +305,7 @@ void BM_DrawRRect(benchmark::State& state,
state.counters["DrawCallCount"] = kRRectsToDraw;
for (size_t i = 0; i < kRRectsToDraw; i++) {
builder.drawRRect(rrect);
builder.DrawRRect(rrect, paint);
rrect.offset(offset, offset);
if (rrect.rect().right() > canvas_size) {
rrect.offset(-canvas_size, 0);
@ -317,7 +318,7 @@ void BM_DrawRRect(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -339,15 +340,15 @@ void BM_DrawDRRect(benchmark::State& state,
SkRRect::Type type) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawDRRectFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawDRRectFlags);
size_t length = state.range(0);
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkVector radii[4] = {};
switch (type) {
@ -386,7 +387,7 @@ void BM_DrawDRRect(benchmark::State& state,
state.counters["DrawCallCount"] = kDRRectsToDraw;
for (size_t i = 0; i < kDRRectsToDraw; i++) {
rrect.inset(0.1f * length, 0.1f * length, &rrect_2);
builder.drawDRRect(rrect, rrect_2);
builder.DrawDRRect(rrect, rrect_2, paint);
rrect.offset(offset, offset);
if (rrect.rect().right() > canvas_size) {
rrect.offset(-canvas_size, 0);
@ -399,7 +400,7 @@ void BM_DrawDRRect(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -413,8 +414,8 @@ void BM_DrawArc(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawArcNoCenterFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawArcNoCenterFlags);
@ -422,7 +423,7 @@ void BM_DrawArc(benchmark::State& state,
size_t canvas_size = length * 2;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkScalar starting_angle = 0.0f;
SkScalar offset = 0.5f;
@ -436,7 +437,7 @@ void BM_DrawArc(benchmark::State& state,
state.counters["DrawCallCount"] = kArcSweepSetsToDraw * segment_sweeps.size();
for (size_t i = 0; i < kArcSweepSetsToDraw; i++) {
for (SkScalar sweep : segment_sweeps) {
builder.drawArc(bounds, starting_angle, sweep, false);
builder.DrawArc(bounds, starting_angle, sweep, false, paint);
starting_angle += sweep + 5.0f;
}
bounds.offset(offset, offset);
@ -452,7 +453,7 @@ void BM_DrawArc(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -629,14 +630,14 @@ void BM_DrawPath(benchmark::State& state,
SkPath::Verb type) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawPathFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPathFlags);
size_t length = kFixedCanvasSize;
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkPath path;
@ -650,12 +651,12 @@ void BM_DrawPath(benchmark::State& state,
state.counters["VerbCount"] = path.countVerbs();
state.counters["DrawCallCount"] = 1;
builder.drawPath(path);
builder.DrawPath(path, paint);
auto display_list = builder.Build();
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -767,14 +768,14 @@ void BM_DrawVertices(benchmark::State& state,
DlVertexMode mode) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawVerticesFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawVerticesFlags);
size_t length = kFixedCanvasSize;
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
@ -791,7 +792,7 @@ void BM_DrawVertices(benchmark::State& state,
std::shared_ptr<DlVertices> vertices =
GetTestVertices(p, radius, 50, mode, vertex_count);
total_vertex_count += vertex_count;
builder.drawVertices(vertices, DlBlendMode::kSrc);
builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, paint);
}
state.counters["VertexCount"] = total_vertex_count;
@ -801,7 +802,7 @@ void BM_DrawVertices(benchmark::State& state,
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -863,26 +864,18 @@ void BM_DrawPoints(benchmark::State& state,
DlCanvas::PointMode mode) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
SkPaint paint;
DlPaint paint = GetPaintForRun(attributes);
switch (mode) {
case DlCanvas::PointMode::kPoints:
builder.SetAttributesFromPaint(
GetPaintForRun(attributes),
DisplayListOpFlags::kDrawPointsAsPointsFlags);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawPointsAsPointsFlags);
break;
case DlCanvas::PointMode::kLines:
builder.SetAttributesFromPaint(
GetPaintForRun(attributes),
DisplayListOpFlags::kDrawPointsAsLinesFlags);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawPointsAsLinesFlags);
break;
case DlCanvas::PointMode::kPolygon:
builder.SetAttributesFromPaint(
GetPaintForRun(attributes),
DisplayListOpFlags::kDrawPointsAsPolygonFlags);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawPointsAsPolygonFlags);
break;
@ -891,7 +884,7 @@ void BM_DrawPoints(benchmark::State& state,
size_t length = kFixedCanvasSize;
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
size_t point_count = state.range(0);
state.SetComplexityN(point_count);
@ -900,12 +893,12 @@ void BM_DrawPoints(benchmark::State& state,
std::vector<SkPoint> points =
GetTestPoints(point_count, SkISize::Make(length, length));
builder.drawPoints(mode, points.size(), points.data());
builder.DrawPoints(mode, points.size(), points.data(), paint);
auto display_list = builder.Build();
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -933,8 +926,8 @@ void BM_DrawImage(benchmark::State& state,
bool upload_bitmap) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawImageWithPaintFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawImageWithPaintFlags);
@ -942,7 +935,7 @@ void BM_DrawImage(benchmark::State& state,
size_t canvas_size = 2 * bitmap_size;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
sk_sp<SkImage> image;
std::shared_ptr<DlSurfaceInstance> offscreen_instance;
@ -969,7 +962,7 @@ void BM_DrawImage(benchmark::State& state,
for (size_t i = 0; i < kImagesToDraw; i++) {
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
: offscreen->makeImageSnapshot();
builder.drawImage(DlImage::Make(image), dst, options, true);
builder.DrawImage(DlImage::Make(image), dst, options, &paint);
dst.offset(offset, offset);
if (dst.x() + bitmap_size > canvas_size) {
@ -983,7 +976,7 @@ void BM_DrawImage(benchmark::State& state,
auto display_list = builder.Build();
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -993,11 +986,11 @@ void BM_DrawImage(benchmark::State& state,
surface_provider->Snapshot(filename);
}
std::string ConstraintToString(SkCanvas::SrcRectConstraint constraint) {
std::string ConstraintToString(DlCanvas::SrcRectConstraint constraint) {
switch (constraint) {
case SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint:
case DlCanvas::SrcRectConstraint::kStrict:
return "Strict";
case SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint:
case DlCanvas::SrcRectConstraint::kFast:
return "Fast";
default:
return "Unknown";
@ -1012,13 +1005,12 @@ void BM_DrawImageRect(benchmark::State& state,
BackendType backend_type,
unsigned attributes,
DlImageSampling options,
SkCanvas::SrcRectConstraint constraint,
DlCanvas::SrcRectConstraint constraint,
bool upload_bitmap) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(
GetPaintForRun(attributes),
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
@ -1026,7 +1018,7 @@ void BM_DrawImageRect(benchmark::State& state,
size_t canvas_size = 2 * bitmap_size;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
sk_sp<SkImage> image;
std::shared_ptr<DlSurfaceInstance> offscreen_instance;
@ -1056,7 +1048,7 @@ void BM_DrawImageRect(benchmark::State& state,
for (size_t i = 0; i < kImagesToDraw; i++) {
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
: offscreen->makeImageSnapshot();
builder.drawImageRect(DlImage::Make(image), src, dst, options, true,
builder.DrawImageRect(DlImage::Make(image), src, dst, options, &paint,
constraint);
dst.offset(offset, offset);
if (dst.right() > canvas_size) {
@ -1070,7 +1062,7 @@ void BM_DrawImageRect(benchmark::State& state,
auto display_list = builder.Build();
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -1104,9 +1096,8 @@ void BM_DrawImageNine(benchmark::State& state,
bool upload_bitmap) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(
GetPaintForRun(attributes),
DisplayListOpFlags::kDrawImageNineWithPaintFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state,
DisplayListOpFlags::kDrawImageNineWithPaintFlags);
@ -1114,7 +1105,7 @@ void BM_DrawImageNine(benchmark::State& state,
size_t canvas_size = 2 * bitmap_size;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4,
bitmap_size / 2, bitmap_size / 2);
@ -1145,7 +1136,7 @@ void BM_DrawImageNine(benchmark::State& state,
for (size_t i = 0; i < kImagesToDraw; i++) {
image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap)
: offscreen->makeImageSnapshot();
builder.drawImageNine(DlImage::Make(image), center, dst, filter, true);
builder.DrawImageNine(DlImage::Make(image), center, dst, filter, &paint);
dst.offset(offset, offset);
if (dst.right() > canvas_size) {
dst.offsetTo(0, dst.y());
@ -1158,7 +1149,7 @@ void BM_DrawImageNine(benchmark::State& state,
auto display_list = builder.Build();
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -1181,15 +1172,15 @@ void BM_DrawTextBlob(benchmark::State& state,
unsigned attributes) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawTextBlobFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawTextBlobFlags);
size_t draw_calls = state.range(0);
size_t canvas_size = kFixedCanvasSize;
surface_provider->InitializeSurface(canvas_size, canvas_size);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
state.counters["DrawCallCount_Varies"] = draw_calls;
state.counters["GlyphCount"] = draw_calls;
@ -1198,13 +1189,13 @@ void BM_DrawTextBlob(benchmark::State& state,
for (size_t i = 0; i < draw_calls; i++) {
character[0] = 'A' + (i % 26);
auto blob = SkTextBlob::MakeFromString(character, SkFont());
builder.drawTextBlob(blob, 50.0f, 50.0f);
builder.DrawTextBlob(blob, 50.0f, 50.0f, paint);
}
auto display_list = builder.Build();
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -1228,14 +1219,14 @@ void BM_DrawShadow(benchmark::State& state,
SkPath::Verb type) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawShadowFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawShadowFlags);
size_t length = kFixedCanvasSize;
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
SkPath path;
@ -1264,12 +1255,12 @@ void BM_DrawShadow(benchmark::State& state,
// We can hardcode dpr to 1.0f as we're varying elevation, and dpr is only
// ever used in conjunction with elevation.
builder.drawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f);
builder.DrawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f);
auto display_list = builder.Build();
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}
@ -1292,14 +1283,14 @@ void BM_SaveLayer(benchmark::State& state,
size_t save_depth) {
auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.SetAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kSaveLayerFlags);
DlPaint paint = GetPaintForRun(attributes);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kSaveLayerFlags);
size_t length = kFixedCanvasSize;
surface_provider->InitializeSurface(length, length);
auto surface = surface_provider->GetPrimarySurface()->sk_surface();
auto canvas = surface->getCanvas();
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
size_t save_layer_calls = state.range(0);
@ -1311,19 +1302,19 @@ void BM_SaveLayer(benchmark::State& state,
state.counters["DrawCallCount_Varies"] = save_layer_calls * save_depth;
for (size_t i = 0; i < save_layer_calls; i++) {
for (size_t j = 0; j < save_depth; j++) {
builder.saveLayer(nullptr, false);
builder.drawRect(rect1);
builder.drawRect(rect2);
builder.SaveLayer(nullptr, nullptr);
builder.DrawRect(rect1, paint);
builder.DrawRect(rect2, paint);
}
for (size_t j = 0; j < save_depth; j++) {
builder.restore();
builder.Restore();
}
}
auto display_list = builder.Build();
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
canvas.DrawDisplayList(display_list);
surface->flushAndSubmit(true);
}

View File

@ -78,7 +78,7 @@ void BM_DrawImageRect(benchmark::State& state,
BackendType backend_type,
unsigned attributes,
DlImageSampling options,
SkCanvas::SrcRectConstraint constraint,
DlCanvas::SrcRectConstraint constraint,
bool upload_bitmap);
void BM_DrawImageNine(benchmark::State& state,
BackendType backend_type,
@ -343,8 +343,8 @@ void BM_SaveLayer(benchmark::State& state,
BM_DrawImageRect, Texture/Strict/BACKEND, \
BackendType::k##BACKEND##_Backend, \
ATTRIBUTES, \
DlImageSampling::kNearestNeighbor, \
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, false) \
DlImageSampling::kNearestNeighbor, \
DlCanvas::SrcRectConstraint::kStrict, false) \
->RangeMultiplier(2) \
->Range(32, 256) \
->UseRealTime() \
@ -354,8 +354,8 @@ void BM_SaveLayer(benchmark::State& state,
BM_DrawImageRect, Texture/Fast/BACKEND, \
BackendType::k##BACKEND##_Backend, \
ATTRIBUTES, \
DlImageSampling::kNearestNeighbor, \
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint, false) \
DlImageSampling::kNearestNeighbor, \
DlCanvas::SrcRectConstraint::kFast, false) \
->RangeMultiplier(2) \
->Range(32, 256) \
->UseRealTime() \
@ -365,8 +365,8 @@ void BM_SaveLayer(benchmark::State& state,
BM_DrawImageRect, Upload/Strict/BACKEND, \
BackendType::k##BACKEND##_Backend, \
ATTRIBUTES, \
DlImageSampling::kNearestNeighbor, \
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, true) \
DlImageSampling::kNearestNeighbor, \
DlCanvas::SrcRectConstraint::kStrict, true) \
->RangeMultiplier(2) \
->Range(32, 256) \
->UseRealTime() \
@ -376,8 +376,8 @@ void BM_SaveLayer(benchmark::State& state,
BM_DrawImageRect, Upload/Fast/BACKEND, \
BackendType::k##BACKEND##_Backend, \
ATTRIBUTES, \
DlImageSampling::kNearestNeighbor, \
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint, true) \
DlImageSampling::kNearestNeighbor, \
DlCanvas::SrcRectConstraint::kFast, true) \
->RangeMultiplier(2) \
->Range(32, 256) \
->UseRealTime() \

View File

@ -66,14 +66,6 @@ enum class DlBlendMode {
kDefaultMode = kSrcOver,
};
inline DlBlendMode ToDl(SkBlendMode mode) {
return static_cast<DlBlendMode>(mode);
}
inline SkBlendMode ToSk(DlBlendMode mode) {
return static_cast<SkBlendMode>(mode);
}
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_

View File

@ -6,7 +6,6 @@
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/display_list/display_list_color_source.h"
#include "flutter/display_list/display_list_ops.h"
#include "fml/logging.h"
@ -250,8 +249,8 @@ void DisplayListBuilder::onSetImageFilter(const DlImageFilter* filter) {
new (pod) DlMatrixImageFilter(matrix_filter);
break;
}
case DlImageFilterType::kComposeFilter:
case DlImageFilterType::kLocalMatrixFilter:
case DlImageFilterType::kCompose:
case DlImageFilterType::kLocalMatrix:
case DlImageFilterType::kColorFilter: {
Push<SetSharedImageFilterOp>(0, 0, filter);
break;
@ -843,7 +842,7 @@ void DisplayListBuilder::drawPoints(PointMode mode,
}
void* data_ptr;
FML_DCHECK(count < Dispatcher::kMaxDrawPointsCount);
FML_DCHECK(count < DlOpReceiver::kMaxDrawPointsCount);
int bytes = count * sizeof(SkPoint);
RectBoundsAccumulator ptBounds;
for (size_t i = 0; i < count; i++) {
@ -947,7 +946,7 @@ void DisplayListBuilder::drawImageRect(const sk_sp<DlImage> image,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
SrcRectConstraint constraint) {
Push<DrawImageRectOp>(0, 1, image, src, dst, sampling, render_with_attributes,
constraint);
CheckLayerOpacityCompatibility(render_with_attributes);
@ -961,10 +960,7 @@ void DisplayListBuilder::DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint,
bool enforce_src_edges) {
SkCanvas::SrcRectConstraint constraint =
enforce_src_edges ? SkCanvas::kStrict_SrcRectConstraint
: SkCanvas::kFast_SrcRectConstraint;
SrcRectConstraint constraint) {
if (paint != nullptr) {
SetAttributesFromPaint(*paint,
DisplayListOpFlags::kDrawImageRectWithPaintFlags);
@ -1077,18 +1073,12 @@ void DisplayListBuilder::DrawAtlas(const sk_sp<DlImage>& atlas,
void DisplayListBuilder::DrawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) {
DlPaint current_paint = current_;
if (opacity < SK_Scalar1) {
SaveLayer(&display_list->bounds(), &DlPaint().setOpacity(opacity));
}
Push<DrawDisplayListOp>(0, 1, display_list);
if (opacity < SK_Scalar1) {
Restore();
// Not really necessary if the developer is interacting with us via
// our attribute-state-less DlCanvas methods, but this avoids surprises
// for those who may have been using the stateful Dispatcher methods.
SetAttributesFromPaint(current_paint,
DisplayListOpFlags::kSaveLayerWithPaintFlags);
}
Push<DrawDisplayListOp>(0, 1, display_list, opacity);
// Not really necessary if the developer is interacting with us via
// our attribute-state-less DlCanvas methods, but this avoids surprises
// for those who may have been using the stateful Dispatcher methods.
SetAttributesFromPaint(current_paint,
DisplayListOpFlags::kSaveLayerWithPaintFlags);
const SkRect bounds = display_list->bounds();
switch (accumulator()->type()) {
@ -1142,8 +1132,8 @@ void DisplayListBuilder::DrawShadow(const SkPath& path,
? Push<DrawShadowTransparentOccluderOp>(0, 1, path, color, elevation, dpr)
: Push<DrawShadowOp>(0, 1, path, color, elevation, dpr);
SkRect shadow_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
path, elevation, dpr, GetTransform());
SkRect shadow_bounds =
DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform());
AccumulateOpBounds(shadow_bounds, kDrawShadowFlags);
UpdateLayerOpacityCompatibility(false);
}
@ -1190,7 +1180,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
pad = std::max(pad, SK_ScalarSqrt2);
}
SkScalar min_stroke_width = 0.01;
pad *= std::max(getStrokeWidth() * 0.5f, min_stroke_width);
pad *= std::max(current_.getStrokeWidth() * 0.5f, min_stroke_width);
bounds.outset(pad, pad);
}
}
@ -1259,7 +1249,7 @@ bool DisplayListBuilder::paint_nops_on_transparency() {
// For example, DstIn is used by masking layers.
// https://code.google.com/p/skia/issues/detail?id=1291
// https://crbug.com/401593
switch (getBlendMode()) {
switch (current_.getBlendMode()) {
// For each of the following transfer modes, if the source
// alpha is zero (our transparent black), the resulting
// blended pixel is not necessarily equal to the original

View File

@ -8,7 +8,6 @@
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_flags.h"
#include "flutter/display_list/display_list_image.h"
#include "flutter/display_list/display_list_matrix_clip_tracker.h"
@ -17,17 +16,18 @@
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_utils.h"
#include "flutter/display_list/dl_canvas.h"
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/macros.h"
namespace flutter {
// The primary class used to build a display list. The list of methods
// here matches the list of methods invoked on a |Dispatcher| combined
// here matches the list of methods invoked on a |DlOpReceiver| combined
// with the list of methods invoked on a |DlCanvas|.
class DisplayListBuilder final : public virtual DlCanvas,
public SkRefCnt,
virtual Dispatcher,
virtual DlOpReceiver,
DisplayListOpFlags {
public:
static constexpr SkRect kMaxCullRect =
@ -39,168 +39,331 @@ class DisplayListBuilder final : public virtual DlCanvas,
explicit DisplayListBuilder(const SkRect& cull_rect = kMaxCullRect,
bool prepare_rtree = false);
SkISize GetBaseLayerSize() const override;
SkImageInfo GetImageInfo() const override;
~DisplayListBuilder();
Dispatcher& asDispatcher() { return *this; }
// |DlCanvas|
SkISize GetBaseLayerSize() const override;
// |DlCanvas|
SkImageInfo GetImageInfo() const override;
// |DlCanvas|
void Save() override;
// |DlCanvas|
void SaveLayer(const SkRect* bounds,
const DlPaint* paint = nullptr,
const DlImageFilter* backdrop = nullptr) override;
// |DlCanvas|
void Restore() override;
// |DlCanvas|
int GetSaveCount() const override { return layer_stack_.size(); }
// |DlCanvas|
void RestoreToCount(int restore_count) override;
// |DlCanvas|
void Translate(SkScalar tx, SkScalar ty) override;
// |DlCanvas|
void Scale(SkScalar sx, SkScalar sy) override;
// |DlCanvas|
void Rotate(SkScalar degrees) override;
// |DlCanvas|
void Skew(SkScalar sx, SkScalar sy) override;
// clang-format off
// 2x3 2D affine subset of a 4x4 transform in row major order
// |DlCanvas|
void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) override;
// full 4x4 transform in row major order
// |DlCanvas|
void TransformFullPerspective(
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
// clang-format on
// |DlCanvas|
void TransformReset() override;
// |DlCanvas|
void Transform(const SkMatrix* matrix) override;
// |DlCanvas|
void Transform(const SkM44* matrix44) override;
// |DlCanvas|
void SetTransform(const SkMatrix* matrix) override {
TransformReset();
Transform(matrix);
}
// |DlCanvas|
void SetTransform(const SkM44* matrix44) override {
TransformReset();
Transform(matrix44);
}
using DlCanvas::Transform;
/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
// |DlCanvas|
SkM44 GetTransformFullPerspective() const override {
return tracker_.matrix_4x4();
}
/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
// |DlCanvas|
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
// |DlCanvas|
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
// |DlCanvas|
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
// |DlCanvas|
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
/// be rendered.
// |DlCanvas|
SkRect GetDestinationClipBounds() const override {
return tracker_.device_cull_rect();
}
/// Conservative estimate of the bounds of all outstanding clip operations
/// transformed into the local coordinate space in which currently
/// recorded rendering operations are interpreted.
// |DlCanvas|
SkRect GetLocalClipBounds() const override {
return tracker_.local_cull_rect();
}
/// Return true iff the supplied bounds are easily shown to be outside
/// of the current clip bounds. This method may conservatively return
/// false if it cannot make the determination.
// |DlCanvas|
bool QuickReject(const SkRect& bounds) const override;
// |DlCanvas|
void DrawPaint(const DlPaint& paint) override;
// |DlCanvas|
void DrawColor(DlColor color, DlBlendMode mode) override;
// |DlCanvas|
void DrawLine(const SkPoint& p0,
const SkPoint& p1,
const DlPaint& paint) override;
// |DlCanvas|
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
// |DlCanvas|
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
// |DlCanvas|
void DrawCircle(const SkPoint& center,
SkScalar radius,
const DlPaint& paint) override;
// |DlCanvas|
void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override;
// |DlCanvas|
void DrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const DlPaint& paint) override;
// |DlCanvas|
void DrawPath(const SkPath& path, const DlPaint& paint) override;
// |DlCanvas|
void DrawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter,
const DlPaint& paint) override;
// |DlCanvas|
void DrawPoints(PointMode mode,
uint32_t count,
const SkPoint pts[],
const DlPaint& paint) override;
// |DlCanvas|
void DrawVertices(const DlVertices* vertices,
DlBlendMode mode,
const DlPaint& paint) override;
using DlCanvas::DrawVertices;
// |DlCanvas|
void DrawImage(const sk_sp<DlImage>& image,
const SkPoint point,
DlImageSampling sampling,
const DlPaint* paint = nullptr) override;
// |DlCanvas|
void DrawImageRect(
const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
// |DlCanvas|
void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
const SkRect& dst,
DlFilterMode filter,
const DlPaint* paint = nullptr) override;
// |DlCanvas|
void DrawAtlas(const sk_sp<DlImage>& atlas,
const SkRSXform xform[],
const SkRect tex[],
const DlColor colors[],
int count,
DlBlendMode mode,
DlImageSampling sampling,
const SkRect* cullRect,
const DlPaint* paint = nullptr) override;
// |DlCanvas|
void DrawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity = SK_Scalar1) override;
// |DlCanvas|
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
SkScalar x,
SkScalar y,
const DlPaint& paint) override;
// |DlCanvas|
void DrawShadow(const SkPath& path,
const DlColor color,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) override;
// |DlCanvas|
void Flush() override {}
sk_sp<DisplayList> Build();
private:
// This method exposes the internal stateful DlOpReceiver implementation
// of the DisplayListBuilder, primarily for testing purposes. Its use
// is obsolete and forbidden in every other case and is only shared to a
// pair of "friend" accessors in the benchmark/unittest files.
DlOpReceiver& asReceiver() { return *this; }
friend DlOpReceiver& DisplayListBuilderBenchmarkAccessor(
DisplayListBuilder& builder);
friend DlOpReceiver& DisplayListBuilderTestingAccessor(
DisplayListBuilder& builder);
void SetAttributesFromPaint(const DlPaint& paint,
const DisplayListAttributeFlags flags);
// |DlOpReceiver|
void setAntiAlias(bool aa) override {
if (current_.isAntiAlias() != aa) {
onSetAntiAlias(aa);
}
}
// |DlOpReceiver|
void setDither(bool dither) override {
if (current_.isDither() != dither) {
onSetDither(dither);
}
}
// |DlOpReceiver|
void setInvertColors(bool invert) override {
if (current_.isInvertColors() != invert) {
onSetInvertColors(invert);
}
}
// |DlOpReceiver|
void setStrokeCap(DlStrokeCap cap) override {
if (current_.getStrokeCap() != cap) {
onSetStrokeCap(cap);
}
}
// |DlOpReceiver|
void setStrokeJoin(DlStrokeJoin join) override {
if (current_.getStrokeJoin() != join) {
onSetStrokeJoin(join);
}
}
// |DlOpReceiver|
void setStyle(DlDrawStyle style) override {
if (current_.getDrawStyle() != style) {
onSetStyle(style);
}
}
// |DlOpReceiver|
void setStrokeWidth(float width) override {
if (current_.getStrokeWidth() != width) {
onSetStrokeWidth(width);
}
}
// |DlOpReceiver|
void setStrokeMiter(float limit) override {
if (current_.getStrokeMiter() != limit) {
onSetStrokeMiter(limit);
}
}
// |DlOpReceiver|
void setColor(DlColor color) override {
if (current_.getColor() != color) {
onSetColor(color);
}
}
// |DlOpReceiver|
void setBlendMode(DlBlendMode mode) override {
if (current_.getBlendMode() != mode) {
onSetBlendMode(mode);
}
}
// |DlOpReceiver|
void setColorSource(const DlColorSource* source) override {
if (NotEquals(current_.getColorSource(), source)) {
onSetColorSource(source);
}
}
// |DlOpReceiver|
void setImageFilter(const DlImageFilter* filter) override {
if (NotEquals(current_.getImageFilter(), filter)) {
onSetImageFilter(filter);
}
}
// |DlOpReceiver|
void setColorFilter(const DlColorFilter* filter) override {
if (NotEquals(current_.getColorFilter(), filter)) {
onSetColorFilter(filter);
}
}
// |DlOpReceiver|
void setPathEffect(const DlPathEffect* effect) override {
if (NotEquals(current_.getPathEffect(), effect)) {
onSetPathEffect(effect);
}
}
// |DlOpReceiver|
void setMaskFilter(const DlMaskFilter* filter) override {
if (NotEquals(current_.getMaskFilter(), filter)) {
onSetMaskFilter(filter);
}
}
bool isAntiAlias() const { return current_.isAntiAlias(); }
bool isDither() const { return current_.isDither(); }
DlDrawStyle getStyle() const { return current_.getDrawStyle(); }
DlColor getColor() const { return current_.getColor(); }
float getStrokeWidth() const { return current_.getStrokeWidth(); }
float getStrokeMiter() const { return current_.getStrokeMiter(); }
DlStrokeCap getStrokeCap() const { return current_.getStrokeCap(); }
DlStrokeJoin getStrokeJoin() const { return current_.getStrokeJoin(); }
std::shared_ptr<const DlColorSource> getColorSource() const {
return current_.getColorSource();
}
std::shared_ptr<const DlColorFilter> getColorFilter() const {
return current_.getColorFilter();
}
bool isInvertColors() const { return current_.isInvertColors(); }
DlBlendMode getBlendMode() const { return current_.getBlendMode(); }
std::shared_ptr<const DlPathEffect> getPathEffect() const {
return current_.getPathEffect();
}
std::shared_ptr<const DlMaskFilter> getMaskFilter() const {
return current_.getMaskFilter();
}
std::shared_ptr<const DlImageFilter> getImageFilter() const {
return current_.getImageFilter();
}
void Save() override;
// |DlOpReceiver|
void save() override { Save(); }
// Only the |renders_with_attributes()| option will be accepted here. Any
// other flags will be ignored and calculated anew as the DisplayList is
// built. Alternatively, use the |saveLayer(SkRect, bool)| method.
// |DlOpReceiver|
void saveLayer(const SkRect* bounds,
const SaveLayerOptions options,
const DlImageFilter* backdrop) override;
// Convenience method with just a boolean to indicate whether the saveLayer
// should apply the rendering attributes.
void saveLayer(const SkRect* bounds, bool renders_with_attributes) {
saveLayer(bounds,
renders_with_attributes ? SaveLayerOptions::kWithAttributes
: SaveLayerOptions::kNoAttributes,
nullptr);
}
void SaveLayer(const SkRect* bounds,
const DlPaint* paint = nullptr,
const DlImageFilter* backdrop = nullptr) override;
void Restore() override;
// |DlOpReceiver|
void restore() override { Restore(); }
int GetSaveCount() const override { return layer_stack_.size(); }
void RestoreToCount(int restore_count) override;
void restoreToCount(int restore_count) { RestoreToCount(restore_count); }
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;
// |DlOpReceiver|
void translate(SkScalar tx, SkScalar ty) override { Translate(tx, ty); }
// |DlOpReceiver|
void scale(SkScalar sx, SkScalar sy) override { Scale(sx, sy); }
// |DlOpReceiver|
void rotate(SkScalar degrees) override { Rotate(degrees); }
// |DlOpReceiver|
void skew(SkScalar sx, SkScalar sy) override { Skew(sx, sy); }
void SetAttributesFromPaint(const DlPaint& paint,
const DisplayListAttributeFlags flags);
// clang-format off
// 2x3 2D affine subset of a 4x4 transform in row major order
void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) override;
// |DlOpReceiver|
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) override {
Transform2DAffine(mxx, mxy, mxt, myx, myy, myt);
}
// full 4x4 transform in row major order
void TransformFullPerspective(
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
// |DlOpReceiver|
void transformFullPerspective(
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
@ -211,148 +374,73 @@ class DisplayListBuilder final : public virtual DlCanvas,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt);
}
// clang-format on
void TransformReset() override;
void Transform(const SkMatrix* matrix) override;
void Transform(const SkM44* matrix44) override;
void SetTransform(const SkMatrix* matrix) override {
TransformReset();
Transform(matrix);
}
void SetTransform(const SkM44* matrix44) override {
TransformReset();
Transform(matrix44);
}
using DlCanvas::Transform;
// clang-format off
// |DlOpReceiver|
void transformReset() override { TransformReset(); }
void transform(const SkMatrix* matrix) { Transform(matrix); }
void transform(const SkM44* matrix44) { Transform(matrix44); }
void transform(const SkMatrix& matrix) { Transform(&matrix); }
void transform(const SkM44& matrix44) { Transform(&matrix44); }
/// Returns the 4x4 full perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkM44 GetTransformFullPerspective() const override {
return tracker_.matrix_4x4();
}
/// Returns the 3x3 partial perspective transform representing all transform
/// operations executed so far in this DisplayList within the enclosing
/// save stack.
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
// |DlOpReceiver|
void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override {
ClipRect(rect, clip_op, is_aa);
}
// |DlOpReceiver|
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override {
ClipRRect(rrect, clip_op, is_aa);
}
// |DlOpReceiver|
void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override {
ClipPath(path, clip_op, is_aa);
}
/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
/// be rendered.
SkRect GetDestinationClipBounds() const override {
return tracker_.device_cull_rect();
}
/// Conservative estimate of the bounds of all outstanding clip operations
/// transformed into the local coordinate space in which currently
/// recorded rendering operations are interpreted.
SkRect GetLocalClipBounds() const override {
return tracker_.local_cull_rect();
}
/// Return true iff the supplied bounds are easily shown to be outside
/// of the current clip bounds. This method may conservatively return
/// false if it cannot make the determination.
bool QuickReject(const SkRect& bounds) const override;
// |DlOpReceiver|
void drawPaint() override;
void DrawPaint(const DlPaint& paint) override;
void DrawColor(DlColor color, DlBlendMode mode) override;
// |DlOpReceiver|
void drawColor(DlColor color, DlBlendMode mode) override {
DrawColor(color, mode);
}
// |DlOpReceiver|
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
void DrawLine(const SkPoint& p0,
const SkPoint& p1,
const DlPaint& paint) override;
// |DlOpReceiver|
void drawRect(const SkRect& rect) override;
void DrawRect(const SkRect& rect, const DlPaint& paint) override;
// |DlOpReceiver|
void drawOval(const SkRect& bounds) override;
void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
// |DlOpReceiver|
void drawCircle(const SkPoint& center, SkScalar radius) override;
void DrawCircle(const SkPoint& center,
SkScalar radius,
const DlPaint& paint) override;
// |DlOpReceiver|
void drawRRect(const SkRRect& rrect) override;
void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override;
// |DlOpReceiver|
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
void DrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const DlPaint& paint) override;
// |DlOpReceiver|
void drawPath(const SkPath& path) override;
void DrawPath(const SkPath& path, const DlPaint& paint) override;
// |DlOpReceiver|
void drawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter) override;
void DrawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter,
const DlPaint& paint) override;
// |DlOpReceiver|
void drawPoints(PointMode mode, uint32_t count, const SkPoint pts[]) override;
void DrawPoints(PointMode mode,
uint32_t count,
const SkPoint pts[],
const DlPaint& paint) override;
// |DlOpReceiver|
void drawVertices(const DlVertices* vertices, DlBlendMode mode) override;
void drawVertices(const std::shared_ptr<const DlVertices> vertices,
DlBlendMode mode) {
drawVertices(vertices.get(), mode);
}
void DrawVertices(const DlVertices* vertices,
DlBlendMode mode,
const DlPaint& paint) override;
using DlCanvas::DrawVertices;
// |DlOpReceiver|
void drawImage(const sk_sp<DlImage> image,
const SkPoint point,
DlImageSampling sampling,
bool render_with_attributes) override;
void DrawImage(const sk_sp<DlImage>& image,
const SkPoint point,
DlImageSampling sampling,
const DlPaint* paint = nullptr) override;
// |DlOpReceiver|
void drawImageRect(
const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint =
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint) override;
void DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) override;
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
// |DlOpReceiver|
void drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
DlFilterMode filter,
bool render_with_attributes) override;
void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
const SkRect& dst,
DlFilterMode filter,
const DlPaint* paint = nullptr) override;
// |DlOpReceiver|
void drawAtlas(const sk_sp<DlImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
@ -362,32 +450,17 @@ class DisplayListBuilder final : public virtual DlCanvas,
DlImageSampling sampling,
const SkRect* cullRect,
bool render_with_attributes) override;
void DrawAtlas(const sk_sp<DlImage>& atlas,
const SkRSXform xform[],
const SkRect tex[],
const DlColor colors[],
int count,
DlBlendMode mode,
DlImageSampling sampling,
const SkRect* cullRect,
const DlPaint* paint = nullptr) override;
void DrawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override {
DrawDisplayList(display_list, SK_Scalar1);
// |DlOpReceiver|
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override {
DrawDisplayList(display_list, opacity);
}
// |DlOpReceiver|
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
SkScalar x,
SkScalar y,
const DlPaint& paint) override;
void DrawShadow(const SkPath& path,
const DlColor color,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) override;
// |DlOpReceiver|
void drawShadow(const SkPath& path,
const DlColor color,
const SkScalar elevation,
@ -396,11 +469,6 @@ class DisplayListBuilder final : public virtual DlCanvas,
DrawShadow(path, color, elevation, transparent_occluder, dpr);
}
void Flush() override {}
sk_sp<DisplayList> Build();
private:
void checkForDeferredSave();
DisplayListStorage storage_;

View File

@ -6,6 +6,11 @@
#include "flutter/display_list/testing/dl_test_snippets.h"
namespace flutter {
DlOpReceiver& DisplayListBuilderBenchmarkAccessor(DisplayListBuilder& builder) {
return builder.asReceiver();
}
namespace {
static std::vector<testing::DisplayListInvocationGroup> allRenderingOps =
@ -19,10 +24,11 @@ enum class DisplayListBuilderBenchmarkType {
};
static void InvokeAllRenderingOps(DisplayListBuilder& builder) {
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
for (auto& group : allRenderingOps) {
for (size_t i = 0; i < group.variants.size(); i++) {
auto& invocation = group.variants[i];
invocation.Invoke(builder);
invocation.Invoke(receiver);
}
}
}
@ -69,8 +75,8 @@ static void BM_DisplayListBuilderWithScaleAndTranslate(
bool prepare_rtree = NeedPrepareRTree(type);
while (state.KeepRunning()) {
DisplayListBuilder builder(prepare_rtree);
builder.scale(3.5, 3.5);
builder.translate(10.3, 6.9);
builder.Scale(3.5, 3.5);
builder.Translate(10.3, 6.9);
InvokeAllRenderingOps(builder);
Complete(builder, type);
}
@ -82,7 +88,7 @@ static void BM_DisplayListBuilderWithPerspective(
bool prepare_rtree = NeedPrepareRTree(type);
while (state.KeepRunning()) {
DisplayListBuilder builder(prepare_rtree);
builder.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0,
builder.TransformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0,
0, 0, 12);
InvokeAllRenderingOps(builder);
Complete(builder, type);
@ -96,7 +102,7 @@ static void BM_DisplayListBuilderWithClipRect(
bool prepare_rtree = NeedPrepareRTree(type);
while (state.KeepRunning()) {
DisplayListBuilder builder(prepare_rtree);
builder.clipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true);
builder.ClipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true);
InvokeAllRenderingOps(builder);
Complete(builder, type);
}
@ -108,12 +114,13 @@ static void BM_DisplayListBuilderWithSaveLayer(
bool prepare_rtree = NeedPrepareRTree(type);
while (state.KeepRunning()) {
DisplayListBuilder builder(prepare_rtree);
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
for (auto& group : allRenderingOps) {
for (size_t i = 0; i < group.variants.size(); i++) {
auto& invocation = group.variants[i];
builder.saveLayer(nullptr, false);
invocation.Invoke(builder);
builder.restore();
builder.SaveLayer(nullptr, nullptr);
invocation.Invoke(receiver);
builder.Restore();
}
}
Complete(builder, type);
@ -129,11 +136,12 @@ static void BM_DisplayListBuilderWithSaveLayerAndImageFilter(
bool prepare_rtree = NeedPrepareRTree(type);
while (state.KeepRunning()) {
DisplayListBuilder builder(prepare_rtree);
DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
for (auto& group : allRenderingOps) {
for (size_t i = 0; i < group.variants.size(); i++) {
auto& invocation = group.variants[i];
builder.SaveLayer(&layer_bounds, &layer_paint);
invocation.Invoke(builder);
invocation.Invoke(receiver);
builder.Restore();
}
}

View File

@ -1,305 +0,0 @@
// 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.
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/fml/trace_event.h"
namespace flutter {
const SkScalar kLightHeight = 600;
const SkScalar kLightRadius = 800;
static SkClipOp ToSk(DlCanvas::ClipOp op) {
return static_cast<SkClipOp>(op);
}
static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
return static_cast<SkCanvas::PointMode>(mode);
}
const SkPaint* DisplayListCanvasDispatcher::safe_paint(bool use_attributes) {
if (use_attributes) {
// The accumulated SkPaint object will already have incorporated
// any attribute overrides.
return &paint();
} else if (has_opacity()) {
temp_paint_.setAlphaf(opacity());
return &temp_paint_;
} else {
return nullptr;
}
}
void DisplayListCanvasDispatcher::save() {
canvas_->save();
// save has no impact on attributes, but it needs to register a record
// on the restore stack so that the eventual call to restore() will
// know what to do at that time. We could annotate the restore record
// with a flag that the record came from a save call, but it is simpler
// to just pass in the current opacity value as the value to be used by
// the children and let the utility calls notice that it didn't change.
save_opacity(opacity());
}
void DisplayListCanvasDispatcher::restore() {
canvas_->restore();
restore_opacity();
}
void DisplayListCanvasDispatcher::saveLayer(const SkRect* bounds,
const SaveLayerOptions options,
const DlImageFilter* backdrop) {
if (bounds == nullptr && options.can_distribute_opacity() &&
backdrop == nullptr) {
// We know that:
// - no bounds is needed for clipping here
// - no backdrop filter is used to initialize the layer
// - the current attributes only have an alpha
// - the children are compatible with individually rendering with
// an inherited opacity
// Therefore we can just use a save instead of a saveLayer and pass the
// intended opacity to the children.
canvas_->save();
// If the saveLayer does not use attributes, the children should continue
// to render with the inherited opacity unmodified. If attributes are to
// be applied, the children should render with the combination of the
// inherited opacity combined with the alpha from the current color.
save_opacity(options.renders_with_attributes() ? combined_opacity()
: opacity());
} else {
TRACE_EVENT0("flutter", "Canvas::saveLayer");
const SkPaint* paint = safe_paint(options.renders_with_attributes());
const sk_sp<SkImageFilter> sk_backdrop =
backdrop ? backdrop->skia_object() : nullptr;
canvas_->saveLayer(
SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0));
// saveLayer will apply the current opacity on behalf of the children
// so they will inherit an opaque opacity.
save_opacity(SK_Scalar1);
}
}
void DisplayListCanvasDispatcher::translate(SkScalar tx, SkScalar ty) {
canvas_->translate(tx, ty);
}
void DisplayListCanvasDispatcher::scale(SkScalar sx, SkScalar sy) {
canvas_->scale(sx, sy);
}
void DisplayListCanvasDispatcher::rotate(SkScalar degrees) {
canvas_->rotate(degrees);
}
void DisplayListCanvasDispatcher::skew(SkScalar sx, SkScalar sy) {
canvas_->skew(sx, sy);
}
// clang-format off
// 2x3 2D affine subset of a 4x4 transform in row major order
void DisplayListCanvasDispatcher::transform2DAffine(
SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) {
// Internally concat(SkMatrix) gets redirected to concat(SkM44)
// so we just jump directly to the SkM44 version
canvas_->concat(SkM44(mxx, mxy, 0, mxt,
myx, myy, 0, myt,
0, 0, 1, 0,
0, 0, 0, 1));
}
// full 4x4 transform in row major order
void DisplayListCanvasDispatcher::transformFullPerspective(
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
canvas_->concat(SkM44(mxx, mxy, mxz, mxt,
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt));
}
// clang-format on
void DisplayListCanvasDispatcher::transformReset() {
canvas_->setMatrix(original_transform_);
}
void DisplayListCanvasDispatcher::clipRect(const SkRect& rect,
ClipOp clip_op,
bool is_aa) {
canvas_->clipRect(rect, ToSk(clip_op), is_aa);
}
void DisplayListCanvasDispatcher::clipRRect(const SkRRect& rrect,
ClipOp clip_op,
bool is_aa) {
canvas_->clipRRect(rrect, ToSk(clip_op), is_aa);
}
void DisplayListCanvasDispatcher::clipPath(const SkPath& path,
ClipOp clip_op,
bool is_aa) {
canvas_->clipPath(path, ToSk(clip_op), is_aa);
}
void DisplayListCanvasDispatcher::drawPaint() {
const SkPaint& sk_paint = paint();
SkImageFilter* filter = sk_paint.getImageFilter();
if (filter && !filter->asColorFilter(nullptr)) {
// drawPaint does an implicit saveLayer if an SkImageFilter is
// present that cannot be replaced by an SkColorFilter.
TRACE_EVENT0("flutter", "Canvas::saveLayer");
}
canvas_->drawPaint(sk_paint);
}
void DisplayListCanvasDispatcher::drawColor(DlColor color, DlBlendMode mode) {
// SkCanvas::drawColor(SkColor) does the following conversion anyway
// We do it here manually to increase precision on applying opacity
SkColor4f color4f = SkColor4f::FromColor(color);
color4f.fA *= opacity();
canvas_->drawColor(color4f, ToSk(mode));
}
void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0,
const SkPoint& p1) {
canvas_->drawLine(p0, p1, paint());
}
void DisplayListCanvasDispatcher::drawRect(const SkRect& rect) {
canvas_->drawRect(rect, paint());
}
void DisplayListCanvasDispatcher::drawOval(const SkRect& bounds) {
canvas_->drawOval(bounds, paint());
}
void DisplayListCanvasDispatcher::drawCircle(const SkPoint& center,
SkScalar radius) {
canvas_->drawCircle(center, radius, paint());
}
void DisplayListCanvasDispatcher::drawRRect(const SkRRect& rrect) {
canvas_->drawRRect(rrect, paint());
}
void DisplayListCanvasDispatcher::drawDRRect(const SkRRect& outer,
const SkRRect& inner) {
canvas_->drawDRRect(outer, inner, paint());
}
void DisplayListCanvasDispatcher::drawPath(const SkPath& path) {
canvas_->drawPath(path, paint());
}
void DisplayListCanvasDispatcher::drawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter) {
canvas_->drawArc(bounds, start, sweep, useCenter, paint());
}
void DisplayListCanvasDispatcher::drawPoints(PointMode mode,
uint32_t count,
const SkPoint pts[]) {
canvas_->drawPoints(ToSk(mode), count, pts, paint());
}
void DisplayListCanvasDispatcher::drawVertices(const DlVertices* vertices,
DlBlendMode mode) {
canvas_->drawVertices(vertices->skia_object(), ToSk(mode), paint());
}
void DisplayListCanvasDispatcher::drawImage(const sk_sp<DlImage> image,
const SkPoint point,
DlImageSampling sampling,
bool render_with_attributes) {
canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY,
ToSk(sampling), safe_paint(render_with_attributes));
}
void DisplayListCanvasDispatcher::drawImageRect(
const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst,
ToSk(sampling), safe_paint(render_with_attributes),
constraint);
}
void DisplayListCanvasDispatcher::drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
DlFilterMode filter,
bool render_with_attributes) {
if (!image) {
return;
}
auto skia_image = image->skia_image();
if (!skia_image) {
return;
}
canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter),
safe_paint(render_with_attributes));
}
void DisplayListCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
const DlColor colors[],
int count,
DlBlendMode mode,
DlImageSampling sampling,
const SkRect* cullRect,
bool render_with_attributes) {
if (!atlas) {
return;
}
auto skia_atlas = atlas->skia_image();
if (!skia_atlas) {
return;
}
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors);
canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode),
ToSk(sampling), cullRect,
safe_paint(render_with_attributes));
}
void DisplayListCanvasDispatcher::drawDisplayList(
const sk_sp<DisplayList> display_list) {
int save_count = canvas_->save();
display_list->RenderTo(canvas_, opacity());
canvas_->restoreToCount(save_count);
}
void DisplayListCanvasDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) {
canvas_->drawTextBlob(blob, x, y, paint());
}
SkRect DisplayListCanvasDispatcher::ComputeShadowBounds(const SkPath& path,
float elevation,
SkScalar dpr,
const SkMatrix& ctm) {
SkRect shadow_bounds(path.getBounds());
SkShadowUtils::GetLocalBounds(
ctm, path, SkPoint3::Make(0, 0, dpr * elevation),
SkPoint3::Make(0, -1, 1), kLightRadius / kLightHeight,
SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds);
return shadow_bounds;
}
void DisplayListCanvasDispatcher::DrawShadow(SkCanvas* canvas,
const SkPath& path,
DlColor color,
float elevation,
bool transparentOccluder,
SkScalar dpr) {
const SkScalar kAmbientAlpha = 0.039f;
const SkScalar kSpotAlpha = 0.25f;
uint32_t flags = transparentOccluder
? SkShadowFlags::kTransparentOccluder_ShadowFlag
: SkShadowFlags::kNone_ShadowFlag;
flags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color));
SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color));
SkColor ambient_color, spot_color;
SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color,
&spot_color);
SkShadowUtils::DrawShadow(canvas, path, SkPoint3::Make(0, 0, dpr * elevation),
SkPoint3::Make(0, -1, 1),
kLightRadius / kLightHeight, ambient_color,
spot_color, flags);
}
void DisplayListCanvasDispatcher::drawShadow(const SkPath& path,
const DlColor color,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) {
DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr);
}
} // namespace flutter

View File

@ -35,6 +35,7 @@ struct DlColor {
uint32_t argb;
bool isOpaque() const { return getAlpha() == 0xFF; }
bool isTransparent() const { return getAlpha() == 0; }
int getAlpha() const { return argb >> 24; }
int getRed() const { return (argb >> 16) & 0xFF; }

View File

@ -8,16 +8,193 @@
namespace flutter {
std::shared_ptr<DlColorFilter> DlBlendColorFilter::Make(DlColor color,
DlBlendMode mode) {
switch (mode) {
case DlBlendMode::kDst: {
return nullptr;
}
case DlBlendMode::kSrcOver: {
if (color.isTransparent()) {
return nullptr;
}
if (color.isOpaque()) {
mode = DlBlendMode::kSrc;
}
break;
}
case DlBlendMode::kDstOver:
case DlBlendMode::kDstOut:
case DlBlendMode::kSrcATop:
case DlBlendMode::kXor:
case DlBlendMode::kDarken: {
if (color.isTransparent()) {
return nullptr;
}
break;
}
case DlBlendMode::kDstIn: {
if (color.isOpaque()) {
return nullptr;
}
break;
}
default:
break;
}
return std::make_shared<DlBlendColorFilter>(color, mode);
}
bool DlBlendColorFilter::modifies_transparent_black() const {
switch (mode_) {
// These modes all act like kSrc when the dest is all 0s.
// So they modify transparent black when the src color is
// not transparent.
case DlBlendMode::kSrc:
case DlBlendMode::kSrcOver:
case DlBlendMode::kDstOver:
case DlBlendMode::kSrcOut:
case DlBlendMode::kDstATop:
case DlBlendMode::kXor:
case DlBlendMode::kPlus:
case DlBlendMode::kScreen:
case DlBlendMode::kOverlay:
case DlBlendMode::kDarken:
case DlBlendMode::kLighten:
case DlBlendMode::kColorDodge:
case DlBlendMode::kColorBurn:
case DlBlendMode::kHardLight:
case DlBlendMode::kSoftLight:
case DlBlendMode::kDifference:
case DlBlendMode::kExclusion:
case DlBlendMode::kMultiply:
case DlBlendMode::kHue:
case DlBlendMode::kSaturation:
case DlBlendMode::kColor:
case DlBlendMode::kLuminosity:
return !color_.isTransparent();
// These modes are all like kDst when the dest is all 0s.
// So they never modify transparent black.
case DlBlendMode::kClear:
case DlBlendMode::kDst:
case DlBlendMode::kSrcIn:
case DlBlendMode::kDstIn:
case DlBlendMode::kDstOut:
case DlBlendMode::kSrcATop:
case DlBlendMode::kModulate:
return false;
}
}
bool DlBlendColorFilter::can_commute_with_opacity() const {
switch (mode_) {
case DlBlendMode::kClear:
case DlBlendMode::kDst:
case DlBlendMode::kSrcIn:
case DlBlendMode::kDstIn:
case DlBlendMode::kDstOut:
case DlBlendMode::kSrcATop:
case DlBlendMode::kModulate:
return true;
case DlBlendMode::kSrc:
case DlBlendMode::kSrcOver:
case DlBlendMode::kDstOver:
case DlBlendMode::kSrcOut:
case DlBlendMode::kDstATop:
case DlBlendMode::kXor:
case DlBlendMode::kPlus:
case DlBlendMode::kScreen:
case DlBlendMode::kOverlay:
case DlBlendMode::kDarken:
case DlBlendMode::kLighten:
case DlBlendMode::kColorDodge:
case DlBlendMode::kColorBurn:
case DlBlendMode::kHardLight:
case DlBlendMode::kSoftLight:
case DlBlendMode::kDifference:
case DlBlendMode::kExclusion:
case DlBlendMode::kMultiply:
case DlBlendMode::kHue:
case DlBlendMode::kSaturation:
case DlBlendMode::kColor:
case DlBlendMode::kLuminosity:
return color_.isTransparent();
}
}
std::shared_ptr<DlColorFilter> DlMatrixColorFilter::Make(
const float matrix[20]) {
float product = 0;
for (int i = 0; i < 20; i++) {
product *= matrix[i];
}
// If any of the elements of the matrix are infinity or NaN, then
// |product| will be NaN, otherwise 0.
if (product == 0) {
return std::make_shared<DlMatrixColorFilter>(matrix);
}
return nullptr;
}
bool DlMatrixColorFilter::modifies_transparent_black() const {
// Values are considered in non-premultiplied form when the matrix is
// applied, but we only care about this answer for whether it leaves
// an incoming color with a transparent alpha as transparent on output.
// Thus, we only need to consider the alpha part of the matrix equation,
// which is the last row. Since the incoming alpha value is 0, the last
// equation ends up becoming A' = matrix_[19]. Negative results will be
// clamped to the range [0,1] so we only care about positive values.
// Non-finite values are clamped to a zero alpha.
return (SkScalarIsFinite(matrix_[19]) && matrix_[19] > 0);
}
bool DlMatrixColorFilter::can_commute_with_opacity() const {
// We need to check if:
// filter(color) * opacity == filter(color * opacity).
//
// filter(RGBA) = R' = [ R*m[ 0] + G*m[ 1] + B*m[ 2] + A*m[ 3] + m[ 4] ]
// G' = [ R*m[ 5] + G*m[ 6] + B*m[ 7] + A*m[ 8] + m[ 9] ]
// B' = [ R*m[10] + G*m[11] + B*m[12] + A*m[13] + m[14] ]
// A' = [ R*m[15] + G*m[16] + B*m[17] + A*m[18] + m[19] ]
//
// Applying the opacity only affects the alpha value since the operations
// are performed on non-premultiplied colors. (If the data is stored in
// premultiplied form, though, there may be rounding errors due to
// premul->unpremul->premul conversions.)
// We test for the successful cases and return false if they fail so that
// we fail and return false if any matrix values are NaN.
// If any of the alpha column are non-zero then the prior alpha affects
// the result color, so applying opacity before the filter will change
// the incoming alpha and therefore the colors that are produced.
if (!(matrix_[3] == 0 && // A does not affect R'
matrix_[8] == 0 && // A does not affect G'
matrix_[13] == 0)) { // A does not affect B'
return false;
}
// Similarly, if any of the alpha row are non-zero then the prior colors
// affect the result alpha in a way that prevents opacity from commuting
// through the filter operation.
if (!(matrix_[15] == 0 && // R does not affect A'
matrix_[16] == 0 && // G does not affect A'
matrix_[17] == 0 && // B does not affect A'
matrix_[19] == 0)) { // A' is not offset by an absolute value
return false;
}
return true;
}
const std::shared_ptr<DlSrgbToLinearGammaColorFilter>
DlSrgbToLinearGammaColorFilter::instance =
std::make_shared<DlSrgbToLinearGammaColorFilter>();
const sk_sp<SkColorFilter> DlSrgbToLinearGammaColorFilter::sk_filter_ =
SkColorFilters::SRGBToLinearGamma();
const std::shared_ptr<DlLinearToSrgbGammaColorFilter>
DlLinearToSrgbGammaColorFilter::instance =
std::make_shared<DlLinearToSrgbGammaColorFilter>();
const sk_sp<SkColorFilter> DlLinearToSrgbGammaColorFilter::sk_filter_ =
SkColorFilters::LinearToSRGBGamma();
} // namespace flutter

View File

@ -28,8 +28,7 @@ enum class DlColorFilterType {
kLinearToSrgbGamma,
};
class DlColorFilter
: public DlAttribute<DlColorFilter, SkColorFilter, DlColorFilterType> {
class DlColorFilter : public DlAttribute<DlColorFilter, DlColorFilterType> {
public:
// Return a boolean indicating whether the color filtering operation will
// modify transparent black. This is typically used to determine if applying
@ -68,23 +67,18 @@ class DlBlendColorFilter final : public DlColorFilter {
DlBlendColorFilter(const DlBlendColorFilter* filter)
: DlBlendColorFilter(filter->color_, filter->mode_) {}
static std::shared_ptr<DlColorFilter> Make(DlColor color, DlBlendMode mode);
DlColorFilterType type() const override { return DlColorFilterType::kBlend; }
size_t size() const override { return sizeof(*this); }
bool modifies_transparent_black() const override {
// Look at blend and color to make a faster determination?
sk_sp<SkColorFilter> sk_filter = skia_object();
return sk_filter &&
sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
}
bool modifies_transparent_black() const override;
bool can_commute_with_opacity() const override;
std::shared_ptr<DlColorFilter> shared() const override {
return std::make_shared<DlBlendColorFilter>(this);
}
sk_sp<SkColorFilter> skia_object() const override {
return SkColorFilters::Blend(color_, ToSk(mode_));
}
const DlBlendColorFilter* asBlend() const override { return this; }
DlColor color() const { return color_; }
@ -114,6 +108,10 @@ class DlBlendColorFilter final : public DlColorFilter {
//
// The resulting color [oR,oG,oB,oA] is then clamped to the range of
// valid pixel components before storing in the output.
//
// The incoming and outgoing [iR,iG,iB,iA] and [oR,oG,oB,oA] are
// considered to be non-premultiplied. When working on premultiplied
// pixel data, the necessary pre<->non-pre conversions must be performed.
class DlMatrixColorFilter final : public DlColorFilter {
public:
DlMatrixColorFilter(const float matrix[20]) {
@ -124,30 +122,18 @@ class DlMatrixColorFilter final : public DlColorFilter {
DlMatrixColorFilter(const DlMatrixColorFilter* filter)
: DlMatrixColorFilter(filter->matrix_) {}
static std::shared_ptr<DlColorFilter> Make(const float matrix[20]);
DlColorFilterType type() const override { return DlColorFilterType::kMatrix; }
size_t size() const override { return sizeof(*this); }
bool modifies_transparent_black() const override {
// Look at the matrix to make a faster determination?
// Basically, are the translation components all 0?
sk_sp<SkColorFilter> sk_filter = skia_object();
return sk_filter &&
sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
}
bool can_commute_with_opacity() const override {
return matrix_[3] == 0 && matrix_[8] == 0 && matrix_[13] == 0 &&
matrix_[15] == 0 && matrix_[16] == 0 && matrix_[17] == 0 &&
(matrix_[18] >= 0.0 && matrix_[18] <= 1.0) && matrix_[19] == 0;
}
bool modifies_transparent_black() const override;
bool can_commute_with_opacity() const override;
std::shared_ptr<DlColorFilter> shared() const override {
return std::make_shared<DlMatrixColorFilter>(this);
}
sk_sp<SkColorFilter> skia_object() const override {
return SkColorFilters::Matrix(matrix_);
}
const DlMatrixColorFilter* asMatrix() const override { return this; }
const float& operator[](int index) const { return matrix_[index]; }
@ -186,7 +172,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter {
bool can_commute_with_opacity() const override { return true; }
std::shared_ptr<DlColorFilter> shared() const override { return instance; }
sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }
protected:
bool equals_(const DlColorFilter& other) const override {
@ -195,7 +180,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter {
}
private:
static const sk_sp<SkColorFilter> sk_filter_;
friend class DlColorFilter;
};
@ -219,7 +203,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter {
bool can_commute_with_opacity() const override { return true; }
std::shared_ptr<DlColorFilter> shared() const override { return instance; }
sk_sp<SkColorFilter> skia_object() const override { return sk_filter_; }
protected:
bool equals_(const DlColorFilter& other) const override {
@ -228,7 +211,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter {
}
private:
static const sk_sp<SkColorFilter> sk_filter_;
friend class DlColorFilter;
};

View File

@ -17,18 +17,6 @@ static const float kMatrix[20] = {
16, 17, 18, 19, 20, //
};
TEST(DisplayListColorFilter, BuilderSetGet) {
DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop);
DisplayListBuilder builder;
ASSERT_EQ(builder.getColorFilter(), nullptr);
builder.setColorFilter(&filter);
ASSERT_NE(builder.getColorFilter(), nullptr);
ASSERT_TRUE(
Equals(builder.getColorFilter(), static_cast<DlColorFilter*>(&filter)));
builder.setColorFilter(nullptr);
ASSERT_EQ(builder.getColorFilter(), nullptr);
}
TEST(DisplayListColorFilter, BlendConstructor) {
DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop);
}

View File

@ -19,7 +19,7 @@ static void DlGradientDeleter(void* p) {
::operator delete(p);
}
std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
std::shared_ptr<DlLinearGradientColorSource> DlColorSource::MakeLinear(
const SkPoint start_point,
const SkPoint end_point,
uint32_t stop_count,
@ -37,10 +37,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
DlLinearGradientColorSource(start_point, end_point, stop_count,
colors, stops, tile_mode, matrix),
DlGradientDeleter);
return std::move(ret);
return ret;
}
std::shared_ptr<DlColorSource> DlColorSource::MakeRadial(
std::shared_ptr<DlRadialGradientColorSource> DlColorSource::MakeRadial(
SkPoint center,
SkScalar radius,
uint32_t stop_count,
@ -57,10 +57,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeRadial(
ret.reset(new (storage) DlRadialGradientColorSource(
center, radius, stop_count, colors, stops, tile_mode, matrix),
DlGradientDeleter);
return std::move(ret);
return ret;
}
std::shared_ptr<DlColorSource> DlColorSource::MakeConical(
std::shared_ptr<DlConicalGradientColorSource> DlColorSource::MakeConical(
SkPoint start_center,
SkScalar start_radius,
SkPoint end_center,
@ -80,10 +80,10 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeConical(
start_center, start_radius, end_center, end_radius, stop_count,
colors, stops, tile_mode, matrix),
DlGradientDeleter);
return std::move(ret);
return ret;
}
std::shared_ptr<DlColorSource> DlColorSource::MakeSweep(
std::shared_ptr<DlSweepGradientColorSource> DlColorSource::MakeSweep(
SkPoint center,
SkScalar start,
SkScalar end,
@ -102,7 +102,7 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeSweep(
DlSweepGradientColorSource(center, start, end, stop_count,
colors, stops, tile_mode, matrix),
DlGradientDeleter);
return std::move(ret);
return ret;
}
std::shared_ptr<DlRuntimeEffectColorSource> DlColorSource::MakeRuntimeEffect(

View File

@ -63,10 +63,9 @@ enum class DlColorSourceType {
#endif // IMPELLER_ENABLE_3D
};
class DlColorSource
: public DlAttribute<DlColorSource, SkShader, DlColorSourceType> {
class DlColorSource : public DlAttribute<DlColorSource, DlColorSourceType> {
public:
static std::shared_ptr<DlColorSource> MakeLinear(
static std::shared_ptr<DlLinearGradientColorSource> MakeLinear(
const SkPoint start_point,
const SkPoint end_point,
uint32_t stop_count,
@ -75,7 +74,7 @@ class DlColorSource
DlTileMode tile_mode,
const SkMatrix* matrix = nullptr);
static std::shared_ptr<DlColorSource> MakeRadial(
static std::shared_ptr<DlRadialGradientColorSource> MakeRadial(
SkPoint center,
SkScalar radius,
uint32_t stop_count,
@ -84,7 +83,7 @@ class DlColorSource
DlTileMode tile_mode,
const SkMatrix* matrix = nullptr);
static std::shared_ptr<DlColorSource> MakeConical(
static std::shared_ptr<DlConicalGradientColorSource> MakeConical(
SkPoint start_center,
SkScalar start_radius,
SkPoint end_center,
@ -95,7 +94,7 @@ class DlColorSource
DlTileMode tile_mode,
const SkMatrix* matrix = nullptr);
static std::shared_ptr<DlColorSource> MakeSweep(
static std::shared_ptr<DlSweepGradientColorSource> MakeSweep(
SkPoint center,
SkScalar start,
SkScalar end,
@ -190,10 +189,6 @@ class DlColorColorSource final : public DlColorSource {
DlColor color() const { return color_; }
sk_sp<SkShader> skia_object() const override {
return SkShaders::Color(color_);
}
protected:
bool equals_(DlColorSource const& other) const override {
FML_DCHECK(other.type() == DlColorSourceType::kColor);
@ -263,15 +258,6 @@ class DlImageColorSource final : public SkRefCnt,
DlTileMode vertical_tile_mode() const { return vertical_tile_mode_; }
DlImageSampling sampling() const { return sampling_; }
virtual sk_sp<SkShader> skia_object() const override {
if (!image_->skia_image()) {
return nullptr;
}
return image_->skia_image()->makeShader(ToSk(horizontal_tile_mode_),
ToSk(vertical_tile_mode_),
ToSk(sampling_), matrix_ptr());
}
protected:
bool equals_(DlColorSource const& other) const override {
FML_DCHECK(other.type() == DlColorSourceType::kImage);
@ -386,13 +372,6 @@ class DlLinearGradientColorSource final : public DlGradientColorSourceBase {
const SkPoint& start_point() const { return start_point_; }
const SkPoint& end_point() const { return end_point_; }
sk_sp<SkShader> skia_object() const override {
SkPoint pts[] = {start_point_, end_point_};
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
return SkGradientShader::MakeLinear(pts, sk_colors, stops(), stop_count(),
ToSk(tile_mode()), 0, matrix_ptr());
}
protected:
virtual const void* pod() const override { return this + 1; }
@ -454,13 +433,6 @@ class DlRadialGradientColorSource final : public DlGradientColorSourceBase {
SkPoint center() const { return center_; }
SkScalar radius() const { return radius_; }
sk_sp<SkShader> skia_object() const override {
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
return SkGradientShader::MakeRadial(center_, radius_, sk_colors, stops(),
stop_count(), ToSk(tile_mode()), 0,
matrix_ptr());
}
protected:
virtual const void* pod() const override { return this + 1; }
@ -525,13 +497,6 @@ class DlConicalGradientColorSource final : public DlGradientColorSourceBase {
SkPoint end_center() const { return end_center_; }
SkScalar end_radius() const { return end_radius_; }
sk_sp<SkShader> skia_object() const override {
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
return SkGradientShader::MakeTwoPointConical(
start_center_, start_radius_, end_center_, end_radius_, sk_colors,
stops(), stop_count(), ToSk(tile_mode()), 0, matrix_ptr());
}
protected:
virtual const void* pod() const override { return this + 1; }
@ -604,13 +569,6 @@ class DlSweepGradientColorSource final : public DlGradientColorSourceBase {
SkScalar start() const { return start_; }
SkScalar end() const { return end_; }
sk_sp<SkShader> skia_object() const override {
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
return SkGradientShader::MakeSweep(center_.x(), center_.y(), sk_colors,
stops(), stop_count(), ToSk(tile_mode()),
start_, end_, 0, matrix_ptr());
}
protected:
virtual const void* pod() const override { return this + 1; }
@ -693,35 +651,6 @@ class DlRuntimeEffectColorSource final : public DlColorSource {
return uniform_data_;
}
sk_sp<SkShader> skia_object() const override {
if (!runtime_effect_) {
return nullptr;
}
if (!runtime_effect_->skia_runtime_effect()) {
return nullptr;
}
std::vector<sk_sp<SkShader>> sk_samplers(samplers_.size());
for (size_t i = 0; i < samplers_.size(); i++) {
auto sampler = samplers_[i];
if (sampler == nullptr) {
return nullptr;
}
sk_samplers[i] = sampler->skia_object();
}
auto ref = new std::shared_ptr<std::vector<uint8_t>>(uniform_data_);
auto uniform_data = SkData::MakeWithProc(
uniform_data_->data(), uniform_data_->size(),
[](const void* ptr, void* context) {
delete reinterpret_cast<std::shared_ptr<std::vector<uint8_t>>*>(
context);
},
ref);
return runtime_effect_->skia_runtime_effect()->makeShader(
uniform_data, sk_samplers.data(), sk_samplers.size());
}
protected:
bool equals_(DlColorSource const& other) const override {
FML_DCHECK(other.type() == DlColorSourceType::kRuntimeEffect);

View File

@ -86,19 +86,6 @@ static constexpr SkPoint kTestPoints2[2] = {
SkPoint::Make(107, 118),
};
TEST(DisplayListColorSource, BuilderSetGet) {
DlImageColorSource source(kTestImage1, DlTileMode::kClamp, DlTileMode::kClamp,
DlImageSampling::kLinear, &kTestMatrix1);
DisplayListBuilder builder;
ASSERT_EQ(builder.getColorSource(), nullptr);
builder.setColorSource(&source);
ASSERT_NE(builder.getColorSource(), nullptr);
ASSERT_TRUE(
Equals(builder.getColorSource(), static_cast<DlColorSource*>(&source)));
builder.setColorSource(nullptr);
ASSERT_EQ(builder.getColorSource(), nullptr);
}
TEST(DisplayListColorSource, ColorConstructor) {
DlColorColorSource source(SK_ColorRED);
}
@ -763,23 +750,11 @@ TEST(DisplayListColorSource, RuntimeEffect) {
ASSERT_EQ(source1->asConicalGradient(), nullptr);
ASSERT_EQ(source1->asSweepGradient(), nullptr);
ASSERT_NE(source1->skia_object(), nullptr);
ASSERT_EQ(source3->skia_object(), nullptr);
TestEquals(source1, source1);
TestEquals(source3, source3);
TestNotEquals(source1, source2, "SkRuntimeEffect differs");
TestNotEquals(source2, source3, "SkRuntimeEffect differs");
}
TEST(DisplayListColorSource, RuntimeEffectWithNullSampler) {
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
DlColorSource::MakeRuntimeEffect(
kTestRuntimeEffect1, {nullptr},
std::make_shared<std::vector<uint8_t>>());
ASSERT_EQ(source1->skia_object(), nullptr);
}
} // namespace testing
} // namespace flutter

View File

@ -114,7 +114,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRect(const SkRect& rect) {
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// No real difference for AA with filled styles
unsigned int area = rect.width() * rect.height();
@ -165,7 +165,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawOval(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// With filled styles, there is no significant AA penalty.
// m = 1/6000
// c = 0
@ -199,7 +199,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawCircle(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// We can ignore pi here
unsigned int area = radius * radius;
// m = 1/525
@ -245,7 +245,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
// These values were worked out by creating a straight line graph (y=mx+c)
// approximately matching the measured data, normalising the data so that
// 0.0005ms resulted in a score of 100 then simplifying down the formula.
if (Style() == SkPaint::Style::kFill_Style ||
if (DrawStyle() == DlDrawStyle::kFill ||
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased())) {
unsigned int area = rrect.width() * rrect.height();
// m = 1/3200
@ -295,7 +295,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
unsigned int area = outer.width() * outer.height();
if (outer.getType() == SkRRect::Type::kComplex_Type) {
// m = 1/500
@ -382,7 +382,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawArc(
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kStroke_Style) {
if (DrawStyle() == DlDrawStyle::kStroke) {
if (IsAntiAliased()) {
// m = 1/3800
// c = 12
@ -550,7 +550,7 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect(
const SkISize& size,
bool texture_backed,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
bool enforce_src_edges) {
if (IsComplex()) {
return;
}
@ -563,10 +563,8 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect(
// approximately matching the measured data, normalising the data so that
// 0.0005ms resulted in a score of 100 then simplifying down the formula.
unsigned int complexity;
if (!texture_backed ||
(texture_backed && render_with_attributes &&
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
IsAntiAliased())) {
if (!texture_backed || (texture_backed && render_with_attributes &&
enforce_src_edges && IsAntiAliased())) {
unsigned int area = size.width() * size.height();
// m = 1/4000
// c = 5
@ -610,11 +608,15 @@ void DisplayListGLComplexityCalculator::GLHelper::drawImageNine(
}
void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList(
const sk_sp<DisplayList> display_list) {
const sk_sp<DisplayList> display_list,
SkScalar opacity) {
if (IsComplex()) {
return;
}
GLHelper helper(Ceiling() - CurrentComplexityScore());
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr);
}
display_list->Dispatch(helper);
AccumulateComplexity(helper.ComplexityScore());
}

View File

@ -65,7 +65,8 @@ class DisplayListGLComplexityCalculator
const SkRect& dst,
DlFilterMode filter,
bool render_with_attributes) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
@ -79,7 +80,7 @@ class DisplayListGLComplexityCalculator
void ImageRect(const SkISize& size,
bool texture_backed,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override;
bool enforce_src_edges) override;
unsigned int BatchedComplexity() override;

View File

@ -7,8 +7,8 @@
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_complexity.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_utils.h"
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
@ -92,7 +92,7 @@ namespace flutter {
// y = 4x
class ComplexityCalculatorHelper
: public virtual Dispatcher,
: public virtual DlOpReceiver,
public virtual IgnoreClipDispatchHelper,
public virtual IgnoreTransformDispatchHelper {
public:
@ -121,7 +121,7 @@ class ComplexityCalculatorHelper
void setAntiAlias(bool aa) override { current_paint_.setAntiAlias(aa); }
void setStyle(DlDrawStyle style) override {
current_paint_.setStyle(ToSk(style));
current_paint_.setDrawStyle(style);
}
void setStrokeWidth(SkScalar width) override {
@ -145,17 +145,18 @@ class ComplexityCalculatorHelper
AccumulateComplexity(50);
}
void drawImageRect(const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override {
void drawImageRect(
const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SrcRectConstraint constraint = SrcRectConstraint::kFast) override {
if (IsComplex()) {
return;
}
ImageRect(image->dimensions(), image->isTextureBacked(),
render_with_attributes, constraint);
render_with_attributes, constraint == SrcRectConstraint::kStrict);
}
void drawAtlas(const sk_sp<DlImage> atlas,
@ -174,8 +175,7 @@ class ComplexityCalculatorHelper
// This is equivalent to calling drawImageRect lots of times
for (int i = 0; i < count; i++) {
ImageRect(SkISize::Make(tex[i].width(), tex[i].height()), true,
render_with_attributes,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);
render_with_attributes, true);
}
}
@ -211,7 +211,7 @@ class ComplexityCalculatorHelper
inline bool IsAntiAliased() { return current_paint_.isAntiAlias(); }
inline bool IsHairline() { return current_paint_.getStrokeWidth() == 0.0f; }
inline SkPaint::Style Style() { return current_paint_.getStyle(); }
inline DlDrawStyle DrawStyle() { return current_paint_.getDrawStyle(); }
inline bool IsComplex() { return is_complex_; }
inline unsigned int Ceiling() { return ceiling_; }
inline unsigned int CurrentComplexityScore() { return complexity_score_; }
@ -248,7 +248,7 @@ class ComplexityCalculatorHelper
virtual void ImageRect(const SkISize& size,
bool texture_backed,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) = 0;
bool enforce_src_edges) = 0;
// This calculates and returns the cost of draw calls which are batched and
// thus have a time cost proportional to the number of draw calls made, such
@ -256,7 +256,7 @@ class ComplexityCalculatorHelper
virtual unsigned int BatchedComplexity() = 0;
private:
SkPaint current_paint_;
DlPaint current_paint_;
// If we exceed the ceiling (defaults to the largest number representable
// by unsigned int), then set the is_complex_ bool and we no longer

View File

@ -128,7 +128,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRect(
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// No real difference for AA with filled styles.
unsigned int area = rect.width() * rect.height();
@ -170,7 +170,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawOval(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// With filled styles, there is no significant AA penalty.
// m = 1/16000
// c = 0
@ -204,7 +204,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawCircle(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
// We can ignore pi here.
unsigned int area = radius * radius;
// m = 1/1300
@ -244,7 +244,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
//
// Expensive: All filled style, symmetric w/AA.
bool expensive =
(Style() == SkPaint::Style::kFill_Style) ||
(DrawStyle() == DlDrawStyle::kFill) ||
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased());
unsigned int complexity;
@ -292,7 +292,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kFill_Style) {
if (DrawStyle() == DlDrawStyle::kFill) {
unsigned int area = outer.width() * outer.height();
if (outer.getType() == SkRRect::Type::kComplex_Type) {
// m = 1/1000
@ -374,7 +374,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawArc(
//
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (Style() == SkPaint::Style::kStroke_Style) {
if (DrawStyle() == DlDrawStyle::kStroke) {
if (IsAntiAliased()) {
// m = 1/8500
// c = 16
@ -493,7 +493,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect(
const SkISize& size,
bool texture_backed,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
bool enforce_src_edges) {
if (IsComplex()) {
return;
}
@ -512,16 +512,12 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect(
// m = 1/23000
// c = 2.3
complexity = (area + 52900) * 2 / 115;
if (render_with_attributes &&
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
IsAntiAliased()) {
if (render_with_attributes && enforce_src_edges && IsAntiAliased()) {
// There's about a 30% performance penalty from the baseline.
complexity *= 1.3f;
}
} else {
if (render_with_attributes &&
constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint &&
IsAntiAliased()) {
if (render_with_attributes && enforce_src_edges && IsAntiAliased()) {
// m = 1/12200
// c = 2.75
complexity = (area + 33550) * 2 / 61;
@ -556,11 +552,15 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawImageNine(
}
void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList(
const sk_sp<DisplayList> display_list) {
const sk_sp<DisplayList> display_list,
SkScalar opacity) {
if (IsComplex()) {
return;
}
MetalHelper helper(Ceiling() - CurrentComplexityScore());
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr);
}
display_list->Dispatch(helper);
AccumulateComplexity(helper.ComplexityScore());
}

View File

@ -65,7 +65,8 @@ class DisplayListMetalComplexityCalculator
const SkRect& dst,
DlFilterMode filter,
bool render_with_attributes) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
@ -79,7 +80,7 @@ class DisplayListMetalComplexityCalculator
void ImageRect(const SkISize& size,
bool texture_backed,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override;
bool enforce_src_edges) override;
unsigned int BatchedComplexity() override;

View File

@ -76,12 +76,13 @@ TEST(DisplayListComplexity, NestedDisplayList) {
TEST(DisplayListComplexity, AntiAliasing) {
DisplayListBuilder builder_no_aa;
builder_no_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
builder_no_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
DlPaint());
auto display_list_no_aa = builder_no_aa.Build();
DisplayListBuilder builder_aa;
builder_aa.setAntiAlias(true);
builder_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
builder_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
DlPaint().setAntiAlias(true));
auto display_list_aa = builder_aa.Build();
auto calculators = AccumulatorCalculators();
@ -93,13 +94,13 @@ TEST(DisplayListComplexity, AntiAliasing) {
TEST(DisplayListComplexity, StrokeWidth) {
DisplayListBuilder builder_stroke_0;
builder_stroke_0.setStrokeWidth(0.0f);
builder_stroke_0.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
DlPaint().setStrokeWidth(0.0f));
auto display_list_stroke_0 = builder_stroke_0.Build();
DisplayListBuilder builder_stroke_1;
builder_stroke_1.setStrokeWidth(1.0f);
builder_stroke_1.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100));
builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100),
DlPaint().setStrokeWidth(1.0f));
auto display_list_stroke_1 = builder_stroke_1.Build();
auto calculators = AccumulatorCalculators();
@ -111,13 +112,13 @@ TEST(DisplayListComplexity, StrokeWidth) {
TEST(DisplayListComplexity, Style) {
DisplayListBuilder builder_filled;
builder_filled.setStyle(DlDrawStyle::kFill);
builder_filled.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
builder_filled.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
DlPaint().setDrawStyle(DlDrawStyle::kFill));
auto display_list_filled = builder_filled.Build();
DisplayListBuilder builder_stroked;
builder_stroked.setStyle(DlDrawStyle::kStroke);
builder_stroked.drawRect(SkRect::MakeXYWH(10, 10, 80, 80));
builder_stroked.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80),
DlPaint().setDrawStyle(DlDrawStyle::kStroke));
auto display_list_stroked = builder_stroked.Build();
auto calculators = AccumulatorCalculators();
@ -129,7 +130,7 @@ TEST(DisplayListComplexity, Style) {
TEST(DisplayListComplexity, SaveLayers) {
DisplayListBuilder builder;
builder.saveLayer(nullptr, true);
builder.SaveLayer(nullptr, nullptr);
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -144,7 +145,7 @@ TEST(DisplayListComplexity, DrawPath) {
line_path.moveTo(SkPoint::Make(0, 0));
line_path.lineTo(SkPoint::Make(10, 10));
line_path.close();
builder_line.drawPath(line_path);
builder_line.DrawPath(line_path, DlPaint());
auto display_list_line = builder_line.Build();
DisplayListBuilder builder_quad;
@ -152,7 +153,7 @@ TEST(DisplayListComplexity, DrawPath) {
quad_path.moveTo(SkPoint::Make(0, 0));
quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
quad_path.close();
builder_quad.drawPath(quad_path);
builder_quad.DrawPath(quad_path, DlPaint());
auto display_list_quad = builder_quad.Build();
DisplayListBuilder builder_conic;
@ -160,7 +161,7 @@ TEST(DisplayListComplexity, DrawPath) {
conic_path.moveTo(SkPoint::Make(0, 0));
conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
conic_path.close();
builder_conic.drawPath(conic_path);
builder_conic.DrawPath(conic_path, DlPaint());
auto display_list_conic = builder_conic.Build();
DisplayListBuilder builder_cubic;
@ -168,7 +169,7 @@ TEST(DisplayListComplexity, DrawPath) {
cubic_path.moveTo(SkPoint::Make(0, 0));
cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
SkPoint::Make(20, 20));
builder_cubic.drawPath(cubic_path);
builder_cubic.DrawPath(cubic_path, DlPaint());
auto display_list_cubic = builder_cubic.Build();
auto calculators = AccumulatorCalculators();
@ -186,7 +187,7 @@ TEST(DisplayListComplexity, DrawShadow) {
line_path.moveTo(SkPoint::Make(0, 0));
line_path.lineTo(SkPoint::Make(10, 10));
line_path.close();
builder_line.drawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f);
builder_line.DrawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f);
auto display_list_line = builder_line.Build();
DisplayListBuilder builder_quad;
@ -194,7 +195,7 @@ TEST(DisplayListComplexity, DrawShadow) {
quad_path.moveTo(SkPoint::Make(0, 0));
quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20));
quad_path.close();
builder_quad.drawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f);
builder_quad.DrawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f);
auto display_list_quad = builder_quad.Build();
DisplayListBuilder builder_conic;
@ -202,7 +203,7 @@ TEST(DisplayListComplexity, DrawShadow) {
conic_path.moveTo(SkPoint::Make(0, 0));
conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f);
conic_path.close();
builder_conic.drawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f);
builder_conic.DrawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f);
auto display_list_conic = builder_conic.Build();
DisplayListBuilder builder_cubic;
@ -210,7 +211,7 @@ TEST(DisplayListComplexity, DrawShadow) {
cubic_path.moveTo(SkPoint::Make(0, 0));
cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20),
SkPoint::Make(20, 20));
builder_cubic.drawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f);
builder_cubic.DrawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f);
auto display_list_cubic = builder_cubic.Build();
auto calculators = AccumulatorCalculators();
@ -224,7 +225,7 @@ TEST(DisplayListComplexity, DrawShadow) {
TEST(DisplayListComplexity, DrawOval) {
DisplayListBuilder builder;
builder.drawOval(SkRect::MakeXYWH(10, 10, 100, 80));
builder.DrawOval(SkRect::MakeXYWH(10, 10, 100, 80), DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -235,7 +236,7 @@ TEST(DisplayListComplexity, DrawOval) {
TEST(DisplayListComplexity, DrawCircle) {
DisplayListBuilder builder;
builder.drawCircle(SkPoint::Make(50, 50), 10.0f);
builder.DrawCircle(SkPoint::Make(50, 50), 10.0f, DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -246,8 +247,9 @@ TEST(DisplayListComplexity, DrawCircle) {
TEST(DisplayListComplexity, DrawRRect) {
DisplayListBuilder builder;
builder.drawRRect(
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f));
builder.DrawRRect(
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f),
DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -262,7 +264,7 @@ TEST(DisplayListComplexity, DrawDRRect) {
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f);
SkRRect inner =
SkRRect::MakeRectXY(SkRect::MakeXYWH(15, 15, 70, 70), 1.5f, 1.5f);
builder.drawDRRect(outer, inner);
builder.DrawDRRect(outer, inner, DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -273,7 +275,8 @@ TEST(DisplayListComplexity, DrawDRRect) {
TEST(DisplayListComplexity, DrawArc) {
DisplayListBuilder builder;
builder.drawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true);
builder.DrawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true,
DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -287,7 +290,7 @@ TEST(DisplayListComplexity, DrawVertices) {
auto vertices = DlVertices::Make(DlVertexMode::kTriangles, points.size(),
points.data(), nullptr, nullptr);
DisplayListBuilder builder;
builder.drawVertices(vertices, DlBlendMode::kSrc);
builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, DlPaint());
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -301,12 +304,12 @@ TEST(DisplayListComplexity, DrawTextBlob) {
"The quick brown fox jumps over the lazy dog.", SkFont());
DisplayListBuilder builder;
builder.drawTextBlob(text_blob, 0.0f, 0.0f);
builder.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
auto display_list = builder.Build();
DisplayListBuilder builder_multiple;
builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f);
builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint());
auto display_list_multiple = builder_multiple.Build();
auto calculators = AccumulatorCalculators();
@ -320,18 +323,18 @@ TEST(DisplayListComplexity, DrawTextBlob) {
TEST(DisplayListComplexity, DrawPoints) {
auto points = GetTestPoints();
DisplayListBuilder builder_lines;
builder_lines.drawPoints(DlCanvas::PointMode::kLines, points.size(),
points.data());
builder_lines.DrawPoints(DlCanvas::PointMode::kLines, points.size(),
points.data(), DlPaint());
auto display_list_lines = builder_lines.Build();
DisplayListBuilder builder_points;
builder_points.drawPoints(DlCanvas::PointMode::kPoints, points.size(),
points.data());
builder_points.DrawPoints(DlCanvas::PointMode::kPoints, points.size(),
points.data(), DlPaint());
auto display_list_points = builder_points.Build();
DisplayListBuilder builder_polygon;
builder_polygon.drawPoints(DlCanvas::PointMode::kPolygon, points.size(),
points.data());
builder_polygon.DrawPoints(DlCanvas::PointMode::kPolygon, points.size(),
points.data(), DlPaint());
auto display_list_polygon = builder_polygon.Build();
auto calculators = AccumulatorCalculators();
@ -351,8 +354,8 @@ TEST(DisplayListComplexity, DrawImage) {
auto image = SkImage::MakeFromBitmap(bitmap);
DisplayListBuilder builder;
builder.drawImage(DlImage::Make(image), SkPoint::Make(0, 0),
DlImageSampling::kNearestNeighbor, false);
builder.DrawImage(DlImage::Make(image), SkPoint::Make(0, 0),
DlImageSampling::kNearestNeighbor, nullptr);
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -373,8 +376,8 @@ TEST(DisplayListComplexity, DrawImageNine) {
SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
DisplayListBuilder builder;
builder.drawImageNine(DlImage::Make(image), center, dest,
DlFilterMode::kNearest, true);
builder.DrawImageNine(DlImage::Make(image), center, dest,
DlFilterMode::kNearest, nullptr);
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -395,8 +398,8 @@ TEST(DisplayListComplexity, DrawImageRect) {
SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50);
DisplayListBuilder builder;
builder.drawImageRect(DlImage::Make(image), src, dest,
DlImageSampling::kNearestNeighbor, true);
builder.DrawImageRect(DlImage::Make(image), src, dest,
DlImageSampling::kNearestNeighbor, nullptr);
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();
@ -421,9 +424,9 @@ TEST(DisplayListComplexity, DrawAtlas) {
}
DisplayListBuilder builder;
builder.drawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
builder.DrawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr,
10, DlBlendMode::kSrc, DlImageSampling::kNearestNeighbor,
nullptr, true);
nullptr, nullptr);
auto display_list = builder.Build();
auto calculators = AccumulatorCalculators();

View File

@ -1,172 +0,0 @@
// 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.
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_paint.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_tile_mode.h"
#include "flutter/display_list/display_list_vertices.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
#include "include/core/SkSamplingOptions.h"
namespace flutter {
namespace testing {
TEST(DisplayListEnum, ToDlTileMode) {
ASSERT_EQ(ToDl(SkTileMode::kClamp), DlTileMode::kClamp);
ASSERT_EQ(ToDl(SkTileMode::kRepeat), DlTileMode::kRepeat);
ASSERT_EQ(ToDl(SkTileMode::kMirror), DlTileMode::kMirror);
ASSERT_EQ(ToDl(SkTileMode::kDecal), DlTileMode::kDecal);
}
TEST(DisplayListEnum, ToSkTileMode) {
ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp);
ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat);
ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror);
ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal);
}
TEST(DisplayListEnum, ToDlDrawStyle) {
ASSERT_EQ(ToDl(SkPaint::Style::kFill_Style), DlDrawStyle::kFill);
ASSERT_EQ(ToDl(SkPaint::Style::kStroke_Style), DlDrawStyle::kStroke);
ASSERT_EQ(ToDl(SkPaint::Style::kStrokeAndFill_Style),
DlDrawStyle::kStrokeAndFill);
}
TEST(DisplayListEnum, ToSkDrawStyle) {
ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style);
ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style);
ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill),
SkPaint::Style::kStrokeAndFill_Style);
}
TEST(DisplayListEnum, ToDlStrokeCap) {
ASSERT_EQ(ToDl(SkPaint::Cap::kButt_Cap), DlStrokeCap::kButt);
ASSERT_EQ(ToDl(SkPaint::Cap::kRound_Cap), DlStrokeCap::kRound);
ASSERT_EQ(ToDl(SkPaint::Cap::kSquare_Cap), DlStrokeCap::kSquare);
}
TEST(DisplayListEnum, ToSkStrokeCap) {
ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap);
ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap);
ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap);
}
TEST(DisplayListEnum, ToDlStrokeJoin) {
ASSERT_EQ(ToDl(SkPaint::Join::kMiter_Join), DlStrokeJoin::kMiter);
ASSERT_EQ(ToDl(SkPaint::Join::kRound_Join), DlStrokeJoin::kRound);
ASSERT_EQ(ToDl(SkPaint::Join::kBevel_Join), DlStrokeJoin::kBevel);
}
TEST(DisplayListEnum, ToSkStrokeJoin) {
ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join);
ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join);
ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join);
}
TEST(DisplayListEnum, ToDlVertexMode) {
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangles_VertexMode),
DlVertexMode::kTriangles);
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleStrip_VertexMode),
DlVertexMode::kTriangleStrip);
ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleFan_VertexMode),
DlVertexMode::kTriangleFan);
}
TEST(DisplayListEnum, ToSkVertexMode) {
ASSERT_EQ(ToSk(DlVertexMode::kTriangles),
SkVertices::VertexMode::kTriangles_VertexMode);
ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip),
SkVertices::VertexMode::kTriangleStrip_VertexMode);
ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan),
SkVertices::VertexMode::kTriangleFan_VertexMode);
}
TEST(DisplayListEnum, ToDlFilterMode) {
ASSERT_EQ(ToDl(SkFilterMode::kLinear), DlFilterMode::kLinear);
ASSERT_EQ(ToDl(SkFilterMode::kNearest), DlFilterMode::kNearest);
ASSERT_EQ(ToDl(SkFilterMode::kLast), DlFilterMode::kLast);
}
TEST(DisplayListEnum, ToSkFilterMode) {
ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear);
ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest);
ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast);
}
TEST(DisplayListEnum, ToDlImageSampling) {
ASSERT_EQ(ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)),
DlImageSampling::kLinear);
ASSERT_EQ(
ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)),
DlImageSampling::kMipmapLinear);
ASSERT_EQ(
ToDl(SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)),
DlImageSampling::kNearestNeighbor);
ASSERT_EQ(ToDl(SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f})),
DlImageSampling::kCubic);
}
TEST(DisplayListEnum, ToSkSamplingOptions) {
ASSERT_EQ(ToSk(DlImageSampling::kLinear),
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear),
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor),
SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone));
ASSERT_EQ(ToSk(DlImageSampling::kCubic),
SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}));
}
#define CHECK_TO_DLENUM(V) ASSERT_EQ(ToDl(SkBlendMode::V), DlBlendMode::V);
#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V);
#define FOR_EACH_ENUM(FUNC) \
FUNC(kSrc) \
FUNC(kClear) \
FUNC(kSrc) \
FUNC(kDst) \
FUNC(kSrcOver) \
FUNC(kDstOver) \
FUNC(kSrcIn) \
FUNC(kDstIn) \
FUNC(kSrcOut) \
FUNC(kDstOut) \
FUNC(kSrcATop) \
FUNC(kDstATop) \
FUNC(kXor) \
FUNC(kPlus) \
FUNC(kModulate) \
FUNC(kScreen) \
FUNC(kOverlay) \
FUNC(kDarken) \
FUNC(kLighten) \
FUNC(kColorDodge) \
FUNC(kColorBurn) \
FUNC(kHardLight) \
FUNC(kSoftLight) \
FUNC(kDifference) \
FUNC(kExclusion) \
FUNC(kMultiply) \
FUNC(kHue) \
FUNC(kSaturation) \
FUNC(kColor) \
FUNC(kLuminosity) \
FUNC(kLastCoeffMode) \
FUNC(kLastSeparableMode) \
FUNC(kLastMode)
TEST(DisplayListEnum, ToDlBlendMode){FOR_EACH_ENUM(CHECK_TO_DLENUM)}
TEST(DisplayListEnum, ToSkBlendMode) {
FOR_EACH_ENUM(CHECK_TO_SKENUM)
}
#undef CHECK_TO_DLENUM
#undef CHECK_TO_SKENUM
#undef FOR_EACH_ENUM
} // namespace testing
} // namespace flutter

View File

@ -29,9 +29,9 @@ enum class DlImageFilterType {
kDilate,
kErode,
kMatrix,
kComposeFilter,
kCompose,
kColorFilter,
kLocalMatrixFilter,
kLocalMatrix,
};
class DlBlurImageFilter;
@ -42,8 +42,7 @@ class DlLocalMatrixImageFilter;
class DlComposeImageFilter;
class DlColorFilterImageFilter;
class DlImageFilter
: public DlAttribute<DlImageFilter, SkImageFilter, DlImageFilterType> {
class DlImageFilter : public DlAttribute<DlImageFilter, DlImageFilterType> {
public:
enum class MatrixCapability {
kTranslate,
@ -227,6 +226,16 @@ class DlBlurImageFilter final : public DlImageFilter {
explicit DlBlurImageFilter(const DlBlurImageFilter& filter)
: DlBlurImageFilter(&filter) {}
static std::shared_ptr<DlImageFilter> Make(SkScalar sigma_x,
SkScalar sigma_y,
DlTileMode tile_mode) {
if (SkScalarIsFinite(sigma_x) && sigma_x > SK_ScalarNearlyZero &&
SkScalarIsFinite(sigma_y) && sigma_y > SK_ScalarNearlyZero) {
return std::make_shared<DlBlurImageFilter>(sigma_x, sigma_y, tile_mode);
}
return nullptr;
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlBlurImageFilter>(this);
}
@ -262,10 +271,6 @@ class DlBlurImageFilter final : public DlImageFilter {
SkScalar sigma_y() const { return sigma_y_; }
DlTileMode tile_mode() const { return tile_mode_; }
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::Blur(sigma_x_, sigma_y_, ToSk(tile_mode_), nullptr);
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kBlur);
@ -289,6 +294,15 @@ class DlDilateImageFilter final : public DlImageFilter {
explicit DlDilateImageFilter(const DlDilateImageFilter& filter)
: DlDilateImageFilter(&filter) {}
static std::shared_ptr<DlImageFilter> Make(SkScalar radius_x,
SkScalar radius_y) {
if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero &&
SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) {
return std::make_shared<DlDilateImageFilter>(radius_x, radius_y);
}
return nullptr;
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlDilateImageFilter>(this);
}
@ -323,10 +337,6 @@ class DlDilateImageFilter final : public DlImageFilter {
SkScalar radius_x() const { return radius_x_; }
SkScalar radius_y() const { return radius_y_; }
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::Dilate(radius_x_, radius_y_, nullptr);
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kDilate);
@ -348,6 +358,15 @@ class DlErodeImageFilter final : public DlImageFilter {
explicit DlErodeImageFilter(const DlErodeImageFilter& filter)
: DlErodeImageFilter(&filter) {}
static std::shared_ptr<DlImageFilter> Make(SkScalar radius_x,
SkScalar radius_y) {
if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero &&
SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) {
return std::make_shared<DlErodeImageFilter>(radius_x, radius_y);
}
return nullptr;
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlErodeImageFilter>(this);
}
@ -382,10 +401,6 @@ class DlErodeImageFilter final : public DlImageFilter {
SkScalar radius_x() const { return radius_x_; }
SkScalar radius_y() const { return radius_y_; }
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::Erode(radius_x_, radius_y_, nullptr);
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kErode);
@ -407,6 +422,14 @@ class DlMatrixImageFilter final : public DlImageFilter {
explicit DlMatrixImageFilter(const DlMatrixImageFilter& filter)
: DlMatrixImageFilter(&filter) {}
static std::shared_ptr<DlImageFilter> Make(const SkMatrix& matrix,
DlImageSampling sampling) {
if (matrix.isFinite() && !matrix.isIdentity()) {
return std::make_shared<DlMatrixImageFilter>(matrix, sampling);
}
return nullptr;
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlMatrixImageFilter>(this);
}
@ -460,10 +483,6 @@ class DlMatrixImageFilter final : public DlImageFilter {
return &input_bounds;
}
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::MatrixTransform(matrix_, ToSk(sampling_), nullptr);
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kMatrix);
@ -478,8 +497,8 @@ class DlMatrixImageFilter final : public DlImageFilter {
class DlComposeImageFilter final : public DlImageFilter {
public:
DlComposeImageFilter(std::shared_ptr<DlImageFilter> outer,
std::shared_ptr<DlImageFilter> inner)
DlComposeImageFilter(std::shared_ptr<const DlImageFilter> outer,
std::shared_ptr<const DlImageFilter> inner)
: outer_(std::move(outer)), inner_(std::move(inner)) {}
DlComposeImageFilter(const DlImageFilter* outer, const DlImageFilter* inner)
: outer_(outer->shared()), inner_(inner->shared()) {}
@ -490,17 +509,29 @@ class DlComposeImageFilter final : public DlImageFilter {
explicit DlComposeImageFilter(const DlComposeImageFilter& filter)
: DlComposeImageFilter(&filter) {}
static std::shared_ptr<const DlImageFilter> Make(
std::shared_ptr<const DlImageFilter> outer,
std::shared_ptr<const DlImageFilter> inner) {
if (!outer) {
return inner;
}
if (!inner) {
return outer;
}
return std::make_shared<DlComposeImageFilter>(outer, inner);
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlComposeImageFilter>(this);
}
DlImageFilterType type() const override {
return DlImageFilterType::kComposeFilter;
return DlImageFilterType::kCompose;
}
size_t size() const override { return sizeof(*this); }
std::shared_ptr<DlImageFilter> outer() const { return outer_; }
std::shared_ptr<DlImageFilter> inner() const { return inner_; }
std::shared_ptr<const DlImageFilter> outer() const { return outer_; }
std::shared_ptr<const DlImageFilter> inner() const { return inner_; }
const DlComposeImageFilter* asCompose() const override { return this; }
@ -525,30 +556,25 @@ class DlComposeImageFilter final : public DlImageFilter {
const SkMatrix& ctm,
SkIRect& input_bounds) const override;
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::Compose(outer_->skia_object(),
inner_->skia_object());
}
MatrixCapability matrix_capability() const override {
return std::min(outer_->matrix_capability(), inner_->matrix_capability());
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kComposeFilter);
FML_DCHECK(other.type() == DlImageFilterType::kCompose);
auto that = static_cast<const DlComposeImageFilter*>(&other);
return (Equals(outer_, that->outer_) && Equals(inner_, that->inner_));
}
private:
std::shared_ptr<DlImageFilter> outer_;
std::shared_ptr<DlImageFilter> inner_;
std::shared_ptr<const DlImageFilter> outer_;
std::shared_ptr<const DlImageFilter> inner_;
};
class DlColorFilterImageFilter final : public DlImageFilter {
public:
explicit DlColorFilterImageFilter(std::shared_ptr<DlColorFilter> filter)
explicit DlColorFilterImageFilter(std::shared_ptr<const DlColorFilter> filter)
: color_filter_(std::move(filter)) {}
explicit DlColorFilterImageFilter(const DlColorFilter* filter)
: color_filter_(filter->shared()) {}
@ -559,6 +585,14 @@ class DlColorFilterImageFilter final : public DlImageFilter {
explicit DlColorFilterImageFilter(const DlColorFilterImageFilter& filter)
: DlColorFilterImageFilter(&filter) {}
static std::shared_ptr<DlImageFilter> Make(
std::shared_ptr<const DlColorFilter> filter) {
if (filter) {
return std::make_shared<DlColorFilterImageFilter>(filter);
}
return nullptr;
}
std::shared_ptr<DlImageFilter> shared() const override {
return std::make_shared<DlColorFilterImageFilter>(color_filter_);
}
@ -568,7 +602,7 @@ class DlColorFilterImageFilter final : public DlImageFilter {
}
size_t size() const override { return sizeof(*this); }
const std::shared_ptr<DlColorFilter> color_filter() const {
const std::shared_ptr<const DlColorFilter> color_filter() const {
return color_filter_;
}
@ -602,10 +636,6 @@ class DlColorFilterImageFilter final : public DlImageFilter {
return map_device_bounds(output_bounds, ctm, input_bounds);
}
sk_sp<SkImageFilter> skia_object() const override {
return SkImageFilters::ColorFilter(color_filter_->skia_object(), nullptr);
}
MatrixCapability matrix_capability() const override {
return MatrixCapability::kComplex;
}
@ -623,7 +653,7 @@ class DlColorFilterImageFilter final : public DlImageFilter {
}
private:
std::shared_ptr<DlColorFilter> color_filter_;
std::shared_ptr<const DlColorFilter> color_filter_;
};
class DlLocalMatrixImageFilter final : public DlImageFilter {
@ -640,7 +670,7 @@ class DlLocalMatrixImageFilter final : public DlImageFilter {
}
DlImageFilterType type() const override {
return DlImageFilterType::kLocalMatrixFilter;
return DlImageFilterType::kLocalMatrix;
}
size_t size() const override { return sizeof(*this); }
@ -689,20 +719,9 @@ class DlLocalMatrixImageFilter final : public DlImageFilter {
output_bounds, SkMatrix::Concat(ctm, matrix_), input_bounds);
}
sk_sp<SkImageFilter> skia_object() const override {
if (!image_filter_) {
return nullptr;
}
sk_sp<SkImageFilter> skia_object = image_filter_->skia_object();
if (!skia_object) {
return nullptr;
}
return skia_object->makeWithLocalMatrix(matrix_);
}
protected:
bool equals_(const DlImageFilter& other) const override {
FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrixFilter);
FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrix);
auto that = static_cast<const DlLocalMatrixImageFilter*>(&other);
return (matrix_ == that->matrix_ &&
Equals(image_filter_, that->image_filter_));

View File

@ -17,21 +17,6 @@
namespace flutter {
namespace testing {
TEST(DisplayListImageFilter, BuilderSetGet) {
DlBlurImageFilter filter(5.0, 5.0, DlTileMode::kDecal);
DisplayListBuilder builder;
ASSERT_EQ(builder.getImageFilter(), nullptr);
builder.setImageFilter(&filter);
ASSERT_NE(builder.getImageFilter(), nullptr);
ASSERT_TRUE(
Equals(builder.getImageFilter(), static_cast<DlImageFilter*>(&filter)));
builder.setImageFilter(nullptr);
ASSERT_EQ(builder.getImageFilter(), nullptr);
}
// SkRect::contains treats the rect as a half-open interval which is
// appropriate for so many operations. Unfortunately, we are using
// it here to test containment of the corners of a transformed quad
@ -708,8 +693,8 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) {
SkImageFilters::ColorFilter(
SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcOver), nullptr),
SkImageFilters::Dilate(5.0, 10.0, nullptr),
SkImageFilters::MatrixTransform(filter_matrix,
ToSk(DlImageSampling::kLinear), nullptr),
SkImageFilters::MatrixTransform(
filter_matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr),
SkImageFilters::Compose(
SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr),
SkImageFilters::ColorFilter(
@ -785,15 +770,5 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) {
}
}
TEST(DisplayListImageFilter, LocalImageSkiaNull) {
auto blur_filter =
std::make_shared<DlBlurImageFilter>(0, 0, DlTileMode::kClamp);
DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45),
blur_filter);
// With sigmas set to zero on the blur filter, Skia will return a null filter.
// The local matrix filter should return nullptr instead of crashing.
ASSERT_EQ(dl_local_matrix_filter.skia_object(), nullptr);
}
} // namespace testing
} // namespace flutter

View File

@ -20,8 +20,7 @@ class DlBlurMaskFilter;
// An enumerated type for the supported MaskFilter operations.
enum class DlMaskFilterType { kBlur };
class DlMaskFilter
: public DlAttribute<DlMaskFilter, SkMaskFilter, DlMaskFilterType> {
class DlMaskFilter : public DlAttribute<DlMaskFilter, DlMaskFilterType> {
public:
// Return a DlBlurMaskFilter pointer to this object iff it is a Blur
// type of MaskFilter, otherwise return nullptr.
@ -43,6 +42,15 @@ class DlBlurMaskFilter final : public DlMaskFilter {
: DlBlurMaskFilter(filter->style_, filter->sigma_, filter->respect_ctm_) {
}
static std::shared_ptr<DlMaskFilter> Make(SkBlurStyle style,
SkScalar sigma,
bool respect_ctm = true) {
if (SkScalarIsFinite(sigma) && sigma > 0) {
return std::make_shared<DlBlurMaskFilter>(style, sigma, respect_ctm);
}
return nullptr;
}
DlMaskFilterType type() const override { return DlMaskFilterType::kBlur; }
size_t size() const override { return sizeof(*this); }
@ -50,10 +58,6 @@ class DlBlurMaskFilter final : public DlMaskFilter {
return std::make_shared<DlBlurMaskFilter>(this);
}
sk_sp<SkMaskFilter> skia_object() const override {
return SkMaskFilter::MakeBlur(style_, sigma_, respect_ctm_);
}
const DlBlurMaskFilter* asBlur() const override { return this; }
SkBlurStyle style() const { return style_; }

View File

@ -12,18 +12,6 @@
namespace flutter {
namespace testing {
TEST(DisplayListMaskFilter, BuilderSetGet) {
DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
DisplayListBuilder builder;
ASSERT_EQ(builder.getMaskFilter(), nullptr);
builder.setMaskFilter(&filter);
ASSERT_NE(builder.getMaskFilter(), nullptr);
ASSERT_TRUE(
Equals(builder.getMaskFilter(), static_cast<DlMaskFilter*>(&filter)));
builder.setMaskFilter(nullptr);
ASSERT_EQ(builder.getMaskFilter(), nullptr);
}
TEST(DisplayListMaskFilter, BlurConstructor) {
DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0);
}

View File

@ -8,8 +8,8 @@
#include "display_list_color_source.h"
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/display_list/types.h"
#include "flutter/fml/macros.h"
@ -37,7 +37,7 @@ namespace flutter {
// cheap to deal with a complicated "lifetime" tracking to
// determine if they will be used.
struct DispatchContext {
Dispatcher& dispatcher;
DlOpReceiver& receiver;
int cur_index;
int next_render_index;
@ -111,7 +111,7 @@ struct DLOp {
const bool value; \
\
void dispatch(DispatchContext& ctx) const { \
ctx.dispatcher.set##name(value); \
ctx.receiver.set##name(value); \
} \
};
DEFINE_SET_BOOL_OP(AntiAlias)
@ -129,7 +129,7 @@ DEFINE_SET_BOOL_OP(InvertColors)
const DlStroke##name value; \
\
void dispatch(DispatchContext& ctx) const { \
ctx.dispatcher.setStroke##name(value); \
ctx.receiver.setStroke##name(value); \
} \
};
DEFINE_SET_ENUM_OP(Cap)
@ -144,7 +144,7 @@ struct SetStyleOp final : DLOp {
const DlDrawStyle style;
void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setStyle(style); }
void dispatch(DispatchContext& ctx) const { ctx.receiver.setStyle(style); }
};
// 4 byte header + 4 byte payload packs into minimum 8 bytes
struct SetStrokeWidthOp final : DLOp {
@ -155,7 +155,7 @@ struct SetStrokeWidthOp final : DLOp {
const float width;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setStrokeWidth(width);
ctx.receiver.setStrokeWidth(width);
}
};
// 4 byte header + 4 byte payload packs into minimum 8 bytes
@ -167,7 +167,7 @@ struct SetStrokeMiterOp final : DLOp {
const float limit;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setStrokeMiter(limit);
ctx.receiver.setStrokeMiter(limit);
}
};
@ -179,7 +179,7 @@ struct SetColorOp final : DLOp {
const DlColor color;
void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setColor(color); }
void dispatch(DispatchContext& ctx) const { ctx.receiver.setColor(color); }
};
// 4 byte header + 4 byte payload packs into minimum 8 bytes
struct SetBlendModeOp final : DLOp {
@ -189,8 +189,8 @@ struct SetBlendModeOp final : DLOp {
const DlBlendMode mode;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setBlendMode(mode);
void dispatch(DispatchContext& ctx) const { //
ctx.receiver.setBlendMode(mode);
}
};
@ -207,7 +207,7 @@ struct SetBlendModeOp final : DLOp {
Clear##name##Op() {} \
\
void dispatch(DispatchContext& ctx) const { \
ctx.dispatcher.set##name(nullptr); \
ctx.receiver.set##name(nullptr); \
} \
}; \
struct SetPod##name##Op final : DLOp { \
@ -217,7 +217,7 @@ struct SetBlendModeOp final : DLOp {
\
void dispatch(DispatchContext& ctx) const { \
const Dl##name* filter = reinterpret_cast<const Dl##name*>(this + 1); \
ctx.dispatcher.set##name(filter); \
ctx.receiver.set##name(filter); \
} \
};
DEFINE_SET_CLEAR_DLATTR_OP(ColorFilter, ColorFilter, filter)
@ -242,7 +242,7 @@ struct SetImageColorSourceOp : DLOp {
const DlImageColorSource source;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setColorSource(&source);
ctx.receiver.setColorSource(&source);
}
};
@ -259,7 +259,7 @@ struct SetRuntimeEffectColorSourceOp : DLOp {
const DlRuntimeEffectColorSource source;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setColorSource(&source);
ctx.receiver.setColorSource(&source);
}
DisplayListCompare equals(const SetRuntimeEffectColorSourceOp* other) const {
@ -278,7 +278,7 @@ struct SetSceneColorSourceOp : DLOp {
const DlSceneColorSource source;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setColorSource(&source);
ctx.receiver.setColorSource(&source);
}
DisplayListCompare equals(const SetSceneColorSourceOp* other) const {
@ -298,7 +298,7 @@ struct SetSharedImageFilterOp : DLOp {
const std::shared_ptr<DlImageFilter> filter;
void dispatch(DispatchContext& ctx) const {
ctx.dispatcher.setImageFilter(filter.get());
ctx.receiver.setImageFilter(filter.get());
}
DisplayListCompare equals(const SetSharedImageFilterOp* other) const {
@ -336,7 +336,7 @@ struct SaveOp final : SaveOpBase {
void dispatch(DispatchContext& ctx) const {
if (save_needed(ctx)) {
ctx.dispatcher.save();
ctx.receiver.save();
}
}
};
@ -348,7 +348,7 @@ struct SaveLayerOp final : SaveOpBase {
void dispatch(DispatchContext& ctx) const {
if (save_needed(ctx)) {
ctx.dispatcher.saveLayer(nullptr, options);
ctx.receiver.saveLayer(nullptr, options);
}
}
};
@ -363,7 +363,7 @@ struct SaveLayerBoundsOp final : SaveOpBase {
void dispatch(DispatchContext& ctx) const {
if (save_needed(ctx)) {
ctx.dispatcher.saveLayer(&rect, options);
ctx.receiver.saveLayer(&rect, options);
}
}
};
@ -379,7 +379,7 @@ struct SaveLayerBackdropOp final : SaveOpBase {
void dispatch(DispatchContext& ctx) const {
if (save_needed(ctx)) {
ctx.dispatcher.saveLayer(nullptr, options, backdrop.get());
ctx.receiver.saveLayer(nullptr, options, backdrop.get());
}
}
@ -403,7 +403,7 @@ struct SaveLayerBackdropBoundsOp final : SaveOpBase {
void dispatch(DispatchContext& ctx) const {
if (save_needed(ctx)) {
ctx.dispatcher.saveLayer(&rect, options, backdrop.get());
ctx.receiver.saveLayer(&rect, options, backdrop.get());
}
}
@ -423,7 +423,7 @@ struct RestoreOp final : DLOp {
void dispatch(DispatchContext& ctx) const {
DispatchContext::SaveInfo& info = ctx.save_infos.back();
if (info.save_was_needed) {
ctx.dispatcher.restore();
ctx.receiver.restore();
}
ctx.next_restore_index = info.previous_restore_index;
ctx.save_infos.pop_back();
@ -447,7 +447,7 @@ struct TranslateOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.translate(tx, ty);
ctx.receiver.translate(tx, ty);
}
}
};
@ -463,7 +463,7 @@ struct ScaleOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.scale(sx, sy);
ctx.receiver.scale(sx, sy);
}
}
};
@ -477,7 +477,7 @@ struct RotateOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.rotate(degrees);
ctx.receiver.rotate(degrees);
}
}
};
@ -493,7 +493,7 @@ struct SkewOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.skew(sx, sy);
ctx.receiver.skew(sx, sy);
}
}
};
@ -513,8 +513,8 @@ struct Transform2DAffineOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.transform2DAffine(mxx, mxy, mxt, //
myx, myy, myt);
ctx.receiver.transform2DAffine(mxx, mxy, mxt, //
myx, myy, myt);
}
}
};
@ -542,10 +542,10 @@ struct TransformFullPerspectiveOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.transformFullPerspective(mxx, mxy, mxz, mxt, //
myx, myy, myz, myt, //
mzx, mzy, mzz, mzt, //
mwx, mwy, mwz, mwt);
ctx.receiver.transformFullPerspective(mxx, mxy, mxz, mxt, //
myx, myy, myz, myt, //
mzx, mzy, mzz, mzt, //
mwx, mwy, mwz, mwt);
}
}
};
@ -558,7 +558,7 @@ struct TransformResetOp final : TransformClipOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.transformReset();
ctx.receiver.transformReset();
}
}
};
@ -585,8 +585,8 @@ struct TransformResetOp final : TransformClipOpBase {
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \
is_aa); \
ctx.receiver.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \
is_aa); \
} \
} \
};
@ -596,27 +596,27 @@ DEFINE_CLIP_SHAPE_OP(Rect, Difference)
DEFINE_CLIP_SHAPE_OP(RRect, Difference)
#undef DEFINE_CLIP_SHAPE_OP
#define DEFINE_CLIP_PATH_OP(clipop) \
struct Clip##clipop##PathOp final : TransformClipOpBase { \
static const auto kType = DisplayListOpType::kClip##clipop##Path; \
\
Clip##clipop##PathOp(SkPath path, bool is_aa) \
: is_aa(is_aa), path(path) {} \
\
const bool is_aa; \
const SkPath path; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \
} \
} \
\
DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
return is_aa == other->is_aa && path == other->path \
? DisplayListCompare::kEqual \
: DisplayListCompare::kNotEqual; \
} \
#define DEFINE_CLIP_PATH_OP(clipop) \
struct Clip##clipop##PathOp final : TransformClipOpBase { \
static const auto kType = DisplayListOpType::kClip##clipop##Path; \
\
Clip##clipop##PathOp(SkPath path, bool is_aa) \
: is_aa(is_aa), path(path) {} \
\
const bool is_aa; \
const SkPath path; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.receiver.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \
} \
} \
\
DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
return is_aa == other->is_aa && path == other->path \
? DisplayListCompare::kEqual \
: DisplayListCompare::kNotEqual; \
} \
};
DEFINE_CLIP_PATH_OP(Intersect)
DEFINE_CLIP_PATH_OP(Difference)
@ -636,7 +636,7 @@ struct DrawPaintOp final : DrawOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawPaint();
ctx.receiver.drawPaint();
}
}
};
@ -652,7 +652,7 @@ struct DrawColorOp final : DrawOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawColor(color, mode);
ctx.receiver.drawColor(color, mode);
}
}
};
@ -672,7 +672,7 @@ struct DrawColorOp final : DrawOpBase {
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.draw##op_name(arg_name); \
ctx.receiver.draw##op_name(arg_name); \
} \
} \
};
@ -692,7 +692,7 @@ struct DrawPathOp final : DrawOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawPath(path);
ctx.receiver.drawPath(path);
}
}
@ -720,7 +720,7 @@ struct DrawPathOp final : DrawOpBase {
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.draw##op_name(name1, name2); \
ctx.receiver.draw##op_name(name1, name2); \
} \
} \
};
@ -743,7 +743,7 @@ struct DrawArcOp final : DrawOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawArc(bounds, start, sweep, center);
ctx.receiver.drawArc(bounds, start, sweep, center);
}
}
};
@ -754,20 +754,20 @@ struct DrawArcOp final : DrawOpBase {
// so this op will always pack efficiently
// The point type is packed into 3 different OpTypes to avoid expanding
// the fixed payload beyond the 8 bytes
#define DEFINE_DRAW_POINTS_OP(name, mode) \
struct Draw##name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::kDraw##name; \
\
explicit Draw##name##Op(uint32_t count) : count(count) {} \
\
const uint32_t count; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
const SkPoint* pts = reinterpret_cast<const SkPoint*>(this + 1); \
ctx.dispatcher.drawPoints(DlCanvas::PointMode::mode, count, pts); \
} \
} \
#define DEFINE_DRAW_POINTS_OP(name, mode) \
struct Draw##name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::kDraw##name; \
\
explicit Draw##name##Op(uint32_t count) : count(count) {} \
\
const uint32_t count; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
const SkPoint* pts = reinterpret_cast<const SkPoint*>(this + 1); \
ctx.receiver.drawPoints(DlCanvas::PointMode::mode, count, pts); \
} \
} \
};
DEFINE_DRAW_POINTS_OP(Points, kPoints);
DEFINE_DRAW_POINTS_OP(Lines, kLines);
@ -792,38 +792,38 @@ struct DrawVerticesOp final : DrawOpBase {
if (op_needed(ctx)) {
const DlVertices* vertices =
reinterpret_cast<const DlVertices*>(this + 1);
ctx.dispatcher.drawVertices(vertices, mode);
ctx.receiver.drawVertices(vertices, mode);
}
}
};
// 4 byte header + 40 byte payload uses 44 bytes but is rounded up to 48 bytes
// (4 bytes unused)
#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \
struct name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::k##name; \
\
name##Op(const sk_sp<DlImage> image, \
const SkPoint& point, \
DlImageSampling sampling) \
: point(point), sampling(sampling), image(std::move(image)) {} \
\
const SkPoint point; \
const DlImageSampling sampling; \
const sk_sp<DlImage> image; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.drawImage(image, point, sampling, with_attributes); \
} \
} \
\
DisplayListCompare equals(const name##Op* other) const { \
return (point == other->point && sampling == other->sampling && \
image->Equals(other->image)) \
? DisplayListCompare::kEqual \
: DisplayListCompare::kNotEqual; \
} \
#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \
struct name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::k##name; \
\
name##Op(const sk_sp<DlImage> image, \
const SkPoint& point, \
DlImageSampling sampling) \
: point(point), sampling(sampling), image(std::move(image)) {} \
\
const SkPoint point; \
const DlImageSampling sampling; \
const sk_sp<DlImage> image; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.receiver.drawImage(image, point, sampling, with_attributes); \
} \
} \
\
DisplayListCompare equals(const name##Op* other) const { \
return (point == other->point && sampling == other->sampling && \
image->Equals(other->image)) \
? DisplayListCompare::kEqual \
: DisplayListCompare::kNotEqual; \
} \
};
DEFINE_DRAW_IMAGE_OP(DrawImage, false)
DEFINE_DRAW_IMAGE_OP(DrawImageWithAttr, true)
@ -839,7 +839,7 @@ struct DrawImageRectOp final : DrawOpBase {
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint)
DlCanvas::SrcRectConstraint constraint)
: src(src),
dst(dst),
sampling(sampling),
@ -851,13 +851,13 @@ struct DrawImageRectOp final : DrawOpBase {
const SkRect dst;
const DlImageSampling sampling;
const bool render_with_attributes;
const SkCanvas::SrcRectConstraint constraint;
const DlCanvas::SrcRectConstraint constraint;
const sk_sp<DlImage> image;
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawImageRect(image, src, dst, sampling,
render_with_attributes, constraint);
ctx.receiver.drawImageRect(image, src, dst, sampling,
render_with_attributes, constraint);
}
}
@ -889,8 +889,8 @@ struct DrawImageRectOp final : DrawOpBase {
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.drawImageNine(image, center, dst, mode, \
render_with_attributes); \
ctx.receiver.drawImageNine(image, center, dst, mode, \
render_with_attributes); \
} \
} \
\
@ -976,8 +976,8 @@ struct DrawAtlasOp final : DrawAtlasBaseOp {
const DlColor* colors =
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
nullptr, render_with_attributes);
ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
nullptr, render_with_attributes);
}
}
@ -1021,8 +1021,8 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp {
const DlColor* colors =
has_colors ? reinterpret_cast<const DlColor*>(tex + count) : nullptr;
const DlBlendMode mode = static_cast<DlBlendMode>(mode_index);
ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
&cull_rect, render_with_attributes);
ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling,
&cull_rect, render_with_attributes);
}
}
@ -1041,19 +1041,22 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp {
struct DrawDisplayListOp final : DrawOpBase {
static const auto kType = DisplayListOpType::kDrawDisplayList;
explicit DrawDisplayListOp(const sk_sp<DisplayList> display_list)
: display_list(std::move(display_list)) {}
explicit DrawDisplayListOp(const sk_sp<DisplayList> display_list,
SkScalar opacity)
: opacity(opacity), display_list(std::move(display_list)) {}
SkScalar opacity;
const sk_sp<DisplayList> display_list;
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawDisplayList(display_list);
ctx.receiver.drawDisplayList(display_list, opacity);
}
}
DisplayListCompare equals(const DrawDisplayListOp* other) const {
return display_list->Equals(other->display_list)
return (opacity == other->opacity &&
display_list->Equals(other->display_list))
? DisplayListCompare::kEqual
: DisplayListCompare::kNotEqual;
}
@ -1073,33 +1076,33 @@ struct DrawTextBlobOp final : DrawOpBase {
void dispatch(DispatchContext& ctx) const {
if (op_needed(ctx)) {
ctx.dispatcher.drawTextBlob(blob, x, y);
ctx.receiver.drawTextBlob(blob, x, y);
}
}
};
// 4 byte header + 28 byte payload packs evenly into 32 bytes
#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
struct Draw##name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::kDraw##name; \
\
Draw##name##Op(const SkPath& path, \
DlColor color, \
SkScalar elevation, \
SkScalar dpr) \
: color(color), elevation(elevation), dpr(dpr), path(path) {} \
\
const DlColor color; \
const SkScalar elevation; \
const SkScalar dpr; \
const SkPath path; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.dispatcher.drawShadow(path, color, elevation, \
transparent_occluder, dpr); \
} \
} \
#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
struct Draw##name##Op final : DrawOpBase { \
static const auto kType = DisplayListOpType::kDraw##name; \
\
Draw##name##Op(const SkPath& path, \
DlColor color, \
SkScalar elevation, \
SkScalar dpr) \
: color(color), elevation(elevation), dpr(dpr), path(path) {} \
\
const DlColor color; \
const SkScalar elevation; \
const SkScalar dpr; \
const SkPath path; \
\
void dispatch(DispatchContext& ctx) const { \
if (op_needed(ctx)) { \
ctx.receiver.drawShadow(path, color, elevation, transparent_occluder, \
dpr); \
} \
} \
};
DEFINE_DRAW_SHADOW_OP(Shadow, false)
DEFINE_DRAW_SHADOW_OP(ShadowTransparentOccluder, true)

View File

@ -25,14 +25,6 @@ enum class DlDrawStyle {
kDefaultStyle = kFill,
};
inline DlDrawStyle ToDl(SkPaint::Style style) {
return static_cast<DlDrawStyle>(style);
}
inline SkPaint::Style ToSk(DlDrawStyle style) {
return static_cast<SkPaint::Style>(style);
}
enum class DlStrokeCap {
kButt, //!< no stroke extension
kRound, //!< adds circle
@ -42,14 +34,6 @@ enum class DlStrokeCap {
kDefaultCap = kButt,
};
inline DlStrokeCap ToDl(SkPaint::Cap cap) {
return static_cast<DlStrokeCap>(cap);
}
inline SkPaint::Cap ToSk(DlStrokeCap cap) {
return static_cast<SkPaint::Cap>(cap);
}
enum class DlStrokeJoin {
kMiter, //!< extends to miter limit
kRound, //!< adds circle
@ -59,14 +43,6 @@ enum class DlStrokeJoin {
kDefaultJoin = kMiter,
};
inline DlStrokeJoin ToDl(SkPaint::Join join) {
return static_cast<DlStrokeJoin>(join);
}
inline SkPaint::Join ToSk(DlStrokeJoin join) {
return static_cast<SkPaint::Join>(join);
}
class DlPaint {
public:
static constexpr DlColor kDefaultColor = DlColor::kBlack();
@ -174,7 +150,7 @@ class DlPaint {
}
const DlColorFilter* getColorFilterPtr() const { return colorFilter_.get(); }
DlPaint& setColorFilter(const std::shared_ptr<const DlColorFilter> filter) {
colorFilter_ = filter ? filter->shared() : nullptr;
colorFilter_ = filter;
return *this;
}
DlPaint& setColorFilter(const DlColorFilter* filter) {
@ -216,6 +192,10 @@ class DlPaint {
pathEffect_ = pathEffect;
return *this;
}
DlPaint& setPathEffect(const DlPathEffect* effect) {
pathEffect_ = effect ? effect->shared() : nullptr;
return *this;
}
bool isDefault() const { return *this == kDefault; }

View File

@ -25,8 +25,7 @@ enum class DlPathEffectType {
kDash,
};
class DlPathEffect
: public DlAttribute<DlPathEffect, SkPathEffect, DlPathEffectType> {
class DlPathEffect : public DlAttribute<DlPathEffect, DlPathEffectType> {
public:
virtual const DlDashPathEffect* asDash() const { return nullptr; }
@ -77,13 +76,11 @@ class DlDashPathEffect final : public DlPathEffect {
const DlDashPathEffect* asDash() const override { return this; }
sk_sp<SkPathEffect> skia_object() const override {
return SkDashPathEffect::Make(intervals(), count_, phase_);
}
const SkScalar* intervals() const {
return reinterpret_cast<const SkScalar*>(this + 1);
}
int count() const { return count_; }
SkScalar phase() const { return phase_; }
std::optional<SkRect> effect_bounds(SkRect& rect) const override;

View File

@ -13,19 +13,6 @@
namespace flutter {
namespace testing {
TEST(DisplayListPathEffect, BuilderSetGet) {
const SkScalar test_dashes[] = {4.0, 2.0};
auto dash_path_effect = DlDashPathEffect::Make(test_dashes, 2, 0.0);
DisplayListBuilder builder;
ASSERT_EQ(builder.getPathEffect(), nullptr);
builder.setPathEffect(dash_path_effect.get());
ASSERT_NE(builder.getPathEffect(), nullptr);
ASSERT_TRUE(Equals(builder.getPathEffect(),
static_cast<DlPathEffect*>(dash_path_effect.get())));
builder.setPathEffect(nullptr);
ASSERT_EQ(builder.getPathEffect(), nullptr);
}
TEST(DisplayListPathEffect, EffectShared) {
const SkScalar TestDashes2[] = {1.0, 1.5};
auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0);

View File

@ -16,14 +16,6 @@ enum class DlFilterMode {
kLast = kLinear,
};
inline DlFilterMode ToDl(const SkFilterMode filter_mode) {
return static_cast<DlFilterMode>(filter_mode);
}
inline SkFilterMode ToSk(const DlFilterMode filter_mode) {
return static_cast<SkFilterMode>(filter_mode);
}
enum class DlImageSampling {
kNearestNeighbor,
kLinear,
@ -31,34 +23,6 @@ enum class DlImageSampling {
kCubic,
};
inline DlImageSampling ToDl(const SkSamplingOptions& so) {
if (so.useCubic) {
return DlImageSampling::kCubic;
}
if (so.filter == SkFilterMode::kLinear) {
if (so.mipmap == SkMipmapMode::kNone) {
return DlImageSampling::kLinear;
}
if (so.mipmap == SkMipmapMode::kLinear) {
return DlImageSampling::kMipmapLinear;
}
}
return DlImageSampling::kNearestNeighbor;
}
inline SkSamplingOptions ToSk(DlImageSampling sampling) {
switch (sampling) {
case DlImageSampling::kCubic:
return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f});
case DlImageSampling::kLinear:
return SkSamplingOptions(SkFilterMode::kLinear);
case DlImageSampling::kMipmapLinear:
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
case DlImageSampling::kNearestNeighbor:
return SkSamplingOptions(SkFilterMode::kNearest);
}
}
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_SAMPLING_OPTIONS_H_

View File

@ -30,14 +30,6 @@ enum class DlTileMode {
kDecal,
};
inline DlTileMode ToDl(SkTileMode sk_mode) {
return static_cast<DlTileMode>(sk_mode);
}
inline SkTileMode ToSk(DlTileMode dl_mode) {
return static_cast<SkTileMode>(dl_mode);
}
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_TILE_MODE_H_

File diff suppressed because it is too large Load Diff

View File

@ -4,106 +4,8 @@
#include "flutter/display_list/display_list_utils.h"
#include <math.h>
#include <optional>
#include <type_traits>
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkMaskFilter.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRSXform.h"
#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/utils/SkShadowUtils.h"
namespace flutter {
// clang-format off
constexpr float kInvertColorMatrix[20] = {
-1.0, 0, 0, 1.0, 0,
0, -1.0, 0, 1.0, 0,
0, 0, -1.0, 1.0, 0,
1.0, 1.0, 1.0, 1.0, 0
};
// clang-format on
void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) {
save_stack_.emplace_back(opacity_);
set_opacity(child_opacity);
}
void SkPaintDispatchHelper::restore_opacity() {
if (save_stack_.empty()) {
return;
}
set_opacity(save_stack_.back().opacity);
save_stack_.pop_back();
}
void SkPaintDispatchHelper::setAntiAlias(bool aa) {
paint_.setAntiAlias(aa);
}
void SkPaintDispatchHelper::setDither(bool dither) {
paint_.setDither(dither);
}
void SkPaintDispatchHelper::setInvertColors(bool invert) {
invert_colors_ = invert;
paint_.setColorFilter(makeColorFilter());
}
void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) {
paint_.setStrokeCap(ToSk(cap));
}
void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) {
paint_.setStrokeJoin(ToSk(join));
}
void SkPaintDispatchHelper::setStyle(DlDrawStyle style) {
paint_.setStyle(ToSk(style));
}
void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) {
paint_.setStrokeWidth(width);
}
void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) {
paint_.setStrokeMiter(limit);
}
void SkPaintDispatchHelper::setColor(DlColor color) {
current_color_ = color;
paint_.setColor(color);
if (has_opacity()) {
paint_.setAlphaf(paint_.getAlphaf() * opacity());
}
}
void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) {
paint_.setBlendMode(ToSk(mode));
}
void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) {
paint_.setShader(source ? source->skia_object() : nullptr);
}
void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) {
paint_.setImageFilter(filter ? filter->skia_object() : nullptr);
}
void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) {
color_filter_ = filter ? filter->shared() : nullptr;
paint_.setColorFilter(makeColorFilter());
}
void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) {
paint_.setPathEffect(effect ? effect->skia_object() : nullptr);
}
void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) {
paint_.setMaskFilter(filter ? filter->skia_object() : nullptr);
}
sk_sp<SkColorFilter> SkPaintDispatchHelper::makeColorFilter() const {
if (!invert_colors_) {
return color_filter_ ? color_filter_->skia_object() : nullptr;
}
sk_sp<SkColorFilter> invert_filter =
SkColorFilters::Matrix(kInvertColorMatrix);
if (color_filter_) {
invert_filter = invert_filter->makeComposed(color_filter_->skia_object());
}
return invert_filter;
}
void RectBoundsAccumulator::accumulate(const SkRect& r, int index) {
if (r.fLeft < r.fRight && r.fTop < r.fBottom) {
rect_.accumulate(r.fLeft, r.fTop);

View File

@ -7,33 +7,24 @@
#include <optional>
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_flags.h"
#include "flutter/display_list/display_list_rtree.h"
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkMaskFilter.h"
// This file contains various utility classes to ease implementing
// a Flutter DisplayList Dispatcher, including:
// a Flutter DisplayList DlOpReceiver, including:
//
// IgnoreAttributeDispatchHelper:
// IgnoreClipDispatchHelper:
// IgnoreTransformDispatchHelper
// Empty overrides of all of the associated methods of Dispatcher
// for dispatchers that only track some of the rendering operations
//
// SkPaintAttributeDispatchHelper:
// Tracks the attribute methods and maintains their state in an
// SkPaint object.
// Empty overrides of all of the associated methods of DlOpReceiver
// for receivers that only track some of the rendering operations
namespace flutter {
// A utility class that will ignore all Dispatcher methods relating
// A utility class that will ignore all DlOpReceiver methods relating
// to the setting of attributes.
class IgnoreAttributeDispatchHelper : public virtual Dispatcher {
class IgnoreAttributeDispatchHelper : public virtual DlOpReceiver {
public:
void setAntiAlias(bool aa) override {}
void setDither(bool dither) override {}
@ -52,9 +43,9 @@ class IgnoreAttributeDispatchHelper : public virtual Dispatcher {
void setMaskFilter(const DlMaskFilter* filter) override {}
};
// A utility class that will ignore all Dispatcher methods relating
// A utility class that will ignore all DlOpReceiver methods relating
// to setting a clip.
class IgnoreClipDispatchHelper : public virtual Dispatcher {
class IgnoreClipDispatchHelper : public virtual DlOpReceiver {
void clipRect(const SkRect& rect,
DlCanvas::ClipOp clip_op,
bool is_aa) override {}
@ -66,9 +57,9 @@ class IgnoreClipDispatchHelper : public virtual Dispatcher {
bool is_aa) override {}
};
// A utility class that will ignore all Dispatcher methods relating
// A utility class that will ignore all DlOpReceiver methods relating
// to modifying the transform.
class IgnoreTransformDispatchHelper : public virtual Dispatcher {
class IgnoreTransformDispatchHelper : public virtual DlOpReceiver {
public:
void translate(SkScalar tx, SkScalar ty) override {}
void scale(SkScalar sx, SkScalar sy) override {}
@ -88,7 +79,7 @@ class IgnoreTransformDispatchHelper : public virtual Dispatcher {
void transformReset() override {}
};
class IgnoreDrawDispatchHelper : public virtual Dispatcher {
class IgnoreDrawDispatchHelper : public virtual DlOpReceiver {
public:
void save() override {}
void saveLayer(const SkRect* bounds,
@ -121,7 +112,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override {}
SrcRectConstraint constraint) override {}
void drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
@ -136,7 +127,8 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
DlImageSampling sampling,
const SkRect* cull_rect,
bool render_with_attributes) override {}
void drawDisplayList(const sk_sp<DisplayList> display_list) override {}
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override {}
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override {}
@ -147,77 +139,6 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher {
SkScalar dpr) override {}
};
// A utility class that will monitor the Dispatcher methods relating
// to the rendering attributes and accumulate them into an SkPaint
// which can be accessed at any time via paint().
class SkPaintDispatchHelper : public virtual Dispatcher {
public:
SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1)
: current_color_(SK_ColorBLACK), opacity_(opacity) {
if (opacity < SK_Scalar1) {
paint_.setAlphaf(opacity);
}
}
void setAntiAlias(bool aa) override;
void setDither(bool dither) override;
void setStyle(DlDrawStyle style) override;
void setColor(DlColor color) override;
void setStrokeWidth(SkScalar width) override;
void setStrokeMiter(SkScalar limit) override;
void setStrokeCap(DlStrokeCap cap) override;
void setStrokeJoin(DlStrokeJoin join) override;
void setColorSource(const DlColorSource* source) override;
void setColorFilter(const DlColorFilter* filter) override;
void setInvertColors(bool invert) override;
void setBlendMode(DlBlendMode mode) override;
void setPathEffect(const DlPathEffect* effect) override;
void setMaskFilter(const DlMaskFilter* filter) override;
void setImageFilter(const DlImageFilter* filter) override;
const SkPaint& paint() { return paint_; }
/// Returns the current opacity attribute which is used to reduce
/// the alpha of all setColor calls encountered in the streeam
SkScalar opacity() { return opacity_; }
/// Returns the combined opacity that includes both the current
/// opacity attribute and the alpha of the most recent color.
/// The most recently set color will have combined the two and
/// stored the combined value in the alpha of the paint.
SkScalar combined_opacity() { return paint_.getAlphaf(); }
/// Returns true iff the current opacity attribute is not opaque,
/// irrespective of the alpha of the current color
bool has_opacity() { return opacity_ < SK_Scalar1; }
protected:
void save_opacity(SkScalar opacity_for_children);
void restore_opacity();
private:
SkPaint paint_;
bool invert_colors_ = false;
std::shared_ptr<const DlColorFilter> color_filter_;
sk_sp<SkColorFilter> makeColorFilter() const;
struct SaveInfo {
SaveInfo(SkScalar opacity) : opacity(opacity) {}
SkScalar opacity;
};
std::vector<SaveInfo> save_stack_;
void set_opacity(SkScalar opacity) {
if (opacity_ != opacity) {
opacity_ = opacity;
setColor(current_color_);
}
}
SkColor current_color_;
SkScalar opacity_;
};
enum class BoundsAccumulatorType {
kRect,
kRTree,

View File

@ -176,13 +176,6 @@ DlVertices::DlVertices(DlVertexMode mode,
FML_DCHECK((index_count_ != 0) == (indices() != nullptr));
}
sk_sp<SkVertices> DlVertices::skia_object() const {
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors());
return SkVertices::MakeCopy(ToSk(mode_), vertex_count_, vertices(),
texture_coordinates(), sk_colors, index_count_,
indices());
}
bool DlVertices::operator==(DlVertices const& other) const {
auto lists_equal = [](auto* a, auto* b, int count) {
if (a == nullptr || b == nullptr) {

View File

@ -30,14 +30,6 @@ enum class DlVertexMode {
kTriangleFan,
};
inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) {
return static_cast<SkVertices::VertexMode>(dl_mode);
}
inline DlVertexMode ToDl(SkVertices::VertexMode sk_mode) {
return static_cast<DlVertexMode>(sk_mode);
}
//------------------------------------------------------------------------------
/// @brief Holds all of the data (both required and optional) for a
/// DisplayList drawVertices call.
@ -233,9 +225,6 @@ class DlVertices {
return static_cast<const uint16_t*>(pod(indices_offset_));
}
// Returns an equivalent sk_sp<SkVertices> analog to this object.
sk_sp<SkVertices> skia_object() const;
bool operator==(DlVertices const& other) const;
bool operator!=(DlVertices const& other) const { return !(*this == other); }

View File

@ -22,7 +22,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) {
EXPECT_EQ(vertices1->colors(), nullptr);
EXPECT_EQ(vertices1->index_count(), 0);
EXPECT_EQ(vertices1->indices(), nullptr);
EXPECT_NE(vertices1->skia_object(), nullptr);
std::shared_ptr<const DlVertices> vertices2 = DlVertices::Make(
DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr);
@ -33,7 +32,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) {
EXPECT_EQ(vertices2->colors(), nullptr);
EXPECT_EQ(vertices2->index_count(), 0);
EXPECT_EQ(vertices2->indices(), nullptr);
EXPECT_NE(vertices2->skia_object(), nullptr);
TestEquals(*vertices1, *vertices2);
}
@ -425,7 +423,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) {
EXPECT_EQ(vertices1->colors(), nullptr);
EXPECT_EQ(vertices1->index_count(), 0);
EXPECT_EQ(vertices1->indices(), nullptr);
EXPECT_NE(vertices1->skia_object(), nullptr);
Builder builder2(DlVertexMode::kTriangles, -1, Builder::kNone, -1);
EXPECT_TRUE(builder2.is_valid());
@ -437,7 +434,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) {
EXPECT_EQ(vertices2->colors(), nullptr);
EXPECT_EQ(vertices2->index_count(), 0);
EXPECT_EQ(vertices2->indices(), nullptr);
EXPECT_NE(vertices2->skia_object(), nullptr);
TestEquals(*vertices1, *vertices2);
}

View File

@ -0,0 +1,23 @@
// 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.
#include "flutter/display_list/dl_canvas.h"
#include "third_party/skia/include/utils/SkShadowUtils.h"
namespace flutter {
SkRect DlCanvas::ComputeShadowBounds(const SkPath& path,
float elevation,
SkScalar dpr,
const SkMatrix& ctm) {
SkRect shadow_bounds(path.getBounds());
SkShadowUtils::GetLocalBounds(
ctm, path, SkPoint3::Make(0, 0, dpr * elevation),
SkPoint3::Make(0, -1, 1), kShadowLightRadius / kShadowLightHeight,
SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds);
return shadow_bounds;
}
} // namespace flutter

View File

@ -35,6 +35,11 @@ class DlCanvas {
kPolygon, //!< draw each pair of overlapping points as a line segment
};
enum class SrcRectConstraint {
kStrict,
kFast,
};
virtual ~DlCanvas() = default;
virtual SkISize GetBaseLayerSize() const = 0;
@ -146,28 +151,29 @@ class DlCanvas {
const SkPoint point,
DlImageSampling sampling,
const DlPaint* paint = nullptr) = 0;
virtual void DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) = 0;
virtual void DrawImageRect(const sk_sp<DlImage>& image,
const SkIRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) {
DrawImageRect(image, SkRect::Make(src), dst, sampling, paint,
enforce_src_edges);
virtual void DrawImageRect(
const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) = 0;
virtual void DrawImageRect(
const sk_sp<DlImage>& image,
const SkIRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
DrawImageRect(image, SkRect::Make(src), dst, sampling, paint, constraint);
}
virtual void DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) {
DrawImageRect(image, image->bounds(), dst, sampling, paint,
enforce_src_edges);
virtual void DrawImageRect(
const sk_sp<DlImage>& image,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
DrawImageRect(image, image->bounds(), dst, sampling, paint, constraint);
}
virtual void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
@ -196,6 +202,14 @@ class DlCanvas {
SkScalar dpr) = 0;
virtual void Flush() = 0;
static constexpr SkScalar kShadowLightHeight = 600;
static constexpr SkScalar kShadowLightRadius = 800;
static SkRect ComputeShadowBounds(const SkPath& path,
float elevation,
SkScalar dpr,
const SkMatrix& ctm);
};
class DlAutoCanvasRestore {

View File

@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
//
// Just exists to ensure that the header can be cleanly imported.
} // namespace flutter

View File

@ -28,10 +28,11 @@ class DisplayList;
/// through the DisplayListBuilder and also the methods that will be
/// invoked through the DisplayList::dispatch() method.
///
class Dispatcher {
class DlOpReceiver {
protected:
using ClipOp = DlCanvas::ClipOp;
using PointMode = DlCanvas::PointMode;
using SrcRectConstraint = DlCanvas::SrcRectConstraint;
public:
// MaxDrawPointsCount * sizeof(SkPoint) must be less than 1 << 32
@ -219,12 +220,13 @@ class Dispatcher {
const SkPoint point,
DlImageSampling sampling,
bool render_with_attributes) = 0;
virtual void drawImageRect(const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) = 0;
virtual void drawImageRect(
const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SrcRectConstraint constraint = SrcRectConstraint::kFast) = 0;
virtual void drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
@ -239,7 +241,8 @@ class Dispatcher {
DlImageSampling sampling,
const SkRect* cull_rect,
bool render_with_attributes) = 0;
virtual void drawDisplayList(const sk_sp<DisplayList> display_list) = 0;
virtual void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity = SK_Scalar1) = 0;
virtual void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) = 0;

View File

@ -4,43 +4,11 @@
#include "flutter/display_list/skia/dl_sk_canvas.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
namespace flutter {
static sk_sp<SkShader> ToSk(const DlColorSource* source) {
return source ? source->skia_object() : nullptr;
}
static sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter) {
return filter ? filter->skia_object() : nullptr;
}
static sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter) {
return filter ? filter->skia_object() : nullptr;
}
static sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter) {
return filter ? filter->skia_object() : nullptr;
}
static sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect) {
return effect ? effect->skia_object() : nullptr;
}
static SkCanvas::SrcRectConstraint ToSkConstraint(bool enforce_edges) {
return enforce_edges ? SkCanvas::kStrict_SrcRectConstraint
: SkCanvas::kFast_SrcRectConstraint;
}
static SkClipOp ToSk(DlCanvas::ClipOp op) {
return static_cast<SkClipOp>(op);
}
static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
return static_cast<SkCanvas::PointMode>(mode);
}
// clang-format off
constexpr float kInvertColorMatrix[20] = {
-1.0, 0, 0, 1.0, 0,
@ -119,10 +87,10 @@ void DlSkCanvasAdapter::Save() {
void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds,
const DlPaint* paint,
const DlImageFilter* backdrop) {
sk_sp<SkImageFilter> sk_filter = backdrop ? backdrop->skia_object() : nullptr;
sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
SkOptionalPaint sk_paint(paint);
delegate_->saveLayer(
SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_filter.get(), 0});
SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_backdrop.get(), 0});
}
void DlSkCanvasAdapter::Restore() {
@ -309,7 +277,7 @@ void DlSkCanvasAdapter::DrawPoints(PointMode mode,
void DlSkCanvasAdapter::DrawVertices(const DlVertices* vertices,
DlBlendMode mode,
const DlPaint& paint) {
delegate_->drawVertices(vertices->skia_object(), ToSk(mode), ToSk(paint));
delegate_->drawVertices(ToSk(vertices), ToSk(mode), ToSk(paint));
}
void DlSkCanvasAdapter::DrawImage(const sk_sp<DlImage>& image,
@ -327,11 +295,11 @@ void DlSkCanvasAdapter::DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint,
bool enforce_src_edges) {
SrcRectConstraint constraint) {
SkOptionalPaint sk_paint(paint);
sk_sp<SkImage> sk_image = image->skia_image();
delegate_->drawImageRect(sk_image.get(), src, dst, ToSk(sampling), sk_paint(),
ToSkConstraint(enforce_src_edges));
ToSk(constraint));
}
void DlSkCanvasAdapter::DrawImageNine(const sk_sp<DlImage>& image,
@ -363,7 +331,26 @@ void DlSkCanvasAdapter::DrawAtlas(const sk_sp<DlImage>& atlas,
void DlSkCanvasAdapter::DrawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) {
display_list->RenderTo(delegate_, opacity);
int restore_count = delegate_->getSaveCount();
// Figure out whether we can apply the opacity during dispatch or
// if we need a saveLayer.
if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) {
DlPaint save_paint = DlPaint().setOpacity(opacity);
SaveLayer(&display_list->bounds(), &save_paint);
opacity = SK_Scalar1;
} else {
Save();
}
DlSkCanvasDispatcher dispatcher(delegate_, opacity);
if (display_list->has_rtree()) {
display_list->Dispatch(dispatcher, delegate_->getLocalClipBounds());
} else {
display_list->Dispatch(dispatcher);
}
delegate_->restoreToCount(restore_count);
}
void DlSkCanvasAdapter::DrawTextBlob(const sk_sp<SkTextBlob>& blob,
@ -378,8 +365,8 @@ void DlSkCanvasAdapter::DrawShadow(const SkPath& path,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) {
DisplayListCanvasDispatcher::DrawShadow(delegate_, path, color, elevation,
transparent_occluder, dpr);
DlSkCanvasDispatcher::DrawShadow(delegate_, path, color, elevation,
transparent_occluder, dpr);
}
void DlSkCanvasAdapter::Flush() {

View File

@ -114,12 +114,13 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
const SkPoint point,
DlImageSampling sampling,
const DlPaint* paint = nullptr) override;
void DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) override;
void DrawImageRect(
const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
const SkRect& dst,
@ -135,7 +136,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas {
const SkRect* cullRect,
const DlPaint* paint = nullptr) override;
void DrawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
SkScalar opacity = SK_Scalar1) override;
void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
SkScalar x,
SkScalar y,

View File

@ -0,0 +1,235 @@
// 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.
#include "flutter/display_list/skia/dl_sk_conversions.h"
namespace flutter {
sk_sp<SkShader> ToSk(const DlColorSource* source) {
if (!source) {
return nullptr;
}
static auto ToSkColors = [](const DlGradientColorSourceBase* gradient) {
return reinterpret_cast<const SkColor*>(gradient->colors());
};
switch (source->type()) {
case DlColorSourceType::kColor: {
const DlColorColorSource* color_source = source->asColor();
FML_DCHECK(color_source != nullptr);
return SkShaders::Color(color_source->color());
}
case DlColorSourceType::kImage: {
const DlImageColorSource* image_source = source->asImage();
FML_DCHECK(image_source != nullptr);
auto image = image_source->image();
if (!image || !image->skia_image()) {
return nullptr;
}
return image->skia_image()->makeShader(
ToSk(image_source->horizontal_tile_mode()),
ToSk(image_source->vertical_tile_mode()),
ToSk(image_source->sampling()), image_source->matrix_ptr());
}
case DlColorSourceType::kLinearGradient: {
const DlLinearGradientColorSource* linear_source =
source->asLinearGradient();
FML_DCHECK(linear_source != nullptr);
SkPoint pts[] = {linear_source->start_point(),
linear_source->end_point()};
return SkGradientShader::MakeLinear(
pts, ToSkColors(linear_source), linear_source->stops(),
linear_source->stop_count(), ToSk(linear_source->tile_mode()), 0,
linear_source->matrix_ptr());
}
case DlColorSourceType::kRadialGradient: {
const DlRadialGradientColorSource* radial_source =
source->asRadialGradient();
FML_DCHECK(radial_source != nullptr);
return SkGradientShader::MakeRadial(
radial_source->center(), radial_source->radius(),
ToSkColors(radial_source), radial_source->stops(),
radial_source->stop_count(), ToSk(radial_source->tile_mode()), 0,
radial_source->matrix_ptr());
}
case DlColorSourceType::kConicalGradient: {
const DlConicalGradientColorSource* conical_source =
source->asConicalGradient();
FML_DCHECK(conical_source != nullptr);
return SkGradientShader::MakeTwoPointConical(
conical_source->start_center(), conical_source->start_radius(),
conical_source->end_center(), conical_source->end_radius(),
ToSkColors(conical_source), conical_source->stops(),
conical_source->stop_count(), ToSk(conical_source->tile_mode()), 0,
conical_source->matrix_ptr());
}
case DlColorSourceType::kSweepGradient: {
const DlSweepGradientColorSource* sweep_source =
source->asSweepGradient();
FML_DCHECK(sweep_source != nullptr);
return SkGradientShader::MakeSweep(
sweep_source->center().x(), sweep_source->center().y(),
ToSkColors(sweep_source), sweep_source->stops(),
sweep_source->stop_count(), ToSk(sweep_source->tile_mode()),
sweep_source->start(), sweep_source->end(), 0,
sweep_source->matrix_ptr());
}
case DlColorSourceType::kRuntimeEffect: {
const DlRuntimeEffectColorSource* runtime_source =
source->asRuntimeEffect();
FML_DCHECK(runtime_source != nullptr);
auto runtime_effect = runtime_source->runtime_effect();
if (!runtime_effect || !runtime_effect->skia_runtime_effect()) {
return nullptr;
}
auto samplers = runtime_source->samplers();
std::vector<sk_sp<SkShader>> sk_samplers(samplers.size());
for (size_t i = 0; i < samplers.size(); i++) {
auto sampler = samplers[i];
if (sampler == nullptr) {
return nullptr;
}
sk_samplers[i] = ToSk(sampler);
}
auto uniform_data = runtime_source->uniform_data();
auto ref = new std::shared_ptr<std::vector<uint8_t>>(uniform_data);
auto sk_uniform_data = SkData::MakeWithProc(
uniform_data->data(), uniform_data->size(),
[](const void* ptr, void* context) {
delete reinterpret_cast<std::shared_ptr<std::vector<uint8_t>>*>(
context);
},
ref);
return runtime_effect->skia_runtime_effect()->makeShader(
sk_uniform_data, sk_samplers.data(), sk_samplers.size());
}
}
}
sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter) {
if (!filter) {
return nullptr;
}
switch (filter->type()) {
case DlImageFilterType::kBlur: {
const DlBlurImageFilter* blur_filter = filter->asBlur();
FML_DCHECK(blur_filter != nullptr);
return SkImageFilters::Blur(blur_filter->sigma_x(),
blur_filter->sigma_y(),
ToSk(blur_filter->tile_mode()), nullptr);
}
case DlImageFilterType::kDilate: {
const DlDilateImageFilter* dilate_filter = filter->asDilate();
FML_DCHECK(dilate_filter != nullptr);
return SkImageFilters::Dilate(dilate_filter->radius_x(),
dilate_filter->radius_y(), nullptr);
}
case DlImageFilterType::kErode: {
const DlErodeImageFilter* erode_filter = filter->asErode();
FML_DCHECK(erode_filter != nullptr);
return SkImageFilters::Erode(erode_filter->radius_x(),
erode_filter->radius_y(), nullptr);
}
case DlImageFilterType::kMatrix: {
const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
FML_DCHECK(matrix_filter != nullptr);
return SkImageFilters::MatrixTransform(
matrix_filter->matrix(), ToSk(matrix_filter->sampling()), nullptr);
}
case DlImageFilterType::kCompose: {
const DlComposeImageFilter* compose_filter = filter->asCompose();
FML_DCHECK(compose_filter != nullptr);
return SkImageFilters::Compose(ToSk(compose_filter->outer()),
ToSk(compose_filter->inner()));
}
case DlImageFilterType::kColorFilter: {
const DlColorFilterImageFilter* cf_filter = filter->asColorFilter();
FML_DCHECK(cf_filter != nullptr);
return SkImageFilters::ColorFilter(ToSk(cf_filter->color_filter()),
nullptr);
}
case DlImageFilterType::kLocalMatrix: {
const DlLocalMatrixImageFilter* lm_filter = filter->asLocalMatrix();
FML_DCHECK(lm_filter != nullptr);
sk_sp<SkImageFilter> skia_filter = ToSk(lm_filter->image_filter());
// The image_filter property itself might have been null, or the
// construction of the SkImageFilter might be optimized to null
// for any number of reasons. In any case, if the filter is null
// or optimizaed away, let's then optimize away this local matrix
// case by returning null.
if (!skia_filter) {
return nullptr;
}
return skia_filter->makeWithLocalMatrix(lm_filter->matrix());
}
}
}
sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter) {
if (!filter) {
return nullptr;
}
switch (filter->type()) {
case DlColorFilterType::kBlend: {
const DlBlendColorFilter* blend_filter = filter->asBlend();
FML_DCHECK(blend_filter != nullptr);
return SkColorFilters::Blend(blend_filter->color(),
ToSk(blend_filter->mode()));
}
case DlColorFilterType::kMatrix: {
const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
FML_DCHECK(matrix_filter != nullptr);
float matrix[20];
matrix_filter->get_matrix(matrix);
return SkColorFilters::Matrix(matrix);
}
case DlColorFilterType::kSrgbToLinearGamma: {
return SkColorFilters::SRGBToLinearGamma();
}
case DlColorFilterType::kLinearToSrgbGamma: {
return SkColorFilters::LinearToSRGBGamma();
}
}
}
sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter) {
if (!filter) {
return nullptr;
}
switch (filter->type()) {
case DlMaskFilterType::kBlur: {
const DlBlurMaskFilter* blur_filter = filter->asBlur();
FML_DCHECK(blur_filter != nullptr);
return SkMaskFilter::MakeBlur(blur_filter->style(), blur_filter->sigma(),
blur_filter->respectCTM());
}
}
}
sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect) {
if (!effect) {
return nullptr;
}
switch (effect->type()) {
case DlPathEffectType::kDash: {
const DlDashPathEffect* dash_effect = effect->asDash();
FML_DCHECK(dash_effect != nullptr);
return SkDashPathEffect::Make(dash_effect->intervals(),
dash_effect->count(), dash_effect->phase());
}
}
}
sk_sp<SkVertices> ToSk(const DlVertices* vertices) {
const SkColor* sk_colors =
reinterpret_cast<const SkColor*>(vertices->colors());
return SkVertices::MakeCopy(ToSk(vertices->mode()), vertices->vertex_count(),
vertices->vertices(),
vertices->texture_coordinates(), sk_colors,
vertices->index_count(), vertices->indices());
}
} // namespace flutter

View File

@ -0,0 +1,116 @@
// 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_SKIA_DL_SK_CONVERSIONS_H_
#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
inline SkBlendMode ToSk(DlBlendMode mode) {
return static_cast<SkBlendMode>(mode);
}
inline SkPaint::Style ToSk(DlDrawStyle style) {
return static_cast<SkPaint::Style>(style);
}
inline SkPaint::Cap ToSk(DlStrokeCap cap) {
return static_cast<SkPaint::Cap>(cap);
}
inline SkPaint::Join ToSk(DlStrokeJoin join) {
return static_cast<SkPaint::Join>(join);
}
inline SkTileMode ToSk(DlTileMode dl_mode) {
return static_cast<SkTileMode>(dl_mode);
}
inline SkFilterMode ToSk(const DlFilterMode filter_mode) {
return static_cast<SkFilterMode>(filter_mode);
}
inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) {
return static_cast<SkVertices::VertexMode>(dl_mode);
}
inline SkSamplingOptions ToSk(DlImageSampling sampling) {
switch (sampling) {
case DlImageSampling::kCubic:
return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f});
case DlImageSampling::kLinear:
return SkSamplingOptions(SkFilterMode::kLinear);
case DlImageSampling::kMipmapLinear:
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
case DlImageSampling::kNearestNeighbor:
return SkSamplingOptions(SkFilterMode::kNearest);
}
}
inline SkCanvas::SrcRectConstraint ToSk(
DlCanvas::SrcRectConstraint constraint) {
return static_cast<SkCanvas::SrcRectConstraint>(constraint);
}
inline SkClipOp ToSk(DlCanvas::ClipOp op) {
return static_cast<SkClipOp>(op);
}
inline SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) {
return static_cast<SkCanvas::PointMode>(mode);
}
extern sk_sp<SkShader> ToSk(const DlColorSource* source);
inline sk_sp<SkShader> ToSk(std::shared_ptr<const DlColorSource> source) {
return ToSk(source.get());
}
inline sk_sp<SkShader> ToSk(const DlColorSource& source) {
return ToSk(&source);
}
extern sk_sp<SkImageFilter> ToSk(const DlImageFilter* filter);
inline sk_sp<SkImageFilter> ToSk(std::shared_ptr<const DlImageFilter> filter) {
return ToSk(filter.get());
}
inline sk_sp<SkImageFilter> ToSk(const DlImageFilter& filter) {
return ToSk(&filter);
}
extern sk_sp<SkColorFilter> ToSk(const DlColorFilter* filter);
inline sk_sp<SkColorFilter> ToSk(std::shared_ptr<const DlColorFilter> filter) {
return ToSk(filter.get());
}
inline sk_sp<SkColorFilter> ToSk(const DlColorFilter& filter) {
return ToSk(&filter);
}
extern sk_sp<SkMaskFilter> ToSk(const DlMaskFilter* filter);
inline sk_sp<SkMaskFilter> ToSk(std::shared_ptr<const DlMaskFilter> filter) {
return ToSk(filter.get());
}
inline sk_sp<SkMaskFilter> ToSk(const DlMaskFilter& filter) {
return ToSk(&filter);
}
extern sk_sp<SkPathEffect> ToSk(const DlPathEffect* effect);
inline sk_sp<SkPathEffect> ToSk(std::shared_ptr<const DlPathEffect> effect) {
return ToSk(effect.get());
}
inline sk_sp<SkPathEffect> ToSk(const DlPathEffect& effect) {
return ToSk(&effect);
}
extern sk_sp<SkVertices> ToSk(const DlVertices* vertices);
inline sk_sp<SkVertices> ToSk(std::shared_ptr<const DlVertices> vertices) {
return ToSk(vertices.get());
}
inline sk_sp<SkVertices> ToSk(const DlVertices& vertices) {
return ToSk(&vertices);
}
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_

View File

@ -0,0 +1,267 @@
// 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.
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_paint.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_tile_mode.h"
#include "flutter/display_list/display_list_vertices.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
#include "include/core/SkSamplingOptions.h"
namespace flutter {
namespace testing {
TEST(DisplayListImageFilter, LocalImageSkiaNull) {
auto blur_filter =
std::make_shared<DlBlurImageFilter>(0, 0, DlTileMode::kClamp);
DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45),
blur_filter);
// With sigmas set to zero on the blur filter, Skia will return a null filter.
// The local matrix filter should return nullptr instead of crashing.
ASSERT_EQ(ToSk(dl_local_matrix_filter), nullptr);
}
TEST(DisplayListSkConversions, ToSkTileMode) {
ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp);
ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat);
ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror);
ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal);
}
TEST(DisplayListSkConversions, ToSkDrawStyle) {
ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style);
ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style);
ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill),
SkPaint::Style::kStrokeAndFill_Style);
}
TEST(DisplayListSkConversions, ToSkStrokeCap) {
ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap);
ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap);
ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap);
}
TEST(DisplayListSkConversions, ToSkStrokeJoin) {
ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join);
ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join);
ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join);
}
TEST(DisplayListSkConversions, ToSkVertexMode) {
ASSERT_EQ(ToSk(DlVertexMode::kTriangles),
SkVertices::VertexMode::kTriangles_VertexMode);
ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip),
SkVertices::VertexMode::kTriangleStrip_VertexMode);
ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan),
SkVertices::VertexMode::kTriangleFan_VertexMode);
}
TEST(DisplayListSkConversions, ToSkFilterMode) {
ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear);
ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest);
ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast);
}
TEST(DisplayListSkConversions, ToSkSrcRectConstraint) {
ASSERT_EQ(ToSk(DlCanvas::SrcRectConstraint::kFast),
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
ASSERT_EQ(ToSk(DlCanvas::SrcRectConstraint::kStrict),
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);
}
TEST(DisplayListSkConversions, ToSkSamplingOptions) {
ASSERT_EQ(ToSk(DlImageSampling::kLinear),
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear),
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor),
SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone));
ASSERT_EQ(ToSk(DlImageSampling::kCubic),
SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}));
}
#define FOR_EACH_BLEND_MODE_ENUM(FUNC) \
FUNC(kSrc) \
FUNC(kClear) \
FUNC(kSrc) \
FUNC(kDst) \
FUNC(kSrcOver) \
FUNC(kDstOver) \
FUNC(kSrcIn) \
FUNC(kDstIn) \
FUNC(kSrcOut) \
FUNC(kDstOut) \
FUNC(kSrcATop) \
FUNC(kDstATop) \
FUNC(kXor) \
FUNC(kPlus) \
FUNC(kModulate) \
FUNC(kScreen) \
FUNC(kOverlay) \
FUNC(kDarken) \
FUNC(kLighten) \
FUNC(kColorDodge) \
FUNC(kColorBurn) \
FUNC(kHardLight) \
FUNC(kSoftLight) \
FUNC(kDifference) \
FUNC(kExclusion) \
FUNC(kMultiply) \
FUNC(kHue) \
FUNC(kSaturation) \
FUNC(kColor) \
FUNC(kLuminosity) \
FUNC(kLastCoeffMode) \
FUNC(kLastSeparableMode) \
FUNC(kLastMode)
TEST(DisplayListSkConversions, ToSkBlendMode) {
#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V);
FOR_EACH_BLEND_MODE_ENUM(CHECK_TO_SKENUM)
#undef CHECK_TO_SKENUM
}
TEST(DisplayListSkConversions, BlendColorFilterModifiesTransparency) {
auto test_mode_color = [](DlBlendMode mode, DlColor color) {
std::stringstream desc_str;
desc_str << "blend[" << static_cast<int>(mode) << ", " << color << "]";
std::string desc = desc_str.str();
DlBlendColorFilter filter(color, mode);
if (filter.modifies_transparent_black()) {
auto dl_filter = DlBlendColorFilter::Make(color, mode);
auto sk_filter = ToSk(filter);
ASSERT_NE(dl_filter, nullptr) << desc;
ASSERT_NE(sk_filter, nullptr) << desc;
ASSERT_TRUE(sk_filter->filterColor(0) != 0) << desc;
} else {
auto dl_filter = DlBlendColorFilter::Make(color, mode);
auto sk_filter = ToSk(filter);
EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr) << desc;
ASSERT_TRUE(sk_filter == nullptr || sk_filter->filterColor(0) == 0)
<< desc;
}
};
auto test_mode = [&test_mode_color](DlBlendMode mode) {
test_mode_color(mode, DlColor::kTransparent());
test_mode_color(mode, DlColor::kWhite());
test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
test_mode_color(mode, DlColor::kBlack());
test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
};
#define TEST_MODE(V) test_mode(DlBlendMode::V);
FOR_EACH_BLEND_MODE_ENUM(TEST_MODE)
#undef TEST_MODE
}
#undef FOR_EACH_BLEND_MODE_ENUM
TEST(DisplayListSkConversions, ConvertWithZeroAndNegativeVerticesAndIndices) {
std::shared_ptr<const DlVertices> vertices1 = DlVertices::Make(
DlVertexMode::kTriangles, 0, nullptr, nullptr, nullptr, 0, nullptr);
EXPECT_NE(vertices1, nullptr);
EXPECT_NE(ToSk(vertices1), nullptr);
std::shared_ptr<const DlVertices> vertices2 = DlVertices::Make(
DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr);
EXPECT_NE(vertices2, nullptr);
EXPECT_NE(ToSk(vertices2), nullptr);
}
TEST(DisplayListVertices, ConvertWithZeroAndNegativeVerticesAndIndices) {
DlVertices::Builder builder1(DlVertexMode::kTriangles, 0,
DlVertices::Builder::kNone, 0);
EXPECT_TRUE(builder1.is_valid());
std::shared_ptr<DlVertices> vertices1 = builder1.build();
EXPECT_NE(vertices1, nullptr);
EXPECT_NE(ToSk(vertices1), nullptr);
DlVertices::Builder builder2(DlVertexMode::kTriangles, -1,
DlVertices::Builder::kNone, -1);
EXPECT_TRUE(builder2.is_valid());
std::shared_ptr<DlVertices> vertices2 = builder2.build();
EXPECT_NE(vertices2, nullptr);
EXPECT_NE(ToSk(vertices2), nullptr);
}
TEST(DisplayListColorSource, ConvertRuntimeEffect) {
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia(
SkRuntimeEffect::MakeForShader(
SkString("vec4 main(vec2 p) { return vec4(0); }"))
.effect);
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect2 = DlRuntimeEffect::MakeSkia(
SkRuntimeEffect::MakeForShader(
SkString("vec4 main(vec2 p) { return vec4(1); }"))
.effect);
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
DlColorSource::MakeRuntimeEffect(
kTestRuntimeEffect1, {}, std::make_shared<std::vector<uint8_t>>());
std::shared_ptr<DlRuntimeEffectColorSource> source2 =
DlColorSource::MakeRuntimeEffect(
kTestRuntimeEffect2, {}, std::make_shared<std::vector<uint8_t>>());
std::shared_ptr<DlRuntimeEffectColorSource> source3 =
DlColorSource::MakeRuntimeEffect(
nullptr, {}, std::make_shared<std::vector<uint8_t>>());
ASSERT_NE(ToSk(source1), nullptr);
ASSERT_NE(ToSk(source2), nullptr);
ASSERT_EQ(ToSk(source3), nullptr);
}
TEST(DisplayListColorSource, ConvertRuntimeEffectWithNullSampler) {
const sk_sp<DlRuntimeEffect> kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia(
SkRuntimeEffect::MakeForShader(
SkString("vec4 main(vec2 p) { return vec4(0); }"))
.effect);
std::shared_ptr<DlRuntimeEffectColorSource> source1 =
DlColorSource::MakeRuntimeEffect(
kTestRuntimeEffect1, {nullptr},
std::make_shared<std::vector<uint8_t>>());
ASSERT_EQ(ToSk(source1), nullptr);
}
TEST(DisplayListSkConversions, MatrixColorFilterModifiesTransparency) {
auto test_matrix = [](int element, SkScalar value) {
// clang-format off
float matrix[] = {
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
};
// clang-format on
std::string desc =
"matrix[" + std::to_string(element) + "] = " + std::to_string(value);
matrix[element] = value;
DlMatrixColorFilter filter(matrix);
auto dl_filter = DlMatrixColorFilter::Make(matrix);
auto sk_filter = ToSk(filter);
EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr);
EXPECT_EQ(filter.modifies_transparent_black(),
sk_filter && sk_filter->filterColor(0) != 0);
};
// Tests identity (matrix[0] already == 1 in an identity filter)
test_matrix(0, 1);
// test_matrix(19, 1);
for (int i = 0; i < 20; i++) {
test_matrix(i, -0.25);
test_matrix(i, 0);
test_matrix(i, 0.25);
test_matrix(i, 1);
test_matrix(i, 1.25);
test_matrix(i, SK_ScalarNaN);
test_matrix(i, SK_ScalarInfinity);
test_matrix(i, -SK_ScalarInfinity);
}
}
} // namespace testing
} // namespace flutter

View File

@ -0,0 +1,305 @@
// 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.
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/utils/SkShadowUtils.h"
namespace flutter {
const SkPaint* DlSkCanvasDispatcher::safe_paint(bool use_attributes) {
if (use_attributes) {
// The accumulated SkPaint object will already have incorporated
// any attribute overrides.
return &paint();
} else if (has_opacity()) {
temp_paint_.setAlphaf(opacity());
return &temp_paint_;
} else {
return nullptr;
}
}
void DlSkCanvasDispatcher::save() {
canvas_->save();
// save has no impact on attributes, but it needs to register a record
// on the restore stack so that the eventual call to restore() will
// know what to do at that time. We could annotate the restore record
// with a flag that the record came from a save call, but it is simpler
// to just pass in the current opacity value as the value to be used by
// the children and let the utility calls notice that it didn't change.
save_opacity(opacity());
}
void DlSkCanvasDispatcher::restore() {
canvas_->restore();
restore_opacity();
}
void DlSkCanvasDispatcher::saveLayer(const SkRect* bounds,
const SaveLayerOptions options,
const DlImageFilter* backdrop) {
if (bounds == nullptr && options.can_distribute_opacity() &&
backdrop == nullptr) {
// We know that:
// - no bounds is needed for clipping here
// - no backdrop filter is used to initialize the layer
// - the current attributes only have an alpha
// - the children are compatible with individually rendering with
// an inherited opacity
// Therefore we can just use a save instead of a saveLayer and pass the
// intended opacity to the children.
canvas_->save();
// If the saveLayer does not use attributes, the children should continue
// to render with the inherited opacity unmodified. If attributes are to
// be applied, the children should render with the combination of the
// inherited opacity combined with the alpha from the current color.
save_opacity(options.renders_with_attributes() ? combined_opacity()
: opacity());
} else {
TRACE_EVENT0("flutter", "Canvas::saveLayer");
const SkPaint* paint = safe_paint(options.renders_with_attributes());
const sk_sp<SkImageFilter> sk_backdrop = ToSk(backdrop);
canvas_->saveLayer(
SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0));
// saveLayer will apply the current opacity on behalf of the children
// so they will inherit an opaque opacity.
save_opacity(SK_Scalar1);
}
}
void DlSkCanvasDispatcher::translate(SkScalar tx, SkScalar ty) {
canvas_->translate(tx, ty);
}
void DlSkCanvasDispatcher::scale(SkScalar sx, SkScalar sy) {
canvas_->scale(sx, sy);
}
void DlSkCanvasDispatcher::rotate(SkScalar degrees) {
canvas_->rotate(degrees);
}
void DlSkCanvasDispatcher::skew(SkScalar sx, SkScalar sy) {
canvas_->skew(sx, sy);
}
// clang-format off
// 2x3 2D affine subset of a 4x4 transform in row major order
void DlSkCanvasDispatcher::transform2DAffine(
SkScalar mxx, SkScalar mxy, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myt) {
// Internally concat(SkMatrix) gets redirected to concat(SkM44)
// so we just jump directly to the SkM44 version
canvas_->concat(SkM44(mxx, mxy, 0, mxt,
myx, myy, 0, myt,
0, 0, 1, 0,
0, 0, 0, 1));
}
// full 4x4 transform in row major order
void DlSkCanvasDispatcher::transformFullPerspective(
SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
canvas_->concat(SkM44(mxx, mxy, mxz, mxt,
myx, myy, myz, myt,
mzx, mzy, mzz, mzt,
mwx, mwy, mwz, mwt));
}
// clang-format on
void DlSkCanvasDispatcher::transformReset() {
canvas_->setMatrix(original_transform_);
}
void DlSkCanvasDispatcher::clipRect(const SkRect& rect,
ClipOp clip_op,
bool is_aa) {
canvas_->clipRect(rect, ToSk(clip_op), is_aa);
}
void DlSkCanvasDispatcher::clipRRect(const SkRRect& rrect,
ClipOp clip_op,
bool is_aa) {
canvas_->clipRRect(rrect, ToSk(clip_op), is_aa);
}
void DlSkCanvasDispatcher::clipPath(const SkPath& path,
ClipOp clip_op,
bool is_aa) {
canvas_->clipPath(path, ToSk(clip_op), is_aa);
}
void DlSkCanvasDispatcher::drawPaint() {
const SkPaint& sk_paint = paint();
SkImageFilter* filter = sk_paint.getImageFilter();
if (filter && !filter->asColorFilter(nullptr)) {
// drawPaint does an implicit saveLayer if an SkImageFilter is
// present that cannot be replaced by an SkColorFilter.
TRACE_EVENT0("flutter", "Canvas::saveLayer");
}
canvas_->drawPaint(sk_paint);
}
void DlSkCanvasDispatcher::drawColor(DlColor color, DlBlendMode mode) {
// SkCanvas::drawColor(SkColor) does the following conversion anyway
// We do it here manually to increase precision on applying opacity
SkColor4f color4f = SkColor4f::FromColor(color);
color4f.fA *= opacity();
canvas_->drawColor(color4f, ToSk(mode));
}
void DlSkCanvasDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
canvas_->drawLine(p0, p1, paint());
}
void DlSkCanvasDispatcher::drawRect(const SkRect& rect) {
canvas_->drawRect(rect, paint());
}
void DlSkCanvasDispatcher::drawOval(const SkRect& bounds) {
canvas_->drawOval(bounds, paint());
}
void DlSkCanvasDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
canvas_->drawCircle(center, radius, paint());
}
void DlSkCanvasDispatcher::drawRRect(const SkRRect& rrect) {
canvas_->drawRRect(rrect, paint());
}
void DlSkCanvasDispatcher::drawDRRect(const SkRRect& outer,
const SkRRect& inner) {
canvas_->drawDRRect(outer, inner, paint());
}
void DlSkCanvasDispatcher::drawPath(const SkPath& path) {
canvas_->drawPath(path, paint());
}
void DlSkCanvasDispatcher::drawArc(const SkRect& bounds,
SkScalar start,
SkScalar sweep,
bool useCenter) {
canvas_->drawArc(bounds, start, sweep, useCenter, paint());
}
void DlSkCanvasDispatcher::drawPoints(PointMode mode,
uint32_t count,
const SkPoint pts[]) {
canvas_->drawPoints(ToSk(mode), count, pts, paint());
}
void DlSkCanvasDispatcher::drawVertices(const DlVertices* vertices,
DlBlendMode mode) {
canvas_->drawVertices(ToSk(vertices), ToSk(mode), paint());
}
void DlSkCanvasDispatcher::drawImage(const sk_sp<DlImage> image,
const SkPoint point,
DlImageSampling sampling,
bool render_with_attributes) {
canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY,
ToSk(sampling), safe_paint(render_with_attributes));
}
void DlSkCanvasDispatcher::drawImageRect(const sk_sp<DlImage> image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SrcRectConstraint constraint) {
canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst,
ToSk(sampling), safe_paint(render_with_attributes),
ToSk(constraint));
}
void DlSkCanvasDispatcher::drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
DlFilterMode filter,
bool render_with_attributes) {
if (!image) {
return;
}
auto skia_image = image->skia_image();
if (!skia_image) {
return;
}
canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter),
safe_paint(render_with_attributes));
}
void DlSkCanvasDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
const DlColor colors[],
int count,
DlBlendMode mode,
DlImageSampling sampling,
const SkRect* cullRect,
bool render_with_attributes) {
if (!atlas) {
return;
}
auto skia_atlas = atlas->skia_image();
if (!skia_atlas) {
return;
}
const SkColor* sk_colors = reinterpret_cast<const SkColor*>(colors);
canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode),
ToSk(sampling), cullRect,
safe_paint(render_with_attributes));
}
void DlSkCanvasDispatcher::drawDisplayList(
const sk_sp<DisplayList> display_list,
SkScalar opacity) {
int restore_count;
// Compute combined opacity and figure out whether we can apply it
// during dispatch or if we need a saveLayer.
SkScalar combined_opacity = opacity * this->opacity();
if (combined_opacity < SK_Scalar1 &&
!display_list->can_apply_group_opacity()) {
SkPaint save_paint;
save_paint.setAlphaf(combined_opacity);
restore_count = canvas_->saveLayer(display_list->bounds(), &save_paint);
combined_opacity = SK_Scalar1;
} else {
restore_count = canvas_->save();
}
// Create a new CanvasDispatcher to isolate the actions of the
// display_list from the current environment.
DlSkCanvasDispatcher dispatcher(canvas_, combined_opacity);
if (display_list->rtree()) {
display_list->Dispatch(dispatcher, canvas_->getLocalClipBounds());
} else {
display_list->Dispatch(dispatcher);
}
// Restore canvas state to what it was before dispatching.
canvas_->restoreToCount(restore_count);
}
void DlSkCanvasDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) {
canvas_->drawTextBlob(blob, x, y, paint());
}
void DlSkCanvasDispatcher::DrawShadow(SkCanvas* canvas,
const SkPath& path,
DlColor color,
float elevation,
bool transparentOccluder,
SkScalar dpr) {
const SkScalar kAmbientAlpha = 0.039f;
const SkScalar kSpotAlpha = 0.25f;
uint32_t flags = transparentOccluder
? SkShadowFlags::kTransparentOccluder_ShadowFlag
: SkShadowFlags::kNone_ShadowFlag;
flags |= SkShadowFlags::kDirectionalLight_ShadowFlag;
SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color));
SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color));
SkColor ambient_color, spot_color;
SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color,
&spot_color);
SkShadowUtils::DrawShadow(
canvas, path, SkPoint3::Make(0, 0, dpr * elevation),
SkPoint3::Make(0, -1, 1),
DlCanvas::kShadowLightRadius / DlCanvas::kShadowLightHeight,
ambient_color, spot_color, flags);
}
void DlSkCanvasDispatcher::drawShadow(const SkPath& path,
const DlColor color,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) {
DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr);
}
} // namespace flutter

View File

@ -6,9 +6,8 @@
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_CANVAS_DISPATCHER_H_
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_utils.h"
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/display_list/skia/dl_sk_utils.h"
#include "flutter/fml/macros.h"
namespace flutter {
@ -19,11 +18,10 @@ namespace flutter {
///
/// Receives all methods on Dispatcher and sends them to an SkCanvas
///
class DisplayListCanvasDispatcher : public virtual Dispatcher,
public SkPaintDispatchHelper {
class DlSkCanvasDispatcher : public virtual DlOpReceiver,
public SkPaintDispatchHelper {
public:
explicit DisplayListCanvasDispatcher(SkCanvas* canvas,
SkScalar opacity = SK_Scalar1)
explicit DlSkCanvasDispatcher(SkCanvas* canvas, SkScalar opacity = SK_Scalar1)
: SkPaintDispatchHelper(opacity),
canvas_(canvas),
original_transform_(canvas->getLocalToDevice()) {}
@ -81,7 +79,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override;
SrcRectConstraint constraint) override;
void drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
@ -96,7 +94,8 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
DlImageSampling sampling,
const SkRect* cullRect,
bool render_with_attributes) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
@ -106,11 +105,6 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher,
bool transparent_occluder,
SkScalar dpr) override;
static SkRect ComputeShadowBounds(const SkPath& path,
float elevation,
SkScalar dpr,
const SkMatrix& ctm);
static void DrawShadow(SkCanvas* canvas,
const SkPath& path,
DlColor color,

View File

@ -0,0 +1,102 @@
// 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.
#include "flutter/display_list/skia/dl_sk_utils.h"
#include <math.h>
#include <optional>
#include <type_traits>
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/fml/logging.h"
namespace flutter {
// clang-format off
constexpr float kInvertColorMatrix[20] = {
-1.0, 0, 0, 1.0, 0,
0, -1.0, 0, 1.0, 0,
0, 0, -1.0, 1.0, 0,
1.0, 1.0, 1.0, 1.0, 0
};
// clang-format on
void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) {
save_stack_.emplace_back(opacity_);
set_opacity(child_opacity);
}
void SkPaintDispatchHelper::restore_opacity() {
if (save_stack_.empty()) {
return;
}
set_opacity(save_stack_.back().opacity);
save_stack_.pop_back();
}
void SkPaintDispatchHelper::setAntiAlias(bool aa) {
paint_.setAntiAlias(aa);
}
void SkPaintDispatchHelper::setDither(bool dither) {
paint_.setDither(dither);
}
void SkPaintDispatchHelper::setInvertColors(bool invert) {
invert_colors_ = invert;
paint_.setColorFilter(makeColorFilter());
}
void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) {
paint_.setStrokeCap(ToSk(cap));
}
void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) {
paint_.setStrokeJoin(ToSk(join));
}
void SkPaintDispatchHelper::setStyle(DlDrawStyle style) {
paint_.setStyle(ToSk(style));
}
void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) {
paint_.setStrokeWidth(width);
}
void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) {
paint_.setStrokeMiter(limit);
}
void SkPaintDispatchHelper::setColor(DlColor color) {
current_color_ = color;
paint_.setColor(color);
if (has_opacity()) {
paint_.setAlphaf(paint_.getAlphaf() * opacity());
}
}
void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) {
paint_.setBlendMode(ToSk(mode));
}
void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) {
paint_.setShader(ToSk(source));
}
void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) {
paint_.setImageFilter(ToSk(filter));
}
void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) {
sk_color_filter_ = ToSk(filter);
paint_.setColorFilter(makeColorFilter());
}
void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) {
paint_.setPathEffect(ToSk(effect));
}
void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) {
paint_.setMaskFilter(ToSk(filter));
}
sk_sp<SkColorFilter> SkPaintDispatchHelper::makeColorFilter() const {
if (!invert_colors_) {
return sk_color_filter_;
}
sk_sp<SkColorFilter> invert_filter =
SkColorFilters::Matrix(kInvertColorMatrix);
if (sk_color_filter_) {
invert_filter = invert_filter->makeComposed(sk_color_filter_);
}
return invert_filter;
}
} // namespace flutter

View File

@ -0,0 +1,85 @@
// 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_SKIA_DL_SK_UTILS_H_
#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
// A utility class that will monitor the DlOpReceiver methods relating
// to the rendering attributes and accumulate them into an SkPaint
// which can be accessed at any time via paint().
class SkPaintDispatchHelper : public virtual DlOpReceiver {
public:
SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1)
: current_color_(SK_ColorBLACK), opacity_(opacity) {
if (opacity < SK_Scalar1) {
paint_.setAlphaf(opacity);
}
}
void setAntiAlias(bool aa) override;
void setDither(bool dither) override;
void setStyle(DlDrawStyle style) override;
void setColor(DlColor color) override;
void setStrokeWidth(SkScalar width) override;
void setStrokeMiter(SkScalar limit) override;
void setStrokeCap(DlStrokeCap cap) override;
void setStrokeJoin(DlStrokeJoin join) override;
void setColorSource(const DlColorSource* source) override;
void setColorFilter(const DlColorFilter* filter) override;
void setInvertColors(bool invert) override;
void setBlendMode(DlBlendMode mode) override;
void setPathEffect(const DlPathEffect* effect) override;
void setMaskFilter(const DlMaskFilter* filter) override;
void setImageFilter(const DlImageFilter* filter) override;
const SkPaint& paint() { return paint_; }
/// Returns the current opacity attribute which is used to reduce
/// the alpha of all setColor calls encountered in the streeam
SkScalar opacity() { return opacity_; }
/// Returns the combined opacity that includes both the current
/// opacity attribute and the alpha of the most recent color.
/// The most recently set color will have combined the two and
/// stored the combined value in the alpha of the paint.
SkScalar combined_opacity() { return paint_.getAlphaf(); }
/// Returns true iff the current opacity attribute is not opaque,
/// irrespective of the alpha of the current color
bool has_opacity() { return opacity_ < SK_Scalar1; }
protected:
void save_opacity(SkScalar opacity_for_children);
void restore_opacity();
private:
SkPaint paint_;
bool invert_colors_ = false;
sk_sp<SkColorFilter> sk_color_filter_;
sk_sp<SkColorFilter> makeColorFilter() const;
struct SaveInfo {
SaveInfo(SkScalar opacity) : opacity(opacity) {}
SkScalar opacity;
};
std::vector<SaveInfo> save_stack_;
void set_opacity(SkScalar opacity) {
if (opacity_ != opacity) {
opacity_ = opacity;
setColor(current_color_);
}
}
SkColor current_color_;
SkScalar opacity_;
};
} // namespace flutter
#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_

View File

@ -3,12 +3,13 @@
// found in the LICENSE file.
#include "flutter/display_list/display_list_utils.h"
#include "flutter/display_list/skia/dl_sk_utils.h"
#include "gtest/gtest.h"
namespace flutter {
namespace testing {
class MockDispatchHelper final : public virtual Dispatcher,
class MockDispatchHelper final : public virtual DlOpReceiver,
public SkPaintDispatchHelper,
public IgnoreClipDispatchHelper,
public IgnoreTransformDispatchHelper,

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ sk_sp<DisplayList> GetSampleDisplayList();
sk_sp<DisplayList> GetSampleDisplayList(int ops);
sk_sp<DisplayList> GetSampleNestedDisplayList();
typedef const std::function<void(DisplayListBuilder&)> DlInvoker;
typedef const std::function<void(DlOpReceiver&)> DlInvoker;
constexpr SkPoint kEndPoints[] = {
{0, 0},
@ -214,8 +214,7 @@ static std::shared_ptr<const DlVertices> TestVertices2 =
static sk_sp<DisplayList> MakeTestDisplayList(int w, int h, SkColor color) {
DisplayListBuilder builder;
builder.setColor(color);
builder.drawRect(SkRect::MakeWH(w, h));
builder.DrawRect(SkRect::MakeWH(w, h), DlPaint(color));
return builder.Build();
}
static sk_sp<DisplayList> TestDisplayList1 =
@ -271,13 +270,13 @@ struct DisplayListInvocation {
// through an SkCanvas interface, comparable to |DisplayList.byte_count().
size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; }
void Invoke(DisplayListBuilder& builder) { invoker(builder); }
void Invoke(DlOpReceiver& builder) { invoker(builder); }
sk_sp<DisplayList> Build() {
DisplayListBuilder builder;
invoker(builder);
return builder.Build();
}
// sk_sp<DisplayList> Build() {
// DisplayListBuilder builder;
// invoker(builder.asReceiver());
// return builder.Build();
// }
};
struct DisplayListInvocationGroup {

View File

@ -28,5 +28,4 @@
#include "third_party/skia/include/effects/SkDashPathEffect.h"
#include "third_party/skia/include/effects/SkDiscretePathEffect.h"
#include "third_party/skia/include/gpu/GrTypes.h"
#include "third_party/skia/include/utils/SkShadowUtils.h"
#endif // FLUTTER_DISPLAY_LIST_TYPES_H_

View File

@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/flow/layers/clip_path_layer.h"
#include "flutter/flow/layers/clip_rect_layer.h"
#include "flutter/flow/layers/clip_rrect_layer.h"
@ -235,8 +234,8 @@ TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerCheckBoard) {
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
// their shadows , so we do not do any painting there.
EXPECT_EQ(layer->paint_bounds(),
DisplayListCanvasDispatcher::ComputeShadowBounds(
layer_path, initial_elevation, 1.0f, SkMatrix()));
DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f,
SkMatrix()));
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(layer->elevation(), initial_elevation);

View File

@ -424,7 +424,7 @@ TEST_F(ClipPathLayerTest, OpacityInheritancePainting) {
{
expected_builder.Translate(offset.fX, offset.fY);
/* ClipRectLayer::Paint() */ {
expected_builder.save();
expected_builder.Save();
expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true);
/* child layer1 paint */ {
expected_builder.DrawPath(path1, DlPaint().setAlpha(opacity_alpha));
@ -472,25 +472,24 @@ TEST_F(ClipPathLayerTest, OpacityInheritanceSaveLayerPainting) {
DisplayListBuilder expected_builder;
/* OpacityLayer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(offset.fX, offset.fY);
expected_builder.Translate(offset.fX, offset.fY);
/* ClipRectLayer::Paint() */ {
expected_builder.save();
expected_builder.clipPath(layer_clip, ClipOp::kIntersect, true);
expected_builder.setColor(opacity_alpha << 24);
expected_builder.saveLayer(&children_bounds, true);
expected_builder.Save();
expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true);
expected_builder.SaveLayer(&children_bounds,
&DlPaint().setAlpha(opacity_alpha));
/* child layer1 paint */ {
expected_builder.setColor(0xFF000000);
expected_builder.drawPath(path1);
expected_builder.DrawPath(path1, DlPaint());
}
/* child layer2 paint */ { //
expected_builder.drawPath(path2);
expected_builder.DrawPath(path2, DlPaint());
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer->Paint(display_list_paint_context());

View File

@ -454,25 +454,24 @@ TEST_F(ClipRectLayerTest, OpacityInheritanceSaveLayerPainting) {
DisplayListBuilder expected_builder;
/* OpacityLayer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(offset.fX, offset.fY);
expected_builder.Translate(offset.fX, offset.fY);
/* ClipRectLayer::Paint() */ {
expected_builder.save();
expected_builder.clipRect(clip_rect, ClipOp::kIntersect, true);
expected_builder.setColor(opacity_alpha << 24);
expected_builder.saveLayer(&children_bounds, true);
expected_builder.Save();
expected_builder.ClipRect(clip_rect, ClipOp::kIntersect, true);
expected_builder.SaveLayer(&children_bounds,
&DlPaint().setAlpha(opacity_alpha));
/* child layer1 paint */ {
expected_builder.setColor(0xFF000000);
expected_builder.drawPath(path1);
expected_builder.DrawPath(path1, DlPaint());
}
/* child layer2 paint */ { //
expected_builder.drawPath(path2);
expected_builder.DrawPath(path2, DlPaint());
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer->Paint(display_list_paint_context());

View File

@ -467,25 +467,24 @@ TEST_F(ClipRRectLayerTest, OpacityInheritanceSaveLayerPainting) {
DisplayListBuilder expected_builder;
/* OpacityLayer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(offset.fX, offset.fY);
expected_builder.Translate(offset.fX, offset.fY);
/* ClipRectLayer::Paint() */ {
expected_builder.save();
expected_builder.clipRRect(clip_rrect, ClipOp::kIntersect, true);
expected_builder.setColor(opacity_alpha << 24);
expected_builder.saveLayer(&children_bounds, true);
expected_builder.Save();
expected_builder.ClipRRect(clip_rrect, ClipOp::kIntersect, true);
expected_builder.SaveLayer(&children_bounds,
&DlPaint().setAlpha(opacity_alpha));
/* child layer1 paint */ {
expected_builder.setColor(0xFF000000);
expected_builder.drawPath(path1);
expected_builder.DrawPath(path1, DlPaint());
}
/* child layer2 paint */ { //
expected_builder.drawPath(path2);
expected_builder.DrawPath(path2, DlPaint());
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer->Paint(display_list_paint_context());

View File

@ -32,7 +32,7 @@ TEST_F(DisplayListLayerTest, PaintBeforePrerollDies) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject<DisplayList>(display_list, unref_queue()),
@ -47,7 +47,7 @@ TEST_F(DisplayListLayerTest, PaintingEmptyLayerDies) {
const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f);
const SkRect picture_bounds = SkRect::MakeEmpty();
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject<DisplayList>(display_list, unref_queue()),
@ -77,7 +77,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) {
SkMatrix::Translate(layer_offset.fX, layer_offset.fY);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
@ -102,7 +102,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) {
TEST_F(DisplayListLayerTest, CachingDoesNotChangeCullRect) {
const SkPoint layer_offset = SkPoint::Make(10, 10);
DisplayListBuilder builder;
builder.drawRect({10, 10, 20, 20});
builder.DrawRect({10, 10, 20, 20}, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
@ -118,7 +118,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto display_list_layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
@ -130,6 +130,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
LayerStateStack::kCallerCanApplyOpacity);
int opacity_alpha = 0x7F;
SkScalar opacity = opacity_alpha / 255.0;
SkPoint opacity_offset = SkPoint::Make(10, 10);
auto opacity_layer =
std::make_shared<OpacityLayer>(opacity_alpha, opacity_offset);
@ -138,30 +139,24 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
EXPECT_TRUE(opacity_layer->children_can_accept_opacity());
DisplayListBuilder child_builder;
child_builder.drawRect(picture_bounds);
child_builder.DrawRect(picture_bounds, DlPaint());
auto child_display_list = child_builder.Build();
DisplayListBuilder expected_builder;
/* opacity_layer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(opacity_offset.fX, opacity_offset.fY);
expected_builder.Translate(opacity_offset.fX, opacity_offset.fY);
/* display_list_layer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(layer_offset.fX, layer_offset.fY);
expected_builder.setColor(opacity_alpha << 24);
expected_builder.saveLayer(&picture_bounds, true);
/* display_list contents */ { //
expected_builder.drawDisplayList(child_display_list);
}
expected_builder.restore();
expected_builder.setColor(DlColor::kBlack());
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
expected_builder.DrawDisplayList(child_display_list, opacity);
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer->Paint(display_list_paint_context());
@ -174,8 +169,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
DisplayListBuilder builder;
builder.drawRect(picture1_bounds);
builder.drawRect(picture2_bounds);
builder.DrawRect(picture1_bounds, DlPaint());
builder.DrawRect(picture2_bounds, DlPaint());
auto display_list = builder.Build();
auto display_list_layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
@ -194,8 +189,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
EXPECT_FALSE(opacity_layer->children_can_accept_opacity());
DisplayListBuilder child_builder;
child_builder.drawRect(picture1_bounds);
child_builder.drawRect(picture2_bounds);
child_builder.DrawRect(picture1_bounds, DlPaint());
child_builder.DrawRect(picture2_bounds, DlPaint());
auto child_display_list = child_builder.Build();
auto display_list_bounds = picture1_bounds;
@ -204,24 +199,24 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
display_list_bounds.makeOffset(layer_offset.fX, layer_offset.fY);
DisplayListBuilder expected_builder;
/* opacity_layer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(opacity_offset.fX, opacity_offset.fY);
expected_builder.setColor(opacity_alpha << 24);
expected_builder.saveLayer(&save_layer_bounds, true);
expected_builder.Translate(opacity_offset.fX, opacity_offset.fY);
expected_builder.SaveLayer(&save_layer_bounds,
&DlPaint().setAlpha(opacity_alpha));
{
/* display_list_layer::Paint() */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(layer_offset.fX, layer_offset.fY);
expected_builder.drawDisplayList(child_display_list);
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
expected_builder.DrawDisplayList(child_display_list);
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer->Paint(display_list_paint_context());
@ -234,8 +229,8 @@ TEST_F(DisplayListLayerTest, CachedIncompatibleDisplayListOpacityInheritance) {
const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
DisplayListBuilder builder;
builder.drawRect(picture1_bounds);
builder.drawRect(picture2_bounds);
builder.DrawRect(picture1_bounds, DlPaint());
builder.DrawRect(picture2_bounds, DlPaint());
auto display_list = builder.Build();
auto display_list_layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
@ -386,7 +381,7 @@ TEST_F(DisplayListLayerTest, LayerTreeSnapshotsWhenEnabled) {
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
@ -405,7 +400,7 @@ TEST_F(DisplayListLayerTest, NoLayerTreeSnapshotsWhenDisabledByDefault) {
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false);
@ -423,7 +418,7 @@ TEST_F(DisplayListLayerTest, DisplayListAccessCountDependsOnVisibility) {
const SkRect missed_cull_rect = SkRect::MakeLTRB(100, 100, 200, 200);
const SkRect hit_cull_rect = SkRect::MakeLTRB(0, 0, 200, 200);
DisplayListBuilder builder;
builder.drawRect(picture_bounds);
builder.DrawRect(picture_bounds, DlPaint());
auto display_list = builder.Build();
auto layer = std::make_shared<DisplayListLayer>(
layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false);
@ -524,8 +519,8 @@ TEST_F(DisplayListLayerTest, OverflowCachedDisplayListOpacityInheritance) {
std::shared_ptr<DisplayListLayer> layers[layer_count];
for (int i = 0; i < layer_count; i++) {
DisplayListBuilder builder(false);
builder.drawRect({0, 0, 100, 100});
builder.drawRect({50, 50, 100, 100});
builder.DrawRect({0, 0, 100, 100}, DlPaint());
builder.DrawRect({50, 50, 100, 100}, DlPaint());
auto display_list = builder.Build();
ASSERT_FALSE(display_list->can_apply_group_opacity());
SkPoint offset = {i * 200.0f, 0};

View File

@ -248,7 +248,7 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) {
}
}
}
expected_builder.restore();
expected_builder.Restore();
auto expected_display_list = expected_builder.Build();
layer->Paint(display_list_paint_context());

View File

@ -606,24 +606,23 @@ TEST_F(OpacityLayerTest, OpacityInheritanceNestedWithIncompatibleChild) {
DisplayListBuilder expected_builder;
/* opacity_layer_1::Paint */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(offset1.fX, offset1.fY);
expected_builder.Translate(offset1.fX, offset1.fY);
/* opacity_layer_2::Paint */ {
expected_builder.save();
expected_builder.Save();
{
expected_builder.translate(offset2.fX, offset2.fY);
expected_builder.setColor(savelayer_paint.getAlpha() << 24);
expected_builder.saveLayer(&mock_layer->paint_bounds(), true);
expected_builder.Translate(offset2.fX, offset2.fY);
expected_builder.SaveLayer(&mock_layer->paint_bounds(),
&savelayer_paint);
/* mock_layer::Paint */ {
expected_builder.setColor(0xFF000000);
expected_builder.drawPath(mock_path);
expected_builder.DrawPath(mock_path, DlPaint());
}
}
expected_builder.restore();
expected_builder.Restore();
}
}
expected_builder.restore();
expected_builder.Restore();
}
opacity_layer_1->Paint(display_list_paint_context());

View File

@ -4,7 +4,6 @@
#include "flutter/flow/layers/physical_shape_layer.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/flow/paint_utils.h"
namespace flutter {
@ -36,9 +35,9 @@ void PhysicalShapeLayer::Diff(DiffContext* context, const Layer* old_layer) {
if (elevation_ == 0) {
bounds = path_.getBounds();
} else {
bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
path_, elevation_, context->frame_device_pixel_ratio(),
context->GetTransform3x3());
bounds = DlCanvas::ComputeShadowBounds(path_, elevation_,
context->frame_device_pixel_ratio(),
context->GetTransform3x3());
}
context->AddLayerBounds(bounds);
@ -65,7 +64,7 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context) {
} else {
// We will draw the shadow in Paint(), so add some margin to the paint
// bounds to leave space for the shadow.
paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
paint_bounds = DlCanvas::ComputeShadowBounds(
path_, elevation_, context->frame_device_pixel_ratio,
context->state_stack.transform_3x3());
}

View File

@ -4,7 +4,6 @@
#include "flutter/flow/layers/physical_shape_layer.h"
#include "flutter/display_list/display_list_canvas_dispatcher.h"
#include "flutter/flow/testing/diff_context_test.h"
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
@ -214,8 +213,8 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
// their shadows , so we do not do any painting there.
EXPECT_EQ(layer->paint_bounds(),
DisplayListCanvasDispatcher::ComputeShadowBounds(
layer_path, initial_elevation, 1.0f, SkMatrix()));
DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f,
SkMatrix()));
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(layer->elevation(), initial_elevation);
@ -264,7 +263,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
// On Fuchsia, the system compositor handles all elevated
// PhysicalShapeLayers and their shadows , so we do not do any painting
// there.
SkRect paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
SkRect paint_bounds = DlCanvas::ComputeShadowBounds(
layer_path, initial_elevations[i], 1.0f /* pixel_ratio */, SkMatrix());
// Without clipping the children will be painted as well
@ -313,15 +312,15 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsCtm) {
path.addRect(0, 0, 8, 8).close();
for (SkScalar elevation : elevations) {
SkRect baseline_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
path, elevation, 1.0f, SkMatrix());
SkRect baseline_bounds =
DlCanvas::ComputeShadowBounds(path, elevation, 1.0f, SkMatrix());
for (SkScalar scale : scales) {
for (SkScalar translate_x : translates) {
for (SkScalar translate_y : translates) {
SkMatrix ctm;
ctm.setScaleTranslate(scale, scale, translate_x, translate_y);
SkRect bounds = DisplayListCanvasDispatcher::ComputeShadowBounds(
path, elevation, scale, ctm);
SkRect bounds =
DlCanvas::ComputeShadowBounds(path, elevation, scale, ctm);
EXPECT_FLOAT_EQ(bounds.fLeft, baseline_bounds.fLeft);
EXPECT_FLOAT_EQ(bounds.fTop, baseline_bounds.fTop);
EXPECT_FLOAT_EQ(bounds.fRight, baseline_bounds.fRight);
@ -377,14 +376,14 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsPathSize) {
[=](SkCanvas* canvas) {
SkPath path;
path.addRect(test_case[0]).close();
DisplayListCanvasDispatcher::DrawShadow(
canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f);
DlSkCanvasAdapter(canvas).DrawShadow(
path, DlColor::kBlack(), 1.0f, false, 1.0f);
},
[=](SkCanvas* canvas) {
SkPath path;
path.addRect(test_case[1]).close();
DisplayListCanvasDispatcher::DrawShadow(
canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f);
DlSkCanvasAdapter(canvas).DrawShadow(
path, DlColor::kBlack(), 1.0f, false, 1.0f);
},
SkSize::Make(100, 100)),
0);

View File

@ -383,7 +383,7 @@ TEST_F(ShaderMaskLayerTest, OpacityInheritance) {
/* child layer paint */ {
expected_builder.DrawPath(child_path, DlPaint());
}
expected_builder.translate(mask_rect.fLeft, mask_rect.fTop);
expected_builder.Translate(mask_rect.fLeft, mask_rect.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(mask_rect.width(), mask_rect.height()),
DlPaint().setBlendMode(DlBlendMode::kSrc));

View File

@ -449,8 +449,7 @@ TEST(RasterCache, DeviceRectRoundOutForDisplayList) {
SkRect logical_rect = SkRect::MakeLTRB(28, 0, 354.56731, 310.288);
DisplayListBuilder builder(logical_rect);
builder.setColor(SK_ColorRED);
builder.drawRect(logical_rect);
builder.DrawRect(logical_rect, DlPaint(DlColor::kRed()));
sk_sp<DisplayList> display_list = builder.Build();
SkMatrix ctm = SkMatrix::MakeAll(1.3312, 0, 233, 0, 1.3312, 206, 0, 0, 1);

View File

@ -35,8 +35,7 @@ Damage DiffContextTest::DiffLayerTree(MockLayerTree& layer_tree,
sk_sp<DisplayList> DiffContextTest::CreateDisplayList(const SkRect& bounds,
SkColor color) {
DisplayListBuilder builder;
builder.setColor(color);
builder.drawRect(bounds);
builder.DrawRect(bounds, DlPaint().setColor(color));
return builder.Build();
}

View File

@ -180,12 +180,12 @@ static Matrix ToMatrix(const SkMatrix& m) {
};
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setAntiAlias(bool aa) {
// Nothing to do because AA is implicit.
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setDither(bool dither) {}
static Paint::Style ToStyle(flutter::DlDrawStyle style) {
@ -201,12 +201,12 @@ static Paint::Style ToStyle(flutter::DlDrawStyle style) {
return Paint::Style::kFill;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setStyle(flutter::DlDrawStyle style) {
paint_.style = ToStyle(style);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setColor(flutter::DlColor color) {
paint_.color = {
color.getRedF(),
@ -216,17 +216,17 @@ void DisplayListDispatcher::setColor(flutter::DlColor color) {
};
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setStrokeWidth(SkScalar width) {
paint_.stroke_width = width;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setStrokeMiter(SkScalar limit) {
paint_.stroke_miter = limit;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
switch (cap) {
case flutter::DlStrokeCap::kButt:
@ -241,7 +241,7 @@ void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) {
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
switch (join) {
case flutter::DlStrokeJoin::kMiter:
@ -345,7 +345,7 @@ static std::optional<Paint::ColorSourceType> ToColorSourceType(
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setColorSource(
const flutter::DlColorSource* source) {
if (!source) {
@ -583,24 +583,24 @@ static std::optional<Paint::ColorFilterProc> ToColorFilterProc(
return std::nullopt;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setColorFilter(
const flutter::DlColorFilter* filter) {
// Needs https://github.com/flutter/flutter/issues/95434
paint_.color_filter = ToColorFilterProc(filter);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setInvertColors(bool invert) {
paint_.invert_colors = invert;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setBlendMode(flutter::DlBlendMode dl_mode) {
paint_.blend_mode = ToBlendMode(dl_mode);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setPathEffect(const flutter::DlPathEffect* effect) {
// Needs https://github.com/flutter/flutter/issues/95434
UNIMPLEMENTED;
@ -619,7 +619,7 @@ static FilterContents::BlurStyle ToBlurStyle(SkBlurStyle blur_style) {
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
// Needs https://github.com/flutter/flutter/issues/95434
if (filter == nullptr) {
@ -704,7 +704,7 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
};
break;
}
case flutter::DlImageFilterType::kComposeFilter: {
case flutter::DlImageFilterType::kCompose: {
auto compose = filter->asCompose();
FML_DCHECK(compose);
auto outer = compose->outer();
@ -741,7 +741,7 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
};
break;
}
case flutter::DlImageFilterType::kLocalMatrixFilter: {
case flutter::DlImageFilterType::kLocalMatrix: {
auto local_matrix_filter = filter->asLocalMatrix();
FML_DCHECK(local_matrix_filter);
auto internal_filter = local_matrix_filter->image_filter();
@ -766,13 +766,13 @@ static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::setImageFilter(
const flutter::DlImageFilter* filter) {
paint_.image_filter = ToImageFilterProc(filter);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::save() {
canvas_.Save();
}
@ -792,7 +792,7 @@ static std::vector<Rect> ToRects(const SkRect tex[], int count) {
return result;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) {
@ -800,32 +800,32 @@ void DisplayListDispatcher::saveLayer(const SkRect* bounds,
canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop));
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::restore() {
canvas_.Restore();
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::translate(SkScalar tx, SkScalar ty) {
canvas_.Translate({tx, ty, 0.0});
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::scale(SkScalar sx, SkScalar sy) {
canvas_.Scale({sx, sy, 1.0});
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::rotate(SkScalar degrees) {
canvas_.Rotate(Degrees{degrees});
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::skew(SkScalar sx, SkScalar sy) {
canvas_.Skew(sx, sy);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::transform2DAffine(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
@ -842,7 +842,7 @@ void DisplayListDispatcher::transform2DAffine(SkScalar mxx,
// clang-format on
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::transformFullPerspective(SkScalar mxx,
SkScalar mxy,
SkScalar mxz,
@ -872,7 +872,7 @@ void DisplayListDispatcher::transformFullPerspective(SkScalar mxx,
canvas_.Transform(xformation);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::transformReset() {
canvas_.ResetTransform();
canvas_.Transform(initial_matrix_);
@ -892,7 +892,7 @@ static Entity::ClipOperation ToClipOperation(
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::clipRect(const SkRect& rect,
ClipOp clip_op,
bool is_aa) {
@ -979,7 +979,7 @@ static Path ToPath(const SkPath& path) {
case SkPathFillType::kInverseWinding:
case SkPathFillType::kInverseEvenOdd:
// Flutter doesn't expose these path fill types. These are only visible
// via the dispatcher interface. We should never get here.
// via the receiver interface. We should never get here.
fill_type = FillType::kNonZero;
break;
}
@ -992,21 +992,21 @@ static Path ToPath(const SkRRect& rrect) {
.TakePath();
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::clipRRect(const SkRRect& rrect,
ClipOp clip_op,
bool is_aa) {
canvas_.ClipPath(ToPath(rrect), ToClipOperation(clip_op));
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::clipPath(const SkPath& path,
ClipOp clip_op,
bool is_aa) {
canvas_.ClipPath(ToPath(path), ToClipOperation(clip_op));
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawColor(flutter::DlColor color,
flutter::DlBlendMode dl_mode) {
Paint paint;
@ -1015,12 +1015,12 @@ void DisplayListDispatcher::drawColor(flutter::DlColor color,
canvas_.DrawPaint(paint);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawPaint() {
canvas_.DrawPaint(paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).TakePath();
Paint paint = paint_;
@ -1028,12 +1028,12 @@ void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
canvas_.DrawPath(path, paint);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawRect(const SkRect& rect) {
canvas_.DrawRect(ToRect(rect), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawOval(const SkRect& bounds) {
if (bounds.width() == bounds.height()) {
canvas_.DrawCircle(ToPoint(bounds.center()), bounds.width() * 0.5, paint_);
@ -1043,12 +1043,12 @@ void DisplayListDispatcher::drawOval(const SkRect& bounds) {
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
canvas_.DrawCircle(ToPoint(center), radius, paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
if (rrect.isSimple()) {
canvas_.DrawRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX, paint_);
@ -1057,7 +1057,7 @@ void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawDRRect(const SkRRect& outer,
const SkRRect& inner) {
PathBuilder builder;
@ -1066,12 +1066,12 @@ void DisplayListDispatcher::drawDRRect(const SkRRect& outer,
canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawPath(const SkPath& path) {
canvas_.DrawPath(ToPath(path), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawArc(const SkRect& oval_bounds,
SkScalar start_degrees,
SkScalar sweep_degrees,
@ -1082,7 +1082,7 @@ void DisplayListDispatcher::drawArc(const SkRect& oval_bounds,
canvas_.DrawPath(builder.TakePath(), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawPoints(PointMode mode,
uint32_t count,
const SkPoint points[]) {
@ -1121,14 +1121,14 @@ void DisplayListDispatcher::drawPoints(PointMode mode,
}
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawVertices(const flutter::DlVertices* vertices,
flutter::DlBlendMode dl_mode) {
canvas_.DrawVertices(DLVerticesGeometry::MakeVertices(vertices),
ToBlendMode(dl_mode), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawImage(const sk_sp<flutter::DlImage> image,
const SkPoint point,
flutter::DlImageSampling sampling,
@ -1147,24 +1147,23 @@ void DisplayListDispatcher::drawImage(const sk_sp<flutter::DlImage> image,
const auto dest =
SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);
drawImageRect(
image, // image
src, // source rect
dest, // destination rect
sampling, // sampling options
render_with_attributes, // render with attributes
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint // constraint
drawImageRect(image, // image
src, // source rect
dest, // destination rect
sampling, // sampling options
render_with_attributes, // render with attributes
SrcRectConstraint::kStrict // constraint
);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawImageRect(
const sk_sp<flutter::DlImage> image,
const SkRect& src,
const SkRect& dst,
flutter::DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
canvas_.DrawImageRect(
std::make_shared<Image>(image->impeller_texture()), // image
ToRect(src), // source rect
@ -1174,7 +1173,7 @@ void DisplayListDispatcher::drawImageRect(
);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
const SkIRect& center,
const SkRect& dst,
@ -1187,7 +1186,7 @@ void DisplayListDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
ToRect(dst), ToSamplerDescriptor(filter), &canvas_, &paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
@ -1203,21 +1202,43 @@ void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
ToSamplerDescriptor(sampling), ToRect(cull_rect), paint_);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawDisplayList(
const sk_sp<flutter::DisplayList> display_list) {
int saveCount = canvas_.GetSaveCount();
Paint savePaint = paint_;
Matrix saveMatrix = initial_matrix_;
paint_ = Paint();
const sk_sp<flutter::DisplayList> display_list,
SkScalar opacity) {
// Save all values that must remain untouched after the operation.
Paint saved_paint = paint_;
Matrix saved_initial_matrix = initial_matrix_;
int restore_count = canvas_.GetSaveCount();
// Establish a new baseline for interpreting the new DL.
// Matrix and clip are left untouched, the current
// transform is saved as the new base matrix, and paint
// values are reset to defaults.
initial_matrix_ = canvas_.GetCurrentTransformation();
paint_ = Paint();
// Handle passed opacity in the most brute-force way by using
// a SaveLayer. If the display_list is able to inherit the
// opacity, this could also be handled by modulating all of its
// attribute settings (for example, color), by the indicated
// opacity.
if (opacity < SK_Scalar1) {
Paint save_paint;
save_paint.color = Color(0, 0, 0, opacity);
canvas_.SaveLayer(save_paint);
}
display_list->Dispatch(*this);
paint_ = savePaint;
initial_matrix_ = saveMatrix;
canvas_.RestoreToCount(saveCount);
// Restore all saved state back to what it was before we interpreted
// the display_list
canvas_.RestoreToCount(restore_count);
initial_matrix_ = saved_initial_matrix;
paint_ = saved_paint;
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) {
@ -1228,7 +1249,7 @@ void DisplayListDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
);
}
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawShadow(const SkPath& path,
const flutter::DlColor color,
const SkScalar elevation,

View File

@ -7,14 +7,14 @@
#include "display_list/display_list_path_effect.h"
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/fml/macros.h"
#include "impeller/aiks/canvas.h"
#include "impeller/aiks/paint.h"
namespace impeller {
class DisplayListDispatcher final : public flutter::Dispatcher {
class DisplayListDispatcher final : public flutter::DlOpReceiver {
public:
DisplayListDispatcher();
@ -22,75 +22,75 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
Picture EndRecordingAsPicture();
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setAntiAlias(bool aa) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setDither(bool dither) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setStyle(flutter::DlDrawStyle style) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setColor(flutter::DlColor color) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setStrokeWidth(SkScalar width) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setStrokeMiter(SkScalar limit) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setStrokeCap(flutter::DlStrokeCap cap) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setStrokeJoin(flutter::DlStrokeJoin join) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setColorSource(const flutter::DlColorSource* source) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setColorFilter(const flutter::DlColorFilter* filter) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setInvertColors(bool invert) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setBlendMode(flutter::DlBlendMode mode) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setPathEffect(const flutter::DlPathEffect* effect) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setMaskFilter(const flutter::DlMaskFilter* filter) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void setImageFilter(const flutter::DlImageFilter* filter) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void save() override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void saveLayer(const SkRect* bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void restore() override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void translate(SkScalar tx, SkScalar ty) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void scale(SkScalar sx, SkScalar sy) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void rotate(SkScalar degrees) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void skew(SkScalar sx, SkScalar sy) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void transform2DAffine(SkScalar mxx,
SkScalar mxy,
SkScalar mxt,
@ -98,7 +98,7 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
SkScalar myy,
SkScalar myt) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void transformFullPerspective(SkScalar mxx,
SkScalar mxy,
SkScalar mxz,
@ -116,82 +116,82 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
SkScalar mwz,
SkScalar mwt) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void transformReset() override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawPaint() override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawLine(const SkPoint& p0, const SkPoint& p1) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawRect(const SkRect& rect) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawOval(const SkRect& bounds) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawCircle(const SkPoint& center, SkScalar radius) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawRRect(const SkRRect& rrect) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawPath(const SkPath& path) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawArc(const SkRect& oval_bounds,
SkScalar start_degrees,
SkScalar sweep_degrees,
bool use_center) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawPoints(PointMode mode,
uint32_t count,
const SkPoint points[]) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawVertices(const flutter::DlVertices* vertices,
flutter::DlBlendMode dl_mode) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawImage(const sk_sp<flutter::DlImage> image,
const SkPoint point,
flutter::DlImageSampling sampling,
bool render_with_attributes) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawImageRect(const sk_sp<flutter::DlImage> image,
const SkRect& src,
const SkRect& dst,
flutter::DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override;
SrcRectConstraint constraint) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawImageNine(const sk_sp<flutter::DlImage> image,
const SkIRect& center,
const SkRect& dst,
flutter::DlFilterMode filter,
bool render_with_attributes) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawAtlas(const sk_sp<flutter::DlImage> atlas,
const SkRSXform xform[],
const SkRect tex[],
@ -202,15 +202,16 @@ class DisplayListDispatcher final : public flutter::Dispatcher {
const SkRect* cull_rect,
bool render_with_attributes) override;
// |flutter::Dispatcher|
void drawDisplayList(const sk_sp<flutter::DisplayList> display_list) override;
// |flutter::DlOpReceiver|
void drawDisplayList(const sk_sp<flutter::DisplayList> display_list,
SkScalar opacity) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;
// |flutter::Dispatcher|
// |flutter::DlOpReceiver|
void drawShadow(const SkPath& path,
const flutter::DlColor color,
const SkScalar elevation,

View File

@ -44,85 +44,83 @@ INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest);
TEST_P(DisplayListTest, CanDrawRect) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorBLUE);
builder.drawRect(SkRect::MakeXYWH(10, 10, 100, 100));
builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
flutter::DlPaint(flutter::DlColor::kBlue()));
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(DisplayListTest, CanDrawTextBlob) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorBLUE);
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
100, 100);
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(DisplayListTest, CanDrawTextWithSaveLayer) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorRED);
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
100, 100);
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
flutter::DlPaint save_paint;
float alpha = 0.5;
save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
builder.SaveLayer(nullptr, &save_paint);
builder.setColor(SK_ColorRED);
builder.drawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
CreateTestFontOfSize(100)),
100, 300);
builder.restore();
100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(DisplayListTest, CanDrawImage) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(DisplayListTest, CanDrawCapsAndJoins) {
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
builder.setStyle(flutter::DlDrawStyle::kStroke);
builder.setStrokeWidth(30);
builder.setColor(SK_ColorRED);
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
paint.setStrokeWidth(30);
paint.setColor(SK_ColorRED);
auto path =
SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
builder.translate(100, 100);
builder.Translate(100, 100);
{
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
builder.setStrokeMiter(4);
builder.drawPath(path);
paint.setStrokeCap(flutter::DlStrokeCap::kButt);
paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
paint.setStrokeMiter(4);
builder.DrawPath(path, paint);
}
{
builder.save();
builder.translate(0, 100);
builder.Save();
builder.Translate(0, 100);
// The joint in the path is 45 degrees. A miter length of 1 convert to a
// bevel in this case.
builder.setStrokeMiter(1);
builder.drawPath(path);
builder.restore();
paint.setStrokeMiter(1);
builder.DrawPath(path, paint);
builder.Restore();
}
builder.translate(150, 0);
builder.Translate(150, 0);
{
builder.setStrokeCap(flutter::DlStrokeCap::kSquare);
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
builder.drawPath(path);
paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
builder.DrawPath(path, paint);
}
builder.translate(150, 0);
builder.Translate(150, 0);
{
builder.setStrokeCap(flutter::DlStrokeCap::kRound);
builder.setStrokeJoin(flutter::DlStrokeJoin::kRound);
builder.drawPath(path);
paint.setStrokeCap(flutter::DlStrokeCap::kRound);
paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
builder.DrawPath(path, paint);
}
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
@ -167,20 +165,21 @@ TEST_P(DisplayListTest, CanDrawArc) {
Point(200, 200), Point(400, 400), 20, Color::White(), Color::White());
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
Vector2 scale = GetContentScale();
builder.scale(scale.x, scale.y);
builder.setStyle(flutter::DlDrawStyle::kStroke);
builder.setStrokeCap(cap);
builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
builder.setStrokeMiter(10);
builder.Scale(scale.x, scale.y);
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
paint.setStrokeCap(cap);
paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
paint.setStrokeMiter(10);
auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
builder.setColor(SK_ColorGREEN);
builder.setStrokeWidth(2);
builder.drawRect(rect);
builder.setColor(SK_ColorRED);
builder.setStrokeWidth(stroke_width);
builder.drawArc(rect, start_angle, sweep_angle, use_center);
paint.setColor(SK_ColorGREEN);
paint.setStrokeWidth(2);
builder.DrawRect(rect, paint);
paint.setColor(SK_ColorRED);
paint.setStrokeWidth(stroke_width);
builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
return builder.Build();
};
@ -189,45 +188,48 @@ TEST_P(DisplayListTest, CanDrawArc) {
TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorRED);
builder.setStyle(flutter::DlDrawStyle::kStroke);
builder.setStrokeWidth(10);
flutter::DlPaint paint;
paint.setColor(SK_ColorRED);
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
paint.setStrokeWidth(10);
// Rectangle
builder.translate(100, 100);
builder.drawRect(SkRect::MakeSize({100, 100}));
builder.Translate(100, 100);
builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
// Rounded rectangle
builder.translate(150, 0);
builder.drawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10));
builder.Translate(150, 0);
builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
paint);
// Double rounded rectangle
builder.translate(150, 0);
builder.drawDRRect(
builder.Translate(150, 0);
builder.DrawDRRect(
SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10));
SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
// Contour with duplicate join points
{
builder.translate(150, 0);
builder.Translate(150, 0);
SkPath path;
path.lineTo({100, 0});
path.lineTo({100, 0});
path.lineTo({100, 100});
builder.drawPath(path);
builder.DrawPath(path, paint);
}
// Contour with duplicate end points
{
builder.setStrokeCap(flutter::DlStrokeCap::kRound);
builder.translate(150, 0);
paint.setStrokeCap(flutter::DlStrokeCap::kRound);
builder.Translate(150, 0);
SkPath path;
path.moveTo(0, 0);
path.lineTo({0, 0});
path.lineTo({50, 50});
path.lineTo({100, 0});
path.lineTo({100, 0});
builder.drawPath(path);
builder.DrawPath(path, paint);
}
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
@ -235,15 +237,17 @@ TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
TEST_P(DisplayListTest, CanDrawWithOddPathWinding) {
flutter::DisplayListBuilder builder;
builder.setColor(SK_ColorRED);
builder.setStyle(flutter::DlDrawStyle::kFill);
flutter::DlPaint paint;
builder.translate(300, 300);
paint.setColor(SK_ColorRED);
paint.setDrawStyle(flutter::DlDrawStyle::kFill);
builder.Translate(300, 300);
SkPath path;
path.setFillType(SkPathFillType::kEvenOdd);
path.addCircle(0, 0, 100);
path.addCircle(0, 0, 50);
builder.drawPath(path);
builder.DrawPath(path, paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -251,29 +255,31 @@ TEST_P(DisplayListTest, CanDrawWithOddPathWinding) {
TEST_P(DisplayListTest, CanDrawWithMaskBlur) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
// Mask blurred image.
{
auto filter = flutter::DlBlurMaskFilter(kNormal_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setMaskFilter(&filter);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
}
// Mask blurred filled path.
{
builder.setColor(SK_ColorYELLOW);
paint.setColor(SK_ColorYELLOW);
auto filter = flutter::DlBlurMaskFilter(kOuter_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true);
paint.setMaskFilter(&filter);
builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
}
// Mask blurred text.
{
auto filter = flutter::DlBlurMaskFilter(kSolid_SkBlurStyle, 10.0f);
builder.setMaskFilter(&filter);
builder.drawTextBlob(
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170);
paint.setMaskFilter(&filter);
builder.DrawTextBlob(
SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
paint);
}
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
@ -295,23 +301,24 @@ TEST_P(DisplayListTest, IgnoreMaskFilterWhenSavingLayer) {
TEST_P(DisplayListTest, CanDrawWithBlendColorFilter) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
// Pipeline blended image.
{
auto filter = flutter::DlBlendColorFilter(SK_ColorYELLOW,
flutter::DlBlendMode::kModulate);
builder.setColorFilter(&filter);
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setColorFilter(&filter);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
}
// Advanced blended image.
{
auto filter =
flutter::DlBlendColorFilter(SK_ColorRED, flutter::DlBlendMode::kScreen);
builder.setColorFilter(&filter);
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setColorFilter(&filter);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
flutter::DlImageSampling::kNearestNeighbor, &paint);
}
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
@ -326,18 +333,21 @@ TEST_P(DisplayListTest, CanDrawWithColorFilterImageFilter) {
};
auto texture = CreateTextureForFixture("boston.jpg");
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
auto color_filter =
std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
auto image_filter =
std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
builder.setImageFilter(image_filter.get());
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
builder.translate(0, 700);
builder.setColorFilter(color_filter.get());
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setImageFilter(image_filter.get());
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
builder.Translate(0, 700);
paint.setColorFilter(color_filter.get());
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -352,12 +362,13 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
ImGui::End();
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
flutter::DlTileMode::kClamp);
builder.setImageFilter(&filter);
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setImageFilter(&filter);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
flutter::DlImageSampling::kNearestNeighbor, &paint);
return builder.Build();
};
@ -368,17 +379,20 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
TEST_P(DisplayListTest, CanDrawWithComposeImageFilter) {
auto texture = CreateTextureForFixture("boston.jpg");
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
builder.setImageFilter(open.get());
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
builder.translate(0, 700);
builder.setImageFilter(close.get());
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
paint.setImageFilter(open.get());
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
builder.Translate(0, 700);
paint.setImageFilter(close.get());
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -407,9 +421,10 @@ TEST_P(DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter) {
auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
flutter::DisplayListBuilder builder;
builder.setImageFilter(compose.get());
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, true);
flutter::DlPaint paint;
paint.setImageFilter(compose.get());
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
flutter::DlImageSampling::kNearestNeighbor, &paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -543,7 +558,7 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
flutter::DisplayListBuilder builder;
Vector2 scale = ctm_scale * GetContentScale();
builder.scale(scale.x, scale.y);
builder.Scale(scale.x, scale.y);
auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
flutter::DlTileMode::kClamp);
@ -558,12 +573,12 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
// Insert a clip to test that the backdrop filter handles stencil depths > 0
// correctly.
if (add_clip) {
builder.clipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
flutter::DlCanvas::ClipOp::kIntersect, true);
}
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
flutter::DlImageSampling::kNearestNeighbor, true);
builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
flutter::DlImageSampling::kNearestNeighbor, nullptr);
builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
&filter);
@ -571,12 +586,13 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) {
auto circle_center =
IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());
builder.setStyle(flutter::DlDrawStyle::kStroke);
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
builder.setStrokeWidth(10);
builder.setColor(flutter::DlColor::kRed().withAlpha(100));
builder.drawCircle({circle_center.x, circle_center.y}, 100);
flutter::DlPaint paint;
paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
paint.setStrokeCap(flutter::DlStrokeCap::kButt);
paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
paint.setStrokeWidth(10);
paint.setColor(flutter::DlColor::kRed().withAlpha(100));
builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
}
return builder.Build();
@ -590,12 +606,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImage) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
auto size = texture->GetSize();
builder.drawImageNine(
builder.DrawImageNine(
DlImageImpeller::Make(texture),
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
size.height * 3 / 4),
SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
flutter::DlFilterMode::kNearest, true);
flutter::DlFilterMode::kNearest, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -606,12 +622,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
auto size = texture->GetSize();
builder.drawImageNine(
builder.DrawImageNine(
DlImageImpeller::Make(texture),
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
size.height * 3 / 4),
SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
flutter::DlFilterMode::kNearest, true);
flutter::DlFilterMode::kNearest, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -622,12 +638,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
auto size = texture->GetSize();
builder.drawImageNine(
builder.DrawImageNine(
DlImageImpeller::Make(texture),
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
size.height * 3 / 4),
SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
flutter::DlFilterMode::kNearest, true);
flutter::DlFilterMode::kNearest, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -637,12 +653,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
auto size = texture->GetSize();
builder.drawImageNine(
builder.DrawImageNine(
DlImageImpeller::Make(texture),
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
size.height * 3 / 4),
SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
flutter::DlFilterMode::kNearest, true);
flutter::DlFilterMode::kNearest, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -652,12 +668,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCornersScaledDown) {
auto texture = CreateTextureForFixture("embarcadero.jpg");
flutter::DisplayListBuilder builder;
auto size = texture->GetSize();
builder.drawImageNine(
builder.DrawImageNine(
DlImageImpeller::Make(texture),
SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
size.height * 3 / 4),
SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
flutter::DlFilterMode::kNearest, true);
flutter::DlFilterMode::kNearest, nullptr);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
@ -722,9 +738,10 @@ TEST_P(DisplayListTest, CanDrawZeroLengthLine) {
TEST_P(DisplayListTest, CanDrawShadow) {
flutter::DisplayListBuilder builder;
flutter::DlPaint paint;
auto content_scale = GetContentScale() * 0.8;
builder.scale(content_scale.x, content_scale.y);
builder.Scale(content_scale.x, content_scale.y);
constexpr size_t star_spikes = 5;
constexpr SkScalar half_spike_rotation = kPi / star_spikes;
@ -749,20 +766,20 @@ TEST_P(DisplayListTest, CanDrawShadow) {
SkPath{}.addCircle(100, 50, 50),
SkPath{}.addPoly(star.data(), star.size(), true),
};
builder.setColor(flutter::DlColor::kWhite());
builder.drawPaint();
builder.setColor(flutter::DlColor::kCyan());
builder.translate(100, 50);
paint.setColor(flutter::DlColor::kWhite());
builder.DrawPaint(paint);
paint.setColor(flutter::DlColor::kCyan());
builder.Translate(100, 50);
for (size_t x = 0; x < paths.size(); x++) {
builder.save();
builder.Save();
for (size_t y = 0; y < 6; y++) {
builder.drawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
1);
builder.drawPath(paths[x]);
builder.translate(0, 150);
builder.DrawPath(paths[x], paint);
builder.Translate(0, 150);
}
builder.restore();
builder.translate(250, 0);
builder.Restore();
builder.Translate(250, 0);
}
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
@ -878,20 +895,21 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
ImGui::End();
flutter::DisplayListBuilder builder;
SkPaint paint;
flutter::DlPaint paint;
if (enable_savelayer) {
builder.SaveLayer(nullptr, nullptr);
}
{
auto content_scale = GetContentScale();
builder.scale(content_scale.x, content_scale.y);
builder.Scale(content_scale.x, content_scale.y);
// Set the current transform
auto ctm_matrix =
SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
ctm_skew[1], ctm_scale[1], ctm_translation[1], //
0, 0, 1);
builder.transform(ctm_matrix);
builder.Transform(ctm_matrix);
// Set the matrix filter
auto filter_matrix =
@ -904,7 +922,7 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
case 0: {
auto filter = flutter::DlMatrixImageFilter(
filter_matrix, flutter::DlImageSampling::kLinear);
builder.setImageFilter(&filter);
paint.setImageFilter(&filter);
break;
}
case 1: {
@ -913,17 +931,17 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
.shared();
auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
internal_filter);
builder.setImageFilter(&filter);
paint.setImageFilter(&filter);
break;
}
}
}
builder.drawImage(DlImageImpeller::Make(boston), {},
flutter::DlImageSampling::kLinear, true);
builder.DrawImage(DlImageImpeller::Make(boston), {},
flutter::DlImageSampling::kLinear, &paint);
}
if (enable_savelayer) {
builder.restore();
builder.Restore();
}
return builder.Build();

View File

@ -47,7 +47,7 @@ Canvas::~Canvas() {}
void Canvas::save() {
if (display_list_builder_) {
builder()->save();
builder()->Save();
}
}
@ -57,11 +57,11 @@ void Canvas::saveLayerWithoutBounds(Dart_Handle paint_objects,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
bool restore_with_paint =
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
FML_DCHECK(restore_with_paint);
DlPaint dl_paint;
const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags);
FML_DCHECK(save_paint);
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
builder()->saveLayer(nullptr, restore_with_paint);
builder()->SaveLayer(nullptr, save_paint);
}
}
@ -76,17 +76,17 @@ void Canvas::saveLayer(double left,
FML_DCHECK(paint.isNotNull());
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
if (display_list_builder_) {
bool restore_with_paint =
paint.sync_to(builder(), kSaveLayerWithPaintFlags);
FML_DCHECK(restore_with_paint);
DlPaint dl_paint;
const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags);
FML_DCHECK(save_paint);
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
builder()->saveLayer(&bounds, restore_with_paint);
builder()->SaveLayer(&bounds, save_paint);
}
}
void Canvas::restore() {
if (display_list_builder_) {
builder()->restore();
builder()->Restore();
}
}
@ -100,31 +100,31 @@ int Canvas::getSaveCount() {
void Canvas::restoreToCount(int count) {
if (display_list_builder_ && count < getSaveCount()) {
builder()->restoreToCount(count);
builder()->RestoreToCount(count);
}
}
void Canvas::translate(double dx, double dy) {
if (display_list_builder_) {
builder()->translate(dx, dy);
builder()->Translate(dx, dy);
}
}
void Canvas::scale(double sx, double sy) {
if (display_list_builder_) {
builder()->scale(sx, sy);
builder()->Scale(sx, sy);
}
}
void Canvas::rotate(double radians) {
if (display_list_builder_) {
builder()->rotate(radians * 180.0 / M_PI);
builder()->Rotate(radians * 180.0 / M_PI);
}
}
void Canvas::skew(double sx, double sy) {
if (display_list_builder_) {
builder()->skew(sx, sy);
builder()->Skew(sx, sy);
}
}
@ -133,7 +133,7 @@ void Canvas::transform(const tonic::Float64List& matrix4) {
// Both DisplayList and SkM44 constructor take row-major matrix order
if (display_list_builder_) {
// clang-format off
builder()->transformFullPerspective(
builder()->TransformFullPerspective(
matrix4[ 0], matrix4[ 4], matrix4[ 8], matrix4[12],
matrix4[ 1], matrix4[ 5], matrix4[ 9], matrix4[13],
matrix4[ 2], matrix4[ 6], matrix4[10], matrix4[14],
@ -162,14 +162,14 @@ void Canvas::clipRect(double left,
DlCanvas::ClipOp clipOp,
bool doAntiAlias) {
if (display_list_builder_) {
builder()->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
builder()->ClipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp,
doAntiAlias);
}
}
void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) {
if (display_list_builder_) {
builder()->clipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect,
builder()->ClipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect,
doAntiAlias);
}
}
@ -181,7 +181,7 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) {
return;
}
if (display_list_builder_) {
builder()->clipPath(path->path(), DlCanvas::ClipOp::kIntersect,
builder()->ClipPath(path->path(), DlCanvas::ClipOp::kIntersect,
doAntiAlias);
}
}
@ -210,7 +210,7 @@ void Canvas::getLocalClipBounds(Dart_Handle rect_handle) {
void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) {
if (display_list_builder_) {
builder()->drawColor(color, blend_mode);
builder()->DrawColor(color, blend_mode);
}
}
@ -224,8 +224,9 @@ void Canvas::drawLine(double x1,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawLineFlags);
builder()->drawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
DlPaint dl_paint;
paint.paint(dl_paint, kDrawLineFlags);
builder()->DrawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), dl_paint);
}
}
@ -234,14 +235,15 @@ void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) {
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawPaintFlags);
std::shared_ptr<const DlImageFilter> filter = builder()->getImageFilter();
DlPaint dl_paint;
paint.paint(dl_paint, kDrawPaintFlags);
std::shared_ptr<const DlImageFilter> filter = dl_paint.getImageFilter();
if (filter && !filter->asColorFilter()) {
// drawPaint does an implicit saveLayer if an SkImageFilter is
// present that cannot be replaced by an SkColorFilter.
TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)");
}
builder()->drawPaint();
builder()->DrawPaint(dl_paint);
}
}
@ -255,8 +257,9 @@ void Canvas::drawRect(double left,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawRectFlags);
builder()->drawRect(SkRect::MakeLTRB(left, top, right, bottom));
DlPaint dl_paint;
paint.paint(dl_paint, kDrawRectFlags);
builder()->DrawRect(SkRect::MakeLTRB(left, top, right, bottom), dl_paint);
}
}
@ -267,8 +270,9 @@ void Canvas::drawRRect(const RRect& rrect,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawRRectFlags);
builder()->drawRRect(rrect.sk_rrect);
DlPaint dl_paint;
paint.paint(dl_paint, kDrawRRectFlags);
builder()->DrawRRect(rrect.sk_rrect, dl_paint);
}
}
@ -280,8 +284,9 @@ void Canvas::drawDRRect(const RRect& outer,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawDRRectFlags);
builder()->drawDRRect(outer.sk_rrect, inner.sk_rrect);
DlPaint dl_paint;
paint.paint(dl_paint, kDrawDRRectFlags);
builder()->DrawDRRect(outer.sk_rrect, inner.sk_rrect, dl_paint);
}
}
@ -295,8 +300,9 @@ void Canvas::drawOval(double left,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawOvalFlags);
builder()->drawOval(SkRect::MakeLTRB(left, top, right, bottom));
DlPaint dl_paint;
paint.paint(dl_paint, kDrawOvalFlags);
builder()->DrawOval(SkRect::MakeLTRB(left, top, right, bottom), dl_paint);
}
}
@ -309,8 +315,9 @@ void Canvas::drawCircle(double x,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawCircleFlags);
builder()->drawCircle(SkPoint::Make(x, y), radius);
DlPaint dl_paint;
paint.paint(dl_paint, kDrawCircleFlags);
builder()->DrawCircle(SkPoint::Make(x, y), radius, dl_paint);
}
}
@ -327,13 +334,13 @@ void Canvas::drawArc(double left,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(),
useCenter //
? kDrawArcWithCenterFlags
: kDrawArcNoCenterFlags);
builder()->drawArc(SkRect::MakeLTRB(left, top, right, bottom),
DlPaint dl_paint;
paint.paint(dl_paint, useCenter //
? kDrawArcWithCenterFlags
: kDrawArcNoCenterFlags);
builder()->DrawArc(SkRect::MakeLTRB(left, top, right, bottom),
startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
useCenter);
useCenter, dl_paint);
}
}
@ -349,8 +356,9 @@ void Canvas::drawPath(const CanvasPath* path,
return;
}
if (display_list_builder_) {
paint.sync_to(builder(), kDrawPathFlags);
builder()->drawPath(path->path());
DlPaint dl_paint;
paint.paint(dl_paint, kDrawPathFlags);
builder()->DrawPath(path->path(), dl_paint);
}
}
@ -378,9 +386,9 @@ Dart_Handle Canvas::drawImage(const CanvasImage* image,
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
if (display_list_builder_) {
bool with_attributes = paint.sync_to(builder(), kDrawImageWithPaintFlags);
builder()->drawImage(dl_image, SkPoint::Make(x, y), sampling,
with_attributes);
DlPaint dl_paint;
const DlPaint* opt_paint = paint.paint(dl_paint, kDrawImageWithPaintFlags);
builder()->DrawImage(dl_image, SkPoint::Make(x, y), sampling, opt_paint);
}
return Dart_Null();
}
@ -417,10 +425,11 @@ Dart_Handle Canvas::drawImageRect(const CanvasImage* image,
SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
if (display_list_builder_) {
bool with_attributes =
paint.sync_to(builder(), kDrawImageRectWithPaintFlags);
builder()->drawImageRect(dl_image, src, dst, sampling, with_attributes,
SkCanvas::kFast_SrcRectConstraint);
DlPaint dl_paint;
const DlPaint* opt_paint =
paint.paint(dl_paint, kDrawImageRectWithPaintFlags);
builder()->DrawImageRect(dl_image, src, dst, sampling, opt_paint,
DlCanvas::SrcRectConstraint::kFast);
}
return Dart_Null();
}
@ -459,9 +468,10 @@ Dart_Handle Canvas::drawImageNine(const CanvasImage* image,
SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
auto filter = ImageFilter::FilterModeFromIndex(bitmapSamplingIndex);
if (display_list_builder_) {
bool with_attributes =
paint.sync_to(builder(), kDrawImageNineWithPaintFlags);
builder()->drawImageNine(dl_image, icenter, dst, filter, with_attributes);
DlPaint dl_paint;
const DlPaint* opt_paint =
paint.paint(dl_paint, kDrawImageNineWithPaintFlags);
builder()->DrawImageNine(dl_image, icenter, dst, filter, opt_paint);
}
return Dart_Null();
}
@ -474,7 +484,7 @@ void Canvas::drawPicture(Picture* picture) {
}
if (picture->display_list()) {
if (display_list_builder_) {
builder()->drawDisplayList(picture->display_list());
builder()->DrawDisplayList(picture->display_list());
}
} else {
FML_DCHECK(false);
@ -492,20 +502,22 @@ void Canvas::drawPoints(Dart_Handle paint_objects,
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
DlPaint dl_paint;
switch (point_mode) {
case DlCanvas::PointMode::kPoints:
paint.sync_to(builder(), kDrawPointsAsPointsFlags);
paint.paint(dl_paint, kDrawPointsAsPointsFlags);
break;
case DlCanvas::PointMode::kLines:
paint.sync_to(builder(), kDrawPointsAsLinesFlags);
paint.paint(dl_paint, kDrawPointsAsLinesFlags);
break;
case DlCanvas::PointMode::kPolygon:
paint.sync_to(builder(), kDrawPointsAsPolygonFlags);
paint.paint(dl_paint, kDrawPointsAsPolygonFlags);
break;
}
builder()->drawPoints(point_mode,
builder()->DrawPoints(point_mode,
points.num_elements() / 2, // SkPoints have 2 floats
reinterpret_cast<const SkPoint*>(points.data()));
reinterpret_cast<const SkPoint*>(points.data()),
dl_paint);
}
}
@ -522,8 +534,9 @@ void Canvas::drawVertices(const Vertices* vertices,
}
FML_DCHECK(paint.isNotNull());
if (display_list_builder_) {
paint.sync_to(builder(), kDrawVerticesFlags);
builder()->drawVertices(vertices->vertices(), blend_mode);
DlPaint dl_paint;
paint.paint(dl_paint, kDrawVerticesFlags);
builder()->DrawVertices(vertices->vertices(), blend_mode, dl_paint);
}
}
@ -564,14 +577,15 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects,
tonic::Int32List colors(colors_handle);
tonic::Float32List cull_rect(cull_rect_handle);
bool with_attributes = paint.sync_to(builder(), kDrawAtlasWithPaintFlags);
builder()->drawAtlas(
DlPaint dl_paint;
const DlPaint* opt_paint = paint.paint(dl_paint, kDrawAtlasWithPaintFlags);
builder()->DrawAtlas(
dl_image, reinterpret_cast<const SkRSXform*>(transforms.data()),
reinterpret_cast<const SkRect*>(rects.data()),
reinterpret_cast<const DlColor*>(colors.data()),
rects.num_elements() / 4, // SkRect have four floats.
blend_mode, sampling, reinterpret_cast<const SkRect*>(cull_rect.data()),
with_attributes);
opt_paint);
}
return Dart_Null();
}
@ -598,7 +612,7 @@ void Canvas::drawShadow(const CanvasPath* path,
// that situation we bypass the canvas interface and inject the
// shadow parameters directly into the underlying DisplayList.
// See: https://bugs.chromium.org/p/skia/issues/detail?id=12125
builder()->drawShadow(path->path(), color, elevation, transparentOccluder,
builder()->DrawShadow(path->path(), color, elevation, transparentOccluder,
dpr);
}
}

View File

@ -23,8 +23,8 @@ void ColorFilter::Create(Dart_Handle wrapper) {
}
void ColorFilter::initMode(int color, int blend_mode) {
filter_ = std::make_shared<DlBlendColorFilter>(
static_cast<DlColor>(color), static_cast<DlBlendMode>(blend_mode));
filter_ = DlBlendColorFilter::Make(static_cast<DlColor>(color),
static_cast<DlBlendMode>(blend_mode));
}
void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) {
@ -39,7 +39,7 @@ void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) {
matrix[9] *= 1.0f / 255;
matrix[14] *= 1.0f / 255;
matrix[19] *= 1.0f / 255;
filter_ = std::make_shared<DlMatrixColorFilter>(matrix);
filter_ = DlMatrixColorFilter::Make(matrix);
}
void ColorFilter::initLinearToSrgbGamma() {

View File

@ -31,9 +31,6 @@ class ColorFilter : public RefCountedDartWrappable<ColorFilter> {
~ColorFilter() override;
const std::shared_ptr<const DlColorFilter> filter() const { return filter_; }
const DlColorFilter* dl_filter() const {
return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr;
}
private:
std::shared_ptr<const DlColorFilter> filter_;

View File

@ -25,7 +25,7 @@ void CanvasGradient::Create(Dart_Handle wrapper) {
void CanvasGradient::initLinear(const tonic::Float32List& end_points,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4) {
FML_DCHECK(end_points.num_elements() == 4);
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
@ -48,7 +48,7 @@ void CanvasGradient::initLinear(const tonic::Float32List& end_points,
dl_shader_ = DlColorSource::MakeLinear(
p0, p1, colors.num_elements(), colors_array, color_stops.data(),
ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
tile_mode, has_matrix ? &sk_matrix : nullptr);
}
void CanvasGradient::initRadial(double center_x,
@ -56,7 +56,7 @@ void CanvasGradient::initRadial(double center_x,
double radius,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4) {
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
color_stops.data() == nullptr);
@ -74,7 +74,7 @@ void CanvasGradient::initRadial(double center_x,
dl_shader_ = DlColorSource::MakeRadial(
SkPoint::Make(center_x, center_y), radius, colors.num_elements(),
colors_array, color_stops.data(), ToDl(tile_mode),
colors_array, color_stops.data(), tile_mode,
has_matrix ? &sk_matrix : nullptr);
}
@ -82,7 +82,7 @@ void CanvasGradient::initSweep(double center_x,
double center_y,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
double start_angle,
double end_angle,
const tonic::Float64List& matrix4) {
@ -103,7 +103,7 @@ void CanvasGradient::initSweep(double center_x,
dl_shader_ = DlColorSource::MakeSweep(
SkPoint::Make(center_x, center_y), start_angle * 180.0 / M_PI,
end_angle * 180.0 / M_PI, colors.num_elements(), colors_array,
color_stops.data(), ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
color_stops.data(), tile_mode, has_matrix ? &sk_matrix : nullptr);
}
void CanvasGradient::initTwoPointConical(double start_x,
@ -114,7 +114,7 @@ void CanvasGradient::initTwoPointConical(double start_x,
double end_radius,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4) {
FML_DCHECK(colors.num_elements() == color_stops.num_elements() ||
color_stops.data() == nullptr);
@ -134,7 +134,7 @@ void CanvasGradient::initTwoPointConical(double start_x,
SkPoint::Make(start_x, start_y), start_radius, //
SkPoint::Make(end_x, end_y), end_radius, //
colors.num_elements(), colors_array, color_stops.data(), //
ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr);
tile_mode, has_matrix ? &sk_matrix : nullptr);
}
CanvasGradient::CanvasGradient() = default;

View File

@ -12,9 +12,6 @@
namespace flutter {
// TODO: update this if/when Skia adds Decal mode skbug.com/7638
static_assert(kSkTileModeCount >= 3, "Need to update tile mode enum");
class CanvasGradient : public Shader {
DEFINE_WRAPPERTYPEINFO();
FML_FRIEND_MAKE_REF_COUNTED(CanvasGradient);
@ -26,7 +23,7 @@ class CanvasGradient : public Shader {
void initLinear(const tonic::Float32List& end_points,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4);
void initRadial(double center_x,
@ -34,14 +31,14 @@ class CanvasGradient : public Shader {
double radius,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4);
void initSweep(double center_x,
double center_y,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
double start_angle,
double end_angle,
const tonic::Float64List& matrix4);
@ -54,7 +51,7 @@ class CanvasGradient : public Shader {
double end_radius,
const tonic::Int32List& colors,
const tonic::Float32List& color_stops,
SkTileMode tile_mode,
DlTileMode tile_mode,
const tonic::Float64List& matrix4);
std::shared_ptr<DlColorSource> shader(DlImageSampling sampling) override {

View File

@ -52,45 +52,32 @@ ImageFilter::~ImageFilter() {}
void ImageFilter::initBlur(double sigma_x,
double sigma_y,
SkTileMode tile_mode) {
filter_ =
std::make_shared<DlBlurImageFilter>(sigma_x, sigma_y, ToDl(tile_mode));
DlTileMode tile_mode) {
filter_ = DlBlurImageFilter::Make(sigma_x, sigma_y, tile_mode);
}
void ImageFilter::initDilate(double radius_x, double radius_y) {
filter_ = std::make_shared<DlDilateImageFilter>(radius_x, radius_y);
filter_ = DlDilateImageFilter::Make(radius_x, radius_y);
}
void ImageFilter::initErode(double radius_x, double radius_y) {
filter_ = std::make_shared<DlErodeImageFilter>(radius_x, radius_y);
filter_ = DlErodeImageFilter::Make(radius_x, radius_y);
}
void ImageFilter::initMatrix(const tonic::Float64List& matrix4,
int filterQualityIndex) {
auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
filter_ =
std::make_shared<DlMatrixImageFilter>(ToSkMatrix(matrix4), sampling);
filter_ = DlMatrixImageFilter::Make(ToSkMatrix(matrix4), sampling);
}
void ImageFilter::initColorFilter(ColorFilter* colorFilter) {
FML_DCHECK(colorFilter);
auto dl_filter = colorFilter->dl_filter();
// Skia may return nullptr if the colorfilter is a no-op.
if (dl_filter) {
filter_ = std::make_shared<DlColorFilterImageFilter>(dl_filter);
}
filter_ = DlColorFilterImageFilter::Make(colorFilter->filter());
}
void ImageFilter::initComposeFilter(ImageFilter* outer, ImageFilter* inner) {
FML_DCHECK(outer && inner);
if (!outer->dl_filter()) {
filter_ = inner->filter();
} else if (!inner->dl_filter()) {
filter_ = outer->filter();
} else {
filter_ = std::make_shared<DlComposeImageFilter>(outer->dl_filter(),
inner->dl_filter());
}
filter_ = DlComposeImageFilter::Make(outer->filter(), inner->filter());
}
} // namespace flutter

View File

@ -30,7 +30,7 @@ class ImageFilter : public RefCountedDartWrappable<ImageFilter> {
static DlImageSampling SamplingFromIndex(int filterQualityIndex);
static DlFilterMode FilterModeFromIndex(int index);
void initBlur(double sigma_x, double sigma_y, SkTileMode tile_mode);
void initBlur(double sigma_x, double sigma_y, DlTileMode tile_mode);
void initDilate(double radius_x, double radius_y);
void initErode(double radius_x, double radius_y);
void initMatrix(const tonic::Float64List& matrix4, int filter_quality_index);
@ -38,9 +38,6 @@ class ImageFilter : public RefCountedDartWrappable<ImageFilter> {
void initComposeFilter(ImageFilter* outer, ImageFilter* inner);
const std::shared_ptr<const DlImageFilter> filter() const { return filter_; }
const DlImageFilter* dl_filter() const {
return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr;
}
static void RegisterNatives(tonic::DartLibraryNatives* natives);

View File

@ -24,8 +24,8 @@ void ImageShader::Create(Dart_Handle wrapper) {
}
Dart_Handle ImageShader::initWithImage(CanvasImage* image,
SkTileMode tmx,
SkTileMode tmy,
DlTileMode tmx,
DlTileMode tmy,
int filter_quality_index,
Dart_Handle matrix_handle) {
if (!image) {
@ -41,7 +41,7 @@ Dart_Handle ImageShader::initWithImage(CanvasImage* image,
sampling_is_locked_ ? ImageFilter::SamplingFromIndex(filter_quality_index)
: DlImageSampling::kLinear;
cached_shader_ = UIDartState::CreateGPUObject(sk_make_sp<DlImageColorSource>(
image_, ToDl(tmx), ToDl(tmy), sampling, &local_matrix));
image_, tmx, tmy, sampling, &local_matrix));
return Dart_Null();
}

View File

@ -25,8 +25,8 @@ class ImageShader : public Shader {
static void Create(Dart_Handle wrapper);
Dart_Handle initWithImage(CanvasImage* image,
SkTileMode tmx,
SkTileMode tmy,
DlTileMode tmx,
DlTileMode tmy,
int filter_quality_index,
Dart_Handle matrix_handle);

View File

@ -53,148 +53,17 @@ constexpr uint32_t kBlendModeDefault =
// default SkPaintDefaults_MiterLimit in Skia (which is not in a public header).
constexpr double kStrokeMiterLimitDefault = 4.0;
// A color matrix which inverts colors.
// clang-format off
constexpr float kInvertColors[20] = {
-1.0, 0, 0, 1.0, 0,
0, -1.0, 0, 1.0, 0,
0, 0, -1.0, 1.0, 0,
1.0, 1.0, 1.0, 1.0, 0
};
// clang-format on
// Must be kept in sync with the MaskFilter private constants in painting.dart.
enum MaskFilterType { kNull, kBlur };
Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data)
: paint_objects_(paint_objects), paint_data_(paint_data) {}
const SkPaint* Paint::paint(SkPaint& paint) const {
const DlPaint* Paint::paint(DlPaint& paint,
const DisplayListAttributeFlags& flags) const {
if (isNull()) {
return nullptr;
}
FML_DCHECK(paint == SkPaint());
tonic::DartByteData byte_data(paint_data_);
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
const uint32_t* uint_data = static_cast<const uint32_t*>(byte_data.data());
const float* float_data = static_cast<const float*>(byte_data.data());
Dart_Handle values[kObjectCount];
if (!Dart_IsNull(paint_objects_)) {
FML_DCHECK(Dart_IsList(paint_objects_));
intptr_t length = 0;
Dart_ListLength(paint_objects_, &length);
FML_CHECK(length == kObjectCount);
if (Dart_IsError(
Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) {
return nullptr;
}
Dart_Handle shader = values[kShaderIndex];
if (!Dart_IsNull(shader)) {
if (Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader)) {
auto sampling =
ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]);
auto color_source = decoded->shader(sampling);
// TODO(dnfield): Remove this restriction.
// This currently is only used by paragraph code. Once SkParagraph does
// not need to take an SkPaint, we won't be restricted in this way
// because we will not need to access the shader on the UI task runner.
if (color_source->owning_context() != DlImage::OwningContext::kRaster) {
paint.setShader(color_source->skia_object());
}
}
}
Dart_Handle color_filter = values[kColorFilterIndex];
if (!Dart_IsNull(color_filter)) {
ColorFilter* decoded =
tonic::DartConverter<ColorFilter*>::FromDart(color_filter);
paint.setColorFilter(decoded->filter()->skia_object());
}
Dart_Handle image_filter = values[kImageFilterIndex];
if (!Dart_IsNull(image_filter)) {
ImageFilter* decoded =
tonic::DartConverter<ImageFilter*>::FromDart(image_filter);
paint.setImageFilter(decoded->filter()->skia_object());
}
}
paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
uint32_t encoded_color = uint_data[kColorIndex];
if (encoded_color) {
SkColor color = encoded_color ^ kColorDefault;
paint.setColor(color);
}
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex];
if (encoded_blend_mode) {
uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault;
paint.setBlendMode(static_cast<SkBlendMode>(blend_mode));
}
uint32_t style = uint_data[kStyleIndex];
if (style) {
paint.setStyle(static_cast<SkPaint::Style>(style));
}
float stroke_width = float_data[kStrokeWidthIndex];
if (stroke_width != 0.0) {
paint.setStrokeWidth(stroke_width);
}
uint32_t stroke_cap = uint_data[kStrokeCapIndex];
if (stroke_cap) {
paint.setStrokeCap(static_cast<SkPaint::Cap>(stroke_cap));
}
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
if (stroke_join) {
paint.setStrokeJoin(static_cast<SkPaint::Join>(stroke_join));
}
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex];
if (stroke_miter_limit != 0.0) {
paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
}
if (uint_data[kInvertColorIndex]) {
sk_sp<SkColorFilter> invert_filter = SkColorFilters::Matrix(kInvertColors);
sk_sp<SkColorFilter> current_filter = paint.refColorFilter();
if (current_filter) {
invert_filter = invert_filter->makeComposed(current_filter);
}
paint.setColorFilter(invert_filter);
}
if (uint_data[kDitherIndex]) {
paint.setDither(true);
}
switch (uint_data[kMaskFilterIndex]) {
case kNull:
break;
case kBlur:
SkBlurStyle blur_style =
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
double sigma = float_data[kMaskFilterSigmaIndex];
paint.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma));
break;
}
return &paint;
}
bool Paint::sync_to(DisplayListBuilder* builder,
const DisplayListAttributeFlags& flags) const {
if (isNull()) {
return false;
}
tonic::DartByteData byte_data(paint_data_);
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
@ -204,13 +73,13 @@ bool Paint::sync_to(DisplayListBuilder* builder,
Dart_Handle values[kObjectCount];
if (Dart_IsNull(paint_objects_)) {
if (flags.applies_shader()) {
builder->setColorSource(nullptr);
paint.setColorSource(nullptr);
}
if (flags.applies_color_filter()) {
builder->setColorFilter(nullptr);
paint.setColorFilter(nullptr);
}
if (flags.applies_image_filter()) {
builder->setImageFilter(nullptr);
paint.setImageFilter(nullptr);
}
} else {
FML_DCHECK(Dart_IsList(paint_objects_));
@ -220,20 +89,20 @@ bool Paint::sync_to(DisplayListBuilder* builder,
FML_CHECK(length == kObjectCount);
if (Dart_IsError(
Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) {
return false;
return nullptr;
}
if (flags.applies_shader()) {
Dart_Handle shader = values[kShaderIndex];
if (Dart_IsNull(shader)) {
builder->setColorSource(nullptr);
paint.setColorSource(nullptr);
} else {
if (Shader* decoded = tonic::DartConverter<Shader*>::FromDart(shader)) {
auto sampling =
ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]);
builder->setColorSource(decoded->shader(sampling).get());
paint.setColorSource(decoded->shader(sampling).get());
} else {
builder->setColorSource(nullptr);
paint.setColorSource(nullptr);
}
}
}
@ -241,94 +110,89 @@ bool Paint::sync_to(DisplayListBuilder* builder,
if (flags.applies_color_filter()) {
Dart_Handle color_filter = values[kColorFilterIndex];
if (Dart_IsNull(color_filter)) {
builder->setColorFilter(nullptr);
paint.setColorFilter(nullptr);
} else {
ColorFilter* decoded =
tonic::DartConverter<ColorFilter*>::FromDart(color_filter);
builder->setColorFilter(decoded->dl_filter());
paint.setColorFilter(decoded->filter());
}
}
if (flags.applies_image_filter()) {
Dart_Handle image_filter = values[kImageFilterIndex];
if (Dart_IsNull(image_filter)) {
builder->setImageFilter(nullptr);
paint.setImageFilter(nullptr);
} else {
ImageFilter* decoded =
tonic::DartConverter<ImageFilter*>::FromDart(image_filter);
builder->setImageFilter(decoded->dl_filter());
paint.setImageFilter(decoded->filter());
}
}
}
if (flags.applies_anti_alias()) {
builder->setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0);
}
if (flags.applies_alpha_or_color()) {
uint32_t encoded_color = uint_data[kColorIndex];
builder->setColor(encoded_color ^ kColorDefault);
paint.setColor(encoded_color ^ kColorDefault);
}
if (flags.applies_blend()) {
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex];
uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault;
builder->setBlendMode(static_cast<DlBlendMode>(blend_mode));
paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
}
if (flags.applies_style()) {
uint32_t style = uint_data[kStyleIndex];
builder->setStyle(static_cast<DlDrawStyle>(style));
paint.setDrawStyle(static_cast<DlDrawStyle>(style));
}
if (flags.is_stroked(builder->getStyle())) {
if (flags.is_stroked(paint.getDrawStyle())) {
float stroke_width = float_data[kStrokeWidthIndex];
builder->setStrokeWidth(stroke_width);
paint.setStrokeWidth(stroke_width);
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex];
builder->setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault);
uint32_t stroke_cap = uint_data[kStrokeCapIndex];
builder->setStrokeCap(static_cast<DlStrokeCap>(stroke_cap));
paint.setStrokeCap(static_cast<DlStrokeCap>(stroke_cap));
uint32_t stroke_join = uint_data[kStrokeJoinIndex];
builder->setStrokeJoin(static_cast<DlStrokeJoin>(stroke_join));
paint.setStrokeJoin(static_cast<DlStrokeJoin>(stroke_join));
}
if (flags.applies_color_filter()) {
builder->setInvertColors(uint_data[kInvertColorIndex] != 0);
paint.setInvertColors(uint_data[kInvertColorIndex] != 0);
}
if (flags.applies_dither()) {
builder->setDither(uint_data[kDitherIndex] != 0);
paint.setDither(uint_data[kDitherIndex] != 0);
}
if (flags.applies_path_effect()) {
// The paint API exposed to Dart does not support path effects. But other
// operations such as text may set a path effect, which must be cleared.
builder->setPathEffect(nullptr);
paint.setPathEffect(nullptr);
}
if (flags.applies_mask_filter()) {
switch (uint_data[kMaskFilterIndex]) {
case kNull:
builder->setMaskFilter(nullptr);
paint.setMaskFilter(nullptr);
break;
case kBlur:
SkBlurStyle blur_style =
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
double sigma = float_data[kMaskFilterSigmaIndex];
DlBlurMaskFilter dl_filter(blur_style, sigma);
if (dl_filter.skia_object()) {
builder->setMaskFilter(&dl_filter);
} else {
builder->setMaskFilter(nullptr);
}
paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma));
break;
}
}
return true;
return &paint;
}
void Paint::toDlPaint(DlPaint& paint) const {
@ -414,11 +278,14 @@ void Paint::toDlPaint(DlPaint& paint) const {
SkBlurStyle blur_style =
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]);
double sigma = float_data[kMaskFilterSigmaIndex];
std::shared_ptr<DlBlurMaskFilter> dl_filter =
std::make_shared<DlBlurMaskFilter>(blur_style, sigma);
if (dl_filter->skia_object()) {
paint.setMaskFilter(dl_filter);
}
// Make could return a nullptr here if the values are NOP or
// do not make sense. We could interpret that as if there was
// no value passed from Dart at all (i.e. don't change the
// setting in the paint object as in the kNull branch right
// above here), but the maskfilter flag was actually set
// indicating that the developer "tried" to set a mask, so we
// should set the null value rather than do nothing.
paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma));
break;
}
}

View File

@ -17,19 +17,11 @@ class Paint {
Paint() = default;
Paint(Dart_Handle paint_objects, Dart_Handle paint_data);
const SkPaint* paint(SkPaint& paint) const;
const DlPaint* paint(DlPaint& paint,
const DisplayListAttributeFlags& flags) const;
void toDlPaint(DlPaint& paint) const;
/// Synchronize the Dart properties to the display list according
/// to the attribute flags that indicate which properties are needed.
/// The return value indicates if the paint was non-null and can
/// either be DCHECKed or used to indicate to the DisplayList
/// draw operation whether or not to use the synchronized attributes
/// (mainly the drawImage and saveLayer methods).
bool sync_to(DisplayListBuilder* builder,
const DisplayListAttributeFlags& flags) const;
bool isNull() const { return Dart_IsNull(paint_data_); }
bool isNotNull() const { return !Dart_IsNull(paint_data_); }

View File

@ -270,9 +270,9 @@ std::unique_ptr<SnapshotDelegate::GpuImageResult> MakeBitmapImage(
};
sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorTRANSPARENT);
display_list->RenderTo(canvas);
auto canvas = DlSkCanvasAdapter(surface->getCanvas());
canvas.Clear(DlColor::kTransparent());
canvas.DrawDisplayList(display_list);
sk_sp<SkImage> image = surface->makeImageSnapshot();
return std::make_unique<SnapshotDelegate::GpuImageResult>(
@ -335,9 +335,9 @@ std::unique_ptr<Rasterizer::GpuImageResult> Rasterizer::MakeSkiaGpuImage(
return;
}
SkCanvas* canvas = sk_surface->getCanvas();
canvas->clear(SK_ColorTRANSPARENT);
display_list->RenderTo(canvas);
auto canvas = DlSkCanvasAdapter(sk_surface->getCanvas());
canvas.Clear(DlColor::kTransparent());
canvas.DrawDisplayList(display_list);
result = std::make_unique<SnapshotDelegate::GpuImageResult>(
texture, sk_ref_sp(context), nullptr, "");

View File

@ -126,7 +126,7 @@ sk_sp<DlImage> SnapshotControllerSkia::MakeRasterSnapshot(
sk_sp<DisplayList> display_list,
SkISize size) {
return DoMakeRasterSnapshot(size, [display_list](SkCanvas* canvas) {
display_list->RenderTo(canvas);
DlSkCanvasAdapter(canvas).DrawDisplayList(display_list);
});
}

View File

@ -61,12 +61,12 @@ FLUTTER_ASSERT_ARC
}
if (_externalImage) {
context.canvas->DrawImageRect(_externalImage, // image
SkRect::Make(_externalImage->bounds()), // source rect
bounds, // destination rect
sampling, // sampling
context.paint, // paint
false // enforce edges
context.canvas->DrawImageRect(_externalImage, // image
SkRect::Make(_externalImage->bounds()), // source rect
bounds, // destination rect
sampling, // sampling
context.paint, // paint
flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges
);
}
}

View File

@ -197,8 +197,15 @@ std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op) {
switch (op) {
case DlCanvas::ClipOp::kDifference: return os << "ClipOp::kDifference";
case DlCanvas::ClipOp::kIntersect: return os << "ClipOp::kIntersect";
}
}
default: return os << "ClipOp::????";
std::ostream& operator<<(std::ostream& os, const DlCanvas::SrcRectConstraint& constraint) {
switch (constraint) {
case DlCanvas::SrcRectConstraint::kFast:
return os << "SrcRectConstraint::kFast";
case DlCanvas::SrcRectConstraint::kStrict:
return os << "SrcRectConstraint::kStrict";
}
}
@ -207,8 +214,6 @@ std::ostream& operator<<(std::ostream& os, const DlStrokeCap& cap) {
case DlStrokeCap::kButt: return os << "Cap::kButt";
case DlStrokeCap::kRound: return os << "Cap::kRound";
case DlStrokeCap::kSquare: return os << "Cap::kSquare";
default: return os << "Cap::????";
}
}
@ -217,8 +222,6 @@ std::ostream& operator<<(std::ostream& os, const DlStrokeJoin& join) {
case DlStrokeJoin::kMiter: return os << "Join::kMiter";
case DlStrokeJoin::kRound: return os << "Join::kRound";
case DlStrokeJoin::kBevel: return os << "Join::kBevel";
default: return os << "Join::????";
}
}
@ -227,8 +230,6 @@ std::ostream& operator<<(std::ostream& os, const DlDrawStyle& style) {
case DlDrawStyle::kFill: return os << "Style::kFill";
case DlDrawStyle::kStroke: return os << "Style::kStroke";
case DlDrawStyle::kStrokeAndFill: return os << "Style::kStrokeAnFill";
default: return os << "Style::????";
}
}
@ -238,19 +239,14 @@ std::ostream& operator<<(std::ostream& os, const SkBlurStyle& style) {
case kSolid_SkBlurStyle: return os << "BlurStyle::kSolid";
case kOuter_SkBlurStyle: return os << "BlurStyle::kOuter";
case kInner_SkBlurStyle: return os << "BlurStyle::kInner";
default: return os << "Style::????";
}
}
static std::ostream& operator<<(std::ostream& os,
const DlCanvas::PointMode& mode) {
std::ostream& operator<<(std::ostream& os, const DlCanvas::PointMode& mode) {
switch (mode) {
case DlCanvas::PointMode::kPoints: return os << "PointMode::kPoints";
case DlCanvas::PointMode::kLines: return os << "PointMode::kLines";
case DlCanvas::PointMode::kPolygon: return os << "PointMode::kPolygon";
default: return os << "PointMode::????";
}
}
@ -448,7 +444,7 @@ void DisplayListStreamDispatcher::setColorSource(const DlColorSource* source) {
break;
}
default:
os_ << "DlUnknownColorSource(" << source->skia_object().get() << ")";
os_ << "?DlUnknownColorSource?()";
break;
}
os_ << ");" << std::endl;
@ -490,7 +486,7 @@ void DisplayListStreamDispatcher::out(const DlColorFilter& filter) {
break;
}
default:
os_ << "DlUnknownColorFilter(" << filter.skia_object().get() << ")";
os_ << "?DlUnknownColorFilter?()";
break;
}
}
@ -530,7 +526,7 @@ void DisplayListStreamDispatcher::setMaskFilter(const DlMaskFilter* filter) {
break;
}
default:
os_ << "DlUnknownMaskFilter(" << filter->skia_object().get() << ")";
os_ << "?DlUnknownMaskFilter?()";
break;
}
os_ << ");" << std::endl;
@ -563,7 +559,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) {
os_ << "DlMatrixImageFilter(" << matrix->matrix() << ", " << matrix->sampling() << ")";
break;
}
case DlImageFilterType::kComposeFilter: {
case DlImageFilterType::kCompose: {
const DlComposeImageFilter* compose = filter.asCompose();
FML_DCHECK(compose);
os_ << "DlComposeImageFilter(" << std::endl;
@ -590,7 +586,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) {
os_ << ")";
break;
}
case DlImageFilterType::kLocalMatrixFilter: {
case DlImageFilterType::kLocalMatrix: {
const DlLocalMatrixImageFilter* local_matrix = filter.asLocalMatrix();
FML_DCHECK(local_matrix);
os_ << "DlLocalMatrixImageFilter(" << local_matrix->matrix();
@ -810,7 +806,7 @@ void DisplayListStreamDispatcher::drawImageRect(const sk_sp<DlImage> image,
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) {
SrcRectConstraint constraint) {
startl() << "drawImageRect(" << image.get() << "," << std::endl;
startl() << " src: " << src << "," << std::endl;
startl() << " dst: " << dst << "," << std::endl;
@ -849,8 +845,12 @@ void DisplayListStreamDispatcher::drawAtlas(const sk_sp<DlImage> atlas,
<< ");" << std::endl;
}
void DisplayListStreamDispatcher::drawDisplayList(
const sk_sp<DisplayList> display_list) {
startl() << "drawDisplayList(ID: " << display_list->unique_id() << ", bounds: " << display_list->bounds() << ");" << std::endl;
const sk_sp<DisplayList> display_list, SkScalar opacity) {
startl() << "drawDisplayList("
<< "ID: " << display_list->unique_id() << ", "
<< "bounds: " << display_list->bounds() << ", "
<< "opacity: " << opacity
<< ");" << std::endl;
}
void DisplayListStreamDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,

View File

@ -8,8 +8,8 @@
#include <ostream>
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_dispatcher.h"
#include "flutter/display_list/display_list_path_effect.h"
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
namespace testing {
@ -36,6 +36,10 @@ extern std::ostream& operator<<(std::ostream& os,
extern std::ostream& operator<<(std::ostream& os, const DlPaint& paint);
extern std::ostream& operator<<(std::ostream& os, const DlBlendMode& mode);
extern std::ostream& operator<<(std::ostream& os, const DlCanvas::ClipOp& op);
extern std::ostream& operator<<(std::ostream& os,
const DlCanvas::PointMode& op);
extern std::ostream& operator<<(std::ostream& os,
const DlCanvas::SrcRectConstraint& op);
extern std::ostream& operator<<(std::ostream& os, const DlStrokeCap& cap);
extern std::ostream& operator<<(std::ostream& os, const DlStrokeJoin& join);
extern std::ostream& operator<<(std::ostream& os, const DlDrawStyle& style);
@ -47,7 +51,7 @@ extern std::ostream& operator<<(std::ostream& os, const DlVertexMode& mode);
extern std::ostream& operator<<(std::ostream& os, const DlTileMode& mode);
extern std::ostream& operator<<(std::ostream& os, const DlImage* image);
class DisplayListStreamDispatcher final : public Dispatcher {
class DisplayListStreamDispatcher final : public DlOpReceiver {
public:
DisplayListStreamDispatcher(std::ostream& os,
int cur_indent = 2,
@ -121,7 +125,7 @@ class DisplayListStreamDispatcher final : public Dispatcher {
const SkRect& dst,
DlImageSampling sampling,
bool render_with_attributes,
SkCanvas::SrcRectConstraint constraint) override;
SrcRectConstraint constraint) override;
void drawImageNine(const sk_sp<DlImage> image,
const SkIRect& center,
const SkRect& dst,
@ -136,7 +140,8 @@ class DisplayListStreamDispatcher final : public Dispatcher {
DlImageSampling sampling,
const SkRect* cull_rect,
bool render_with_attributes) override;
void drawDisplayList(const sk_sp<DisplayList> display_list) override;
void drawDisplayList(const sk_sp<DisplayList> display_list,
SkScalar opacity) override;
void drawTextBlob(const sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y) override;

View File

@ -285,7 +285,7 @@ void MockCanvas::DrawImageRect(const sk_sp<DlImage>&,
const SkRect&,
const DlImageSampling,
const DlPaint*,
bool enforce_src_edges) {
SrcRectConstraint constraint) {
FML_DCHECK(false);
}

View File

@ -247,12 +247,13 @@ class MockCanvas final : public DlCanvas {
const SkPoint point,
DlImageSampling sampling,
const DlPaint* paint = nullptr) override;
void DrawImageRect(const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
bool enforce_src_edges = false) override;
void DrawImageRect(
const sk_sp<DlImage>& image,
const SkRect& src,
const SkRect& dst,
DlImageSampling sampling,
const DlPaint* paint = nullptr,
SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
void DrawImageNine(const sk_sp<DlImage>& image,
const SkIRect& center,
const SkRect& dst,