14 #include "flutter/fml/logging.h"
15 #include "flutter/fml/trace_event.h"
33 #if IMPELLER_ENABLE_3D
35 #endif // IMPELLER_ENABLE_3D
39 #define UNIMPLEMENTED \
40 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
44 case flutter::DlBlendMode::kClear:
46 case flutter::DlBlendMode::kSrc:
48 case flutter::DlBlendMode::kDst:
50 case flutter::DlBlendMode::kSrcOver:
52 case flutter::DlBlendMode::kDstOver:
54 case flutter::DlBlendMode::kSrcIn:
56 case flutter::DlBlendMode::kDstIn:
58 case flutter::DlBlendMode::kSrcOut:
60 case flutter::DlBlendMode::kDstOut:
62 case flutter::DlBlendMode::kSrcATop:
64 case flutter::DlBlendMode::kDstATop:
66 case flutter::DlBlendMode::kXor:
68 case flutter::DlBlendMode::kPlus:
70 case flutter::DlBlendMode::kModulate:
72 case flutter::DlBlendMode::kScreen:
74 case flutter::DlBlendMode::kOverlay:
76 case flutter::DlBlendMode::kDarken:
78 case flutter::DlBlendMode::kLighten:
80 case flutter::DlBlendMode::kColorDodge:
82 case flutter::DlBlendMode::kColorBurn:
84 case flutter::DlBlendMode::kHardLight:
86 case flutter::DlBlendMode::kSoftLight:
88 case flutter::DlBlendMode::kDifference:
90 case flutter::DlBlendMode::kExclusion:
92 case flutter::DlBlendMode::kMultiply:
94 case flutter::DlBlendMode::kHue:
96 case flutter::DlBlendMode::kSaturation:
98 case flutter::DlBlendMode::kColor:
100 case flutter::DlBlendMode::kLuminosity:
108 case flutter::DlTileMode::kClamp:
110 case flutter::DlTileMode::kRepeat:
112 case flutter::DlTileMode::kMirror:
114 case flutter::DlTileMode::kDecal:
120 const flutter::DlImageSampling options) {
123 case flutter::DlImageSampling::kNearestNeighbor:
126 desc.
label =
"Nearest Sampler";
128 case flutter::DlImageSampling::kLinear:
131 desc.
label =
"Linear Sampler";
133 case flutter::DlImageSampling::kCubic:
134 case flutter::DlImageSampling::kMipmapLinear:
137 desc.
label =
"Mipmap Linear Sampler";
144 const flutter::DlFilterMode options) {
147 case flutter::DlFilterMode::kNearest:
149 desc.
label =
"Nearest Sampler";
151 case flutter::DlFilterMode::kLinear:
153 desc.
label =
"Linear Sampler";
179 case flutter::DlDrawStyle::kFill:
181 case flutter::DlDrawStyle::kStroke:
183 case flutter::DlDrawStyle::kStrokeAndFill:
218 case flutter::DlStrokeCap::kButt:
221 case flutter::DlStrokeCap::kRound:
224 case flutter::DlStrokeCap::kSquare:
233 case flutter::DlStrokeJoin::kMiter:
236 case flutter::DlStrokeJoin::kRound:
239 case flutter::DlStrokeJoin::kBevel:
245 static std::vector<Color>
ToColors(
const flutter::DlColor colors[],
int count) {
246 auto result = std::vector<Color>();
247 if (colors ==
nullptr) {
250 for (
int i = 0; i < count; i++) {
257 flutter::DlColorSourceType
type) {
259 case flutter::DlColorSourceType::kColor:
261 case flutter::DlColorSourceType::kImage:
263 case flutter::DlColorSourceType::kLinearGradient:
265 case flutter::DlColorSourceType::kRadialGradient:
267 case flutter::DlColorSourceType::kConicalGradient:
269 case flutter::DlColorSourceType::kSweepGradient:
271 case flutter::DlColorSourceType::kRuntimeEffect:
273 #ifdef IMPELLER_ENABLE_3D
274 case flutter::DlColorSourceType::kScene:
276 #endif // IMPELLER_ENABLE_3D
289 if (!
type.has_value()) {
290 FML_LOG(ERROR) <<
"Requested ColorSourceType::kUnknown";
295 switch (
type.value()) {
297 const flutter::DlColorColorSource*
color = source->asColor();
305 const flutter::DlLinearGradientColorSource* linear =
306 source->asLinearGradient();
310 std::vector<Color> colors;
311 std::vector<float> stops;
314 auto tile_mode =
ToTileMode(linear->tile_mode());
315 auto matrix =
ToMatrix(linear->matrix());
318 start_point, end_point, std::move(colors), std::move(stops),
323 const flutter::DlConicalGradientColorSource* conical_gradient =
324 source->asConicalGradient();
325 FML_DCHECK(conical_gradient);
327 SkScalar radius = conical_gradient->end_radius();
330 SkScalar focus_radius = conical_gradient->start_radius();
331 std::vector<Color> colors;
332 std::vector<float> stops;
335 auto tile_mode =
ToTileMode(conical_gradient->tile_mode());
336 auto matrix =
ToMatrix(conical_gradient->matrix());
339 center, radius, std::move(colors), std::move(stops), focus_center,
340 focus_radius, tile_mode, matrix);
344 const flutter::DlRadialGradientColorSource* radialGradient =
345 source->asRadialGradient();
346 FML_DCHECK(radialGradient);
348 auto radius = radialGradient->radius();
349 std::vector<Color> colors;
350 std::vector<float> stops;
353 auto tile_mode =
ToTileMode(radialGradient->tile_mode());
354 auto matrix =
ToMatrix(radialGradient->matrix());
357 std::move(stops), tile_mode, matrix);
361 const flutter::DlSweepGradientColorSource* sweepGradient =
362 source->asSweepGradient();
363 FML_DCHECK(sweepGradient);
366 auto start_angle =
Degrees(sweepGradient->start());
367 auto end_angle =
Degrees(sweepGradient->end());
368 std::vector<Color> colors;
369 std::vector<float> stops;
372 auto tile_mode =
ToTileMode(sweepGradient->tile_mode());
373 auto matrix =
ToMatrix(sweepGradient->matrix());
375 center, start_angle, end_angle, std::move(colors), std::move(stops),
380 const flutter::DlImageColorSource* image_color_source = source->asImage();
381 FML_DCHECK(image_color_source &&
382 image_color_source->image()->impeller_texture());
383 auto texture = image_color_source->image()->impeller_texture();
384 auto x_tile_mode =
ToTileMode(image_color_source->horizontal_tile_mode());
385 auto y_tile_mode =
ToTileMode(image_color_source->vertical_tile_mode());
387 auto matrix =
ToMatrix(image_color_source->matrix());
389 y_tile_mode, desc, matrix);
393 const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
394 source->asRuntimeEffect();
396 runtime_effect_color_source->runtime_effect()->runtime_stage();
397 auto uniform_data = runtime_effect_color_source->uniform_data();
398 auto samplers = runtime_effect_color_source->samplers();
400 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
402 for (
auto& sampler : samplers) {
403 if (sampler ==
nullptr) {
406 auto* image = sampler->asImage();
407 if (!sampler->asImage()) {
411 FML_DCHECK(image->image()->impeller_texture());
412 texture_inputs.push_back({
414 .texture = image->image()->impeller_texture(),
419 runtime_stage, uniform_data, texture_inputs);
423 #ifdef IMPELLER_ENABLE_3D
424 const flutter::DlSceneColorSource* scene_color_source = source->asScene();
425 std::shared_ptr<scene::Node> scene_node =
426 scene_color_source->scene_node();
427 Matrix camera_transform = scene_color_source->camera_matrix();
430 ColorSource::MakeScene(scene_node, camera_transform);
431 #else // IMPELLER_ENABLE_3D
432 FML_LOG(ERROR) <<
"ColorSourceType::kScene can only be used if Impeller "
434 #endif // IMPELLER_ENABLE_3D
441 const flutter::DlColorFilter* filter) {
442 if (filter ==
nullptr) {
445 switch (filter->type()) {
446 case flutter::DlColorFilterType::kBlend: {
447 auto dl_blend = filter->asBlend();
452 case flutter::DlColorFilterType::kMatrix: {
453 const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
455 dl_matrix->get_matrix(color_matrix.
array);
458 case flutter::DlColorFilterType::kSrgbToLinearGamma:
460 case flutter::DlColorFilterType::kLinearToSrgbGamma:
482 switch (blur_style) {
483 case flutter::DlBlurStyle::kNormal:
485 case flutter::DlBlurStyle::kSolid:
487 case flutter::DlBlurStyle::kOuter:
489 case flutter::DlBlurStyle::kInner:
497 if (filter ==
nullptr) {
501 switch (filter->type()) {
502 case flutter::DlMaskFilterType::kBlur: {
503 auto blur = filter->asBlur();
507 .sigma =
Sigma(blur->sigma()),
508 .respect_ctm = blur->respectCTM(),
516 const flutter::DlImageFilter* filter) {
517 if (filter ==
nullptr) {
521 switch (filter->type()) {
522 case flutter::DlImageFilterType::kBlur: {
523 auto blur = filter->asBlur();
524 auto sigma_x =
Sigma(blur->sigma_x());
525 auto sigma_y =
Sigma(blur->sigma_y());
526 auto tile_mode =
ToTileMode(blur->tile_mode());
530 case flutter::DlImageFilterType::kDilate: {
531 auto dilate = filter->asDilate();
533 if (dilate->radius_x() < 0 || dilate->radius_y() < 0) {
536 auto radius_x =
Radius(dilate->radius_x());
537 auto radius_y =
Radius(dilate->radius_y());
540 case flutter::DlImageFilterType::kErode: {
541 auto erode = filter->asErode();
543 if (erode->radius_x() < 0 || erode->radius_y() < 0) {
546 auto radius_x =
Radius(erode->radius_x());
547 auto radius_y =
Radius(erode->radius_y());
550 case flutter::DlImageFilterType::kMatrix: {
551 auto matrix_filter = filter->asMatrix();
552 FML_DCHECK(matrix_filter);
553 auto matrix =
ToMatrix(matrix_filter->matrix());
557 case flutter::DlImageFilterType::kCompose: {
558 auto compose = filter->asCompose();
560 auto outer_dl_filter = compose->outer();
561 auto inner_dl_filter = compose->inner();
570 FML_DCHECK(outer_filter && inner_filter);
574 case flutter::DlImageFilterType::kColorFilter: {
575 auto color_filter_image_filter = filter->asColorFilter();
576 FML_DCHECK(color_filter_image_filter);
578 ToColorFilter(color_filter_image_filter->color_filter().get());
588 case flutter::DlImageFilterType::kLocalMatrix: {
589 auto local_matrix_filter = filter->asLocalMatrix();
590 FML_DCHECK(local_matrix_filter);
591 auto internal_filter = local_matrix_filter->image_filter();
592 FML_DCHECK(internal_filter);
599 auto matrix =
ToMatrix(local_matrix_filter->matrix());
616 SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
620 const flutter::SaveLayerOptions& options,
621 uint32_t total_content_depth,
622 flutter::DlBlendMode max_content_mode,
623 const flutter::DlImageFilter* backdrop) {
624 auto paint = options.renders_with_attributes() ? paint_ :
Paint{};
625 auto promise = options.content_is_clipped()
628 std::optional<Rect> impeller_bounds;
630 impeller_bounds = std::nullopt;
636 promise, total_content_depth,
637 options.can_distribute_opacity());
719 flutter::DlCanvas::ClipOp clip_op) {
721 case flutter::DlCanvas::ClipOp::kDifference:
723 case flutter::DlCanvas::ClipOp::kIntersect:
741 if (rrect.isRect()) {
743 }
else if (rrect.isOval()) {
745 }
else if (rrect.isSimple()) {
759 const Path& DlDispatcherBase::GetOrCachePath(
const CacheablePath& cache) {
760 if (cache.cached_impeller_path.IsEmpty() && !cache.sk_path.isEmpty()) {
763 return cache.cached_impeller_path;
773 if (cache.sk_path.isRect(&rect)) {
775 }
else if (cache.sk_path.isOval(&rect)) {
779 if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
791 flutter::DlBlendMode dl_mode) {
813 Scalar length = p0.GetDistance(p1);
819 if (length > 0.0f && on_length >= 0.0f && off_length > 0.0f) {
820 Point delta = (p1 - p0) / length;
824 while (consumed < length) {
825 builder.
MoveTo(p0 + delta * consumed);
827 Scalar dash_end = consumed + on_length;
828 if (dash_end < length) {
829 builder.
LineTo(p0 + delta * dash_end);
837 consumed = dash_end + off_length;
840 Paint stroke_paint = paint_;
844 drawLine(flutter::ToSkPoint(p0), flutter::ToSkPoint(p1));
889 SimplifyOrDrawPath(
GetCanvas(), cache, paint_);
892 void DlDispatcherBase::SimplifyOrDrawPath(
Canvas& canvas,
893 const CacheablePath& cache,
899 if (cache.sk_path.isRect(&rect, &closed) && closed) {
905 if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
912 if (cache.sk_path.isOval(&oval)) {
922 SkScalar start_degrees,
923 SkScalar sweep_degrees,
927 Degrees(sweep_degrees), use_center);
934 const SkPoint points[]) {
938 case flutter::DlCanvas::PointMode::kPoints: {
942 auto radius =
paint.stroke_width;
949 case flutter::DlCanvas::PointMode::kLines:
950 for (uint32_t i = 1; i < count; i += 2) {
956 case flutter::DlCanvas::PointMode::kPolygon:
959 for (uint32_t i = 1; i < count; i++) {
971 const std::shared_ptr<flutter::DlVertices>& vertices,
972 flutter::DlBlendMode dl_mode) {
980 flutter::DlImageSampling sampling,
981 bool render_with_attributes) {
986 auto texture = image->impeller_texture();
991 const auto size = texture->GetSize();
992 const auto src = SkRect::MakeWH(size.width, size.height);
994 SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);
1000 render_with_attributes,
1001 SrcRectConstraint::kStrict
1007 const sk_sp<flutter::DlImage> image,
1010 flutter::DlImageSampling sampling,
1011 bool render_with_attributes,
1012 SrcRectConstraint constraint = SrcRectConstraint::kFast) {
1014 std::make_shared<Image>(image->impeller_texture()),
1017 render_with_attributes ? paint_ :
Paint(),
1024 const SkIRect& center,
1026 flutter::DlFilterMode filter,
1027 bool render_with_attributes) {
1030 std::make_shared<Image>(image->impeller_texture()),
1031 Rect::MakeLTRB(center.fLeft, center.fTop, center.fRight, center.fBottom),
1038 const SkRSXform xform[],
1040 const flutter::DlColor colors[],
1042 flutter::DlBlendMode mode,
1043 flutter::DlImageSampling sampling,
1044 const SkRect* cull_rect,
1045 bool render_with_attributes) {
1056 const sk_sp<flutter::DisplayList> display_list,
1059 Paint saved_paint = paint_;
1060 Matrix saved_initial_matrix = initial_matrix_;
1075 if (opacity < SK_Scalar1) {
1081 display_list->can_apply_group_opacity());
1090 if (display_list->has_rtree() && !initial_matrix_.
HasPerspective()) {
1097 if (cull_bounds.has_value()) {
1098 Rect cull_rect = cull_bounds.value();
1099 display_list->Dispatch(
1100 *
this, SkRect::MakeLTRB(cull_rect.
GetLeft(), cull_rect.
GetTop(),
1103 display_list->Dispatch(*
this);
1106 display_list->Dispatch(*
this);
1112 initial_matrix_ = saved_initial_matrix;
1113 paint_ = saved_paint;
1126 const std::shared_ptr<TextFrame>& text_frame,
1137 const flutter::DlColor
color,
1138 const SkScalar elevation,
1139 bool transparent_occluder,
1146 const flutter::DlColor
color,
1147 const SkScalar elevation,
1148 bool transparent_occluder,
1151 spot_color.
alpha *= 0.25;
1156 std::max(std::max(spot_color.
red, spot_color.
green), spot_color.
blue);
1158 std::min(std::min(spot_color.
red, spot_color.
green), spot_color.
blue);
1159 Scalar luminance = (min + max) * 0.5;
1162 (2.6f + (-2.66667f + 1.06667f * spot_color.
alpha) * spot_color.
alpha) *
1165 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
1167 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
1170 std::clamp(spot_color.
alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
1172 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
1173 Scalar tonal_alpha = color_scale + greyscale_alpha;
1174 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
1175 spot_color =
Color(unpremul_scale * spot_color.
red,
1176 unpremul_scale * spot_color.
green,
1177 unpremul_scale * spot_color.
blue, tonal_alpha);
1180 Vector3 light_position(0, -1, 1);
1181 Scalar occluder_z = dpr * elevation;
1183 constexpr
Scalar kLightRadius = 800 / 600;
1187 paint.color = spot_color;
1190 .sigma =
Radius{kLightRadius * occluder_z /
1204 TRACE_EVENT0(
"impeller",
"DisplayListDispatcher::EndRecordingAsPicture");
1216 Canvas& DlDispatcher::GetCanvas() {
1222 flutter::DlBlendMode max_root_blend_mode) {
1230 bool has_root_backdrop_filter,
1231 flutter::DlBlendMode max_root_blend_mode,
1235 has_root_backdrop_filter ||
1239 Canvas& ExperimentalDlDispatcher::GetCanvas() {
1246 const Matrix& initial_matrix)
1247 : renderer_(renderer), matrix_(initial_matrix) {}
1250 stack_.emplace_back(matrix_);
1254 const flutter::SaveLayerOptions options,
1255 const flutter::DlImageFilter* backdrop) {
1260 matrix_ = stack_.back();
1269 matrix_ = matrix_.
Scale({sx, sy, 1.0f});
1283 SkScalar myx, SkScalar myy, SkScalar myt) {
1285 mxx, myx, 0.0f, 0.0f,
1286 mxy, myy, 0.0f, 0.0f,
1287 0.0f, 0.0f, 1.0f, 0.0f,
1288 mxt, myt, 0.0f, 1.0f
1294 SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
1295 SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
1296 SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
1297 SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
1312 const std::shared_ptr<impeller::TextFrame>& text_frame,
1317 properties.
stroke =
true;
1323 if (text_frame->HasColor()) {
1336 const sk_sp<flutter::DisplayList> display_list,
1338 [[maybe_unused]]
size_t stack_depth = stack_.size();
1340 display_list->Dispatch(*
this);
1342 FML_DCHECK(stack_depth == stack_.size());
1373 case flutter::DlStrokeCap::kButt:
1376 case flutter::DlStrokeCap::kRound:
1379 case flutter::DlStrokeCap::kSquare:
1388 case flutter::DlStrokeJoin::kMiter:
1391 case flutter::DlStrokeJoin::kRound:
1394 case flutter::DlStrokeJoin::kBevel: