11 #include <unordered_map>
15 #include "flutter/fml/logging.h"
16 #include "flutter/fml/trace_event.h"
38 #if IMPELLER_ENABLE_3D
40 #endif // IMPELLER_ENABLE_3D
44 #define UNIMPLEMENTED \
45 FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
57 case flutter::DlBlendMode::kClear:
59 case flutter::DlBlendMode::kSrc:
61 case flutter::DlBlendMode::kDst:
63 case flutter::DlBlendMode::kSrcOver:
65 case flutter::DlBlendMode::kDstOver:
67 case flutter::DlBlendMode::kSrcIn:
69 case flutter::DlBlendMode::kDstIn:
71 case flutter::DlBlendMode::kSrcOut:
73 case flutter::DlBlendMode::kDstOut:
75 case flutter::DlBlendMode::kSrcATop:
77 case flutter::DlBlendMode::kDstATop:
79 case flutter::DlBlendMode::kXor:
81 case flutter::DlBlendMode::kPlus:
83 case flutter::DlBlendMode::kModulate:
85 case flutter::DlBlendMode::kScreen:
87 case flutter::DlBlendMode::kOverlay:
89 case flutter::DlBlendMode::kDarken:
91 case flutter::DlBlendMode::kLighten:
93 case flutter::DlBlendMode::kColorDodge:
95 case flutter::DlBlendMode::kColorBurn:
97 case flutter::DlBlendMode::kHardLight:
99 case flutter::DlBlendMode::kSoftLight:
101 case flutter::DlBlendMode::kDifference:
103 case flutter::DlBlendMode::kExclusion:
105 case flutter::DlBlendMode::kMultiply:
107 case flutter::DlBlendMode::kHue:
109 case flutter::DlBlendMode::kSaturation:
113 case flutter::DlBlendMode::kLuminosity:
121 case flutter::DlTileMode::kClamp:
123 case flutter::DlTileMode::kRepeat:
125 case flutter::DlTileMode::kMirror:
127 case flutter::DlTileMode::kDecal:
133 const flutter::DlImageSampling options) {
136 case flutter::DlImageSampling::kNearestNeighbor:
138 desc.
label =
"Nearest Sampler";
140 case flutter::DlImageSampling::kLinear:
143 case flutter::DlImageSampling::kCubic:
145 desc.
label =
"Linear Sampler";
147 case flutter::DlImageSampling::kMipmapLinear:
150 desc.
label =
"Mipmap Linear Sampler";
157 const flutter::DlFilterMode options) {
160 case flutter::DlFilterMode::kNearest:
162 desc.
label =
"Nearest Sampler";
164 case flutter::DlFilterMode::kLinear:
166 desc.
label =
"Linear Sampler";
197 case flutter::DlDrawStyle::kFill:
199 case flutter::DlDrawStyle::kStroke:
201 case flutter::DlDrawStyle::kStrokeAndFill:
236 case flutter::DlStrokeCap::kButt:
239 case flutter::DlStrokeCap::kRound:
242 case flutter::DlStrokeCap::kSquare:
251 case flutter::DlStrokeJoin::kMiter:
254 case flutter::DlStrokeJoin::kRound:
257 case flutter::DlStrokeJoin::kBevel:
263 static std::vector<Color>
ToColors(
const flutter::DlColor colors[],
int count) {
264 auto result = std::vector<Color>();
265 if (colors ==
nullptr) {
268 for (
int i = 0; i < count; i++) {
275 flutter::DlColorSourceType type) {
279 case flutter::DlColorSourceType::kImage:
281 case flutter::DlColorSourceType::kLinearGradient:
283 case flutter::DlColorSourceType::kRadialGradient:
285 case flutter::DlColorSourceType::kConicalGradient:
287 case flutter::DlColorSourceType::kSweepGradient:
289 case flutter::DlColorSourceType::kRuntimeEffect:
291 #ifdef IMPELLER_ENABLE_3D
292 case flutter::DlColorSourceType::kScene:
294 #endif // IMPELLER_ENABLE_3D
307 if (!type.has_value()) {
308 FML_LOG(ERROR) <<
"Requested ColorSourceType::kUnknown";
313 switch (type.value()) {
315 const flutter::DlColorColorSource* color = source->asColor();
323 const flutter::DlLinearGradientColorSource* linear =
324 source->asLinearGradient();
328 std::vector<Color> colors;
329 std::vector<float> stops;
332 auto tile_mode =
ToTileMode(linear->tile_mode());
333 auto matrix =
ToMatrix(linear->matrix());
336 start_point, end_point, std::move(colors), std::move(stops),
341 const flutter::DlConicalGradientColorSource* conical_gradient =
342 source->asConicalGradient();
343 FML_DCHECK(conical_gradient);
345 SkScalar radius = conical_gradient->end_radius();
348 SkScalar focus_radius = conical_gradient->start_radius();
349 std::vector<Color> colors;
350 std::vector<float> stops;
353 auto tile_mode =
ToTileMode(conical_gradient->tile_mode());
354 auto matrix =
ToMatrix(conical_gradient->matrix());
357 center, radius, std::move(colors), std::move(stops), focus_center,
358 focus_radius, tile_mode, matrix);
362 const flutter::DlRadialGradientColorSource* radialGradient =
363 source->asRadialGradient();
364 FML_DCHECK(radialGradient);
366 auto radius = radialGradient->radius();
367 std::vector<Color> colors;
368 std::vector<float> stops;
371 auto tile_mode =
ToTileMode(radialGradient->tile_mode());
372 auto matrix =
ToMatrix(radialGradient->matrix());
375 std::move(stops), tile_mode, matrix);
379 const flutter::DlSweepGradientColorSource* sweepGradient =
380 source->asSweepGradient();
381 FML_DCHECK(sweepGradient);
384 auto start_angle =
Degrees(sweepGradient->start());
385 auto end_angle =
Degrees(sweepGradient->end());
386 std::vector<Color> colors;
387 std::vector<float> stops;
390 auto tile_mode =
ToTileMode(sweepGradient->tile_mode());
391 auto matrix =
ToMatrix(sweepGradient->matrix());
393 center, start_angle, end_angle, std::move(colors), std::move(stops),
398 const flutter::DlImageColorSource* image_color_source = source->asImage();
399 FML_DCHECK(image_color_source &&
400 image_color_source->image()->impeller_texture());
401 auto texture = image_color_source->image()->impeller_texture();
402 auto x_tile_mode =
ToTileMode(image_color_source->horizontal_tile_mode());
403 auto y_tile_mode =
ToTileMode(image_color_source->vertical_tile_mode());
405 auto matrix =
ToMatrix(image_color_source->matrix());
407 y_tile_mode, desc, matrix);
411 const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
412 source->asRuntimeEffect();
414 runtime_effect_color_source->runtime_effect()->runtime_stage();
415 auto uniform_data = runtime_effect_color_source->uniform_data();
416 auto samplers = runtime_effect_color_source->samplers();
418 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
420 for (
auto& sampler : samplers) {
421 if (sampler ==
nullptr) {
424 auto* image = sampler->asImage();
425 if (!sampler->asImage()) {
429 FML_DCHECK(image->image()->impeller_texture());
430 texture_inputs.push_back({
432 .texture = image->image()->impeller_texture(),
437 runtime_stage, uniform_data, texture_inputs);
441 #ifdef IMPELLER_ENABLE_3D
442 const flutter::DlSceneColorSource* scene_color_source = source->asScene();
443 std::shared_ptr<scene::Node> scene_node =
444 scene_color_source->scene_node();
445 Matrix camera_transform = scene_color_source->camera_matrix();
448 ColorSource::MakeScene(scene_node, camera_transform);
449 #else // IMPELLER_ENABLE_3D
450 FML_LOG(ERROR) <<
"ColorSourceType::kScene can only be used if Impeller "
452 #endif // IMPELLER_ENABLE_3D
459 const flutter::DlColorFilter* filter) {
460 if (filter ==
nullptr) {
463 switch (filter->type()) {
464 case flutter::DlColorFilterType::kBlend: {
465 auto dl_blend = filter->asBlend();
470 case flutter::DlColorFilterType::kMatrix: {
471 const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
473 dl_matrix->get_matrix(color_matrix.
array);
476 case flutter::DlColorFilterType::kSrgbToLinearGamma:
478 case flutter::DlColorFilterType::kLinearToSrgbGamma:
507 switch (blur_style) {
508 case flutter::DlBlurStyle::kNormal:
510 case flutter::DlBlurStyle::kSolid:
512 case flutter::DlBlurStyle::kOuter:
514 case flutter::DlBlurStyle::kInner:
522 if (filter ==
nullptr) {
526 switch (filter->type()) {
527 case flutter::DlMaskFilterType::kBlur: {
528 auto blur = filter->asBlur();
532 .sigma =
Sigma(blur->sigma()),
540 const flutter::DlImageFilter* filter) {
541 if (filter ==
nullptr) {
545 switch (filter->type()) {
546 case flutter::DlImageFilterType::kBlur: {
547 auto blur = filter->asBlur();
548 auto sigma_x =
Sigma(blur->sigma_x());
549 auto sigma_y =
Sigma(blur->sigma_y());
550 auto tile_mode =
ToTileMode(blur->tile_mode());
554 case flutter::DlImageFilterType::kDilate: {
555 auto dilate = filter->asDilate();
557 if (dilate->radius_x() < 0 || dilate->radius_y() < 0) {
560 auto radius_x =
Radius(dilate->radius_x());
561 auto radius_y =
Radius(dilate->radius_y());
564 case flutter::DlImageFilterType::kErode: {
565 auto erode = filter->asErode();
567 if (erode->radius_x() < 0 || erode->radius_y() < 0) {
570 auto radius_x =
Radius(erode->radius_x());
571 auto radius_y =
Radius(erode->radius_y());
574 case flutter::DlImageFilterType::kMatrix: {
575 auto matrix_filter = filter->asMatrix();
576 FML_DCHECK(matrix_filter);
577 auto matrix =
ToMatrix(matrix_filter->matrix());
581 case flutter::DlImageFilterType::kCompose: {
582 auto compose = filter->asCompose();
584 auto outer_dl_filter = compose->outer();
585 auto inner_dl_filter = compose->inner();
594 FML_DCHECK(outer_filter && inner_filter);
598 case flutter::DlImageFilterType::kColorFilter: {
599 auto color_filter_image_filter = filter->asColorFilter();
600 FML_DCHECK(color_filter_image_filter);
602 ToColorFilter(color_filter_image_filter->color_filter().get());
612 case flutter::DlImageFilterType::kLocalMatrix: {
613 auto local_matrix_filter = filter->asLocalMatrix();
614 FML_DCHECK(local_matrix_filter);
615 auto internal_filter = local_matrix_filter->image_filter();
616 FML_DCHECK(internal_filter);
623 auto matrix =
ToMatrix(local_matrix_filter->matrix());
641 const flutter::SaveLayerOptions options,
642 const flutter::DlImageFilter* backdrop) {
643 auto paint = options.renders_with_attributes() ? paint_ :
Paint{};
660 canvas_.
Scale({sx, sy, 1.0});
670 canvas_.
Skew(sx, sy);
727 flutter::DlCanvas::ClipOp clip_op) {
729 case flutter::DlCanvas::ClipOp::kDifference:
731 case flutter::DlCanvas::ClipOp::kIntersect:
743 if (rrect.isSimple()) {
758 flutter::DlBlendMode dl_mode) {
777 Paint paint = paint_;
789 if (bounds.width() == bounds.height()) {
791 bounds.width() * 0.5, paint_);
808 if (rrect.isSimple()) {
810 rrect.getSimpleRadii().fX, paint_);
830 if (path.isRect(&rect, &closed) && closed) {
836 if (path.isRRect(&rrect) && rrect.isSimple()) {
838 rrect.getSimpleRadii().fX, paint_);
843 if (path.isOval(&oval) && oval.width() == oval.height()) {
845 oval.width() * 0.5, paint_);
854 SkScalar start_degrees,
855 SkScalar sweep_degrees,
859 Degrees(sweep_degrees), use_center);
866 const SkPoint points[]) {
867 Paint paint = paint_;
870 case flutter::DlCanvas::PointMode::kPoints: {
881 case flutter::DlCanvas::PointMode::kLines:
882 for (uint32_t i = 1; i < count; i += 2) {
889 case flutter::DlCanvas::PointMode::kPolygon:
892 for (uint32_t i = 1; i < count; i++) {
905 flutter::DlBlendMode dl_mode) {
912 flutter::DlImageSampling sampling,
913 bool render_with_attributes) {
918 auto texture = image->impeller_texture();
923 const auto size = texture->GetSize();
924 const auto src = SkRect::MakeWH(size.width, size.height);
926 SkRect::MakeXYWH(point.fX, point.fY, size.width, size.height);
932 render_with_attributes,
933 SrcRectConstraint::kStrict
939 const sk_sp<flutter::DlImage> image,
942 flutter::DlImageSampling sampling,
943 bool render_with_attributes,
944 SrcRectConstraint constraint = SrcRectConstraint::kFast) {
946 std::make_shared<Image>(image->impeller_texture()),
949 render_with_attributes ? paint_ :
Paint(),
956 const SkIRect& center,
958 flutter::DlFilterMode filter,
959 bool render_with_attributes) {
962 std::make_shared<Image>(image->impeller_texture()),
963 Rect::MakeLTRB(center.fLeft, center.fTop, center.fRight, center.fBottom),
970 const SkRSXform xform[],
972 const flutter::DlColor colors[],
974 flutter::DlBlendMode mode,
975 flutter::DlImageSampling sampling,
976 const SkRect* cull_rect,
977 bool render_with_attributes) {
978 canvas_.
DrawAtlas(std::make_shared<Image>(atlas->impeller_texture()),
988 const sk_sp<flutter::DisplayList> display_list,
991 Paint saved_paint = paint_;
992 Matrix saved_initial_matrix = initial_matrix_;
1011 if (opacity < SK_Scalar1) {
1019 if (display_list->has_rtree() && !initial_matrix_.
HasPerspective()) {
1026 if (cull_bounds.has_value()) {
1027 Rect cull_rect = cull_bounds.value();
1028 display_list->Dispatch(
1029 *
this, SkRect::MakeLTRB(cull_rect.
GetLeft(), cull_rect.
GetTop(),
1032 display_list->Dispatch(*
this);
1035 display_list->Dispatch(*
this);
1041 initial_matrix_ = saved_initial_matrix;
1042 paint_ = saved_paint;
1065 const flutter::DlColor color,
1066 const SkScalar elevation,
1067 bool transparent_occluder,
1070 spot_color.
alpha *= 0.25;
1075 std::max(std::max(spot_color.
red, spot_color.
green), spot_color.
blue);
1077 std::min(std::min(spot_color.
red, spot_color.
green), spot_color.
blue);
1078 Scalar luminance = (min + max) * 0.5;
1081 (2.6f + (-2.66667f + 1.06667f * spot_color.
alpha) * spot_color.
alpha) *
1084 (3.544762f + (-4.891428f + 2.3466f * luminance) * luminance) *
1086 color_alpha = std::clamp(alpha_adjust * color_alpha, 0.0f, 1.0f);
1089 std::clamp(spot_color.
alpha * (1 - 0.4f * luminance), 0.0f, 1.0f);
1091 Scalar color_scale = color_alpha * (1 - greyscale_alpha);
1092 Scalar tonal_alpha = color_scale + greyscale_alpha;
1093 Scalar unpremul_scale = tonal_alpha != 0 ? color_scale / tonal_alpha : 0;
1094 spot_color =
Color(unpremul_scale * spot_color.
red,
1095 unpremul_scale * spot_color.
green,
1096 unpremul_scale * spot_color.
blue, tonal_alpha);
1099 Vector3 light_position(0, -1, 1);
1100 Scalar occluder_z = dpr * elevation;
1102 constexpr
Scalar kLightRadius = 800 / 600;
1106 paint.
color = spot_color;
1109 .sigma =
Radius{kLightRadius * occluder_z /
1120 if (path.isRect(&rect)) {
1122 }
else if (path.isRRect(&rrect) && rrect.isSimple()) {
1124 rrect.getSimpleRadii().fX, paint);
1125 }
else if (path.isOval(&oval) && oval.width() == oval.height()) {
1127 oval.width() * 0.5, paint);
1136 TRACE_EVENT0(
"impeller",
"DisplayListDispatcher::EndRecordingAsPicture");